Merge ^/head r352308 through r352318.
This commit is contained in:
commit
d9ec4fa9ce
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/projects/clang900-import/; revision=352319
@ -43,6 +43,7 @@ uint32_t version = G_NOP_VERSION;
|
||||
struct g_command class_commands[] = {
|
||||
{ "create", G_FLAG_VERBOSE | G_FLAG_LOADKLD, NULL,
|
||||
{
|
||||
{ 'c', "count_until_fail", "-1", G_TYPE_NUMBER },
|
||||
{ 'd', "delaymsec", "-1", G_TYPE_NUMBER },
|
||||
{ 'e', "error", "-1", G_TYPE_NUMBER },
|
||||
{ 'o', "offset", "0", G_TYPE_NUMBER },
|
||||
@ -57,12 +58,14 @@ struct g_command class_commands[] = {
|
||||
{ 'z', "physpath", G_NOP_PHYSPATH_PASSTHROUGH, G_TYPE_STRING },
|
||||
G_OPT_SENTINEL
|
||||
},
|
||||
"[-v] [-d delaymsec] [-e error] [-o offset] [-p stripesize] "
|
||||
"[-P stripeoffset] [-q rdelayprob] [-r rfailprob] [-s size] "
|
||||
"[-S secsize] [-w wfailprob] [-x wdelayprob] [-z physpath] dev ..."
|
||||
"[-v] [-c count_until_fail] [-d delaymsec] [-e error] [-o offset] "
|
||||
"[-p stripesize] [-P stripeoffset] [-q rdelayprob] [-r rfailprob] "
|
||||
"[-s size] [-S secsize] [-w wfailprob] [-x wdelayprob] "
|
||||
"[-z physpath] dev ..."
|
||||
},
|
||||
{ "configure", G_FLAG_VERBOSE, NULL,
|
||||
{
|
||||
{ 'c', "count_until_fail", "-1", G_TYPE_NUMBER },
|
||||
{ 'd', "delaymsec", "-1", G_TYPE_NUMBER },
|
||||
{ 'e', "error", "-1", G_TYPE_NUMBER },
|
||||
{ 'q', "rdelayprob", "-1", G_TYPE_NUMBER },
|
||||
@ -71,8 +74,9 @@ struct g_command class_commands[] = {
|
||||
{ 'x', "wdelayprob", "-1", G_TYPE_NUMBER },
|
||||
G_OPT_SENTINEL
|
||||
},
|
||||
"[-v] [-d delaymsec] [-e error] [-q rdelayprob] [-r rfailprob] "
|
||||
"[-w wfailprob] [-x wdelayprob] prov ..."
|
||||
"[-v] [-c count_until_fail] [-d delaymsec] [-e error] "
|
||||
"[-q rdelayprob] [-r rfailprob] [-w wfailprob] [-x wdelayprob] "
|
||||
"prov ..."
|
||||
},
|
||||
{ "destroy", G_FLAG_VERBOSE, NULL,
|
||||
{
|
||||
|
@ -24,7 +24,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd July 31, 2019
|
||||
.Dd September 13, 2019
|
||||
.Dt GNOP 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -34,6 +34,7 @@
|
||||
.Nm
|
||||
.Cm create
|
||||
.Op Fl v
|
||||
.Op Fl c Ar count_until_fail
|
||||
.Op Fl d Ar delaymsec
|
||||
.Op Fl e Ar error
|
||||
.Op Fl o Ar offset
|
||||
@ -50,6 +51,7 @@
|
||||
.Nm
|
||||
.Cm configure
|
||||
.Op Fl v
|
||||
.Op Fl c Ar count_until_fail
|
||||
.Op Fl d Ar delaymsec
|
||||
.Op Fl e Ar error
|
||||
.Op Fl q Ar rdelayprob
|
||||
@ -118,7 +120,10 @@ See
|
||||
.El
|
||||
.Pp
|
||||
Additional options:
|
||||
.Bl -tag -width ".Fl r Ar rfailprob"
|
||||
.Bl -tag -width "-c count_until_fail"
|
||||
.It Fl c Ar count_until_fail
|
||||
Specifies the number of I/O requests to allow before setting the read and write
|
||||
failure probabilities to 100%.
|
||||
.It Fl d Ar delaymsec
|
||||
Specifies the delay of the requests in milliseconds.
|
||||
Note that requests will be delayed before they are sent to the backing device.
|
||||
|
@ -24,7 +24,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd August 7, 2003
|
||||
.Dd September 12, 2019
|
||||
.Dt BIG5 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -37,7 +37,7 @@ encoding for Traditional Chinese text
|
||||
.Qq BIG5
|
||||
.Sh DESCRIPTION
|
||||
.Dq Big Five
|
||||
is the de facto standard for encoding Traditional Chinese text.
|
||||
is a standard for encoding Traditional Chinese text.
|
||||
Each character is represented by either one or two bytes.
|
||||
Characters from the
|
||||
.Tn ASCII
|
||||
@ -49,3 +49,10 @@ the first in the range 0xA1 - 0xFE, the second in the range
|
||||
.Xr euc 5 ,
|
||||
.Xr gb18030 5 ,
|
||||
.Xr utf8 5
|
||||
.Sh BUGS
|
||||
The range of the second byte overlaps some ASCII characters, including
|
||||
0x5C (`\\') and 0x7C (`|') which may cause problems in program execution or
|
||||
display.
|
||||
Big5 is considered a legacy standard and only preserved for backward
|
||||
compatibility reason.
|
||||
New documents and systems are suggested using UTF-8 directly.
|
||||
|
@ -125,6 +125,10 @@ cli['boot-conf'] = function(...)
|
||||
core.autoboot(argstr)
|
||||
end
|
||||
|
||||
cli['reload-conf'] = function(...)
|
||||
config.reload()
|
||||
end
|
||||
|
||||
-- Used for splitting cli varargs into cmd_name and the rest of argv
|
||||
function cli.arguments(...)
|
||||
local argv = {...}
|
||||
|
@ -26,7 +26,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd October 31, 2018
|
||||
.Dd September 13, 2019
|
||||
.Dt CLI.LUA 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -82,14 +82,27 @@ As of present, the
|
||||
module by default provides commands for
|
||||
.Ic autoboot ,
|
||||
.Ic boot ,
|
||||
.Ic boot-conf ,
|
||||
and
|
||||
.Ic boot-conf.
|
||||
In all three cases, the
|
||||
.Ic reload-conf .
|
||||
.Pp
|
||||
For
|
||||
.Ic autoboot ,
|
||||
.Ic boot ,
|
||||
and
|
||||
.Ic boot-conf ,
|
||||
the
|
||||
.Xr core.lua 8
|
||||
module will load all ELF modules as-needed before executing the equivalent
|
||||
built-in loader commands.
|
||||
All non-kernel arguments to these commands are passed in the same order to the
|
||||
loader command.
|
||||
.Pp
|
||||
The
|
||||
.Ic reload-conf
|
||||
command will reload the configuration from disk.
|
||||
This is useful if you have manually changed currdev and would like to easily
|
||||
reload the configuration from the new device.
|
||||
.Ss Exported Functions
|
||||
The following functions are exported from
|
||||
.Nm :
|
||||
|
@ -192,6 +192,7 @@ powerpc/powernv/opal_flash.c optional powernv opalflash
|
||||
powerpc/powernv/opal_hmi.c optional powernv
|
||||
powerpc/powernv/opal_i2c.c optional iicbus fdt powernv
|
||||
powerpc/powernv/opal_i2cm.c optional iicbus fdt powernv
|
||||
powerpc/powernv/opal_nvram.c optional powernv nvram
|
||||
powerpc/powernv/opal_pci.c optional powernv pci
|
||||
powerpc/powernv/opal_sensor.c optional powernv
|
||||
powerpc/powernv/opalcall.S optional powernv
|
||||
|
@ -195,6 +195,10 @@ g_nop_start(struct bio *bp)
|
||||
|
||||
G_NOP_LOGREQ(bp, "Request received.");
|
||||
mtx_lock(&sc->sc_lock);
|
||||
if (sc->sc_count_until_fail != 0 && --sc->sc_count_until_fail == 0) {
|
||||
sc->sc_rfailprob = 100;
|
||||
sc->sc_wfailprob = 100;
|
||||
}
|
||||
switch (bp->bio_cmd) {
|
||||
case BIO_READ:
|
||||
sc->sc_reads++;
|
||||
@ -308,9 +312,10 @@ g_nop_access(struct g_provider *pp, int dr, int dw, int de)
|
||||
|
||||
static int
|
||||
g_nop_create(struct gctl_req *req, struct g_class *mp, struct g_provider *pp,
|
||||
int ioerror, u_int rfailprob, u_int wfailprob, u_int delaymsec, u_int rdelayprob,
|
||||
u_int wdelayprob, off_t offset, off_t size, u_int secsize, off_t stripesize,
|
||||
off_t stripeoffset, const char *physpath)
|
||||
int ioerror, u_int count_until_fail, u_int rfailprob, u_int wfailprob,
|
||||
u_int delaymsec, u_int rdelayprob, u_int wdelayprob, off_t offset,
|
||||
off_t size, u_int secsize, off_t stripesize, off_t stripeoffset,
|
||||
const char *physpath)
|
||||
{
|
||||
struct g_nop_softc *sc;
|
||||
struct g_geom *gp;
|
||||
@ -386,6 +391,7 @@ g_nop_create(struct gctl_req *req, struct g_class *mp, struct g_provider *pp,
|
||||
} else
|
||||
sc->sc_physpath = NULL;
|
||||
sc->sc_error = ioerror;
|
||||
sc->sc_count_until_fail = count_until_fail;
|
||||
sc->sc_rfailprob = rfailprob;
|
||||
sc->sc_wfailprob = wfailprob;
|
||||
sc->sc_delaymsec = delaymsec;
|
||||
@ -491,8 +497,9 @@ static void
|
||||
g_nop_ctl_create(struct gctl_req *req, struct g_class *mp)
|
||||
{
|
||||
struct g_provider *pp;
|
||||
intmax_t *error, *rfailprob, *wfailprob, *offset, *secsize, *size,
|
||||
*stripesize, *stripeoffset, *delaymsec, *rdelayprob, *wdelayprob;
|
||||
intmax_t *error, *rfailprob, *wfailprob, *count_until_fail, *offset,
|
||||
*secsize, *size, *stripesize, *stripeoffset, *delaymsec,
|
||||
*rdelayprob, *wdelayprob;
|
||||
const char *name, *physpath;
|
||||
char param[16];
|
||||
int i, *nargs;
|
||||
@ -558,6 +565,16 @@ g_nop_ctl_create(struct gctl_req *req, struct g_class *mp)
|
||||
gctl_error(req, "Invalid '%s' argument", "wdelayprob");
|
||||
return;
|
||||
}
|
||||
count_until_fail = gctl_get_paraml(req, "count_until_fail",
|
||||
sizeof(*count_until_fail));
|
||||
if (count_until_fail == NULL) {
|
||||
gctl_error(req, "No '%s' argument", "count_until_fail");
|
||||
return;
|
||||
}
|
||||
if (*count_until_fail < -1) {
|
||||
gctl_error(req, "Invalid '%s' argument", "count_until_fail");
|
||||
return;
|
||||
}
|
||||
offset = gctl_get_paraml(req, "offset", sizeof(*offset));
|
||||
if (offset == NULL) {
|
||||
gctl_error(req, "No '%s' argument", "offset");
|
||||
@ -622,6 +639,7 @@ g_nop_ctl_create(struct gctl_req *req, struct g_class *mp)
|
||||
}
|
||||
if (g_nop_create(req, mp, pp,
|
||||
*error == -1 ? EIO : (int)*error,
|
||||
*count_until_fail == -1 ? 0 : (u_int)*count_until_fail,
|
||||
*rfailprob == -1 ? 0 : (u_int)*rfailprob,
|
||||
*wfailprob == -1 ? 0 : (u_int)*wfailprob,
|
||||
*delaymsec == -1 ? 1 : (u_int)*delaymsec,
|
||||
@ -640,7 +658,8 @@ g_nop_ctl_configure(struct gctl_req *req, struct g_class *mp)
|
||||
{
|
||||
struct g_nop_softc *sc;
|
||||
struct g_provider *pp;
|
||||
intmax_t *delaymsec, *error, *rdelayprob, *rfailprob, *wdelayprob, *wfailprob;
|
||||
intmax_t *delaymsec, *error, *rdelayprob, *rfailprob, *wdelayprob,
|
||||
*wfailprob, *count_until_fail;
|
||||
const char *name;
|
||||
char param[16];
|
||||
int i, *nargs;
|
||||
@ -661,6 +680,12 @@ g_nop_ctl_configure(struct gctl_req *req, struct g_class *mp)
|
||||
gctl_error(req, "No '%s' argument", "error");
|
||||
return;
|
||||
}
|
||||
count_until_fail = gctl_get_paraml(req, "count_until_fail",
|
||||
sizeof(*count_until_fail));
|
||||
if (count_until_fail == NULL) {
|
||||
gctl_error(req, "No '%s' argument", "count_until_fail");
|
||||
return;
|
||||
}
|
||||
rfailprob = gctl_get_paraml(req, "rfailprob", sizeof(*rfailprob));
|
||||
if (rfailprob == NULL) {
|
||||
gctl_error(req, "No '%s' argument", "rfailprob");
|
||||
@ -736,6 +761,8 @@ g_nop_ctl_configure(struct gctl_req *req, struct g_class *mp)
|
||||
sc->sc_wdelayprob = (u_int)*wdelayprob;
|
||||
if (*delaymsec != -1)
|
||||
sc->sc_delaymsec = (u_int)*delaymsec;
|
||||
if (*count_until_fail != -1)
|
||||
sc->sc_count_until_fail = (u_int)*count_until_fail;
|
||||
}
|
||||
}
|
||||
|
||||
@ -904,6 +931,8 @@ g_nop_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp,
|
||||
sbuf_printf(sb, "%s<WriteDelayedProb>%u</WriteDelayedProb>\n", indent,
|
||||
sc->sc_wdelayprob);
|
||||
sbuf_printf(sb, "%s<Delay>%d</Delay>\n", indent, sc->sc_delaymsec);
|
||||
sbuf_printf(sb, "%s<CountUntilFail>%u</CountUntilFail>\n", indent,
|
||||
sc->sc_count_until_fail);
|
||||
sbuf_printf(sb, "%s<Error>%d</Error>\n", indent, sc->sc_error);
|
||||
sbuf_printf(sb, "%s<Reads>%ju</Reads>\n", indent, sc->sc_reads);
|
||||
sbuf_printf(sb, "%s<Writes>%ju</Writes>\n", indent, sc->sc_writes);
|
||||
|
@ -62,6 +62,7 @@ struct g_nop_softc {
|
||||
u_int sc_delaymsec;
|
||||
u_int sc_rdelayprob;
|
||||
u_int sc_wdelayprob;
|
||||
u_int sc_count_until_fail;
|
||||
uintmax_t sc_reads;
|
||||
uintmax_t sc_writes;
|
||||
uintmax_t sc_deletes;
|
||||
|
@ -762,10 +762,11 @@ _wi= wi
|
||||
|
||||
.if ${MACHINE_ARCH} == "powerpc64"
|
||||
_ipmi= ipmi
|
||||
_nvram= opal_nvram
|
||||
.endif
|
||||
.if ${MACHINE_ARCH} == "powerpc64" || ${MACHINE_ARCH} == "powerpc"
|
||||
# Don't build powermac_nvram for powerpcspe, it's never supported.
|
||||
_nvram= powermac_nvram
|
||||
_nvram+= powermac_nvram
|
||||
.endif
|
||||
|
||||
.if ${MACHINE_CPUARCH} == "sparc64"
|
||||
|
10
sys/modules/opal_nvram/Makefile
Normal file
10
sys/modules/opal_nvram/Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${SRCTOP}/sys/powerpc/powernv
|
||||
|
||||
KMOD= opal_nvram
|
||||
SRCS= opal_nvram.c
|
||||
SRCS+= bus_if.h device_if.h
|
||||
SRCS+= ofw_bus_if.h
|
||||
|
||||
.include <bsd.kmod.mk>
|
@ -1448,7 +1448,10 @@ ipfw_chk(struct ip_fw_args *args)
|
||||
do { \
|
||||
int x = (_len) + T + EHLEN; \
|
||||
if (mem) { \
|
||||
MPASS(pktlen >= x); \
|
||||
if (__predict_false(pktlen < x)) { \
|
||||
unlock; \
|
||||
goto pullup_failed; \
|
||||
} \
|
||||
p = (char *)args->mem + (_len) + EHLEN; \
|
||||
} else { \
|
||||
if (__predict_false((m)->m_len < x)) { \
|
||||
|
@ -45,6 +45,8 @@ int opal_call(uint64_t token, ...);
|
||||
#define OPAL_RTC_WRITE 4
|
||||
#define OPAL_CEC_POWER_DOWN 5
|
||||
#define OPAL_CEC_REBOOT 6
|
||||
#define OPAL_READ_NVRAM 7
|
||||
#define OPAL_WRITE_NVRAM 8
|
||||
#define OPAL_HANDLE_INTERRUPT 9
|
||||
#define OPAL_POLL_EVENTS 10
|
||||
#define OPAL_PCI_CONFIG_READ_BYTE 13
|
||||
|
@ -81,6 +81,26 @@ opal_hmi_event_handler(void *unused, struct opal_msg *msg)
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
opal_hmi_handler2(struct trapframe *frame)
|
||||
{
|
||||
uint64_t flags;
|
||||
int err;
|
||||
|
||||
flags = 0;
|
||||
err = opal_call(OPAL_HANDLE_HMI2, vtophys(&flags));
|
||||
|
||||
if (flags & OPAL_HMI_FLAGS_TOD_TB_FAIL)
|
||||
panic("TOD/TB recovery failure");
|
||||
|
||||
if (err == OPAL_SUCCESS)
|
||||
return (0);
|
||||
|
||||
printf("HMI handler failed! OPAL error code: %d\n", err);
|
||||
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static int
|
||||
opal_hmi_handler(struct trapframe *frame)
|
||||
{
|
||||
@ -88,10 +108,8 @@ opal_hmi_handler(struct trapframe *frame)
|
||||
|
||||
err = opal_call(OPAL_HANDLE_HMI);
|
||||
|
||||
if (err == OPAL_SUCCESS) {
|
||||
mtspr(SPR_HMER, 0);
|
||||
if (err == OPAL_SUCCESS)
|
||||
return (0);
|
||||
}
|
||||
|
||||
printf("HMI handler failed! OPAL error code: %d\n", err);
|
||||
|
||||
@ -105,7 +123,9 @@ opal_setup_hmi(void *data)
|
||||
if (opal_check() != 0)
|
||||
return;
|
||||
|
||||
if (opal_call(OPAL_CHECK_TOKEN, OPAL_HANDLE_HMI) == OPAL_TOKEN_PRESENT)
|
||||
if (opal_call(OPAL_CHECK_TOKEN, OPAL_HANDLE_HMI2) == OPAL_TOKEN_PRESENT)
|
||||
hmi_handler = opal_hmi_handler2;
|
||||
else if (opal_call(OPAL_CHECK_TOKEN, OPAL_HANDLE_HMI) == OPAL_TOKEN_PRESENT)
|
||||
hmi_handler = opal_hmi_handler;
|
||||
else {
|
||||
printf("Warning: No OPAL HMI handler found.\n");
|
||||
|
276
sys/powerpc/powernv/opal_nvram.c
Normal file
276
sys/powerpc/powernv/opal_nvram.c
Normal file
@ -0,0 +1,276 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
||||
*
|
||||
* Copyright (c) 2019 Justin Hibbits
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/disk.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <dev/ofw/openfirm.h>
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/md_var.h>
|
||||
#include <machine/pio.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include "opal.h"
|
||||
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/pmap.h>
|
||||
|
||||
#define NVRAM_BUFSIZE (65536) /* 64k blocks */
|
||||
|
||||
struct opal_nvram_softc {
|
||||
device_t sc_dev;
|
||||
uint32_t sc_size;
|
||||
uint8_t *sc_buf;
|
||||
vm_paddr_t sc_buf_phys;
|
||||
|
||||
struct cdev *sc_cdev;
|
||||
int sc_isopen;
|
||||
};
|
||||
|
||||
/*
|
||||
* Device interface.
|
||||
*/
|
||||
static int opal_nvram_probe(device_t);
|
||||
static int opal_nvram_attach(device_t);
|
||||
static int opal_nvram_detach(device_t);
|
||||
|
||||
/*
|
||||
* Driver methods.
|
||||
*/
|
||||
static device_method_t opal_nvram_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, opal_nvram_probe),
|
||||
DEVMETHOD(device_attach, opal_nvram_attach),
|
||||
DEVMETHOD(device_detach, opal_nvram_detach),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t opal_nvram_driver = {
|
||||
"opal_nvram",
|
||||
opal_nvram_methods,
|
||||
sizeof(struct opal_nvram_softc)
|
||||
};
|
||||
|
||||
static devclass_t opal_nvram_devclass;
|
||||
|
||||
DRIVER_MODULE(opal_nvram, opal, opal_nvram_driver, opal_nvram_devclass, 0, 0);
|
||||
|
||||
/*
|
||||
* Cdev methods.
|
||||
*/
|
||||
|
||||
static d_open_t opal_nvram_open;
|
||||
static d_close_t opal_nvram_close;
|
||||
static d_read_t opal_nvram_read;
|
||||
static d_write_t opal_nvram_write;
|
||||
static d_ioctl_t opal_nvram_ioctl;
|
||||
|
||||
static struct cdevsw opal_nvram_cdevsw = {
|
||||
.d_version = D_VERSION,
|
||||
.d_flags = D_NEEDGIANT,
|
||||
.d_open = opal_nvram_open,
|
||||
.d_close = opal_nvram_close,
|
||||
.d_read = opal_nvram_read,
|
||||
.d_write = opal_nvram_write,
|
||||
.d_ioctl = opal_nvram_ioctl,
|
||||
.d_name = "nvram",
|
||||
};
|
||||
|
||||
static int
|
||||
opal_nvram_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (!ofw_bus_is_compatible(dev, "ibm,opal-nvram"))
|
||||
return (ENXIO);
|
||||
|
||||
device_set_desc(dev, "OPAL NVRAM");
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
static int
|
||||
opal_nvram_attach(device_t dev)
|
||||
{
|
||||
struct opal_nvram_softc *sc;
|
||||
phandle_t node;
|
||||
int err;
|
||||
|
||||
node = ofw_bus_get_node(dev);
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
sc->sc_dev = dev;
|
||||
|
||||
err = OF_getencprop(node, "#bytes", &sc->sc_size,
|
||||
sizeof(sc->sc_size));
|
||||
|
||||
if (err < 0)
|
||||
return (ENXIO);
|
||||
|
||||
sc->sc_buf = contigmalloc(NVRAM_BUFSIZE, M_DEVBUF, M_WAITOK,
|
||||
0, BUS_SPACE_MAXADDR, PAGE_SIZE, 0);
|
||||
if (sc->sc_buf == NULL) {
|
||||
device_printf(dev, "No memory for buffer.\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
sc->sc_buf_phys = pmap_kextract((vm_offset_t)sc->sc_buf);
|
||||
sc->sc_cdev = make_dev(&opal_nvram_cdevsw, 0, 0, 0, 0600,
|
||||
"nvram");
|
||||
sc->sc_cdev->si_drv1 = sc;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
opal_nvram_detach(device_t dev)
|
||||
{
|
||||
struct opal_nvram_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
if (sc->sc_cdev != NULL)
|
||||
destroy_dev(sc->sc_cdev);
|
||||
if (sc->sc_buf != NULL)
|
||||
contigfree(sc->sc_buf, NVRAM_BUFSIZE, M_DEVBUF);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
opal_nvram_open(struct cdev *dev, int flags, int fmt, struct thread *td)
|
||||
{
|
||||
struct opal_nvram_softc *sc = dev->si_drv1;
|
||||
|
||||
if (sc->sc_isopen)
|
||||
return EBUSY;
|
||||
sc->sc_isopen = 1;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
opal_nvram_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
|
||||
{
|
||||
struct opal_nvram_softc *sc = dev->si_drv1;
|
||||
|
||||
sc->sc_isopen = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
opal_nvram_read(struct cdev *dev, struct uio *uio, int ioflag)
|
||||
{
|
||||
struct opal_nvram_softc *sc = dev->si_drv1;
|
||||
int rv, amnt;
|
||||
|
||||
rv = 0;
|
||||
while (uio->uio_resid > 0) {
|
||||
amnt = MIN(uio->uio_resid, sc->sc_size - uio->uio_offset);
|
||||
amnt = MIN(amnt, NVRAM_BUFSIZE);
|
||||
if (amnt == 0)
|
||||
break;
|
||||
|
||||
rv = opal_call(OPAL_READ_NVRAM, sc->sc_buf_phys,
|
||||
amnt, uio->uio_offset);
|
||||
if (rv != OPAL_SUCCESS) {
|
||||
switch (rv) {
|
||||
case OPAL_HARDWARE:
|
||||
rv = EIO;
|
||||
break;
|
||||
case OPAL_PARAMETER:
|
||||
rv = EINVAL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
rv = uiomove(sc->sc_buf, amnt, uio);
|
||||
if (rv != 0)
|
||||
break;
|
||||
}
|
||||
return (rv);
|
||||
}
|
||||
|
||||
static int
|
||||
opal_nvram_write(struct cdev *dev, struct uio *uio, int ioflag)
|
||||
{
|
||||
off_t offset;
|
||||
int rv, amnt;
|
||||
struct opal_nvram_softc *sc = dev->si_drv1;
|
||||
|
||||
rv = 0;
|
||||
while (uio->uio_resid > 0) {
|
||||
amnt = MIN(uio->uio_resid, sc->sc_size - uio->uio_offset);
|
||||
amnt = MIN(amnt, NVRAM_BUFSIZE);
|
||||
if (amnt == 0) {
|
||||
rv = ENOSPC;
|
||||
break;
|
||||
}
|
||||
offset = uio->uio_offset;
|
||||
rv = uiomove(sc->sc_buf, amnt, uio);
|
||||
if (rv != 0)
|
||||
break;
|
||||
rv = opal_call(OPAL_WRITE_NVRAM, sc->sc_buf_phys, amnt,
|
||||
offset);
|
||||
if (rv != OPAL_SUCCESS) {
|
||||
switch (rv) {
|
||||
case OPAL_HARDWARE:
|
||||
rv = EIO;
|
||||
break;
|
||||
case OPAL_PARAMETER:
|
||||
rv = EINVAL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (rv);
|
||||
}
|
||||
|
||||
static int
|
||||
opal_nvram_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
|
||||
struct thread *td)
|
||||
{
|
||||
struct opal_nvram_softc *sc = dev->si_drv1;
|
||||
|
||||
switch (cmd) {
|
||||
case DIOCGMEDIASIZE:
|
||||
*(off_t *)data = sc->sc_size;
|
||||
return (0);
|
||||
}
|
||||
return (EINVAL);
|
||||
}
|
Loading…
Reference in New Issue
Block a user