1 /* 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This software was developed by the Computer Systems Engineering group 6 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 7 * contributed to Berkeley. 8 * 9 * All advertising materials mentioning features or use of this software 10 * must display the following acknowledgement: 11 * This product includes software developed by the University of 12 * California, Lawrence Berkeley Laboratories. 13 * 14 * %sccs.include.redist.c% 15 * 16 * @(#)scsi_subr.c 8.1 (Berkeley) 06/16/93 17 * 18 * from: $Header: scsi_subr.c,v 1.10 93/02/01 19:21:58 torek Exp $ (LBL) 19 */ 20 21 /* 22 * Generic SCSI host adapter driver. 23 * Does almost nothing (most work is relegated to per-hba drivers). 24 */ 25 26 #include <sys/param.h> 27 #include <sys/buf.h> 28 #include <sys/device.h> 29 30 #include <dev/scsi/scsi.h> 31 #include <dev/scsi/scsivar.h> 32 33 /* 34 * General subroutines, and scsi data. 35 */ 36 37 /* table of lengths of scsi commands */ 38 const char scsicmdlen[8] = { 6, 10, 0, 0, 0, 12, 0, 0 }; 39 40 /* table of lengths of scsi messages */ 41 const signed char scsimsglen[0x24] = { 42 SMLEN_DONE, /* MSG_CMD_COMPLETE */ 43 SMLEN_EXTENDED, /* MSG_EXT_MESSAGE */ 44 1, /* MSG_SAVE_DATA_PTR */ 45 1, /* MSG_RESTORE_PTR */ 46 1, /* MSG_DISCONNECT */ 47 1, /* MSG_INIT_DETECT_ERROR */ 48 1, /* MSG_ABORT */ 49 1, /* MSG_REJECT */ 50 1, /* MSG_NOOP */ 51 1, /* MSG_PARITY_ERROR */ 52 1, /* MSG_LCC */ 53 1, /* MSG_LCCF */ 54 1, /* MSG_BUS_DEVICE_RESET */ 55 1, /* MSG_ABORT_TAG */ 56 1, /* MSG_CLEAR_QUEUE */ 57 1, /* MSG_INITIATE_RECOVERY */ 58 1, /* MSG_RELEASE_RECOVERY */ 59 1, /* MSG_TERMINATE_PROCESS */ 60 SMLEN_UNDEF, /* 0x12 */ 61 SMLEN_UNDEF, /* 0x13 */ 62 SMLEN_UNDEF, /* 0x14 */ 63 SMLEN_UNDEF, /* 0x15 */ 64 SMLEN_UNDEF, /* 0x16 */ 65 SMLEN_UNDEF, /* 0x17 */ 66 SMLEN_UNDEF, /* 0x18 */ 67 SMLEN_UNDEF, /* 0x19 */ 68 SMLEN_UNDEF, /* 0x1a */ 69 SMLEN_UNDEF, /* 0x1b */ 70 SMLEN_UNDEF, /* 0x1c */ 71 SMLEN_UNDEF, /* 0x1d */ 72 SMLEN_UNDEF, /* 0x1e */ 73 SMLEN_UNDEF, /* 0x1f */ 74 2, /* MSG_SIMPLE_QTAG */ 75 2, /* MSG_HEAD_QTAG */ 76 2, /* MSG_ORDERED_QTAG */ 77 2, /* MSG_IGNORE_WIDE_RESID */ 78 }; 79 80 /* definition of `tg' target driver for autoconfig */ 81 static int scsi_targmatch __P((struct device *, struct cfdata *, void *)); 82 static void scsi_targattach __P((struct device *, struct device *, void *)); 83 struct cfdriver tgcd = 84 { NULL, "tg", scsi_targmatch, scsi_targattach, 85 DV_DULL, sizeof(struct targ) }; 86 87 void scsi_targstart __P((struct device *, struct sq *, struct buf *, 88 scdgo_fn, struct device *)); 89 int scsi_targgo __P((struct device *, int targ, 90 scintr_fn, struct device *, struct buf *, int)); 91 void scsi_targintr __P((struct device *, int, int)); 92 void scsi_targrel __P((struct device *)); 93 94 #define NOBUF ((caddr_t)0) 95 96 /* 97 * Perform a TEST UNIT READY immediate (polled) command 98 * on the given <target,unit> pair. Return the status byte 99 * returned, or -1 for none. 100 */ 101 int 102 scsi_test_unit_ready(hba, targ, unit) 103 struct hba_softc *hba; 104 int targ, unit; 105 { 106 struct scsi_cdb cdb; 107 108 CDB6(&cdb)->cdb_cmd = CMD_TEST_UNIT_READY; 109 CDB6(&cdb)->cdb_lun_lbah = unit << 5; 110 *(short *)&CDB6(&cdb)->cdb_lbam = 0; 111 *(short *)&CDB6(&cdb)->cdb_len = 0; 112 return (hba->hba_driver->hd_icmd(hba, targ, &cdb, NOBUF, 0, 0)); 113 } 114 115 /* 116 * Request sense. The sense is to be written into the given buffer. 117 * The given length must be < 256. 118 */ 119 int 120 scsi_request_sense(hba, targ, unit, buf, len) 121 struct hba_softc *hba; 122 int targ, unit; 123 caddr_t buf; 124 int len; 125 { 126 struct scsi_cdb cdb; 127 128 CDB6(&cdb)->cdb_cmd = CMD_REQUEST_SENSE; 129 CDB6(&cdb)->cdb_lun_lbah = unit << 5; 130 *(short *)&CDB6(&cdb)->cdb_lbam = 0; 131 CDB6(&cdb)->cdb_len = len; 132 CDB6(&cdb)->cdb_ctrl = 0; 133 return (hba->hba_driver->hd_icmd(hba, targ, &cdb, buf, len, B_READ)); 134 } 135 136 /* 137 * Called (indirectly, via config_found) from scsi_hbaattach. 138 * Print target number, and if no device was configured there, 139 * the hba as well. 140 */ 141 int 142 scsi_targprint(aux, hba) 143 void *aux; 144 char *hba; 145 { 146 147 if (hba) { 148 printf("target %d on %s", *(int *)aux, hba); 149 return (UNCONF); 150 } 151 printf(" target %d", *(int *)aux); 152 return (QUIET); 153 } 154 155 /* 156 * Print information about a unit found on some target. 157 * If the unit was not configured, `targ' is the name of the target 158 * on which the unit was found. If it was, targ is NULL and we 159 * let the unit's attach routine print the INQUIRE result if 160 * appropriate. 161 */ 162 static int 163 scsi_unitprint(aux, targ) 164 void *aux; 165 char *targ; 166 { 167 register struct scsi_attach_args *sa = aux; 168 169 if (targ) { 170 printf("unit %d at %s", sa->sa_unit, targ); 171 if ((sa->sa_inq_status & STS_MASK) == STS_GOOD) { 172 printf(" ("); 173 scsi_printinq(&sa->sa_si); 174 printf(")"); 175 } 176 return (UNCONF); 177 } 178 printf(" unit %d", sa->sa_unit); 179 return (QUIET); 180 } 181 182 /* 183 * Generic target-match. 184 */ 185 static int 186 scsi_targmatch(parent, cf, aux) 187 struct device *parent; 188 register struct cfdata *cf; 189 void *aux; 190 { 191 int targ = *(int *)aux; 192 193 return (cf->cf_loc[0] == targ || cf->cf_loc[0] == -1); 194 } 195 196 /* 197 * And now, a generic `target attach' routine. 198 * We assume that INQUIRY works. 199 */ 200 static void 201 scsi_targattach(parent, self, aux) 202 struct device *parent, *self; 203 void *aux; 204 { 205 register struct targ *t = (struct targ *)self; 206 register struct hba_softc *hba; 207 register struct hbadriver *hd; 208 register int targ, unit; 209 struct scsi_attach_args sa; 210 struct scsi_cdb si; 211 212 printf("\n"); 213 t->t_targ = targ = *(int *)aux; 214 hba = (struct hba_softc *)parent; 215 hba->hba_targets[targ] = t; 216 217 /* 218 * Probe each of the 8 units using the sequence 219 * TEST UNIT READY 220 * REQUEST SENSE 221 * INQUIRY 222 * The first should not be necessary, but some SCSI devices 223 * refuse to speak until it is done. The second is only necessary 224 * if the first returns a CHECK CONDITION status, but we do it 225 * anyway. 226 */ 227 hd = hba->hba_driver; 228 sa.sa_targ = targ; 229 CDB6(&si)->cdb_cmd = CMD_INQUIRY; 230 *(short *)&CDB6(&si)->cdb_lbam = 0; 231 CDB6(&si)->cdb_len = sizeof sa.sa_si; 232 CDB6(&si)->cdb_ctrl = 0; 233 for (unit = 0; unit < 8; unit++) { 234 if (scsi_test_unit_ready(hba, targ, unit) == -1) 235 continue; 236 sa.sa_unit = unit; 237 sa.sa_req_status = scsi_request_sense(hba, targ, unit, 238 (caddr_t)&sa.sa_sn, sizeof sa.sa_sn); 239 CDB6(&si)->cdb_lun_lbah = unit << 5; 240 sa.sa_inq_status = (*hd->hd_icmd)(hba, targ, &si, 241 (caddr_t)&sa.sa_si, sizeof sa.sa_si, B_READ); 242 if ((sa.sa_inq_status & STS_MASK) == STS_GOOD && 243 #ifdef notdef /* XXX don't know if this is a reasonable test */ 244 (sa.sa_si.si_type & TYPE_QUAL_MASK) == TYPE_QUAL_NOTCONN && 245 #endif 246 (sa.sa_si.si_type & TYPE_TYPE_MASK) == TYPE_NP) { 247 continue; 248 } 249 config_found(&t->t_dev, (void *)&sa, scsi_unitprint); 250 } 251 } 252 253 /* 254 * Each unit calls scsi_establish to tell the hba and target of 255 * its existence. 256 */ 257 void 258 scsi_establish(u, dev, unit) 259 register struct unit *u; 260 struct device *dev; 261 register int unit; 262 { 263 register struct targ *t; 264 register struct hba_softc *hba; 265 register struct hbadriver *hbd; 266 267 u->u_dev = dev; 268 t = (struct targ *)dev->dv_parent; 269 hba = (struct hba_softc *)t->t_dev.dv_parent; 270 hbd = hba->hba_driver; 271 t->t_units[unit] = u; 272 if (t->t_nunits == 0) { 273 /* 274 * This is the first unit on the target. We can 275 * probably just call the hba start code, avoiding 276 * one level of calls and queueing. If we attach 277 * another target we will fix this in the code below. 278 */ 279 u->u_start = hbd->hd_start; 280 u->u_go = hbd->hd_go; 281 u->u_rel = hbd->hd_rel; 282 u->u_updev = &hba->hba_dev; 283 t->t_firstunit = unit; 284 } else { 285 /* 286 * This is not the only unit on the target, so we 287 * must call the target start code rather than the 288 * hba start code. Fix the linkage on the first 289 * target too (possibly for the 2nd, 3rd, ..., time). 290 */ 291 t->t_units[t->t_firstunit]->u_start = scsi_targstart; 292 t->t_units[t->t_firstunit]->u_go = scsi_targgo; 293 t->t_units[t->t_firstunit]->u_rel = scsi_targrel; 294 t->t_units[t->t_firstunit]->u_updev = &t->t_dev; 295 u->u_start = scsi_targstart; 296 u->u_go = scsi_targgo; 297 u->u_rel = scsi_targrel; 298 u->u_updev = &t->t_dev; 299 } 300 t->t_nunits++; /* another unit is alive */ 301 u->u_unit = unit; 302 u->u_targ = t->t_targ; /* record target number, */ 303 u->u_hba = hba; /* hba ... */ 304 u->u_hbd = hbd; /* and driver */ 305 } 306 307 /* NO DOUBT SOME OF THE STUFF PRINTED HERE IS USELESS */ 308 void 309 scsi_printinq(inq) 310 register struct scsi_inquiry *inq; 311 { 312 register int iso, ecma, ansi, t; 313 static char *types[] = { "disk", "tape", "printer", "processor", 314 "WORM", "ROM disk", "scanner", "magneto-optical", 315 "jukebox", "lan" }; 316 317 if ((t = (inq->si_type & TYPE_QUAL_MASK)) != 0) 318 printf("type-qual=0x%x ", t); 319 t = inq->si_type & TYPE_TYPE_MASK; 320 if (t < sizeof types / sizeof *types) 321 printf("%s", types[t]); 322 else 323 printf("<type %d>", t); 324 if (inq->si_qual & QUAL_RMB) 325 printf(" (removable)"); 326 printf(" qual=0x%x", inq->si_qual & QUAL_MASK); 327 iso = (inq->si_qual >> VER_ISO_SHIFT) & VER_ISO_MASK; 328 ecma = (inq->si_qual >> VER_ECMA_SHIFT) & VER_ECMA_MASK; 329 ansi = (inq->si_qual >> VER_ANSI_SHIFT) & VER_ANSI_MASK; 330 printf(" version=<iso %d, ecma %d, ansi %d>", iso, ecma, ansi); 331 if (ansi == 1 || ansi == 2) { 332 char v[9], p[17], r[5]; 333 334 scsi_inq_ansi((struct scsi_inq_ansi *)inq, v, p, r); 335 printf(" vendor %s, product %s, rev %s", v, p, r); 336 } 337 } 338 339 /* copy a counted string but trim trailing blanks; make the dest a C string */ 340 static void 341 scsi_str(src, dst, len) 342 register char *src, *dst; 343 register int len; 344 { 345 346 while (src[len - 1] == ' ') { 347 if (--len == 0) { 348 *dst = 0; 349 return; 350 } 351 } 352 bcopy(src, dst, len); 353 dst[len] = 0; 354 } 355 356 void 357 scsi_inq_ansi(si, vendor, product, rev) 358 register struct scsi_inq_ansi *si; 359 char *vendor, *product, *rev; 360 { 361 register int i, len; 362 363 /* if too short, extend with blanks */ 364 len = si->si_len + 5; /* 5 fixed; len is `additional' */ 365 if (len < sizeof(*si)) 366 for (i = len; i < sizeof *si; i++) 367 ((char *)si)[i] = ' '; 368 scsi_str(si->si_vendor, vendor, sizeof si->si_vendor); 369 scsi_str(si->si_product, product, sizeof si->si_product); 370 scsi_str(si->si_rev, rev, sizeof si->si_rev); 371 } 372 373 /* 374 * Tell all the devices on the given hba that it has been reset. 375 * SHOULD PROBABLY DO MORE HERE 376 */ 377 void 378 scsi_reset_units(hba) 379 register struct hba_softc *hba; 380 { 381 register int targ, unit; 382 register struct targ *t; 383 register struct unit *u; 384 385 for (targ = 0; targ < 8; targ++) { 386 if ((t = hba->hba_targets[targ]) == NULL) 387 continue; 388 for (unit = 0; unit < 8; unit++) 389 if ((u = t->t_units[unit]) != NULL) 390 (*u->u_driver->ud_reset)(u); 391 } 392 } 393 394 /* 395 * Start a unit on a target. 396 * If the target is busy, just enqueue the unit; 397 * once the target becomes free, we will call the hba start routine. 398 * Otherwise, call the hba start routine now, and then when the hba 399 * becomes free it will call the unit's dgo routine. 400 */ 401 void 402 scsi_targstart(self, sq, bp, dgo, dev) 403 struct device *self; 404 register struct sq *sq; 405 struct buf *bp; 406 scdgo_fn dgo; 407 struct device *dev; 408 { 409 register struct targ *t = (struct targ *)self; 410 register struct hba_softc *hba; 411 412 sq->sq_forw = NULL; 413 if (t->t_head == NULL) 414 t->t_head = sq; 415 else 416 t->t_tail->sq_forw = sq; 417 t->t_tail = sq; 418 if (t->t_busy == 0) { 419 t->t_busy = 1; 420 hba = (struct hba_softc *)t->t_dev.dv_parent; 421 (*hba->hba_driver->hd_start)(&hba->hba_dev, &t->t_forw, bp, 422 dgo, dev); 423 } else { 424 sq->sq_bp = bp; 425 sq->sq_dgo = dgo; 426 sq->sq_dev = dev; 427 } 428 } 429 430 /* 431 * The unit got the bus, and wants the hba to go. 432 * Remember its interrupt handler; substitute ours instead. 433 */ 434 int 435 scsi_targgo(self, targ, intr, dev, bp, pad) 436 struct device *self; 437 int targ; 438 scintr_fn intr; 439 struct device *dev; 440 struct buf *bp; 441 int pad; 442 { 443 register struct targ *t = (struct targ *)self; 444 register struct hba_softc *hba; 445 446 t->t_intr = intr; 447 t->t_intrdev = dev; 448 hba = (struct hba_softc *)t->t_dev.dv_parent; 449 return ((*hba->hba_driver->hd_go)(&hba->hba_dev, targ, 450 scsi_targintr, &t->t_dev, bp, pad)); 451 } 452 453 /* 454 * The hba got an interrupt. Dequeue the unit from the target 455 * (the target is already off the hba queue) and then call the 456 * underlying interrupt handler. 457 */ 458 void 459 scsi_targintr(self, stat, resid) 460 struct device *self; 461 int stat, resid; 462 { 463 register struct targ *t = (struct targ *)self; 464 register struct hba_softc *hba; 465 register struct sq *sq; 466 467 sq = t->t_head; 468 if (sq == NULL) panic("scsi_targintr"); 469 t->t_head = sq = sq->sq_forw; 470 (*t->t_intr)(t->t_intrdev, stat, resid); 471 if (sq != NULL) { 472 hba = (struct hba_softc *)t->t_dev.dv_parent; 473 (*hba->hba_driver->hd_start)(&hba->hba_dev, &t->t_forw, 474 sq->sq_bp, sq->sq_dgo, sq->sq_dev); 475 } else 476 t->t_busy = 0; 477 } 478 479 /* 480 * The unit decided that it needed to `give up' its hold on the bus early. 481 */ 482 void 483 scsi_targrel(self) 484 struct device *self; 485 { 486 register struct targ *t = (struct targ *)self; 487 register struct hba_softc *hba; 488 register struct sq *sq; 489 490 hba = (struct hba_softc *)t->t_dev.dv_parent; 491 sq = t->t_head; 492 if (sq == NULL) panic("scsi_targrel"); 493 /* 494 * This target is at the head of the hba queue. 495 * Remove it by calling hba bus release. Then, if the 496 * target queue is not empty, put it back on the hba queue. 497 * (This produces round robin service.) 498 */ 499 (*hba->hba_driver->hd_rel)(&hba->hba_dev); 500 sq = sq->sq_forw; 501 if ((t->t_head = sq) != NULL) 502 (*hba->hba_driver->hd_start)(&hba->hba_dev, &t->t_forw, 503 sq->sq_bp, sq->sq_dgo, sq->sq_dev); 504 else 505 t->t_busy = 0; 506 } 507