diff options
author | Marco Peereboom <marco@cvs.openbsd.org> | 2004-12-26 00:11:25 +0000 |
---|---|---|
committer | Marco Peereboom <marco@cvs.openbsd.org> | 2004-12-26 00:11:25 +0000 |
commit | d183791fce4eeb99a399a9ba4c1de10f297d5194 (patch) | |
tree | c931c1a0b509b7c1438df448213491ff507709da | |
parent | f61599123255c5e32425e5311bf19a99877520b3 (diff) |
This should fix long outstanding issues with ami(4). The reported
symptoms that were fixed are:
* Very slow throughput
* ccb timeout (i.e. ami0: timeout ccb 1)
* All IO to ami devices hangs
* Only 1 LD (Logical Drive) can be accessed at the same time
* System hangs/freezes when running IO to ami cards.
Issues it doesn't fix:
* Really old ULTRA-2 controllers still crash whenever more than 1 LD are
accessed at the same time therefore the driver limits the maximum LDs to 1.
Tested by several folks and ok beck@ mickey@
-rw-r--r-- | sys/dev/ic/ami.c | 280 | ||||
-rw-r--r-- | sys/dev/ic/amireg.h | 5 | ||||
-rw-r--r-- | sys/dev/ic/amivar.h | 9 | ||||
-rw-r--r-- | sys/dev/pci/ami_pci.c | 71 |
4 files changed, 275 insertions, 90 deletions
diff --git a/sys/dev/ic/ami.c b/sys/dev/ic/ami.c index e3db905c426..0b02b2f7465 100644 --- a/sys/dev/ic/ami.c +++ b/sys/dev/ic/ami.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ami.c,v 1.24 2004/01/09 21:32:23 brad Exp $ */ +/* $OpenBSD: ami.c,v 1.25 2004/12/26 00:11:24 marco Exp $ */ /* * Copyright (c) 2001 Michael Shalayeff @@ -103,8 +103,14 @@ struct scsi_device ami_raw_dev = { NULL, NULL, NULL, NULL }; -static __inline struct ami_ccb *ami_get_ccb(struct ami_softc *sc); -static __inline void ami_put_ccb(struct ami_ccb *ccb); +struct ami_ccb *ami_get_ccb(struct ami_softc *sc); +void ami_put_ccb(struct ami_ccb *ccb); + +void ami_write_inbound_db(struct ami_softc *, u_int32_t); +void ami_write_outbound_db(struct ami_softc *, u_int32_t); +u_int32_t ami_read_inbound_db(struct ami_softc *); +u_int32_t ami_read_outbound_db(struct ami_softc *); + void ami_copyhds(struct ami_softc *sc, const u_int32_t *sizes, const u_int8_t *props, const u_int8_t *stats); void *ami_allocmem(bus_dma_tag_t dmat, bus_dmamap_t *map, @@ -121,7 +127,7 @@ void ami_copy_internal_data(struct scsi_xfer *xs, void *v, size_t size); int ami_inquire(struct ami_softc *sc, u_int8_t op); -static __inline struct ami_ccb * +struct ami_ccb * ami_get_ccb(sc) struct ami_softc *sc; { @@ -135,7 +141,7 @@ ami_get_ccb(sc) return ccb; } -static __inline void +void ami_put_ccb(ccb) struct ami_ccb *ccb; { @@ -145,6 +151,58 @@ ami_put_ccb(ccb) TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, ccb_link); } +void +ami_write_inbound_db(sc, v) + struct ami_softc *sc; + u_int32_t v; +{ + AMI_DPRINTF(AMI_D_CMD, ("ami_write_inbound_db(%x)", v)); + + bus_space_write_4(sc->iot, sc->ioh, AMI_QIDB, v); + bus_space_barrier(sc->iot, sc->ioh, + AMI_QIDB, 4, BUS_SPACE_BARRIER_WRITE); +} + +u_int32_t +ami_read_inbound_db(sc) + struct ami_softc *sc; +{ + u_int32_t rv; + + bus_space_barrier(sc->iot, sc->ioh, + AMI_QIDB, 4, BUS_SPACE_BARRIER_READ); + rv = bus_space_read_4(sc->iot, sc->ioh, AMI_QIDB); + AMI_DPRINTF(AMI_D_CMD, ("ami_read_inbound_db(%x)", rv)); + + return (rv); +} + +void +ami_write_outbound_db(sc, v) + struct ami_softc *sc; + u_int32_t v; +{ + AMI_DPRINTF(AMI_D_CMD, ("ami_write_outbound_db(%x)", v)); + + bus_space_write_4(sc->iot, sc->ioh, AMI_QODB, v); + bus_space_barrier(sc->iot, sc->ioh, + AMI_QODB, 4, BUS_SPACE_BARRIER_WRITE); +} + +u_int32_t +ami_read_outbound_db(sc) + struct ami_softc *sc; +{ + u_int32_t rv; + + bus_space_barrier(sc->iot, sc->ioh, + AMI_QODB, 4, BUS_SPACE_BARRIER_READ); + rv = bus_space_read_4(sc->iot, sc->ioh, AMI_QODB); + AMI_DPRINTF(AMI_D_CMD, ("ami_read_outbound_db(%x)", rv)); + + return (rv); +} + void * ami_allocmem(dmat, map, segp, isize, nent, iname) bus_dma_tag_t dmat; @@ -414,8 +472,22 @@ ami_attach(sc) AMI_UNLOCK_AMI(sc, lock); - if (sc->sc_maxcmds > AMI_MAXCMDS) - sc->sc_maxcmds = 1 /* AMI_MAXCMDS */; + if (sc->sc_quirks & AMI_BROKEN) { + sc->sc_link.openings = 1; + sc->sc_maxcmds = 1; + sc->sc_maxunits = 1; + } + else { + sc->sc_maxunits = AMI_BIG_MAX_LDRIVES; + if (sc->sc_maxcmds > AMI_MAXCMDS) + sc->sc_maxcmds = AMI_MAXCMDS; + + if (sc->sc_nunits) + sc->sc_link.openings = + sc->sc_maxcmds / sc->sc_nunits; + else + sc->sc_link.openings = sc->sc_maxcmds; + } } ami_freemem(sc->dmat, &idatamap, idataseg, NBPG, 1, "init data"); @@ -431,22 +503,35 @@ ami_attach(sc) sc->sc_biosver[2], sc->sc_biosver[1], sc->sc_biosver[0]); } - printf(": FW %s, BIOS v%s, %dMB RAM\n" - "%s: %d channels, %d %ss, %d logical drives\n", - sc->sc_fwver, sc->sc_biosver, sc->sc_memory, - sc->sc_dev.dv_xname, - sc->sc_channels, sc->sc_targets, p, sc->sc_nunits); - /* TODO: fetch & print cache strategy */ /* TODO: fetch & print scsi and raid info */ sc->sc_link.device = &ami_dev; - sc->sc_link.openings = sc->sc_maxcmds; sc->sc_link.adapter_softc = sc; sc->sc_link.adapter = &ami_switch; sc->sc_link.adapter_target = sc->sc_maxunits; sc->sc_link.adapter_buswidth = sc->sc_maxunits; +#ifdef AMI_DEBUG + printf(": FW %s, BIOS v%s, %dMB RAM\n" + "%s: %d channels, %d %ss, %d logical drives, " + "openings %d, max commands %d, quirks: %04x\n", + sc->sc_fwver, sc->sc_biosver, sc->sc_memory, + sc->sc_dev.dv_xname, + sc->sc_channels, sc->sc_targets, p, sc->sc_nunits, + sc->sc_link.openings, sc->sc_maxcmds, sc->sc_quirks); +#else + printf(": FW %s, BIOS v%s, %dMB RAM\n" + "%s: %d channels, %d %ss, %d logical drives\n", + sc->sc_fwver, sc->sc_biosver, sc->sc_memory, + sc->sc_dev.dv_xname, + sc->sc_channels, sc->sc_targets, p, sc->sc_nunits); +#endif /* AMI_DEBUG */ + + if (sc->sc_quirks & AMI_BROKEN && sc->sc_nunits > 1) + printf("%s: firmware buggy, limiting access to first logical " + "disk\n", sc->sc_dev.dv_xname); + config_found(&sc->sc_dev, &sc->sc_link, scsiprint); #if 0 rsc = malloc(sizeof(struct ami_rawsoftc) * sc->sc_channels, @@ -483,9 +568,7 @@ int ami_quartz_init(sc) struct ami_softc *sc; { - bus_space_write_4(sc->iot, sc->ioh, AMI_QIDB, 0); - bus_space_barrier(sc->iot, sc->ioh, - AMI_QIDB, 4, BUS_SPACE_BARRIER_WRITE); + ami_write_inbound_db(sc, 0); return 0; } @@ -495,31 +578,32 @@ ami_quartz_exec(sc, cmd) struct ami_softc *sc; struct ami_iocmd *cmd; { - u_int32_t qidb; + u_int32_t qidb, i; - bus_space_barrier(sc->iot, sc->ioh, - AMI_QIDB, 4, BUS_SPACE_BARRIER_READ); - qidb = bus_space_read_4(sc->iot, sc->ioh, AMI_QIDB); - if (qidb & (AMI_QIDB_EXEC | AMI_QIDB_ACK)) { - AMI_DPRINTF(AMI_D_CMD, ("qidb1=%x ", qidb)); - return (EBUSY); - } + AMI_DPRINTF(AMI_D_CMD, ("ami_quartz_exec() ")); - /* do not scramble the busy mailbox */ + i = 0; + while (sc->sc_mbox->acc_busy && (i < AMI_MAX_BUSYWAIT)) { + delay(1); + i++; + } if (sc->sc_mbox->acc_busy) { AMI_DPRINTF(AMI_D_CMD, ("mbox_busy ")); return (EBUSY); } - *sc->sc_mbox = *cmd; - bus_dmamap_sync(sc->dmat, sc->sc_cmdmap, 0, sizeof(*cmd), + memcpy((struct ami_iocmd *)sc->sc_mbox, cmd, 16); + bus_dmamap_sync(sc->dmat, sc->sc_cmdmap, 0, 16, BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD); + sc->sc_mbox->acc_busy = 1; + sc->sc_mbox->acc_poll = 0; + sc->sc_mbox->acc_ack = 0; + qidb = sc->sc_mbox_pa | AMI_QIDB_EXEC; - AMI_DPRINTF(AMI_D_CMD, ("qidb2=%x ", qidb)); - bus_space_write_4(sc->iot, sc->ioh, AMI_QIDB, qidb); - bus_space_barrier(sc->iot, sc->ioh, - AMI_QIDB, 4, BUS_SPACE_BARRIER_WRITE); + ami_write_inbound_db(sc, qidb); + + AMI_DPRINTF(AMI_D_CMD, ("ami_quartz_exec() returning ")); return (0); } @@ -528,46 +612,72 @@ ami_quartz_done(sc, mbox) struct ami_softc *sc; struct ami_iocmd *mbox; { - u_int32_t qdb; - - bus_space_barrier(sc->iot, sc->ioh, - AMI_QIDB, 4, BUS_SPACE_BARRIER_READ); - qdb = bus_space_read_4(sc->iot, sc->ioh, AMI_QIDB); - if (qdb & (AMI_QIDB_EXEC | AMI_QIDB_ACK)) { - AMI_DPRINTF(AMI_D_CMD, ("qidb3=%x ", qdb)); - return (0); + u_int32_t qdb, i, n; + u_int8_t nstat, status; + u_int8_t completed[AMI_MAXSTATACK]; + + AMI_DPRINTF(AMI_D_CMD, ("ami_quartz_done() ")); + + qdb = ami_read_outbound_db(sc); + if (qdb != AMI_QODB_READY) + return (0); /* nothing to do */ + + ami_write_outbound_db(sc, AMI_QODB_READY); + + /* + * The following sequence is not supposed to have a timeout clause + * since the firmware has a "guarantee" that all commands will + * complete. The choice is either panic or hoping for a miracle + * and that the IOs will complete much later. + */ + i = 0; + while ((nstat = sc->sc_mbox->acc_nstat) == 0xff) { + delay(1); + if (i++ > 1000000) + return (0); /* nothing to do */ } - - /* do not scramble the busy mailbox */ - if (sc->sc_mbox->acc_busy) { - AMI_DPRINTF(AMI_D_CMD, ("mbox_busy ")); - return (0); + sc->sc_mbox->acc_nstat = 0xff; + + /* wait until fw wrote out all completions */ + i = 0; + AMI_DPRINTF(AMI_D_CMD, ("ami_quartz_done() nstat %d ", nstat)); + for (n = 0; n < nstat; n++) { + while ((completed[n] = sc->sc_mbox->acc_cmplidl[n]) == + 0xff) { + delay(1); + if (i++ > 1000000) + return (0); /* nothing to do */ + } + sc->sc_mbox->acc_cmplidl[n] = 0xff; } - bus_space_barrier(sc->iot, sc->ioh, - AMI_QODB, 4, BUS_SPACE_BARRIER_READ); - qdb = bus_space_read_4(sc->iot, sc->ioh, AMI_QODB); - if (qdb == AMI_QODB_READY) { + /* this should never happen, someone screwed up the completion status */ + if ((status = sc->sc_mbox->acc_status) == 0xff) + panic("%s: status 0xff from the firmware", sc->sc_dev.dv_xname); - bus_dmamap_sync(sc->dmat, sc->sc_cmdmap, 0, sizeof(*mbox), - BUS_DMASYNC_POSTWRITE); - *mbox = *sc->sc_mbox; + sc->sc_mbox->acc_status = 0xff; - /* ack interrupt */ - bus_space_write_4(sc->iot, sc->ioh, AMI_QODB, AMI_QODB_READY); - bus_space_barrier(sc->iot, sc->ioh, - AMI_QODB, 4, BUS_SPACE_BARRIER_WRITE); + /* ack interrupt */ + ami_write_inbound_db(sc, AMI_QIDB_ACK); - qdb = sc->sc_mbox_pa | AMI_QIDB_ACK; - bus_space_write_4(sc->iot, sc->ioh, AMI_QIDB, qdb); - bus_space_barrier(sc->iot, sc->ioh, - AMI_QIDB, 4, BUS_SPACE_BARRIER_WRITE); - return (1); + i = 0; + while(ami_read_inbound_db(sc) & AMI_QIDB_ACK) { + delay(1); + if (i++ > 1000000) + return (0); /* nothing to do */ } - AMI_DPRINTF(AMI_D_CMD, ("qodb=%x ", qdb)); + /* copy mailbox to temporary one and fixup other changed values */ + bus_dmamap_sync(sc->dmat, sc->sc_cmdmap, 0, 16, + BUS_DMASYNC_POSTWRITE); + memcpy(mbox, (struct ami_iocmd *)sc->sc_mbox, 16); + mbox->acc_nstat = nstat; + mbox->acc_status = status; + for (n = 0; n < nstat; n++) { + mbox->acc_cmplidl[n] = completed[n]; + } - return (0); + return (1); /* ready to complete all IOs in acc_cmplidl */ } int @@ -576,6 +686,8 @@ ami_schwartz_init(sc) { u_int32_t a = (u_int32_t)sc->sc_mbox_pa; + AMI_DPRINTF(AMI_D_CMD, ("ami_schwartz_init() ")); + bus_space_write_4(sc->iot, sc->ioh, AMI_SMBADDR, a); /* XXX 40bit address ??? */ bus_space_write_1(sc->iot, sc->ioh, AMI_SMBENA, 0); @@ -592,10 +704,18 @@ ami_schwartz_exec(sc, cmd) struct ami_softc *sc; struct ami_iocmd *cmd; { - if (bus_space_read_1(sc->iot, sc->ioh, AMI_SMBSTAT) & AMI_SMBST_BUSY) + AMI_DPRINTF(AMI_D_CMD, ("ami_schwartz_exec() ")); + + if (bus_space_read_1(sc->iot, sc->ioh, AMI_SMBSTAT) & AMI_SMBST_BUSY) { + AMI_DPRINTF(AMI_D_CMD, ("mbox_busy ")); return EBUSY; + } + + memcpy((struct ami_iocmd *)sc->sc_mbox, cmd, 16); + sc->sc_mbox->acc_busy = 1; + sc->sc_mbox->acc_poll = 0; + sc->sc_mbox->acc_ack = 0; - *sc->sc_mbox = *cmd; bus_space_write_1(sc->iot, sc->ioh, AMI_SCMD, AMI_SCMD_EXEC); return 0; } @@ -606,6 +726,8 @@ ami_schwartz_done(sc, mbox) struct ami_iocmd *mbox; { u_int8_t stat; + + AMI_DPRINTF(AMI_D_CMD, ("ami_schwartz_done() ")); #if 0 /* do not scramble the busy mailbox */ if (sc->sc_mbox->acc_busy) @@ -619,6 +741,8 @@ ami_schwartz_done(sc, mbox) bus_space_write_1(sc->iot, sc->ioh, AMI_ISTAT, stat); *mbox = *sc->sc_mbox; + AMI_DPRINTF(AMI_D_CMD, ("ami_schwartz_done() acc_nstat %d ", + mbox->acc_nstat)); bus_space_write_1(sc->iot, sc->ioh, AMI_SCMD, AMI_SCMD_ACK); @@ -735,10 +859,6 @@ ami_start(ccb, wait) AMI_DPRINTF(AMI_D_CMD, ("exec ")); - cmd->acc_busy = 1; - cmd->acc_poll = 0; - cmd->acc_ack = 0; - if (!(i = (sc->sc_exec)(sc, cmd))) { ccb->ccb_state = AMI_CCB_QUEUED; TAILQ_INSERT_TAIL(&sc->sc_ccbq, ccb, ccb_link); @@ -1301,7 +1421,6 @@ ami_intr(v) lock = AMI_LOCK_AMI(sc); s = splimp(); /* XXX need to do this to mask timeouts */ while ((sc->sc_done)(sc, &mbox)) { - AMI_DPRINTF(AMI_D_CMD, ("got#%d ", mbox.acc_nstat)); for (i = 0; i < mbox.acc_nstat; i++ ) { int ready = mbox.acc_cmplidl[i]; @@ -1324,3 +1443,24 @@ ami_intr(v) AMI_DPRINTF(AMI_D_INTR, ("exit ")); return (rv); } + +#ifdef AMI_DEBUG +void +ami_print_mbox(mbox) + struct ami_iocmd *mbox; +{ + int i; + + printf("acc_cmd: %d aac_id: %d acc_busy: %d acc_nstat: %d", + mbox->acc_cmd, mbox->acc_id, mbox->acc_busy, mbox->acc_nstat); + printf("acc_status: %d acc_poll: %d acc_ack: %d\n", + mbox->acc_status, mbox->acc_poll, mbox->acc_ack); + + printf("acc_cmplidl: "); + for (i = 0; i < AMI_MAXSTATACK; i++) { + printf("[%d] = %d ", i, mbox->acc_cmplidl[i]); + } + + printf("\n"); +} +#endif /* AMI_DEBUG */ diff --git a/sys/dev/ic/amireg.h b/sys/dev/ic/amireg.h index bd333549210..739b5d8a010 100644 --- a/sys/dev/ic/amireg.h +++ b/sys/dev/ic/amireg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: amireg.h,v 1.4 2003/06/02 19:24:22 mickey Exp $ */ +/* $OpenBSD: amireg.h,v 1.5 2004/12/26 00:11:24 marco Exp $ */ /* * Copyright (c) 2000 Michael Shalayeff @@ -36,10 +36,11 @@ #define AMI_BIG_MAX_SPANDEPTH 8 #define AMI_BIG_MAX_DEVDEPTH 32 -#define AMI_MAXCMDS 120 /* theoretical limit is 255 */ +#define AMI_MAXCMDS 126 /* theoretical limit is 250 */ #define AMI_SECTOR_SIZE 512 #define AMI_MAXOFFSETS 26 #define AMI_SGEPERCMD 32 /* to prevent page boundary crossing */ +#define AMI_MAX_BUSYWAIT 10 /* wait up to 10 usecs */ #define AMI_MAXFER (AMI_MAXOFFSETS * PAGE_SIZE) diff --git a/sys/dev/ic/amivar.h b/sys/dev/ic/amivar.h index 2e544c072b1..c4a5d556f06 100644 --- a/sys/dev/ic/amivar.h +++ b/sys/dev/ic/amivar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: amivar.h,v 1.6 2003/06/02 19:24:22 mickey Exp $ */ +/* $OpenBSD: amivar.h,v 1.7 2004/12/26 00:11:24 marco Exp $ */ /* * Copyright (c) 2001 Michael Shalayeff @@ -86,6 +86,10 @@ struct ami_softc { struct timeout sc_requeue_tmo; struct timeout sc_poll_tmo; +/* don't use 0x0001 */ +#define AMI_BROKEN 0x0002 + u_int16_t sc_quirks; + char sc_fwver[16]; char sc_biosver[16]; int sc_maxcmds; @@ -122,3 +126,6 @@ int ami_schwartz_init(struct ami_softc *sc); int ami_schwartz_exec(struct ami_softc *sc, struct ami_iocmd *); int ami_schwartz_done(struct ami_softc *sc, struct ami_iocmd *); +#ifdef AMI_DEBUG +void ami_print_mbox(struct ami_iocmd *); +#endif /* AMI_DEBUG */ diff --git a/sys/dev/pci/ami_pci.c b/sys/dev/pci/ami_pci.c index afe418f5d33..28ec9ee9b12 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.20 2004/11/22 21:09:18 deraadt Exp $ */ +/* $OpenBSD: ami_pci.c,v 1.21 2004/12/26 00:11:24 marco Exp $ */ /* * Copyright (c) 2001 Michael Shalayeff @@ -62,6 +62,7 @@ #define AMI_SGL_LHC 0x00000299 #define AMI_SGL_HLC 0x00000199 +int ami_pci_find_device(void *); int ami_pci_match(struct device *, void *, void *); void ami_pci_attach(struct device *, struct device *, void *); @@ -77,12 +78,13 @@ struct ami_pci_device { #define AMI_CHECK_SIGN 0x001 } ami_pci_devices[] = { { PCI_VENDOR_AMI, PCI_PRODUCT_AMI_MEGARAID, 0 }, - { PCI_VENDOR_AMI, PCI_PRODUCT_AMI_MEGARAID428, 0 }, - { PCI_VENDOR_AMI, PCI_PRODUCT_AMI_MEGARAID434, 0 }, + { PCI_VENDOR_AMI, PCI_PRODUCT_AMI_MEGARAID428, AMI_BROKEN }, + { PCI_VENDOR_AMI, PCI_PRODUCT_AMI_MEGARAID434, AMI_BROKEN }, { PCI_VENDOR_DELL, PCI_PRODUCT_DELL_PERC_4DI, 0 }, { PCI_VENDOR_DELL, PCI_PRODUCT_DELL_PERC_4DI_2, 0 }, { PCI_VENDOR_DELL, PCI_PRODUCT_DELL_PERC_4EDI, 0 }, - { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_80960RP_ATU, AMI_CHECK_SIGN }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_80960RP_ATU, + AMI_CHECK_SIGN | AMI_BROKEN }, { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_MEGARAID, 0 }, { 0 } }; @@ -117,6 +119,25 @@ struct ami_pci_vendor { { 0 } }; +int ami_pci_find_device(aux) + void *aux; +{ + int i; + struct pci_attach_args *pa = aux; + + for (i = 0; ami_pci_devices[i].vendor; i++) { + if (ami_pci_devices[i].vendor == PCI_VENDOR(pa->pa_id) && + ami_pci_devices[i].product == PCI_PRODUCT(pa->pa_id)) { +#ifdef AMI_DEBUG + printf(" ami_pci_find_device() %i ", i); +#endif /* AMI_DEBUG */ + return (i); + } + } + + return (-1); +} + int ami_pci_match(parent, match, aux) struct device *parent; @@ -124,25 +145,29 @@ ami_pci_match(parent, match, aux) void *aux; { struct pci_attach_args *pa = aux; - const struct ami_pci_device *pami; + int i; pcireg_t sig; if (PCI_CLASS(pa->pa_class) == PCI_CLASS_I2O) return (0); - for (pami = ami_pci_devices; pami->vendor; pami++) { - if (pami->vendor == PCI_VENDOR(pa->pa_id) && - pami->product == PCI_PRODUCT(pa->pa_id)) { - if (!(pami->flags & AMI_CHECK_SIGN)) - return (1); - /* some cards have 0x11223344, but some only 16bit */ - sig = pci_conf_read(pa->pa_pc, pa->pa_tag, - AMI_PCI_SIG) & 0xffff; - if (sig == AMI_SIGNATURE_1 || - sig == AMI_SIGNATURE_2) - return (1); - } + if ((i = ami_pci_find_device(aux)) != -1) { +#ifdef AMI_DEBUG + printf("\nvendor: %04x product: %04x\n", + ami_pci_devices[i].vendor, + ami_pci_devices[i].product); +#endif /* AMI_DEBUG */ + + if (!(ami_pci_devices[i].flags & AMI_CHECK_SIGN)) + return (1); + /* some cards have 0x11223344, but some only 16bit */ + sig = pci_conf_read(pa->pa_pc, pa->pa_tag, + AMI_PCI_SIG) & 0xffff; + if (sig == AMI_SIGNATURE_1 || + sig == AMI_SIGNATURE_2) + return (1); } + return (0); } @@ -158,6 +183,7 @@ ami_pci_attach(parent, self, aux) const struct ami_pci_subsys *ssp; bus_size_t size; pcireg_t csr; + int i; #if 0 /* reset */ pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_EBCR, @@ -247,6 +273,17 @@ ami_pci_attach(parent, self, aux) default: lhc = "32b"; } + if ((i = ami_pci_find_device(aux)) != -1) { + if (ami_pci_devices[i].flags & AMI_BROKEN) + sc->sc_quirks = AMI_BROKEN; + else + sc->sc_quirks = 0x0000; + } + else { + /* this device existed at _match() should never happen */ + panic("ami device dissapeared between match() and attach()\n"); + } + printf(" %s/%s\n%s", model, lhc, sc->sc_dev.dv_xname); if (ami_attach(sc)) { |