154879Storek /* 254879Storek * Copyright (c) 1992 The Regents of the University of California. 354879Storek * All rights reserved. 454879Storek * 554879Storek * This software was developed by the Computer Systems Engineering group 654879Storek * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 754879Storek * contributed to Berkeley. 854879Storek * 9*55559Storek * All advertising materials mentioning features or use of this software 10*55559Storek * must display the following acknowledgement: 11*55559Storek * This product includes software developed by the University of 12*55559Storek * California, Lawrence Berkeley Laboratories. 13*55559Storek * 1454879Storek * %sccs.include.redist.c% 1554879Storek * 16*55559Storek * @(#)scsi_subr.c 5.2 (Berkeley) 07/23/92 1754879Storek * 1854879Storek * from: $Header: scsi_subr.c,v 1.7 92/06/11 17:55:48 torek Exp $ (LBL) 1954879Storek */ 2054879Storek 2154879Storek /* 2254879Storek * Generic SCSI host adapter driver. 2354879Storek * Does almost nothing (most work is relegated to per-hba drivers). 2454879Storek */ 2554879Storek 26*55559Storek #include <sys/param.h> 27*55559Storek #include <sys/buf.h> 28*55559Storek #include <sys/device.h> 2954879Storek 30*55559Storek #include "scsi.h" 31*55559Storek #include "scsivar.h" 32*55559Storek 3354879Storek /* 3454879Storek * General subroutines, and scsi data. 3554879Storek */ 3654879Storek 3754879Storek /* table of lengths of scsi commands */ 3854879Storek const char scsicmdlen[8] = { 6, 10, 0, 0, 0, 12, 0, 0 }; 3954879Storek 4054879Storek /* table of lengths of scsi messages */ 4154879Storek const signed char scsimsglen[0x24] = { 4254879Storek SMLEN_DONE, /* MSG_CMD_COMPLETE */ 4354879Storek SMLEN_EXTENDED, /* MSG_EXT_MESSAGE */ 4454879Storek 1, /* MSG_SAVE_DATA_PTR */ 4554879Storek 1, /* MSG_RESTORE_PTR */ 4654879Storek 1, /* MSG_DISCONNECT */ 4754879Storek 1, /* MSG_INIT_DETECT_ERROR */ 4854879Storek 1, /* MSG_ABORT */ 4954879Storek 1, /* MSG_REJECT */ 5054879Storek 1, /* MSG_NOOP */ 5154879Storek 1, /* MSG_PARITY_ERROR */ 5254879Storek 1, /* MSG_LCC */ 5354879Storek 1, /* MSG_LCCF */ 5454879Storek 1, /* MSG_BUS_DEVICE_RESET */ 5554879Storek 1, /* MSG_ABORT_TAG */ 5654879Storek 1, /* MSG_CLEAR_QUEUE */ 5754879Storek 1, /* MSG_INITIATE_RECOVERY */ 5854879Storek 1, /* MSG_RELEASE_RECOVERY */ 5954879Storek 1, /* MSG_TERMINATE_PROCESS */ 6054879Storek SMLEN_UNDEF, /* 0x12 */ 6154879Storek SMLEN_UNDEF, /* 0x13 */ 6254879Storek SMLEN_UNDEF, /* 0x14 */ 6354879Storek SMLEN_UNDEF, /* 0x15 */ 6454879Storek SMLEN_UNDEF, /* 0x16 */ 6554879Storek SMLEN_UNDEF, /* 0x17 */ 6654879Storek SMLEN_UNDEF, /* 0x18 */ 6754879Storek SMLEN_UNDEF, /* 0x19 */ 6854879Storek SMLEN_UNDEF, /* 0x1a */ 6954879Storek SMLEN_UNDEF, /* 0x1b */ 7054879Storek SMLEN_UNDEF, /* 0x1c */ 7154879Storek SMLEN_UNDEF, /* 0x1d */ 7254879Storek SMLEN_UNDEF, /* 0x1e */ 7354879Storek SMLEN_UNDEF, /* 0x1f */ 7454879Storek 2, /* MSG_SIMPLE_QTAG */ 7554879Storek 2, /* MSG_HEAD_QTAG */ 7654879Storek 2, /* MSG_ORDERED_QTAG */ 7754879Storek 2, /* MSG_IGNORE_WIDE_RESID */ 7854879Storek }; 7954879Storek 8054879Storek /* definition of `tg' target driver for autoconfig */ 8154879Storek static int scsi_targmatch __P((struct device *, struct cfdata *, void *)); 8254879Storek static void scsi_targattach __P((struct device *, struct device *, void *)); 8354879Storek struct cfdriver tgcd = 8454879Storek { NULL, "tg", scsi_targmatch, scsi_targattach, 8554879Storek DV_DULL, sizeof(struct targ) }; 8654879Storek 8754879Storek void scsi_targstart __P((struct device *, struct sq *, struct buf *, 8854879Storek scdgo_fn, struct device *)); 8954879Storek int scsi_targgo __P((struct device *, int targ, 9054879Storek scintr_fn, struct device *, struct buf *, int)); 9154879Storek void scsi_targintr __P((struct device *, int, int)); 9254879Storek void scsi_targrel __P((struct device *)); 9354879Storek 9454879Storek #define NOBUF ((caddr_t)0) 9554879Storek 9654879Storek /* 9754879Storek * Perform a TEST UNIT READY immediate (polled) command 9854879Storek * on the given <target,unit> pair. Return the status byte 9954879Storek * returned, or -1 for none. 10054879Storek */ 10154879Storek int 10254879Storek scsi_test_unit_ready(hba, targ, unit) 10354879Storek struct hba_softc *hba; 10454879Storek int targ, unit; 10554879Storek { 10654879Storek struct scsi_cdb cdb; 10754879Storek 10854879Storek CDB6(&cdb)->cdb_cmd = CMD_TEST_UNIT_READY; 10954879Storek CDB6(&cdb)->cdb_lun_lbah = unit << 5; 11054879Storek *(short *)&CDB6(&cdb)->cdb_lbam = 0; 11154879Storek *(short *)&CDB6(&cdb)->cdb_len = 0; 11254879Storek return (hba->hba_driver->hd_icmd(hba, targ, &cdb, NOBUF, 0, 0)); 11354879Storek } 11454879Storek 11554879Storek /* 11654879Storek * Request sense. The sense is to be written into the given buffer. 11754879Storek * The given length must be < 256. 11854879Storek */ 11954879Storek int 12054879Storek scsi_request_sense(hba, targ, unit, buf, len) 12154879Storek struct hba_softc *hba; 12254879Storek int targ, unit; 12354879Storek caddr_t buf; 12454879Storek int len; 12554879Storek { 12654879Storek struct scsi_cdb cdb; 12754879Storek 12854879Storek CDB6(&cdb)->cdb_cmd = CMD_REQUEST_SENSE; 12954879Storek CDB6(&cdb)->cdb_lun_lbah = unit << 5; 13054879Storek *(short *)&CDB6(&cdb)->cdb_lbam = 0; 13154879Storek CDB6(&cdb)->cdb_len = len; 13254879Storek CDB6(&cdb)->cdb_ctrl = 0; 13354879Storek return (hba->hba_driver->hd_icmd(hba, targ, &cdb, buf, len, B_READ)); 13454879Storek } 13554879Storek 13654879Storek /* 13754879Storek * Called (indirectly, via config_found) from scsi_hbaattach. 13854879Storek * Print target number, and if no device was configured there, 13954879Storek * the hba as well. 14054879Storek */ 14154879Storek int 14254879Storek scsi_targprint(aux, hba) 14354879Storek void *aux; 14454879Storek char *hba; 14554879Storek { 14654879Storek 14754879Storek if (hba) { 14854879Storek printf("target %d on %s", *(int *)aux, hba); 14954879Storek return (UNCONF); 15054879Storek } 15154879Storek printf(" target %d", *(int *)aux); 15254879Storek return (QUIET); 15354879Storek } 15454879Storek 15554879Storek /* 15654879Storek * Print information about a unit found on some target. 15754879Storek * If the unit was not configured, `targ' is the name of the target 15854879Storek * on which the unit was found. If it was, targ is NULL and we 15954879Storek * let the unit's attach routine print the INQUIRE result if 16054879Storek * appropriate. 16154879Storek */ 16254879Storek static int 16354879Storek scsi_unitprint(aux, targ) 16454879Storek void *aux; 16554879Storek char *targ; 16654879Storek { 16754879Storek register struct scsi_attach_args *sa = aux; 16854879Storek 16954879Storek if (targ) { 17054879Storek printf("unit %d at %s", sa->sa_unit, targ); 17154879Storek if ((sa->sa_inq_status & STS_MASK) == STS_GOOD) { 17254879Storek printf(" ("); 17354879Storek scsi_printinq(&sa->sa_si); 17454879Storek printf(")"); 17554879Storek } 17654879Storek return (UNCONF); 17754879Storek } 17854879Storek printf(" unit %d", sa->sa_unit); 17954879Storek return (QUIET); 18054879Storek } 18154879Storek 18254879Storek /* 18354879Storek * Generic target-match. 18454879Storek */ 18554879Storek static int 18654879Storek scsi_targmatch(parent, cf, aux) 18754879Storek struct device *parent; 18854879Storek register struct cfdata *cf; 18954879Storek void *aux; 19054879Storek { 19154879Storek int targ = *(int *)aux; 19254879Storek 19354879Storek return (cf->cf_loc[0] == targ || cf->cf_loc[0] == -1); 19454879Storek } 19554879Storek 19654879Storek /* 19754879Storek * And now, a generic `target attach' routine. 19854879Storek * We assume that INQUIRY works. 19954879Storek */ 20054879Storek static void 20154879Storek scsi_targattach(parent, self, aux) 20254879Storek struct device *parent, *self; 20354879Storek void *aux; 20454879Storek { 20554879Storek register struct targ *t = (struct targ *)self; 20654879Storek register struct hba_softc *hba; 20754879Storek register struct hbadriver *hd; 20854879Storek register int targ, unit; 20954879Storek struct scsi_attach_args sa; 21054879Storek struct scsi_cdb si; 21154879Storek 21254879Storek printf("\n"); 21354879Storek t->t_targ = targ = *(int *)aux; 21454879Storek hba = (struct hba_softc *)parent; 21554879Storek hba->hba_targets[targ] = t; 21654879Storek 21754879Storek /* 21854879Storek * Probe each of the 8 units using the sequence 21954879Storek * TEST UNIT READY 22054879Storek * REQUEST SENSE 22154879Storek * INQUIRY 22254879Storek * The first should not be necessary, but some SCSI devices 22354879Storek * refuse to speak until it is done. The second is only necessary 22454879Storek * if the first returns a CHECK CONDITION status, but we do it 22554879Storek * anyway. 22654879Storek */ 22754879Storek hd = hba->hba_driver; 22854879Storek sa.sa_targ = targ; 22954879Storek CDB6(&si)->cdb_cmd = CMD_INQUIRY; 23054879Storek *(short *)&CDB6(&si)->cdb_lbam = 0; 23154879Storek CDB6(&si)->cdb_len = sizeof sa.sa_si; 23254879Storek CDB6(&si)->cdb_ctrl = 0; 23354879Storek for (unit = 0; unit < 8; unit++) { 23454879Storek if (scsi_test_unit_ready(hba, targ, unit) == -1) 23554879Storek continue; 23654879Storek sa.sa_unit = unit; 23754879Storek sa.sa_req_status = scsi_request_sense(hba, targ, unit, 23854879Storek (caddr_t)&sa.sa_sn, sizeof sa.sa_sn); 23954879Storek CDB6(&si)->cdb_lun_lbah = unit << 5; 24054879Storek sa.sa_inq_status = (*hd->hd_icmd)(hba, targ, &si, 24154879Storek (caddr_t)&sa.sa_si, sizeof sa.sa_si, B_READ); 24254879Storek if ((sa.sa_inq_status & STS_MASK) == STS_GOOD && 24354879Storek #ifdef notdef /* XXX don't know if this is a reasonable test */ 24454879Storek (sa.sa_si.si_type & TYPE_QUAL_MASK) == TYPE_QUAL_NOTCONN && 24554879Storek #endif 24654879Storek (sa.sa_si.si_type & TYPE_TYPE_MASK) == TYPE_NP) { 24754879Storek continue; 24854879Storek } 24954879Storek config_found(&t->t_dev, (void *)&sa, scsi_unitprint); 25054879Storek } 25154879Storek } 25254879Storek 25354879Storek /* 25454879Storek * Each unit calls scsi_establish to tell the hba and target of 25554879Storek * its existence. 25654879Storek */ 25754879Storek void 25854879Storek scsi_establish(u, dev, unit) 25954879Storek register struct unit *u; 26054879Storek struct device *dev; 26154879Storek register int unit; 26254879Storek { 26354879Storek register struct targ *t; 26454879Storek register struct hba_softc *hba; 26554879Storek register struct hbadriver *hbd; 26654879Storek 26754879Storek u->u_dev = dev; 26854879Storek t = (struct targ *)dev->dv_parent; 26954879Storek hba = (struct hba_softc *)t->t_dev.dv_parent; 27054879Storek hbd = hba->hba_driver; 27154879Storek t->t_units[unit] = u; 27254879Storek if (t->t_nunits == 0) { 27354879Storek /* 27454879Storek * This is the first unit on the target. We can 27554879Storek * probably just call the hba start code, avoiding 27654879Storek * one level of calls and queueing. If we attach 27754879Storek * another target we will fix this in the code below. 27854879Storek */ 27954879Storek u->u_start = hbd->hd_start; 28054879Storek u->u_go = hbd->hd_go; 28154879Storek u->u_rel = hbd->hd_rel; 28254879Storek u->u_updev = &hba->hba_dev; 28354879Storek t->t_firstunit = unit; 28454879Storek } else { 28554879Storek /* 28654879Storek * This is not the only unit on the target, so we 28754879Storek * must call the target start code rather than the 28854879Storek * hba start code. Fix the linkage on the first 28954879Storek * target too (possibly for the 2nd, 3rd, ..., time). 29054879Storek */ 29154879Storek t->t_units[t->t_firstunit]->u_start = scsi_targstart; 29254879Storek t->t_units[t->t_firstunit]->u_updev = &t->t_dev; 29354879Storek u->u_start = scsi_targstart; 29454879Storek u->u_go = scsi_targgo; 29554879Storek u->u_rel = scsi_targrel; 29654879Storek u->u_updev = &t->t_dev; 29754879Storek } 29854879Storek t->t_nunits++; /* another unit is alive */ 29954879Storek u->u_unit = unit; 30054879Storek u->u_targ = t->t_targ; /* record target number, */ 30154879Storek u->u_hba = hba; /* hba ... */ 30254879Storek u->u_hbd = hbd; /* and driver */ 30354879Storek } 30454879Storek 30554879Storek /* NO DOUBT SOME OF THE STUFF PRINTED HERE IS USELESS */ 30654879Storek void 30754879Storek scsi_printinq(inq) 30854879Storek register struct scsi_inquiry *inq; 30954879Storek { 31054879Storek register int iso, ecma, ansi, t; 31154879Storek static char *types[] = { "disk", "tape", "printer", "processor", 31254879Storek "WORM", "ROM disk", "scanner", "magneto-optical", 31354879Storek "jukebox", "lan" }; 31454879Storek 31554879Storek if ((t = (inq->si_type & TYPE_QUAL_MASK)) != 0) 31654879Storek printf("type-qual=0x%x ", t); 31754879Storek t = inq->si_type & TYPE_TYPE_MASK; 31854879Storek if (t < sizeof types / sizeof *types) 31954879Storek printf("%s", types[t]); 32054879Storek else 32154879Storek printf("<type %d>", t); 32254879Storek if (inq->si_qual & QUAL_RMB) 32354879Storek printf(" (removable)"); 32454879Storek printf(" qual=0x%x", inq->si_qual & QUAL_MASK); 32554879Storek iso = (inq->si_qual >> VER_ISO_SHIFT) & VER_ISO_MASK; 32654879Storek ecma = (inq->si_qual >> VER_ECMA_SHIFT) & VER_ECMA_MASK; 32754879Storek ansi = (inq->si_qual >> VER_ANSI_SHIFT) & VER_ANSI_MASK; 32854879Storek printf(" version=<iso %d, ecma %d, ansi %d>", iso, ecma, ansi); 32954879Storek if (ansi == 1 || ansi == 2) { 33054879Storek char v[9], p[17], r[5]; 33154879Storek 33254879Storek scsi_inq_ansi((struct scsi_inq_ansi *)inq, v, p, r); 33354879Storek printf(" vendor %s, product %s, rev %s", v, p, r); 33454879Storek } 33554879Storek } 33654879Storek 33754879Storek /* copy a counted string but trim trailing blanks; make the dest a C string */ 33854879Storek static void 33954879Storek scsi_str(src, dst, len) 34054879Storek register char *src, *dst; 34154879Storek register int len; 34254879Storek { 34354879Storek 34454879Storek while (src[len - 1] == ' ') { 34554879Storek if (--len == 0) { 34654879Storek *dst = 0; 34754879Storek return; 34854879Storek } 34954879Storek } 35054879Storek bcopy(src, dst, len); 35154879Storek dst[len] = 0; 35254879Storek } 35354879Storek 35454879Storek void 35554879Storek scsi_inq_ansi(si, vendor, product, rev) 35654879Storek register struct scsi_inq_ansi *si; 35754879Storek char *vendor, *product, *rev; 35854879Storek { 35954879Storek register int i, len; 36054879Storek 36154879Storek /* if too short, extend with blanks */ 36254879Storek len = si->si_len + 5; /* 5 fixed; len is `additional' */ 36354879Storek if (len < sizeof(*si)) 36454879Storek for (i = len; i < sizeof *si; i++) 36554879Storek ((char *)si)[i] = ' '; 36654879Storek scsi_str(si->si_vendor, vendor, sizeof si->si_vendor); 36754879Storek scsi_str(si->si_product, product, sizeof si->si_product); 36854879Storek scsi_str(si->si_rev, rev, sizeof si->si_rev); 36954879Storek } 37054879Storek 37154879Storek /* 37254879Storek * Tell all the devices on the given hba that it has been reset. 37354879Storek * SHOULD PROBABLY DO MORE HERE 37454879Storek */ 37554879Storek void 37654879Storek scsi_reset_units(hba) 37754879Storek register struct hba_softc *hba; 37854879Storek { 37954879Storek register int targ, unit; 38054879Storek register struct targ *t; 38154879Storek register struct unit *u; 38254879Storek 38354879Storek for (targ = 0; targ < 8; targ++) { 38454879Storek if ((t = hba->hba_targets[targ]) == NULL) 38554879Storek continue; 38654879Storek for (unit = 0; unit < 8; unit++) 38754879Storek if ((u = t->t_units[unit]) != NULL) 38854879Storek (*u->u_driver->ud_reset)(u); 38954879Storek } 39054879Storek } 39154879Storek 39254879Storek /* 39354879Storek * Start a unit on a target. 39454879Storek * If the target is busy, just enqueue the unit; 39554879Storek * once the target becomes free, we will call the hba start routine. 39654879Storek * Otherwise, call the hba start routine now, and then when the hba 39754879Storek * becomes free it will call the unit's dgo routine. 39854879Storek */ 39954879Storek void 40054879Storek scsi_targstart(self, sq, bp, dgo, dev) 40154879Storek struct device *self; 40254879Storek register struct sq *sq; 40354879Storek struct buf *bp; 40454879Storek scdgo_fn dgo; 40554879Storek struct device *dev; 40654879Storek { 40754879Storek register struct targ *t = (struct targ *)self; 40854879Storek register struct hba_softc *hba; 40954879Storek 41054879Storek sq->sq_forw = NULL; 41154879Storek if (t->t_head == NULL) 41254879Storek t->t_head = sq; 41354879Storek else 41454879Storek t->t_tail->sq_forw = sq; 41554879Storek t->t_tail = sq; 41654879Storek if (t->t_busy == 0) { 41754879Storek t->t_busy = 1; 41854879Storek hba = (struct hba_softc *)t->t_dev.dv_parent; 41954879Storek (*hba->hba_driver->hd_start)(&hba->hba_dev, &t->t_forw, bp, 42054879Storek dgo, dev); 42154879Storek } else { 42254879Storek sq->sq_bp = bp; 42354879Storek sq->sq_dgo = dgo; 42454879Storek sq->sq_dev = dev; 42554879Storek } 42654879Storek } 42754879Storek 42854879Storek /* 42954879Storek * The unit got the bus, and wants the hba to go. 43054879Storek * Remember its interrupt handler; substitute ours instead. 43154879Storek */ 43254879Storek int 43354879Storek scsi_targgo(self, targ, intr, dev, bp, pad) 43454879Storek struct device *self; 43554879Storek int targ; 43654879Storek scintr_fn intr; 43754879Storek struct device *dev; 43854879Storek struct buf *bp; 43954879Storek int pad; 44054879Storek { 44154879Storek register struct targ *t = (struct targ *)self; 44254879Storek register struct hba_softc *hba; 44354879Storek 44454879Storek t->t_intr = intr; 44554879Storek t->t_intrdev = dev; 44654879Storek hba = (struct hba_softc *)t->t_dev.dv_parent; 44754879Storek return ((*hba->hba_driver->hd_go)(&hba->hba_dev, targ, 44854879Storek scsi_targintr, &t->t_dev, bp, pad)); 44954879Storek } 45054879Storek 45154879Storek /* 45254879Storek * The hba got an interrupt. Dequeue the unit from the target 45354879Storek * (the target is already off the hba queue) and then call the 45454879Storek * underlying interrupt handler. 45554879Storek */ 45654879Storek void 45754879Storek scsi_targintr(self, stat, resid) 45854879Storek struct device *self; 45954879Storek int stat, resid; 46054879Storek { 46154879Storek register struct targ *t = (struct targ *)self; 46254879Storek register struct hba_softc *hba; 46354879Storek register struct sq *sq; 46454879Storek 46554879Storek sq = t->t_head; 46654879Storek if (sq == NULL) panic("scsi_targintr"); 46754879Storek t->t_head = sq = sq->sq_forw; 46854879Storek (*t->t_intr)(t->t_intrdev, stat, resid); 46954879Storek if (sq != NULL) { 47054879Storek hba = (struct hba_softc *)t->t_dev.dv_parent; 47154879Storek (*hba->hba_driver->hd_start)(&hba->hba_dev, &t->t_forw, 47254879Storek sq->sq_bp, sq->sq_dgo, sq->sq_dev); 47354879Storek } else 47454879Storek t->t_busy = 0; 47554879Storek } 47654879Storek 47754879Storek /* 47854879Storek * The unit decided that it needed to `give up' its hold on the bus early. 47954879Storek */ 48054879Storek void 48154879Storek scsi_targrel(self) 48254879Storek struct device *self; 48354879Storek { 48454879Storek register struct targ *t = (struct targ *)self; 48554879Storek register struct hba_softc *hba; 48654879Storek register struct sq *sq; 48754879Storek 48854879Storek hba = (struct hba_softc *)t->t_dev.dv_parent; 48954879Storek sq = t->t_head; 49054879Storek if (sq == NULL) panic("scsi_targrel"); 49154879Storek /* 49254879Storek * This target is at the head of the hba queue. 49354879Storek * Remove it by calling hba bus release. Then, if the 49454879Storek * target queue is not empty, put it back on the hba queue. 49554879Storek * (This produces round robin service.) 49654879Storek */ 49754879Storek (*hba->hba_driver->hd_rel)(&hba->hba_dev); 49854879Storek sq = sq->sq_forw; 49954879Storek if ((t->t_head = sq) != NULL) 50054879Storek (*hba->hba_driver->hd_start)(&hba->hba_dev, &t->t_forw, 50154879Storek sq->sq_bp, sq->sq_dgo, sq->sq_dev); 50254879Storek else 50354879Storek t->t_busy = 0; 50454879Storek } 505