|
|
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.