diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/ic/ami.c | 225 | ||||
-rw-r--r-- | sys/dev/ic/amireg.h | 9 | ||||
-rw-r--r-- | sys/dev/ic/amivar.h | 9 | ||||
-rw-r--r-- | sys/dev/pci/ami_pci.c | 4 |
4 files changed, 167 insertions, 80 deletions
diff --git a/sys/dev/ic/ami.c b/sys/dev/ic/ami.c index ca6c21a94d3..9508de67b4a 100644 --- a/sys/dev/ic/ami.c +++ b/sys/dev/ic/ami.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ami.c,v 1.38 2005/05/17 18:38:52 marco Exp $ */ +/* $OpenBSD: ami.c,v 1.39 2005/05/27 20:39:29 marco Exp $ */ /* * Copyright (c) 2001 Michael Shalayeff @@ -45,7 +45,7 @@ * Theo de Raadt. */ - /*#define AMI_DEBUG */ +/*#define AMI_DEBUG */ #include <sys/param.h> #include <sys/systm.h> @@ -75,8 +75,8 @@ #define AMI_D_DMA 0x0008 #define AMI_D_IOCTL 0x0010 int ami_debug = 0 -/* | AMI_D_CMD */ -/* | AMI_D_INTR */ + | AMI_D_CMD + | AMI_D_INTR | AMI_D_MISC /* | AMI_D_DMA */ /* | AMI_D_IOCTL */ @@ -128,7 +128,6 @@ void ami_dispose(struct ami_softc *sc); void ami_stimeout(void *v); int ami_cmd(struct ami_ccb *ccb, int flags, int wait); int ami_start(struct ami_ccb *ccb, int wait); -int ami_complete(struct ami_ccb *ccb); int ami_done(struct ami_softc *sc, int idx); 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); @@ -745,6 +744,123 @@ ami_quartz_done(sc, mbox) } int +ami_quartz_poll(sc, cmd) + struct ami_softc *sc; + struct ami_iocmd *cmd; +{ + /* struct scsi_xfer *xs = ccb->ccb_xs; */ + u_int32_t qidb, i; + u_int8_t status, ready; + + if (sc->sc_dis_poll) + return 1; /* fail */ + + 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); + } + + 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_id = 0xfe; + sc->sc_mbox->acc_busy = 1; + sc->sc_mbox->acc_poll = 0; + sc->sc_mbox->acc_ack = 0; + + sc->sc_mbox->acc_nstat = 0xff; + sc->sc_mbox->acc_status = 0xff; + + /* send command to firmware */ + qidb = sc->sc_mbox_pa | AMI_QIDB_EXEC; + ami_write_inbound_db(sc, qidb); + + while ((sc->sc_mbox->acc_nstat == 0xff) && (i < AMI_MAX_POLLWAIT)) { + delay(1); + i++; + } + if (i >= AMI_MAX_POLLWAIT) { + printf("%s: command not accepted, polling disabled\n", + sc->sc_dev.dv_xname); + sc->sc_dis_poll = 1; + return 1; + } + + sc->sc_mbox->acc_nstat = 0xff; + + while ((sc->sc_mbox->acc_status == 0xff) && (i < AMI_MAX_POLLWAIT)) { + delay(1); + i++; + } + if (i >= AMI_MAX_POLLWAIT) { + printf("%s: bad status, polling disabled\n", + sc->sc_dev.dv_xname); + sc->sc_dis_poll = 1; + return 1; + } + status = sc->sc_mbox->acc_status; + sc->sc_mbox->acc_status = 0xff; + + /* poll firmware */ + while ((sc->sc_mbox->acc_poll != 0x77) && (i < AMI_MAX_POLLWAIT)) { + delay(1); + i++; + } + if (i >= AMI_MAX_POLLWAIT) { + printf("%s: firmware didn't reply, polling disabled\n", + sc->sc_dev.dv_xname); + sc->sc_dis_poll = 1; + return 1; + } + + sc->sc_mbox->acc_poll = 0; + sc->sc_mbox->acc_ack = 0x77; + + /* ack */ + qidb = sc->sc_mbox_pa | AMI_QIDB_ACK; + ami_write_inbound_db(sc, qidb); + + while((ami_read_inbound_db(sc) & AMI_QIDB_ACK) && + (i < AMI_MAX_POLLWAIT)) { + delay(1); + i++; + } + if (i >= AMI_MAX_POLLWAIT) { + printf("%s: firmware didn't ack the ack, polling disabled\n", + sc->sc_dev.dv_xname); + sc->sc_dis_poll = 1; + return 1; + } + + ready = sc->sc_mbox->acc_cmplidl[0]; + + for (i = 0; i < AMI_MAXSTATACK; i++) + sc->sc_mbox->acc_cmplidl[i] = 0xff; +#if 0 + /* FIXME */ + /* am I a scsi command? if so complete it */ + if (xs) { + printf("sc "); + if (!ami_done(sc, ready)) + status = 0; + else + status = 1; /* failed */ + } + else /* need to clean up ccb ourselves */ + ami_put_ccb(ccb); +#endif + + + return status; +} + +int ami_schwartz_init(sc) struct ami_softc *sc; { @@ -811,6 +927,15 @@ ami_schwartz_done(sc, mbox) } int +ami_schwartz_poll(sc, cmd) + struct ami_softc *sc; + struct ami_iocmd *cmd; +{ + /* FIXME add the actual code here */ + return 1; +} + +int ami_cmd(ccb, flags, wait) struct ami_ccb *ccb; int flags, wait; @@ -866,16 +991,21 @@ ami_cmd(ccb, flags, wait) bus_dmamap_sync(sc->dmat, sc->sc_cmdmap, 0, sc->sc_cmdmap->dm_mapsize, BUS_DMASYNC_PREWRITE); - if ((error = ami_start(ccb, wait))) { + if (wait) { + AMI_DPRINTF(AMI_D_DMA, ("waiting ")); + /* FIXME remove all wait out ami_start */ + if ((error = sc->sc_poll(sc, ccb->ccb_cmd))) { + AMI_DPRINTF(AMI_D_MISC, ("pf ")); + } + /* always free ccb */ + ami_put_ccb(ccb); + } + else if ((error = ami_start(ccb, wait))) { AMI_DPRINTF(AMI_D_DMA, ("error=%d ", error)); __asm __volatile(".globl _bpamierr\n_bpamierr:"); if (ccb->ccb_data) bus_dmamap_unload(sc->dmat, dmap); ami_put_ccb(ccb); - } else if (wait) { - AMI_DPRINTF(AMI_D_DMA, ("waiting ")); - if ((error = ami_complete(ccb))) - ami_put_ccb(ccb); } return (error); @@ -941,6 +1071,7 @@ ami_start(ccb, wait) return (i); } +/* FIXME timeouts should be rethought */ void ami_stimeout(v) void *v; @@ -998,44 +1129,6 @@ ami_stimeout(v) } int -ami_complete(ccb) - struct ami_ccb *ccb; -{ - struct ami_softc *sc = ccb->ccb_sc; - struct scsi_xfer *xs = ccb->ccb_xs; - struct ami_iocmd mbox; - int i, j, rv, status; - - i = 1 * (xs? xs->timeout: 1000); - AMI_DPRINTF(AMI_D_CMD, ("%d ", i)); - for (rv = 1, status = 0; !status && rv && i--; DELAY(1000)) - if ((sc->sc_done)(sc, &mbox)) { - AMI_DPRINTF(AMI_D_CMD, ("got#%d ", mbox.acc_nstat)); - status = mbox.acc_status; - for (j = 0; j < mbox.acc_nstat; j++ ) { - int ready = mbox.acc_cmplidl[j]; - - AMI_DPRINTF(AMI_D_CMD, ("ready=%x ", ready)); - - if (!ami_done(sc, ready) && - ccb->ccb_cmd->acc_id == ready) - rv = 0; - } - } - - if (status) { - AMI_DPRINTF(AMI_D_CMD, ("aborted\n")); - } else if (!rv) { - AMI_DPRINTF(AMI_D_CMD, ("complete\n")); - } else if (i < 0) { - AMI_DPRINTF(AMI_D_CMD, ("timeout\n")); - } else - AMI_DPRINTF(AMI_D_CMD, ("screwed\n")); - - return rv? rv : status; -} - -int ami_done(sc, idx) struct ami_softc *sc; int idx; @@ -1502,12 +1595,18 @@ ami_ioctl(dev, cmd, addr) u_long cmd; caddr_t addr; { - int error = 0; + int lock, error = 0; struct ami_softc *sc = (struct ami_softc *)dev; if (sc->sc_flags & AMI_BROKEN) return ENODEV; /* can't do this to broken device for now */ + lock = AMI_LOCK_AMI(sc); + if (sc->sc_flags & AMI_CMDWAIT) { + AMI_UNLOCK_AMI(sc, lock); + return EBUSY; + } + switch (cmd) { case BIOCPING: ((bioc_ping *)addr)->x++; @@ -1562,6 +1661,8 @@ ami_ioctl(dev, cmd, addr) error = EINVAL; } + AMI_UNLOCK_AMI(sc, lock); + return (error); } @@ -1573,7 +1674,6 @@ ami_ioctl_alarm(sc, ra) int error = 0; struct ami_ccb *ccb; struct ami_iocmd *cmd; - ami_lock_t lock; void *idata; bus_dmamap_t idatamap; bus_dma_segment_t idataseg[1]; @@ -1591,8 +1691,6 @@ ami_ioctl_alarm(sc, ra) pa = idataseg[0].ds_addr; p = idata; - lock = AMI_LOCK_AMI(sc); - ccb = ami_get_ccb(sc); ccb->ccb_data = NULL; cmd = ccb->ccb_cmd; @@ -1627,7 +1725,6 @@ ami_ioctl_alarm(sc, ra) AMI_DPRINTF(AMI_D_IOCTL, ("%s: biocalarm invalid opcode %x\n", sc->sc_dev.dv_xname, ra->opcode)); ami_put_ccb(ccb); - AMI_UNLOCK_AMI(sc, lock); return EINVAL; } @@ -1647,8 +1744,6 @@ ami_ioctl_alarm(sc, ra) error = EINVAL; } - AMI_UNLOCK_AMI(sc, lock); - ami_freemem(sc->dmat, &idatamap, idataseg, NBPG, 1, "ioctl data"); return (error); @@ -1662,9 +1757,6 @@ ami_ioctl_startstop(sc, bs) int error = 0; struct ami_ccb *ccb; struct ami_iocmd *cmd; - ami_lock_t lock; - - lock = AMI_LOCK_AMI(sc); ccb = ami_get_ccb(sc); ccb->ccb_data = NULL; @@ -1695,8 +1787,6 @@ ami_ioctl_startstop(sc, bs) error = EINVAL; } - AMI_UNLOCK_AMI(sc, lock); - return (error); } @@ -1708,7 +1798,6 @@ ami_ioctl_status(sc, bs) int error = 0; struct ami_ccb *ccb; struct ami_iocmd *cmd; - ami_lock_t lock; void *idata; bus_dmamap_t idatamap; bus_dma_segment_t idataseg[1]; @@ -1725,8 +1814,6 @@ ami_ioctl_status(sc, bs) pa = idataseg[0].ds_addr; p = idata; - lock = AMI_LOCK_AMI(sc); - ccb = ami_get_ccb(sc); ccb->ccb_data = NULL; cmd = ccb->ccb_cmd; @@ -1746,8 +1833,6 @@ ami_ioctl_status(sc, bs) error = EINVAL; } - AMI_UNLOCK_AMI(sc, lock); - ami_freemem(sc->dmat, &idatamap, idataseg, NBPG, 1, "ioctl data"); return (error); @@ -1762,7 +1847,6 @@ ami_ioctl_passthru(sc, bp) struct ami_ccb *ccb; struct ami_iocmd *cmd; struct ami_passthrough *ps; - ami_lock_t lock; void *idata; bus_dmamap_t idatamap; bus_dma_segment_t idataseg[1]; @@ -1798,8 +1882,6 @@ ami_ioctl_passthru(sc, bp) pa = idataseg[0].ds_addr; ps = idata; - lock = AMI_LOCK_AMI(sc); - ccb = ami_get_ccb(sc); ccb->ccb_data = NULL; cmd = ccb->ccb_cmd; @@ -1861,16 +1943,13 @@ ami_ioctl_passthru(sc, bp) sc->sc_dev.dv_xname, bp->status, bp->senselen, sc->sc_dev.dv_xname)); - for (i = 0; i < bp->senselen; i++) { - bp->sensebuf[i] = ps->apt_sense[i]; + for (i = 0; i < bp->senselen; i++) printf("%0x ", bp->sensebuf[i]); - } + printf("\n"); #endif /* AMI_DEBUG */ } - AMI_UNLOCK_AMI(sc, lock); - ami_freemem(sc->dmat, &idatamap, idataseg, NBPG, 1, "ioctl data"); return (error); diff --git a/sys/dev/ic/amireg.h b/sys/dev/ic/amireg.h index 8ba8da442f9..75008649fbe 100644 --- a/sys/dev/ic/amireg.h +++ b/sys/dev/ic/amireg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: amireg.h,v 1.9 2005/05/24 19:56:53 marco Exp $ */ +/* $OpenBSD: amireg.h,v 1.10 2005/05/27 20:39:30 marco Exp $ */ /* * Copyright (c) 2000 Michael Shalayeff @@ -40,9 +40,10 @@ #define AMI_MAXCMDS 250 /* 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_SGEPERCMD 32 /* to prevent page boundary crossing */ +#define AMI_MAX_BUSYWAIT 10 /* wait up to 10 usecs */ +#define AMI_MAX_POLLWAIT 1000000 /* wait up to 1000 000 usecs */ + #define AMI_MAXFER (AMI_MAXOFFSETS * PAGE_SIZE) #define AMI_QIDB 0x20 diff --git a/sys/dev/ic/amivar.h b/sys/dev/ic/amivar.h index 2ffcfde6e60..77a5d86048f 100644 --- a/sys/dev/ic/amivar.h +++ b/sys/dev/ic/amivar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: amivar.h,v 1.9 2005/05/09 19:50:48 marco Exp $ */ +/* $OpenBSD: amivar.h,v 1.10 2005/05/27 20:39:30 marco Exp $ */ /* * Copyright (c) 2001 Michael Shalayeff @@ -60,13 +60,15 @@ struct ami_softc { struct scsi_link sc_link; /* don't use 0x0001 */ -#define AMI_BROKEN 0x0002 +#define AMI_BROKEN 0x0002 +#define AMI_CMDWAIT 0x0004 u_int sc_flags; /* low-level interface */ int (*sc_init)(struct ami_softc *sc); int (*sc_exec)(struct ami_softc *sc, struct ami_iocmd *); int (*sc_done)(struct ami_softc *sc, struct ami_iocmd *); + int (*sc_poll)(struct ami_softc *sc, struct ami_iocmd *); bus_space_tag_t iot; bus_space_handle_t ioh; @@ -88,6 +90,7 @@ struct ami_softc { int sc_timeout; struct timeout sc_requeue_tmo; struct timeout sc_poll_tmo; + int sc_dis_poll; char sc_fwver[16]; char sc_biosver[16]; @@ -120,10 +123,12 @@ int ami_intr(void *); int ami_quartz_init(struct ami_softc *sc); int ami_quartz_exec(struct ami_softc *sc, struct ami_iocmd *); int ami_quartz_done(struct ami_softc *sc, struct ami_iocmd *); +int ami_quartz_poll(struct ami_softc *sc, struct ami_iocmd *); 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 *); +int ami_schwartz_poll(struct ami_softc *sc, struct ami_iocmd *); #ifdef AMI_DEBUG void ami_print_mbox(struct ami_iocmd *); diff --git a/sys/dev/pci/ami_pci.c b/sys/dev/pci/ami_pci.c index da4dff9fe23..8ca590d9412 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.24 2005/05/09 19:50:48 marco Exp $ */ +/* $OpenBSD: ami_pci.c,v 1.25 2005/05/27 20:39:30 marco Exp $ */ /* * Copyright (c) 2001 Michael Shalayeff @@ -203,10 +203,12 @@ ami_pci_attach(parent, self, aux) sc->sc_init = ami_schwartz_init; sc->sc_exec = ami_schwartz_exec; sc->sc_done = ami_schwartz_done; + sc->sc_poll = ami_schwartz_poll; } else { sc->sc_init = ami_quartz_init; sc->sc_exec = ami_quartz_exec; sc->sc_done = ami_quartz_done; + sc->sc_poll = ami_quartz_poll; } sc->dmat = pa->pa_dmat; |