Initial bio(4) support; only volume status is handled. The driver doesn't
yet know about physical drives. Derived from the OpenBSD ciss(4) bio(4) support.
This commit is contained in:
parent
f742db2180
commit
b6044f13b8
206
sys/dev/ic/cac.c
206
sys/dev/ic/cac.c
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: cac.c,v 1.43 2007/12/05 07:06:51 ad Exp $ */
|
||||
/* $NetBSD: cac.c,v 1.44 2008/03/14 03:30:19 mhitch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2000, 2006, 2007 The NetBSD Foundation, Inc.
|
||||
@ -41,7 +41,9 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: cac.c,v 1.43 2007/12/05 07:06:51 ad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: cac.c,v 1.44 2008/03/14 03:30:19 mhitch Exp $");
|
||||
|
||||
#include "bio.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -62,6 +64,10 @@ __KERNEL_RCSID(0, "$NetBSD: cac.c,v 1.43 2007/12/05 07:06:51 ad Exp $");
|
||||
#include <dev/ic/cacreg.h>
|
||||
#include <dev/ic/cacvar.h>
|
||||
|
||||
#if NBIO > 0
|
||||
#include <dev/biovar.h>
|
||||
#endif /* NBIO > 0 */
|
||||
|
||||
#include "locators.h"
|
||||
|
||||
static struct cac_ccb *cac_ccb_alloc(struct cac_softc *, int);
|
||||
@ -80,6 +86,13 @@ static void cac_l0_submit(struct cac_softc *, struct cac_ccb *);
|
||||
|
||||
static void *cac_sdh; /* shutdown hook */
|
||||
|
||||
#if NBIO > 0
|
||||
int cac_ioctl(struct device *, u_long, void *);
|
||||
int cac_ioctl_vol(struct cac_softc *, struct bioc_vol *);
|
||||
int cac_create_sensors(struct cac_softc *);
|
||||
void cac_sensor_refresh(struct sysmon_envsys *, envsys_data_t *);
|
||||
#endif /* NBIO > 0 */
|
||||
|
||||
const struct cac_linkage cac_l0 = {
|
||||
cac_l0_completed,
|
||||
cac_l0_fifo_full,
|
||||
@ -203,6 +216,16 @@ cac_init(struct cac_softc *sc, const char *intrstr, int startfw)
|
||||
(*sc->sc_cl.cl_intr_enable)(sc, CAC_INTR_ENABLE);
|
||||
mutex_exit(&sc->sc_mutex);
|
||||
|
||||
#if NBIO > 0
|
||||
if (bio_register(&sc->sc_dv, cac_ioctl) != 0)
|
||||
printf("%s: controller registration failed",
|
||||
sc->sc_dv.dv_xname);
|
||||
else
|
||||
sc->sc_ioctl = cac_ioctl;
|
||||
if (cac_create_sensors(sc) != 0)
|
||||
aprint_error("%s: unable to create sensors\n", sc->sc_dv.dv_xname);
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -571,3 +594,182 @@ cac_l0_intr_enable(struct cac_softc *sc, int state)
|
||||
cac_outl(sc, CAC_REG_INTR_MASK,
|
||||
state ? CAC_INTR_ENABLE : CAC_INTR_DISABLE);
|
||||
}
|
||||
|
||||
#if NBIO > 0
|
||||
const int cac_level[] = { 0, 4, 1, 5, 51, 7 };
|
||||
const int cac_stat[] = { BIOC_SVONLINE, BIOC_SVOFFLINE, BIOC_SVOFFLINE,
|
||||
BIOC_SVDEGRADED, BIOC_SVREBUILD, BIOC_SVREBUILD, BIOC_SVDEGRADED,
|
||||
BIOC_SVDEGRADED, BIOC_SVINVALID, BIOC_SVINVALID, BIOC_SVBUILDING,
|
||||
BIOC_SVOFFLINE, BIOC_SVBUILDING };
|
||||
|
||||
int
|
||||
cac_ioctl(struct device *dev, u_long cmd, void *addr)
|
||||
{
|
||||
struct cac_softc *sc = (struct cac_softc *)dev;
|
||||
struct bioc_inq *bi;
|
||||
struct bioc_disk *bd;
|
||||
cac_lock_t lock;
|
||||
int error = 0;
|
||||
|
||||
lock = CAC_LOCK(sc);
|
||||
switch (cmd) {
|
||||
case BIOCINQ:
|
||||
bi = (struct bioc_inq *)addr;
|
||||
strlcpy(bi->bi_dev, sc->sc_dv.dv_xname, sizeof(bi->bi_dev));
|
||||
bi->bi_novol = sc->sc_nunits;
|
||||
bi->bi_nodisk = 0;
|
||||
break;
|
||||
|
||||
case BIOCVOL:
|
||||
error = cac_ioctl_vol(sc, (struct bioc_vol *)addr);
|
||||
break;
|
||||
|
||||
case BIOCDISK:
|
||||
case BIOCDISK_NOVOL:
|
||||
bd = (struct bioc_disk *)addr;
|
||||
if (bd->bd_volid > sc->sc_nunits) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
/* No disk information yet */
|
||||
break;
|
||||
|
||||
case BIOCBLINK:
|
||||
case BIOCALARM:
|
||||
case BIOCSETSTATE:
|
||||
default:
|
||||
error = EINVAL;
|
||||
}
|
||||
CAC_UNLOCK(sc, lock);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
cac_ioctl_vol(struct cac_softc *sc, struct bioc_vol *bv)
|
||||
{
|
||||
struct cac_drive_info dinfo;
|
||||
struct cac_drive_status dstatus;
|
||||
u_int32_t blks;
|
||||
|
||||
if (bv->bv_volid > sc->sc_nunits) {
|
||||
return EINVAL;
|
||||
}
|
||||
if (cac_cmd(sc, CAC_CMD_GET_LOG_DRV_INFO, &dinfo, sizeof(dinfo),
|
||||
bv->bv_volid, 0, CAC_CCB_DATA_IN, NULL)) {
|
||||
return EIO;
|
||||
}
|
||||
if (cac_cmd(sc, CAC_CMD_SENSE_DRV_STATUS, &dstatus, sizeof(dstatus),
|
||||
bv->bv_volid, 0, CAC_CCB_DATA_IN, NULL)) {
|
||||
return EIO;
|
||||
}
|
||||
blks = CAC_GET2(dinfo.ncylinders) * CAC_GET1(dinfo.nheads) *
|
||||
CAC_GET1(dinfo.nsectors);
|
||||
bv->bv_size = (off_t)blks * CAC_GET2(dinfo.secsize);
|
||||
bv->bv_level = cac_level[CAC_GET1(dinfo.mirror)]; /*XXX limit check */
|
||||
bv->bv_nodisk = 0; /* XXX */
|
||||
bv->bv_status = 0; /* XXX */
|
||||
bv->bv_percent = -1;
|
||||
bv->bv_seconds = 0;
|
||||
if (dstatus.stat < sizeof(cac_stat)/sizeof(cac_stat[0]))
|
||||
bv->bv_status = cac_stat[dstatus.stat];
|
||||
if (bv->bv_status == BIOC_SVREBUILD ||
|
||||
bv->bv_status == BIOC_SVBUILDING)
|
||||
bv->bv_percent = ((blks - CAC_GET4(dstatus.prog)) * 1000ULL) /
|
||||
blks;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
cac_create_sensors(struct cac_softc *sc)
|
||||
{
|
||||
int i;
|
||||
int nsensors = sc->sc_nunits;
|
||||
|
||||
sc->sc_sme = sysmon_envsys_create();
|
||||
sc->sc_sensor = malloc(sizeof(envsys_data_t) * nsensors,
|
||||
M_DEVBUF, M_NOWAIT | M_ZERO);
|
||||
if (sc->sc_sensor == NULL) {
|
||||
aprint_error("%s: can't allocate envsys_data_t\n",
|
||||
sc->sc_dv.dv_xname);
|
||||
return(ENOMEM);
|
||||
}
|
||||
|
||||
for (i = 0; i < nsensors; i++) {
|
||||
sc->sc_sensor[i].units = ENVSYS_DRIVE;
|
||||
sc->sc_sensor[i].monitor = true;
|
||||
/* Enable monitoring for drive state changes */
|
||||
sc->sc_sensor[i].flags |= ENVSYS_FMONSTCHANGED;
|
||||
/* logical drives */
|
||||
snprintf(sc->sc_sensor[i].desc,
|
||||
sizeof(sc->sc_sensor[i].desc), "%s:%d",
|
||||
sc->sc_dv.dv_xname, i);
|
||||
if (sysmon_envsys_sensor_attach(sc->sc_sme,
|
||||
&sc->sc_sensor[i]))
|
||||
goto out;
|
||||
}
|
||||
sc->sc_sme->sme_name = sc->sc_dv.dv_xname;
|
||||
sc->sc_sme->sme_cookie = sc;
|
||||
sc->sc_sme->sme_refresh = cac_sensor_refresh;
|
||||
if (sysmon_envsys_register(sc->sc_sme)) {
|
||||
printf("%s: unable to register with sysmon\n", sc->sc_dv.dv_xname);
|
||||
return(1);
|
||||
}
|
||||
return (0);
|
||||
|
||||
out:
|
||||
free(sc->sc_sensor, M_DEVBUF);
|
||||
sysmon_envsys_destroy(sc->sc_sme);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
void
|
||||
cac_sensor_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
|
||||
{
|
||||
struct cac_softc *sc = sme->sme_cookie;
|
||||
struct bioc_vol bv;
|
||||
int s;
|
||||
|
||||
if (edata->sensor >= sc->sc_nunits)
|
||||
return;
|
||||
|
||||
bzero(&bv, sizeof(bv));
|
||||
bv.bv_volid = edata->sensor;
|
||||
s = splbio();
|
||||
if (cac_ioctl_vol(sc, &bv)) {
|
||||
splx(s);
|
||||
return;
|
||||
}
|
||||
splx(s);
|
||||
|
||||
switch(bv.bv_status) {
|
||||
case BIOC_SVOFFLINE:
|
||||
edata->value_cur = ENVSYS_DRIVE_FAIL;
|
||||
edata->state = ENVSYS_SCRITICAL;
|
||||
break;
|
||||
|
||||
case BIOC_SVDEGRADED:
|
||||
edata->value_cur = ENVSYS_DRIVE_PFAIL;
|
||||
edata->state = ENVSYS_SCRITICAL;
|
||||
break;
|
||||
|
||||
case BIOC_SVSCRUB:
|
||||
case BIOC_SVONLINE:
|
||||
edata->value_cur = ENVSYS_DRIVE_ONLINE;
|
||||
edata->state = ENVSYS_SVALID;
|
||||
break;
|
||||
|
||||
case BIOC_SVREBUILD:
|
||||
case BIOC_SVBUILDING:
|
||||
edata->value_cur = ENVSYS_DRIVE_REBUILD;
|
||||
edata->state = ENVSYS_SVALID;
|
||||
break;
|
||||
|
||||
case BIOC_SVINVALID:
|
||||
/* FALLTRHOUGH */
|
||||
default:
|
||||
edata->value_cur = 0; /* unknown */
|
||||
edata->state = ENVSYS_SINVALID;
|
||||
}
|
||||
}
|
||||
#endif /* NBIO > 0 */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: cacreg.h,v 1.9 2007/12/25 18:33:38 perry Exp $ */
|
||||
/* $NetBSD: cacreg.h,v 1.10 2008/03/14 03:30:19 mhitch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||
@ -177,6 +177,59 @@ struct cac_controller_info {
|
||||
u_int8_t reserved[403];
|
||||
} __packed;
|
||||
|
||||
struct cac_drive_status {
|
||||
u_int8_t stat;
|
||||
#define CAC_LD_OK 0
|
||||
#define CAC_LD_FAILED 1
|
||||
#define CAC_LD_UNCONF 2
|
||||
#define CAC_LD_DEGRAD 3
|
||||
#define CAC_LD_RBLDRD 4 /* ready for rebuild */
|
||||
#define CAC_LD_REBLD 5
|
||||
#define CAC_LD_PDINV 6 /* wrong phys drive replaced */
|
||||
#define CAC_LD_PDUNC 7 /* phys drive is not connected proper */
|
||||
#define CAC_LD_EXPND 10 /* expanding */
|
||||
#define CAC_LD_NORDY 11 /* volume is not ready */
|
||||
#define CAC_LD_QEXPND 12 /* queued for expansion */
|
||||
u_int8_t failed[4]; /* failed map */
|
||||
u_int8_t res0[416];
|
||||
u_int8_t prog[4]; /* blocks left to rebuild/expand */
|
||||
u_int8_t rebuild; /* drive that is rebuilding */
|
||||
u_int16_t remapcnt[32]; /* count of re3mapped blocks for pds */
|
||||
u_int8_t replaced[4]; /* replaced drives map */
|
||||
u_int8_t spare[4]; /* used spares map */
|
||||
u_int8_t sparestat; /* spare status */
|
||||
#define CAC_LD_CONF 0x01 /* spare configured */
|
||||
#define CAC_LD_RBLD 0x02 /* spare is used and rebuilding */
|
||||
#define CAC_LD_DONE 0x04 /* spare rebuild done */
|
||||
#define CAC_LD_FAIL 0x08 /* at least one spare drive has failed */
|
||||
#define CAC_LD_USED 0x10 /* at least one spare drive is used */
|
||||
#define CAC_LD_AVAIL 0x20 /* at least one spare is available */
|
||||
u_int8_t sparemap[32]; /* spare->pd replacement map */
|
||||
u_int8_t replok[4]; /* replaced failed map */
|
||||
u_int8_t readyok; /* ready to become ok */
|
||||
u_int8_t memfail; /* cache mem failure */
|
||||
u_int8_t expfail; /* expansion failure */
|
||||
u_int8_t rebldfail; /* rebuild failure */
|
||||
#define CAC_LD_RBLD_READ 0x01 /* read faild */
|
||||
#define CAC_LD_RBLD_WRITE 0x02 /* write fail */
|
||||
u_int8_t bigfailed[16]; /* bigmap vers of same of the above */
|
||||
u_int8_t bigremapcnt[256];
|
||||
u_int8_t bigreplaced[16];
|
||||
u_int8_t bigspare[16];
|
||||
u_int8_t bigsparemap[128];
|
||||
u_int8_t bigreplok[16];
|
||||
u_int8_t bigrebuild; /* big-number rebuilding driveno */
|
||||
} __packed;
|
||||
|
||||
struct cac_blink {
|
||||
u_int32_t duration; /* x100ms */
|
||||
u_int32_t elapsed; /* only for sense */
|
||||
u_int8_t pdtab[256];
|
||||
#define CAC_BLINK_ALL 1
|
||||
#define CAC_BLINK_TIMED 2
|
||||
u_int8_t res[248];
|
||||
} __packed;
|
||||
|
||||
struct cac_hdr {
|
||||
u_int8_t drive; /* logical drive */
|
||||
u_int8_t priority; /* block priority */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: cacvar.h,v 1.16 2007/06/27 17:57:55 mhitch Exp $ */
|
||||
/* $NetBSD: cacvar.h,v 1.17 2008/03/14 03:30:19 mhitch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||
@ -42,6 +42,9 @@
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/condvar.h>
|
||||
|
||||
#include <dev/sysmon/sysmonvar.h>
|
||||
#include <sys/envsys.h>
|
||||
|
||||
#define CAC_MAX_CCBS 256
|
||||
#define CAC_MAX_XFER (0xffff * 512)
|
||||
#define CAC_SG_SIZE 32
|
||||
@ -122,8 +125,19 @@ struct cac_softc {
|
||||
SIMPLEQ_HEAD(, cac_ccb) sc_ccb_queue;
|
||||
kcondvar_t sc_ccb_cv;
|
||||
struct cac_linkage sc_cl;
|
||||
|
||||
/* scsi ioctl from sd device */
|
||||
int (*sc_ioctl)(struct device *, u_long, void *);
|
||||
|
||||
struct sysmon_envsys *sc_sme;
|
||||
envsys_data_t *sc_sensor;
|
||||
};
|
||||
|
||||
/* XXX These have to become spinlocks in case of fine SMP */
|
||||
#define CAC_LOCK(sc) splbio()
|
||||
#define CAC_UNLOCK(sc, lock) splx(lock)
|
||||
typedef int cac_lock_t;
|
||||
|
||||
struct cac_attach_args {
|
||||
int caca_unit;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user