|
|
1.1 ! root 1: /* ! 2: * Written by Julian Elischer ([email protected]) ! 3: * for TRW Financial Systems for use under the MACH(2.5) operating system. ! 4: * ! 5: * TRW Financial Systems, in accordance with their agreement with Carnegie ! 6: * Mellon University, makes this software available to CMU to distribute ! 7: * or use in any manner that they see fit as long as this message is kept with ! 8: * the software. For this reason TFS also grants any other persons or ! 9: * organisations permission to use or modify this software. ! 10: * ! 11: * TFS supplies this software to be publicly redistributed ! 12: * on the understanding that TFS is not responsible for the correct ! 13: * functioning of this software in any circumstances. ! 14: * ! 15: * ! 16: * PATCHES MAGIC LEVEL PATCH THAT GOT US HERE ! 17: * -------------------- ----- ---------------------- ! 18: * CURRENT PATCH LEVEL: 1 00098 ! 19: * -------------------- ----- ---------------------- ! 20: * ! 21: * 16 Feb 93 Julian Elischer ADDED for SCSI system ! 22: */ ! 23: ! 24: /* ! 25: * Ported to run under 386BSD by Julian Elischer ([email protected]) Sept 1992 ! 26: */ ! 27: ! 28: /* ! 29: $Log: ! 30: * ! 31: */ ! 32: #include <sys/types.h> ! 33: #include "st.h" ! 34: #include "sd.h" ! 35: #include "ch.h" ! 36: #include "cd.h" ! 37: ! 38: #ifdef MACH ! 39: #include <i386/machparam.h> ! 40: #endif MACH ! 41: #include <scsi/scsi_all.h> ! 42: #include <scsi/scsiconf.h> ! 43: ! 44: #if !defined(OSF) && !defined(__386BSD__) ! 45: #include "bll.h" ! 46: #include "cals.h" ! 47: #include "kil.h" ! 48: #else ! 49: #define NBLL 0 ! 50: #define NCALS 0 ! 51: #define NKIL 0 ! 52: #endif /* !defined(OSF) && !defined(__386BSD__) */ ! 53: ! 54: #if NSD > 0 ! 55: extern sdattach(); ! 56: #endif NSD ! 57: #if NST > 0 ! 58: extern stattach(); ! 59: #endif NST ! 60: #if NCH > 0 ! 61: extern chattach(); ! 62: #endif NCH ! 63: #if NCD > 0 ! 64: extern cdattach(); ! 65: #endif NCD ! 66: #if NBLL > 0 ! 67: extern bllattach(); ! 68: #endif NBLL ! 69: #if NCALS > 0 ! 70: extern calsattach(); ! 71: #endif NCALS ! 72: #if NKIL > 0 ! 73: extern kil_attach(); ! 74: #endif NKIL ! 75: ! 76: /***************************************************************\ ! 77: * The structure of pre-configured devices that might be turned * ! 78: * off and therefore may not show up * ! 79: \***************************************************************/ ! 80: struct predefined ! 81: { ! 82: u_char scsibus; ! 83: u_char dev; ! 84: u_char lu; ! 85: int (*attach_rtn)(); ! 86: char *devname; ! 87: char flags; ! 88: } ! 89: pd[] = ! 90: { ! 91: #ifdef EXAMPLE_PREDEFINE ! 92: #if NSD > 0 ! 93: {0,0,0,sdattach,"sd",0},/* define a disk at scsibus=0 dev=0 lu=0 */ ! 94: #endif NSD ! 95: #endif EXAMPLE_PREDEFINE ! 96: {0,9,9} /*illegal dummy end entry */ ! 97: }; ! 98: ! 99: ! 100: /***************************************************************\ ! 101: * The structure of known drivers for autoconfiguration * ! 102: \***************************************************************/ ! 103: static struct scsidevs ! 104: { ! 105: int type; ! 106: int removable; ! 107: char *manufacturer; ! 108: char *model; ! 109: char *version; ! 110: int (*attach_rtn)(); ! 111: char *devname; ! 112: char flags; /* 1 show my comparisons during boot(debug) */ ! 113: } ! 114: #define SC_SHOWME 0x01 ! 115: #define SC_ONE_LU 0x00 ! 116: #define SC_MORE_LUS 0x02 ! 117: knowndevs[] = { ! 118: #if NSD > 0 ! 119: { T_DIRECT,T_FIXED,"standard","any" ! 120: ,"any",sdattach,"sd",SC_ONE_LU }, ! 121: { T_DIRECT,T_FIXED,"MAXTOR ","XT-4170S " ! 122: ,"B5A ",sdattach,"mx1",SC_ONE_LU }, ! 123: #endif NSD ! 124: #if NST > 0 ! 125: { T_SEQUENTIAL,T_REMOV,"standard","any" ! 126: ,"any",stattach,"st",SC_ONE_LU }, ! 127: #endif NST ! 128: #if NCALS > 0 ! 129: { T_PROCESSOR,T_FIXED,"standard","any" ! 130: ,"any",calsattach,"cals",SC_MORE_LUS }, ! 131: #endif NCALS ! 132: #if NCH > 0 ! 133: { T_CHANGER,T_REMOV,"standard","any" ! 134: ,"any",chattach,"ch",SC_ONE_LU }, ! 135: #endif NCH ! 136: #if NCD > 0 ! 137: { T_READONLY,T_REMOV,"SONY ","CD-ROM CDU-8012 " ! 138: ,"3.1a",cdattach,"cd",SC_ONE_LU }, ! 139: #endif NCD ! 140: #if NBLL > 0 ! 141: { T_PROCESSOR,T_FIXED,"AEG ","READER " ! 142: ,"V1.0",bllattach,"bll",SC_MORE_LUS }, ! 143: #endif NBLL ! 144: #if NKIL > 0 ! 145: { T_SCANNER,T_FIXED,"KODAK ","IL Scanner 900 " ! 146: ,"any",kil_attach,"kil",SC_ONE_LU }, ! 147: #endif NKIL ! 148: ! 149: {0} ! 150: }; ! 151: /***************************************************************\ ! 152: * Declarations * ! 153: \***************************************************************/ ! 154: struct predefined *scsi_get_predef(); ! 155: struct scsidevs *scsi_probedev(); ! 156: struct scsidevs *selectdev(); ! 157: ! 158: /* controls debug level within the scsi subsystem */ ! 159: /* see scsiconf.h for values */ ! 160: int scsi_debug = 0x0; ! 161: int scsibus = 0x0; /* This is the Nth scsibus */ ! 162: ! 163: /***************************************************************\ ! 164: * The routine called by the adapter boards to get all their * ! 165: * devices configured in. * ! 166: \***************************************************************/ ! 167: scsi_attachdevs( unit, scsi_addr, scsi_switch) ! 168: int unit,scsi_addr; ! 169: struct scsi_switch *scsi_switch; ! 170: { ! 171: int targ,lun; ! 172: struct scsidevs *bestmatch = (struct scsidevs *)0; ! 173: struct predefined *predef; ! 174: int maybe_more; ! 175: ! 176: #ifdef SCSI_DELAY ! 177: #if SCSI_DELAY > 2 ! 178: printf("waiting for scsi devices to settle\n"); ! 179: #else SCSI_DELAY > 2 ! 180: #define SCSI_DELAY 15 ! 181: #endif SCSI_DELAY > 2 ! 182: #else ! 183: #define SCSI_DELAY 2 ! 184: #endif SCSI_DELAY ! 185: spinwait(1000 * SCSI_DELAY); ! 186: targ = 0; ! 187: while(targ < 8) ! 188: { ! 189: maybe_more = 0; /* by default only check 1 lun */ ! 190: if (targ == scsi_addr) ! 191: { ! 192: targ++; ! 193: continue; ! 194: } ! 195: lun = 0; ! 196: while(lun < 8) ! 197: { ! 198: predef = scsi_get_predef(scsibus ! 199: ,targ ! 200: ,lun ! 201: ,&maybe_more); ! 202: bestmatch = scsi_probedev(unit ! 203: ,targ ! 204: ,lun ! 205: ,scsi_switch ! 206: ,&maybe_more); ! 207: if((bestmatch) && (predef)) /* both exist */ ! 208: { ! 209: if(bestmatch->attach_rtn ! 210: != predef->attach_rtn) ! 211: { ! 212: printf("Clash in found/expected devices\n"); ! 213: printf("will link in FOUND\n"); ! 214: } ! 215: (*(bestmatch->attach_rtn))(unit, ! 216: targ, ! 217: lun, ! 218: scsi_switch); ! 219: } ! 220: if((bestmatch) && (!predef)) /* just FOUND */ ! 221: { ! 222: (*(bestmatch->attach_rtn))(unit, ! 223: targ, ! 224: lun, ! 225: scsi_switch); ! 226: } ! 227: if((!bestmatch) && (predef)) /* just predef */ ! 228: { ! 229: (*(predef->attach_rtn))(unit, ! 230: targ, ! 231: lun, ! 232: scsi_switch); ! 233: } ! 234: if(!(maybe_more)) /* nothing suggests we'll find more */ ! 235: { ! 236: break; /* nothing here, skip to next targ */ ! 237: } ! 238: /* otherwise something says we should look further*/ ! 239: lun++; ! 240: } ! 241: targ++; ! 242: } ! 243: #if NGENSCSI > 0 ! 244: /***************************************************************\ ! 245: * If available hook up the generic scsi driver, letting it * ! 246: * know which target is US. (i.e. illegal or at least special) * ! 247: \***************************************************************/ ! 248: genscsi_attach(unit,scsi_addr,0,scsi_switch); ! 249: #endif ! 250: scsibus++; /* next time we are on the NEXT scsi bus */ ! 251: } ! 252: ! 253: /***********************************************\ ! 254: * given a target and lu, check if there is a * ! 255: * predefined device for that address * ! 256: \***********************************************/ ! 257: struct predefined *scsi_get_predef(unit,target,lu,maybe_more) ! 258: int unit,target,lu,*maybe_more; ! 259: { ! 260: int upto,numents; ! 261: ! 262: numents = (sizeof(pd)/sizeof(struct predefined)) - 1; ! 263: ! 264: for(upto = 0;upto < numents;upto++) ! 265: { ! 266: if(pd[upto].scsibus != unit) ! 267: continue; ! 268: if(pd[upto].dev != target) ! 269: continue; ! 270: if(pd[upto].lu != lu) ! 271: continue; ! 272: ! 273: printf(" dev%d,lu%d: %s - PRECONFIGURED -\n" ! 274: ,target ! 275: ,lu ! 276: ,pd[upto].devname); ! 277: *maybe_more = pd[upto].flags & SC_MORE_LUS; ! 278: return(&(pd[upto])); ! 279: } ! 280: return((struct predefined *)0); ! 281: } ! 282: ! 283: /***********************************************\ ! 284: * given a target and lu, ask the device what * ! 285: * it is, and find the correct driver table * ! 286: * entry. * ! 287: \***********************************************/ ! 288: struct scsidevs *scsi_probedev(unit,target,lu,scsi_switch, maybe_more) ! 289: ! 290: struct scsi_switch *scsi_switch; ! 291: int unit,target,lu; ! 292: int *maybe_more; ! 293: { ! 294: struct scsidevs *bestmatch = (struct scsidevs *)0; ! 295: char *dtype=(char *)0,*desc; ! 296: char *qtype; ! 297: static struct scsi_inquiry_data inqbuf; ! 298: int len,qualifier,type,remov; ! 299: char manu[32]; ! 300: char model[32]; ! 301: char version[32]; ! 302: ! 303: ! 304: bzero(&inqbuf,sizeof(inqbuf)); ! 305: /***********************************************\ ! 306: * Ask the device what it is * ! 307: \***********************************************/ ! 308: #ifdef DEBUG ! 309: if((target == 0) && (lu == 0)) ! 310: scsi_debug = 0xfff; ! 311: else ! 312: scsi_debug = 0; ! 313: #endif DEBUG ! 314: if(scsi_ready( unit, ! 315: target, ! 316: lu, ! 317: scsi_switch, ! 318: SCSI_NOSLEEP | SCSI_NOMASK) != COMPLETE) ! 319: { ! 320: return(struct scsidevs *)0; ! 321: } ! 322: if(scsi_inquire(unit, ! 323: target, ! 324: lu, ! 325: scsi_switch, ! 326: &inqbuf, ! 327: SCSI_NOSLEEP | SCSI_NOMASK) != COMPLETE) ! 328: { ! 329: return(struct scsidevs *)0; ! 330: } ! 331: ! 332: /***********************************************\ ! 333: * note what BASIC type of device it is * ! 334: \***********************************************/ ! 335: if(scsi_debug & SHOWINQUIRY) ! 336: { ! 337: desc=(char *)&inqbuf; ! 338: printf("inq: %x %x %x %x %x %x %x %x %x %x %x %x %x\n", ! 339: desc[0], desc[1], desc[2], desc[3], ! 340: desc[4], desc[5], desc[6], desc[7], ! 341: desc[8], desc[9], desc[10], desc[11], ! 342: desc[12]); ! 343: } ! 344: ! 345: type = inqbuf.device_type; ! 346: qualifier = inqbuf.device_qualifier; ! 347: remov = inqbuf.removable; ! 348: ! 349: /* Check for a non-existent unit. If the device is returning ! 350: * this much, then we must set the flag that has ! 351: * the searcher keep looking on other luns. ! 352: */ ! 353: if (qualifier == 3 && type == T_NODEVICE) ! 354: { ! 355: *maybe_more = 1; ! 356: return (struct scsidevs *)0; ! 357: } ! 358: ! 359: /* Any device qualifier that has ! 360: * the top bit set (qualifier&4 != 0) is vendor specific and ! 361: * won't match in this switch. ! 362: */ ! 363: ! 364: switch(qualifier) ! 365: { ! 366: case 0: ! 367: qtype=""; ! 368: break; ! 369: case 1: ! 370: qtype=", Unit not Connected!"; ! 371: break; ! 372: case 2: ! 373: qtype=", Reserved Peripheral Qualifier!"; ! 374: break; ! 375: case 3: ! 376: qtype=", The Target can't support this Unit!"; ! 377: break; ! 378: ! 379: default: ! 380: dtype="vendor specific"; ! 381: qtype=""; ! 382: *maybe_more = 1; ! 383: break; ! 384: } ! 385: ! 386: if (dtype == 0) ! 387: switch(type) ! 388: { ! 389: case T_DIRECT: ! 390: dtype="direct"; ! 391: break; ! 392: case T_SEQUENTIAL: ! 393: dtype="sequential"; ! 394: break; ! 395: case T_PRINTER: ! 396: dtype="printer"; ! 397: break; ! 398: case T_PROCESSOR: ! 399: dtype="processor"; ! 400: break; ! 401: case T_READONLY: ! 402: dtype="readonly"; ! 403: break; ! 404: case T_WORM: ! 405: dtype="worm"; ! 406: break; ! 407: case T_SCANNER: ! 408: dtype="scanner"; ! 409: break; ! 410: case T_OPTICAL: ! 411: dtype="optical"; ! 412: break; ! 413: case T_CHANGER: ! 414: dtype="changer"; ! 415: break; ! 416: case T_COMM: ! 417: dtype="communication"; ! 418: break; ! 419: default: ! 420: dtype="unknown"; ! 421: break; ! 422: } ! 423: ! 424: /***********************************************\ ! 425: * Then if it's advanced enough, more detailed * ! 426: * information * ! 427: \***********************************************/ ! 428: if(inqbuf.ansii_version > 0) ! 429: { ! 430: if ((len = inqbuf.additional_length ! 431: + ( (char *)inqbuf.unused ! 432: - (char *)&inqbuf)) ! 433: > (sizeof(struct scsi_inquiry_data) - 1)) ! 434: len = sizeof(struct scsi_inquiry_data) - 1; ! 435: desc=inqbuf.vendor; ! 436: desc[len-(desc - (char *)&inqbuf)] = 0; ! 437: strncpy(manu,inqbuf.vendor,8);manu[8]=0; ! 438: strncpy(model,inqbuf.product,16);model[16]=0; ! 439: strncpy(version,inqbuf.revision,4);version[4]=0; ! 440: } ! 441: else ! 442: /***********************************************\ ! 443: * If not advanced enough, use default values * ! 444: \***********************************************/ ! 445: { ! 446: desc="early protocol device"; ! 447: strncpy(manu,"unknown",8); ! 448: strncpy(model,"unknown",16); ! 449: strncpy(version,"????",4); ! 450: } ! 451: printf(" dev%d,lu%d: type %d:%d(%s%s),%s '%s%s%s' scsi%d\n" ! 452: ,target ! 453: ,lu ! 454: ,qualifier,type ! 455: ,dtype,qtype ! 456: ,remov?"removable":"fixed" ! 457: ,manu ! 458: ,model ! 459: ,version ! 460: ,inqbuf.ansii_version ! 461: ); ! 462: /***********************************************\ ! 463: * Try make as good a match as possible with * ! 464: * available sub drivers * ! 465: \***********************************************/ ! 466: bestmatch = (selectdev(unit,target,lu,&scsi_switch, ! 467: qualifier,type,remov,manu,model,version)); ! 468: if((bestmatch) && (bestmatch->flags & SC_MORE_LUS)) ! 469: { ! 470: *maybe_more = 1; ! 471: } ! 472: return(bestmatch); ! 473: } ! 474: ! 475: /***********************************************\ ! 476: * Try make as good a match as possible with * ! 477: * available sub drivers * ! 478: \***********************************************/ ! 479: struct scsidevs ! 480: *selectdev(unit,target,lu,dvr_switch,qualifier,type,remov,manu,model,rev) ! 481: int unit,target,lu; ! 482: struct scsi_switch *dvr_switch; ! 483: int qualifier,type,remov; ! 484: char *manu,*model,*rev; ! 485: { ! 486: int numents = (sizeof(knowndevs)/sizeof(struct scsidevs)) - 1; ! 487: int count = 0; ! 488: int bestmatches = 0; ! 489: struct scsidevs *bestmatch = (struct scsidevs *)0; ! 490: struct scsidevs *thisentry = knowndevs; ! 491: ! 492: type |= (qualifier << 5); ! 493: ! 494: thisentry--; ! 495: while( count++ < numents) ! 496: { ! 497: thisentry++; ! 498: if(type != thisentry->type) ! 499: { ! 500: continue; ! 501: } ! 502: if(bestmatches < 1) ! 503: { ! 504: bestmatches = 1; ! 505: bestmatch = thisentry; ! 506: } ! 507: if(remov != thisentry->removable) ! 508: { ! 509: continue; ! 510: } ! 511: if(bestmatches < 2) ! 512: { ! 513: bestmatches = 2; ! 514: bestmatch = thisentry; ! 515: } ! 516: if(thisentry->flags & SC_SHOWME) ! 517: printf("\n%s-\n%s-",thisentry->manufacturer, manu); ! 518: if(strcmp(thisentry->manufacturer, manu)) ! 519: { ! 520: continue; ! 521: } ! 522: if(bestmatches < 3) ! 523: { ! 524: bestmatches = 3; ! 525: bestmatch = thisentry; ! 526: } ! 527: if(thisentry->flags & SC_SHOWME) ! 528: printf("\n%s-\n%s-",thisentry->model, model); ! 529: if(strcmp(thisentry->model, model)) ! 530: { ! 531: continue; ! 532: } ! 533: if(bestmatches < 4) ! 534: { ! 535: bestmatches = 4; ! 536: bestmatch = thisentry; ! 537: } ! 538: if(thisentry->flags & SC_SHOWME) ! 539: printf("\n%s-\n%s-",thisentry->version, rev); ! 540: if(strcmp(thisentry->version, rev)) ! 541: { ! 542: continue; ! 543: } ! 544: if(bestmatches < 5) ! 545: { ! 546: bestmatches = 5; ! 547: bestmatch = thisentry; ! 548: break; ! 549: } ! 550: } ! 551: ! 552: if (bestmatch == (struct scsidevs *)0) ! 553: printf(" No explicit device driver match for \"%s %s\".\n", ! 554: manu, model); ! 555: ! 556: return(bestmatch); ! 557: } ! 558: ! 559: static int recurse = 0; ! 560: /***********************************************\ ! 561: * Do a scsi operation asking a device if it is * ! 562: * ready. Use the scsi_cmd routine in the switch * ! 563: * table. * ! 564: \***********************************************/ ! 565: scsi_ready(unit,target,lu,scsi_switch, flags) ! 566: struct scsi_switch *scsi_switch; ! 567: { ! 568: struct scsi_test_unit_ready scsi_cmd; ! 569: struct scsi_xfer scsi_xfer; ! 570: volatile int rval; ! 571: int key; ! 572: ! 573: bzero(&scsi_cmd, sizeof(scsi_cmd)); ! 574: bzero(&scsi_xfer, sizeof(scsi_xfer)); ! 575: scsi_cmd.op_code = TEST_UNIT_READY; ! 576: ! 577: scsi_xfer.flags=flags | INUSE; ! 578: scsi_xfer.adapter=unit; ! 579: scsi_xfer.targ=target; ! 580: scsi_xfer.lu=lu; ! 581: scsi_xfer.cmd=(struct scsi_generic *)&scsi_cmd; ! 582: scsi_xfer.retries=8; ! 583: scsi_xfer.timeout=10000; ! 584: scsi_xfer.cmdlen=sizeof(scsi_cmd); ! 585: scsi_xfer.data=0; ! 586: scsi_xfer.datalen=0; ! 587: scsi_xfer.resid=0; ! 588: scsi_xfer.when_done=0; ! 589: scsi_xfer.done_arg=0; ! 590: retry: scsi_xfer.error=0; ! 591: /*******************************************************\ ! 592: * do not use interrupts * ! 593: \*******************************************************/ ! 594: rval = (*(scsi_switch->scsi_cmd))(&scsi_xfer); ! 595: if (rval != COMPLETE) ! 596: { ! 597: if(scsi_debug) ! 598: { ! 599: printf("scsi error, rval = 0x%x\n",rval); ! 600: printf("code from driver: 0x%x\n",scsi_xfer.error); ! 601: } ! 602: switch(scsi_xfer.error) ! 603: { ! 604: case XS_SENSE: ! 605: /*******************************************************\ ! 606: * Any sense value is illegal except UNIT ATTENTION * ! 607: * In which case we need to check again to get the * ! 608: * correct response. * ! 609: *( especially exabytes) * ! 610: \*******************************************************/ ! 611: if(scsi_xfer.sense.error_class == 7 ) ! 612: { ! 613: key = scsi_xfer.sense.ext.extended.sense_key ; ! 614: switch(key) ! 615: { ! 616: case 2: /* not ready BUT PRESENT! */ ! 617: return(COMPLETE); ! 618: case 6: ! 619: spinwait(1000); ! 620: if(scsi_xfer.retries--) ! 621: { ! 622: scsi_xfer.flags &= ~ITSDONE; ! 623: goto retry; ! 624: } ! 625: return(COMPLETE); ! 626: default: ! 627: if(scsi_debug) ! 628: printf("%d:%d,key=%x.", ! 629: target,lu,key); ! 630: } ! 631: } ! 632: return(HAD_ERROR); ! 633: case XS_BUSY: ! 634: spinwait(1000); ! 635: if(scsi_xfer.retries--) ! 636: { ! 637: scsi_xfer.flags &= ~ITSDONE; ! 638: goto retry; ! 639: } ! 640: return(COMPLETE); /* it's busy so it's there */ ! 641: case XS_TIMEOUT: ! 642: default: ! 643: return(HAD_ERROR); ! 644: } ! 645: } ! 646: return(COMPLETE); ! 647: } ! 648: /***********************************************\ ! 649: * Do a scsi operation asking a device what it is* ! 650: * Use the scsi_cmd routine in the switch table. * ! 651: \***********************************************/ ! 652: scsi_inquire(unit,target,lu,scsi_switch,inqbuf, flags) ! 653: struct scsi_switch *scsi_switch; ! 654: u_char *inqbuf; ! 655: { ! 656: struct scsi_inquiry scsi_cmd; ! 657: struct scsi_xfer scsi_xfer; ! 658: volatile int rval; ! 659: ! 660: bzero(&scsi_cmd, sizeof(scsi_cmd)); ! 661: bzero(&scsi_xfer, sizeof(scsi_xfer)); ! 662: scsi_cmd.op_code = INQUIRY; ! 663: scsi_cmd.length = sizeof(struct scsi_inquiry_data); ! 664: ! 665: scsi_xfer.flags=flags | SCSI_DATA_IN | INUSE; ! 666: scsi_xfer.adapter=unit; ! 667: scsi_xfer.targ=target; ! 668: scsi_xfer.lu=lu; ! 669: scsi_xfer.retries=8; ! 670: scsi_xfer.timeout=10000; ! 671: scsi_xfer.cmd=(struct scsi_generic *)&scsi_cmd; ! 672: scsi_xfer.cmdlen= sizeof(struct scsi_inquiry); ! 673: scsi_xfer.data=inqbuf; ! 674: scsi_xfer.datalen=sizeof(struct scsi_inquiry_data); ! 675: scsi_xfer.resid=sizeof(struct scsi_inquiry_data); ! 676: scsi_xfer.when_done=0; ! 677: scsi_xfer.done_arg=0; ! 678: retry: scsi_xfer.error=0; ! 679: /*******************************************************\ ! 680: * do not use interrupts * ! 681: \*******************************************************/ ! 682: if ((*(scsi_switch->scsi_cmd))(&scsi_xfer) != COMPLETE) ! 683: { ! 684: if(scsi_debug) printf("inquiry had error(0x%x) ",scsi_xfer.error); ! 685: switch(scsi_xfer.error) ! 686: { ! 687: case XS_NOERROR: ! 688: break; ! 689: case XS_SENSE: ! 690: /*******************************************************\ ! 691: * Any sense value is illegal except UNIT ATTENTION * ! 692: * In which case we need to check again to get the * ! 693: * correct response. * ! 694: *( especially exabytes) * ! 695: \*******************************************************/ ! 696: if((scsi_xfer.sense.error_class == 7 ) ! 697: && (scsi_xfer.sense.ext.extended.sense_key == 6)) ! 698: { /* it's changed so it's there */ ! 699: spinwait(1000); ! 700: { ! 701: if(scsi_xfer.retries--) ! 702: { ! 703: scsi_xfer.flags &= ~ITSDONE; ! 704: goto retry; ! 705: } ! 706: } ! 707: return( COMPLETE); ! 708: } ! 709: return(HAD_ERROR); ! 710: case XS_BUSY: ! 711: spinwait(1000); ! 712: if(scsi_xfer.retries--) ! 713: { ! 714: scsi_xfer.flags &= ~ITSDONE; ! 715: goto retry; ! 716: } ! 717: case XS_TIMEOUT: ! 718: default: ! 719: return(HAD_ERROR); ! 720: } ! 721: } ! 722: return(COMPLETE); ! 723: } ! 724: ! 725: ! 726: ! 727: ! 728: /***********************************************\ ! 729: * Utility routines often used in SCSI stuff * ! 730: \***********************************************/ ! 731: ! 732: /***********************************************\ ! 733: * convert a physical address to 3 bytes, * ! 734: * MSB at the lowest address, * ! 735: * LSB at the highest. * ! 736: \***********************************************/ ! 737: ! 738: lto3b(val, bytes) ! 739: u_char *bytes; ! 740: { ! 741: *bytes++ = (val&0xff0000)>>16; ! 742: *bytes++ = (val&0xff00)>>8; ! 743: *bytes = val&0xff; ! 744: } ! 745: ! 746: /***********************************************\ ! 747: * The reverse of lto3b * ! 748: \***********************************************/ ! 749: _3btol(bytes) ! 750: u_char *bytes; ! 751: { ! 752: int rc; ! 753: rc = (*bytes++ << 16); ! 754: rc += (*bytes++ << 8); ! 755: rc += *bytes; ! 756: return(rc); ! 757: } ! 758:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.