diff options
-rw-r--r-- | sys/dev/ic/siop.c | 115 |
1 files changed, 61 insertions, 54 deletions
diff --git a/sys/dev/ic/siop.c b/sys/dev/ic/siop.c index a2016049846..4801a549890 100644 --- a/sys/dev/ic/siop.c +++ b/sys/dev/ic/siop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: siop.c,v 1.61 2010/07/02 15:10:48 blambert Exp $ */ +/* $OpenBSD: siop.c,v 1.62 2010/07/06 23:32:01 dlg Exp $ */ /* $NetBSD: siop.c,v 1.79 2005/11/18 23:10:32 bouyer Exp $ */ /* @@ -92,6 +92,8 @@ void siop_timeout(void *); void siop_scsicmd(struct scsi_xfer *); void * siop_cmd_get(void *); void siop_cmd_put(void *, void *); +int siop_scsiprobe(struct scsi_link *); +void siop_scsifree(struct scsi_link *); #ifdef DUMP_SCRIPT void siop_dump_script(struct siop_softc *); #endif @@ -107,8 +109,8 @@ struct cfdriver siop_cd = { struct scsi_adapter siop_adapter = { siop_scsicmd, siop_minphys, - NULL, - NULL, + siop_scsiprobe, + siop_scsifree }; #ifdef SIOP_STATS @@ -358,7 +360,6 @@ siop_intr(v) int offset, target, lun, tag; bus_addr_t dsa; struct siop_cbd *cbdp; - int freetarget = 0; int restart = 0; istat = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_ISTAT); @@ -579,7 +580,6 @@ siop_intr(v) if (siop_cmd) { siop_cmd->cmd_c.status = CMDST_DONE; xs->error = XS_SELTIMEOUT; - freetarget = 1; goto end; } else { printf("%s: selection timeout without " @@ -1073,8 +1073,6 @@ end: restart = 1; siop_lun->siop_tag[tag].active = NULL; siop_scsicmd_end(siop_cmd); - if (freetarget && siop_target->target_c.status == TARST_PROBING) - siop_del_dev(sc, target, lun); siop_start(sc); if (restart) CALL_SCRIPT(Ent_script_sched); @@ -1386,41 +1384,32 @@ siop_cmd_put(void *cookie, void *io) splx(s); } -void -siop_scsicmd(xs) - struct scsi_xfer *xs; +int +siop_scsiprobe(struct scsi_link *link) { - struct siop_softc *sc = (struct siop_softc *)xs->sc_link->adapter_softc; - struct siop_cmd *siop_cmd; + struct siop_softc *sc = (struct siop_softc *)link->adapter_softc; struct siop_target *siop_target; - int s, error, i, j; - const int target = xs->sc_link->target; - const int lun = xs->sc_link->lun; + const int target = link->target; + const int lun = link->lun; + int i; - s = splbio(); -#ifdef SIOP_DEBUG_SCHED - printf("starting cmd for %d:%d\n", target, lun); +#ifdef SIOP_DEBUG + printf("%s:%d:%d: probe\n", + sc->sc_c.sc_dev.dv_xname, target, lun); #endif + + /* XXX locking */ + siop_target = (struct siop_target*)sc->sc_c.targets[target]; if (siop_target == NULL) { -#ifdef SIOP_DEBUG - printf("%s: alloc siop_target for target %d\n", - sc->sc_c.sc_dev.dv_xname, target); -#endif - sc->sc_c.targets[target] = - malloc(sizeof(struct siop_target), M_DEVBUF, - M_NOWAIT | M_ZERO); - if (sc->sc_c.targets[target] == NULL) { - printf("%s: can't malloc memory for " - "target %d\n", sc->sc_c.sc_dev.dv_xname, - target); - xs->error = XS_NO_CCB; - scsi_done(xs); - splx(s); - return; + siop_target = malloc(sizeof(*siop_target), M_DEVBUF, + M_WAITOK | M_CANFAIL | M_ZERO); + if (siop_target == NULL) { + printf("%s: can't malloc memory for target %d\n", + sc->sc_c.sc_dev.dv_xname, target); + return (ENOMEM); } - siop_target = - (struct siop_target*)sc->sc_c.targets[target]; + siop_target->target_c.status = TARST_PROBING; siop_target->target_c.flags = 0; siop_target->target_c.id = @@ -1433,30 +1422,49 @@ siop_scsicmd(xs) if (siop_target->lunsw == NULL) { printf("%s: can't alloc lunsw for target %d\n", sc->sc_c.sc_dev.dv_xname, target); - xs->error = XS_NO_CCB; - scsi_done(xs); - splx(s); - return; + free(siop_target, M_DEVBUF); + return (ENOMEM); } - for (i=0; i < 8; i++) + for (i = 0; i < 8; i++) siop_target->siop_lun[i] = NULL; + + sc->sc_c.targets[target] = + (struct siop_common_target *)siop_target; + siop_add_reselsw(sc, target); } + if (siop_target->siop_lun[lun] == NULL) { siop_target->siop_lun[lun] = malloc(sizeof(struct siop_lun), M_DEVBUF, - M_NOWAIT | M_ZERO); + M_WAITOK | M_CANFAIL | M_ZERO); if (siop_target->siop_lun[lun] == NULL) { printf("%s: can't alloc siop_lun for " "target %d lun %d\n", sc->sc_c.sc_dev.dv_xname, target, lun); - xs->error = XS_NO_CCB; - scsi_done(xs); - splx(s); - return; + return (ENOMEM); } } + return (0); +} + +void +siop_scsicmd(xs) + struct scsi_xfer *xs; +{ + struct siop_softc *sc = (struct siop_softc *)xs->sc_link->adapter_softc; + struct siop_cmd *siop_cmd; + struct siop_target *siop_target; + int s, error, i, j; + const int target = xs->sc_link->target; + const int lun = xs->sc_link->lun; + +#ifdef SIOP_DEBUG_SCHED + printf("starting cmd for %d:%d\n", target, lun); +#endif + + siop_target = (struct siop_target*)sc->sc_c.targets[target]; siop_cmd = xs->io; /* @@ -1490,7 +1498,6 @@ siop_scsicmd(xs) sc->sc_c.sc_dev.dv_xname, error); xs->error = XS_DRIVER_STUFFUP; scsi_done(xs); - splx(s); return; } bus_dmamap_sync(sc->sc_c.sc_dmat, @@ -1505,13 +1512,13 @@ siop_scsicmd(xs) siop_table_sync(siop_cmd, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - TAILQ_INSERT_TAIL(&sc->ready_list, siop_cmd, next); - /* Negotiate transfer parameters on first non-polling command. */ if (((xs->flags & SCSI_POLL) == 0) && siop_target->target_c.status == TARST_PROBING) siop_target->target_c.status = TARST_ASYNC; + s = splbio(); + TAILQ_INSERT_TAIL(&sc->ready_list, siop_cmd, next); siop_start(sc); if ((xs->flags & SCSI_POLL) == 0) { splx(s); @@ -2174,19 +2181,19 @@ siop_add_dev(sc, target, lun) } void -siop_del_dev(sc, target, lun) - struct siop_softc *sc; - int target; - int lun; +siop_scsifree(struct scsi_link *link) { + struct siop_softc *sc = link->adapter_softc; + int target = link->target; + int lun = link->lun; int i; struct siop_target *siop_target; + #ifdef SIOP_DEBUG printf("%s:%d:%d: free lun sw entry\n", sc->sc_c.sc_dev.dv_xname, target, lun); #endif - if (sc->sc_c.targets[target] == NULL) - return; + siop_target = (struct siop_target *)sc->sc_c.targets[target]; free(siop_target->siop_lun[lun], M_DEVBUF); siop_target->siop_lun[lun] = NULL; |