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