Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pci - Fix the mailbox protocol. Not tested with newe...
details: https://anonhg.NetBSD.org/src/rev/15c8fdfb39b5
branches: trunk
changeset: 546708:15c8fdfb39b5
user: ad <ad%NetBSD.org@localhost>
date: Sun May 04 16:15:35 2003 +0000
description:
- Fix the mailbox protocol. Not tested with newer 'Quartz' controllers.
- Handle failure during initalisation more gracefully.
- Create a watchdog thread to poke the board and check for status changes.
- Make ready for > 64kB transfers.
diffstat:
sys/dev/pci/amr.c | 513 +++++++++++++++++++++++++++++++++++++++-----------
sys/dev/pci/amrreg.h | 29 +-
sys/dev/pci/amrvar.h | 52 +++-
sys/dev/pci/ld_amr.c | 45 +--
4 files changed, 460 insertions(+), 179 deletions(-)
diffs (truncated from 1255 to 300 lines):
diff -r 82e46bd4fdcc -r 15c8fdfb39b5 sys/dev/pci/amr.c
--- a/sys/dev/pci/amr.c Sun May 04 15:09:45 2003 +0000
+++ b/sys/dev/pci/amr.c Sun May 04 16:15:35 2003 +0000
@@ -1,7 +1,7 @@
-/* $NetBSD: amr.c,v 1.8 2003/01/31 00:07:40 thorpej Exp $ */
+/* $NetBSD: amr.c,v 1.9 2003/05/04 16:15:35 ad Exp $ */
/*-
- * Copyright (c) 2002 The NetBSD Foundation, Inc.
+ * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -71,7 +71,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: amr.c,v 1.8 2003/01/31 00:07:40 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: amr.c,v 1.9 2003/05/04 16:15:35 ad Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -81,6 +81,7 @@
#include <sys/proc.h>
#include <sys/buf.h>
#include <sys/malloc.h>
+#include <sys/kthread.h>
#include <uvm/uvm_extern.h>
@@ -92,15 +93,8 @@
#include <dev/pci/amrreg.h>
#include <dev/pci/amrvar.h>
-#if AMR_MAX_SEGS > 32
-#error AMR_MAX_SEGS too high
-#endif
-
-#define AMR_ENQUIRY_BUFSIZE 2048
-#define AMR_SGL_SIZE (sizeof(struct amr_sgentry) * 32)
-
void amr_attach(struct device *, struct device *, void *);
-void *amr_enquire(struct amr_softc *, u_int8_t, u_int8_t, u_int8_t);
+void *amr_enquire(struct amr_softc *, u_int8_t, u_int8_t, u_int8_t, void *);
int amr_init(struct amr_softc *, const char *,
struct pci_attach_args *pa);
int amr_intr(void *);
@@ -108,11 +102,14 @@
int amr_print(void *, const char *);
void amr_shutdown(void *);
int amr_submatch(struct device *, struct cfdata *, void *);
+void amr_teardown(struct amr_softc *);
+void amr_thread(void *);
+void amr_thread_create(void *);
int amr_mbox_wait(struct amr_softc *);
-int amr_quartz_get_work(struct amr_softc *, struct amr_mailbox *);
+int amr_quartz_get_work(struct amr_softc *, struct amr_mailbox_resp *);
int amr_quartz_submit(struct amr_softc *, struct amr_ccb *);
-int amr_std_get_work(struct amr_softc *, struct amr_mailbox *);
+int amr_std_get_work(struct amr_softc *, struct amr_mailbox_resp *);
int amr_std_submit(struct amr_softc *, struct amr_ccb *);
static inline u_int8_t amr_inb(struct amr_softc *, int);
@@ -130,7 +127,7 @@
u_short apt_vendor;
u_short apt_product;
u_short apt_flags;
-} static const amr_pci_type[] = {
+} const amr_pci_type[] = {
{ PCI_VENDOR_AMI, PCI_PRODUCT_AMI_MEGARAID, 0 },
{ PCI_VENDOR_AMI, PCI_PRODUCT_AMI_MEGARAID2, 0 },
{ PCI_VENDOR_AMI, PCI_PRODUCT_AMI_MEGARAID3, AT_QUARTZ },
@@ -140,7 +137,7 @@
struct amr_typestr {
const char *at_str;
int at_sig;
-} static const amr_typestr[] = {
+} const amr_typestr[] = {
{ "Series 431", AMR_SIG_431 },
{ "Series 438", AMR_SIG_438 },
{ "Series 466", AMR_SIG_466 },
@@ -151,7 +148,22 @@
{ "HP NetRAID (T7)", AMR_SIG_T7 },
};
-static void *amr_sdh;
+struct {
+ const char *ds_descr;
+ int ds_happy;
+} const amr_dstate[] = {
+ { "offline", 0 },
+ { "degraded", 1 },
+ { "optimal", 1 },
+ { "online", 1 },
+ { "failed", 0 },
+ { "rebuilding", 1 },
+ { "hotspare", 0 },
+};
+
+void *amr_sdh;
+int amr_max_segs;
+int amr_max_xfer;
static inline u_int8_t
amr_inb(struct amr_softc *amr, int off)
@@ -224,8 +236,7 @@
}
/*
- * Attach a supported device. XXX This doesn't fail gracefully, and may
- * over-allocate resources.
+ * Attach a supported device.
*/
void
amr_attach(struct device *parent, struct device *self, void *aux)
@@ -240,8 +251,8 @@
pci_intr_handle_t ih;
const char *intrstr;
pcireg_t reg;
- int rseg, i, size, rv, memreg, ioreg;
- bus_dma_segment_t seg;
+ int rseg, i, j, size, rv, memreg, ioreg;
+ bus_size_t memsize, iosize;
struct amr_ccb *ac;
aprint_naive(": RAID controller\n");
@@ -261,11 +272,11 @@
reg = pci_conf_read(pc, pa->pa_tag, i);
switch (PCI_MAPREG_TYPE(reg)) {
case PCI_MAPREG_TYPE_MEM:
- if (PCI_MAPREG_MEM_SIZE(reg) != 0)
+ if ((memsize = PCI_MAPREG_MEM_SIZE(reg)) != 0)
memreg = i;
break;
case PCI_MAPREG_TYPE_IO:
- if (PCI_MAPREG_IO_SIZE(reg) != 0)
+ if ((iosize = PCI_MAPREG_IO_SIZE(reg)) != 0)
ioreg = i;
break;
}
@@ -283,15 +294,20 @@
if (memreg) {
amr->amr_iot = memt;
amr->amr_ioh = memh;
+ amr->amr_ios = memsize;
} else if (ioreg) {
amr->amr_iot = iot;
amr->amr_ioh = ioh;
+ amr->amr_ios = iosize;
} else {
aprint_error("can't map control registers\n");
+ amr_teardown(amr);
return;
}
+ amr->amr_flags |= AMRF_PCI_REGS;
amr->amr_dmat = pa->pa_dmat;
+ amr->amr_pc = pa->pa_pc;
/* Enable the device. */
reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
@@ -301,6 +317,7 @@
/* Map and establish the interrupt. */
if (pci_intr_map(pa, &ih)) {
aprint_error("can't map interrupt\n");
+ amr_teardown(amr);
return;
}
intrstr = pci_intr_string(pc, ih);
@@ -310,8 +327,10 @@
if (intrstr != NULL)
aprint_normal(" at %s", intrstr);
aprint_normal("\n");
+ amr_teardown(amr);
return;
}
+ amr->amr_flags |= AMRF_PCI_INTR;
/*
* Allocate space for the mailbox and S/G lists. Some controllers
@@ -323,43 +342,51 @@
* size, which preceeds the standard mailbox.
*/
size = AMR_SGL_SIZE * AMR_MAX_CMDS + 0x2000;
+ amr->amr_dmasize = size;
- if ((rv = bus_dmamem_alloc(amr->amr_dmat, size, PAGE_SIZE, NULL, &seg,
- 1, &rseg, BUS_DMA_NOWAIT)) != 0) {
+ if ((rv = bus_dmamem_alloc(amr->amr_dmat, size, PAGE_SIZE, NULL,
+ &amr->amr_dmaseg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) {
aprint_error("%s: unable to allocate buffer, rv = %d\n",
amr->amr_dv.dv_xname, rv);
+ amr_teardown(amr);
return;
}
+ amr->amr_flags |= AMRF_DMA_ALLOC;
- if ((rv = bus_dmamem_map(amr->amr_dmat, &seg, rseg, size,
+ if ((rv = bus_dmamem_map(amr->amr_dmat, &amr->amr_dmaseg, rseg, size,
(caddr_t *)&amr->amr_mbox,
BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) {
aprint_error("%s: unable to map buffer, rv = %d\n",
amr->amr_dv.dv_xname, rv);
+ amr_teardown(amr);
return;
}
+ amr->amr_flags |= AMRF_DMA_MAP;
if ((rv = bus_dmamap_create(amr->amr_dmat, size, 1, size, 0,
BUS_DMA_NOWAIT, &amr->amr_dmamap)) != 0) {
aprint_error("%s: unable to create buffer DMA map, rv = %d\n",
amr->amr_dv.dv_xname, rv);
+ amr_teardown(amr);
return;
}
+ amr->amr_flags |= AMRF_DMA_CREATE;
if ((rv = bus_dmamap_load(amr->amr_dmat, amr->amr_dmamap,
amr->amr_mbox, size, NULL, BUS_DMA_NOWAIT)) != 0) {
aprint_error("%s: unable to load buffer DMA map, rv = %d\n",
amr->amr_dv.dv_xname, rv);
+ amr_teardown(amr);
return;
}
+ amr->amr_flags |= AMRF_DMA_LOAD;
memset(amr->amr_mbox, 0, size);
- amr->amr_mbox_paddr = amr->amr_dmamap->dm_segs[0].ds_addr + 16;
+ amr->amr_mbox_paddr = amr->amr_dmamap->dm_segs[0].ds_addr;
amr->amr_sgls_paddr = (amr->amr_mbox_paddr + 0x1fff) & ~0x1fff;
amr->amr_sgls = (struct amr_sgentry *)((caddr_t)amr->amr_mbox +
amr->amr_sgls_paddr - amr->amr_dmamap->dm_segs[0].ds_addr);
- amr->amr_mbox = (struct amr_mailbox *)((caddr_t)amr->amr_mbox + 16);
/*
* Allocate and initalise the command control blocks.
@@ -367,21 +394,28 @@
ac = malloc(sizeof(*ac) * AMR_MAX_CMDS, M_DEVBUF, M_NOWAIT | M_ZERO);
amr->amr_ccbs = ac;
SLIST_INIT(&amr->amr_ccb_freelist);
+ amr->amr_flags |= AMRF_CCBS;
+
+ if (amr_max_xfer == 0) {
+ amr_max_xfer = min(((AMR_MAX_SEGS - 1) * PAGE_SIZE), MAXPHYS);
+ amr_max_segs = (amr_max_xfer + (PAGE_SIZE * 2) - 1) / PAGE_SIZE;
+ }
for (i = 0; i < AMR_MAX_CMDS; i++, ac++) {
- rv = bus_dmamap_create(amr->amr_dmat, AMR_MAX_XFER,
- AMR_MAX_SEGS, AMR_MAX_XFER, 0,
- BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
- &ac->ac_xfer_map);
+ rv = bus_dmamap_create(amr->amr_dmat, amr_max_xfer,
+ amr_max_segs, amr_max_xfer, 0,
+ BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ac->ac_xfer_map);
if (rv != 0)
break;
ac->ac_ident = i;
- SLIST_INSERT_HEAD(&amr->amr_ccb_freelist, ac, ac_chain.slist);
+ amr_ccb_free(amr, ac);
}
- if (i != AMR_MAX_CMDS)
- aprint_error("%s: %d/%d CCBs created\n", amr->amr_dv.dv_xname,
- i, AMR_MAX_CMDS);
+ if (i != AMR_MAX_CMDS) {
+ aprint_error("%s: memory exhausted\n", amr->amr_dv.dv_xname);
+ amr_teardown(amr);
+ return;
+ }
/*
* Take care of model-specific tasks.
@@ -394,7 +428,7 @@
amr->amr_get_work = amr_std_get_work;
/* Notify the controller of the mailbox location. */
- amr_outl(amr, AMR_SREG_MBOX, amr->amr_mbox_paddr);
+ amr_outl(amr, AMR_SREG_MBOX, (u_int32_t)amr->amr_mbox_paddr + 16);
amr_outb(amr, AMR_SREG_MBOX_ENABLE, AMR_SMBOX_ENABLE_ADDR);
/* Clear outstanding interrupts and enable interrupts. */
@@ -406,10 +440,14 @@
/*
* Retrieve parameters, and tell the world about us.
*/
+ amr->amr_enqbuf = malloc(AMR_ENQUIRY_BUFSIZE, M_DEVBUF, M_NOWAIT);
+ amr->amr_flags |= AMRF_ENQBUF;
amr->amr_maxqueuecnt = i;
aprint_normal(": AMI RAID ");
- if (amr_init(amr, intrstr, pa) != 0)
+ if (amr_init(amr, intrstr, pa) != 0) {
+ amr_teardown(amr);
return;
+ }
/*
* Cap the maximum number of outstanding commands. AMI's Linux
Home |
Main Index |
Thread Index |
Old Index