Annotation of src/sys/arch/i386/eisa/aha1742.c, Revision 1.24
1.1 cgd 1: /*
1.23 mycroft 2: * Copyright (c) 1994 Charles Hannum. All rights reserved.
3: *
4: * Redistribution and use in source and binary forms, with or without
5: * modification, are permitted provided that the following conditions
6: * are met:
7: * 1. Redistributions of source code must retain the above copyright
8: * notice, this list of conditions and the following disclaimer.
9: * 2. Redistributions in binary form must reproduce the above copyright
10: * notice, this list of conditions and the following disclaimer in the
11: * documentation and/or other materials provided with the distribution.
12: * 3. All advertising materials mentioning features or use of this software
13: * must display the following acknowledgement:
14: * This product includes software developed by Charles Hannum.
15: * 4. The name of the author may not be used to endorse or promote products
16: * derived from this software without specific prior written permission.
17: *
18: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28: *
29: * $Id: aha1742.c,v 1.14.2.7 1994/03/25 10:19:35 mycroft Exp $
30: */
31:
32: /*
33: * Originally written by Julian Elischer (julian@tfs.com)
1.1 cgd 34: * for TRW Financial Systems for use under the MACH(2.5) operating system.
35: *
36: * TRW Financial Systems, in accordance with their agreement with Carnegie
37: * Mellon University, makes this software available to CMU to distribute
38: * or use in any manner that they see fit as long as this message is kept with
39: * the software. For this reason TFS also grants any other persons or
40: * organisations permission to use or modify this software.
41: *
42: * TFS supplies this software to be publicly redistributed
43: * on the understanding that TFS is not responsible for the correct
44: * functioning of this software in any circumstances.
1.11 cgd 45: *
1.23 mycroft 46: * commenced: Sun Sep 27 18:14:01 PDT 1992
1.1 cgd 47: */
48:
1.15 mycroft 49: #include <sys/types.h>
50: #include <sys/param.h>
51: #include <sys/systm.h>
1.23 mycroft 52: #include <sys/kernel.h>
1.15 mycroft 53: #include <sys/errno.h>
54: #include <sys/ioctl.h>
1.23 mycroft 55: #include <sys/device.h>
56: #include <sys/malloc.h>
1.15 mycroft 57: #include <sys/buf.h>
58: #include <sys/proc.h>
59: #include <sys/user.h>
60:
61: #include <machine/pio.h>
62:
1.23 mycroft 63: #include <i386/isa/isavar.h>
64: #include <i386/isa/icu.h>
1.15 mycroft 65: #include <scsi/scsi_all.h>
66: #include <scsi/scsiconf.h>
67:
1.6 glass 68: #ifdef DDB
1.23 mycroft 69: int Debugger();
70: #else /* DDB */
71: #define Debugger()
72: #endif /* DDB */
73:
74: typedef u_long physaddr;
75:
76: #define KVTOPHYS(x) vtophys(x)
77:
78: #define AHB_ECB_MAX 32 /* store up to 32ECBs at any one time */
79: /* in aha1742 H/W ( Not MAX ? ) */
80: #define ECB_HASH_SIZE 32 /* when we have a physical addr. for */
81: /* a ecb and need to find the ecb in */
82: /* space, look it up in the hash table */
83: #define ECB_HASH_SHIFT 9 /* only hash on multiples of 512 */
84: #define ECB_HASH(x) ((((long int)(x))>>ECB_HASH_SHIFT) % ECB_HASH_SIZE)
1.5 deraadt 85:
1.23 mycroft 86: #define AHB_NSEG 33 /* number of dma segments supported */
1.5 deraadt 87:
88: /*
89: * AHA1740 standard EISA Host ID regs (Offset from slot base)
90: */
1.23 mycroft 91: #define HID0 0xC80 /* 0,1: msb of ID2, 3-7: ID1 */
92: #define HID1 0xC81 /* 0-4: ID3, 4-7: LSB ID2 */
93: #define HID2 0xC82 /* product, 0=174[20] 1 = 1744 */
1.24 ! mycroft 94: #define PRODUCT_1742 0x00
! 95: #define PRODUCT_1744 0x01
1.23 mycroft 96: #define HID3 0xC83 /* firmware revision */
1.1 cgd 97:
98: #define CHAR1(B1,B2) (((B1>>2) & 0x1F) | '@')
99: #define CHAR2(B1,B2) (((B1<<3) & 0x18) | ((B2>>5) & 0x7)|'@')
100: #define CHAR3(B1,B2) ((B2 & 0x1F) | '@')
101:
1.23 mycroft 102: /*
103: * AHA1740 EISA board control registers (Offset from slot base)
104: */
1.1 cgd 105: #define EBCTRL 0xC84
106: #define CDEN 0x01
1.23 mycroft 107:
1.5 deraadt 108: /*
109: * AHA1740 EISA board mode registers (Offset from slot base)
110: */
1.1 cgd 111: #define PORTADDR 0xCC0
112: #define PORTADDR_ENHANCED 0x80
113: #define BIOSADDR 0xCC1
114: #define INTDEF 0xCC2
115: #define SCSIDEF 0xCC3
116: #define BUSDEF 0xCC4
117: #define RESV0 0xCC5
118: #define RESV1 0xCC6
119: #define RESV2 0xCC7
1.23 mycroft 120: /**** bit definitions for INTDEF ****/
1.1 cgd 121: #define INT9 0x00
122: #define INT10 0x01
123: #define INT11 0x02
124: #define INT12 0x03
125: #define INT14 0x05
126: #define INT15 0x06
1.23 mycroft 127: #define INTHIGH 0x08 /* int high=ACTIVE (else edge) */
1.1 cgd 128: #define INTEN 0x10
1.23 mycroft 129: /**** bit definitions for SCSIDEF ****/
130: #define HSCSIID 0x0F /* our SCSI ID */
131: #define RSTPWR 0x10 /* reset scsi bus on power up or reset */
132: /**** bit definitions for BUSDEF ****/
133: #define B0uS 0x00 /* give up bus immediatly */
134: #define B4uS 0x01 /* delay 4uSec. */
1.1 cgd 135: #define B8uS 0x02
1.5 deraadt 136:
137: /*
138: * AHA1740 ENHANCED mode mailbox control regs (Offset from slot base)
139: */
1.1 cgd 140: #define MBOXOUT0 0xCD0
141: #define MBOXOUT1 0xCD1
142: #define MBOXOUT2 0xCD2
143: #define MBOXOUT3 0xCD3
144:
145: #define ATTN 0xCD4
146: #define G2CNTRL 0xCD5
147: #define G2INTST 0xCD6
148: #define G2STAT 0xCD7
149:
150: #define MBOXIN0 0xCD8
151: #define MBOXIN1 0xCD9
152: #define MBOXIN2 0xCDA
153: #define MBOXIN3 0xCDB
154:
155: #define G2STAT2 0xCDC
156:
1.5 deraadt 157: /*
158: * Bit definitions for the 5 control/status registers
159: */
1.1 cgd 160: #define ATTN_TARGET 0x0F
161: #define ATTN_OPCODE 0xF0
162: #define OP_IMMED 0x10
163: #define AHB_TARG_RESET 0x80
164: #define OP_START_ECB 0x40
165: #define OP_ABORT_ECB 0x50
166:
167: #define G2CNTRL_SET_HOST_READY 0x20
168: #define G2CNTRL_CLEAR_EISA_INT 0x40
169: #define G2CNTRL_HARD_RESET 0x80
170:
171: #define G2INTST_TARGET 0x0F
172: #define G2INTST_INT_STAT 0xF0
173: #define AHB_ECB_OK 0x10
174: #define AHB_ECB_RECOVERED 0x50
175: #define AHB_HW_ERR 0x70
176: #define AHB_IMMED_OK 0xA0
177: #define AHB_ECB_ERR 0xC0
178: #define AHB_ASN 0xD0 /* for target mode */
179: #define AHB_IMMED_ERR 0xE0
180:
181: #define G2STAT_BUSY 0x01
182: #define G2STAT_INT_PEND 0x02
183: #define G2STAT_MBOX_EMPTY 0x04
184:
185: #define G2STAT2_HOST_READY 0x01
1.5 deraadt 186:
187: struct ahb_dma_seg {
1.23 mycroft 188: physaddr addr;
189: long len;
1.1 cgd 190: };
191:
1.5 deraadt 192: struct ahb_ecb_status {
1.23 mycroft 193: u_short status;
194: #define ST_DON 0x0001
195: #define ST_DU 0x0002
196: #define ST_QF 0x0008
197: #define ST_SC 0x0010
198: #define ST_DO 0x0020
199: #define ST_CH 0x0040
200: #define ST_INT 0x0080
201: #define ST_ASA 0x0100
202: #define ST_SNS 0x0200
203: #define ST_INI 0x0800
204: #define ST_ME 0x1000
205: #define ST_ECA 0x4000
206: u_char ha_status;
207: #define HS_OK 0x00
208: #define HS_CMD_ABORTED_HOST 0x04
209: #define HS_CMD_ABORTED_ADAPTER 0x05
210: #define HS_TIMED_OUT 0x11
211: #define HS_HARDWARE_ERR 0x20
212: #define HS_SCSI_RESET_ADAPTER 0x22
213: #define HS_SCSI_RESET_INCOMING 0x23
214: u_char targ_status;
215: #define TS_OK 0x00
216: #define TS_CHECK_CONDITION 0x02
217: #define TS_BUSY 0x08
218: u_long resid_count;
219: u_long resid_addr;
220: u_short addit_status;
221: u_char sense_len;
222: u_char unused[9];
223: u_char cdb[6];
1.1 cgd 224: };
225:
1.5 deraadt 226: struct ecb {
1.23 mycroft 227: u_char opcode;
228: #define ECB_SCSI_OP 0x01
229: u_char:4;
230: u_char options:3;
231: u_char:1;
232: short opt1;
233: #define ECB_CNE 0x0001
234: #define ECB_DI 0x0080
235: #define ECB_SES 0x0400
236: #define ECB_S_G 0x1000
237: #define ECB_DSB 0x4000
238: #define ECB_ARS 0x8000
239: short opt2;
240: #define ECB_LUN 0x0007
241: #define ECB_TAG 0x0008
242: #define ECB_TT 0x0030
243: #define ECB_ND 0x0040
244: #define ECB_DAT 0x0100
245: #define ECB_DIR 0x0200
246: #define ECB_ST 0x0400
247: #define ECB_CHK 0x0800
248: #define ECB_REC 0x4000
249: #define ECB_NRB 0x8000
250: u_short unused1;
251: physaddr data;
252: u_long datalen;
253: physaddr status;
254: physaddr chain;
255: short unused2;
256: short unused3;
257: physaddr sense;
258: u_char senselen;
259: u_char cdblen;
260: short cksum;
261: u_char cdb[12];
1.1 cgd 262: /*-----------------end of hardware supported fields----------------*/
1.23 mycroft 263: struct ecb *next; /* in free list */
264: struct scsi_xfer *xs; /* the scsi_xfer for this cmd */
265: int flags;
1.1 cgd 266: #define ECB_FREE 0
267: #define ECB_ACTIVE 1
268: #define ECB_ABORTED 2
269: #define ECB_IMMED 4
270: #define ECB_IMMED_FAIL 8
1.23 mycroft 271: struct ahb_dma_seg ahb_dma[AHB_NSEG];
272: struct ahb_ecb_status ecb_status;
273: struct scsi_sense_data ecb_sense;
274: struct ecb *nexthash;
275: physaddr hashkey; /* physaddr of this struct */
1.1 cgd 276: };
277:
1.23 mycroft 278: struct ahb_softc {
279: struct device sc_dev;
280: struct isadev sc_id;
281: struct intrhand sc_ih;
282:
283: u_short baseport;
284: struct ecb *ecbhash[ECB_HASH_SIZE];
1.5 deraadt 285: struct ecb *free_ecb;
1.23 mycroft 286: int our_id; /* our scsi id */
287: int vect;
288: struct ecb *immed_ecb; /* an outstanding immediete command */
289: int numecbs;
290: struct scsi_link sc_link;
291: };
292:
293: void ahb_send_mbox __P((struct ahb_softc *, int, int, struct ecb *));
294: int ahb_poll __P((struct ahb_softc *, int));
295: void ahb_send_immed __P((struct ahb_softc *, int, u_long));
296: u_int ahb_adapter_info __P((struct ahb_softc *));
297: int ahbintr __P((int));
298: void ahb_done __P((struct ahb_softc *, struct ecb *, int));
299: void ahb_free_ecb __P((struct ahb_softc *, struct ecb *, int));
300: struct ecb *ahb_get_ecb __P((struct ahb_softc *, int));
301: struct ecb *ahb_ecb_phys_kv __P((struct ahb_softc *, physaddr));
302: int ahb_find __P((struct ahb_softc *));
303: void ahb_init __P((struct ahb_softc *));
304: void ahbminphys __P((struct buf *));
305: int ahb_scsi_cmd __P((struct scsi_xfer *));
306: void ahb_timeout __P((caddr_t));
307: void ahb_print_ecb __P((struct ecb *));
308: void ahb_print_active_ecb __P((struct ahb_softc *));
309:
310: struct ecb *cheat;
311:
312: #define MAX_SLOTS 15
313: static ahb_slot = 0; /* slot last board was found in */
314: int ahb_debug = 0;
1.1 cgd 315: #define AHB_SHOWECBS 0x01
316: #define AHB_SHOWINTS 0x02
317: #define AHB_SHOWCMDS 0x04
318: #define AHB_SHOWMISC 0x08
1.23 mycroft 319:
320: struct scsi_adapter ahb_switch = {
321: ahb_scsi_cmd,
322: ahbminphys,
323: 0,
324: 0,
325: ahb_adapter_info,
1.5 deraadt 326: "ahb"
327: };
328:
1.23 mycroft 329: /* the below structure is so we have a default dev struct for our link struct */
330: struct scsi_device ahb_dev = {
331: NULL, /* Use default error handler */
332: NULL, /* have a queue, served by this */
333: NULL, /* have no async handler */
334: NULL, /* Use default 'done' routine */
335: "ahb",
336: 0
337: };
338:
339: int ahbprobe();
340: int ahbprobe1 __P((struct ahb_softc *, struct isa_attach_args *));
341: void ahbattach();
342:
343: struct cfdriver ahbcd = {
344: NULL, "ahb", ahbprobe, ahbattach, DV_DULL, sizeof(struct ahb_softc)
345: };
1.5 deraadt 346:
347: /*
348: * Function to send a command out through a mailbox
349: */
350: void
1.23 mycroft 351: ahb_send_mbox(ahb, opcode, target, ecb)
352: struct ahb_softc *ahb;
353: int opcode, target;
354: struct ecb *ecb;
1.1 cgd 355: {
1.23 mycroft 356: u_short port = ahb->baseport;
357: u_short stport = port + G2STAT;
358: int wait = 100; /* 1ms should be enough */
359: int s = splbio();
360:
361: while (--wait) {
362: if ((inb(stport) & (G2STAT_BUSY | G2STAT_MBOX_EMPTY))
363: == (G2STAT_MBOX_EMPTY))
364: break;
365: delay(10);
366: }
367: if (!wait) {
368: printf("%s: board not responding\n", ahb->sc_dev.dv_xname);
1.1 cgd 369: Debugger();
370: }
371:
1.23 mycroft 372: outl(port + MBOXOUT0, KVTOPHYS(ecb)); /* don't know this will work */
373: outb(port + ATTN, opcode | target);
374:
1.1 cgd 375: splx(s);
376: }
377:
1.5 deraadt 378: /*
379: * Function to poll for command completion when in poll mode
380: */
381: int
1.23 mycroft 382: ahb_poll(ahb, wait)
383: struct ahb_softc *ahb;
384: int wait;
385: { /* in msec */
386: u_short port = ahb->baseport;
387: u_short stport = port + G2STAT;
388:
389: retry:
390: while (--wait) {
391: if (inb(stport) & G2STAT_INT_PEND)
392: break;
393: delay(1000);
394: }
395: if (!wait) {
396: printf("%s: board not responding\n", ahb->sc_dev.dv_xname);
397: return EIO;
1.1 cgd 398: }
1.23 mycroft 399:
400: if (cheat != ahb_ecb_phys_kv(ahb, inl(port + MBOXIN0))) {
401: printf("discarding %x ", inl(port + MBOXIN0));
1.5 deraadt 402: outb(port + G2CNTRL, G2CNTRL_CLEAR_EISA_INT);
1.23 mycroft 403: delay(50000);
1.5 deraadt 404: goto retry;
405: }
1.23 mycroft 406:
407: /* don't know this will work */
408: ahbintr(ahb->sc_dev.dv_unit);
409: return 0;
1.1 cgd 410: }
1.23 mycroft 411:
1.5 deraadt 412: /*
413: * Function to send an immediate type command to the adapter
414: */
415: void
1.23 mycroft 416: ahb_send_immed(ahb, target, cmd)
417: struct ahb_softc *ahb;
418: int target;
419: u_long cmd;
1.1 cgd 420: {
1.23 mycroft 421: u_short port = ahb->baseport;
422: u_short stport = port + G2STAT;
423: int wait = 100; /* 1 ms enough? */
1.5 deraadt 424: int s = splbio();
425:
1.23 mycroft 426: while (--wait) {
427: if ((inb(stport) & (G2STAT_BUSY | G2STAT_MBOX_EMPTY))
428: == (G2STAT_MBOX_EMPTY))
429: break;
430: delay(10);
431: }
432: if (!wait) {
433: printf("%s: board not responding\n", ahb->sc_dev.dv_xname);
1.1 cgd 434: Debugger();
435: }
436:
1.5 deraadt 437: outl(port + MBOXOUT0, cmd); /* don't know this will work */
1.1 cgd 438: outb(port + G2CNTRL, G2CNTRL_SET_HOST_READY);
439: outb(port + ATTN, OP_IMMED | target);
440: splx(s);
441: }
442:
1.5 deraadt 443: /*
1.23 mycroft 444: * Check the slots looking for a board we recognise
1.5 deraadt 445: * If we find one, note it's address (slot) and call
446: * the actual probe routine to check it out.
447: */
448: int
1.23 mycroft 449: ahbprobe(parent, self, aux)
450: struct device *parent, *self;
451: void *aux;
1.1 cgd 452: {
1.23 mycroft 453: struct ahb_softc *ahb = (void *)self;
454: struct isa_attach_args *ia = aux;
455: u_short port;
456: u_char byte1, byte2, byte3;
457:
458: #ifdef NEWCONFIG
459: if (ia->ia_iobase != IOBASEUNK)
460: return ahbprobe1(ahb, ia);
461: #endif
1.5 deraadt 462:
1.23 mycroft 463: while (ahb_slot < MAX_SLOTS) {
464: ahb_slot++;
1.1 cgd 465: port = 0x1000 * ahb_slot;
466: byte1 = inb(port + HID0);
467: byte2 = inb(port + HID1);
468: byte3 = inb(port + HID2);
1.23 mycroft 469: if (byte1 == 0xff)
470: continue;
471: if (CHAR1(byte1, byte2) != 'A' ||
472: CHAR2(byte1, byte2) != 'D' ||
473: CHAR3(byte1, byte2) != 'P' ||
1.24 ! mycroft 474: (byte3 != PRODUCT_1742 && byte3 != PRODUCT_1744)) {
1.1 cgd 475: continue;
476: }
1.23 mycroft 477: ia->ia_iobase = port;
478: if (ahbprobe1(ahb, ia))
479: return 1;
1.1 cgd 480: }
1.23 mycroft 481:
1.5 deraadt 482: return 0;
1.1 cgd 483: }
1.5 deraadt 484:
485: /*
1.23 mycroft 486: * Check if the device can be found at the port given
487: * and if so, set it up ready for further work
488: * as an argument, takes the isa_device structure from
489: * autoconf.c.
1.5 deraadt 490: */
491: int
1.23 mycroft 492: ahbprobe1(ahb, ia)
493: struct ahb_softc *ahb;
494: struct isa_attach_args *ia;
1.1 cgd 495: {
1.5 deraadt 496:
1.23 mycroft 497: ahb->baseport = ia->ia_iobase;
1.5 deraadt 498:
499: /*
500: * Try initialise a unit at this location
1.23 mycroft 501: * sets up dma and bus speed, loads ahb->vect
1.5 deraadt 502: */
1.23 mycroft 503: if (ahb_find(ahb) != 0)
1.5 deraadt 504: return 0;
1.1 cgd 505:
1.23 mycroft 506: #ifdef NEWCONFIG
507: if (ia->ia_irq == IRQUNK) {
508: ia->ia_irq = (1 << ahb->vect);
509: } else {
510: if (ia->ia_irq != (1 << ahb->vect)) {
511: printf("ahb%d: irq mismatch, %x != %x\n",
512: ahb->sc_dev.dv_unit, ia->ia_irq,
513: 1 << ahb->vect);
514: return 0;
515: }
516: }
517: #endif
518:
519: ia->ia_drq = DRQUNK;
520: ia->ia_msize = 0;
521: ia->ia_iosize = 0x1000;
522: return 1;
523: }
524:
525: ahbprint()
526: {
527:
1.1 cgd 528: }
529:
1.5 deraadt 530: /*
531: * Attach all the sub-devices we can find
532: */
1.23 mycroft 533: void
534: ahbattach(parent, self, aux)
535: struct device *parent, *self;
536: void *aux;
1.1 cgd 537: {
1.23 mycroft 538: struct isa_attach_args *ia = aux;
539: struct ahb_softc *ahb = (void *)self;
540:
541: ahb_init(ahb);
542:
543: /*
544: * fill in the prototype scsi_link.
545: */
546: ahb->sc_link.adapter_softc = ahb;
547: ahb->sc_link.adapter_targ = ahb->our_id;
548: ahb->sc_link.adapter = &ahb_switch;
549: ahb->sc_link.device = &ahb_dev;
550:
1.24 ! mycroft 551: printf(": ");
! 552: switch (inb(ahb->baseport + HID2)) {
! 553: case PRODUCT_1742:
! 554: printf("model 1740 or 1742");
! 555: break;
! 556: case PRODUCT_1744:
! 557: printf("model 1744");
! 558: }
! 559: printf(", revision %d\n", inb(ahb->baseport + HID3));
1.23 mycroft 560:
561: #ifdef NEWCONFIG
562: isa_establish(&ahb->sc_id, &ahb->sc_dev);
563: ahb->sc_ih.ih_fun = ahbintr;
564: ahb->sc_ih.ih_arg = ahb;
565: /* XXX and DV_TAPE, but either gives us splbio */
566: intr_establish(ia->ia_irq, &ahb->sc_ih, DV_DISK);
567: #endif
1.1 cgd 568:
1.23 mycroft 569: /*
570: * ask the adapter what subunits are present
571: */
572: config_found(self, &ahb->sc_link, ahbprint);
1.1 cgd 573: }
574:
1.5 deraadt 575: /*
1.23 mycroft 576: * Return some information to the caller about
577: * the adapter and it's capabilities
1.5 deraadt 578: */
1.23 mycroft 579: u_int
580: ahb_adapter_info(ahb)
581: struct ahb_softc *ahb;
1.1 cgd 582: {
1.23 mycroft 583:
584: return 2; /* 2 outstanding requests at a time per device */
1.1 cgd 585: }
586:
1.5 deraadt 587: /*
588: * Catch an interrupt from the adaptor
589: */
590: int
1.23 mycroft 591: ahbintr(unit)
592: int unit;
1.1 cgd 593: {
1.23 mycroft 594: struct ahb_softc *ahb = ahbcd.cd_devs[unit];
595: struct ecb *ecb;
596: u_char stat, ahbstat;
597: u_long mboxval;
598: u_short port = ahb->baseport;
599:
600: #ifdef AHBDEBUG
601: printf("ahbintr ");
602: #endif /*AHBDEBUG */
1.1 cgd 603:
1.23 mycroft 604: while (inb(port + G2STAT) & G2STAT_INT_PEND) {
1.5 deraadt 605: /*
606: * First get all the information and then
607: * acknowlege the interrupt
608: */
1.1 cgd 609: ahbstat = inb(port + G2INTST);
610: stat = ahbstat & G2INTST_INT_STAT;
1.23 mycroft 611: mboxval = inl(port + MBOXIN0); /* don't know this will work */
1.1 cgd 612: outb(port + G2CNTRL, G2CNTRL_CLEAR_EISA_INT);
1.23 mycroft 613:
614: #ifdef AHBDEBUG
615: printf("status = 0x%x ", ahbstat);
616: #endif /*AHBDEBUG */
1.5 deraadt 617:
618: /*
619: * Process the completed operation
620: */
1.23 mycroft 621: if (stat == AHB_ECB_OK) { /* common case is fast */
622: ecb = ahb_ecb_phys_kv(ahb, mboxval);
623: } else {
624: switch (stat) {
1.5 deraadt 625: case AHB_IMMED_OK:
1.23 mycroft 626: ecb = ahb->immed_ecb;
627: ahb->immed_ecb = 0;
1.1 cgd 628: break;
1.5 deraadt 629: case AHB_IMMED_ERR:
1.23 mycroft 630: ecb = ahb->immed_ecb;
1.1 cgd 631: ecb->flags |= ECB_IMMED_FAIL;
1.23 mycroft 632: ahb->immed_ecb = 0;
1.1 cgd 633: break;
1.5 deraadt 634: case AHB_ASN: /* for target mode */
1.23 mycroft 635: printf("%s: Unexpected ASN interrupt(%x)\n",
636: ahb->sc_dev.dv_xname, mboxval);
1.1 cgd 637: ecb = 0;
638: break;
1.5 deraadt 639: case AHB_HW_ERR:
1.23 mycroft 640: printf("%s: Hardware error interrupt(%x)\n",
641: ahb->sc_dev.dv_xname, mboxval);
1.1 cgd 642: ecb = 0;
643: break;
1.5 deraadt 644: case AHB_ECB_RECOVERED:
1.23 mycroft 645: ecb = ahb_ecb_phys_kv(ahb, mboxval);
1.1 cgd 646: break;
1.5 deraadt 647: case AHB_ECB_ERR:
1.23 mycroft 648: ecb = ahb_ecb_phys_kv(ahb, mboxval);
1.1 cgd 649: break;
650: default:
1.23 mycroft 651: printf("%s: Unknown return %x\n",
652: ahb->sc_dev.dv_xname, ahbstat);
653: ecb = 0;
1.1 cgd 654: }
1.23 mycroft 655: } if (ecb) {
656: #ifdef AHBDEBUG
657: if (ahb_debug & AHB_SHOWCMDS)
658: show_scsi_cmd(ecb->xs);
659: if ((ahb_debug & AHB_SHOWECBS) && ecb)
660: printf("<int ecb(%x)>", ecb);
661: #endif /*AHBDEBUG */
662: untimeout((timeout_t)ahb_timeout, (caddr_t)ecb);
663: ahb_done(ahb, ecb, stat != AHB_ECB_OK);
1.1 cgd 664: }
665: }
1.5 deraadt 666: return 1;
1.1 cgd 667: }
668:
1.5 deraadt 669: /*
1.23 mycroft 670: * We have a ecb which has been processed by the adaptor, now we look to see
671: * how the operation went.
1.5 deraadt 672: */
673: void
1.23 mycroft 674: ahb_done(ahb, ecb, failed)
675: struct ahb_softc *ahb;
676: struct ecb *ecb;
677: int failed;
1.1 cgd 678: {
1.23 mycroft 679: struct ahb_ecb_status *stat = &ecb->ecb_status;
680: struct scsi_sense_data *s1, *s2;
1.5 deraadt 681: struct scsi_xfer *xs = ecb->xs;
1.1 cgd 682:
1.23 mycroft 683: SC_DEBUG(xs->sc_link, SDEV_DB2, ("ahb_done\n"));
1.5 deraadt 684: /*
685: * Otherwise, put the results of the operation
686: * into the xfer and call whoever started it
687: */
1.23 mycroft 688: if (ecb->flags & ECB_IMMED) {
689: if (ecb->flags & ECB_IMMED_FAIL)
1.1 cgd 690: xs->error = XS_DRIVER_STUFFUP;
691: goto done;
692: }
1.23 mycroft 693:
694: if (!failed || (xs->flags & SCSI_ERR_OK)) { /* All went correctly OR errors expected */
1.1 cgd 695: xs->resid = 0;
696: xs->error = 0;
1.5 deraadt 697: } else {
1.1 cgd 698: s1 = &(ecb->ecb_sense);
699: s2 = &(xs->sense);
700:
1.23 mycroft 701: if (stat->ha_status) {
702: switch (stat->ha_status) {
1.5 deraadt 703: case HS_SCSI_RESET_ADAPTER:
1.1 cgd 704: break;
1.5 deraadt 705: case HS_SCSI_RESET_INCOMING:
1.1 cgd 706: break;
1.5 deraadt 707: case HS_CMD_ABORTED_HOST: /* No response */
708: case HS_CMD_ABORTED_ADAPTER: /* No response */
1.1 cgd 709: break;
1.23 mycroft 710: case HS_TIMED_OUT: /* No response */
711: #ifdef AHBDEBUG
1.1 cgd 712: if (ahb_debug & AHB_SHOWMISC)
713: printf("timeout reported back\n");
1.23 mycroft 714: #endif /*AHBDEBUG */
1.1 cgd 715: xs->error = XS_TIMEOUT;
716: break;
1.23 mycroft 717: default: /* Other scsi protocol messes */
1.1 cgd 718: xs->error = XS_DRIVER_STUFFUP;
1.23 mycroft 719: #ifdef AHBDEBUG
1.1 cgd 720: if (ahb_debug & AHB_SHOWMISC)
1.23 mycroft 721: printf("unexpected ha_status %x\n",
1.1 cgd 722: stat->ha_status);
1.23 mycroft 723: #endif /*AHBDEBUG */
1.1 cgd 724: }
1.5 deraadt 725: } else {
1.23 mycroft 726: switch (stat->targ_status) {
1.1 cgd 727: case TS_CHECK_CONDITION:
1.23 mycroft 728: /* structure copy!!!!! */
1.5 deraadt 729: *s2 = *s1;
1.1 cgd 730: xs->error = XS_SENSE;
731: break;
732: case TS_BUSY:
733: xs->error = XS_BUSY;
734: break;
735: default:
1.23 mycroft 736: #ifdef AHBDEBUG
737: if (ahb_debug & AHB_SHOWMISC) {
738: printf("unexpected targ_status %x\n",
1.1 cgd 739: stat->targ_status);
1.23 mycroft 740: }
741: #endif /*AHBDEBUG */
1.1 cgd 742: xs->error = XS_DRIVER_STUFFUP;
743: }
744: }
745: }
1.23 mycroft 746: done:
1.5 deraadt 747: xs->flags |= ITSDONE;
1.23 mycroft 748: ahb_free_ecb(ahb, ecb, xs->flags);
749: scsi_done(xs);
1.1 cgd 750: }
751:
1.5 deraadt 752: /*
753: * A ecb (and hence a mbx-out is put onto the
754: * free list.
755: */
756: void
1.23 mycroft 757: ahb_free_ecb(ahb, ecb, flags)
758: struct ahb_softc *ahb;
759: struct ecb *ecb;
760: int flags;
1.1 cgd 761: {
1.23 mycroft 762: int opri;
1.5 deraadt 763:
1.23 mycroft 764: if (!(flags & SCSI_NOMASK))
765: opri = splbio();
1.1 cgd 766:
1.23 mycroft 767: ecb->next = ahb->free_ecb;
768: ahb->free_ecb = ecb;
1.1 cgd 769: ecb->flags = ECB_FREE;
1.5 deraadt 770: /*
771: * If there were none, wake abybody waiting for
1.23 mycroft 772: * one to come free, starting with queued entries
1.5 deraadt 773: */
774: if (!ecb->next)
1.23 mycroft 775: wakeup((caddr_t)&ahb->free_ecb);
1.5 deraadt 776:
1.23 mycroft 777: if (!(flags & SCSI_NOMASK))
1.1 cgd 778: splx(opri);
779: }
780:
1.5 deraadt 781: /*
1.23 mycroft 782: * Get a free ecb
783: *
784: * If there are none, see if we can allocate a new one. If so, put it in the
785: * hash table too otherwise either return an error or sleep.
1.5 deraadt 786: */
1.1 cgd 787: struct ecb *
1.23 mycroft 788: ahb_get_ecb(ahb, flags)
789: struct ahb_softc *ahb;
790: int flags;
1.1 cgd 791: {
1.23 mycroft 792: int opri;
793: struct ecb *ecbp;
794: int hashnum;
1.1 cgd 795:
1.23 mycroft 796: if (!(flags & SCSI_NOMASK))
797: opri = splbio();
1.5 deraadt 798:
799: /*
1.23 mycroft 800: * If we can and have to, sleep waiting for one to come free
801: * but only if we can't allocate a new one.
1.5 deraadt 802: */
1.23 mycroft 803: while (!(ecbp = ahb->free_ecb)) {
804: if (ahb->numecbs < AHB_ECB_MAX) {
805: if (ecbp = (struct ecb *) malloc(sizeof(struct ecb),
806: M_TEMP,
807: M_NOWAIT)) {
808: bzero(ecbp, sizeof(struct ecb));
809: ahb->numecbs++;
810: ecbp->flags = ECB_ACTIVE;
811: /*
812: * put in the phystokv hash table
813: * Never gets taken out.
814: */
815: ecbp->hashkey = KVTOPHYS(ecbp);
816: hashnum = ECB_HASH(ecbp->hashkey);
817: ecbp->nexthash = ahb->ecbhash[hashnum];
818: ahb->ecbhash[hashnum] = ecbp;
819: } else {
820: printf("%s: Can't malloc ECB\n",
821: ahb->sc_dev.dv_xname);
822: }
823: goto gottit;
824: } else {
825: if (!(flags & SCSI_NOSLEEP))
826: tsleep((caddr_t)&ahb->free_ecb, PRIBIO,
827: "ahbecb", 0);
828: }
829: }
830: if (ecbp) {
831: /* Get ECB from from free list */
832: ahb->free_ecb = ecbp->next;
833: ecbp->flags = ECB_ACTIVE;
834: }
835: gottit:
836: if (!(flags & SCSI_NOMASK))
837: splx(opri);
838:
839: return ecbp;
840: }
841:
842: /*
843: * given a physical address, find the ecb that it corresponds to.
844: */
845: struct ecb *
846: ahb_ecb_phys_kv(ahb, ecb_phys)
847: struct ahb_softc *ahb;
848: physaddr ecb_phys;
849: {
850: int hashnum = ECB_HASH(ecb_phys);
851: struct ecb *ecbp = ahb->ecbhash[hashnum];
1.5 deraadt 852:
1.23 mycroft 853: while (ecbp) {
854: if (ecbp->hashkey == ecb_phys)
855: break;
856: ecbp = ecbp->nexthash;
1.1 cgd 857: }
1.23 mycroft 858: return ecbp;
1.1 cgd 859: }
860:
1.5 deraadt 861: /*
862: * Start the board, ready for normal operation
863: */
864: int
1.23 mycroft 865: ahb_find(ahb)
866: struct ahb_softc *ahb;
1.5 deraadt 867: {
1.23 mycroft 868: u_short port = ahb->baseport;
869: u_short stport = port + G2STAT;
870: u_char intdef;
1.5 deraadt 871: int i;
1.23 mycroft 872: int wait = 1000; /* 1 sec enough? */
1.1 cgd 873:
874: #define NO_NO 1
875: #ifdef NO_NO
1.5 deraadt 876: /*
877: * reset board, If it doesn't respond, assume
878: * that it's not there.. good for the probe
879: */
1.23 mycroft 880: outb(port + EBCTRL, CDEN); /* enable full card */
881: outb(port + PORTADDR, PORTADDR_ENHANCED);
1.1 cgd 882:
1.23 mycroft 883: outb(port + G2CNTRL, G2CNTRL_HARD_RESET);
884: delay(1000);
885: outb(port + G2CNTRL, 0);
886: delay(10000);
887: while (--wait) {
888: if ((inb(stport) & G2STAT_BUSY) == 0)
889: break;
890: delay(1000);
891: }
892: if (!wait) {
893: #ifdef AHBDEBUG
1.1 cgd 894: if (ahb_debug & AHB_SHOWMISC)
1.23 mycroft 895: printf("ahb_find: No answer from aha1742 board\n");
896: #endif /*AHBDEBUG */
897: return ENXIO;
898: }
899: i = inb(port + MBOXIN0);
900: if (i) {
901: printf("self test failed, val = 0x%x\n", i);
902: return EIO;
1.1 cgd 903: }
904: #endif
1.5 deraadt 905:
1.23 mycroft 906: while (inb(stport) & G2STAT_INT_PEND) {
1.1 cgd 907: printf(".");
908: outb(port + G2CNTRL, G2CNTRL_CLEAR_EISA_INT);
1.23 mycroft 909: delay(10000);
1.1 cgd 910: }
1.23 mycroft 911: outb(port + EBCTRL, CDEN); /* enable full card */
912: outb(port + PORTADDR, PORTADDR_ENHANCED);
1.5 deraadt 913:
1.1 cgd 914: intdef = inb(port + INTDEF);
1.23 mycroft 915: switch (intdef & 0x07) {
1.5 deraadt 916: case INT9:
1.23 mycroft 917: ahb->vect = 9;
1.1 cgd 918: break;
1.5 deraadt 919: case INT10:
1.23 mycroft 920: ahb->vect = 10;
1.1 cgd 921: break;
1.5 deraadt 922: case INT11:
1.23 mycroft 923: ahb->vect = 11;
1.1 cgd 924: break;
1.5 deraadt 925: case INT12:
1.23 mycroft 926: ahb->vect = 12;
1.1 cgd 927: break;
1.5 deraadt 928: case INT14:
1.23 mycroft 929: ahb->vect = 14;
1.1 cgd 930: break;
1.5 deraadt 931: case INT15:
1.23 mycroft 932: ahb->vect = 15;
1.1 cgd 933: break;
934: default:
1.23 mycroft 935: printf("illegal int setting %x\n", intdef);
936: return EIO;
1.1 cgd 937: }
1.5 deraadt 938:
1.23 mycroft 939: outb(port + INTDEF, (intdef | INTEN)); /* make sure we can interrupt */
1.1 cgd 940:
1.23 mycroft 941: /* who are we on the scsi bus? */
942: ahb->our_id = (inb(port + SCSIDEF) & HSCSIID);
1.1 cgd 943:
1.5 deraadt 944: /*
945: * Note that we are going and return (to probe)
946: */
947: return 0;
1.1 cgd 948: }
949:
1.5 deraadt 950: void
1.23 mycroft 951: ahb_init(ahb)
952: struct ahb_softc *ahb;
1.1 cgd 953: {
1.23 mycroft 954:
955: }
956:
957: void
958: ahbminphys(bp)
959: struct buf *bp;
960: {
961:
962: if (bp->b_bcount > ((AHB_NSEG - 1) << PGSHIFT))
963: bp->b_bcount = ((AHB_NSEG - 1) << PGSHIFT);
1.1 cgd 964: }
1.5 deraadt 965:
966: /*
1.23 mycroft 967: * start a scsi operation given the command and the data address. Also needs
968: * the unit, target and lu.
1.5 deraadt 969: */
1.23 mycroft 970: int
971: ahb_scsi_cmd(xs)
972: struct scsi_xfer *xs;
1.1 cgd 973: {
1.23 mycroft 974: struct scsi_link *sc_link = xs->sc_link;
975: struct ahb_softc *ahb = sc_link->adapter_softc;
1.1 cgd 976: struct ecb *ecb;
977: struct ahb_dma_seg *sg;
1.23 mycroft 978: int seg; /* scatter gather seg being worked on */
979: int thiskv;
980: physaddr thisphys, nextphys;
981: int bytes_this_seg, bytes_this_page, datalen, flags;
982: int s;
983:
984: SC_DEBUG(sc_link, SDEV_DB2, ("ahb_scsi_cmd\n"));
1.5 deraadt 985: /*
986: * get a ecb (mbox-out) to use. If the transfer
987: * is from a buf (possibly from interrupt time)
988: * then we can't allow it to sleep
989: */
1.1 cgd 990: flags = xs->flags;
1.23 mycroft 991: if (xs->bp)
992: flags |= SCSI_NOSLEEP; /* just to be sure */
993: if (flags & ITSDONE) {
994: printf("%s: already done?", ahb->sc_dev.dv_xname);
1.1 cgd 995: xs->flags &= ~ITSDONE;
996: }
1.23 mycroft 997: if (!(flags & INUSE)) {
998: printf("%s: not in use?", ahb->sc_dev.dv_xname);
1.1 cgd 999: xs->flags |= INUSE;
1000: }
1.23 mycroft 1001: if (!(ecb = ahb_get_ecb(ahb, flags))) {
1.1 cgd 1002: xs->error = XS_DRIVER_STUFFUP;
1.23 mycroft 1003: return TRY_AGAIN_LATER;
1.1 cgd 1004: }
1.23 mycroft 1005: cheat = ecb;
1006: SC_DEBUG(sc_link, SDEV_DB3, ("start ecb(%x)\n", ecb));
1007: ecb->xs = xs;
1.1 cgd 1008:
1.5 deraadt 1009: /*
1010: * If it's a reset, we need to do an 'immediate'
1.23 mycroft 1011: * command, and store it's ecb for later
1.5 deraadt 1012: * if there is already an immediate waiting,
1013: * then WE must wait
1014: */
1.23 mycroft 1015: if (flags & SCSI_RESET) {
1.1 cgd 1016: ecb->flags |= ECB_IMMED;
1.23 mycroft 1017: if (ahb->immed_ecb)
1018: return TRY_AGAIN_LATER;
1019: ahb->immed_ecb = ecb;
1.5 deraadt 1020: if (!(flags & SCSI_NOMASK)) {
1.1 cgd 1021: s = splbio();
1.23 mycroft 1022: ahb_send_immed(ahb, sc_link->target, AHB_TARG_RESET);
1023: timeout(ahb_timeout, (caddr_t)ecb, (xs->timeout * hz) / 1000);
1.1 cgd 1024: splx(s);
1.23 mycroft 1025: return SUCCESSFULLY_QUEUED;
1.5 deraadt 1026: } else {
1.23 mycroft 1027: ahb_send_immed(ahb, sc_link->target, AHB_TARG_RESET);
1.5 deraadt 1028: /*
1.23 mycroft 1029: * If we can't use interrupts, poll on completion
1.5 deraadt 1030: */
1.23 mycroft 1031: SC_DEBUG(sc_link, SDEV_DB3, ("wait\n"));
1032: if (ahb_poll(ahb, xs->timeout)) {
1033: ahb_free_ecb(ahb, ecb, flags);
1.1 cgd 1034: xs->error = XS_TIMEOUT;
1.23 mycroft 1035: return HAD_ERROR;
1.1 cgd 1036: }
1.23 mycroft 1037: return COMPLETE;
1.1 cgd 1038: }
1.5 deraadt 1039: }
1040: /*
1041: * Put all the arguments for the xfer in the ecb
1042: */
1.1 cgd 1043: ecb->opcode = ECB_SCSI_OP;
1.23 mycroft 1044: ecb->opt1 = ECB_SES | ECB_DSB | ECB_ARS;
1045: if (xs->datalen)
1.1 cgd 1046: ecb->opt1 |= ECB_S_G;
1.23 mycroft 1047: ecb->opt2 = sc_link->lun | ECB_NRB;
1048: ecb->cdblen = xs->cmdlen;
1049: ecb->sense = KVTOPHYS(&ecb->ecb_sense);
1050: ecb->senselen = sizeof(ecb->ecb_sense);
1051: ecb->status = KVTOPHYS(&ecb->ecb_status);
1052:
1053: if (xs->datalen) { /* should use S/G only if not zero length */
1054: ecb->data = KVTOPHYS(ecb->ahb_dma);
1055: sg = ecb->ahb_dma;
1056: seg = 0;
1057:
1058: #ifdef TFS
1059: if (flags & SCSI_DATA_UIO) {
1060: iovp = ((struct uio *) xs->data)->uio_iov;
1061: datalen = ((struct uio *) xs->data)->uio_iovcnt;
1.1 cgd 1062: xs->datalen = 0;
1.23 mycroft 1063: while (datalen && seg < AHB_NSEG) {
1064: sg->addr = (physaddr) iovp->iov_base;
1.5 deraadt 1065: xs->datalen += sg->len = iovp->iov_len;
1.23 mycroft 1066: SC_DEBUGN(sc_link, SDEV_DB4, ("(0x%x@0x%x)",
1067: iovp->iov_len, iovp->iov_base));
1.1 cgd 1068: sg++;
1069: iovp++;
1070: seg++;
1071: datalen--;
1072: }
1.23 mycroft 1073: }
1074: else
1075: #endif /*TFS */
1076: {
1077: /*
1078: * Set up the scatter gather block
1079: */
1080: SC_DEBUG(sc_link, SDEV_DB4,
1081: ("%d @0x%x:- ", xs->datalen, xs->data));
1082: datalen = xs->datalen;
1083: thiskv = (int) xs->data;
1084: thisphys = KVTOPHYS(thiskv);
1.5 deraadt 1085:
1.23 mycroft 1086: while (datalen && seg < AHB_NSEG) {
1087: bytes_this_seg = 0;
1.5 deraadt 1088:
1.1 cgd 1089: /* put in the base address */
1090: sg->addr = thisphys;
1.5 deraadt 1091:
1.23 mycroft 1092: SC_DEBUGN(sc_link, SDEV_DB4,
1093: ("0x%x", thisphys));
1.5 deraadt 1094:
1.1 cgd 1095: /* do it at least once */
1.5 deraadt 1096: nextphys = thisphys;
1097: while ((datalen) && (thisphys == nextphys)) {
1.23 mycroft 1098: /*
1099: * This page is contiguous (physically)
1100: * with the the last, just extend the
1101: * length
1102: */
1103: /* how far to the end of the page */
1104: nextphys = (thisphys & ~PGOFSET) + NBPG;
1105: bytes_this_page = nextphys - thisphys;
1106: /**** or the data ****/
1107: bytes_this_page = min(bytes_this_page,
1108: datalen);
1109: bytes_this_seg += bytes_this_page;
1110: datalen -= bytes_this_page;
1.5 deraadt 1111:
1.1 cgd 1112: /* get more ready for the next page */
1.23 mycroft 1113: thiskv = (thiskv & ~PGOFSET) + NBPG;
1114: if (datalen)
1.1 cgd 1115: thisphys = KVTOPHYS(thiskv);
1116: }
1.5 deraadt 1117: /*
1.23 mycroft 1118: * next page isn't contiguous, finish the seg
1.5 deraadt 1119: */
1.23 mycroft 1120: SC_DEBUGN(sc_link, SDEV_DB4,
1121: ("(0x%x)", bytes_this_seg));
1.5 deraadt 1122: sg->len = bytes_this_seg;
1.1 cgd 1123: sg++;
1124: seg++;
1125: }
1.5 deraadt 1126: }
1.23 mycroft 1127:
1128: /*end of iov/kv decision */
1.1 cgd 1129: ecb->datalen = seg * sizeof(struct ahb_dma_seg);
1.23 mycroft 1130: SC_DEBUGN(sc_link, SDEV_DB4, ("\n"));
1131:
1.5 deraadt 1132: if (datalen) {
1.23 mycroft 1133: /*
1134: * there's still data, must have run out of segs!
1135: */
1136: printf("%s: ahb_scsi_cmd, more than %d DMA segs\n",
1137: ahb->sc_dev.dv_xname, AHB_NSEG);
1.1 cgd 1138: xs->error = XS_DRIVER_STUFFUP;
1.23 mycroft 1139: ahb_free_ecb(ahb, ecb, flags);
1140: return HAD_ERROR;
1.1 cgd 1141: }
1.23 mycroft 1142: } else { /* No data xfer, use non S/G values */
1143: ecb->data = (physaddr) 0;
1.1 cgd 1144: ecb->datalen = 0;
1145: }
1.23 mycroft 1146: ecb->chain = (physaddr) 0;
1.5 deraadt 1147:
1148: /*
1149: * Put the scsi command in the ecb and start it
1150: */
1.1 cgd 1151: bcopy(xs->cmd, ecb->cdb, xs->cmdlen);
1.5 deraadt 1152:
1.23 mycroft 1153: /*
1154: * Usually return SUCCESSFULLY QUEUED
1155: */
1156: if (!(flags & SCSI_NOMASK)) {
1.1 cgd 1157: s = splbio();
1.23 mycroft 1158: ahb_send_mbox(ahb, OP_START_ECB, sc_link->target, ecb);
1159: timeout(ahb_timeout, (caddr_t)ecb, (xs->timeout * hz) / 1000);
1.1 cgd 1160: splx(s);
1.23 mycroft 1161: SC_DEBUG(sc_link, SDEV_DB3, ("cmd_sent\n"));
1162: return SUCCESSFULLY_QUEUED;
1.1 cgd 1163: }
1.5 deraadt 1164:
1.23 mycroft 1165: /*
1166: * If we can't use interrupts, poll on completion
1167: */
1168: ahb_send_mbox(ahb, OP_START_ECB, sc_link->target, ecb);
1169: SC_DEBUG(sc_link, SDEV_DB3, ("cmd_wait\n"));
1.5 deraadt 1170: do {
1.23 mycroft 1171: if (ahb_poll(ahb, xs->timeout)) {
1172: if (!(xs->flags & SCSI_SILENT))
1173: printf("%s: cmd fail\n", ahb->sc_dev.dv_xname);
1174: ahb_send_mbox(ahb, OP_ABORT_ECB, sc_link->target, ecb);
1175: if (ahb_poll(ahb, 2000)) {
1176: printf("%s: abort failed in wait\n",
1177: ahb->sc_dev.dv_xname);
1178: ahb_free_ecb(ahb, ecb, flags);
1.1 cgd 1179: }
1180: xs->error = XS_DRIVER_STUFFUP;
1.23 mycroft 1181: return HAD_ERROR;
1.1 cgd 1182: }
1.23 mycroft 1183: } while (!(xs->flags & ITSDONE));/* something (?) else finished */
1184: if (xs->error)
1.5 deraadt 1185: return HAD_ERROR;
1186: return COMPLETE;
1.1 cgd 1187: }
1188:
1.5 deraadt 1189: void
1.23 mycroft 1190: ahb_timeout(arg)
1191: caddr_t arg;
1.1 cgd 1192: {
1.5 deraadt 1193: int s = splbio();
1.23 mycroft 1194: struct ecb *ecb = (void *)arg;
1195: struct ahb_softc *ahb = ecb->xs->sc_link->adapter_softc;
1.1 cgd 1196:
1.23 mycroft 1197: sc_print_addr(ecb->xs->sc_link);
1198: printf("timed out ");
1.1 cgd 1199:
1.23 mycroft 1200: #ifdef AHBDEBUG
1201: if (ahb_debug & AHB_SHOWECBS)
1202: ahb_print_active_ecb(ahb);
1203: #endif /*AHBDEBUG */
1.1 cgd 1204:
1.23 mycroft 1205: /*
1206: * If it's immediate, don't try abort it
1207: */
1208: if (ecb->flags & ECB_IMMED) {
1209: ecb->xs->retries = 0; /* I MEAN IT ! */
1210: ecb->flags |= ECB_IMMED_FAIL;
1211: ahb_done(ahb, ecb, 1);
1212: splx(s);
1213: return;
1.1 cgd 1214: }
1215:
1.23 mycroft 1216: /*
1217: * If it has been through before, then
1218: * a previous abort has failed, don't
1219: * try abort again
1220: */
1221: if (ecb->flags == ECB_ABORTED) {
1222: printf("AGAIN\n");
1223: ecb->xs->retries = 0; /* I MEAN IT ! */
1224: ecb->ecb_status.ha_status = HS_CMD_ABORTED_HOST;
1225: ahb_done(ahb, ecb, 1);
1226: } else { /* abort the operation that has timed out */
1.5 deraadt 1227: printf("\n");
1.23 mycroft 1228: ahb_send_mbox(ahb, OP_ABORT_ECB, ecb->xs->sc_link->target, ecb);
1229: timeout(ahb_timeout, (caddr_t)ecb, 2 * hz);
1230: ecb->flags = ECB_ABORTED;
1.1 cgd 1231: }
1.23 mycroft 1232: splx(s);
1.1 cgd 1233: }
1.5 deraadt 1234:
1.23 mycroft 1235: #ifdef AHBDEBUG
1.5 deraadt 1236: void
1.23 mycroft 1237: ahb_print_ecb(ecb)
1238: struct ecb *ecb;
1.1 cgd 1239: {
1.23 mycroft 1240: printf("ecb:%x op:%x cmdlen:%d senlen:%d\n",
1241: ecb, ecb->opcode, ecb->cdblen, ecb->senselen);
1242: printf(" datlen:%d hstat:%x tstat:%x flags:%x\n",
1.5 deraadt 1243: ecb->datalen, ecb->ecb_status.ha_status,
1.23 mycroft 1244: ecb->ecb_status.targ_status, ecb->flags);
1245: show_scsi_cmd(ecb->xs);
1.1 cgd 1246: }
1247:
1.5 deraadt 1248: void
1.23 mycroft 1249: ahb_print_active_ecb(ahb)
1250: struct ahb_softc *ahb;
1.1 cgd 1251: {
1.5 deraadt 1252: struct ecb *ecb;
1.23 mycroft 1253: int i = 0;
1.1 cgd 1254:
1.23 mycroft 1255: while (i++ < ECB_HASH_SIZE) {
1256: ecb = ahb->ecbhash[i];
1257: while (ecb) {
1258: if (ecb->flags != ECB_FREE)
1259: ahb_print_ecb(ecb);
1260: ecb = ecb->nexthash;
1261: }
1.1 cgd 1262: }
1263: }
1.23 mycroft 1264: #endif /* AHBDEBUG */
CVSweb <webmaster@jp.NetBSD.org>