adw.c revision 1.12.2.4 1 /* $NetBSD: adw.c,v 1.12.2.4 1999/10/26 23:10:14 thorpej Exp $ */
2
3 /*
4 * Generic driver for the Advanced Systems Inc. SCSI controllers
5 *
6 * Copyright (c) 1998 The NetBSD Foundation, Inc.
7 * All rights reserved.
8 *
9 * Author: Baldassare Dante Profeta <dante (at) mclink.it>
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40 #include <sys/types.h>
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/kernel.h>
44 #include <sys/errno.h>
45 #include <sys/ioctl.h>
46 #include <sys/device.h>
47 #include <sys/malloc.h>
48 #include <sys/buf.h>
49 #include <sys/proc.h>
50 #include <sys/user.h>
51
52 #include <machine/bus.h>
53 #include <machine/intr.h>
54
55 #include <vm/vm.h>
56 #include <vm/vm_param.h>
57 #include <vm/pmap.h>
58
59 #include <dev/scsipi/scsi_all.h>
60 #include <dev/scsipi/scsipi_all.h>
61 #include <dev/scsipi/scsiconf.h>
62
63 #include <dev/ic/adwlib.h>
64 #include <dev/ic/adw.h>
65
66 #ifndef DDB
67 #define Debugger() panic("should call debugger here (adw.c)")
68 #endif /* ! DDB */
69
70 /******************************************************************************/
71
72
73 static int adw_alloc_ccbs __P((ADW_SOFTC *));
74 static int adw_create_ccbs __P((ADW_SOFTC *, ADW_CCB *, int));
75 static void adw_free_ccb __P((ADW_SOFTC *, ADW_CCB *));
76 static void adw_reset_ccb __P((ADW_CCB *));
77 static int adw_init_ccb __P((ADW_SOFTC *, ADW_CCB *));
78 static ADW_CCB *adw_get_ccb __P((ADW_SOFTC *));
79 static void adw_queue_ccb __P((ADW_SOFTC *, ADW_CCB *));
80 static void adw_start_ccbs __P((ADW_SOFTC *));
81
82 static void adw_scsipi_request __P((struct scsipi_channel *,
83 scsipi_adapter_req_t, void *));
84 static int adw_build_req __P((ADW_SOFTC *, ADW_CCB *));
85 static void adw_build_sglist __P((ADW_CCB *, ADW_SCSI_REQ_Q *, ADW_SG_BLOCK *));
86 static void adwminphys __P((struct buf *));
87 static void adw_wide_isr_callback __P((ADW_SOFTC *, ADW_SCSI_REQ_Q *));
88 static void adw_sbreset_callback __P((ADW_SOFTC *));
89
90 static int adw_poll __P((ADW_SOFTC *, struct scsipi_xfer *, int));
91 static void adw_timeout __P((void *));
92
93
94 /******************************************************************************/
95
96 #define ADW_ABORT_TIMEOUT 10000 /* time to wait for abort (mSec) */
97 #define ADW_WATCH_TIMEOUT 10000 /* time to wait for watchdog (mSec) */
98
99 /******************************************************************************/
100 /* Control Blocks routines */
101 /******************************************************************************/
102
103
104 static int
105 adw_alloc_ccbs(sc)
106 ADW_SOFTC *sc;
107 {
108 bus_dma_segment_t seg;
109 int error, rseg;
110
111 /*
112 * Allocate the control blocks.
113 */
114 if ((error = bus_dmamem_alloc(sc->sc_dmat, sizeof(struct adw_control),
115 NBPG, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) {
116 printf("%s: unable to allocate control structures,"
117 " error = %d\n", sc->sc_dev.dv_xname, error);
118 return (error);
119 }
120 if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg,
121 sizeof(struct adw_control), (caddr_t *) & sc->sc_control,
122 BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) {
123 printf("%s: unable to map control structures, error = %d\n",
124 sc->sc_dev.dv_xname, error);
125 return (error);
126 }
127 /*
128 * Create and load the DMA map used for the control blocks.
129 */
130 if ((error = bus_dmamap_create(sc->sc_dmat, sizeof(struct adw_control),
131 1, sizeof(struct adw_control), 0, BUS_DMA_NOWAIT,
132 &sc->sc_dmamap_control)) != 0) {
133 printf("%s: unable to create control DMA map, error = %d\n",
134 sc->sc_dev.dv_xname, error);
135 return (error);
136 }
137 if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap_control,
138 sc->sc_control, sizeof(struct adw_control), NULL,
139 BUS_DMA_NOWAIT)) != 0) {
140 printf("%s: unable to load control DMA map, error = %d\n",
141 sc->sc_dev.dv_xname, error);
142 return (error);
143 }
144 return (0);
145 }
146
147
148 /*
149 * Create a set of ccbs and add them to the free list. Called once
150 * by adw_init(). We return the number of CCBs successfully created.
151 */
152 static int
153 adw_create_ccbs(sc, ccbstore, count)
154 ADW_SOFTC *sc;
155 ADW_CCB *ccbstore;
156 int count;
157 {
158 ADW_CCB *ccb;
159 int i, error;
160
161 bzero(ccbstore, sizeof(ADW_CCB) * count);
162 for (i = 0; i < count; i++) {
163 ccb = &ccbstore[i];
164 if ((error = adw_init_ccb(sc, ccb)) != 0) {
165 printf("%s: unable to initialize ccb, error = %d\n",
166 sc->sc_dev.dv_xname, error);
167 return (i);
168 }
169 TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, chain);
170 }
171
172 return (i);
173 }
174
175
176 /*
177 * A ccb is put onto the free list.
178 */
179 static void
180 adw_free_ccb(sc, ccb)
181 ADW_SOFTC *sc;
182 ADW_CCB *ccb;
183 {
184 int s;
185
186 s = splbio();
187 adw_reset_ccb(ccb);
188 TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, chain);
189 splx(s);
190 }
191
192
193 static void
194 adw_reset_ccb(ccb)
195 ADW_CCB *ccb;
196 {
197
198 ccb->flags = 0;
199 }
200
201
202 static int
203 adw_init_ccb(sc, ccb)
204 ADW_SOFTC *sc;
205 ADW_CCB *ccb;
206 {
207 int hashnum, error;
208
209 /*
210 * Create the DMA map for this CCB.
211 */
212 error = bus_dmamap_create(sc->sc_dmat,
213 (ADW_MAX_SG_LIST - 1) * PAGE_SIZE,
214 ADW_MAX_SG_LIST, (ADW_MAX_SG_LIST - 1) * PAGE_SIZE,
215 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ccb->dmamap_xfer);
216 if (error) {
217 printf("%s: unable to create DMA map, error = %d\n",
218 sc->sc_dev.dv_xname, error);
219 return (error);
220 }
221
222 /*
223 * put in the phystokv hash table
224 * Never gets taken out.
225 */
226 ccb->hashkey = sc->sc_dmamap_control->dm_segs[0].ds_addr +
227 ADW_CCB_OFF(ccb);
228 hashnum = CCB_HASH(ccb->hashkey);
229 ccb->nexthash = sc->sc_ccbhash[hashnum];
230 sc->sc_ccbhash[hashnum] = ccb;
231 adw_reset_ccb(ccb);
232 return (0);
233 }
234
235
236 /*
237 * Get a free ccb
238 *
239 * If there are none, see if we can allocate a new one
240 */
241 static ADW_CCB *
242 adw_get_ccb(sc)
243 ADW_SOFTC *sc;
244 {
245 ADW_CCB *ccb = 0;
246 int s;
247
248 s = splbio();
249 ccb = TAILQ_FIRST(&sc->sc_free_ccb);
250 if (ccb != NULL) {
251 TAILQ_REMOVE(&sc->sc_free_ccb, ccb, chain);
252 ccb->flags |= CCB_ALLOC;
253 }
254 splx(s);
255 return (ccb);
256 }
257
258
259 /*
260 * Given a physical address, find the ccb that it corresponds to.
261 */
262 ADW_CCB *
263 adw_ccb_phys_kv(sc, ccb_phys)
264 ADW_SOFTC *sc;
265 u_int32_t ccb_phys;
266 {
267 int hashnum = CCB_HASH(ccb_phys);
268 ADW_CCB *ccb = sc->sc_ccbhash[hashnum];
269
270 while (ccb) {
271 if (ccb->hashkey == ccb_phys)
272 break;
273 ccb = ccb->nexthash;
274 }
275 return (ccb);
276 }
277
278
279 /*
280 * Queue a CCB to be sent to the controller, and send it if possible.
281 */
282 static void
283 adw_queue_ccb(sc, ccb)
284 ADW_SOFTC *sc;
285 ADW_CCB *ccb;
286 {
287 int s;
288
289 s = splbio();
290 TAILQ_INSERT_TAIL(&sc->sc_waiting_ccb, ccb, chain);
291 splx(s);
292
293 adw_start_ccbs(sc);
294 }
295
296
297 static void
298 adw_start_ccbs(sc)
299 ADW_SOFTC *sc;
300 {
301 ADW_CCB *ccb;
302 int s;
303
304 while ((ccb = sc->sc_waiting_ccb.tqh_first) != NULL) {
305
306 while (AdvExeScsiQueue(sc, &ccb->scsiq) == ADW_BUSY);
307
308 s = splbio();
309 TAILQ_REMOVE(&sc->sc_waiting_ccb, ccb, chain);
310 splx(s);
311
312 if ((ccb->xs->xs_control & XS_CTL_POLL) == 0)
313 timeout(adw_timeout, ccb, (ccb->timeout * hz) / 1000);
314 }
315 }
316
317
318 /******************************************************************************/
319 /* SCSI layer interfacing routines */
320 /******************************************************************************/
321
322
323 int
324 adw_init(sc)
325 ADW_SOFTC *sc;
326 {
327 u_int16_t warn_code;
328
329
330 sc->cfg.lib_version = (ADW_LIB_VERSION_MAJOR << 8) |
331 ADW_LIB_VERSION_MINOR;
332 sc->cfg.chip_version =
333 ADW_GET_CHIP_VERSION(sc->sc_iot, sc->sc_ioh, sc->bus_type);
334
335 /*
336 * Reset the chip to start and allow register writes.
337 */
338 if (ADW_FIND_SIGNATURE(sc->sc_iot, sc->sc_ioh) == 0) {
339 panic("adw_init: adw_find_signature failed");
340 } else {
341 AdvResetChip(sc->sc_iot, sc->sc_ioh);
342
343 warn_code = AdvInitFromEEP(sc);
344 if (warn_code & ASC_WARN_EEPROM_CHKSUM)
345 printf("%s: Bad checksum found. "
346 "Setting default values\n",
347 sc->sc_dev.dv_xname);
348 if (warn_code & ASC_WARN_EEPROM_TERMINATION)
349 printf("%s: Bad bus termination setting."
350 "Using automatic termination.\n",
351 sc->sc_dev.dv_xname);
352
353 /*
354 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
355 * Resets should be performed.
356 */
357 if (sc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS)
358 AdvResetSCSIBus(sc);
359 }
360
361 sc->isr_callback = (ADW_CALLBACK) adw_wide_isr_callback;
362 sc->sbreset_callback = (ADW_CALLBACK) adw_sbreset_callback;
363
364 return (0);
365 }
366
367
368 void
369 adw_attach(sc)
370 ADW_SOFTC *sc;
371 {
372 struct scsipi_adapter *adapt = &sc->sc_adapter;
373 struct scsipi_channel *chan = &sc->sc_channel;
374 int i, error;
375
376 /*
377 * Initialize the ASC3550.
378 */
379 switch (AdvInitAsc3550Driver(sc)) {
380 case ASC_IERR_MCODE_CHKSUM:
381 panic("%s: Microcode checksum error",
382 sc->sc_dev.dv_xname);
383 break;
384
385 case ASC_IERR_ILLEGAL_CONNECTION:
386 panic("%s: All three connectors are in use",
387 sc->sc_dev.dv_xname);
388 break;
389
390 case ASC_IERR_REVERSED_CABLE:
391 panic("%s: Cable is reversed",
392 sc->sc_dev.dv_xname);
393 break;
394
395 case ASC_IERR_SINGLE_END_DEVICE:
396 panic("%s: single-ended device is attached to"
397 " one of the connectors",
398 sc->sc_dev.dv_xname);
399 break;
400 }
401
402 /*
403 * Fill in the scsipi_adapter.
404 */
405 memset(adapt, 0, sizeof(*adapt));
406 adapt->adapt_dev = &sc->sc_dev;
407 adapt->adapt_nchannels = 1;
408 /* adapt_openings filled in below */
409 /* adapt_max_periph filled in below */
410 adapt->adapt_request = adw_scsipi_request;
411 adapt->adapt_minphys = adwminphys;
412
413 /*
414 * Fill in the scsipi_channel.
415 */
416 memset(chan, 0, sizeof(*chan));
417 chan->chan_adapter = adapt;
418 chan->chan_bustype = &scsi_bustype;
419 chan->chan_channel = 0;
420 chan->chan_ntargets = ADW_MAX_TID + 1;
421 chan->chan_nluns = 7;
422 chan->chan_id = sc->chip_scsi_id;
423
424 TAILQ_INIT(&sc->sc_free_ccb);
425 TAILQ_INIT(&sc->sc_waiting_ccb);
426
427 /*
428 * Allocate the Control Blocks.
429 */
430 error = adw_alloc_ccbs(sc);
431 if (error)
432 return; /* (error) */ ;
433
434 /*
435 * Create and initialize the Control Blocks.
436 */
437 i = adw_create_ccbs(sc, sc->sc_control->ccbs, ADW_MAX_CCB);
438 if (i == 0) {
439 printf("%s: unable to create control blocks\n",
440 sc->sc_dev.dv_xname);
441 return; /* (ENOMEM) */ ;
442 } else if (i != ADW_MAX_CCB) {
443 printf("%s: WARNING: only %d of %d control blocks"
444 " created\n",
445 sc->sc_dev.dv_xname, i, ADW_MAX_CCB);
446 }
447
448 adapt->adapt_openings = i;
449 adapt->adapt_max_periph = adapt->adapt_openings;
450
451 config_found(&sc->sc_dev, &sc->sc_channel, scsiprint);
452 }
453
454
455 static void
456 adwminphys(bp)
457 struct buf *bp;
458 {
459
460 if (bp->b_bcount > ((ADW_MAX_SG_LIST - 1) * PAGE_SIZE))
461 bp->b_bcount = ((ADW_MAX_SG_LIST - 1) * PAGE_SIZE);
462 minphys(bp);
463 }
464
465
466 /*
467 * start a scsi operation given the command and the data address.
468 * Also needs the unit, target and lu.
469 */
470 static void
471 adw_scsipi_request(chan, req, arg)
472 struct scsipi_channel *chan;
473 scsipi_adapter_req_t req;
474 void *arg;
475 {
476 struct scsipi_xfer *xs;
477 ADW_SOFTC *sc = (void *)chan->chan_adapter->adapt_dev;
478 ADW_CCB *ccb;
479
480 switch (req) {
481 case ADAPTER_REQ_RUN_XFER:
482 xs = arg;
483
484 /*
485 * Get a CCB to use.
486 */
487 ccb = adw_get_ccb(sc);
488 #ifdef DIAGNOSTIC
489 /*
490 * This should never happen as we track the resources
491 * in the mid-layer.
492 */
493 if (ccb == NULL) {
494 scsipi_printaddr(xs->xs_periph);
495 printf("unable to allocate ccb\n");
496 panic("adw_scsipi_request");
497 }
498 #endif
499
500 ccb->xs = xs;
501 ccb->timeout = xs->timeout;
502
503 if (adw_build_req(sc, ccb)) {
504 adw_queue_ccb(sc, ccb);
505
506 if ((xs->xs_control & XS_CTL_POLL) == 0)
507 return;
508
509 /*
510 * Not allowed to use interrupts, poll for completion.
511 */
512 if (adw_poll(sc, xs, ccb->timeout)) {
513 adw_timeout(ccb);
514 if (adw_poll(sc, xs, ccb->timeout))
515 adw_timeout(ccb);
516 }
517 }
518 return;
519
520 case ADAPTER_REQ_GROW_RESOURCES:
521 /* XXX Not supported. */
522 return;
523
524 case ADAPTER_REQ_SET_XFER_MODE:
525 /* XXX XXX XXX */
526 return;
527 }
528 }
529
530 /*
531 * Build a request structure for the Wide Boards.
532 */
533 static int
534 adw_build_req(sc, ccb)
535 ADW_SOFTC *sc;
536 ADW_CCB *ccb;
537 {
538 struct scsipi_xfer *xs = ccb->xs;
539 struct scsipi_periph *periph = xs->xs_periph;
540 bus_dma_tag_t dmat = sc->sc_dmat;
541 ADW_SCSI_REQ_Q *scsiqp;
542 int error;
543
544 scsiqp = &ccb->scsiq;
545 bzero(scsiqp, sizeof(ADW_SCSI_REQ_Q));
546
547 /*
548 * Set the ADW_SCSI_REQ_Q 'ccb_ptr' to point to the
549 * physical CCB structure.
550 */
551 scsiqp->ccb_ptr = ccb->hashkey;
552
553 /*
554 * Build the ADW_SCSI_REQ_Q request.
555 */
556
557 /*
558 * Set CDB length and copy it to the request structure.
559 */
560 bcopy(xs->cmd, &scsiqp->cdb, scsiqp->cdb_len = xs->cmdlen);
561
562 scsiqp->target_id = periph->periph_target;
563 scsiqp->target_lun = periph->periph_lun;
564
565 scsiqp->vsense_addr = &ccb->scsi_sense;
566 scsiqp->sense_addr = ccb->hashkey +
567 offsetof(struct adw_ccb, scsi_sense);
568 scsiqp->sense_len = sizeof(struct scsipi_sense_data);
569
570 /*
571 * Build ADW_SCSI_REQ_Q for a scatter-gather buffer command.
572 */
573 if (xs->datalen) {
574 /*
575 * Map the DMA transfer.
576 */
577 #ifdef TFS
578 if (xs->xs_control & SCSI_DATA_UIO) {
579 error = bus_dmamap_load_uio(dmat,
580 ccb->dmamap_xfer, (struct uio *) xs->data,
581 BUS_DMA_NOWAIT);
582 } else
583 #endif /* TFS */
584 {
585 error = bus_dmamap_load(dmat,
586 ccb->dmamap_xfer, xs->data, xs->datalen, NULL,
587 BUS_DMA_NOWAIT);
588 }
589
590 switch (error) {
591 case 0:
592 break;
593
594 case ENOMEM:
595 case EAGAIN:
596 xs->error = XS_RESOURCE_SHORTAGE;
597 goto out_bad;
598
599 default:
600 xs->error = XS_DRIVER_STUFFUP;
601 printf("%s: error %d loading DMA map\n",
602 sc->sc_dev.dv_xname, error);
603 out_bad:
604 adw_free_ccb(sc, ccb);
605 scsipi_done(xs);
606 return (0);
607 }
608 bus_dmamap_sync(dmat, ccb->dmamap_xfer, 0,
609 ccb->dmamap_xfer->dm_mapsize,
610 (xs->xs_control & XS_CTL_DATA_IN) ?
611 BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
612
613 /*
614 * Build scatter-gather list.
615 */
616 scsiqp->data_cnt = xs->datalen;
617 scsiqp->vdata_addr = xs->data;
618 scsiqp->data_addr = ccb->dmamap_xfer->dm_segs[0].ds_addr;
619 bzero(ccb->sg_block, sizeof(ADW_SG_BLOCK) * ADW_NUM_SG_BLOCK);
620 adw_build_sglist(ccb, scsiqp, ccb->sg_block);
621 } else {
622 /*
623 * No data xfer, use non S/G values.
624 */
625 scsiqp->data_cnt = 0;
626 scsiqp->vdata_addr = 0;
627 scsiqp->data_addr = 0;
628 }
629
630 return (1);
631 }
632
633
634 /*
635 * Build scatter-gather list for Wide Boards.
636 */
637 static void
638 adw_build_sglist(ccb, scsiqp, sg_block)
639 ADW_CCB *ccb;
640 ADW_SCSI_REQ_Q *scsiqp;
641 ADW_SG_BLOCK *sg_block;
642 {
643 u_long sg_block_next_addr; /* block and its next */
644 u_int32_t sg_block_physical_addr;
645 int sg_block_index, i; /* how many SG entries */
646 bus_dma_segment_t *sg_list = &ccb->dmamap_xfer->dm_segs[0];
647 int sg_elem_cnt = ccb->dmamap_xfer->dm_nsegs;
648
649
650 sg_block_next_addr = (u_long) sg_block; /* allow math operation */
651 sg_block_physical_addr = ccb->hashkey +
652 offsetof(struct adw_ccb, sg_block[0]);
653 scsiqp->sg_real_addr = sg_block_physical_addr;
654
655 /*
656 * If there are more than NO_OF_SG_PER_BLOCK dma segments (hw sg-list)
657 * then split the request into multiple sg-list blocks.
658 */
659
660 sg_block_index = 0;
661 do {
662 sg_block->first_entry_no = sg_block_index;
663 for (i = 0; i < NO_OF_SG_PER_BLOCK; i++) {
664 sg_block->sg_list[i].sg_addr = sg_list->ds_addr;
665 sg_block->sg_list[i].sg_count = sg_list->ds_len;
666
667 if (--sg_elem_cnt == 0) {
668 /* last entry, get out */
669 scsiqp->sg_entry_cnt = sg_block_index + i + 1;
670 sg_block->last_entry_no = sg_block_index + i;
671 sg_block->sg_ptr = NULL; /* next link = NULL */
672 return;
673 }
674 sg_list++;
675 }
676 sg_block_next_addr += sizeof(ADW_SG_BLOCK);
677 sg_block_physical_addr += sizeof(ADW_SG_BLOCK);
678
679 sg_block_index += NO_OF_SG_PER_BLOCK;
680 sg_block->sg_ptr = sg_block_physical_addr;
681 sg_block->last_entry_no = sg_block_index - 1;
682 sg_block = (ADW_SG_BLOCK *) sg_block_next_addr; /* virt. addr */
683 } while (1);
684 }
685
686
687 int
688 adw_intr(arg)
689 void *arg;
690 {
691 ADW_SOFTC *sc = arg;
692
693 AdvISR(sc);
694 return (1);
695 }
696
697
698 /*
699 * Poll a particular unit, looking for a particular xs
700 */
701 static int
702 adw_poll(sc, xs, count)
703 ADW_SOFTC *sc;
704 struct scsipi_xfer *xs;
705 int count;
706 {
707
708 /* timeouts are in msec, so we loop in 1000 usec cycles */
709 while (count) {
710 adw_intr(sc);
711 if (xs->xs_status & XS_STS_DONE)
712 return (0);
713 delay(1000); /* only happens in boot so ok */
714 count--;
715 }
716 return (1);
717 }
718
719
720 static void
721 adw_timeout(arg)
722 void *arg;
723 {
724 ADW_CCB *ccb = arg;
725 struct scsipi_xfer *xs = ccb->xs;
726 struct scsipi_periph *periph = xs->xs_periph;
727 ADW_SOFTC *sc =
728 (void *)periph->periph_channel->chan_adapter->adapt_dev;
729 int s;
730
731 scsipi_printaddr(periph);
732 printf("timed out");
733
734 s = splbio();
735
736 /*
737 * If it has been through before, then a previous abort has failed,
738 * don't try abort again, reset the bus instead.
739 */
740 if (ccb->flags & CCB_ABORTED) {
741 /*
742 * Abort Timed Out
743 * Lets try resetting the bus!
744 */
745 printf(" AGAIN. Resetting SCSI Bus\n");
746 ccb->flags &= ~CCB_ABORTED;
747 /* AdvResetSCSIBus() will call sbreset_callback() */
748 AdvResetSCSIBus(sc);
749 } else {
750 /*
751 * Abort the operation that has timed out
752 */
753 printf("\n");
754 xs->error = XS_TIMEOUT;
755 ccb->flags |= CCB_ABORTING;
756 /* ADW_ABORT_CCB() will implicitly call isr_callback() */
757 ADW_ABORT_CCB(sc, ccb);
758 }
759
760 splx(s);
761 }
762
763
764 /******************************************************************************/
765 /* WIDE boards Interrupt callbacks */
766 /******************************************************************************/
767
768
769 /*
770 * adw_wide_isr_callback() - Second Level Interrupt Handler called by AdvISR()
771 *
772 * Interrupt callback function for the Wide SCSI Adv Library.
773 */
774 static void
775 adw_wide_isr_callback(sc, scsiq)
776 ADW_SOFTC *sc;
777 ADW_SCSI_REQ_Q *scsiq;
778 {
779 bus_dma_tag_t dmat = sc->sc_dmat;
780 ADW_CCB *ccb;
781 struct scsipi_xfer *xs;
782 struct scsipi_sense_data *s1, *s2;
783 int s;
784 //int underrun = ASC_FALSE;
785
786
787 ccb = adw_ccb_phys_kv(sc, scsiq->ccb_ptr);
788
789 untimeout(adw_timeout, ccb);
790
791 if(ccb->flags & CCB_ABORTING) {
792 printf("Retrying request\n");
793 ccb->flags &= ~CCB_ABORTING;
794 ccb->flags |= CCB_ABORTED;
795 s = splbio();
796 adw_queue_ccb(sc, ccb);
797 splx(s);
798 return;
799 }
800
801 xs = ccb->xs;
802
803
804 /*
805 * If we were a data transfer, unload the map that described
806 * the data buffer.
807 */
808 if (xs->datalen) {
809 bus_dmamap_sync(dmat, ccb->dmamap_xfer, 0,
810 ccb->dmamap_xfer->dm_mapsize,
811 (xs->xs_control & XS_CTL_DATA_IN) ?
812 BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
813 bus_dmamap_unload(dmat, ccb->dmamap_xfer);
814 }
815 if ((ccb->flags & CCB_ALLOC) == 0) {
816 printf("%s: exiting ccb not allocated!\n", sc->sc_dev.dv_xname);
817 Debugger();
818 return;
819 }
820 /*
821 * Check for an underrun condition.
822 */
823 /*
824 * if (xs->request_bufflen != 0 && scsiqp->data_cnt != 0) {
825 * ASC_DBG1(1, "adw_isr_callback: underrun condition %lu bytes\n",
826 * scsiqp->data_cnt); underrun = ASC_TRUE; }
827 */
828 /*
829 * 'done_status' contains the command's ending status.
830 */
831 switch (scsiq->done_status) {
832 case QD_NO_ERROR:
833 switch (scsiq->host_status) {
834 case QHSTA_NO_ERROR:
835 xs->error = XS_NOERROR;
836 xs->resid = 0;
837 break;
838 case QHSTA_M_SEL_TIMEOUT:
839 default:
840 /* QHSTA error occurred. */
841 xs->error = XS_DRIVER_STUFFUP;
842 break;
843 }
844 /*
845 * If there was an underrun without any other error,
846 * set DID_ERROR to indicate the underrun error.
847 *
848 * Note: There is no way yet to indicate the number
849 * of underrun bytes.
850 */
851 /*
852 * if (xs->error == XS_NOERROR && underrun == ASC_TRUE) {
853 * scp->result = HOST_BYTE(DID_UNDERRUN); }
854 */ break;
855
856 case QD_WITH_ERROR:
857 switch (scsiq->host_status) {
858 case QHSTA_NO_ERROR:
859 switch(scsiq->scsi_status) {
860 case SS_CHK_CONDITION:
861 case SS_CMD_TERMINATED:
862 s1 = &ccb->scsi_sense;
863 s2 = &xs->sense.scsi_sense;
864 *s2 = *s1;
865 xs->error = XS_SENSE;
866 break;
867 case SS_TARGET_BUSY:
868 case SS_RSERV_CONFLICT:
869 case SS_QUEUE_FULL:
870 xs->error = XS_DRIVER_STUFFUP;
871 break;
872 case SS_CONDITION_MET:
873 case SS_INTERMID:
874 case SS_INTERMID_COND_MET:
875 xs->error = XS_DRIVER_STUFFUP;
876 break;
877 case SS_GOOD:
878 break;
879 }
880 break;
881
882 case QHSTA_M_SEL_TIMEOUT:
883 xs->error = XS_DRIVER_STUFFUP;
884 break;
885
886 default:
887 /* Some other QHSTA error occurred. */
888 xs->error = XS_DRIVER_STUFFUP;
889 break;
890 }
891 break;
892
893 case QD_ABORTED_BY_HOST:
894 xs->error = XS_DRIVER_STUFFUP;
895 break;
896
897 default:
898 xs->error = XS_DRIVER_STUFFUP;
899 break;
900 }
901
902 adw_free_ccb(sc, ccb);
903 xs->xs_status |= XS_STS_DONE;
904 scsipi_done(xs);
905 }
906
907
908 static void
909 adw_sbreset_callback(sc)
910 ADW_SOFTC *sc;
911 {
912 }
913