|
|
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: * commenced: Sun Sep 27 18:14:01 PDT 1992
23: */
24:
25: #include <sys/types.h>
26: #include <ahb.h>
27:
28: #include <sys/param.h>
29: #include <sys/systm.h>
30: #include <sys/errno.h>
31: #include <sys/ioctl.h>
32: #include <sys/buf.h>
33: #include <sys/proc.h>
34: #include <sys/user.h>
35:
36: #ifdef MACH /* EITHER CMU OR OSF */
37: #include <i386/ipl.h>
38: #include <i386at/scsi.h>
39: #include <i386at/scsiconf.h>
40:
41: #ifdef OSF /* OSF ONLY */
42: #include <sys/table.h>
43: #include <i386/handler.h>
44: #include <i386/dispatcher.h>
45: #include <i386/AT386/atbus.h>
46:
47: #else OSF /* CMU ONLY */
48: #include <i386at/atbus.h>
49: #include <i386/pio.h>
50: #endif OSF
51: #endif MACH /* end of MACH specific */
52:
53: #ifdef __386BSD__ /* 386BSD specific */
54: #define isa_dev isa_device
55: #define dev_unit id_unit
56: #define dev_addr id_iobase
57:
58: #include <i386/include/pio.h>
59: #include <i386/isa/isa_device.h>
60: #include <scsi/scsi_all.h>
61: #include <scsi/scsiconf.h>
62: #endif __386BSD__
63:
64: /**/
65:
66: #ifdef __386BSD__
67: #ifdef DDB
68: int Debugger();
69: #else
70: #define Debugger() panic("should call debugger here (adaptec.c)")
71: #endif /*DDB*/
72: #endif __386BSD__
73:
74: #ifdef MACH
75: int Debugger();
76: #endif MACH
77:
78: typedef unsigned long int physaddr;
79:
80: #ifdef MACH
81: extern physaddr kvtophys();
82: #define PHYSTOKV(x) phystokv(x)
83: #define KVTOPHYS(x) kvtophys(x)
84: #endif MACH
85:
86: #ifdef __386BSD__
87: #define PHYSTOKV(x) (x | 0xFE000000)
88: #define KVTOPHYS(x) vtophys(x)
89: #endif __386BSD__
90:
91: extern int delaycount; /* from clock setup code */
92: #define NUM_CONCURRENT 16 /* number of concurrent ops per board */
93: #define AHB_NSEG 33 /* number of dma segments supported */
94: #define FUDGE(X) (X>>1) /* our loops are slower than spinwait() */
95: /**/
96: /***********************************************************************\
97: * AHA1740 standard EISA Host ID regs (Offset from slot base) *
98: \***********************************************************************/
99: #define HID0 0xC80 /* 0,1: msb of ID2, 3-7: ID1 */
100: #define HID1 0xC81 /* 0-4: ID3, 4-7: LSB ID2 */
101: #define HID2 0xC82 /* product, 0=174[20] 1 = 1744 */
102: #define HID3 0xC83 /* firmware revision */
103:
104: #define CHAR1(B1,B2) (((B1>>2) & 0x1F) | '@')
105: #define CHAR2(B1,B2) (((B1<<3) & 0x18) | ((B2>>5) & 0x7)|'@')
106: #define CHAR3(B1,B2) ((B2 & 0x1F) | '@')
107:
108: /* AHA1740 EISA board control registers (Offset from slot base) */
109: #define EBCTRL 0xC84
110: #define CDEN 0x01
111: /***********************************************************************\
112: * AHA1740 EISA board mode registers (Offset from slot base) *
113: \***********************************************************************/
114: #define PORTADDR 0xCC0
115: #define PORTADDR_ENHANCED 0x80
116: #define BIOSADDR 0xCC1
117: #define INTDEF 0xCC2
118: #define SCSIDEF 0xCC3
119: #define BUSDEF 0xCC4
120: #define RESV0 0xCC5
121: #define RESV1 0xCC6
122: #define RESV2 0xCC7
123: /**** bit definitions for INTDEF ****/
124: #define INT9 0x00
125: #define INT10 0x01
126: #define INT11 0x02
127: #define INT12 0x03
128: #define INT14 0x05
129: #define INT15 0x06
130: #define INTHIGH 0x08 /* int high=ACTIVE (else edge) */
131: #define INTEN 0x10
132: /**** bit definitions for SCSIDEF ****/
133: #define HSCSIID 0x0F /* our SCSI ID */
134: #define RSTPWR 0x10 /* reset scsi bus on power up or reset */
135: /**** bit definitions for BUSDEF ****/
136: #define B0uS 0x00 /* give up bus immediatly */
137: #define B4uS 0x01 /* delay 4uSec. */
138: #define B8uS 0x02
139: /***********************************************************************\
140: * AHA1740 ENHANCED mode mailbox control regs (Offset from slot base) *
141: \***********************************************************************/
142: #define MBOXOUT0 0xCD0
143: #define MBOXOUT1 0xCD1
144: #define MBOXOUT2 0xCD2
145: #define MBOXOUT3 0xCD3
146:
147: #define ATTN 0xCD4
148: #define G2CNTRL 0xCD5
149: #define G2INTST 0xCD6
150: #define G2STAT 0xCD7
151:
152: #define MBOXIN0 0xCD8
153: #define MBOXIN1 0xCD9
154: #define MBOXIN2 0xCDA
155: #define MBOXIN3 0xCDB
156:
157: #define G2STAT2 0xCDC
158:
159: /*******************************************************\
160: * Bit definitions for the 5 control/status registers *
161: \*******************************************************/
162: #define ATTN_TARGET 0x0F
163: #define ATTN_OPCODE 0xF0
164: #define OP_IMMED 0x10
165: #define AHB_TARG_RESET 0x80
166: #define OP_START_ECB 0x40
167: #define OP_ABORT_ECB 0x50
168:
169: #define G2CNTRL_SET_HOST_READY 0x20
170: #define G2CNTRL_CLEAR_EISA_INT 0x40
171: #define G2CNTRL_HARD_RESET 0x80
172:
173: #define G2INTST_TARGET 0x0F
174: #define G2INTST_INT_STAT 0xF0
175: #define AHB_ECB_OK 0x10
176: #define AHB_ECB_RECOVERED 0x50
177: #define AHB_HW_ERR 0x70
178: #define AHB_IMMED_OK 0xA0
179: #define AHB_ECB_ERR 0xC0
180: #define AHB_ASN 0xD0 /* for target mode */
181: #define AHB_IMMED_ERR 0xE0
182:
183: #define G2STAT_BUSY 0x01
184: #define G2STAT_INT_PEND 0x02
185: #define G2STAT_MBOX_EMPTY 0x04
186:
187: #define G2STAT2_HOST_READY 0x01
188: /**/
189:
190: struct ahb_dma_seg
191: {
192: physaddr addr;
193: long len;
194: };
195:
196: struct ahb_ecb_status
197: {
198: u_short status;
199: # define ST_DON 0x0001
200: # define ST_DU 0x0002
201: # define ST_QF 0x0008
202: # define ST_SC 0x0010
203: # define ST_DO 0x0020
204: # define ST_CH 0x0040
205: # define ST_INT 0x0080
206: # define ST_ASA 0x0100
207: # define ST_SNS 0x0200
208: # define ST_INI 0x0800
209: # define ST_ME 0x1000
210: # define ST_ECA 0x4000
211: u_char ha_status;
212: # define HS_OK 0x00
213: # define HS_CMD_ABORTED_HOST 0x04
214: # define HS_CMD_ABORTED_ADAPTER 0x05
215: # define HS_TIMED_OUT 0x11
216: # define HS_HARDWARE_ERR 0x20
217: # define HS_SCSI_RESET_ADAPTER 0x22
218: # define HS_SCSI_RESET_INCOMING 0x23
219: u_char targ_status;
220: # define TS_OK 0x00
221: # define TS_CHECK_CONDITION 0x02
222: # define TS_BUSY 0x08
223: u_long resid_count;
224: u_long resid_addr;
225: u_short addit_status;
226: u_char sense_len;
227: u_char unused[9];
228: u_char cdb[6];
229: };
230:
231: /**/
232:
233: struct ecb
234: {
235: u_char opcode;
236: # define ECB_SCSI_OP 0x01
237: u_char :4;
238: u_char options:3;
239: u_char :1;
240: short opt1;
241: # define ECB_CNE 0x0001
242: # define ECB_DI 0x0080
243: # define ECB_SES 0x0400
244: # define ECB_S_G 0x1000
245: # define ECB_DSB 0x4000
246: # define ECB_ARS 0x8000
247: short opt2;
248: # define ECB_LUN 0x0007
249: # define ECB_TAG 0x0008
250: # define ECB_TT 0x0030
251: # define ECB_ND 0x0040
252: # define ECB_DAT 0x0100
253: # define ECB_DIR 0x0200
254: # define ECB_ST 0x0400
255: # define ECB_CHK 0x0800
256: # define ECB_REC 0x4000
257: # define ECB_NRB 0x8000
258: u_short unused1;
259: physaddr data;
260: u_long datalen;
261: physaddr status;
262: physaddr chain;
263: short unused2;
264: short unused3;
265: physaddr sense;
266: u_char senselen;
267: u_char cdblen;
268: short cksum;
269: u_char cdb[12];
270: /*-----------------end of hardware supported fields----------------*/
271: struct ecb *next; /* in free list */
272: struct scsi_xfer *xs; /* the scsi_xfer for this cmd */
273: long int delta; /* difference from previous*/
274: struct ecb *later,*sooner;
275: int flags;
276: #define ECB_FREE 0
277: #define ECB_ACTIVE 1
278: #define ECB_ABORTED 2
279: #define ECB_IMMED 4
280: #define ECB_IMMED_FAIL 8
281: struct ahb_dma_seg ahb_dma[AHB_NSEG];
282: struct ahb_ecb_status ecb_status;
283: struct scsi_sense_data ecb_sense;
284: };
285:
286: struct ecb *ahb_soonest = (struct ecb *)0;
287: struct ecb *ahb_latest = (struct ecb *)0;
288: long int ahb_furtherest = 0; /* longest time in the timeout queue */
289: /**/
290:
291: struct ahb_data
292: {
293: int flags;
294: #define AHB_INIT 0x01;
295: int baseport;
296: struct ecb ecbs[NUM_CONCURRENT];
297: struct ecb *free_ecb;
298: int our_id; /* our scsi id */
299: int vect;
300: struct ecb *immed_ecb; /* an outstanding immediete command */
301: } ahb_data[NAHB];
302:
303: int ahbprobe();
304: int ahb_attach();
305: int ahbintr();
306: int ahb_scsi_cmd();
307: int ahb_timeout();
308: struct ecb *cheat;
309: void ahbminphys();
310: long int ahb_adapter_info();
311:
312: #ifdef MACH
313: struct isa_driver ahbdriver = { ahbprobe, 0, ahb_attach, "ahb", 0, 0, 0};
314: int (*ahbintrs[])() = {ahbintr, 0};
315: #endif MACH
316:
317: #ifdef __386BSD__
318: struct isa_driver ahbdriver = { ahbprobe, ahb_attach, "ahb"};
319: #endif __386BSD__
320:
321: #define MAX_SLOTS 8
322: static ahb_slot = 0; /* slot last board was found in */
323: static ahb_unit = 0;
324: int ahb_debug = 0;
325: #define AHB_SHOWECBS 0x01
326: #define AHB_SHOWINTS 0x02
327: #define AHB_SHOWCMDS 0x04
328: #define AHB_SHOWMISC 0x08
329: #define FAIL 1
330: #define SUCCESS 0
331: #define PAGESIZ 4096
332:
333: struct scsi_switch ahb_switch =
334: {
335: ahb_scsi_cmd,
336: ahbminphys,
337: 0,
338: 0,
339: ahb_adapter_info,
340: 0,0,0
341: };
342:
343: /**/
344: /***********************************************************************\
345: * Function to send a command out through a mailbox *
346: \***********************************************************************/
347: ahb_send_mbox( int unit
348: ,int opcode
349: ,int target
350: ,struct ecb *ecb)
351: {
352: int port = ahb_data[unit].baseport;
353: int spincount = FUDGE(delaycount) * 1; /* 1ms should be enough */
354: int s = splbio();
355: int stport = port + G2STAT;
356:
357: while( ((inb(stport) & (G2STAT_BUSY | G2STAT_MBOX_EMPTY))
358: != (G2STAT_MBOX_EMPTY))
359: && (spincount--));
360: if(spincount == -1)
361: {
362: printf("ahb%d: board not responding\n",unit);
363: Debugger();
364: }
365:
366: outl(port + MBOXOUT0,KVTOPHYS(ecb)); /* don't know this will work */
367: outb(port + ATTN, opcode|target);
368:
369: splx(s);
370: }
371:
372: /***********************************************************************\
373: * Function to poll for command completion when in poll mode *
374: \***********************************************************************/
375: ahb_poll(int unit ,int wait) /* in msec */
376: {
377: int port = ahb_data[unit].baseport;
378: int spincount = FUDGE(delaycount) * wait; /* in msec */
379: int stport = port + G2STAT;
380: int start = spincount;
381:
382: retry:
383: while( (spincount--) && (!(inb(stport) & G2STAT_INT_PEND)));
384: if(spincount == -1)
385: {
386: printf("ahb%d: board not responding\n",unit);
387: return(EIO);
388: }
389: if ((int)cheat != PHYSTOKV(inl(port + MBOXIN0)))
390: {
391: printf("discarding %x ",inl(port + MBOXIN0));
392: outb(port + G2CNTRL, G2CNTRL_CLEAR_EISA_INT);
393: spinwait(50);
394: goto retry;
395: }/* don't know this will work */
396: ahbintr(unit);
397: return(0);
398: }
399: /***********************************************************************\
400: * Function to send an immediate type command to the adapter *
401: \***********************************************************************/
402: ahb_send_immed( int unit
403: ,int target
404: ,u_long cmd)
405: {
406: int port = ahb_data[unit].baseport;
407: int spincount = FUDGE(delaycount) * 1; /* 1ms should be enough */
408: int s = splbio();
409: int stport = port + G2STAT;
410:
411: while( ((inb(stport) & (G2STAT_BUSY | G2STAT_MBOX_EMPTY))
412: != (G2STAT_MBOX_EMPTY))
413: && (spincount--));
414: if(spincount == -1)
415: {
416: printf("ahb%d: board not responding\n",unit);
417: Debugger();
418: }
419:
420: outl(port + MBOXOUT0,cmd); /* don't know this will work */
421: outb(port + G2CNTRL, G2CNTRL_SET_HOST_READY);
422: outb(port + ATTN, OP_IMMED | target);
423: splx(s);
424: }
425:
426: /**/
427:
428: /*******************************************************\
429: * Check the slots looking for a board we recognise *
430: * If we find one, note it's address (slot) and call *
431: * the actual probe routine to check it out. *
432: \*******************************************************/
433: ahbprobe(dev)
434: struct isa_dev *dev;
435: {
436: int port;
437: u_char byte1,byte2,byte3;
438: ahb_slot++;
439: while (ahb_slot<8)
440: {
441: port = 0x1000 * ahb_slot;
442: byte1 = inb(port + HID0);
443: byte2 = inb(port + HID1);
444: byte3 = inb(port + HID2);
445: if(byte1 == 0xff)
446: {
447: ahb_slot++;
448: continue;
449: }
450: if ((CHAR1(byte1,byte2) == 'A')
451: && (CHAR2(byte1,byte2) == 'D')
452: && (CHAR3(byte1,byte2) == 'P')
453: && ((byte3 == 0 ) || (byte3 == 1)))
454: {
455: dev->dev_addr = port;
456: return(ahbprobe1(dev) ? 0x1000 : 0);
457: }
458: ahb_slot++;
459: }
460: return(0);
461: }
462: /*******************************************************\
463: * Check if the device can be found at the port given *
464: * and if so, set it up ready for further work *
465: * as an argument, takes the isa_dev structure from *
466: * autoconf.c *
467: \*******************************************************/
468: ahbprobe1(dev)
469: struct isa_dev *dev;
470: {
471: /***********************************************\
472: * find unit and check we have that many defined *
473: \***********************************************/
474: int unit = ahb_unit;
475: #if defined(OSF)
476: static ihandler_t ahb_handler[NAHB];
477: static ihandler_id_t *ahb_handler_id[NAHB];
478: register ihandler_t *chp = &ahb_handler[unit];;
479: #endif /* defined(OSF) */
480:
481: dev->dev_unit = unit;
482: ahb_data[unit].baseport = dev->dev_addr;
483: if(unit >= NAHB)
484: {
485: printf("ahb: unit number (%d) too high\n",unit);
486: return(0);
487: }
488: /***********************************************\
489: * Try initialise a unit at this location *
490: * sets up dma and bus speed, loads ahb_data[unit].vect*
491: \***********************************************/
492: if (ahb_init(unit) != 0)
493: {
494: return(0);
495: }
496:
497: /***********************************************\
498: * If it's there, put in it's interrupt vectors *
499: \***********************************************/
500: #ifdef MACH
501: #if defined(OSF) /* OSF */
502: chp->ih_level = dev->dev_pic;
503: chp->ih_handler = dev->dev_intr[0];
504: chp->ih_resolver = i386_resolver;
505: chp->ih_rdev = dev;
506: chp->ih_stats.intr_type = INTR_DEVICE;
507: chp->ih_stats.intr_cnt = 0;
508: chp->ih_hparam[0].intparam = unit;
509: if ((ahb_handler_id[unit] = handler_add(chp)) != NULL)
510: handler_enable(ahb_handler_id[unit]);
511: else
512: panic("Unable to add ahb interrupt handler");
513: #else /* CMU */
514: dev->dev_pic = ahb_data[unit].vect;
515: take_dev_irq(dev);
516: #endif /* !defined(OSF) */
517: printf("port=%x spl=%d\n", dev->dev_addr, dev->dev_spl);
518: #endif MACH
519: #ifdef __386BSD__ /* 386BSD */
520: dev->id_irq = (1 << ahb_data[unit].vect);
521: dev->id_drq = -1; /* use EISA dma */
522: printf("\n **");
523: #endif __386BSD__
524:
525: ahb_unit++;
526: return(1);
527: }
528:
529: /***********************************************\
530: * Attach all the sub-devices we can find *
531: \***********************************************/
532: ahb_attach(dev)
533: struct isa_dev *dev;
534: {
535: int unit = dev->dev_unit;
536:
537:
538: #ifdef __386BSD__
539: printf("ahb%d: probing for scsi devices..\n", unit);
540: #endif __386BSD__
541:
542: /***********************************************\
543: * ask the adapter what subunits are present *
544: \***********************************************/
545: scsi_attachdevs( unit, ahb_data[unit].our_id, &ahb_switch);
546: #if defined(OSF)
547: ahb_attached[unit]=1;
548: #endif /* defined(OSF) */
549: if(!unit) /* only one for all boards */
550: {
551: ahb_timeout(0);
552: }
553: return;
554: }
555:
556: /***********************************************\
557: * Return some information to the caller about *
558: * the adapter and it's capabilities *
559: \***********************************************/
560: long int ahb_adapter_info(unit)
561: int unit;
562: {
563: return(2); /* 2 outstanding requests at a time per device */
564: }
565:
566: /***********************************************\
567: * Catch an interrupt from the adaptor *
568: \***********************************************/
569: ahbintr(unit)
570: {
571: struct ecb *ecb;
572: unsigned char stat;
573: register i;
574: u_char ahbstat;
575: int target;
576: long int mboxval;
577:
578: int port = ahb_data[unit].baseport;
579:
580: if(scsi_debug & PRINTROUTINES)
581: printf("ahbintr ");
582:
583: #if defined(OSF)
584: if (!ahb_attached[unit])
585: {
586: return(1);
587: }
588: #endif /* defined(OSF) */
589: while(inb(port + G2STAT) & G2STAT_INT_PEND)
590: {
591: /***********************************************\
592: * First get all the information and then *
593: * acknowlege the interrupt *
594: \***********************************************/
595: ahbstat = inb(port + G2INTST);
596: target = ahbstat & G2INTST_TARGET;
597: stat = ahbstat & G2INTST_INT_STAT;
598: mboxval = inl(port + MBOXIN0);/* don't know this will work */
599: outb(port + G2CNTRL, G2CNTRL_CLEAR_EISA_INT);
600: if(scsi_debug & TRACEINTERRUPTS)
601: printf("status = 0x%x ",stat);
602: /***********************************************\
603: * Process the completed operation *
604: \***********************************************/
605:
606: if(stat == AHB_ECB_OK) /* common case is fast */
607: {
608: ecb = (struct ecb *)PHYSTOKV(mboxval);
609: }
610: else
611: {
612: switch(stat)
613: {
614: case AHB_IMMED_OK:
615: ecb = ahb_data[unit].immed_ecb;
616: ahb_data[unit].immed_ecb = 0;
617: break;
618: case AHB_IMMED_ERR:
619: ecb = ahb_data[unit].immed_ecb;
620: ecb->flags |= ECB_IMMED_FAIL;
621: ahb_data[unit].immed_ecb = 0;
622: break;
623: case AHB_ASN: /* for target mode */
624: ecb = 0;
625: break;
626: case AHB_HW_ERR:
627: ecb = 0;
628: break;
629: case AHB_ECB_RECOVERED:
630: ecb = (struct ecb *)PHYSTOKV(mboxval);
631: break;
632: case AHB_ECB_ERR:
633: ecb = (struct ecb *)PHYSTOKV(mboxval);
634: break;
635: default:
636: printf(" Unknown return from ahb%d(%x)\n",unit,ahbstat);
637: ecb=0;
638: }
639: }
640: if(ecb)
641: {
642: if(ahb_debug & AHB_SHOWCMDS )
643: {
644: ahb_show_scsi_cmd(ecb->xs);
645: }
646: if((ahb_debug & AHB_SHOWECBS) && ecb)
647: printf("<int ecb(%x)>",ecb);
648: ahb_remove_timeout(ecb);
649: ahb_done(unit,ecb,((stat == AHB_ECB_OK)?SUCCESS:FAIL));
650: }
651: }
652: return(1);
653: }
654:
655: /***********************************************\
656: * We have a ecb which has been processed by the *
657: * adaptor, now we look to see how the operation *
658: * went. *
659: \***********************************************/
660: ahb_done(unit,ecb,state)
661: int unit,state;
662: struct ecb *ecb;
663: {
664: struct ahb_ecb_status *stat = &ecb->ecb_status;
665: struct scsi_sense_data *s1,*s2;
666: struct scsi_xfer *xs = ecb->xs;
667:
668: if(scsi_debug & (PRINTROUTINES | TRACEINTERRUPTS))
669: printf("ahb_done ");
670: /***********************************************\
671: * Otherwise, put the results of the operation *
672: * into the xfer and call whoever started it *
673: \***********************************************/
674: if(ecb->flags & ECB_IMMED)
675: {
676: if(ecb->flags & ECB_IMMED_FAIL)
677: {
678: xs->error = XS_DRIVER_STUFFUP;
679: }
680: goto done;
681: }
682: if ( (state == SUCCESS) || (xs->flags & SCSI_ERR_OK))
683: { /* All went correctly OR errors expected */
684: xs->resid = 0;
685: xs->error = 0;
686: }
687: else
688: {
689:
690: s1 = &(ecb->ecb_sense);
691: s2 = &(xs->sense);
692:
693: if(stat->ha_status)
694: {
695: switch(stat->ha_status)
696: {
697: case HS_SCSI_RESET_ADAPTER:
698: break;
699: case HS_SCSI_RESET_INCOMING:
700: break;
701: case HS_CMD_ABORTED_HOST: /* No response */
702: case HS_CMD_ABORTED_ADAPTER: /* No response */
703: break;
704: case HS_TIMED_OUT: /* No response */
705: if (ahb_debug & AHB_SHOWMISC)
706: {
707: printf("timeout reported back\n");
708: }
709: xs->error = XS_TIMEOUT;
710: break;
711: default: /* Other scsi protocol messes */
712: xs->error = XS_DRIVER_STUFFUP;
713: if (ahb_debug & AHB_SHOWMISC)
714: {
715: printf("unexpected ha_status: %x\n",
716: stat->ha_status);
717: }
718: }
719:
720: }
721: else
722: {
723: switch(stat->targ_status)
724: {
725: case TS_CHECK_CONDITION:
726: /* structure copy!!!!!*/
727: *s2=*s1;
728: xs->error = XS_SENSE;
729: break;
730: case TS_BUSY:
731: xs->error = XS_BUSY;
732: break;
733: default:
734: if (ahb_debug & AHB_SHOWMISC)
735: {
736: printf("unexpected targ_status: %x\n",
737: stat->targ_status);
738: }
739: xs->error = XS_DRIVER_STUFFUP;
740: }
741: }
742: }
743: done: xs->flags |= ITSDONE;
744: ahb_free_ecb(unit,ecb, xs->flags);
745: if(xs->when_done)
746: (*(xs->when_done))(xs->done_arg,xs->done_arg2);
747: }
748:
749: /***********************************************\
750: * A ecb (and hence a mbx-out is put onto the *
751: * free list. *
752: \***********************************************/
753: ahb_free_ecb(unit,ecb, flags)
754: struct ecb *ecb;
755: {
756: unsigned int opri;
757:
758: if(scsi_debug & PRINTROUTINES)
759: printf("ecb%d(0x%x)> ",unit,flags);
760: if (!(flags & SCSI_NOMASK))
761: opri = splbio();
762:
763: ecb->next = ahb_data[unit].free_ecb;
764: ahb_data[unit].free_ecb = ecb;
765: ecb->flags = ECB_FREE;
766: /***********************************************\
767: * If there were none, wake abybody waiting for *
768: * one to come free, starting with queued entries*
769: \***********************************************/
770: if (!ecb->next) {
771: wakeup(&ahb_data[unit].free_ecb);
772: }
773: if (!(flags & SCSI_NOMASK))
774: splx(opri);
775: }
776:
777: /***********************************************\
778: * Get a free ecb (and hence mbox-out entry) *
779: \***********************************************/
780: struct ecb *
781: ahb_get_ecb(unit,flags)
782: {
783: unsigned opri;
784: struct ecb *rc;
785:
786: if(scsi_debug & PRINTROUTINES)
787: printf("<ecb%d(0x%x) ",unit,flags);
788: if (!(flags & SCSI_NOMASK))
789: opri = splbio();
790: /***********************************************\
791: * If we can and have to, sleep waiting for one *
792: * to come free *
793: \***********************************************/
794: while ((!(rc = ahb_data[unit].free_ecb)) && (!(flags & SCSI_NOSLEEP)))
795: {
796: sleep(&ahb_data[unit].free_ecb, PRIBIO);
797: }
798: if (rc)
799: {
800: ahb_data[unit].free_ecb = rc->next;
801: rc->flags = ECB_ACTIVE;
802: }
803: if (!(flags & SCSI_NOMASK))
804: splx(opri);
805: return(rc);
806: }
807:
808:
809:
810: /***********************************************\
811: * Start the board, ready for normal operation *
812: \***********************************************/
813: ahb_init(unit)
814: int unit;
815: {
816: int port = ahb_data[unit].baseport;
817: int intdef;
818: int spincount = FUDGE(delaycount) * 1000; /* 1 sec enough? */
819: int i;
820: int stport = port + G2STAT;
821: #define NO_NO 1
822: #ifdef NO_NO
823: /***********************************************\
824: * reset board, If it doesn't respond, assume *
825: * that it's not there.. good for the probe *
826: \***********************************************/
827: outb(port + EBCTRL,CDEN); /* enable full card */
828: outb(port + PORTADDR,PORTADDR_ENHANCED);
829:
830: outb(port + G2CNTRL,G2CNTRL_HARD_RESET);
831: spinwait(1);
832: outb(port + G2CNTRL,0);
833: spinwait(10);
834: while( ((inb(stport) & G2STAT_BUSY ))
835: && (spincount--));
836: if(spincount == -1)
837: {
838: if (ahb_debug & AHB_SHOWMISC)
839: printf("ahb_init: No answer from bt742a board\n");
840: return(ENXIO);
841: }
842: i = inb(port + MBOXIN0) & 0xff;
843: if(i)
844: {
845: printf("self test failed, val = 0x%x\n",i);
846: return(EIO);
847: }
848: #endif
849: while( inb(stport) & G2STAT_INT_PEND)
850: {
851: printf(".");
852: outb(port + G2CNTRL, G2CNTRL_CLEAR_EISA_INT);
853: spinwait(10);
854: }
855: outb(port + EBCTRL,CDEN); /* enable full card */
856: outb(port + PORTADDR,PORTADDR_ENHANCED);
857: /***********************************************\
858: * Assume we have a board at this stage *
859: * setup dma channel from jumpers and save int *
860: * level *
861: \***********************************************/
862: #ifdef __386BSD__
863: printf("ahb%d reading board settings, ",unit);
864: #define PRNT(x)
865: #else __386BSD__
866: printf("ahb%d:",unit);
867: #define PRNT(x) printf(x)
868: #endif __386BSD__
869:
870: intdef = inb(port + INTDEF);
871: switch(intdef & 0x07)
872: {
873: case INT9:
874: ahb_data[unit].vect = 9;
875: PRNT("int=9 ");
876: break;
877: case INT10:
878: ahb_data[unit].vect = 10;
879: PRNT("int=10 ");
880: break;
881: case INT11:
882: ahb_data[unit].vect = 11;
883: PRNT("int=11 ");
884: break;
885: case INT12:
886: ahb_data[unit].vect = 12;
887: PRNT("int=12 ");
888: break;
889: case INT14:
890: ahb_data[unit].vect = 14;
891: PRNT("int=14 ");
892: break;
893: case INT15:
894: ahb_data[unit].vect = 15;
895: PRNT("int=15 ");
896: break;
897: default:
898: printf("illegal int setting\n");
899: return(EIO);
900: }
901: outb(port + INTDEF ,(intdef | INTEN)); /* make sure we can interrupt */
902: /* who are we on the scsi bus */
903: ahb_data[unit].our_id = (inb(port + SCSIDEF) & HSCSIID);
904:
905: /***********************************************\
906: * link up all our ECBs into a free list *
907: \***********************************************/
908: for (i=0; i < NUM_CONCURRENT; i++)
909: {
910: ahb_data[unit].ecbs[i].next = ahb_data[unit].free_ecb;
911: ahb_data[unit].free_ecb = &ahb_data[unit].ecbs[i];
912: ahb_data[unit].free_ecb->flags = ECB_FREE;
913: }
914:
915: /***********************************************\
916: * Note that we are going and return (to probe) *
917: \***********************************************/
918: ahb_data[unit].flags |= AHB_INIT;
919: return( 0 );
920: }
921:
922:
923: #ifndef min
924: #define min(x,y) (x < y ? x : y)
925: #endif min
926:
927:
928: void ahbminphys(bp)
929: struct buf *bp;
930: {
931: #ifdef MACH
932: #if !defined(OSF)
933: bp->b_flags |= B_NPAGES; /* can support scat/gather */
934: #endif /* defined(OSF) */
935: #endif MACH
936: if(bp->b_bcount > ((AHB_NSEG-1) * PAGESIZ))
937: {
938: bp->b_bcount = ((AHB_NSEG-1) * PAGESIZ);
939: }
940: }
941:
942: /***********************************************\
943: * start a scsi operation given the command and *
944: * the data address. Also needs the unit, target *
945: * and lu *
946: \***********************************************/
947: int ahb_scsi_cmd(xs)
948: struct scsi_xfer *xs;
949: {
950: struct scsi_sense_data *s1,*s2;
951: struct ecb *ecb;
952: struct ahb_dma_seg *sg;
953: int seg; /* scatter gather seg being worked on */
954: int i = 0;
955: int rc = 0;
956: int thiskv;
957: physaddr thisphys,nextphys;
958: int unit =xs->adapter;
959: int bytes_this_seg,bytes_this_page,datalen,flags;
960: struct iovec *iovp;
961: int s;
962: if(scsi_debug & PRINTROUTINES)
963: printf("ahb_scsi_cmd ");
964: /***********************************************\
965: * get a ecb (mbox-out) to use. If the transfer *
966: * is from a buf (possibly from interrupt time) *
967: * then we can't allow it to sleep *
968: \***********************************************/
969: flags = xs->flags;
970: if(xs->bp) flags |= (SCSI_NOSLEEP); /* just to be sure */
971: if(flags & ITSDONE)
972: {
973: printf("Already done?");
974: xs->flags &= ~ITSDONE;
975: }
976: if(!(flags & INUSE))
977: {
978: printf("Not in use?");
979: xs->flags |= INUSE;
980: }
981: if (!(ecb = ahb_get_ecb(unit,flags)))
982: {
983: xs->error = XS_DRIVER_STUFFUP;
984: return(TRY_AGAIN_LATER);
985: }
986:
987: cheat = ecb;
988: if(ahb_debug & AHB_SHOWECBS)
989: printf("<start ecb(%x)>",ecb);
990: if(scsi_debug & SHOWCOMMANDS)
991: {
992: ahb_show_scsi_cmd(xs);
993: }
994: ecb->xs = xs;
995: /***********************************************\
996: * If it's a reset, we need to do an 'immediate' *
997: * command, and store it's ccb for later *
998: * if there is already an immediate waiting, *
999: * then WE must wait *
1000: \***********************************************/
1001: if(flags & SCSI_RESET)
1002: {
1003: ecb->flags |= ECB_IMMED;
1004: if(ahb_data[unit].immed_ecb)
1005: {
1006: return(TRY_AGAIN_LATER);
1007: }
1008: ahb_data[unit].immed_ecb = ecb;
1009: if (!(flags & SCSI_NOMASK))
1010: {
1011: s = splbio();
1012: ahb_send_immed(unit,xs->targ,AHB_TARG_RESET);
1013: ahb_add_timeout(ecb,xs->timeout);
1014: splx(s);
1015: return(SUCCESSFULLY_QUEUED);
1016: }
1017: else
1018: {
1019: ahb_send_immed(unit,xs->targ,AHB_TARG_RESET);
1020: /***********************************************\
1021: * If we can't use interrupts, poll on completion*
1022: \***********************************************/
1023: if(scsi_debug & TRACEINTERRUPTS)
1024: printf("wait ");
1025: if( ahb_poll(unit,xs->timeout))
1026: {
1027: ahb_free_ecb(unit,ecb,flags);
1028: xs->error = XS_TIMEOUT;
1029: return(HAD_ERROR);
1030: }
1031: return(COMPLETE);
1032: }
1033: }
1034: /***********************************************\
1035: * Put all the arguments for the xfer in the ecb *
1036: \***********************************************/
1037: ecb->opcode = ECB_SCSI_OP;
1038: ecb->opt1 = ECB_SES|ECB_DSB|ECB_ARS;
1039: if(xs->datalen)
1040: {
1041: ecb->opt1 |= ECB_S_G;
1042: }
1043: ecb->opt2 = xs->lu | ECB_NRB;
1044: ecb->cdblen = xs->cmdlen;
1045: ecb->sense = KVTOPHYS(&(ecb->ecb_sense));
1046: ecb->senselen = sizeof(ecb->ecb_sense);
1047: ecb->status = KVTOPHYS(&(ecb->ecb_status));
1048:
1049: if(xs->datalen)
1050: { /* should use S/G only if not zero length */
1051: ecb->data = KVTOPHYS(ecb->ahb_dma);
1052: sg = ecb->ahb_dma ;
1053: seg = 0;
1054: if(flags & SCSI_DATA_UIO)
1055: {
1056: iovp = ((struct uio *)xs->data)->uio_iov;
1057: datalen = ((struct uio *)xs->data)->uio_iovcnt;
1058: xs->datalen = 0;
1059: while ((datalen) && (seg < AHB_NSEG))
1060: {
1061: sg->addr = (physaddr)iovp->iov_base;
1062: xs->datalen += sg->len = iovp->iov_len;
1063: if(scsi_debug & SHOWSCATGATH)
1064: printf("(0x%x@0x%x)"
1065: ,iovp->iov_len
1066: ,iovp->iov_base);
1067: sg++;
1068: iovp++;
1069: seg++;
1070: datalen--;
1071: }
1072: }
1073: else
1074: {
1075: /***********************************************\
1076: * Set up the scatter gather block *
1077: \***********************************************/
1078:
1079: if(scsi_debug & SHOWSCATGATH)
1080: printf("%d @0x%x:- ",xs->datalen,xs->data);
1081: datalen = xs->datalen;
1082: thiskv = (int)xs->data;
1083: thisphys = KVTOPHYS(thiskv);
1084:
1085: while ((datalen) && (seg < AHB_NSEG))
1086: {
1087: bytes_this_seg = 0;
1088:
1089: /* put in the base address */
1090: sg->addr = thisphys;
1091:
1092: if(scsi_debug & SHOWSCATGATH)
1093: printf("0x%x",thisphys);
1094:
1095: /* do it at least once */
1096: nextphys = thisphys;
1097: while ((datalen) && (thisphys == nextphys))
1098: /*********************************************\
1099: * This page is contiguous (physically) with *
1100: * the the last, just extend the length *
1101: \*********************************************/
1102: {
1103: /* how far to the end of the page */
1104: nextphys= (thisphys & (~(PAGESIZ - 1)))
1105: + PAGESIZ;
1106: bytes_this_page = nextphys - thisphys;
1107: /**** or the data ****/
1108: bytes_this_page = min(bytes_this_page
1109: ,datalen);
1110: bytes_this_seg += bytes_this_page;
1111: datalen -= bytes_this_page;
1112:
1113: /* get more ready for the next page */
1114: thiskv = (thiskv & (~(PAGESIZ - 1)))
1115: + PAGESIZ;
1116: if(datalen)
1117: thisphys = KVTOPHYS(thiskv);
1118: }
1119: /********************************************\
1120: * next page isn't contiguous, finish the seg *
1121: \********************************************/
1122: if(scsi_debug & SHOWSCATGATH)
1123: printf("(0x%x)",bytes_this_seg);
1124: sg->len = bytes_this_seg;
1125: sg++;
1126: seg++;
1127: }
1128: } /*end of iov/kv decision */
1129: ecb->datalen = seg * sizeof(struct ahb_dma_seg);
1130: if(scsi_debug & SHOWSCATGATH)
1131: printf("\n");
1132: if (datalen)
1133: { /* there's still data, must have run out of segs! */
1134: printf("ahb_scsi_cmd%d: more than %d DMA segs\n",
1135: unit,AHB_NSEG);
1136: xs->error = XS_DRIVER_STUFFUP;
1137: ahb_free_ecb(unit,ecb,flags);
1138: return(HAD_ERROR);
1139: }
1140:
1141: }
1142: else
1143: { /* No data xfer, use non S/G values */
1144: ecb->data = (physaddr)0;
1145: ecb->datalen = 0;
1146: }
1147: ecb->chain = (physaddr)0;
1148: /***********************************************\
1149: * Put the scsi command in the ecb and start it *
1150: \***********************************************/
1151: bcopy(xs->cmd, ecb->cdb, xs->cmdlen);
1152: /***********************************************\
1153: * Usually return SUCCESSFULLY QUEUED *
1154: \***********************************************/
1155: if (!(flags & SCSI_NOMASK))
1156: {
1157: s = splbio();
1158: ahb_send_mbox(unit,OP_START_ECB,xs->targ,ecb);
1159: ahb_add_timeout(ecb,xs->timeout);
1160: splx(s);
1161: if(scsi_debug & TRACEINTERRUPTS)
1162: printf("cmd_sent ");
1163: return(SUCCESSFULLY_QUEUED);
1164: }
1165: /***********************************************\
1166: * If we can't use interrupts, poll on completion*
1167: \***********************************************/
1168: ahb_send_mbox(unit,OP_START_ECB,xs->targ,ecb);
1169: if(scsi_debug & TRACEINTERRUPTS)
1170: printf("cmd_wait ");
1171: do
1172: {
1173: if(ahb_poll(unit,xs->timeout))
1174: {
1175: if (!(xs->flags & SCSI_SILENT)) printf("cmd fail\n");
1176: ahb_send_mbox(unit,OP_ABORT_ECB,xs->targ,ecb);
1177: if(ahb_poll(unit,2000))
1178: {
1179: printf("abort failed in wait\n");
1180: ahb_free_ecb(unit,ecb,flags);
1181: }
1182: xs->error = XS_DRIVER_STUFFUP;
1183: splx(s);
1184: return(HAD_ERROR);
1185: }
1186: } while (!(xs->flags & ITSDONE));/* something (?) else finished */
1187: splx(s);
1188: scsi_debug = 0;ahb_debug = 0;
1189: if(xs->error)
1190: {
1191: return(HAD_ERROR);
1192: }
1193: return(COMPLETE);
1194: }
1195:
1196: /*
1197: * +----------+ +----------+ +----------+
1198: * ahb_soonest--->| later |--->| later|--->| later|--->0
1199: * | [Delta] | | [Delta] | | [Delta] |
1200: * 0<---|sooner |<---|sooner |<---|sooner |<---ahb_latest
1201: * +----------+ +----------+ +----------+
1202: *
1203: * ahb_furtherest = sum(Delta[1..n])
1204: */
1205: ahb_add_timeout(ecb,time)
1206: struct ecb *ecb;
1207: int time;
1208: {
1209: int timeprev;
1210: struct ecb *prev;
1211: int s = splbio();
1212:
1213: if(prev = ahb_latest) /* yes, an assign */
1214: {
1215: timeprev = ahb_furtherest;
1216: }
1217: else
1218: {
1219: timeprev = 0;
1220: }
1221: while(prev && (timeprev > time))
1222: {
1223: timeprev -= prev->delta;
1224: prev = prev->sooner;
1225: }
1226: if(prev)
1227: {
1228: ecb->delta = time - timeprev;
1229: if( ecb->later = prev->later) /* yes an assign */
1230: {
1231: ecb->later->sooner = ecb;
1232: ecb->later->delta -= ecb->delta;
1233: }
1234: else
1235: {
1236: ahb_furtherest = time;
1237: ahb_latest = ecb;
1238: }
1239: ecb->sooner = prev;
1240: prev->later = ecb;
1241: }
1242: else
1243: {
1244: if( ecb->later = ahb_soonest) /* yes, an assign*/
1245: {
1246: ecb->later->sooner = ecb;
1247: ecb->later->delta -= time;
1248: }
1249: else
1250: {
1251: ahb_furtherest = time;
1252: ahb_latest = ecb;
1253: }
1254: ecb->delta = time;
1255: ecb->sooner = (struct ecb *)0;
1256: ahb_soonest = ecb;
1257: }
1258: splx(s);
1259: }
1260:
1261: ahb_remove_timeout(ecb)
1262: struct ecb *ecb;
1263: {
1264: int s = splbio();
1265:
1266: if(ecb->sooner)
1267: {
1268: ecb->sooner->later = ecb->later;
1269: }
1270: else
1271: {
1272: ahb_soonest = ecb->later;
1273: }
1274: if(ecb->later)
1275: {
1276: ecb->later->sooner = ecb->sooner;
1277: ecb->later->delta += ecb->delta;
1278: }
1279: else
1280: {
1281: ahb_latest = ecb->sooner;
1282: ahb_furtherest -= ecb->delta;
1283: }
1284: ecb->sooner = ecb->later = (struct ecb *)0;
1285: splx(s);
1286: }
1287:
1288:
1289: extern int hz;
1290: #define ONETICK 500 /* milliseconds */
1291: #define SLEEPTIME ((hz * 1000) / ONETICK)
1292: ahb_timeout(arg)
1293: int arg;
1294: {
1295: struct ecb *ecb;
1296: int unit;
1297: int s = splbio();
1298:
1299: while( ecb = ahb_soonest )
1300: {
1301: if(ecb->delta <= ONETICK)
1302: /***********************************************\
1303: * It has timed out, we need to do some work *
1304: \***********************************************/
1305: {
1306: unit = ecb->xs->adapter;
1307: printf("ahb%d:%d device timed out\n",unit
1308: ,ecb->xs->targ);
1309: if(ahb_debug & AHB_SHOWECBS)
1310: ahb_print_active_ecb();
1311:
1312: /***************************************\
1313: * Unlink it from the queue *
1314: \***************************************/
1315: ahb_remove_timeout(ecb);
1316:
1317: /***************************************\
1318: * If it's immediate, don't try abort it *
1319: \***************************************/
1320: if(ecb->flags & ECB_IMMED)
1321: {
1322: ecb->xs->retries = 0; /* I MEAN IT ! */
1323: ecb->flags |= ECB_IMMED_FAIL;
1324: ahb_done(unit,ecb,FAIL);
1325: continue;
1326: }
1327: /***************************************\
1328: * If it has been through before, then *
1329: * a previous abort has failed, don't *
1330: * try abort again *
1331: \***************************************/
1332: if(ecb->flags == ECB_ABORTED) /* abort timed out */
1333: {
1334: printf("AGAIN");
1335: ecb->xs->retries = 0; /* I MEAN IT ! */
1336: ecb->ecb_status.ha_status = HS_CMD_ABORTED_HOST;
1337: ahb_done(unit,ecb,FAIL);
1338: }
1339: else /* abort the operation that has timed out */
1340: {
1341: printf("\n");
1342: ahb_send_mbox(unit,OP_ABORT_ECB,ecb->xs->targ,ecb);
1343: /* 2 secs for the abort */
1344: ahb_add_timeout(ecb,2000 + ONETICK);
1345: ecb->flags = ECB_ABORTED;
1346: }
1347: }
1348: else
1349: /***********************************************\
1350: * It has not timed out, adjust and leave *
1351: \***********************************************/
1352: {
1353: ecb->delta -= ONETICK;
1354: ahb_furtherest -= ONETICK;
1355: break;
1356: }
1357: }
1358: splx(s);
1359: timeout(ahb_timeout,arg,SLEEPTIME);
1360: }
1361:
1362: ahb_show_scsi_cmd(struct scsi_xfer *xs)
1363: {
1364: u_char *b = (u_char *)xs->cmd;
1365: int i = 0;
1366: if(!(xs->flags & SCSI_RESET))
1367: {
1368: printf("ahb%d:%d:%d-"
1369: ,xs->adapter
1370: ,xs->targ
1371: ,xs->lu);
1372: while(i < xs->cmdlen )
1373: {
1374: if(i) printf(",");
1375: printf("%x",b[i++]);
1376: }
1377: printf("-\n");
1378: }
1379: else
1380: {
1381: printf("ahb%d:%d:%d-RESET-\n"
1382: ,xs->adapter
1383: ,xs->targ
1384: ,xs->lu
1385: );
1386: }
1387: }
1388: ahb_print_ecb(ecb)
1389: struct ecb *ecb;
1390: {
1391: printf("ecb:%x op:%x cmdlen:%d senlen:%d\n"
1392: ,ecb
1393: ,ecb->opcode
1394: ,ecb->cdblen
1395: ,ecb->senselen);
1396: printf(" datlen:%d hstat:%x tstat:%x delta:%d flags:%x\n"
1397: ,ecb->datalen
1398: ,ecb->ecb_status.ha_status
1399: ,ecb->ecb_status.targ_status
1400: ,ecb->delta
1401: ,ecb->flags);
1402: ahb_show_scsi_cmd(ecb->xs);
1403: }
1404:
1405: ahb_print_active_ecb()
1406: {
1407: struct ecb *ecb;
1408: ecb = ahb_soonest;
1409:
1410: while(ecb)
1411: {
1412: ahb_print_ecb(ecb);
1413: ecb = ecb->later;
1414: }
1415: printf("Furtherest = %d\n",ahb_furtherest);
1416: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.