summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarco Peereboom <marco@cvs.openbsd.org>2005-08-15 23:22:47 +0000
committerMarco Peereboom <marco@cvs.openbsd.org>2005-08-15 23:22:47 +0000
commit08292787802a803cd3887751840486d134097773 (patch)
tree2319708b5314330e19fd17f9eae0a9851f21fc14
parent80c5f53c80014fb803e03c81f1bafed702c073e5 (diff)
Add global hot spare support.
Add flag to determine controller type. ok deraadt@
-rw-r--r--sys/dev/ic/ami.c117
-rw-r--r--sys/dev/ic/amivar.h3
-rw-r--r--sys/dev/pci/ami_pci.c7
3 files changed, 114 insertions, 13 deletions
diff --git a/sys/dev/ic/ami.c b/sys/dev/ic/ami.c
index 91775bdeb40..cbe5d0bd331 100644
--- a/sys/dev/ic/ami.c
+++ b/sys/dev/ic/ami.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ami.c,v 1.57 2005/08/09 14:29:18 marco Exp $ */
+/* $OpenBSD: ami.c,v 1.58 2005/08/15 23:22:45 marco Exp $ */
/*
* Copyright (c) 2001 Michael Shalayeff
@@ -141,6 +141,10 @@ int ami_mgmt(struct ami_softc *, u_int8_t, u_int8_t, u_int8_t,
int ami_drv_inq(struct ami_softc *, u_int8_t, u_int8_t, u_int8_t, void *);
int ami_ioctl(struct device *, u_long, caddr_t);
int ami_ioctl_inq(struct ami_softc *, struct bioc_inq *);
+int ami_global_hsvol(struct ami_softc *, struct bioc_vol *,
+ struct ami_big_diskarray *);
+int ami_global_hsdisk(struct ami_softc *, struct bioc_disk *,
+ struct ami_big_diskarray *);
int ami_ioctl_vol(struct ami_softc *, struct bioc_vol *);
int ami_ioctl_disk(struct ami_softc *, struct bioc_disk *);
int ami_ioctl_alarm(struct ami_softc *, struct bioc_alarm *);
@@ -2033,10 +2037,22 @@ ami_ioctl_inq(sc, bi)
if (!plist[off]) {
plist[off] = 1;
bi->bi_nodisk++;
-
}
}
+ /* count global hotspares as volumes */
+ for(i = 0; i < ((sc->sc_flags & AMI_QUARTZ) ?
+ AMI_BIG_MAX_PDRIVES : AMI_MAX_PDRIVES); i++)
+ if (p->apd[i].adp_ostatus == AMI_PD_HOTSPARE
+ && p->apd[i].adp_type == 0) {
+ bi->bi_novol++;
+
+ if (!plist[i]) {
+ plist[i] = 1;
+ bi->bi_nodisk++;
+ }
+ }
+
bail2:
free(plist, M_DEVBUF);
bail:
@@ -2046,6 +2062,88 @@ bail:
}
int
+ami_global_hsvol(sc, bv, p)
+ struct ami_softc *sc;
+ struct bioc_vol *bv;
+ struct ami_big_diskarray *p;
+{
+ int i;
+ int ld = p->ada_nld;
+
+ for(i = 0; i < ((sc->sc_flags & AMI_QUARTZ) ?
+ AMI_BIG_MAX_PDRIVES : AMI_MAX_PDRIVES); i++)
+ if (p->apd[i].adp_ostatus == AMI_PD_HOTSPARE
+ && p->apd[i].adp_type == 0) {
+ if (ld == bv->bv_volid) {
+ /* found hs, fake data */
+ bv->bv_status = BIOC_SVONLINE;
+ bv->bv_size = (u_quad_t)p->apd[i].adp_size *
+ (u_quad_t)512;
+ bv->bv_level = -1;
+ bv->bv_nodisk = 1;
+ strlcpy(bv->bv_dev,
+ sc->sc_hdr[bv->bv_volid].dev,
+ sizeof(bv->bv_dev));
+
+ return (0);
+ }
+ ld++;
+ }
+
+ return (EINVAL);
+}
+
+int
+ami_global_hsdisk(sc, bd, p)
+ struct ami_softc *sc;
+ struct bioc_disk *bd;
+ struct ami_big_diskarray *p;
+{
+ struct scsi_inquiry_data inqbuf;
+ struct scsi_inquiry_vpd vpdbuf;
+ int i;
+ int ld = p->ada_nld;
+ u_int8_t ch, tg;
+
+ for(i = 0; i < ((sc->sc_flags & AMI_QUARTZ) ?
+ AMI_BIG_MAX_PDRIVES : AMI_MAX_PDRIVES); i++)
+ if (p->apd[i].adp_ostatus == AMI_PD_HOTSPARE
+ && p->apd[i].adp_type == 0) {
+ if (ld == bd->bd_volid) {
+ bd->bd_status = BIOC_SDHOTSPARE;
+ bd->bd_size = (u_quad_t)p->apd[i].adp_size *
+ (u_quad_t)512;
+
+ ch = (i & 0xf0) >> 4;
+ tg = i & 0x0f;
+
+ if (!ami_drv_inq(sc, ch, tg, 0, &inqbuf))
+ strlcpy(bd->bd_vendor, inqbuf.vendor,
+ 8 + 16 + 4 + 1);
+
+ if (!ami_drv_inq(sc, ch, tg, 0x80, &vpdbuf))
+ strlcpy(bd->bd_serial, vpdbuf.serial,
+ vpdbuf.page_length <
+ sizeof(bd->bd_serial) ?
+ vpdbuf.page_length :
+ sizeof(bd->bd_serial));
+
+ bd->bd_channel = ch;
+ bd->bd_target = tg;
+
+ strlcpy(bd->bd_procdev,
+ sc->sc_rawsoftcs[ch].sc_procdev,
+ sizeof(bd->bd_procdev));
+
+ return (0);
+ }
+ ld++;
+ }
+
+ return (EINVAL);
+}
+
+int
ami_ioctl_vol(sc, bv)
struct ami_softc *sc;
struct bioc_vol *bv;
@@ -2065,8 +2163,9 @@ ami_ioctl_vol(sc, bv)
goto bail;
}
- if (bv->bv_volid > p->ada_nld) {
- error = EINVAL;
+ if (bv->bv_volid >= p->ada_nld) {
+ /* is this a global hot spare? */
+ error = ami_global_hsvol(sc, bv, p);
goto bail;
}
@@ -2114,6 +2213,8 @@ ami_ioctl_vol(sc, bv)
}
}
+ /* XXX adjust disk count to account for dedicated hot spares */
+
if (p->ald[i].adl_spandepth > 1)
bv->bv_level *= 10;
@@ -2151,15 +2252,15 @@ ami_ioctl_disk(sc, bd)
goto bail;
}
- if (bd->bd_volid > p->ada_nld) {
- error = EINVAL;
+ if (bd->bd_volid >= p->ada_nld) {
+ error = ami_global_hsdisk(sc, bd, p);
goto bail;
}
i = bd->bd_volid;
error = EINVAL;
- for (s = 0, d = 0; s < p->ald[i].adl_spandepth; s++) {
+ for (s = 0, d = 0; s < p->ald[i].adl_spandepth; s++)
for (t = 0; t < p->ald[i].adl_nstripes; t++) {
if (d != bd->bd_diskid) {
d++;
@@ -2220,8 +2321,8 @@ ami_ioctl_disk(sc, bd)
error = 0;
goto bail;
}
- }
+ /* XXX if we reach this do dedicated hotspare magic*/
bail:
free(p, M_DEVBUF);
diff --git a/sys/dev/ic/amivar.h b/sys/dev/ic/amivar.h
index 3131ccd2ec8..b5d580fd66d 100644
--- a/sys/dev/ic/amivar.h
+++ b/sys/dev/ic/amivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: amivar.h,v 1.17 2005/08/08 20:23:46 marco Exp $ */
+/* $OpenBSD: amivar.h,v 1.18 2005/08/15 23:22:46 marco Exp $ */
/*
* Copyright (c) 2001 Michael Shalayeff
@@ -72,6 +72,7 @@ struct ami_softc {
/* don't use 0x0001 */
#define AMI_BROKEN 0x0002
#define AMI_CMDWAIT 0x0004
+#define AMI_QUARTZ 0x0008
u_int sc_flags;
/* low-level interface */
diff --git a/sys/dev/pci/ami_pci.c b/sys/dev/pci/ami_pci.c
index e31515670e5..c4c2e0830be 100644
--- a/sys/dev/pci/ami_pci.c
+++ b/sys/dev/pci/ami_pci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ami_pci.c,v 1.28 2005/08/09 04:10:10 mickey Exp $ */
+/* $OpenBSD: ami_pci.c,v 1.29 2005/08/15 23:22:46 marco Exp $ */
/*
* Copyright (c) 2001 Michael Shalayeff
@@ -212,6 +212,7 @@ ami_pci_attach(parent, self, aux)
sc->sc_exec = ami_quartz_exec;
sc->sc_done = ami_quartz_done;
sc->sc_poll = ami_quartz_poll;
+ sc->sc_flags |= AMI_QUARTZ;
}
sc->dmat = pa->pa_dmat;
@@ -276,9 +277,7 @@ ami_pci_attach(parent, self, aux)
if ((i = ami_pci_find_device(aux)) != -1) {
if (ami_pci_devices[i].flags & AMI_BROKEN)
- sc->sc_flags = AMI_BROKEN;
- else
- sc->sc_flags = 0x0000;
+ sc->sc_flags |= AMI_BROKEN;
}
else {
/* this device existed at _match() should never happen */