Annotation of sys/dev/ic/bha.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: bha.c,v 1.10 2007/04/10 17:47:55 miod Exp $ */
2: /* $NetBSD: bha.c,v 1.27 1998/11/19 21:53:00 thorpej Exp $ */
3:
4: #undef BHADEBUG
5: #ifdef DDB
6: #define integrate
7: #else
8: #define integrate static inline
9: #endif
10:
11: /*-
12: * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
13: * All rights reserved.
14: *
15: * This code is derived from software contributed to The NetBSD Foundation
16: * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
17: * Simulation Facility, NASA Ames Research Center.
18: *
19: * Redistribution and use in source and binary forms, with or without
20: * modification, are permitted provided that the following conditions
21: * are met:
22: * 1. Redistributions of source code must retain the above copyright
23: * notice, this list of conditions and the following disclaimer.
24: * 2. Redistributions in binary form must reproduce the above copyright
25: * notice, this list of conditions and the following disclaimer in the
26: * documentation and/or other materials provided with the distribution.
27: * 3. All advertising materials mentioning features or use of this software
28: * must display the following acknowledgement:
29: * This product includes software developed by the NetBSD
30: * Foundation, Inc. and its contributors.
31: * 4. Neither the name of The NetBSD Foundation nor the names of its
32: * contributors may be used to endorse or promote products derived
33: * from this software without specific prior written permission.
34: *
35: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
36: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
37: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
38: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
39: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
40: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
41: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
42: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
43: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
44: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
45: * POSSIBILITY OF SUCH DAMAGE.
46: */
47:
48: /*
49: * Originally written by Julian Elischer (julian@tfs.com)
50: * for TRW Financial Systems for use under the MACH(2.5) operating system.
51: *
52: * TRW Financial Systems, in accordance with their agreement with Carnegie
53: * Mellon University, makes this software available to CMU to distribute
54: * or use in any manner that they see fit as long as this message is kept with
55: * the software. For this reason TFS also grants any other persons or
56: * organisations permission to use or modify this software.
57: *
58: * TFS supplies this software to be publicly redistributed
59: * on the understanding that TFS is not responsible for the correct
60: * functioning of this software in any circumstances.
61: */
62:
63: #include <sys/types.h>
64: #include <sys/param.h>
65: #include <sys/systm.h>
66: #include <sys/kernel.h>
67: #include <sys/errno.h>
68: #include <sys/ioctl.h>
69: #include <sys/device.h>
70: #include <sys/malloc.h>
71: #include <sys/buf.h>
72: #include <sys/proc.h>
73: #include <sys/user.h>
74:
75: #include <machine/bus.h>
76: #include <machine/intr.h>
77:
78: #include <scsi/scsi_all.h>
79: #include <scsi/scsiconf.h>
80:
81: #include <dev/ic/bhareg.h>
82: #include <dev/ic/bhavar.h>
83:
84: #ifndef DDB
85: #define Debugger() panic("should call debugger here (bha.c)")
86: #endif /* ! DDB */
87:
88: #define BHA_MAXXFER ((BHA_NSEG - 1) << PGSHIFT)
89: #define ISWIDE(sc) ((sc)->sc_iswide)
90:
91: #ifdef BHADEBUG
92: int bha_debug = 1;
93: #endif /* BHADEBUG */
94:
95: integrate void bha_finish_ccbs(struct bha_softc *);
96: integrate void bha_reset_ccb(struct bha_softc *, struct bha_ccb *);
97: void bha_free_ccb(struct bha_softc *, struct bha_ccb *);
98: integrate int bha_init_ccb(struct bha_softc *, struct bha_ccb *);
99: struct bha_ccb *bha_get_ccb(struct bha_softc *, int);
100: struct bha_ccb *bha_ccb_phys_kv(struct bha_softc *, u_long);
101: void bha_queue_ccb(struct bha_softc *, struct bha_ccb *);
102: void bha_collect_mbo(struct bha_softc *);
103: void bha_start_ccbs(struct bha_softc *);
104: void bha_done(struct bha_softc *, struct bha_ccb *);
105: int bha_init(struct bha_softc *);
106: void bhaminphys(struct buf *);
107: int bha_scsi_cmd(struct scsi_xfer *);
108: int bha_poll(struct bha_softc *, struct scsi_xfer *, int);
109: void bha_timeout(void *arg);
110: int bha_create_ccbs(struct bha_softc *, struct bha_ccb *, int);
111: void bha_enqueue(struct bha_softc *, struct scsi_xfer *, int);
112: struct scsi_xfer *bha_dequeue(struct bha_softc *);
113:
114: struct cfdriver bha_cd = {
115: NULL, "bha", DV_DULL
116: };
117:
118: /* the below structure is so we have a default dev struct for out link struct */
119: struct scsi_device bha_dev = {
120: NULL, /* Use default error handler */
121: NULL, /* have a queue, served by this */
122: NULL, /* have no async handler */
123: NULL, /* Use default 'done' routine */
124: };
125:
126: #define BHA_RESET_TIMEOUT 2000 /* time to wait for reset (mSec) */
127: #define BHA_ABORT_TIMEOUT 2000 /* time to wait for abort (mSec) */
128:
129: /*
130: * Insert a scsi_xfer into the software queue. We overload xs->free_list
131: * to avoid having to allocate additional resources (since we're used
132: * only during resource shortages anyhow.
133: */
134: void
135: bha_enqueue(sc, xs, infront)
136: struct bha_softc *sc;
137: struct scsi_xfer *xs;
138: int infront;
139: {
140:
141: if (infront || LIST_EMPTY(&sc->sc_queue)) {
142: if (LIST_EMPTY(&sc->sc_queue))
143: sc->sc_queuelast = xs;
144: LIST_INSERT_HEAD(&sc->sc_queue, xs, free_list);
145: return;
146: }
147:
148: LIST_INSERT_AFTER(sc->sc_queuelast, xs, free_list);
149: sc->sc_queuelast = xs;
150: }
151:
152: /*
153: * Pull a scsi_xfer off the front of the software queue.
154: */
155: struct scsi_xfer *
156: bha_dequeue(sc)
157: struct bha_softc *sc;
158: {
159: struct scsi_xfer *xs;
160:
161: xs = LIST_FIRST(&sc->sc_queue);
162: LIST_REMOVE(xs, free_list);
163:
164: if (LIST_EMPTY(&sc->sc_queue))
165: sc->sc_queuelast = NULL;
166:
167: return (xs);
168: }
169:
170: /*
171: * bha_cmd(iot, ioh, sc, icnt, ibuf, ocnt, obuf)
172: *
173: * Activate Adapter command
174: * icnt: number of args (outbound bytes including opcode)
175: * ibuf: argument buffer
176: * ocnt: number of expected returned bytes
177: * obuf: result buffer
178: * wait: number of seconds to wait for response
179: *
180: * Performs an adapter command through the ports. Not to be confused with a
181: * scsi command, which is read in via the dma; one of the adapter commands
182: * tells it to read in a scsi command.
183: */
184: int
185: bha_cmd(iot, ioh, sc, icnt, ibuf, ocnt, obuf)
186: bus_space_tag_t iot;
187: bus_space_handle_t ioh;
188: struct bha_softc *sc;
189: int icnt, ocnt;
190: u_char *ibuf, *obuf;
191: {
192: const char *name;
193: register int i;
194: int wait;
195: u_char sts;
196: u_char opcode = ibuf[0];
197:
198: if (sc != NULL)
199: name = sc->sc_dev.dv_xname;
200: else
201: name = "(bha probe)";
202:
203: /*
204: * Calculate a reasonable timeout for the command.
205: */
206: switch (opcode) {
207: case BHA_INQUIRE_DEVICES:
208: case BHA_INQUIRE_DEVICES_2:
209: wait = 90 * 20000;
210: break;
211: default:
212: wait = 1 * 20000;
213: break;
214: }
215:
216: /*
217: * Wait for the adapter to go idle, unless it's one of
218: * the commands which don't need this
219: */
220: if (opcode != BHA_MBO_INTR_EN) {
221: for (i = 20000; i; i--) { /* 1 sec? */
222: sts = bus_space_read_1(iot, ioh, BHA_STAT_PORT);
223: if (sts & BHA_STAT_IDLE)
224: break;
225: delay(50);
226: }
227: if (!i) {
228: printf("%s: bha_cmd, host not idle(0x%x)\n",
229: name, sts);
230: return (1);
231: }
232: }
233: /*
234: * Now that it is idle, if we expect output, preflush the
235: * queue feeding to us.
236: */
237: if (ocnt) {
238: while ((bus_space_read_1(iot, ioh, BHA_STAT_PORT)) &
239: BHA_STAT_DF)
240: bus_space_read_1(iot, ioh, BHA_DATA_PORT);
241: }
242: /*
243: * Output the command and the number of arguments given
244: * for each byte, first check the port is empty.
245: */
246: while (icnt--) {
247: for (i = wait; i; i--) {
248: sts = bus_space_read_1(iot, ioh, BHA_STAT_PORT);
249: if (!(sts & BHA_STAT_CDF))
250: break;
251: delay(50);
252: }
253: if (!i) {
254: if (opcode != BHA_INQUIRE_REVISION)
255: printf("%s: bha_cmd, cmd/data port full\n",
256: name);
257: goto bad;
258: }
259: bus_space_write_1(iot, ioh, BHA_CMD_PORT, *ibuf++);
260: }
261: /*
262: * If we expect input, loop that many times, each time,
263: * looking for the data register to have valid data
264: */
265: while (ocnt--) {
266: for (i = wait; i; i--) {
267: sts = bus_space_read_1(iot, ioh, BHA_STAT_PORT);
268: if (sts & BHA_STAT_DF)
269: break;
270: delay(50);
271: }
272: if (!i) {
273: if (opcode != BHA_INQUIRE_REVISION)
274: printf("%s: bha_cmd, cmd/data port empty %d\n",
275: name, ocnt);
276: goto bad;
277: }
278: *obuf++ = bus_space_read_1(iot, ioh, BHA_DATA_PORT);
279: }
280: /*
281: * Wait for the board to report a finished instruction.
282: * We may get an extra interrupt for the HACC signal, but this is
283: * unimportant.
284: */
285: if (opcode != BHA_MBO_INTR_EN && opcode != BHA_MODIFY_IOPORT) {
286: for (i = 20000; i; i--) { /* 1 sec? */
287: sts = bus_space_read_1(iot, ioh, BHA_INTR_PORT);
288: /* XXX Need to save this in the interrupt handler? */
289: if (sts & BHA_INTR_HACC)
290: break;
291: delay(50);
292: }
293: if (!i) {
294: printf("%s: bha_cmd, host not finished(0x%x)\n",
295: name, sts);
296: return (1);
297: }
298: }
299: bus_space_write_1(iot, ioh, BHA_CTRL_PORT, BHA_CTRL_IRST);
300: return (0);
301:
302: bad:
303: bus_space_write_1(iot, ioh, BHA_CTRL_PORT, BHA_CTRL_SRST);
304: return (1);
305: }
306:
307: /*
308: * Attach all the sub-devices we can find
309: */
310: void
311: bha_attach(sc, bpd)
312: struct bha_softc *sc;
313: struct bha_probe_data *bpd;
314: {
315: struct scsibus_attach_args saa;
316: int s;
317:
318: /*
319: * Fill in the adapter.
320: */
321: sc->sc_adapter.scsi_cmd = bha_scsi_cmd;
322: sc->sc_adapter.scsi_minphys = bhaminphys;
323:
324: /*
325: * fill in the prototype scsi_link.
326: */
327: sc->sc_link.adapter_softc = sc;
328: sc->sc_link.adapter_target = bpd->sc_scsi_dev;
329: sc->sc_link.adapter = &sc->sc_adapter;
330: sc->sc_link.device = &bha_dev;
331: sc->sc_link.openings = 4;
332:
333: TAILQ_INIT(&sc->sc_free_ccb);
334: TAILQ_INIT(&sc->sc_waiting_ccb);
335: LIST_INIT(&sc->sc_queue);
336:
337: s = splbio();
338: bha_inquire_setup_information(sc);
339:
340: printf("%s: model BT-%s, firmware %s\n", sc->sc_dev.dv_xname,
341: sc->sc_model, sc->sc_firmware);
342:
343: if (bha_init(sc) != 0) {
344: /* Error during initialization! */
345: splx(s);
346: return;
347: }
348:
349: splx(s);
350:
351: bzero(&saa, sizeof(saa));
352: saa.saa_sc_link = &sc->sc_link;
353:
354: /*
355: * ask the adapter what subunits are present
356: */
357: config_found(&sc->sc_dev, &saa, scsiprint);
358: }
359:
360: integrate void
361: bha_finish_ccbs(sc)
362: struct bha_softc *sc;
363: {
364: struct bha_mbx_in *wmbi;
365: struct bha_ccb *ccb;
366: int i;
367:
368: wmbi = wmbx->tmbi;
369:
370: bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control,
371: 0, sc->sc_dmamap_control->dm_mapsize,
372: BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
373:
374: if (wmbi->comp_stat == BHA_MBI_FREE) {
375: for (i = 0; i < BHA_MBX_SIZE; i++) {
376: if (wmbi->comp_stat != BHA_MBI_FREE) {
377: printf("%s: mbi not in round-robin order\n",
378: sc->sc_dev.dv_xname);
379: goto AGAIN;
380: }
381: bha_nextmbx(wmbi, wmbx, mbi);
382: bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control,
383: 0, sc->sc_dmamap_control->dm_mapsize,
384: BUS_DMASYNC_POSTREAD);
385: }
386: #ifdef BHADIAGnot
387: printf("%s: mbi interrupt with no full mailboxes\n",
388: sc->sc_dev.dv_xname);
389: #endif
390: return;
391: }
392:
393: AGAIN:
394: do {
395: ccb = bha_ccb_phys_kv(sc, phystol(wmbi->ccb_addr));
396: if (!ccb) {
397: printf("%s: bad mbi ccb pointer; skipping\n",
398: sc->sc_dev.dv_xname);
399: goto next;
400: }
401:
402: bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control,
403: 0, sc->sc_dmamap_control->dm_mapsize,
404: BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
405:
406: #ifdef BHADEBUG
407: if (bha_debug) {
408: u_int8_t *cp = ccb->scsi_cmd.bytes;
409: printf("op=%x %x %x %x %x %x\n",
410: ccb->scsi_cmd.opcode,
411: cp[0], cp[1], cp[2], cp[3], cp[4]);
412: printf("stat %x for mbi addr = 0x%08x, ",
413: wmbi->comp_stat, wmbi);
414: printf("ccb addr = 0x%x\n", ccb);
415: }
416: #endif /* BHADEBUG */
417:
418: switch (wmbi->comp_stat) {
419: case BHA_MBI_OK:
420: case BHA_MBI_ERROR:
421: if ((ccb->flags & CCB_ABORT) != 0) {
422: /*
423: * If we already started an abort, wait for it
424: * to complete before clearing the CCB. We
425: * could instead just clear CCB_SENDING, but
426: * what if the mailbox was already received?
427: * The worst that happens here is that we clear
428: * the CCB a bit later than we need to. BFD.
429: */
430: goto next;
431: }
432: break;
433:
434: case BHA_MBI_ABORT:
435: case BHA_MBI_UNKNOWN:
436: /*
437: * Even if the CCB wasn't found, we clear it anyway.
438: * See preceding comment.
439: */
440: break;
441:
442: default:
443: printf("%s: bad mbi status %02x; skipping\n",
444: sc->sc_dev.dv_xname, wmbi->comp_stat);
445: goto next;
446: }
447:
448: timeout_del(&ccb->xs->stimeout);
449: bha_done(sc, ccb);
450:
451: next:
452: wmbi->comp_stat = BHA_MBI_FREE;
453: bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control,
454: 0, sc->sc_dmamap_control->dm_mapsize,
455: BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
456: bha_nextmbx(wmbi, wmbx, mbi);
457: bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control,
458: 0, sc->sc_dmamap_control->dm_mapsize,
459: BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
460: } while (wmbi->comp_stat != BHA_MBI_FREE);
461:
462: wmbx->tmbi = wmbi;
463: }
464:
465: /*
466: * Catch an interrupt from the adaptor
467: */
468: int
469: bha_intr(arg)
470: void *arg;
471: {
472: struct bha_softc *sc = arg;
473: bus_space_tag_t iot = sc->sc_iot;
474: bus_space_handle_t ioh = sc->sc_ioh;
475: u_char sts;
476:
477: #ifdef BHADEBUG
478: printf("%s: bha_intr ", sc->sc_dev.dv_xname);
479: #endif /* BHADEBUG */
480:
481: /*
482: * First acknowledge the interrupt, Then if it's not telling about
483: * a completed operation just return.
484: */
485: sts = bus_space_read_1(iot, ioh, BHA_INTR_PORT);
486: if ((sts & BHA_INTR_ANYINTR) == 0)
487: return (0);
488: bus_space_write_1(iot, ioh, BHA_CTRL_PORT, BHA_CTRL_IRST);
489:
490: #ifdef BHADIAG
491: /* Make sure we clear CCB_SENDING before finishing a CCB. */
492: bha_collect_mbo(sc);
493: #endif
494:
495: /* Mail box out empty? */
496: if (sts & BHA_INTR_MBOA) {
497: struct bha_toggle toggle;
498:
499: toggle.cmd.opcode = BHA_MBO_INTR_EN;
500: toggle.cmd.enable = 0;
501: bha_cmd(iot, ioh, sc,
502: sizeof(toggle.cmd), (u_char *)&toggle.cmd,
503: 0, (u_char *)0);
504: bha_start_ccbs(sc);
505: }
506:
507: /* Mail box in full? */
508: if (sts & BHA_INTR_MBIF)
509: bha_finish_ccbs(sc);
510:
511: return (1);
512: }
513:
514: integrate void
515: bha_reset_ccb(sc, ccb)
516: struct bha_softc *sc;
517: struct bha_ccb *ccb;
518: {
519:
520: ccb->flags = 0;
521: }
522:
523: /*
524: * A ccb is put onto the free list.
525: */
526: void
527: bha_free_ccb(sc, ccb)
528: struct bha_softc *sc;
529: struct bha_ccb *ccb;
530: {
531: int s;
532:
533: s = splbio();
534:
535: bha_reset_ccb(sc, ccb);
536: TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, chain);
537:
538: /*
539: * If there were none, wake anybody waiting for one to come free,
540: * starting with queued entries.
541: */
542: if (TAILQ_NEXT(ccb, chain) == NULL)
543: wakeup(&sc->sc_free_ccb);
544:
545: splx(s);
546: }
547:
548: integrate int
549: bha_init_ccb(sc, ccb)
550: struct bha_softc *sc;
551: struct bha_ccb *ccb;
552: {
553: bus_dma_tag_t dmat = sc->sc_dmat;
554: int hashnum, error;
555:
556: /*
557: * Create the DMA map for this CCB.
558: */
559: error = bus_dmamap_create(dmat, BHA_MAXXFER, BHA_NSEG, BHA_MAXXFER,
560: 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW | sc->sc_dmaflags,
561: &ccb->dmamap_xfer);
562: if (error) {
563: printf("%s: unable to create ccb DMA map, error = %d\n",
564: sc->sc_dev.dv_xname, error);
565: return (error);
566: }
567:
568: /*
569: * put in the phystokv hash table
570: * Never gets taken out.
571: */
572: ccb->hashkey = sc->sc_dmamap_control->dm_segs[0].ds_addr +
573: BHA_CCB_OFF(ccb);
574: hashnum = CCB_HASH(ccb->hashkey);
575: ccb->nexthash = sc->sc_ccbhash[hashnum];
576: sc->sc_ccbhash[hashnum] = ccb;
577: bha_reset_ccb(sc, ccb);
578: return (0);
579: }
580:
581: /*
582: * Create a set of ccbs and add them to the free list. Called once
583: * by bha_init(). We return the number of CCBs successfully created.
584: */
585: int
586: bha_create_ccbs(sc, ccbstore, count)
587: struct bha_softc *sc;
588: struct bha_ccb *ccbstore;
589: int count;
590: {
591: struct bha_ccb *ccb;
592: int i, error;
593:
594: bzero(ccbstore, sizeof(struct bha_ccb) * count);
595: for (i = 0; i < count; i++) {
596: ccb = &ccbstore[i];
597: if ((error = bha_init_ccb(sc, ccb)) != 0) {
598: printf("%s: unable to initialize ccb, error = %d\n",
599: sc->sc_dev.dv_xname, error);
600: goto out;
601: }
602: TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, chain);
603: }
604: out:
605: return (i);
606: }
607:
608: /*
609: * Get a free ccb
610: *
611: * If there are none, see if we can allocate a new one. If so, put it in
612: * the hash table too otherwise either return an error or sleep.
613: */
614: struct bha_ccb *
615: bha_get_ccb(sc, flags)
616: struct bha_softc *sc;
617: int flags;
618: {
619: struct bha_ccb *ccb;
620: int s;
621:
622: s = splbio();
623:
624: /*
625: * If we can and have to, sleep waiting for one to come free
626: * but only if we can't allocate a new one.
627: */
628: for (;;) {
629: ccb = TAILQ_FIRST(&sc->sc_free_ccb);
630: if (ccb) {
631: TAILQ_REMOVE(&sc->sc_free_ccb, ccb, chain);
632: break;
633: }
634: if ((flags & SCSI_NOSLEEP) != 0)
635: goto out;
636: tsleep(&sc->sc_free_ccb, PRIBIO, "bhaccb", 0);
637: }
638:
639: ccb->flags |= CCB_ALLOC;
640:
641: out:
642: splx(s);
643: return (ccb);
644: }
645:
646: /*
647: * Given a physical address, find the ccb that it corresponds to.
648: */
649: struct bha_ccb *
650: bha_ccb_phys_kv(sc, ccb_phys)
651: struct bha_softc *sc;
652: u_long ccb_phys;
653: {
654: int hashnum = CCB_HASH(ccb_phys);
655: struct bha_ccb *ccb = sc->sc_ccbhash[hashnum];
656:
657: while (ccb) {
658: if (ccb->hashkey == ccb_phys)
659: break;
660: ccb = ccb->nexthash;
661: }
662: return (ccb);
663: }
664:
665: /*
666: * Queue a CCB to be sent to the controller, and send it if possible.
667: */
668: void
669: bha_queue_ccb(sc, ccb)
670: struct bha_softc *sc;
671: struct bha_ccb *ccb;
672: {
673:
674: timeout_set(&ccb->xs->stimeout, bha_timeout, ccb);
675: TAILQ_INSERT_TAIL(&sc->sc_waiting_ccb, ccb, chain);
676: bha_start_ccbs(sc);
677: }
678:
679: /*
680: * Garbage collect mailboxes that are no longer in use.
681: */
682: void
683: bha_collect_mbo(sc)
684: struct bha_softc *sc;
685: {
686: struct bha_mbx_out *wmbo; /* Mail Box Out pointer */
687: #ifdef BHADIAG
688: struct bha_ccb *ccb;
689: #endif
690:
691: wmbo = wmbx->cmbo;
692:
693: while (sc->sc_mbofull > 0) {
694: bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control,
695: 0, sc->sc_dmamap_control->dm_mapsize,
696: BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
697: if (wmbo->cmd != BHA_MBO_FREE)
698: break;
699:
700: #ifdef BHADIAG
701: ccb = bha_ccb_phys_kv(sc, phystol(wmbo->ccb_addr));
702: ccb->flags &= ~CCB_SENDING;
703: #endif
704:
705: --sc->sc_mbofull;
706: bha_nextmbx(wmbo, wmbx, mbo);
707: }
708:
709: wmbx->cmbo = wmbo;
710: }
711:
712: /*
713: * Send as many CCBs as we have empty mailboxes for.
714: */
715: void
716: bha_start_ccbs(sc)
717: struct bha_softc *sc;
718: {
719: bus_space_tag_t iot = sc->sc_iot;
720: bus_space_handle_t ioh = sc->sc_ioh;
721: struct bha_mbx_out *wmbo; /* Mail Box Out pointer */
722: struct bha_ccb *ccb;
723: struct scsi_xfer *xs;
724:
725: wmbo = wmbx->tmbo;
726:
727: while ((ccb = TAILQ_FIRST(&sc->sc_waiting_ccb)) != NULL) {
728:
729: xs = ccb->xs;
730: if (sc->sc_mbofull >= BHA_MBX_SIZE) {
731: bha_collect_mbo(sc);
732: if (sc->sc_mbofull >= BHA_MBX_SIZE) {
733: struct bha_toggle toggle;
734:
735: toggle.cmd.opcode = BHA_MBO_INTR_EN;
736: toggle.cmd.enable = 1;
737: bha_cmd(iot, ioh, sc,
738: sizeof(toggle.cmd), (u_char *)&toggle.cmd,
739: 0, (u_char *)0);
740: break;
741: }
742: }
743:
744: TAILQ_REMOVE(&sc->sc_waiting_ccb, ccb, chain);
745: #ifdef BHADIAG
746: ccb->flags |= CCB_SENDING;
747: #endif
748:
749: /* Link ccb to mbo. */
750: ltophys(sc->sc_dmamap_control->dm_segs[0].ds_addr +
751: BHA_CCB_OFF(ccb), wmbo->ccb_addr);
752: if (ccb->flags & CCB_ABORT)
753: wmbo->cmd = BHA_MBO_ABORT;
754: else
755: wmbo->cmd = BHA_MBO_START;
756:
757: bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control,
758: 0, sc->sc_dmamap_control->dm_mapsize,
759: BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
760:
761: /* Tell the card to poll immediately. */
762: bus_space_write_1(iot, ioh, BHA_CMD_PORT, BHA_START_SCSI);
763:
764: if ((xs->flags & SCSI_POLL) == 0)
765: timeout_add(&xs->stimeout, (ccb->timeout * hz) / 1000);
766:
767: ++sc->sc_mbofull;
768: bha_nextmbx(wmbo, wmbx, mbo);
769: }
770:
771: wmbx->tmbo = wmbo;
772: }
773:
774: /*
775: * We have a ccb which has been processed by the
776: * adaptor, now we look to see how the operation
777: * went. Wake up the owner if waiting
778: */
779: void
780: bha_done(sc, ccb)
781: struct bha_softc *sc;
782: struct bha_ccb *ccb;
783: {
784: bus_dma_tag_t dmat = sc->sc_dmat;
785: struct scsi_sense_data *s1, *s2;
786: struct scsi_xfer *xs = ccb->xs;
787:
788: SC_DEBUG(xs->sc_link, SDEV_DB2, ("bha_done\n"));
789:
790: /*
791: * If we were a data transfer, unload the map that described
792: * the data buffer.
793: */
794: if (xs->datalen) {
795: bus_dmamap_sync(dmat, ccb->dmamap_xfer,
796: 0, ccb->dmamap_xfer->dm_mapsize,
797: (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_POSTREAD :
798: BUS_DMASYNC_POSTWRITE);
799: bus_dmamap_unload(dmat, ccb->dmamap_xfer);
800: }
801:
802: /*
803: * Otherwise, put the results of the operation
804: * into the xfer and call whoever started it
805: */
806: #ifdef BHADIAG
807: if (ccb->flags & CCB_SENDING) {
808: printf("%s: exiting ccb still in transit!\n",
809: sc->sc_dev.dv_xname);
810: Debugger();
811: return;
812: }
813: #endif
814: if ((ccb->flags & CCB_ALLOC) == 0) {
815: printf("%s: exiting ccb not allocated!\n",
816: sc->sc_dev.dv_xname);
817: Debugger();
818: return;
819: }
820: if (xs->error == XS_NOERROR) {
821: if (ccb->host_stat != BHA_OK) {
822: switch (ccb->host_stat) {
823: case BHA_SEL_TIMEOUT: /* No response */
824: xs->error = XS_SELTIMEOUT;
825: break;
826: default: /* Other scsi protocol messes */
827: printf("%s: host_stat %x\n",
828: sc->sc_dev.dv_xname, ccb->host_stat);
829: xs->error = XS_DRIVER_STUFFUP;
830: break;
831: }
832: } else if (ccb->target_stat != SCSI_OK) {
833: switch (ccb->target_stat) {
834: case SCSI_CHECK:
835: s1 = &ccb->scsi_sense;
836: s2 = &xs->sense;
837: *s2 = *s1;
838: xs->error = XS_SENSE;
839: break;
840: case SCSI_BUSY:
841: xs->error = XS_BUSY;
842: break;
843: default:
844: printf("%s: target_stat %x\n",
845: sc->sc_dev.dv_xname, ccb->target_stat);
846: xs->error = XS_DRIVER_STUFFUP;
847: break;
848: }
849: } else
850: xs->resid = 0;
851: }
852: bha_free_ccb(sc, ccb);
853: xs->flags |= ITSDONE;
854: scsi_done(xs);
855:
856: /*
857: * If there are queue entries in the software queue, try to
858: * run the first one. We should be more or less guaranteed
859: * to succeed, since we just freed a CCB.
860: *
861: * NOTE: bha_scsi_cmd() relies on our calling it with
862: * the first entry in the queue.
863: */
864: if ((xs = LIST_FIRST(&sc->sc_queue)) != NULL)
865: (void) bha_scsi_cmd(xs);
866: }
867:
868: /*
869: * Find the board and find its irq/drq
870: */
871: int
872: bha_find(iot, ioh, sc)
873: bus_space_tag_t iot;
874: bus_space_handle_t ioh;
875: struct bha_probe_data *sc;
876: {
877: int i, iswide;
878: u_char sts;
879: struct bha_extended_inquire inquire;
880: struct bha_config config;
881: int irq, drq;
882:
883: /* Check something is at the ports we need to access */
884: sts = bus_space_read_1(iot, ioh, BHA_STAT_PORT);
885: if (sts == 0xFF) {
886: #ifdef BHADEBUG
887: if (bha_debug)
888: printf("bha_find: Not present\n");
889: #endif /* BHADEBUG */
890: return (0);
891: }
892:
893: /*
894: * Reset board, If it doesn't respond, assume
895: * that it's not there.. good for the probe
896: */
897:
898: bus_space_write_1(iot, ioh, BHA_CTRL_PORT,
899: BHA_CTRL_HRST | BHA_CTRL_SRST);
900:
901: for (i = BHA_RESET_TIMEOUT; i--;) {
902: delay(100);
903: sts = bus_space_read_1(iot, ioh, BHA_STAT_PORT);
904: if (sts == (BHA_STAT_IDLE | BHA_STAT_INIT))
905: break;
906: }
907: if (i < 0) {
908: #ifdef BHADEBUG
909: if (bha_debug)
910: printf("bha_find: No answer from board a=%x sts=%b\n",
911: ioh, sts, BHA_STAT_BITS);
912: #endif /* BHADEBUG */
913: return (0);
914: }
915:
916: /*
917: * The BusLogic cards implement an Adaptec 1542 (aha)-compatible
918: * interface. The native bha interface is not compatible with
919: * an aha. 1542. We need to ensure that we never match an
920: * Adaptec 1542. We must also avoid sending Adaptec-compatible
921: * commands to a real bha, lest it go into 1542 emulation mode.
922: * (On an indirect bus like ISA, we should always probe for BusLogic
923: * interfaces before Adaptec interfaces).
924: */
925:
926: /*
927: * Make sure we don't match an AHA-1542A or AHA-1542B, by checking
928: * for an extended-geometry register. The 1542[AB] don't have one.
929: */
930: sts = bus_space_read_1(iot, ioh, BHA_EXTGEOM_PORT);
931: if (sts == 0xFF)
932: return (0);
933:
934: /*
935: * Check that we actually know how to use this board.
936: */
937: delay(1000);
938: inquire.cmd.opcode = BHA_INQUIRE_EXTENDED;
939: inquire.cmd.len = sizeof(inquire.reply);
940: i = bha_cmd(iot, ioh, NULL,
941: sizeof(inquire.cmd), (u_char *)&inquire.cmd,
942: sizeof(inquire.reply), (u_char *)&inquire.reply);
943:
944: /*
945: * Some 1542Cs (CP, perhaps not CF, may depend on firmware rev)
946: * have the extended-geometry register and also respond to
947: * BHA_INQUIRE_EXTENDED. Make sure we never match such cards,
948: * by checking the size of the reply is what a BusLogic card returns.
949: */
950: if (i) {
951: #ifdef BHADEBUG
952: printf("bha_find: board returned %d instead of %d to %s\n",
953: i, sizeof(inquire.reply), "INQUIRE_EXTENDED");
954: #endif
955: return (0);
956: }
957:
958: /* OK, we know we've found a buslogic adaptor. */
959:
960: switch (inquire.reply.bus_type) {
961: case BHA_BUS_TYPE_24BIT:
962: case BHA_BUS_TYPE_32BIT:
963: break;
964: case BHA_BUS_TYPE_MCA:
965: /* We don't grok MicroChannel (yet). */
966: return (0);
967: default:
968: printf("bha_find: illegal bus type %c\n",
969: inquire.reply.bus_type);
970: return (0);
971: }
972:
973: /* Note if we have a wide bus. */
974: iswide = inquire.reply.scsi_flags & BHA_SCSI_WIDE;
975:
976: /*
977: * Assume we have a board at this stage setup dma channel from
978: * jumpers and save int level
979: */
980: delay(1000);
981: config.cmd.opcode = BHA_INQUIRE_CONFIG;
982: bha_cmd(iot, ioh, NULL,
983: sizeof(config.cmd), (u_char *)&config.cmd,
984: sizeof(config.reply), (u_char *)&config.reply);
985: switch (config.reply.chan) {
986: case EISADMA:
987: drq = -1;
988: break;
989: case CHAN0:
990: drq = 0;
991: break;
992: case CHAN5:
993: drq = 5;
994: break;
995: case CHAN6:
996: drq = 6;
997: break;
998: case CHAN7:
999: drq = 7;
1000: break;
1001: default:
1002: printf("bha_find: illegal drq setting %x\n",
1003: config.reply.chan);
1004: return (0);
1005: }
1006:
1007: switch (config.reply.intr) {
1008: case INT9:
1009: irq = 9;
1010: break;
1011: case INT10:
1012: irq = 10;
1013: break;
1014: case INT11:
1015: irq = 11;
1016: break;
1017: case INT12:
1018: irq = 12;
1019: break;
1020: case INT14:
1021: irq = 14;
1022: break;
1023: case INT15:
1024: irq = 15;
1025: break;
1026: default:
1027: printf("bha_find: illegal irq setting %x\n",
1028: config.reply.intr);
1029: return (0);
1030: }
1031:
1032: /* if we want to fill in softc, do so now */
1033: if (sc != NULL) {
1034: sc->sc_irq = irq;
1035: sc->sc_drq = drq;
1036: sc->sc_scsi_dev = config.reply.scsi_dev;
1037: sc->sc_iswide = iswide;
1038: }
1039:
1040: return (1);
1041: }
1042:
1043:
1044: /*
1045: * Disable the ISA-compatibility ioports on PCI bha devices,
1046: * to ensure they're not autoconfigured a second time as an ISA bha.
1047: */
1048: int
1049: bha_disable_isacompat(sc)
1050: struct bha_softc *sc;
1051: {
1052: struct bha_isadisable isa_disable;
1053:
1054: isa_disable.cmd.opcode = BHA_MODIFY_IOPORT;
1055: isa_disable.cmd.modifier = BHA_IOMODIFY_DISABLE1;
1056: bha_cmd(sc->sc_iot, sc->sc_ioh, sc,
1057: sizeof(isa_disable.cmd), (u_char *)&isa_disable.cmd,
1058: 0, (u_char *)0);
1059: return (0);
1060: }
1061:
1062:
1063: /*
1064: * Start the board, ready for normal operation
1065: */
1066: int
1067: bha_init(sc)
1068: struct bha_softc *sc;
1069: {
1070: bus_space_tag_t iot = sc->sc_iot;
1071: bus_space_handle_t ioh = sc->sc_ioh;
1072: bus_dma_segment_t seg;
1073: struct bha_devices devices;
1074: struct bha_setup setup;
1075: struct bha_mailbox mailbox;
1076: struct bha_period period;
1077: int error, i, j, initial_ccbs, rlen, rseg;
1078:
1079: /* Enable round-robin scheme - appeared at firmware rev. 3.31. */
1080: if (strcmp(sc->sc_firmware, "3.31") >= 0) {
1081: struct bha_toggle toggle;
1082:
1083: toggle.cmd.opcode = BHA_ROUND_ROBIN;
1084: toggle.cmd.enable = 1;
1085: bha_cmd(iot, ioh, sc,
1086: sizeof(toggle.cmd), (u_char *)&toggle.cmd,
1087: 0, (u_char *)0);
1088: }
1089:
1090: /*
1091: * Inquire installed devices (to force synchronous negotiation).
1092: */
1093:
1094: /*
1095: * Poll targets 0 - 7.
1096: */
1097: devices.cmd.opcode = BHA_INQUIRE_DEVICES;
1098: bha_cmd(iot, ioh, sc,
1099: sizeof(devices.cmd), (u_char *)&devices.cmd,
1100: sizeof(devices.reply), (u_char *)&devices.reply);
1101:
1102: /* Count installed units. */
1103: initial_ccbs = 0;
1104: for (i = 0; i < 8; i++) {
1105: for (j = 0; j < 8; j++) {
1106: if (((devices.reply.lun_map[i] >> j) & 1) == 1)
1107: initial_ccbs++;
1108: }
1109: }
1110:
1111: /*
1112: * Poll targets 8 - 15 if we have a wide bus.
1113: */
1114: if (ISWIDE(sc)) {
1115: devices.cmd.opcode = BHA_INQUIRE_DEVICES_2;
1116: bha_cmd(iot, ioh, sc,
1117: sizeof(devices.cmd), (u_char *)&devices.cmd,
1118: sizeof(devices.reply), (u_char *)&devices.reply);
1119:
1120: for (i = 0; i < 8; i++) {
1121: for (j = 0; j < 8; j++) {
1122: if (((devices.reply.lun_map[i] >> j) & 1) == 1)
1123: initial_ccbs++;
1124: }
1125: }
1126: }
1127:
1128: initial_ccbs *= sc->sc_link.openings;
1129: if (initial_ccbs > BHA_CCB_MAX)
1130: initial_ccbs = BHA_CCB_MAX;
1131: if (initial_ccbs == 0) /* yes, this can happen */
1132: initial_ccbs = sc->sc_link.openings;
1133:
1134: /* Obtain setup information from. */
1135: rlen = sizeof(setup.reply) +
1136: (ISWIDE(sc) ? sizeof(setup.reply_w) : 0);
1137: setup.cmd.opcode = BHA_INQUIRE_SETUP;
1138: setup.cmd.len = rlen;
1139: bha_cmd(iot, ioh, sc,
1140: sizeof(setup.cmd), (u_char *)&setup.cmd,
1141: rlen, (u_char *)&setup.reply);
1142:
1143: printf("%s: %s, %s\n", sc->sc_dev.dv_xname,
1144: setup.reply.sync_neg ? "sync" : "async",
1145: setup.reply.parity ? "parity" : "no parity");
1146:
1147: for (i = 0; i < 8; i++)
1148: period.reply.period[i] = setup.reply.sync[i].period * 5 + 20;
1149: if (ISWIDE(sc)) {
1150: for (i = 0; i < 8; i++)
1151: period.reply_w.period[i] =
1152: setup.reply_w.sync_high[i].period * 5 + 20;
1153: }
1154:
1155: if (sc->sc_firmware[0] >= '3') {
1156: rlen = sizeof(period.reply) +
1157: (ISWIDE(sc) ? sizeof(period.reply_w) : 0);
1158: period.cmd.opcode = BHA_INQUIRE_PERIOD;
1159: period.cmd.len = sizeof(period.reply);
1160: bha_cmd(iot, ioh, sc,
1161: sizeof(period.cmd), (u_char *)&period.cmd,
1162: rlen, (u_char *)&period.reply);
1163: }
1164:
1165: for (i = 0; i < 8; i++) {
1166: if (!setup.reply.sync[i].valid ||
1167: (!setup.reply.sync[i].offset &&
1168: !setup.reply.sync[i].period))
1169: continue;
1170: printf("%s targ %d: sync, offset %d, period %dnsec\n",
1171: sc->sc_dev.dv_xname, i,
1172: setup.reply.sync[i].offset, period.reply.period[i] * 10);
1173: }
1174: if (ISWIDE(sc)) {
1175: for (i = 0; i < 8; i++) {
1176: if (!setup.reply_w.sync_high[i].valid ||
1177: (!setup.reply_w.sync_high[i].offset &&
1178: !setup.reply_w.sync_high[i].period))
1179: continue;
1180: printf("%s targ %d: sync, offset %d, period %dnsec\n",
1181: sc->sc_dev.dv_xname, i + 8,
1182: setup.reply_w.sync_high[i].offset,
1183: period.reply_w.period[i] * 10);
1184: }
1185: }
1186:
1187: /*
1188: * Allocate the mailbox and control blocks.
1189: */
1190: if ((error = bus_dmamem_alloc(sc->sc_dmat, sizeof(struct bha_control),
1191: NBPG, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) {
1192: printf("%s: unable to allocate control structures, "
1193: "error = %d\n", sc->sc_dev.dv_xname, error);
1194: return (error);
1195: }
1196: if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg,
1197: sizeof(struct bha_control), (caddr_t *)&sc->sc_control,
1198: BUS_DMA_NOWAIT)) != 0) {
1199: printf("%s: unable to map control structures, error = %d\n",
1200: sc->sc_dev.dv_xname, error);
1201: return (error);
1202: }
1203:
1204: /*
1205: * Create and load the DMA map used for the mailbox and
1206: * control blocks.
1207: */
1208: if ((error = bus_dmamap_create(sc->sc_dmat, sizeof(struct bha_control),
1209: 1, sizeof(struct bha_control), 0, BUS_DMA_NOWAIT | sc->sc_dmaflags,
1210: &sc->sc_dmamap_control)) != 0) {
1211: printf("%s: unable to create control DMA map, error = %d\n",
1212: sc->sc_dev.dv_xname, error);
1213: return (error);
1214: }
1215: if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap_control,
1216: sc->sc_control, sizeof(struct bha_control), NULL,
1217: BUS_DMA_NOWAIT)) != 0) {
1218: printf("%s: unable to load control DMA map, error = %d\n",
1219: sc->sc_dev.dv_xname, error);
1220: return (error);
1221: }
1222:
1223: /*
1224: * Initialize the control blocks.
1225: */
1226: i = bha_create_ccbs(sc, sc->sc_control->bc_ccbs, initial_ccbs);
1227: if (i == 0) {
1228: printf("%s: unable to create control blocks\n",
1229: sc->sc_dev.dv_xname);
1230: return (ENOMEM);
1231: } else if (i != initial_ccbs) {
1232: printf("%s: WARNING: only %d of %d control blocks created\n",
1233: sc->sc_dev.dv_xname, i, initial_ccbs);
1234: }
1235:
1236: /*
1237: * Set up initial mail box for round-robin operation.
1238: */
1239: for (i = 0; i < BHA_MBX_SIZE; i++) {
1240: wmbx->mbo[i].cmd = BHA_MBO_FREE;
1241: bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control,
1242: 0, sc->sc_dmamap_control->dm_mapsize,
1243: BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
1244: wmbx->mbi[i].comp_stat = BHA_MBI_FREE;
1245: bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control,
1246: 0, sc->sc_dmamap_control->dm_mapsize,
1247: BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
1248: }
1249: wmbx->cmbo = wmbx->tmbo = &wmbx->mbo[0];
1250: wmbx->tmbi = &wmbx->mbi[0];
1251: sc->sc_mbofull = 0;
1252:
1253: /* Initialize mail box. */
1254: mailbox.cmd.opcode = BHA_MBX_INIT_EXTENDED;
1255: mailbox.cmd.nmbx = BHA_MBX_SIZE;
1256: ltophys(sc->sc_dmamap_control->dm_segs[0].ds_addr +
1257: offsetof(struct bha_control, bc_mbx), mailbox.cmd.addr);
1258: bha_cmd(iot, ioh, sc,
1259: sizeof(mailbox.cmd), (u_char *)&mailbox.cmd,
1260: 0, (u_char *)0);
1261: return (0);
1262: }
1263:
1264: void
1265: bha_inquire_setup_information(sc)
1266: struct bha_softc *sc;
1267: {
1268: bus_space_tag_t iot = sc->sc_iot;
1269: bus_space_handle_t ioh = sc->sc_ioh;
1270: struct bha_model model;
1271: struct bha_revision revision;
1272: struct bha_digit digit;
1273: char *p;
1274:
1275: /*
1276: * Get the firmware revision.
1277: */
1278: p = sc->sc_firmware;
1279: revision.cmd.opcode = BHA_INQUIRE_REVISION;
1280: bha_cmd(iot, ioh, sc,
1281: sizeof(revision.cmd), (u_char *)&revision.cmd,
1282: sizeof(revision.reply), (u_char *)&revision.reply);
1283: *p++ = revision.reply.firm_revision;
1284: *p++ = '.';
1285: *p++ = revision.reply.firm_version;
1286: digit.cmd.opcode = BHA_INQUIRE_REVISION_3;
1287: bha_cmd(iot, ioh, sc,
1288: sizeof(digit.cmd), (u_char *)&digit.cmd,
1289: sizeof(digit.reply), (u_char *)&digit.reply);
1290: *p++ = digit.reply.digit;
1291: if (revision.reply.firm_revision >= '3' ||
1292: (revision.reply.firm_revision == '3' &&
1293: revision.reply.firm_version >= '3')) {
1294: digit.cmd.opcode = BHA_INQUIRE_REVISION_4;
1295: bha_cmd(iot, ioh, sc,
1296: sizeof(digit.cmd), (u_char *)&digit.cmd,
1297: sizeof(digit.reply), (u_char *)&digit.reply);
1298: *p++ = digit.reply.digit;
1299: }
1300: while (p > sc->sc_firmware && (p[-1] == ' ' || p[-1] == '\0'))
1301: p--;
1302: *p = '\0';
1303:
1304: /*
1305: * Get the model number.
1306: */
1307: if (revision.reply.firm_revision >= '3') {
1308: p = sc->sc_model;
1309: model.cmd.opcode = BHA_INQUIRE_MODEL;
1310: model.cmd.len = sizeof(model.reply);
1311: bha_cmd(iot, ioh, sc,
1312: sizeof(model.cmd), (u_char *)&model.cmd,
1313: sizeof(model.reply), (u_char *)&model.reply);
1314: *p++ = model.reply.id[0];
1315: *p++ = model.reply.id[1];
1316: *p++ = model.reply.id[2];
1317: *p++ = model.reply.id[3];
1318: while (p > sc->sc_model && (p[-1] == ' ' || p[-1] == '\0'))
1319: p--;
1320: *p++ = model.reply.version[0];
1321: *p++ = model.reply.version[1];
1322: while (p > sc->sc_model && (p[-1] == ' ' || p[-1] == '\0'))
1323: p--;
1324: *p = '\0';
1325: } else
1326: strlcpy(sc->sc_model, "542B", sizeof sc->sc_model);
1327: }
1328:
1329: void
1330: bhaminphys(bp)
1331: struct buf *bp;
1332: {
1333:
1334: if (bp->b_bcount > BHA_MAXXFER)
1335: bp->b_bcount = BHA_MAXXFER;
1336: minphys(bp);
1337: }
1338:
1339: /*
1340: * start a scsi operation given the command and the data address. Also needs
1341: * the unit, target and lu.
1342: */
1343: int
1344: bha_scsi_cmd(xs)
1345: struct scsi_xfer *xs;
1346: {
1347: struct scsi_link *sc_link = xs->sc_link;
1348: struct bha_softc *sc = sc_link->adapter_softc;
1349: bus_dma_tag_t dmat = sc->sc_dmat;
1350: struct bha_ccb *ccb;
1351: int error, seg, flags, s;
1352: int fromqueue = 0, dontqueue = 0;
1353:
1354: SC_DEBUG(sc_link, SDEV_DB2, ("bha_scsi_cmd\n"));
1355:
1356: s = splbio(); /* protect the queue */
1357:
1358: /*
1359: * If we're running the queue from bha_done(), we've been
1360: * called with the first queue entry as our argument.
1361: */
1362: if (xs == LIST_FIRST(&sc->sc_queue)) {
1363: xs = bha_dequeue(sc);
1364: fromqueue = 1;
1365: goto get_ccb;
1366: }
1367:
1368: /* Polled requests can't be queued for later. */
1369: dontqueue = xs->flags & SCSI_POLL;
1370:
1371: /*
1372: * If there are jobs in the queue, run them first.
1373: */
1374: if (!LIST_EMPTY(&sc->sc_queue)) {
1375: /*
1376: * If we can't queue, we have to abort, since
1377: * we have to preserve order.
1378: */
1379: if (dontqueue) {
1380: splx(s);
1381: return (TRY_AGAIN_LATER);
1382: }
1383:
1384: /*
1385: * Swap with the first queue entry.
1386: */
1387: bha_enqueue(sc, xs, 0);
1388: xs = bha_dequeue(sc);
1389: fromqueue = 1;
1390: }
1391:
1392: get_ccb:
1393: /*
1394: * get a ccb to use. If the transfer
1395: * is from a buf (possibly from interrupt time)
1396: * then we can't allow it to sleep
1397: */
1398: flags = xs->flags;
1399: if ((ccb = bha_get_ccb(sc, flags)) == NULL) {
1400: /*
1401: * If we can't queue, we lose.
1402: */
1403: if (dontqueue) {
1404: splx(s);
1405: return (TRY_AGAIN_LATER);
1406: }
1407:
1408: /*
1409: * Stuff ourselves into the queue, in front
1410: * if we came off in the first place.
1411: */
1412: bha_enqueue(sc, xs, fromqueue);
1413: splx(s);
1414: return (SUCCESSFULLY_QUEUED);
1415: }
1416:
1417: splx(s); /* done playing with the queue */
1418:
1419: ccb->xs = xs;
1420: ccb->timeout = xs->timeout;
1421:
1422: /*
1423: * Put all the arguments for the xfer in the ccb
1424: */
1425: if (flags & SCSI_RESET) {
1426: ccb->opcode = BHA_RESET_CCB;
1427: ccb->scsi_cmd_length = 0;
1428: } else {
1429: /* can't use S/G if zero length */
1430: ccb->opcode = (xs->datalen ? BHA_INIT_SCAT_GATH_CCB
1431: : BHA_INITIATOR_CCB);
1432: bcopy(xs->cmd, &ccb->scsi_cmd,
1433: ccb->scsi_cmd_length = xs->cmdlen);
1434: }
1435:
1436: if (xs->datalen) {
1437: /*
1438: * Map the DMA transfer.
1439: */
1440: #ifdef TFS
1441: if (flags & SCSI_DATA_UIO) {
1442: error = bus_dmamap_load_uio(dmat,
1443: ccb->dmamap_xfer, (struct uio *)xs->data,
1444: (flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT :
1445: BUS_DMA_WAITOK);
1446: } else
1447: #endif /* TFS */
1448: {
1449: error = bus_dmamap_load(dmat,
1450: ccb->dmamap_xfer, xs->data, xs->datalen, NULL,
1451: (flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT :
1452: BUS_DMA_WAITOK);
1453: }
1454:
1455: if (error) {
1456: if (error == EFBIG) {
1457: printf("%s: bha_scsi_cmd, more than %d"
1458: " dma segments\n",
1459: sc->sc_dev.dv_xname, BHA_NSEG);
1460: } else {
1461: printf("%s: bha_scsi_cmd, error %d loading"
1462: " dma map\n",
1463: sc->sc_dev.dv_xname, error);
1464: }
1465: goto bad;
1466: }
1467:
1468: bus_dmamap_sync(dmat, ccb->dmamap_xfer,
1469: 0, ccb->dmamap_xfer->dm_mapsize,
1470: (flags & SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD :
1471: BUS_DMASYNC_PREWRITE);
1472:
1473: /*
1474: * Load the hardware scatter/gather map with the
1475: * contents of the DMA map.
1476: */
1477: for (seg = 0; seg < ccb->dmamap_xfer->dm_nsegs; seg++) {
1478: ltophys(ccb->dmamap_xfer->dm_segs[seg].ds_addr,
1479: ccb->scat_gath[seg].seg_addr);
1480: ltophys(ccb->dmamap_xfer->dm_segs[seg].ds_len,
1481: ccb->scat_gath[seg].seg_len);
1482: }
1483:
1484: ltophys(sc->sc_dmamap_control->dm_segs[0].ds_addr +
1485: BHA_CCB_OFF(ccb) + offsetof(struct bha_ccb, scat_gath),
1486: ccb->data_addr);
1487: ltophys(ccb->dmamap_xfer->dm_nsegs *
1488: sizeof(struct bha_scat_gath), ccb->data_length);
1489: } else {
1490: /*
1491: * No data xfer, use non S/G values.
1492: */
1493: ltophys(0, ccb->data_addr);
1494: ltophys(0, ccb->data_length);
1495: }
1496:
1497: ccb->data_out = 0;
1498: ccb->data_in = 0;
1499: ccb->target = sc_link->target;
1500: ccb->lun = sc_link->lun;
1501: ltophys(sc->sc_dmamap_control->dm_segs[0].ds_addr +
1502: BHA_CCB_OFF(ccb) + offsetof(struct bha_ccb, scsi_sense),
1503: ccb->sense_ptr);
1504: ccb->req_sense_length = sizeof(ccb->scsi_sense);
1505: ccb->host_stat = 0x00;
1506: ccb->target_stat = 0x00;
1507: ccb->link_id = 0;
1508: ltophys(0, ccb->link_addr);
1509:
1510: bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control,
1511: 0, sc->sc_dmamap_control->dm_mapsize,
1512: BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
1513:
1514: s = splbio();
1515: bha_queue_ccb(sc, ccb);
1516: splx(s);
1517:
1518: /*
1519: * Usually return SUCCESSFULLY QUEUED
1520: */
1521: SC_DEBUG(sc_link, SDEV_DB3, ("cmd_sent\n"));
1522: if ((flags & SCSI_POLL) == 0)
1523: return (SUCCESSFULLY_QUEUED);
1524:
1525: /*
1526: * If we can't use interrupts, poll on completion
1527: */
1528: if (bha_poll(sc, xs, ccb->timeout)) {
1529: bha_timeout(ccb);
1530: if (bha_poll(sc, xs, ccb->timeout))
1531: bha_timeout(ccb);
1532: }
1533: return (COMPLETE);
1534:
1535: bad:
1536: xs->error = XS_DRIVER_STUFFUP;
1537: bha_free_ccb(sc, ccb);
1538: return (COMPLETE);
1539: }
1540:
1541: /*
1542: * Poll a particular unit, looking for a particular xs
1543: */
1544: int
1545: bha_poll(sc, xs, count)
1546: struct bha_softc *sc;
1547: struct scsi_xfer *xs;
1548: int count;
1549: {
1550: bus_space_tag_t iot = sc->sc_iot;
1551: bus_space_handle_t ioh = sc->sc_ioh;
1552:
1553: /* timeouts are in msec, so we loop in 1000 usec cycles */
1554: while (count) {
1555: /*
1556: * If we had interrupts enabled, would we
1557: * have got an interrupt?
1558: */
1559: if (bus_space_read_1(iot, ioh, BHA_INTR_PORT) &
1560: BHA_INTR_ANYINTR)
1561: bha_intr(sc);
1562: if (xs->flags & ITSDONE)
1563: return (0);
1564: delay(1000); /* only happens in boot so ok */
1565: count--;
1566: }
1567: return (1);
1568: }
1569:
1570: void
1571: bha_timeout(arg)
1572: void *arg;
1573: {
1574: struct bha_ccb *ccb = arg;
1575: struct scsi_xfer *xs = ccb->xs;
1576: struct scsi_link *sc_link = xs->sc_link;
1577: struct bha_softc *sc = sc_link->adapter_softc;
1578: int s;
1579:
1580: sc_print_addr(sc_link);
1581: printf("timed out");
1582:
1583: s = splbio();
1584:
1585: #ifdef BHADIAG
1586: /*
1587: * If the ccb's mbx is not free, then the board has gone Far East?
1588: */
1589: bha_collect_mbo(sc);
1590: if (ccb->flags & CCB_SENDING) {
1591: printf("%s: not taking commands!\n", sc->sc_dev.dv_xname);
1592: Debugger();
1593: }
1594: #endif
1595:
1596: /*
1597: * If it has been through before, then
1598: * a previous abort has failed, don't
1599: * try abort again
1600: */
1601: if (ccb->flags & CCB_ABORT) {
1602: /* abort timed out */
1603: printf(" AGAIN\n");
1604: /* XXX Must reset! */
1605: } else {
1606: /* abort the operation that has timed out */
1607: printf("\n");
1608: ccb->xs->error = XS_TIMEOUT;
1609: ccb->timeout = BHA_ABORT_TIMEOUT;
1610: ccb->flags |= CCB_ABORT;
1611: bha_queue_ccb(sc, ccb);
1612: }
1613:
1614: splx(s);
1615: }
CVSweb