This source file includes following definitions.
- osiop_attach
- osiop_minphys
- osiop_scsicmd
- osiop_poll
- osiop_sched
- osiop_scsidone
- osiop_abort
- osiop_init
- osiop_reset
- osiop_resetbus
- osiop_start
- osiop_checkintr
- osiop_select
- osiop_intr
- osiop_update_xfer_mode
- scsi_period_to_osiop
- osiop_timeout
- osiop_dump_trace
- osiop_dump_acb
- osiop_dump
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 #include <sys/cdefs.h>
73
74
75 #include <sys/param.h>
76 #include <sys/systm.h>
77 #include <sys/device.h>
78 #include <sys/malloc.h>
79 #include <sys/buf.h>
80 #include <sys/kernel.h>
81
82 #include <scsi/scsi_all.h>
83 #include <scsi/scsiconf.h>
84 #include <scsi/scsi_message.h>
85
86 #include <machine/cpu.h>
87 #include <machine/bus.h>
88
89 #include <dev/ic/osiopreg.h>
90 #include <dev/ic/osiopvar.h>
91
92
93 #include <dev/microcode/siop/osiop.out>
94
95 void osiop_attach(struct osiop_softc *);
96 void osiop_minphys(struct buf *);
97 int osiop_scsicmd(struct scsi_xfer *xs);
98 void osiop_poll(struct osiop_softc *, struct osiop_acb *);
99 void osiop_sched(struct osiop_softc *);
100 void osiop_scsidone(struct osiop_acb *, int);
101 void osiop_abort(struct osiop_softc *, const char *);
102 void osiop_init(struct osiop_softc *);
103 void osiop_reset(struct osiop_softc *);
104 void osiop_resetbus(struct osiop_softc *);
105 void osiop_start(struct osiop_softc *);
106 int osiop_checkintr(struct osiop_softc *, u_int8_t, u_int8_t, u_int8_t, int *);
107 void osiop_select(struct osiop_softc *);
108 void osiop_update_xfer_mode(struct osiop_softc *, int);
109 void scsi_period_to_osiop(struct osiop_softc *, int);
110 void osiop_timeout(void *);
111
112 int osiop_reset_delay = 250;
113
114
115 #ifdef OSIOP_DEBUG
116 #define DEBUG_DMA 0x0001
117 #define DEBUG_INT 0x0002
118 #define DEBUG_PHASE 0x0004
119 #define DEBUG_DISC 0x0008
120 #define DEBUG_CMD 0x0010
121 #define DEBUG_SYNC 0x0020
122 #define DEBUG_SCHED 0x0040
123 #define DEBUG_ALL 0xffff
124 int osiop_debug = 0;
125 int osiopstarts = 0;
126 int osiopints = 0;
127 int osiopphmm = 0;
128 int osiop_trix = 0;
129 #define OSIOP_TRACE_SIZE 128
130 #define OSIOP_TRACE(a,b,c,d) do { \
131 osiop_trbuf[osiop_trix + 0] = (a); \
132 osiop_trbuf[osiop_trix + 1] = (b); \
133 osiop_trbuf[osiop_trix + 2] = (c); \
134 osiop_trbuf[osiop_trix + 3] = (d); \
135 osiop_trix = (osiop_trix + 4) & (OSIOP_TRACE_SIZE - 1); \
136 } while (0)
137 u_int8_t osiop_trbuf[OSIOP_TRACE_SIZE];
138 void osiop_dump_trace(void);
139 void osiop_dump_acb(struct osiop_acb *);
140 void osiop_dump(struct osiop_softc *);
141 #else
142 #define OSIOP_TRACE(a,b,c,d)
143 #endif
144
145 #ifdef OSIOP_DEBUG
146
147
148
149 static struct {
150 u_int8_t p;
151 u_int8_t r;
152 } sync_tab[] = {
153 { 60/4, 0<<4 | 1},
154 { 76/4, 1<<4 | 1},
155 { 92/4, 2<<4 | 1},
156 { 92/4, 0<<4 | 2},
157 {108/4, 3<<4 | 1},
158 {116/4, 1<<4 | 2},
159 {120/4, 4<<4 | 1},
160 {120/4, 0<<4 | 3},
161 {136/4, 5<<4 | 1},
162 {140/4, 2<<4 | 2},
163 {152/4, 6<<4 | 1},
164 {152/4, 1<<4 | 3},
165 {164/4, 3<<4 | 2},
166 {168/4, 7<<4 | 1},
167 {180/4, 2<<4 | 3},
168 {184/4, 4<<4 | 2},
169 {208/4, 5<<4 | 2},
170 {212/4, 3<<4 | 3},
171 {232/4, 6<<4 | 2},
172 {240/4, 4<<4 | 3},
173 {256/4, 7<<4 | 2},
174 {272/4, 5<<4 | 3},
175 {300/4, 6<<4 | 3},
176 {332/4, 7<<4 | 3}
177 };
178 #endif
179
180 struct cfdriver osiop_cd = {
181 NULL, "osiop", DV_DULL
182 };
183
184 struct scsi_adapter osiop_adapter = {
185 osiop_scsicmd,
186 osiop_minphys,
187 NULL,
188 NULL,
189 };
190
191 struct scsi_device osiop_dev = {
192 NULL,
193 NULL,
194 NULL,
195 NULL,
196 };
197
198 void
199 osiop_attach(sc)
200 struct osiop_softc *sc;
201 {
202 struct scsibus_attach_args saa;
203 struct osiop_acb *acb;
204 bus_dma_segment_t seg;
205 int nseg;
206 int i, err;
207
208
209
210
211 err = bus_dmamem_alloc(sc->sc_dmat, PAGE_SIZE, PAGE_SIZE, 0,
212 &seg, 1, &nseg, BUS_DMA_NOWAIT);
213 if (err) {
214 printf(": failed to allocate script memory, err=%d\n", err);
215 return;
216 }
217 err = bus_dmamem_map(sc->sc_dmat, &seg, nseg, PAGE_SIZE,
218 (caddr_t *)&sc->sc_script, BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
219 if (err) {
220 printf(": failed to map script memory, err=%d\n", err);
221 return;
222 }
223 err = bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, 1, PAGE_SIZE, 0,
224 BUS_DMA_NOWAIT, &sc->sc_scrdma);
225 if (err) {
226 printf(": failed to create script map, err=%d\n", err);
227 return;
228 }
229 err = bus_dmamap_load_raw(sc->sc_dmat, sc->sc_scrdma,
230 &seg, nseg, PAGE_SIZE, BUS_DMA_NOWAIT);
231 if (err) {
232 printf(": failed to load script map, err=%d\n", err);
233 return;
234 }
235 bzero(sc->sc_script, PAGE_SIZE);
236
237
238
239
240 memcpy(sc->sc_script, osiop_script, sizeof(osiop_script));
241 bus_dmamap_sync(sc->sc_dmat, sc->sc_scrdma, 0, sizeof(osiop_script),
242 BUS_DMASYNC_PREWRITE);
243
244
245
246
247 err = bus_dmamem_alloc(sc->sc_dmat,
248 sizeof(struct osiop_ds) * OSIOP_NACB, PAGE_SIZE, 0,
249 &seg, 1, &nseg, BUS_DMA_NOWAIT);
250 if (err) {
251 printf(": failed to allocate ds memory, err=%d\n", err);
252 return;
253 }
254 err = bus_dmamem_map(sc->sc_dmat, &seg, nseg,
255 sizeof(struct osiop_ds) * OSIOP_NACB, (caddr_t *)&sc->sc_ds,
256 BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
257 if (err) {
258 printf(": failed to map ds memory, err=%d\n", err);
259 return;
260 }
261 err = bus_dmamap_create(sc->sc_dmat,
262 sizeof(struct osiop_ds) * OSIOP_NACB, 1,
263 sizeof(struct osiop_ds) * OSIOP_NACB, 0,
264 BUS_DMA_NOWAIT, &sc->sc_dsdma);
265 if (err) {
266 printf(": failed to create ds map, err=%d\n", err);
267 return;
268 }
269 err = bus_dmamap_load_raw(sc->sc_dmat, sc->sc_dsdma,
270 &seg, nseg, sizeof(struct osiop_ds) * OSIOP_NACB, BUS_DMA_NOWAIT);
271 if (err) {
272 printf(": failed to load ds map, err=%d\n", err);
273 return;
274 }
275 bzero(sc->sc_ds, sizeof(struct osiop_ds) * OSIOP_NACB);
276
277
278
279
280 acb = malloc(sizeof(struct osiop_acb) * OSIOP_NACB,
281 M_DEVBUF, M_NOWAIT);
282 if (acb == NULL) {
283 printf(": can't allocate memory for acb\n");
284 return;
285 }
286 bzero(acb, sizeof(struct osiop_acb) * OSIOP_NACB);
287 sc->sc_acb = acb;
288
289 sc->sc_cfflags = sc->sc_dev.dv_cfdata->cf_flags;
290 sc->sc_nexus = NULL;
291 sc->sc_active = 0;
292
293 bzero(sc->sc_tinfo, sizeof(sc->sc_tinfo));
294
295
296 TAILQ_INIT(&sc->ready_list);
297 TAILQ_INIT(&sc->nexus_list);
298 TAILQ_INIT(&sc->free_list);
299
300
301 for (i = 0; i < OSIOP_NACB; i++, acb++) {
302 bus_addr_t dsa;
303
304 err = bus_dmamap_create(sc->sc_dmat, OSIOP_MAX_XFER, OSIOP_NSG,
305 OSIOP_MAX_XFER, 0, BUS_DMA_NOWAIT, &acb->datadma);
306 if (err) {
307 printf(": failed to create datadma map, err=%d\n",
308 err);
309 return;
310 }
311
312 acb->sc = sc;
313 acb->ds = &sc->sc_ds[i];
314 acb->dsoffset = sizeof(struct osiop_ds) * i;
315
316 dsa = sc->sc_dsdma->dm_segs[0].ds_addr + acb->dsoffset;
317 acb->ds->id.addr = dsa + OSIOP_DSIDOFF;
318 acb->ds->cmd.addr = dsa + OSIOP_DSCMDOFF;
319 acb->ds->status.count = 1;
320 acb->ds->status.addr = dsa + OSIOP_DSSTATOFF;
321 acb->ds->msg.count = 1;
322 acb->ds->msg.addr = dsa + OSIOP_DSMSGOFF;
323 acb->ds->msgin.count = 1;
324 acb->ds->msgin.addr = dsa + OSIOP_DSMSGINOFF;
325 acb->ds->extmsg.count = 1;
326 acb->ds->extmsg.addr = dsa + OSIOP_DSEXTMSGOFF;
327 acb->ds->synmsg.count = 3;
328 acb->ds->synmsg.addr = dsa + OSIOP_DSSYNMSGOFF;
329 TAILQ_INSERT_TAIL(&sc->free_list, acb, chain);
330 }
331
332 printf(": NCR53C710 rev %d, %dMHz, SCSI ID %d\n",
333 osiop_read_1(sc, OSIOP_CTEST8) >> 4, sc->sc_clock_freq, sc->sc_id);
334
335
336
337
338 osiop_init(sc);
339
340
341
342
343 sc->sc_link.adapter = &osiop_adapter;
344 sc->sc_link.adapter_softc = sc;
345 sc->sc_link.device = &osiop_dev;
346 sc->sc_link.openings = 4;
347 sc->sc_link.adapter_buswidth = OSIOP_NTGT;
348 sc->sc_link.adapter_target = sc->sc_id;
349
350 bzero(&saa, sizeof(saa));
351 saa.saa_sc_link = &sc->sc_link;
352
353
354
355
356 config_found(&sc->sc_dev, &saa, scsiprint);
357 }
358
359
360
361
362 void
363 osiop_minphys(bp)
364 struct buf *bp;
365 {
366
367 if (bp->b_bcount > OSIOP_MAX_XFER)
368 bp->b_bcount = OSIOP_MAX_XFER;
369 minphys(bp);
370 }
371
372
373
374
375
376 int
377 osiop_scsicmd(xs)
378 struct scsi_xfer *xs;
379 {
380 struct scsi_link *periph = xs->sc_link;
381 struct osiop_acb *acb;
382 struct osiop_softc *sc = periph->adapter_softc;
383 int err, s;
384
385
386 if (xs->flags & SCSI_DATA_UIO)
387 panic("osiop: scsi data uio requested");
388
389
390 if (sc->sc_nexus && (xs->flags & SCSI_POLL))
391 #if 0
392 panic("osiop_scsicmd: busy");
393 #else
394 printf("osiop_scsicmd: busy\n");
395 #endif
396
397 s = splbio();
398 acb = TAILQ_FIRST(&sc->free_list);
399 if (acb != NULL) {
400 TAILQ_REMOVE(&sc->free_list, acb, chain);
401 }
402 else {
403 #ifdef DIAGNOSTIC
404 sc_print_addr(periph);
405 printf("unable to allocate acb\n");
406 panic("osiop_scsipi_request");
407 #endif
408 splx(s);
409 return (TRY_AGAIN_LATER);
410 }
411
412 acb->flags = 0;
413 acb->status = ACB_S_READY;
414 acb->xs = xs;
415 acb->xsflags = xs->flags;
416 bcopy(xs->cmd, &acb->ds->scsi_cmd, xs->cmdlen);
417 acb->ds->cmd.count = xs->cmdlen;
418 acb->datalen = 0;
419 #ifdef OSIOP_DEBUG
420 acb->data = xs->data;
421 #endif
422
423
424 if (acb->xsflags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
425 acb->datalen = xs->datalen;
426 err = bus_dmamap_load(sc->sc_dmat, acb->datadma,
427 xs->data, acb->datalen, NULL,
428 BUS_DMA_NOWAIT | BUS_DMA_STREAMING |
429 ((acb->xsflags & SCSI_DATA_IN) ?
430 BUS_DMA_READ : BUS_DMA_WRITE));
431 if (err) {
432 printf("%s: unable to load data DMA map: %d",
433 sc->sc_dev.dv_xname, err);
434 xs->error = XS_DRIVER_STUFFUP;
435 scsi_done(xs);
436 TAILQ_INSERT_TAIL(&sc->free_list, acb, chain);
437 splx(s);
438 return (COMPLETE);
439 }
440 bus_dmamap_sync(sc->sc_dmat, acb->datadma,
441 0, acb->datalen, (acb->xsflags & SCSI_DATA_IN) ?
442 BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
443 }
444
445
446
447
448
449 timeout_set(&xs->stimeout, osiop_timeout, acb);
450
451 TAILQ_INSERT_TAIL(&sc->ready_list, acb, chain);
452
453 osiop_sched(sc);
454
455 splx(s);
456
457 if ((acb->xsflags & SCSI_POLL) || (sc->sc_flags & OSIOP_NODMA))
458 osiop_poll(sc, acb);
459 else
460
461 timeout_add(&xs->stimeout, (xs->timeout/1000) * hz);
462
463 if ((xs->flags & ITSDONE) == 0)
464 return (SUCCESSFULLY_QUEUED);
465 else
466 return (COMPLETE);
467 }
468
469 void
470 osiop_poll(sc, acb)
471 struct osiop_softc *sc;
472 struct osiop_acb *acb;
473 {
474 struct scsi_xfer *xs = acb->xs;
475 int status, i, s, to;
476 u_int8_t istat, dstat, sstat0;
477
478 s = splbio();
479 to = xs->timeout / 1000;
480 if (!TAILQ_EMPTY(&sc->nexus_list))
481 printf("%s: osiop_poll called with disconnected device\n",
482 sc->sc_dev.dv_xname);
483 for (;;) {
484 i = 1000;
485 while (((istat = osiop_read_1(sc, OSIOP_ISTAT)) &
486 (OSIOP_ISTAT_SIP | OSIOP_ISTAT_DIP)) == 0) {
487 if (i <= 0) {
488 #ifdef OSIOP_DEBUG
489 printf("waiting: tgt %d cmd %02x sbcl %02x"
490 " dsp %x (+%lx) dcmd %x"
491 " ds %p timeout %d\n",
492 xs->sc_link->target,
493 acb->ds->scsi_cmd.opcode,
494 osiop_read_1(sc, OSIOP_SBCL),
495 osiop_read_4(sc, OSIOP_DSP),
496 osiop_read_4(sc, OSIOP_DSP) -
497 sc->sc_scrdma->dm_segs[0].ds_addr,
498 osiop_read_1(sc, OSIOP_DCMD),
499 acb->ds, acb->xs->timeout);
500 #endif
501 i = 1000;
502 to--;
503 if (to <= 0) {
504 osiop_reset(sc);
505 splx(s);
506 return;
507 }
508 }
509 delay(1000);
510 i--;
511 }
512 sstat0 = osiop_read_1(sc, OSIOP_SSTAT0);
513 delay(25);
514 dstat = osiop_read_1(sc, OSIOP_DSTAT);
515 if (osiop_checkintr(sc, istat, dstat, sstat0, &status)) {
516 if (acb != sc->sc_nexus)
517 printf("%s: osiop_poll disconnected device"
518 " completed\n", sc->sc_dev.dv_xname);
519 else if ((sc->sc_flags & OSIOP_INTDEFER) == 0) {
520 sc->sc_flags &= ~OSIOP_INTSOFF;
521 osiop_write_1(sc, OSIOP_SIEN, sc->sc_sien);
522 osiop_write_1(sc, OSIOP_DIEN, sc->sc_dien);
523 }
524 osiop_scsidone(sc->sc_nexus, status);
525 }
526
527 if (xs->flags & ITSDONE)
528 break;
529 }
530
531 splx(s);
532 return;
533 }
534
535
536
537
538 void
539 osiop_sched(sc)
540 struct osiop_softc *sc;
541 {
542 struct osiop_tinfo *ti;
543 struct scsi_link *periph;
544 struct osiop_acb *acb;
545
546 if ((sc->sc_nexus != NULL) || TAILQ_EMPTY(&sc->ready_list)) {
547 #ifdef OSIOP_DEBUG
548 if (osiop_debug & DEBUG_SCHED)
549 printf("%s: osiop_sched->nexus %p/%d ready %p/%d\n",
550 sc->sc_dev.dv_xname, sc->sc_nexus,
551 sc->sc_nexus != NULL ?
552 sc->sc_nexus->xs->sc_link->target : 0,
553 TAILQ_FIRST(&sc->ready_list),
554 TAILQ_FIRST(&sc->ready_list) != NULL ?
555 TAILQ_FIRST(&sc->ready_list)->xs->sc_link->target :
556 0);
557 #endif
558 return;
559 }
560 TAILQ_FOREACH(acb, &sc->ready_list, chain) {
561 periph = acb->xs->sc_link;
562 ti = &sc->sc_tinfo[periph->target];
563 if ((ti->lubusy & (1 << periph->lun)) == 0) {
564 TAILQ_REMOVE(&sc->ready_list, acb, chain);
565 sc->sc_nexus = acb;
566 ti->lubusy |= (1 << periph->lun);
567 break;
568 }
569 }
570
571 if (acb == NULL) {
572 #ifdef OSIOP_DEBUG
573 if (osiop_debug & DEBUG_SCHED)
574 printf("%s: osiop_sched didn't find ready command\n",
575 sc->sc_dev.dv_xname);
576 #endif
577 return;
578 }
579
580 if (acb->xsflags & SCSI_RESET)
581 osiop_reset(sc);
582
583 sc->sc_active++;
584 osiop_select(sc);
585 }
586
587 void
588 osiop_scsidone(acb, status)
589 struct osiop_acb *acb;
590 int status;
591 {
592 struct scsi_xfer *xs;
593 struct scsi_link *periph;
594 struct osiop_softc *sc;
595 int autosense;
596
597 #ifdef DIAGNOSTIC
598 if (acb == NULL || acb->xs == NULL) {
599 printf("osiop_scsidone: NULL acb or scsi_xfer\n");
600 #if defined(OSIOP_DEBUG) && defined(DDB)
601 Debugger();
602 #endif
603 return;
604 }
605 #endif
606 xs = acb->xs;
607 sc = acb->sc;
608 periph = xs->sc_link;
609
610
611
612
613
614
615 autosense = acb->flags & ACB_F_AUTOSENSE;
616 acb->flags &= ~ACB_F_AUTOSENSE;
617
618 #ifdef OSIOP_DEBUG
619 if (acb->status != ACB_S_DONE)
620 printf("%s: acb not done (status %d)\n",
621 sc->sc_dev.dv_xname, acb->status);
622 #endif
623
624 if (acb->xsflags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
625 bus_dmamap_sync(sc->sc_dmat, acb->datadma, 0, acb->datalen,
626 (acb->xsflags & SCSI_DATA_IN) ?
627 BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
628 bus_dmamap_unload(sc->sc_dmat, acb->datadma);
629 }
630
631 timeout_del(&xs->stimeout);
632 xs->status = status;
633
634 switch (status) {
635 case SCSI_OK:
636 if (autosense == 0)
637 xs->error = XS_NOERROR;
638 else
639 xs->error = XS_SENSE;
640 break;
641 case SCSI_BUSY:
642 xs->error = XS_BUSY;
643 break;
644 case SCSI_CHECK:
645 if (autosense == 0)
646 acb->flags |= ACB_F_AUTOSENSE;
647 else
648 xs->error = XS_DRIVER_STUFFUP;
649 break;
650 case SCSI_OSIOP_NOCHECK:
651
652
653
654 break;
655 case SCSI_OSIOP_NOSTATUS:
656
657
658
659
660 xs->error = XS_SELTIMEOUT;
661 break;
662 default:
663 #ifdef OSIOP_DEBUG
664 printf("%s: osiop_scsidone: unknown status code (0x%02x)\n",
665 sc->sc_dev.dv_xname, status);
666 #endif
667 xs->error = XS_DRIVER_STUFFUP;
668 break;
669 }
670
671
672
673
674
675
676
677
678 if (acb == sc->sc_nexus) {
679 sc->sc_nexus = NULL;
680 sc->sc_tinfo[periph->target].lubusy &=
681 ~(1 << periph->lun);
682 sc->sc_active--;
683 OSIOP_TRACE('d', 'a', status, 0);
684 } else if (sc->ready_list.tqh_last == &TAILQ_NEXT(acb, chain)) {
685 TAILQ_REMOVE(&sc->ready_list, acb, chain);
686 OSIOP_TRACE('d', 'r', status, 0);
687 } else {
688 struct osiop_acb *acb2;
689 TAILQ_FOREACH(acb2, &sc->nexus_list, chain) {
690 if (acb2 == acb) {
691 TAILQ_REMOVE(&sc->nexus_list, acb, chain);
692 sc->sc_tinfo[periph->target].lubusy &=
693 ~(1 << periph->lun);
694 sc->sc_active--;
695 break;
696 }
697 }
698 if (acb2 == NULL) {
699 if (TAILQ_NEXT(acb, chain) != NULL) {
700 TAILQ_REMOVE(&sc->ready_list, acb, chain);
701 sc->sc_active--;
702 } else {
703 printf("%s: can't find matching acb\n",
704 sc->sc_dev.dv_xname);
705 #ifdef DDB
706 #if 0
707 Debugger();
708 #endif
709 #endif
710 }
711 }
712 OSIOP_TRACE('d', 'n', status, 0);
713 }
714
715 if ((acb->flags & ACB_F_AUTOSENSE) == 0) {
716
717 FREE:
718 acb->status = ACB_S_FREE;
719 TAILQ_INSERT_TAIL(&sc->free_list, acb, chain);
720 sc->sc_tinfo[periph->target].cmds++;
721
722 xs->resid = 0;
723 xs->flags |= ITSDONE;
724 scsi_done(xs);
725 } else {
726
727 struct scsi_sense *cmd = (struct scsi_sense *)&acb->ds->scsi_cmd;
728 int err;
729
730 bzero(cmd, sizeof(*cmd));
731 acb->ds->cmd.count = sizeof(*cmd);
732 cmd->opcode = REQUEST_SENSE;
733 cmd->byte2 = xs->sc_link->lun << 5;
734 cmd->length = sizeof(xs->sense);
735
736
737 acb->xsflags &= SCSI_POLL | SCSI_NOSLEEP;
738 acb->xsflags |= SCSI_DATA_IN;
739 acb->datalen = sizeof xs->sense;
740 #ifdef OSIOP_DEBUG
741 acb->data = &xs->sense;
742 #endif
743 err = bus_dmamap_load(sc->sc_dmat, acb->datadma,
744 &xs->sense, sizeof(xs->sense), NULL,
745 BUS_DMA_NOWAIT | BUS_DMA_STREAMING | BUS_DMA_READ);
746 if (err) {
747 printf("%s: unable to load REQUEST_SENSE data DMA map: %d",
748 sc->sc_dev.dv_xname, err);
749 xs->error = XS_DRIVER_STUFFUP;
750 goto FREE;
751 }
752 bus_dmamap_sync(sc->sc_dmat, acb->datadma,
753 0, sizeof(xs->sense), BUS_DMASYNC_PREREAD);
754
755 sc->sc_tinfo[periph->target].senses++;
756 acb->status = ACB_S_READY;
757 TAILQ_INSERT_HEAD(&sc->ready_list, acb, chain);
758 if (((acb->xsflags & SCSI_POLL) == 0) && ((sc->sc_flags & OSIOP_NODMA) == 0))
759
760 timeout_add(&xs->stimeout, (xs->timeout/1000) * hz);
761 }
762
763 osiop_sched(sc);
764 }
765
766 void
767 osiop_abort(sc, where)
768 struct osiop_softc *sc;
769 const char *where;
770 {
771 u_int8_t dstat, sstat0;
772
773 sstat0 = osiop_read_1(sc, OSIOP_SSTAT0);
774 delay(25);
775 dstat = osiop_read_1(sc, OSIOP_DSTAT);
776
777 printf("%s: abort %s: dstat %02x, sstat0 %02x sbcl %02x\n",
778 sc->sc_dev.dv_xname, where,
779 dstat, sstat0,
780 osiop_read_1(sc, OSIOP_SBCL));
781
782
783 if (sc->sc_active > 0) {
784 sc->sc_active = 0;
785 }
786 }
787
788 void
789 osiop_init(sc)
790 struct osiop_softc *sc;
791 {
792 int i, inhibit_sync, inhibit_disc;
793
794 sc->sc_tcp[1] = 1000 / sc->sc_clock_freq;
795 sc->sc_tcp[2] = 1500 / sc->sc_clock_freq;
796 sc->sc_tcp[3] = 2000 / sc->sc_clock_freq;
797 sc->sc_minsync = sc->sc_tcp[1];
798
799 if (sc->sc_minsync < 25)
800 sc->sc_minsync = 25;
801
802 if (sc->sc_clock_freq <= 25) {
803 sc->sc_dcntl |= OSIOP_DCNTL_CF_1;
804 sc->sc_tcp[0] = sc->sc_tcp[1];
805 } else if (sc->sc_clock_freq <= 37) {
806 sc->sc_dcntl |= OSIOP_DCNTL_CF_1_5;
807 sc->sc_tcp[0] = sc->sc_tcp[2];
808 } else if (sc->sc_clock_freq <= 50) {
809 sc->sc_dcntl |= OSIOP_DCNTL_CF_2;
810 sc->sc_tcp[0] = sc->sc_tcp[3];
811 } else {
812 sc->sc_dcntl |= OSIOP_DCNTL_CF_3;
813 sc->sc_tcp[0] = 3000 / sc->sc_clock_freq;
814 }
815
816 if ((sc->sc_cfflags & 0x10000) != 0) {
817 sc->sc_flags |= OSIOP_NODMA;
818 #ifdef OSIOP_DEBUG
819 printf("%s: DMA disabled; use polling\n",
820 sc->sc_dev.dv_xname);
821 #endif
822 }
823
824 inhibit_sync = (sc->sc_cfflags & 0xff00) >> 8;
825 inhibit_disc = sc->sc_cfflags & 0x00ff;
826 #ifdef OSIOP_DEBUG
827 if (inhibit_sync != 0)
828 printf("%s: Inhibiting synchronous transfer: 0x%02x\n",
829 sc->sc_dev.dv_xname, inhibit_sync);
830 if (inhibit_disc != 0)
831 printf("%s: Inhibiting disconnect: 0x%02x\n",
832 sc->sc_dev.dv_xname, inhibit_disc);
833 #endif
834 for (i = 0; i < OSIOP_NTGT; i++) {
835 if (inhibit_sync & (1 << i))
836 sc->sc_tinfo[i].flags |= TI_NOSYNC;
837 if (inhibit_disc & (1 << i))
838 sc->sc_tinfo[i].flags |= TI_NODISC;
839 }
840
841 osiop_resetbus(sc);
842 osiop_reset(sc);
843 }
844
845 void
846 osiop_reset(sc)
847 struct osiop_softc *sc;
848 {
849 struct osiop_acb *acb;
850 int i, s;
851 u_int8_t stat;
852
853 #ifdef OSIOP_DEBUG
854 printf("%s: resetting chip\n", sc->sc_dev.dv_xname);
855 #endif
856 if (sc->sc_flags & OSIOP_ALIVE)
857 osiop_abort(sc, "reset");
858
859 s = splbio();
860
861
862
863
864
865
866
867 osiop_write_1(sc, OSIOP_ISTAT,
868 osiop_read_1(sc, OSIOP_ISTAT) | OSIOP_ISTAT_ABRT);
869
870 osiop_write_1(sc, OSIOP_ISTAT,
871 osiop_read_1(sc, OSIOP_ISTAT) | OSIOP_ISTAT_RST);
872 delay(100);
873 osiop_write_1(sc, OSIOP_ISTAT,
874 osiop_read_1(sc, OSIOP_ISTAT) & ~OSIOP_ISTAT_RST);
875 delay(100);
876
877
878
879
880 osiop_write_1(sc, OSIOP_SCNTL0,
881 OSIOP_ARB_FULL | OSIOP_SCNTL0_EPC | OSIOP_SCNTL0_EPG);
882 osiop_write_1(sc, OSIOP_SCNTL1, OSIOP_SCNTL1_ESR);
883 osiop_write_1(sc, OSIOP_DCNTL, sc->sc_dcntl);
884 osiop_write_1(sc, OSIOP_DMODE, sc->sc_dmode);
885
886 osiop_write_1(sc, OSIOP_SIEN, 0x00);
887 osiop_write_1(sc, OSIOP_DIEN, 0x00);
888 osiop_write_1(sc, OSIOP_SCID, OSIOP_SCID_VALUE(sc->sc_id));
889 osiop_write_1(sc, OSIOP_DWT, 0x00);
890 osiop_write_1(sc, OSIOP_CTEST0, osiop_read_1(sc, OSIOP_CTEST0)
891 | OSIOP_CTEST0_BTD | OSIOP_CTEST0_EAN);
892 osiop_write_1(sc, OSIOP_CTEST7,
893 osiop_read_1(sc, OSIOP_CTEST7) | sc->sc_ctest7);
894
895
896 for (i = 0; i < OSIOP_NTGT; i++) {
897 sc->sc_tinfo[i].state = NEG_INIT;
898 sc->sc_tinfo[i].period = 0;
899 sc->sc_tinfo[i].offset = 0;
900 }
901
902 stat = osiop_read_1(sc, OSIOP_ISTAT);
903 if (stat & OSIOP_ISTAT_SIP)
904 osiop_read_1(sc, OSIOP_SSTAT0);
905 if (stat & OSIOP_ISTAT_DIP) {
906 if (stat & OSIOP_ISTAT_SIP)
907
908 delay(25);
909 osiop_read_1(sc, OSIOP_DSTAT);
910 }
911
912 splx(s);
913
914 delay(osiop_reset_delay * 1000);
915
916 s = splbio();
917 if (sc->sc_nexus != NULL) {
918 sc->sc_nexus->xs->error =
919 (sc->sc_nexus->flags & ACB_F_TIMEOUT) ?
920 XS_TIMEOUT : XS_RESET;
921 sc->sc_nexus->status = ACB_S_DONE;
922 osiop_scsidone(sc->sc_nexus, SCSI_OSIOP_NOCHECK);
923 }
924 while ((acb = TAILQ_FIRST(&sc->nexus_list)) != NULL) {
925 acb->xs->error = (acb->flags & ACB_F_TIMEOUT) ?
926 XS_TIMEOUT : XS_RESET;
927 acb->status = ACB_S_DONE;
928 osiop_scsidone(acb, SCSI_OSIOP_NOCHECK);
929 }
930 splx(s);
931
932 sc->sc_flags &= ~(OSIOP_INTDEFER | OSIOP_INTSOFF);
933
934 sc->sc_sien = OSIOP_SIEN_M_A | OSIOP_SIEN_STO |
935 OSIOP_SIEN_SGE | OSIOP_SIEN_UDC | OSIOP_SIEN_RST | OSIOP_SIEN_PAR;
936 sc->sc_dien = OSIOP_DIEN_BF | OSIOP_DIEN_ABRT | OSIOP_DIEN_SIR |
937 OSIOP_DIEN_IID;
938 osiop_write_1(sc, OSIOP_SIEN, sc->sc_sien);
939 osiop_write_1(sc, OSIOP_DIEN, sc->sc_dien);
940 }
941
942 void
943 osiop_resetbus(sc)
944 struct osiop_softc *sc;
945 {
946
947 osiop_write_1(sc, OSIOP_SIEN, 0);
948 osiop_write_1(sc, OSIOP_SCNTL1,
949 osiop_read_1(sc, OSIOP_SCNTL1) | OSIOP_SCNTL1_RST);
950 delay(25);
951 osiop_write_1(sc, OSIOP_SCNTL1,
952 osiop_read_1(sc, OSIOP_SCNTL1) & ~OSIOP_SCNTL1_RST);
953 }
954
955
956
957
958
959 void
960 osiop_start(sc)
961 struct osiop_softc *sc;
962 {
963 struct osiop_acb *acb = sc->sc_nexus;
964 struct osiop_ds *ds = acb->ds;
965 struct scsi_xfer *xs = acb->xs;
966 bus_dmamap_t dsdma = sc->sc_dsdma, datadma = acb->datadma;
967 struct osiop_tinfo *ti;
968 int target = xs->sc_link->target;
969 int lun = xs->sc_link->lun;
970 int disconnect, i;
971
972 #ifdef OSIOP_DEBUG
973 if (osiop_debug & DEBUG_DISC &&
974 osiop_read_1(sc, OSIOP_SBCL) & OSIOP_BSY) {
975 printf("ACK! osiop was busy: script %p dsa %p active %d\n",
976 sc->sc_script, acb->ds, sc->sc_active);
977 printf("istat %02x sfbr %02x lcrc %02x sien %02x dien %02x\n",
978 osiop_read_1(sc, OSIOP_ISTAT),
979 osiop_read_1(sc, OSIOP_SFBR),
980 osiop_read_1(sc, OSIOP_LCRC),
981 osiop_read_1(sc, OSIOP_SIEN),
982 osiop_read_1(sc, OSIOP_DIEN));
983 #ifdef DDB
984 #if 0
985 Debugger();
986 #endif
987 #endif
988 }
989 #endif
990
991 #ifdef OSIOP_DEBUG
992 if (acb->status != ACB_S_READY)
993 panic("osiop_start: non-ready cmd in acb");
994 #endif
995
996 acb->intstat = 0;
997
998 ti = &sc->sc_tinfo[target];
999 ds->scsi_addr = ((1 << 16) << target) | (ti->sxfer << 8);
1000
1001 disconnect = (ds->scsi_cmd.opcode != REQUEST_SENSE) &&
1002 (ti->flags & TI_NODISC) == 0;
1003
1004 ds->msgout[0] = MSG_IDENTIFY(lun, disconnect);
1005 ds->id.count = 1;
1006 ds->stat[0] = SCSI_OSIOP_NOSTATUS;
1007 ds->msgbuf[0] = ds->msgbuf[1] = MSG_INVALID;
1008 bzero(&ds->data, sizeof(ds->data));
1009
1010
1011
1012
1013
1014
1015 if (ti->state == NEG_INIT) {
1016 if ((ti->flags & TI_NOSYNC) != 0) {
1017 ti->state = NEG_DONE;
1018 ti->period = 0;
1019 ti->offset = 0;
1020 osiop_update_xfer_mode(sc, target);
1021 #ifdef OSIOP_DEBUG
1022 if (osiop_debug & DEBUG_SYNC)
1023 printf("Forcing target %d asynchronous\n",
1024 target);
1025 #endif
1026 } else {
1027 ds->msgbuf[2] = MSG_INVALID;
1028 ds->msgout[1] = MSG_EXTENDED;
1029 ds->msgout[2] = MSG_EXT_SDTR_LEN;
1030 ds->msgout[3] = MSG_EXT_SDTR;
1031 ds->msgout[4] = sc->sc_minsync;
1032 ds->msgout[5] = OSIOP_MAX_OFFSET;
1033 ds->id.count = MSG_EXT_SDTR_LEN + 3;
1034 ti->state = NEG_WAITS;
1035 #ifdef OSIOP_DEBUG
1036 if (osiop_debug & DEBUG_SYNC)
1037 printf("Sending sync request to target %d\n",
1038 target);
1039 #endif
1040 }
1041 }
1042
1043 acb->curaddr = 0;
1044 acb->curlen = 0;
1045
1046
1047
1048
1049 if (acb->xsflags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
1050 for (i = 0; i < datadma->dm_nsegs; i++) {
1051 ds->data[i].count = datadma->dm_segs[i].ds_len;
1052 ds->data[i].addr = datadma->dm_segs[i].ds_addr;
1053 }
1054 }
1055
1056
1057 bus_dmamap_sync(sc->sc_dmat, dsdma,
1058 acb->dsoffset, sizeof(struct osiop_ds),
1059 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1060
1061 acb->status = ACB_S_ACTIVE;
1062
1063 #ifdef OSIOP_DEBUG
1064 if (osiop_debug & DEBUG_DISC &&
1065 osiop_read_1(sc, OSIOP_SBCL) & OSIOP_BSY) {
1066 printf("ACK! osiop was busy at start: "
1067 "script %p dsa %p active %d\n",
1068 sc->sc_script, acb->ds, sc->sc_active);
1069 #ifdef DDB
1070 #if 0
1071 Debugger();
1072 #endif
1073 #endif
1074 }
1075 #endif
1076 if (TAILQ_EMPTY(&sc->nexus_list)) {
1077 if (osiop_read_1(sc, OSIOP_ISTAT) & OSIOP_ISTAT_CON)
1078 printf("%s: osiop_select while connected?\n",
1079 sc->sc_dev.dv_xname);
1080 osiop_write_4(sc, OSIOP_TEMP, 0);
1081 osiop_write_1(sc, OSIOP_SBCL, ti->sbcl);
1082 osiop_write_4(sc, OSIOP_DSA,
1083 dsdma->dm_segs[0].ds_addr + acb->dsoffset);
1084 osiop_write_4(sc, OSIOP_DSP,
1085 sc->sc_scrdma->dm_segs[0].ds_addr + Ent_scripts);
1086 OSIOP_TRACE('s', 1, 0, 0);
1087 } else {
1088 if ((osiop_read_1(sc, OSIOP_ISTAT) & OSIOP_ISTAT_CON) == 0) {
1089 osiop_write_1(sc, OSIOP_ISTAT, OSIOP_ISTAT_SIGP);
1090 OSIOP_TRACE('s', 2, 0, 0);
1091 } else {
1092 OSIOP_TRACE('s', 3,
1093 osiop_read_1(sc, OSIOP_ISTAT), 0);
1094 }
1095 }
1096 #ifdef OSIOP_DEBUG
1097 osiopstarts++;
1098 #endif
1099 }
1100
1101
1102
1103
1104
1105 int
1106 osiop_checkintr(sc, istat, dstat, sstat0, status)
1107 struct osiop_softc *sc;
1108 u_int8_t istat;
1109 u_int8_t dstat;
1110 u_int8_t sstat0;
1111 int *status;
1112 {
1113 struct osiop_acb *acb = sc->sc_nexus;
1114 struct osiop_ds *ds;
1115 bus_dmamap_t dsdma = sc->sc_dsdma;
1116 bus_addr_t scraddr = sc->sc_scrdma->dm_segs[0].ds_addr;
1117 int target = 0;
1118 int dfifo, dbc, intcode, sstat1;
1119
1120 dfifo = osiop_read_1(sc, OSIOP_DFIFO);
1121 dbc = osiop_read_4(sc, OSIOP_DBC) & 0x00ffffff;
1122 sstat1 = osiop_read_1(sc, OSIOP_SSTAT1);
1123 osiop_write_1(sc, OSIOP_CTEST8,
1124 osiop_read_1(sc, OSIOP_CTEST8) | OSIOP_CTEST8_CLF);
1125 while ((osiop_read_1(sc, OSIOP_CTEST1) & OSIOP_CTEST1_FMT) !=
1126 OSIOP_CTEST1_FMT)
1127 ;
1128 osiop_write_1(sc, OSIOP_CTEST8,
1129 osiop_read_1(sc, OSIOP_CTEST8) & ~OSIOP_CTEST8_CLF);
1130 intcode = osiop_read_4(sc, OSIOP_DSPS);
1131 #ifdef OSIOP_DEBUG
1132 osiopints++;
1133 if (osiop_read_4(sc, OSIOP_DSP) != 0 &&
1134 (osiop_read_4(sc, OSIOP_DSP) < scraddr ||
1135 osiop_read_4(sc, OSIOP_DSP) >= scraddr + sizeof(osiop_script))) {
1136 printf("%s: dsp not within script dsp %x scripts %lx:%lx",
1137 sc->sc_dev.dv_xname,
1138 osiop_read_4(sc, OSIOP_DSP),
1139 scraddr, scraddr + sizeof(osiop_script));
1140 printf(" istat %x dstat %x sstat0 %x\n", istat, dstat, sstat0);
1141 #ifdef DDB
1142 Debugger();
1143 #endif
1144 }
1145 #endif
1146 OSIOP_TRACE('i', dstat, istat, (istat & OSIOP_ISTAT_DIP) ?
1147 intcode & 0xff : sstat0);
1148
1149 ds = NULL;
1150 if (acb != NULL) {
1151 ds = acb->ds;
1152 bus_dmamap_sync(sc->sc_dmat, dsdma,
1153 acb->dsoffset, sizeof(struct osiop_ds),
1154 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1155 #ifdef OSIOP_DEBUG
1156 if (acb->status != ACB_S_ACTIVE)
1157 printf("osiop_checkintr: acb not active (status %d)\n",
1158 acb->status);
1159 #endif
1160 }
1161
1162 if (dstat & OSIOP_DSTAT_SIR && intcode == A_ok) {
1163
1164 struct osiop_tinfo *ti;
1165 if (acb == NULL) {
1166 printf("%s: COMPLETE with no active command?\n",
1167 sc->sc_dev.dv_xname);
1168 return (0);
1169 }
1170 #ifdef OSIOP_DEBUG
1171 if (osiop_read_4(sc, OSIOP_DSA) !=
1172 dsdma->dm_segs[0].ds_addr + acb->dsoffset) {
1173 printf("osiop: invalid dsa: %x %lx\n",
1174 osiop_read_4(sc, OSIOP_DSA),
1175 dsdma->dm_segs[0].ds_addr + acb->dsoffset);
1176 panic("*** osiop DSA invalid ***");
1177 }
1178 #endif
1179 target = acb->xs->sc_link->target;
1180 ti = &sc->sc_tinfo[target];
1181 if (ti->state == NEG_WAITS) {
1182 if (ds->msgbuf[1] == MSG_INVALID)
1183 printf("%s: target %d ignored sync request\n",
1184 sc->sc_dev.dv_xname, target);
1185 else if (ds->msgbuf[1] == MSG_MESSAGE_REJECT)
1186 printf("%s: target %d rejected sync request\n",
1187 sc->sc_dev.dv_xname, target);
1188 ti->period = 0;
1189 ti->offset = 0;
1190 osiop_update_xfer_mode(sc, target);
1191 ti->state = NEG_DONE;
1192 }
1193 #ifdef OSIOP_DEBUG
1194 if (osiop_read_1(sc, OSIOP_SBCL) & OSIOP_BSY) {
1195 #if 0
1196 printf("ACK! osiop was busy at end: "
1197 "script %p dsa %p\n", &osiop_script, ds);
1198 #ifdef DDB
1199 Debugger();
1200 #endif
1201 #endif
1202 }
1203 if (ds->msgbuf[0] != MSG_CMDCOMPLETE)
1204 printf("%s: message was not COMMAND COMPLETE: %02x\n",
1205 sc->sc_dev.dv_xname, ds->msgbuf[0]);
1206 #endif
1207 if (!TAILQ_EMPTY(&sc->nexus_list))
1208 osiop_write_1(sc, OSIOP_DCNTL,
1209 osiop_read_1(sc, OSIOP_DCNTL) | OSIOP_DCNTL_STD);
1210 *status = ds->stat[0];
1211 acb->status = ACB_S_DONE;
1212 return (1);
1213 }
1214 if (dstat & OSIOP_DSTAT_SIR && intcode == A_int_syncmsg) {
1215 if (acb == NULL) {
1216 printf("%s: Sync message with no active command?\n",
1217 sc->sc_dev.dv_xname);
1218 return (0);
1219 }
1220 target = acb->xs->sc_link->target;
1221 if (ds->msgbuf[1] == MSG_EXTENDED &&
1222 ds->msgbuf[2] == MSG_EXT_SDTR_LEN &&
1223 ds->msgbuf[3] == MSG_EXT_SDTR) {
1224 struct osiop_tinfo *ti = &sc->sc_tinfo[target];
1225 #ifdef OSIOP_DEBUG
1226 if (osiop_debug & DEBUG_SYNC)
1227 printf("sync msg in: "
1228 "%02x %02x %02x %02x %02x %02x\n",
1229 ds->msgbuf[0], ds->msgbuf[1],
1230 ds->msgbuf[2], ds->msgbuf[3],
1231 ds->msgbuf[4], ds->msgbuf[5]);
1232 #endif
1233 ti->period = ds->msgbuf[4];
1234 ti->offset = ds->msgbuf[5];
1235 osiop_update_xfer_mode(sc, target);
1236
1237 bus_dmamap_sync(sc->sc_dmat, dsdma,
1238 acb->dsoffset, sizeof(struct osiop_ds),
1239 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1240 osiop_write_1(sc, OSIOP_SXFER, ti->sxfer);
1241 osiop_write_1(sc, OSIOP_SBCL, ti->sbcl);
1242 if (ti->state == NEG_WAITS) {
1243 ti->state = NEG_DONE;
1244 osiop_write_4(sc, OSIOP_DSP,
1245 scraddr + Ent_clear_ack);
1246 return (0);
1247 }
1248 osiop_write_1(sc, OSIOP_DCNTL,
1249 osiop_read_1(sc, OSIOP_DCNTL) | OSIOP_DCNTL_STD);
1250 ti->state = NEG_DONE;
1251 return (0);
1252 }
1253
1254 }
1255 if (sstat0 & OSIOP_SSTAT0_M_A) {
1256
1257 #ifdef OSIOP_DEBUG
1258 osiopphmm++;
1259 #endif
1260 if (acb == NULL) {
1261 printf("%s: Phase mismatch with no active command?\n",
1262 sc->sc_dev.dv_xname);
1263 return (0);
1264 }
1265 if (acb->datalen > 0) {
1266 int adjust = (dfifo - (dbc & 0x7f)) & 0x7f;
1267 if (sstat1 & OSIOP_SSTAT1_ORF)
1268 adjust++;
1269 if (sstat1 & OSIOP_SSTAT1_OLF)
1270 adjust++;
1271 acb->curaddr = osiop_read_4(sc, OSIOP_DNAD) - adjust;
1272 acb->curlen = dbc + adjust;
1273 #ifdef OSIOP_DEBUG
1274 if (osiop_debug & DEBUG_DISC) {
1275 printf("Phase mismatch: curaddr %lx "
1276 "curlen %lx dfifo %x dbc %x sstat1 %x "
1277 "adjust %x sbcl %x starts %d acb %p\n",
1278 acb->curaddr, acb->curlen, dfifo,
1279 dbc, sstat1, adjust,
1280 osiop_read_1(sc, OSIOP_SBCL),
1281 osiopstarts, acb);
1282 if (ds->data[1].count != 0) {
1283 int i;
1284 for (i = 0; ds->data[i].count != 0; i++)
1285 printf("chain[%d] "
1286 "addr %x len %x\n", i,
1287 ds->data[i].addr,
1288 ds->data[i].count);
1289 }
1290 bus_dmamap_sync(sc->sc_dmat, dsdma,
1291 acb->dsoffset, sizeof(struct osiop_ds),
1292 BUS_DMASYNC_PREREAD |
1293 BUS_DMASYNC_PREWRITE);
1294 }
1295 #endif
1296 }
1297 #ifdef OSIOP_DEBUG
1298 OSIOP_TRACE('m', osiop_read_1(sc, OSIOP_SBCL),
1299 osiop_read_4(sc, OSIOP_DSP) >> 8,
1300 osiop_read_4(sc, OSIOP_DSP));
1301 if (osiop_debug & DEBUG_PHASE)
1302 printf("Phase mismatch: %x dsp +%lx dcmd %x\n",
1303 osiop_read_1(sc, OSIOP_SBCL),
1304 osiop_read_4(sc, OSIOP_DSP) - scraddr,
1305 osiop_read_4(sc, OSIOP_DBC));
1306 #endif
1307 if ((osiop_read_1(sc, OSIOP_SBCL) & OSIOP_REQ) == 0) {
1308 printf("Phase mismatch: "
1309 "REQ not asserted! %02x dsp %x\n",
1310 osiop_read_1(sc, OSIOP_SBCL),
1311 osiop_read_4(sc, OSIOP_DSP));
1312 #if defined(OSIOP_DEBUG) && defined(DDB)
1313
1314 #endif
1315 }
1316 switch (OSIOP_PHASE(osiop_read_1(sc, OSIOP_SBCL))) {
1317 case DATA_OUT_PHASE:
1318 case DATA_IN_PHASE:
1319 case STATUS_PHASE:
1320 case COMMAND_PHASE:
1321 case MSG_IN_PHASE:
1322 case MSG_OUT_PHASE:
1323 osiop_write_4(sc, OSIOP_DSP, scraddr + Ent_switch);
1324 break;
1325 default:
1326 printf("%s: invalid phase\n", sc->sc_dev.dv_xname);
1327 goto bad_phase;
1328 }
1329 return (0);
1330 }
1331 if (sstat0 & OSIOP_SSTAT0_STO) {
1332
1333 if (acb == NULL) {
1334 printf("%s: Select timeout with no active command?\n",
1335 sc->sc_dev.dv_xname);
1336 #if 0
1337 return (0);
1338 #else
1339 goto bad_phase;
1340 #endif
1341 }
1342 #ifdef OSIOP_DEBUG
1343 if (osiop_read_1(sc, OSIOP_SBCL) & OSIOP_BSY) {
1344 printf("ACK! osiop was busy at timeout: "
1345 "script %p dsa %lx\n", sc->sc_script,
1346 dsdma->dm_segs[0].ds_addr + acb->dsoffset);
1347 printf(" sbcl %x sdid %x "
1348 "istat %x dstat %x sstat0 %x\n",
1349 osiop_read_1(sc, OSIOP_SBCL),
1350 osiop_read_1(sc, OSIOP_SDID),
1351 istat, dstat, sstat0);
1352 if ((osiop_read_1(sc, OSIOP_SBCL) & OSIOP_BSY) == 0) {
1353 printf("Yikes, it's not busy now!\n");
1354 #if 0
1355 *status = SCSI_OSIOP_NOSTATUS;
1356 if (!TAILQ_EMPTY(&sc->nexus_list))
1357 osiop_write_4(sc, OSIOP_DSP,
1358 scraddr + Ent_wait_reselect);
1359 return (1);
1360 #endif
1361 }
1362 #if 0
1363 osiop_write_1(sc, OSIOP_DCNTL,
1364 osiop_read_1(sc, OSIOP_DCNTL) | OSIOP_DCNTL_STD);
1365 #endif
1366 #ifdef DDB
1367 Debugger();
1368 #endif
1369 return (0);
1370 }
1371 #endif
1372 acb->status = ACB_S_DONE;
1373 *status = SCSI_OSIOP_NOSTATUS;
1374 acb->xs->error = XS_SELTIMEOUT;
1375 if (!TAILQ_EMPTY(&sc->nexus_list))
1376 osiop_write_4(sc, OSIOP_DSP,
1377 scraddr + Ent_wait_reselect);
1378 return (1);
1379 }
1380 if (acb != NULL)
1381 target = acb->xs->sc_link->target;
1382 else
1383 target = sc->sc_id;
1384 if (sstat0 & OSIOP_SSTAT0_UDC) {
1385 #ifdef OSIOP_DEBUG
1386 if (acb == NULL)
1387 printf("%s: Unexpected disconnect "
1388 "with no active command?\n", sc->sc_dev.dv_xname);
1389 printf("%s: target %d disconnected unexpectedly\n",
1390 sc->sc_dev.dv_xname, target);
1391 #endif
1392 #if 0
1393 osiop_abort(sc, "osiop_chkintr");
1394 #endif
1395 *status = SCSI_CHECK;
1396 if (!TAILQ_EMPTY(&sc->nexus_list))
1397 osiop_write_4(sc, OSIOP_DSP,
1398 scraddr + Ent_wait_reselect);
1399 return (acb != NULL);
1400 }
1401 if (dstat & OSIOP_DSTAT_SIR &&
1402 (intcode == A_int_disc || intcode == A_int_disc_wodp)) {
1403
1404 if (acb == NULL) {
1405 printf("%s: Disconnect with no active command?\n",
1406 sc->sc_dev.dv_xname);
1407 return (0);
1408 }
1409 #ifdef OSIOP_DEBUG
1410 if (osiop_debug & DEBUG_DISC) {
1411 printf("%s: ID %02x disconnected TEMP %x (+%lx) "
1412 "curaddr %lx curlen %lx buf %x len %x dfifo %x "
1413 "dbc %x sstat1 %x starts %d acb %p\n",
1414 sc->sc_dev.dv_xname, 1 << target,
1415 osiop_read_4(sc, OSIOP_TEMP),
1416 (osiop_read_4(sc, OSIOP_TEMP) != 0) ?
1417 osiop_read_4(sc, OSIOP_TEMP) - scraddr : 0,
1418 acb->curaddr, acb->curlen,
1419 ds->data[0].addr, ds->data[0].count,
1420 dfifo, dbc, sstat1, osiopstarts, acb);
1421 bus_dmamap_sync(sc->sc_dmat, dsdma,
1422 acb->dsoffset, sizeof(struct osiop_ds),
1423 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1424 }
1425 #endif
1426
1427
1428
1429
1430
1431
1432
1433
1434 if (acb->datalen > 0 &&
1435 osiop_read_4(sc, OSIOP_TEMP) != 0) {
1436 long n = osiop_read_4(sc, OSIOP_TEMP) - scraddr;
1437
1438 if (acb->curlen != 0 &&
1439 acb->curlen != ds->data[0].count)
1440 printf("%s: curaddr/curlen already set? "
1441 "n %lx iob %lx/%lx chain[0] %x/%x\n",
1442 sc->sc_dev.dv_xname, n,
1443 acb->curaddr, acb->curlen,
1444 ds->data[0].addr, ds->data[0].count);
1445 if (n < Ent_datain)
1446 n = (n - Ent_dataout) / 16;
1447 else
1448 n = (n - Ent_datain) / 16;
1449 if (n < 0 || n >= OSIOP_NSG)
1450 printf("TEMP invalid %ld\n", n);
1451 else {
1452 acb->curaddr = ds->data[n].addr;
1453 acb->curlen = ds->data[n].count;
1454 }
1455 #ifdef OSIOP_DEBUG
1456 if (osiop_debug & DEBUG_DISC) {
1457 printf("%s: TEMP offset %ld",
1458 sc->sc_dev.dv_xname, n);
1459 printf(" curaddr %lx curlen %lx\n",
1460 acb->curaddr, acb->curlen);
1461 }
1462 #endif
1463 }
1464
1465
1466
1467
1468
1469
1470
1471 if (acb->curlen > 0) {
1472 int i, j;
1473 #ifdef OSIOP_DEBUG
1474 if (osiop_debug & DEBUG_DISC)
1475 printf("%s: adjusting DMA chain\n",
1476 sc->sc_dev.dv_xname);
1477 if (intcode == A_int_disc_wodp)
1478 printf("%s: ID %02x disconnected "
1479 "without Save Data Pointers\n",
1480 sc->sc_dev.dv_xname, 1 << target);
1481 #endif
1482 for (i = 0; i < OSIOP_NSG; i++) {
1483 if (ds->data[i].count == 0)
1484 break;
1485 if (acb->curaddr >= ds->data[i].addr &&
1486 acb->curaddr <
1487 (ds->data[i].addr + ds->data[i].count))
1488 break;
1489 }
1490 if (i >= OSIOP_NSG || ds->data[i].count == 0) {
1491 printf("couldn't find saved data pointer: "
1492 "curaddr %lx curlen %lx i %d\n",
1493 acb->curaddr, acb->curlen, i);
1494 #if defined(OSIOP_DEBUG) && defined(DDB)
1495 Debugger();
1496 #endif
1497 }
1498 #ifdef OSIOP_DEBUG
1499 if (osiop_debug & DEBUG_DISC)
1500 printf(" chain[0]: %x/%x -> %lx/%lx\n",
1501 ds->data[0].addr, ds->data[0].count,
1502 acb->curaddr, acb->curlen);
1503 #endif
1504 ds->data[0].addr = acb->curaddr;
1505 ds->data[0].count = acb->curlen;
1506 for (j = 1, i = i + 1;
1507 i < OSIOP_NSG && ds->data[i].count > 0;
1508 i++, j++) {
1509 #ifdef OSIOP_DEBUG
1510 if (osiop_debug & DEBUG_DISC)
1511 printf(" chain[%d]: %x/%x -> %x/%x\n",
1512 j,
1513 ds->data[j].addr, ds->data[j].count,
1514 ds->data[i].addr, ds->data[i].count);
1515 #endif
1516 ds->data[j].addr = ds->data[i].addr;
1517 ds->data[j].count = ds->data[i].count;
1518 }
1519 if (j < OSIOP_NSG) {
1520 ds->data[j].addr = 0;
1521 ds->data[j].count = 0;
1522 }
1523 bus_dmamap_sync(sc->sc_dmat, dsdma,
1524 acb->dsoffset, sizeof(struct osiop_ds),
1525 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1526 }
1527 sc->sc_tinfo[target].dconns++;
1528
1529
1530
1531
1532
1533 acb->intstat = sc->sc_flags & OSIOP_INTSOFF;
1534 TAILQ_INSERT_TAIL(&sc->nexus_list, acb, chain);
1535 sc->sc_nexus = NULL;
1536 osiop_write_4(sc, OSIOP_DSP, scraddr + Ent_wait_reselect);
1537
1538 osiop_sched(sc);
1539 return (0);
1540 }
1541 if (dstat & OSIOP_DSTAT_SIR && intcode == A_int_reconnect) {
1542 int reselid = ffs(osiop_read_4(sc, OSIOP_SCRATCH) & 0xff) - 1;
1543 int reselun = osiop_read_1(sc, OSIOP_SFBR) & 0x07;
1544 #ifdef OSIOP_DEBUG
1545 u_int8_t resmsg;
1546 #endif
1547
1548
1549
1550 sc->sc_sstat1 = osiop_read_1(sc, OSIOP_SBCL);
1551 #ifdef OSIOP_DEBUG
1552 if (osiop_debug & DEBUG_DISC)
1553 printf("%s: target ID %02x reselected dsps %x\n",
1554 sc->sc_dev.dv_xname, reselid, intcode);
1555 resmsg = osiop_read_1(sc, OSIOP_SFBR);
1556 if (!MSG_ISIDENTIFY(resmsg))
1557 printf("%s: Reselect message in was not identify: "
1558 "%02x\n", sc->sc_dev.dv_xname, resmsg);
1559 #endif
1560 if (sc->sc_nexus != NULL) {
1561 struct scsi_link *periph =
1562 sc->sc_nexus->xs->sc_link;
1563 #ifdef OSIOP_DEBUG
1564 if (osiop_debug & DEBUG_DISC)
1565 printf("%s: reselect ID %02x w/active\n",
1566 sc->sc_dev.dv_xname, reselid);
1567 #endif
1568 TAILQ_INSERT_HEAD(&sc->ready_list,
1569 sc->sc_nexus, chain);
1570 sc->sc_tinfo[periph->target].lubusy
1571 &= ~(1 << periph->lun);
1572 sc->sc_active--;
1573 }
1574
1575
1576
1577
1578 TAILQ_FOREACH(acb, &sc->nexus_list, chain) {
1579 struct scsi_link *periph = acb->xs->sc_link;
1580 if (reselid != periph->target ||
1581 reselun != periph->lun) {
1582 continue;
1583 }
1584 TAILQ_REMOVE(&sc->nexus_list, acb, chain);
1585 sc->sc_nexus = acb;
1586 sc->sc_flags |= acb->intstat;
1587 acb->intstat = 0;
1588 osiop_write_4(sc, OSIOP_DSA,
1589 dsdma->dm_segs[0].ds_addr + acb->dsoffset);
1590 osiop_write_1(sc, OSIOP_SXFER,
1591 sc->sc_tinfo[reselid].sxfer);
1592 osiop_write_1(sc, OSIOP_SBCL,
1593 sc->sc_tinfo[reselid].sbcl);
1594 break;
1595 }
1596 if (acb == NULL) {
1597 printf("%s: target ID %02x reselect nexus_list %p\n",
1598 sc->sc_dev.dv_xname, reselid,
1599 TAILQ_FIRST(&sc->nexus_list));
1600 panic("unable to find reselecting device");
1601 }
1602
1603 osiop_write_4(sc, OSIOP_TEMP, 0);
1604 osiop_write_1(sc, OSIOP_DCNTL,
1605 osiop_read_1(sc, OSIOP_DCNTL) | OSIOP_DCNTL_STD);
1606 return (0);
1607 }
1608 if (dstat & OSIOP_DSTAT_SIR && intcode == A_int_connect) {
1609 #ifdef OSIOP_DEBUG
1610 u_int8_t ctest2 = osiop_read_1(sc, OSIOP_CTEST2);
1611
1612
1613 if (osiop_debug & DEBUG_DISC ||
1614 (ctest2 & OSIOP_CTEST2_SIGP) == 0)
1615 printf("%s: reselect interrupted (Sig_P?) "
1616 "scntl1 %x ctest2 %x sfbr %x istat %x/%x\n",
1617 sc->sc_dev.dv_xname,
1618 osiop_read_1(sc, OSIOP_SCNTL1), ctest2,
1619 osiop_read_1(sc, OSIOP_SFBR), istat,
1620 osiop_read_1(sc, OSIOP_ISTAT));
1621 #endif
1622
1623 if (sc->sc_nexus == NULL) {
1624 #ifdef OSIOP_DEBUG
1625 printf("%s: reselect interrupted, sc_nexus == NULL\n",
1626 sc->sc_dev.dv_xname);
1627 #if 0
1628 osiop_dump(sc);
1629 #ifdef DDB
1630 Debugger();
1631 #endif
1632 #endif
1633 #endif
1634 osiop_write_1(sc, OSIOP_DCNTL,
1635 osiop_read_1(sc, OSIOP_DCNTL) | OSIOP_DCNTL_STD);
1636 return (0);
1637 }
1638 target = sc->sc_nexus->xs->sc_link->target;
1639 osiop_write_4(sc, OSIOP_TEMP, 0);
1640 osiop_write_4(sc, OSIOP_DSA,
1641 dsdma->dm_segs[0].ds_addr + sc->sc_nexus->dsoffset);
1642 osiop_write_1(sc, OSIOP_SXFER, sc->sc_tinfo[target].sxfer);
1643 osiop_write_1(sc, OSIOP_SBCL, sc->sc_tinfo[target].sbcl);
1644 osiop_write_4(sc, OSIOP_DSP, scraddr + Ent_scripts);
1645 return (0);
1646 }
1647 if (dstat & OSIOP_DSTAT_SIR && intcode == A_int_msgin) {
1648
1649 if (acb == NULL) {
1650 printf("%s: Bad message-in with no active command?\n",
1651 sc->sc_dev.dv_xname);
1652 return (0);
1653 }
1654 printf("%s: Unrecognized message in data "
1655 "sfbr %x msg %x sbcl %x\n", sc->sc_dev.dv_xname,
1656 osiop_read_1(sc, OSIOP_SFBR), ds->msgbuf[1],
1657 osiop_read_1(sc, OSIOP_SBCL));
1658
1659 osiop_write_4(sc, OSIOP_DSP, scraddr + Ent_switch);
1660 bus_dmamap_sync(sc->sc_dmat, dsdma,
1661 acb->dsoffset, sizeof(struct osiop_ds),
1662 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1663 return (0);
1664 }
1665 if (dstat & OSIOP_DSTAT_SIR && intcode == A_int_status) {
1666
1667 printf("%s: Status phase not followed by message in phase? "
1668 "sbcl %x sbdl %x\n", sc->sc_dev.dv_xname,
1669 osiop_read_1(sc, OSIOP_SBCL),
1670 osiop_read_1(sc, OSIOP_SBDL));
1671 if (osiop_read_1(sc, OSIOP_SBCL) == 0xa7) {
1672
1673 osiop_write_1(sc, OSIOP_DCNTL,
1674 osiop_read_1(sc, OSIOP_DCNTL) | OSIOP_DCNTL_STD);
1675 return (0);
1676 }
1677 }
1678 if (dstat & OSIOP_DSTAT_SIR && sstat0 == 0) {
1679 printf("OSIOP interrupt: %x sts %x msg %x %x sbcl %x\n",
1680 intcode, ds->stat[0], ds->msgbuf[0], ds->msgbuf[1],
1681 osiop_read_1(sc, OSIOP_SBCL));
1682 osiop_reset(sc);
1683 *status = SCSI_OSIOP_NOSTATUS;
1684 return (0);
1685 }
1686 if (sstat0 & OSIOP_SSTAT0_SGE)
1687 printf("%s: SCSI Gross Error\n", sc->sc_dev.dv_xname);
1688 if (sstat0 & OSIOP_SSTAT0_PAR)
1689 printf("%s: Parity Error\n", sc->sc_dev.dv_xname);
1690 if (dstat & OSIOP_DSTAT_IID)
1691 printf("%s: Invalid instruction detected\n",
1692 sc->sc_dev.dv_xname);
1693 bad_phase:
1694
1695
1696
1697
1698
1699
1700 printf("osiop_chkintr: target %x ds %p\n", target, ds);
1701 printf("scripts %lx ds %lx dsp %x dcmd %x\n", scraddr,
1702 sc->sc_dsdma->dm_segs[0].ds_addr + acb->dsoffset,
1703 osiop_read_4(sc, OSIOP_DSP),
1704 osiop_read_4(sc, OSIOP_DBC));
1705 printf("osiop_chkintr: istat %x dstat %x sstat0 %x "
1706 "dsps %x dsa %x sbcl %x sts %x msg %x %x sfbr %x\n",
1707 istat, dstat, sstat0, intcode,
1708 osiop_read_4(sc, OSIOP_DSA),
1709 osiop_read_1(sc, OSIOP_SBCL),
1710 ds->stat[0], ds->msgbuf[0], ds->msgbuf[1],
1711 osiop_read_1(sc, OSIOP_SFBR));
1712 #ifdef OSIOP_DEBUG
1713 if (osiop_debug & DEBUG_DMA)
1714 panic("osiop_chkintr: **** temp ****");
1715 #if 0
1716 #ifdef DDB
1717 Debugger();
1718 #endif
1719 #endif
1720 #endif
1721 osiop_reset(sc);
1722 *status = SCSI_OSIOP_NOSTATUS;
1723 if (acb != NULL)
1724 acb->status = ACB_S_DONE;
1725 return (0);
1726 }
1727
1728 void
1729 osiop_select(sc)
1730 struct osiop_softc *sc;
1731 {
1732 struct osiop_acb *acb = sc->sc_nexus;
1733
1734 #ifdef OSIOP_DEBUG
1735 if (osiop_debug & DEBUG_CMD)
1736 printf("%s: select ", sc->sc_dev.dv_xname);
1737 #endif
1738
1739 if (acb->xsflags & SCSI_POLL || sc->sc_flags & OSIOP_NODMA) {
1740 sc->sc_flags |= OSIOP_INTSOFF;
1741 sc->sc_flags &= ~OSIOP_INTDEFER;
1742 if ((osiop_read_1(sc, OSIOP_ISTAT) & OSIOP_ISTAT_CON) == 0) {
1743 osiop_write_1(sc, OSIOP_SIEN, 0);
1744 osiop_write_1(sc, OSIOP_DIEN, 0);
1745 }
1746 #if 0
1747 } else if ((sc->sc_flags & OSIOP_INTDEFER) == 0) {
1748 sc->sc_flags &= ~OSIOP_INTSOFF;
1749 if ((osiop_read_1(sc, OSIOP_ISTAT) & OSIOP_ISTAT_CON) == 0) {
1750 osiop_write_1(sc, OSIOP_SIEN, sc->sc_sien);
1751 osiop_write_1(sc, OSIOP_DIEN, sc->sc_dien);
1752 }
1753 #endif
1754 }
1755 #ifdef OSIOP_DEBUG
1756 if (osiop_debug & DEBUG_CMD)
1757 printf("osiop_select: target %x cmd %02x ds %p\n",
1758 acb->xs->sc_link->target,
1759 acb->ds->scsi_cmd.opcode, sc->sc_nexus->ds);
1760 #endif
1761
1762 osiop_start(sc);
1763
1764 return;
1765 }
1766
1767
1768
1769
1770
1771 void
1772 osiop_intr(sc)
1773 struct osiop_softc *sc;
1774 {
1775 int status, s;
1776 u_int8_t istat, dstat, sstat0;
1777
1778 s = splbio();
1779
1780 istat = sc->sc_istat;
1781 if ((istat & (OSIOP_ISTAT_SIP | OSIOP_ISTAT_DIP)) == 0) {
1782 splx(s);
1783 return;
1784 }
1785
1786
1787 dstat = sc->sc_dstat;
1788 sstat0 = sc->sc_sstat0;
1789 sc->sc_istat = 0;
1790 #ifdef OSIOP_DEBUG
1791 if (!sc->sc_active) {
1792
1793 printf("%s: spurious interrupt? "
1794 "istat %x dstat %x sstat0 %x nexus %p status %x\n",
1795 sc->sc_dev.dv_xname, istat, dstat, sstat0, sc->sc_nexus,
1796 (sc->sc_nexus != NULL) ? sc->sc_nexus->ds->stat[0] : 0);
1797 }
1798 #endif
1799
1800 #ifdef OSIOP_DEBUG
1801 if (osiop_debug & (DEBUG_INT|DEBUG_CMD)) {
1802
1803 printf("%s: intr istat %x dstat %x sstat0 %x dsps %x "
1804 "sbcl %x dsp %x dcmd %x sts %x msg %x\n",
1805 sc->sc_dev.dv_xname,
1806 istat, dstat, sstat0,
1807 osiop_read_4(sc, OSIOP_DSPS),
1808 osiop_read_1(sc, OSIOP_SBCL),
1809 osiop_read_4(sc, OSIOP_DSP),
1810 osiop_read_4(sc, OSIOP_DBC),
1811 (sc->sc_nexus != NULL) ? sc->sc_nexus->ds->stat[0] : 0,
1812 (sc->sc_nexus != NULL) ? sc->sc_nexus->ds->msgbuf[0] : 0);
1813 }
1814 #endif
1815 if (sc->sc_flags & OSIOP_INTDEFER) {
1816 sc->sc_flags &= ~(OSIOP_INTDEFER | OSIOP_INTSOFF);
1817 osiop_write_1(sc, OSIOP_SIEN, sc->sc_sien);
1818 osiop_write_1(sc, OSIOP_DIEN, sc->sc_dien);
1819 }
1820 if (osiop_checkintr(sc, istat, dstat, sstat0, &status)) {
1821 #if 0
1822 if (status == SCSI_OSIOP_NOSTATUS)
1823 printf("osiop_intr: no valid status \n");
1824 #endif
1825 if ((sc->sc_flags & (OSIOP_INTSOFF | OSIOP_INTDEFER)) !=
1826 OSIOP_INTSOFF) {
1827 #if 0
1828 if (osiop_read_1(sc, OSIOP_SBCL) & OSIOP_BSY) {
1829 struct scsi_link *periph;
1830
1831 periph = sc->sc_nexus->xs->sc_link;
1832 printf("%s: SCSI bus busy at completion"
1833 " targ %d sbcl %02x sfbr %x lcrc "
1834 "%02x dsp +%x\n", sc->sc_dev.dv_xname,
1835 periph->periphtarget,
1836 osiop_read_1(sc, OSIOP_SBCL),
1837 osiop_read_1(sc, OSIOP_SFBR),
1838 osiop_read_1(sc, OSIOP_LCRC),
1839 osiop_read_4(sc, OSIOP_DSP) -
1840 sc->sc_scrdma->dm_segs[0].ds_addr);
1841 }
1842 #endif
1843 osiop_scsidone(sc->sc_nexus, status);
1844 }
1845 }
1846 splx(s);
1847 }
1848
1849 void
1850 osiop_update_xfer_mode(sc, target)
1851 struct osiop_softc *sc;
1852 int target;
1853 {
1854 struct osiop_tinfo *ti = &sc->sc_tinfo[target];
1855
1856 printf("%s: target %d now using 8 bit ", sc->sc_dev.dv_xname, target);
1857
1858 ti->sxfer = 0;
1859 ti->sbcl = 0;
1860 if (ti->offset != 0) {
1861 scsi_period_to_osiop(sc, target);
1862 switch (ti->period) {
1863 case 0x00:
1864 case 0x01:
1865 case 0x02:
1866 case 0x03:
1867 case 0x04:
1868 case 0x05:
1869 case 0x06:
1870 case 0x07:
1871 case 0x08:
1872
1873 printf("??");
1874 break;
1875 case 0x09:
1876
1877 printf("80");
1878 break;
1879 case 0x0a:
1880
1881 printf("40");
1882 break;
1883 case 0x0b:
1884
1885 printf("33");
1886 break;
1887 case 0x0c:
1888
1889 printf("20");
1890 break;
1891 default:
1892
1893 printf("%d", 1000/(ti->period*4));
1894 break;
1895 }
1896 printf(" MHz %d REQ/ACK offset", ti->offset);
1897 } else
1898 printf("asynch");
1899
1900 printf(" xfers\n");
1901 }
1902
1903
1904
1905
1906
1907
1908 void
1909 scsi_period_to_osiop(sc, target)
1910 struct osiop_softc *sc;
1911 int target;
1912 {
1913 int period, offset, sxfer, sbcl;
1914 #ifdef OSIOP_DEBUG
1915 int i;
1916 #endif
1917
1918 period = sc->sc_tinfo[target].period;
1919 offset = sc->sc_tinfo[target].offset;
1920 #ifdef OSIOP_DEBUG
1921 if (osiop_debug & DEBUG_SYNC) {
1922 sxfer = 0;
1923 if (offset <= OSIOP_MAX_OFFSET)
1924 sxfer = offset;
1925 for (i = 0; i < sizeof(sync_tab) / sizeof(sync_tab[0]); i++) {
1926 if (period <= sync_tab[i].p) {
1927 sxfer |= sync_tab[i].r & 0x70;
1928 sbcl = sync_tab[i].r & 0x03;
1929 break;
1930 }
1931 }
1932 printf("osiop sync old: osiop_sxfr %02x, osiop_sbcl %02x\n",
1933 sxfer, sbcl);
1934 }
1935 #endif
1936 for (sbcl = 1; sbcl < 4; sbcl++) {
1937 sxfer = (period * 4 - 1) / sc->sc_tcp[sbcl] - 3;
1938 if (sxfer >= 0 && sxfer <= 7)
1939 break;
1940 }
1941 if (sbcl > 3) {
1942 printf("osiop sync: unable to compute sync params "
1943 "for period %d ns\n", period * 4);
1944
1945
1946
1947 sxfer = sbcl = 0;
1948 } else {
1949 sxfer = (sxfer << 4) | ((offset <= OSIOP_MAX_OFFSET) ?
1950 offset : OSIOP_MAX_OFFSET);
1951 #ifdef OSIOP_DEBUG
1952 if (osiop_debug & DEBUG_SYNC) {
1953 printf("osiop sync: params for period %dns: sxfer %x sbcl %x",
1954 period * 4, sxfer, sbcl);
1955 printf(" actual period %dns\n",
1956 sc->sc_tcp[sbcl] * ((sxfer >> 4) + 4));
1957 }
1958 #endif
1959 }
1960 sc->sc_tinfo[target].sxfer = sxfer;
1961 sc->sc_tinfo[target].sbcl = sbcl;
1962 #ifdef OSIOP_DEBUG
1963 if (osiop_debug & DEBUG_SYNC)
1964 printf("osiop sync: osiop_sxfr %02x, osiop_sbcl %02x\n",
1965 sxfer, sbcl);
1966 #endif
1967 }
1968
1969 void
1970 osiop_timeout(arg)
1971 void *arg;
1972 {
1973 struct osiop_acb *acb = arg;
1974 struct scsi_xfer *xs = acb->xs;
1975 struct osiop_softc *sc = acb->sc;
1976 int s;
1977
1978 sc_print_addr(xs->sc_link);
1979 printf("command 0x%02x timeout on xs %p\n", xs->cmd->opcode, xs);
1980
1981 s = splbio();
1982
1983 osiop_resetbus(sc);
1984
1985 acb->flags |= ACB_F_TIMEOUT;
1986 osiop_reset(sc);
1987 splx(s);
1988 return;
1989 }
1990
1991 #ifdef OSIOP_DEBUG
1992
1993 #if OSIOP_TRACE_SIZE
1994 void
1995 osiop_dump_trace()
1996 {
1997 int i;
1998
1999 printf("osiop trace: next index %d\n", osiop_trix);
2000 i = osiop_trix;
2001 do {
2002 printf("%3d: '%c' %02x %02x %02x\n", i,
2003 osiop_trbuf[i], osiop_trbuf[i + 1],
2004 osiop_trbuf[i + 2], osiop_trbuf[i + 3]);
2005 i = (i + 4) & (OSIOP_TRACE_SIZE - 1);
2006 } while (i != osiop_trix);
2007 }
2008 #endif
2009
2010 void
2011 osiop_dump_acb(acb)
2012 struct osiop_acb *acb;
2013 {
2014 u_int8_t *b;
2015 int i;
2016
2017 printf("acb@%p ", acb);
2018 if (acb->xs == NULL) {
2019 printf("<unused>\n");
2020 return;
2021 }
2022
2023 b = (u_int8_t *)&acb->ds->scsi_cmd;
2024 printf("(%d:%d) status %2x cmdlen %2ld cmd ",
2025 acb->xs->sc_link->target,
2026 acb->xs->sc_link->lun,
2027 acb->status,
2028 acb->ds->cmd.count);
2029 for (i = acb->ds->cmd.count; i > 0; i--)
2030 printf(" %02x", *b++);
2031 printf("\n");
2032 printf(" xs: %p data %p:%04x ", acb->xs, acb->data,
2033 acb->datalen);
2034 printf("cur %lx:%lx\n", acb->curaddr, acb->curlen);
2035 }
2036
2037 void
2038 osiop_dump(sc)
2039 struct osiop_softc *sc;
2040 {
2041 struct osiop_acb *acb;
2042 int i, s;
2043
2044 s = splbio();
2045 #if OSIOP_TRACE_SIZE
2046 osiop_dump_trace();
2047 #endif
2048 printf("%s@%p istat %02x\n",
2049 sc->sc_dev.dv_xname, sc, osiop_read_1(sc, OSIOP_ISTAT));
2050 if ((acb = TAILQ_FIRST(&sc->free_list)) != NULL) {
2051 printf("Free list:\n");
2052 while (acb) {
2053 osiop_dump_acb(acb);
2054 acb = TAILQ_NEXT(acb, chain);
2055 }
2056 }
2057 if ((acb = TAILQ_FIRST(&sc->ready_list)) != NULL) {
2058 printf("Ready list:\n");
2059 while (acb) {
2060 osiop_dump_acb(acb);
2061 acb = TAILQ_NEXT(acb, chain);
2062 }
2063 }
2064 if ((acb = TAILQ_FIRST(&sc->nexus_list)) != NULL) {
2065 printf("Nexus list:\n");
2066 while (acb) {
2067 osiop_dump_acb(acb);
2068 acb = TAILQ_NEXT(acb, chain);
2069 }
2070 }
2071 if (sc->sc_nexus) {
2072 printf("Nexus:\n");
2073 osiop_dump_acb(sc->sc_nexus);
2074 }
2075 for (i = 0; i < OSIOP_NTGT; i++) {
2076 if (sc->sc_tinfo[i].cmds > 2) {
2077 printf("tgt %d: cmds %d disc %d lubusy %x\n",
2078 i, sc->sc_tinfo[i].cmds,
2079 sc->sc_tinfo[i].dconns,
2080 sc->sc_tinfo[i].lubusy);
2081 }
2082 }
2083 splx(s);
2084 }
2085 #endif