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