|
|
1.1 root 1: /*
2: * Ported for use with the UltraStor 14f by Gary Close ([email protected])
3: * Thanks to Julian Elischer for advice and help with this port.
4: *
5: * Written by Julian Elischer ([email protected])
6: * for TRW Financial Systems for use under the MACH(2.5) operating system.
7: *
8: * TRW Financial Systems, in accordance with their agreement with Carnegie
9: * Mellon University, makes this software available to CMU to distribute
10: * or use in any manner that they see fit as long as this message is kept with
11: * the software. For this reason TFS also grants any other persons or
12: * organisations permission to use or modify this software.
13: *
14: * TFS supplies this software to be publicly redistributed
15: * on the understanding that TFS is not responsible for the correct
16: * functioning of this software in any circumstances.
17: *
18: *
19: * PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
20: * -------------------- ----- ----------------------
21: * CURRENT PATCH LEVEL: 1 00098
22: * -------------------- ----- ----------------------
23: *
24: * 16 Feb 93 Julian Elischer ADDED for SCSI system
25: * commenced: Sun Sep 27 18:14:01 PDT 1992
26: */
27:
28: #include <sys/types.h>
29: #include <uha.h>
30:
31: #include <sys/param.h>
32: #include <sys/systm.h>
33: #include <sys/errno.h>
34: #include <sys/ioctl.h>
35: #include <sys/buf.h>
36: #include <sys/proc.h>
37: #include <sys/user.h>
38:
39: #ifdef MACH /* EITHER CMU OR OSF */
40: #include <i386/ipl.h>
41: #include <i386at/scsi.h>
42: #include <i386at/scsiconf.h>
43:
44: #ifdef OSF /* OSF ONLY */
45: #include <sys/table.h>
46: #include <i386/handler.h>
47: #include <i386/dispatcher.h>
48: #include <i386/AT386/atbus.h>
49:
50: #else OSF /* CMU ONLY */
51: #include <i386at/atbus.h>
52: #include <i386/pio.h>
53: #endif OSF
54: #endif MACH /* end of MACH specific */
55:
56: #ifdef __386BSD__ /* 386BSD specific */
57: #define isa_dev isa_device
58: #define dev_unit id_unit
59: #define dev_addr id_iobase
60:
61: #include <i386/include/pio.h>
62: #include <i386/isa/isa_device.h>
63: #include <scsi/scsi_all.h>
64: #include <scsi/scsiconf.h>
65: #endif __386BSD__
66:
67: /**/
68:
69: #ifdef __386BSD__
70: #ifdef DDB
71: int Debugger();
72: #else
73: #define Debugger() panic("should call debugger here")
74: #endif /*!DDB*/
75: #endif __386BSD__
76:
77: #ifdef MACH
78: int Debugger();
79: #endif MACH
80:
81: typedef struct {unsigned char addr[4]; } physaddr;
82: typedef struct {unsigned char len[4]; } physlen;
83:
84:
85: #ifdef MACH
86: extern physaddr kvtophys();
87: #define PHYSTOKV(x) phystokv(x)
88: #define KVTOPHYS(x) kvtophys(x)
89: #endif MACH
90:
91: #ifdef __386BSD__
92: #define PHYSTOKV(x) (x | 0xFE000000)
93: #define KVTOPHYS(x) vtophys(x)
94: #endif __386BSD__
95:
96: extern int delaycount; /* from clock setup code */
97: #define NUM_CONCURRENT 16 /* number of concurrent ops per board */
98: #define UHA_NSEG 33 /* number of dma segments supported */
99: #define FUDGE(X) (X>>1) /* our loops are slower than spinwait() */
100: /**/
101: /************************** board definitions *******************************/
102: /*
103: * I/O Port Interface
104: */
105: #define UHA_LMASK (0x000) /* local doorbell mask reg */
106: #define UHA_LINT (0x001) /* local doorbell int/stat reg */
107: #define UHA_SMASK (0x002) /* system doorbell mask reg */
108: #define UHA_SINT (0x003) /* system doorbell int/stat reg */
109: #define UHA_ID0 (0x004) /* product id reg 0 */
110: #define UHA_ID1 (0x005) /* product id reg 1 */
111: #define UHA_CONF1 (0x006) /* config reg 1 */
112: #define UHA_CONF2 (0x007) /* config reg 2 */
113: #define UHA_OGM0 (0x008) /* outgoing mail ptr 0 least sig */
114: #define UHA_OGM1 (0x009) /* outgoing mail ptr 1 least mid */
115: #define UHA_OGM2 (0x00a) /* outgoing mail ptr 2 most mid */
116: #define UHA_OGM3 (0x00b) /* outgoing mail ptr 3 most sig */
117: #define UHA_ICM0 (0x00c) /* incoming mail ptr 0 */
118: #define UHA_ICM1 (0x00d) /* incoming mail ptr 1 */
119: #define UHA_ICM2 (0x00e) /* incoming mail ptr 2 */
120: #define UHA_ICM3 (0x00f) /* incoming mail ptr 3 */
121:
122: /*
123: * UHA_LMASK bits (read only)
124: */
125:
126: #define UHA_LDIE 0x80 /* local doorbell int enabled */
127: #define UHA_SRSTE 0x40 /* soft reset enabled */
128: #define UHA_ABORTEN 0x10 /* abort MSCP enabled */
129: #define UHA_OGMINTEN 0x01 /* outgoing mail interrupt enabled */
130:
131: /*
132: * UHA_LINT bits (read)
133: */
134:
135: #define UHA_LDIP 0x80 /* local doorbell int pending */
136:
137: /*
138: * UHA_LINT bits (write)
139: */
140:
141: #define UHA_ADRST 0x40 /* adapter soft reset */
142: #define UHA_SBRST 0x20 /* scsi bus reset */
143: #define UHA_ASRST 0x60 /* adapter and scsi reset */
144: #define UHA_ABORT 0x10 /* abort MSCP */
145: #define UHA_OGMINT 0x01 /* tell adapter to get mail */
146:
147: /*
148: * UHA_SMASK bits (read)
149: */
150:
151: #define UHA_SINTEN 0x80 /* system doorbell interupt Enabled */
152: #define UHA_ABORT_COMPLETE_EN 0x10 /* abort MSCP command complete int Enabled */
153: #define UHA_ICM_ENABLED 0x01 /* ICM interrupt enabled
154:
155: /*
156: * UHA_SMASK bits (write)
157: */
158:
159: #define UHA_ENSINT 0x80 /* enable system doorbell interrupt */
160: #define UHA_EN_ABORT_COMPLETE 0x10 /* enable abort MSCP complete int */
161: #define UHA_ENICM 0x01 /* enable ICM interrupt */
162:
163: /*
164: * UHA_SINT bits (read)
165: */
166:
167: #define UHA_SINTP 0x80 /* system doorbell int pending */
168: #define UHA_ABORT_SUCC 0x10 /* abort MSCP successful */
169: #define UHA_ABORT_FAIL 0x18 /* abort MSCP failed */
170:
171: /*
172: * UHA_SINT bits (write)
173: */
174:
175: #define UHA_ABORT_ACK 0x18 /* acknowledge status and clear */
176: #define UHA_ICM_ACK 0x01 /* acknowledge ICM and clear */
177:
178: /*
179: * UHA_CONF1 bits (read only)
180: */
181:
182: #define UHA_DMA_CH5 0x00 /* DMA channel 5 */
183: #define UHA_DMA_CH6 0x40 /* 6 */
184: #define UHA_DMA_CH7 0x80 /* 7 */
185: #define UHA_IRQ15 0x00 /* IRQ 15 */
186: #define UHA_IRQ14 0x10 /* 14 */
187: #define UHA_IRQ11 0x20 /* 11 */
188: #define UHA_IRQ10 0x30 /* 10 */
189:
190: /***********************************
191: * ha_status error codes
192: \***********************************/
193:
194: #define UHA_NO_ERR 0x00 /* No error supposedly */
195: #define UHA_SBUS_ABORT_ERR 0x84 /* scsi bus abort error */
196: #define UHA_SBUS_TIMEOUT 0x91 /* scsi bus selection timeout */
197: #define UHA_SBUS_OVER_UNDER 0x92 /* scsi bus over/underrun */
198: #define UHA_BAD_SCSI_CMD 0x96 /* illegal scsi command */
199: #define UHA_AUTO_SENSE_ERR 0x9b /* auto request sense err */
200: #define UHA_SBUS_RES_ERR 0xa3 /* scsi bus reset error */
201: #define UHA_BAD_SG_LIST 0xff /* invalid scatter gath list */
202:
203: /**/
204:
205: struct uha_dma_seg
206: {
207: physaddr addr;
208: physlen len;
209: };
210: /**/
211:
212: struct mscp
213: {
214: unsigned char opcode:3;
215: #define U14_HAC 0x01 /*host adapter command*/
216: #define U14_TSP 0x02 /*target scsi pass through command*/
217: #define U14_SDR 0x04 /*scsi device reset*/
218: unsigned char xdir:2; /*xfer direction*/
219: #define U14_SDET 0x00 /*determined by scsi command*/
220: #define U14_SDIN 0x01 /*scsi data in*/
221: #define U14_SDOUT 0x02 /*scsi data out*/
222: #define U14_NODATA 0x03 /*no data xfer*/
223: unsigned char dcn:1; /*disable disconnect for this command*/
224: unsigned char ca:1; /*Cache control*/
225: unsigned char sgth:1; /*scatter gather flag*/
226: unsigned char target:3;
227: unsigned char chan:2; /*scsi channel (always 0 for 14f)*/
228: unsigned char lun:3;
229: physaddr data;
230: physlen datalen;
231: physaddr link;
232: unsigned char link_id;
233: unsigned char sg_num; /*number of scat gath segs */
234: /*in s-g list if sg flag is*/
235: /*set. starts at 1, 8bytes per*/
236: unsigned char senselen;
237: unsigned char cdblen;
238: unsigned char cdb[12];
239: unsigned char ha_status;
240: unsigned char targ_status;
241: physaddr sense; /* if 0 no auto sense */
242: /*-----------------end of hardware supported fields----------------*/
243: struct mscp *next; /* in free list */
244: struct scsi_xfer *xs; /* the scsi_xfer for this cmd */
245: long int delta; /* difference from previous*/
246: struct mscp *later,*sooner;
247: int flags;
248: #define MSCP_FREE 0
249: #define MSCP_ACTIVE 1
250: #define MSCP_ABORTED 2
251: struct uha_dma_seg uha_dma[UHA_NSEG];
252: struct scsi_sense_data mscp_sense;
253: };
254:
255: struct mscp *uha_soonest = (struct mscp *)0;
256: struct mscp *uha_latest = (struct mscp *)0;
257: long int uha_furtherest = 0; /* longest time in the timeout queue */
258: /**/
259:
260: struct uha_data
261: {
262: int flags;
263: #define UHA_INIT 0x01;
264: int baseport;
265: struct mscp mscps[NUM_CONCURRENT];
266: struct mscp *free_mscp;
267: int our_id; /* our scsi id */
268: int vect;
269: int dma;
270: } uha_data[NUHA];
271:
272: int uhaprobe();
273: int uha_attach();
274: int uhaintr();
275: int uha_scsi_cmd();
276: int uha_timeout();
277: int uha_abort();
278: struct mscp *cheat;
279: void uhaminphys();
280: long int uha_adapter_info();
281:
282: unsigned long int scratch;
283:
284: #ifdef MACH
285: struct isa_driver uhadriver = { uhaprobe, 0, uha_attach, "uha", 0, 0, 0};
286: int (*uhaintrs[])() = {uhaintr, 0};
287: #endif MACH
288:
289: #ifdef __386BSD__
290: struct isa_driver uhadriver = { uhaprobe, uha_attach, "uha"};
291: #endif __386BSD__
292:
293: static uha_unit = 0;
294: int uha_debug = 0;
295: #define UHA_SHOWMSCPS 0x01
296: #define UHA_SHOWINTS 0x02
297: #define UHA_SHOWCMDS 0x04
298: #define UHA_SHOWMISC 0x08
299: #define FAIL 1
300: #define SUCCESS 0
301: #define PAGESIZ 4096
302:
303: struct scsi_switch uha_switch =
304: {
305: uha_scsi_cmd,
306: uhaminphys,
307: 0,
308: 0,
309: uha_adapter_info,
310: 0,0,0
311: };
312:
313: /**/
314: /***********************************************************************\
315: * Function to send a command out through a mailbox *
316: \***********************************************************************/
317: uha_send_mbox( int unit
318: ,struct mscp *mscp)
319: {
320: int port = uha_data[unit].baseport;
321: int spincount = FUDGE(delaycount) * 1; /* 1ms should be enough */
322: int s = splbio();
323:
324: while( ((inb(port + UHA_LINT) & (UHA_LDIP))
325: != (0))
326: && (spincount--));
327: if(spincount == -1)
328: {
329: printf("uha%d: board not responding\n",unit);
330: Debugger();
331: }
332:
333: outl(port + UHA_OGM0,KVTOPHYS(mscp));
334: outb(port + UHA_LINT, (UHA_OGMINT));
335: splx(s);
336: }
337:
338: /***********************************************************************\
339: * Function to send abort to 14f *
340: \***********************************************************************/
341:
342: uha_abort( int unit
343: ,struct mscp *mscp)
344: {
345: int port = uha_data[unit].baseport;
346: int spincount = FUDGE(delaycount) * 1;
347: int abortcount = FUDGE(delaycount) * 2000;
348: int s = splbio();
349:
350: while(((inb(port + UHA_LINT) & (UHA_LDIP))
351: != (0))
352: && (spincount--));
353: if(spincount == -1);
354: {
355: printf("uha%d: board not responding\n",unit);
356: Debugger();
357: }
358:
359: outl(port + UHA_OGM0,KVTOPHYS(mscp));
360: outb(port + UHA_LINT,UHA_ABORT);
361:
362: while((abortcount--) && (!(inb(port + UHA_SINT) & UHA_ABORT_FAIL)));
363: if(abortcount == -1)
364: {
365: printf("uha%d: board not responding\n",unit);
366: Debugger();
367: }
368: if((inb(port + UHA_SINT) & 0x10) != 0)
369: {
370: outb(port + UHA_SINT,UHA_ABORT_ACK);
371: return(1);
372: }
373: else
374: {
375: outb(port + UHA_SINT,UHA_ABORT_ACK);
376: return(0);
377: }
378: }
379:
380: /***********************************************************************\
381: * Function to poll for command completion when in poll mode *
382: \***********************************************************************/
383: uha_poll(int unit ,int wait) /* in msec */
384: {
385: int port = uha_data[unit].baseport;
386: int spincount = FUDGE(delaycount) * wait; /* in msec */
387: int stport = port + UHA_SINT;
388: int start = spincount;
389:
390: retry:
391: while( (spincount--) && (!(inb(stport) & UHA_SINTP)));
392: if(spincount == -1)
393: {
394: printf("uha%d: board not responding\n",unit);
395: return(EIO);
396: }
397: if ((int)cheat != PHYSTOKV(inl(port + UHA_ICM0)))
398: {
399: printf("discarding %x ",inl(port + UHA_ICM0));
400: outb(port + UHA_SINT, UHA_ICM_ACK);
401: spinwait(50);
402: goto retry;
403: }/* don't know this will work */
404: uhaintr(unit);
405: return(0);
406: }
407:
408: /*******************************************************\
409: * Check if the device can be found at the port given *
410: * and if so, set it up ready for further work *
411: * as an argument, takes the isa_dev structure from *
412: * autoconf.c *
413: \*******************************************************/
414: uhaprobe(dev)
415: struct isa_dev *dev;
416: {
417: int unit = uha_unit;
418: dev->dev_unit = unit;
419: uha_data[unit].baseport = dev->dev_addr;
420: if(unit >= NUHA)
421: {
422: printf("uha: unit number (%d) too high\n",unit);
423: return(0);
424: }
425:
426: /*try and initialize unit at this location*/
427: if (uha_init(unit) != 0)
428: {
429: return(0);
430: }
431:
432: /* if its there put in it's interrupt and DRQ vectors */
433:
434: dev->id_irq = (1 << uha_data[unit].vect);
435: dev->id_drq = uha_data[unit].dma;
436:
437:
438: uha_unit ++;
439: return(1);
440: }
441:
442: /***********************************************\
443: * Attach all the sub-devices we can find *
444: \***********************************************/
445: uha_attach(dev)
446: struct isa_dev *dev;
447: {
448: int unit = dev->dev_unit;
449:
450:
451: #ifdef __386BSD__
452: printf("uha%d: probing for scsi devices..", unit);
453: #endif __386BSD__
454:
455: /***********************************************\
456: * ask the adapter what subunits are present *
457: \***********************************************/
458: scsi_attachdevs( unit, uha_data[unit].our_id, &uha_switch);
459:
460: #if defined(OSF)
461: uha_attached[unit]=1;
462: #endif /* defined(OSF) */
463: if(!unit) /* only one for all boards */
464: {
465: uha_timeout(0);
466: }
467: return;
468: }
469:
470: /***********************************************\
471: * Return some information to the caller about *
472: * the adapter and it's capabilities *
473: \***********************************************/
474: long int uha_adapter_info(unit)
475: int unit;
476: {
477: return(2); /* 2 outstanding requests at a time per device */
478: }
479:
480: /***********************************************\
481: * Catch an interrupt from the adaptor *
482: \***********************************************/
483: uhaintr(unit)
484: {
485: struct mscp *mscp;
486: u_char uhastat;
487: unsigned long int mboxval;
488:
489: int port = uha_data[unit].baseport;
490:
491:
492: if(scsi_debug & PRINTROUTINES)
493: printf("uhaintr ");
494:
495: #if defined(OSF)
496: if (!uha_attached[unit])
497: {
498: return(1);
499: }
500: #endif /* defined(OSF) */
501: while(inb(port + UHA_SINT) & UHA_SINTP)
502: {
503: /***********************************************\
504: * First get all the information and then *
505: * acknowlege the interrupt *
506: \***********************************************/
507: uhastat = inb(port + UHA_SINT);
508: mboxval = inl(port + UHA_ICM0);
509: outb(port + UHA_SINT,UHA_ICM_ACK);
510:
511: if(scsi_debug & TRACEINTERRUPTS)
512: printf("status = 0x%x ",uhastat);
513: /***********************************************\
514: * Process the completed operation *
515: \***********************************************/
516:
517: mscp = (struct mscp *)(PHYSTOKV(mboxval));
518:
519: if(uha_debug & UHA_SHOWCMDS )
520: {
521: uha_show_scsi_cmd(mscp->xs);
522: }
523: if((uha_debug & UHA_SHOWMSCPS) && mscp)
524: printf("<int mscp(%x)>",mscp);
525: uha_remove_timeout(mscp);
526:
527: uha_done(unit,mscp);
528: }
529: return(1);
530: }
531:
532: /***********************************************\
533: * We have a mscp which has been processed by the *
534: * adaptor, now we look to see how the operation *
535: * went. *
536: \***********************************************/
537:
538: uha_done(unit,mscp)
539: int unit;
540: struct mscp *mscp;
541: {
542: struct scsi_sense_data *s1,*s2;
543: struct scsi_xfer *xs = mscp->xs;
544:
545: if(scsi_debug & (PRINTROUTINES | TRACEINTERRUPTS))
546: printf("uha_done ");
547: /***********************************************\
548: * Otherwise, put the results of the operation *
549: * into the xfer and call whoever started it *
550: \***********************************************/
551: if ( (mscp->ha_status == UHA_NO_ERR) || (xs->flags & SCSI_ERR_OK))
552: { /* All went correctly OR errors expected */
553: xs->resid = 0;
554: xs->error = 0;
555: }
556: else
557: {
558:
559: s1 = &(mscp->mscp_sense);
560: s2 = &(xs->sense);
561:
562: if(mscp->ha_status != UHA_NO_ERR)
563: {
564: switch(mscp->ha_status)
565: {
566: case UHA_SBUS_TIMEOUT: /* No response */
567: if (uha_debug & UHA_SHOWMISC)
568: {
569: printf("timeout reported back\n");
570: }
571: xs->error = XS_TIMEOUT;
572: break;
573: case UHA_SBUS_OVER_UNDER:
574: if (uha_debug & UHA_SHOWMISC)
575: {
576: printf("scsi bus xfer over/underrun\n");
577: }
578: xs->error = XS_DRIVER_STUFFUP;
579: break;
580: case UHA_BAD_SG_LIST:
581: if (uha_debug & UHA_SHOWMISC)
582: {
583: printf("bad sg list reported back\n");
584: }
585: xs->error = XS_DRIVER_STUFFUP;
586: break;
587: default: /* Other scsi protocol messes */
588: xs->error = XS_DRIVER_STUFFUP;
589: if (uha_debug & UHA_SHOWMISC)
590: {
591: printf("unexpected ha_status: %x\n",
592: mscp->ha_status);
593: }
594: }
595:
596: }
597: else
598: {
599:
600: if (mscp->targ_status != 0)
601: /**************************************************************************\
602: * I have no information for any possible value of target status field *
603: * other than 0 means no error!! So I guess any error is unexpected in that *
604: * event!! *
605: \**************************************************************************/
606:
607: {
608: if (uha_debug & UHA_SHOWMISC)
609: {
610: printf("unexpected targ_status: %x\n",
611: mscp->targ_status);
612: }
613: xs->error = XS_DRIVER_STUFFUP;
614: }
615: }
616: }
617: done: xs->flags |= ITSDONE;
618: uha_free_mscp(unit,mscp, xs->flags);
619: if(xs->when_done)
620: (*(xs->when_done))(xs->done_arg,xs->done_arg2);
621: }
622:
623: /***********************************************\
624: * A mscp (and hence a mbx-out is put onto the *
625: * free list. *
626: \***********************************************/
627: uha_free_mscp(unit,mscp, flags)
628: struct mscp *mscp;
629: {
630: unsigned int opri;
631:
632: if(scsi_debug & PRINTROUTINES)
633: printf("mscp%d(0x%x)> ",unit,flags);
634: if (!(flags & SCSI_NOMASK))
635: opri = splbio();
636:
637: mscp->next = uha_data[unit].free_mscp;
638: uha_data[unit].free_mscp = mscp;
639: mscp->flags = MSCP_FREE;
640: /***********************************************\
641: * If there were none, wake abybody waiting for *
642: * one to come free, starting with queued entries*
643: \***********************************************/
644: if (!mscp->next) {
645: wakeup(&uha_data[unit].free_mscp);
646: }
647: if (!(flags & SCSI_NOMASK))
648: splx(opri);
649: }
650:
651: /***********************************************\
652: * Get a free mscp (and hence mbox-out entry) *
653: \***********************************************/
654: struct mscp *
655: uha_get_mscp(unit,flags)
656: {
657: unsigned opri;
658: struct mscp *rc;
659:
660: if(scsi_debug & PRINTROUTINES)
661: printf("<mscp%d(0x%x) ",unit,flags);
662: if (!(flags & SCSI_NOMASK))
663: opri = splbio();
664: /***********************************************\
665: * If we can and have to, sleep waiting for one *
666: * to come free *
667: \***********************************************/
668: while ((!(rc = uha_data[unit].free_mscp)) && (!(flags & SCSI_NOSLEEP)))
669: {
670: sleep(&uha_data[unit].free_mscp, PRIBIO);
671: }
672: if (rc)
673: {
674: uha_data[unit].free_mscp = rc->next;
675: rc->flags = MSCP_ACTIVE;
676: }
677: if (!(flags & SCSI_NOMASK))
678: splx(opri);
679: return(rc);
680: }
681:
682:
683:
684: /***********************************************\
685: * Start the board, ready for normal operation *
686: \***********************************************/
687:
688: uha_init(unit)
689: int unit;
690: {
691: unsigned char ad[4];
692: volatile unsigned char model;
693: volatile unsigned char submodel;
694: unsigned char config_reg1;
695: unsigned char config_reg2;
696: unsigned char dma_ch;
697: unsigned char irq_ch;
698: unsigned char uha_id;
699: int port = uha_data[unit].baseport;
700: int i;
701: int resetcount = FUDGE(delaycount) * 4000;
702:
703: model = inb(port + UHA_ID0);
704: submodel = inb(port + UHA_ID1);
705: if ((model != 0x56) & (submodel != 0x40))
706: { /* printf("ultrastor 14f not responding\n"); */
707: return(ENXIO); }
708:
709: printf("uha%d reading board settings, ",unit);
710:
711: config_reg1 = inb(port + UHA_CONF1);
712: config_reg2 = inb(port + UHA_CONF2);
713: dma_ch = (config_reg1 & 0xc0);
714: irq_ch = (config_reg1 & 0x30);
715: uha_id = (config_reg2 & 0x07);
716:
717: switch(dma_ch)
718: {
719: case UHA_DMA_CH5:
720: uha_data[unit].dma = 5;
721: printf("dma=5 ");
722: break;
723: case UHA_DMA_CH6:
724: uha_data[unit].dma = 6;
725: printf("dma=6 ");
726: break;
727: case UHA_DMA_CH7:
728: uha_data[unit].dma = 7;
729: printf("dma=7 ");
730: break;
731: default:
732: printf("illegal dma jumper setting\n");
733: return(EIO);
734: }
735: switch(irq_ch)
736: {
737: case UHA_IRQ10:
738: uha_data[unit].vect = 10;
739: printf("int=10 ");
740: break;
741: case UHA_IRQ11:
742: uha_data[unit].vect = 11;
743: printf("int=11 ");
744: break;
745: case UHA_IRQ14:
746: uha_data[unit].vect = 14;
747: printf("int=14 ");
748: break;
749: case UHA_IRQ15:
750: uha_data[unit].vect = 15;
751: printf("int=15 ");
752: break;
753: default:
754: printf("illegal int jumper setting\n");
755: return(EIO);
756: }
757: /* who are we on the scsi bus */
758: printf("id=%x\n",uha_id);
759: uha_data[unit].our_id = uha_id;
760:
761:
762: /***********************************************\
763: * link up all our MSCPs into a free list *
764: \***********************************************/
765: for (i=0; i < NUM_CONCURRENT; i++)
766: {
767: uha_data[unit].mscps[i].next = uha_data[unit].free_mscp;
768: uha_data[unit].free_mscp = &uha_data[unit].mscps[i];
769: uha_data[unit].free_mscp->flags = MSCP_FREE;
770: }
771:
772: /***********************************************\
773: * Note that we are going and return (to probe) *
774: \***********************************************/
775: outb(port + UHA_LINT, UHA_ASRST);
776: while( (resetcount--) && (!(inb(port + UHA_LINT))));
777: if(resetcount == -1)
778: {
779: printf("uha%d: board timed out during reset\n",unit);
780: return(ENXIO);
781: }
782:
783: outb(port + UHA_SMASK, 0x81); /* make sure interrupts are enabled */
784: uha_data[unit].flags |= UHA_INIT;
785: return(0);
786: }
787:
788:
789:
790: #ifndef min
791: #define min(x,y) (x < y ? x : y)
792: #endif min
793:
794:
795: void uhaminphys(bp)
796: struct buf *bp;
797: {
798: #ifdef MACH
799: #if !defined(OSF)
800: bp->b_flags |= B_NPAGES; /* can support scat/gather */
801: #endif /* defined(OSF) */
802: #endif MACH
803: if(bp->b_bcount > ((UHA_NSEG-1) * PAGESIZ))
804: {
805: bp->b_bcount = ((UHA_NSEG-1) * PAGESIZ);
806: }
807: }
808:
809: /***********************************************\
810: * start a scsi operation given the command and *
811: * the data address. Also needs the unit, target *
812: * and lu *
813: \***********************************************/
814: int uha_scsi_cmd(xs)
815: struct scsi_xfer *xs;
816: {
817: struct scsi_sense_data *s1,*s2;
818: struct mscp *mscp;
819: struct uha_dma_seg *sg;
820: int seg; /* scatter gather seg being worked on */
821: int i = 0;
822: int rc = 0;
823: int thiskv;
824: unsigned long int thisphys,nextphys;
825: int unit =xs->adapter;
826: int bytes_this_seg,bytes_this_page,datalen,flags;
827: struct iovec *iovp;
828: int s;
829: unsigned int stat;
830: int port = uha_data[unit].baseport;
831: unsigned long int templen;
832:
833:
834: if(scsi_debug & PRINTROUTINES)
835: printf("uha_scsi_cmd ");
836: /***********************************************\
837: * get a mscp (mbox-out) to use. If the transfer *
838: * is from a buf (possibly from interrupt time) *
839: * then we can't allow it to sleep *
840: \***********************************************/
841: flags = xs->flags;
842: if(xs->bp) flags |= (SCSI_NOSLEEP); /* just to be sure */
843: if(flags & ITSDONE)
844: {
845: printf("Already done?");
846: xs->flags &= ~ITSDONE;
847: }
848: if(!(flags & INUSE))
849: {
850: printf("Not in use?");
851: xs->flags |= INUSE;
852: }
853: if (!(mscp = uha_get_mscp(unit,flags)))
854: {
855: xs->error = XS_DRIVER_STUFFUP;
856: return(TRY_AGAIN_LATER);
857: }
858:
859: cheat = mscp;
860: if(uha_debug & UHA_SHOWMSCPS)
861: printf("<start mscp(%x)>",mscp);
862: if(scsi_debug & SHOWCOMMANDS)
863: {
864: uha_show_scsi_cmd(xs);
865: }
866: mscp->xs = xs;
867: /***********************************************\
868: * Put all the arguments for the xfer in the mscp *
869: \***********************************************/
870:
871: if (flags & SCSI_RESET)
872: {
873: mscp->opcode = 0x04;
874: mscp->ca = 0x01;
875: }
876: else
877: {
878: mscp->opcode = 0x02;
879: mscp->ca = 0x01;
880: }
881:
882: if (flags & SCSI_DATA_IN)
883: {
884: mscp->xdir = 0x01;
885: }
886: if (flags & SCSI_DATA_OUT)
887: {
888: mscp->xdir = 0x02;
889: }
890:
891: if (xs->lu != 0)
892: {
893: xs->error = XS_DRIVER_STUFFUP;
894: uha_free_mscp(unit,mscp,flags);
895: return(HAD_ERROR);
896: }
897:
898: mscp->dcn = 0x00;
899: mscp->chan = 0x00;
900: mscp->target = xs->targ;
901: mscp->lun = xs->lu;
902: mscp->link.addr[0] = 0x00;
903: mscp->link.addr[1] = 0x00;
904: mscp->link.addr[2] = 0x00;
905: mscp->link.addr[3] = 0x00;
906: mscp->link_id = 0x00;
907: mscp->cdblen = xs->cmdlen;
908: scratch = KVTOPHYS(&(mscp->mscp_sense));
909: mscp->sense.addr[0] = (scratch & 0xff);
910: mscp->sense.addr[1] = ((scratch >> 8) & 0xff);
911: mscp->sense.addr[2] = ((scratch >> 16) & 0xff);
912: mscp->sense.addr[3] = ((scratch >> 24) & 0xff);
913: mscp->senselen = sizeof(mscp->mscp_sense);
914: mscp->ha_status = 0x00;
915: mscp->targ_status = 0x00;
916:
917: if(xs->datalen)
918: { /* should use S/G only if not zero length */
919: scratch = KVTOPHYS(mscp->uha_dma);
920: mscp->data.addr[0] = (scratch & 0xff);
921: mscp->data.addr[1] = ((scratch >> 8) & 0xff);
922: mscp->data.addr[2] = ((scratch >> 16) & 0xff);
923: mscp->data.addr[3] = ((scratch >> 24) & 0xff);
924: sg = mscp->uha_dma ;
925: seg = 0;
926: mscp->sgth = 0x01;
927:
928: if(flags & SCSI_DATA_UIO)
929: {
930: iovp = ((struct uio *)xs->data)->uio_iov;
931: datalen = ((struct uio *)xs->data)->uio_iovcnt;
932: xs->datalen = 0;
933: while ((datalen) && (seg < UHA_NSEG))
934: {
935: scratch = (unsigned long)iovp->iov_base;
936: sg->addr.addr[0] = (scratch & 0xff);
937: sg->addr.addr[1] = ((scratch >> 8) & 0xff);
938: sg->addr.addr[2] = ((scratch >> 16) & 0xff);
939: sg->addr.addr[3] = ((scratch >> 24) & 0xff);
940: xs->datalen += *(unsigned long *)sg->len.len = iovp->iov_len;
941: if(scsi_debug & SHOWSCATGATH)
942: printf("(0x%x@0x%x)"
943: ,iovp->iov_len
944: ,iovp->iov_base);
945: sg++;
946: iovp++;
947: seg++;
948: datalen--;
949: }
950: }
951: else
952: {
953: /***********************************************\
954: * Set up the scatter gather block *
955: \***********************************************/
956:
957: if(scsi_debug & SHOWSCATGATH)
958: printf("%d @0x%x:- ",xs->datalen,xs->data);
959: datalen = xs->datalen;
960: thiskv = (int)xs->data;
961: thisphys = KVTOPHYS(thiskv);
962: templen = 0;
963:
964: while ((datalen) && (seg < UHA_NSEG))
965: {
966: bytes_this_seg = 0;
967:
968: /* put in the base address */
969: sg->addr.addr[0] = (thisphys & 0xff);
970: sg->addr.addr[1] = ((thisphys >> 8) & 0xff);
971: sg->addr.addr[2] = ((thisphys >> 16) & 0xff);
972: sg->addr.addr[3] = ((thisphys >> 24) & 0xff);
973:
974: if(scsi_debug & SHOWSCATGATH)
975: printf("0x%x",thisphys);
976:
977: /* do it at least once */
978: nextphys = thisphys;
979: while ((datalen) && (thisphys == nextphys))
980: /*********************************************\
981: * This page is contiguous (physically) with *
982: * the the last, just extend the length *
983: \*********************************************/
984: {
985: /* how far to the end of the page */
986: nextphys = (thisphys & (~(PAGESIZ - 1)))
987: + PAGESIZ;
988: bytes_this_page = nextphys - thisphys;
989: /**** or the data ****/
990: bytes_this_page = min(bytes_this_page
991: ,datalen);
992: bytes_this_seg += bytes_this_page;
993: datalen -= bytes_this_page;
994:
995: /* get more ready for the next page */
996: thiskv = (thiskv & (~(PAGESIZ - 1)))
997: + PAGESIZ;
998: if(datalen)
999: thisphys = KVTOPHYS(thiskv);
1000: }
1001: /********************************************\
1002: * next page isn't contiguous, finish the seg *
1003: \********************************************/
1004: if(scsi_debug & SHOWSCATGATH)
1005: printf("(0x%x)",bytes_this_seg);
1006: sg->len.len[0] = (bytes_this_seg & 0xff);
1007: sg->len.len[1] = ((bytes_this_seg >> 8) & 0xff);
1008: sg->len.len[2] = ((bytes_this_seg >> 16) & 0xff);
1009: sg->len.len[3] = ((bytes_this_seg >> 24) & 0xff);
1010: templen += bytes_this_seg;
1011: sg++;
1012: seg++;
1013: }
1014: } /*end of iov/kv decision */
1015: mscp->datalen.len[0] = (templen & 0xff);
1016: mscp->datalen.len[1] = ((templen >> 8) & 0xff);
1017: mscp->datalen.len[2] = ((templen >> 16) & 0xff);
1018: mscp->datalen.len[3] = ((templen >> 24) & 0xff);
1019: mscp->sg_num = seg;
1020:
1021: if(scsi_debug & SHOWSCATGATH)
1022: printf("\n");
1023: if (datalen)
1024: { /* there's still data, must have run out of segs! */
1025: printf("uha_scsi_cmd%d: more than %d DMA segs\n",
1026: unit,UHA_NSEG);
1027: xs->error = XS_DRIVER_STUFFUP;
1028: uha_free_mscp(unit,mscp,flags);
1029: return(HAD_ERROR);
1030: }
1031:
1032: }
1033: else
1034: { /* No data xfer, use non S/G values */
1035: mscp->data.addr[0] = 0x00;
1036: mscp->data.addr[1] = 0x00;
1037: mscp->data.addr[2] = 0x00;
1038: mscp->data.addr[3] = 0x00;
1039: mscp->datalen.len[0] = 0x00;
1040: mscp->datalen.len[1] = 0x00;
1041: mscp->datalen.len[2] = 0x00;
1042: mscp->datalen.len[3] = 0x00;
1043: mscp->xdir = 0x03;
1044: mscp->sgth = 0x00;
1045: mscp->sg_num = 0x00;
1046: }
1047:
1048: /***********************************************\
1049: * Put the scsi command in the mscp and start it *
1050: \***********************************************/
1051: bcopy(xs->cmd, mscp->cdb, xs->cmdlen);
1052:
1053: /***********************************************\
1054: * Usually return SUCCESSFULLY QUEUED *
1055: \***********************************************/
1056: if (!(flags & SCSI_NOMASK))
1057: {
1058: s = splbio();
1059: uha_send_mbox(unit,mscp);
1060: uha_add_timeout(mscp,xs->timeout);
1061: splx(s);
1062: if(scsi_debug & TRACEINTERRUPTS)
1063: printf("cmd_sent ");
1064: return(SUCCESSFULLY_QUEUED);
1065: }
1066: /***********************************************\
1067: * If we can't use interrupts, poll on completion*
1068: \***********************************************/
1069: uha_send_mbox(unit,mscp);
1070: if(scsi_debug & TRACEINTERRUPTS)
1071: printf("cmd_wait ");
1072: do
1073: {
1074: if(uha_poll(unit,xs->timeout))
1075: {
1076: if (!(xs->flags & SCSI_SILENT)) printf("cmd fail\n");
1077: if(!(uha_abort(unit,mscp)))
1078: {
1079: printf("abort failed in wait\n");
1080: uha_free_mscp(unit,mscp,flags);
1081: }
1082: xs->error = XS_DRIVER_STUFFUP;
1083: splx(s);
1084: return(HAD_ERROR);
1085: }
1086: } while (!(xs->flags & ITSDONE));/* something (?) else finished */
1087: splx(s);
1088: scsi_debug = 0;uha_debug = 0;
1089: if(xs->error)
1090: {
1091: return(HAD_ERROR);
1092: }
1093: return(COMPLETE);
1094: }
1095:
1096: /*
1097: * +----------+ +----------+ +----------+
1098: * uha_soonest--->| later |--->| later|--->| later|--->0
1099: * | [Delta] | | [Delta] | | [Delta] |
1100: * 0<---|sooner |<---|sooner |<---|sooner |<---uha_latest
1101: * +----------+ +----------+ +----------+
1102: *
1103: * uha_furtherest = sum(Delta[1..n])
1104: */
1105: uha_add_timeout(mscp,time)
1106: struct mscp *mscp;
1107: int time;
1108: {
1109: int timeprev;
1110: struct mscp *prev;
1111: int s = splbio();
1112:
1113: if(prev = uha_latest) /* yes, an assign */
1114: {
1115: timeprev = uha_furtherest;
1116: }
1117: else
1118: {
1119: timeprev = 0;
1120: }
1121: while(prev && (timeprev > time))
1122: {
1123: timeprev -= prev->delta;
1124: prev = prev->sooner;
1125: }
1126: if(prev)
1127: {
1128: mscp->delta = time - timeprev;
1129: if( mscp->later = prev->later) /* yes an assign */
1130: {
1131: mscp->later->sooner = mscp;
1132: mscp->later->delta -= mscp->delta;
1133: }
1134: else
1135: {
1136: uha_furtherest = time;
1137: uha_latest = mscp;
1138: }
1139: mscp->sooner = prev;
1140: prev->later = mscp;
1141: }
1142: else
1143: {
1144: if( mscp->later = uha_soonest) /* yes, an assign*/
1145: {
1146: mscp->later->sooner = mscp;
1147: mscp->later->delta -= time;
1148: }
1149: else
1150: {
1151: uha_furtherest = time;
1152: uha_latest = mscp;
1153: }
1154: mscp->delta = time;
1155: mscp->sooner = (struct mscp *)0;
1156: uha_soonest = mscp;
1157: }
1158: splx(s);
1159: }
1160:
1161: uha_remove_timeout(mscp)
1162: struct mscp *mscp;
1163: {
1164: int s = splbio();
1165:
1166: if(mscp->sooner)
1167: {
1168: mscp->sooner->later = mscp->later;
1169: }
1170: else
1171: {
1172: uha_soonest = mscp->later;
1173: }
1174: if(mscp->later)
1175: {
1176: mscp->later->sooner = mscp->sooner;
1177: mscp->later->delta += mscp->delta;
1178: }
1179: else
1180: {
1181: uha_latest = mscp->sooner;
1182: uha_furtherest -= mscp->delta;
1183: }
1184: mscp->sooner = mscp->later = (struct mscp *)0;
1185: splx(s);
1186: }
1187:
1188:
1189: extern int hz;
1190: #define ONETICK 500 /* milliseconds */
1191: #define SLEEPTIME ((hz * 1000) / ONETICK)
1192: uha_timeout(arg)
1193: int arg;
1194: {
1195: struct mscp *mscp;
1196: int unit;
1197: int s = splbio();
1198: unsigned int stat;
1199: int port = uha_data[unit].baseport;
1200:
1201: while( mscp = uha_soonest )
1202: {
1203: if(mscp->delta <= ONETICK)
1204: /***********************************************\
1205: * It has timed out, we need to do some work *
1206: \***********************************************/
1207: {
1208: unit = mscp->xs->adapter;
1209: printf("uha%d:%d device timed out\n",unit
1210: ,mscp->xs->targ);
1211: if(uha_debug & UHA_SHOWMSCPS)
1212: uha_print_active_mscp();
1213:
1214: /***************************************\
1215: * Unlink it from the queue *
1216: \***************************************/
1217: uha_remove_timeout(mscp);
1218:
1219: if((uha_abort(unit,mscp) !=1) || (mscp->flags = MSCP_ABORTED))
1220: {
1221: printf("AGAIN");
1222: mscp->xs->retries = 0; /* I MEAN IT ! */
1223: uha_done(unit,mscp,FAIL);
1224: }
1225: else /* abort the operation that has timed out */
1226: {
1227: printf("\n");
1228: uha_add_timeout(mscp,2000 + ONETICK);
1229: mscp->flags = MSCP_ABORTED;
1230: }
1231: }
1232: else
1233: /***********************************************\
1234: * It has not timed out, adjust and leave *
1235: \***********************************************/
1236: {
1237: mscp->delta -= ONETICK;
1238: uha_furtherest -= ONETICK;
1239: break;
1240: }
1241: }
1242: splx(s);
1243: timeout(uha_timeout,arg,SLEEPTIME);
1244: }
1245:
1246: uha_show_scsi_cmd(struct scsi_xfer *xs)
1247: {
1248: u_char *b = (u_char *)xs->cmd;
1249: int i = 0;
1250: if(!(xs->flags & SCSI_RESET))
1251: {
1252: printf("uha%d:%d:%d-"
1253: ,xs->adapter
1254: ,xs->targ
1255: ,xs->lu);
1256: while(i < xs->cmdlen )
1257: {
1258: if(i) printf(",");
1259: printf("%x",b[i++]);
1260: }
1261: printf("-\n");
1262: }
1263: else
1264: {
1265: printf("uha%d:%d:%d-RESET-\n"
1266: ,xs->adapter
1267: ,xs->targ
1268: ,xs->lu
1269: );
1270: }
1271: }
1272: uha_print_mscp(mscp)
1273: struct mscp *mscp;
1274: {
1275: printf("mscp:%x op:%x cmdlen:%d senlen:%d\n"
1276: ,mscp
1277: ,mscp->opcode
1278: ,mscp->cdblen
1279: ,mscp->senselen);
1280: printf(" sg:%d sgnum:%x datlen:%d hstat:%x tstat:%x delta:%d flags:%x\n"
1281: ,mscp->sgth
1282: ,mscp->sg_num
1283: ,mscp->datalen
1284: ,mscp->ha_status
1285: ,mscp->targ_status
1286: ,mscp->delta
1287: ,mscp->flags);
1288: uha_show_scsi_cmd(mscp->xs);
1289: }
1290:
1291: uha_print_active_mscp()
1292: {
1293: struct mscp *mscp;
1294: mscp = uha_soonest;
1295:
1296: while(mscp)
1297: {
1298: uha_print_mscp(mscp);
1299: mscp = mscp->later;
1300: }
1301: printf("Furtherest = %d\n",uha_furtherest);
1302: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.