summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/ic/siop.c115
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;