This source file includes following definitions.
- oosiop_attach
- oosiop_alloc_cb
- oosiop_relocate_io
- oosiop_relocate_tc
- oosiop_fixup_select
- oosiop_fixup_jump
- oosiop_fixup_move
- oosiop_load_script
- oosiop_setup_sgdma
- oosiop_setup_dma
- oosiop_flush_fifo
- oosiop_clear_fifo
- oosiop_phasemismatch
- oosiop_setup_syncxfer
- oosiop_set_syncparam
- oosiop_minphys
- oosiop_scsicmd
- oosiop_poll
- oosiop_setup
- oosiop_done
- oosiop_timeout
- oosiop_reset
- oosiop_reset_bus
- oosiop_intr
- oosiop_processintr
- oosiop_scriptintr
- oosiop_msgin
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 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/timeout.h>
41 #include <sys/kernel.h>
42 #include <sys/device.h>
43 #include <sys/buf.h>
44 #include <sys/malloc.h>
45 #include <sys/queue.h>
46
47 #include <uvm/uvm_extern.h>
48
49 #include <scsi/scsi_all.h>
50 #include <scsi/scsiconf.h>
51 #include <scsi/scsi_message.h>
52
53 #include <machine/cpu.h>
54 #include <machine/bus.h>
55
56 #include <dev/ic/oosiopreg.h>
57 #include <dev/ic/oosiopvar.h>
58
59
60 #include <dev/microcode/siop/oosiop.out>
61
62 int oosiop_alloc_cb(struct oosiop_softc *, int);
63
64 static __inline void oosiop_relocate_io(struct oosiop_softc *, bus_addr_t);
65 static __inline void oosiop_relocate_tc(struct oosiop_softc *, bus_addr_t);
66 static __inline void oosiop_fixup_select(struct oosiop_softc *, bus_addr_t,
67 int);
68 static __inline void oosiop_fixup_jump(struct oosiop_softc *, bus_addr_t,
69 bus_addr_t);
70 static __inline void oosiop_fixup_move(struct oosiop_softc *, bus_addr_t,
71 bus_size_t, bus_addr_t);
72
73 void oosiop_load_script(struct oosiop_softc *);
74 void oosiop_setup_sgdma(struct oosiop_softc *, struct oosiop_cb *);
75 void oosiop_setup_dma(struct oosiop_softc *);
76 void oosiop_flush_fifo(struct oosiop_softc *);
77 void oosiop_clear_fifo(struct oosiop_softc *);
78 void oosiop_phasemismatch(struct oosiop_softc *);
79 void oosiop_setup_syncxfer(struct oosiop_softc *);
80 void oosiop_set_syncparam(struct oosiop_softc *, int, int, int);
81 void oosiop_minphys(struct buf *);
82 int oosiop_scsicmd(struct scsi_xfer *);
83 void oosiop_done(struct oosiop_softc *, struct oosiop_cb *);
84 void oosiop_timeout(void *);
85 void oosiop_reset(struct oosiop_softc *);
86 void oosiop_reset_bus(struct oosiop_softc *);
87 void oosiop_scriptintr(struct oosiop_softc *);
88 void oosiop_msgin(struct oosiop_softc *, struct oosiop_cb *);
89 void oosiop_setup(struct oosiop_softc *, struct oosiop_cb *);
90 void oosiop_poll(struct oosiop_softc *, struct oosiop_cb *);
91 void oosiop_processintr(struct oosiop_softc *, u_int8_t);
92
93
94 #define DATAIN_TRAP 0xdead0001
95 #define DATAOUT_TRAP 0xdead0002
96
97
98 static const struct {
99 u_int8_t tp;
100 u_int8_t scf;
101 } synctbl[] = {
102 {0, 1},
103 {1, 1},
104 {2, 1},
105 {3, 1},
106 {1, 2},
107 {4, 1},
108 {5, 1},
109 {6, 1},
110 {3, 2},
111 {7, 1},
112 {4, 2},
113 {5, 2},
114 {3, 3},
115 {6, 2},
116 {4, 3},
117 {7, 2},
118 {5, 3},
119 {6, 3},
120 {7, 3}
121 };
122 #define NSYNCTBL (sizeof(synctbl) / sizeof(synctbl[0]))
123
124 #define oosiop_period(sc, tp, scf) \
125 (((1000000000 / (sc)->sc_freq) * (tp) * (scf)) / 40)
126
127 struct cfdriver oosiop_cd = {
128 NULL, "oosiop", DV_DULL
129 };
130
131 struct scsi_adapter oosiop_adapter = {
132 oosiop_scsicmd,
133 oosiop_minphys,
134 NULL,
135 NULL
136 };
137
138 struct scsi_device oosiop_dev = {
139 NULL,
140 NULL,
141 NULL,
142 NULL
143 };
144
145 void
146 oosiop_attach(struct oosiop_softc *sc)
147 {
148 struct scsibus_attach_args saa;
149 bus_size_t scrsize;
150 bus_dma_segment_t seg;
151 struct oosiop_cb *cb;
152 int err, i, nseg;
153
154
155
156
157 scrsize = round_page(sizeof(oosiop_script));
158 err = bus_dmamem_alloc(sc->sc_dmat, scrsize, PAGE_SIZE, 0, &seg, 1,
159 &nseg, BUS_DMA_NOWAIT);
160 if (err) {
161 printf(": failed to allocate script memory, err=%d\n", err);
162 return;
163 }
164 err = bus_dmamem_map(sc->sc_dmat, &seg, nseg, scrsize,
165 (caddr_t *)&sc->sc_scr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
166 if (err) {
167 printf(": failed to map script memory, err=%d\n", err);
168 return;
169 }
170 err = bus_dmamap_create(sc->sc_dmat, scrsize, 1, scrsize, 0,
171 BUS_DMA_NOWAIT, &sc->sc_scrdma);
172 if (err) {
173 printf(": failed to create script map, err=%d\n", err);
174 return;
175 }
176 err = bus_dmamap_load_raw(sc->sc_dmat, sc->sc_scrdma,
177 &seg, nseg, scrsize, BUS_DMA_NOWAIT | BUS_DMA_WRITE);
178 if (err) {
179 printf(": failed to load script map, err=%d\n", err);
180 return;
181 }
182 bzero(sc->sc_scr, scrsize);
183 sc->sc_scrbase = sc->sc_scrdma->dm_segs[0].ds_addr;
184
185
186 TAILQ_INIT(&sc->sc_free_cb);
187 TAILQ_INIT(&sc->sc_cbq);
188 if (oosiop_alloc_cb(sc, OOSIOP_NCB) != 0)
189 return;
190
191
192 cb = TAILQ_FIRST(&sc->sc_free_cb);
193 sc->sc_reselbuf = cb->xferdma->dm_segs[0].ds_addr +
194 offsetof(struct oosiop_xfer, msgin[0]);
195
196 for (i = 0; i < OOSIOP_NTGT; i++) {
197 sc->sc_tgt[i].nexus = NULL;
198 sc->sc_tgt[i].flags = 0;
199 }
200
201
202 if (sc->sc_freq <= 25000000) {
203 sc->sc_ccf = 10;
204 sc->sc_dcntl = OOSIOP_DCNTL_CF_1;
205 } else if (sc->sc_freq <= 37500000) {
206 sc->sc_ccf = 15;
207 sc->sc_dcntl = OOSIOP_DCNTL_CF_1_5;
208 } else if (sc->sc_freq <= 50000000) {
209 sc->sc_ccf = 20;
210 sc->sc_dcntl = OOSIOP_DCNTL_CF_2;
211 } else {
212 sc->sc_ccf = 30;
213 sc->sc_dcntl = OOSIOP_DCNTL_CF_3;
214 }
215
216 if (sc->sc_chip == OOSIOP_700)
217 sc->sc_minperiod = oosiop_period(sc, 4, sc->sc_ccf);
218 else
219 sc->sc_minperiod = oosiop_period(sc, 4, 10);
220
221 if (sc->sc_minperiod < 25)
222 sc->sc_minperiod = 25;
223
224 printf(": NCR53C700%s rev %d, %dMHz, SCSI ID %d\n",
225 sc->sc_chip == OOSIOP_700_66 ? "-66" : "",
226 oosiop_read_1(sc, OOSIOP_CTEST7) >> 4,
227 sc->sc_freq / 1000000, sc->sc_id);
228
229
230
231 oosiop_reset(sc);
232 oosiop_reset_bus(sc);
233
234
235
236
237 oosiop_load_script(sc);
238 sc->sc_active = 0;
239 oosiop_write_4(sc, OOSIOP_DSP, sc->sc_scrbase + Ent_wait_reselect);
240
241
242
243
244 sc->sc_link.adapter = &oosiop_adapter;
245 sc->sc_link.adapter_softc = sc;
246 sc->sc_link.device = &oosiop_dev;
247 sc->sc_link.openings = 1;
248 sc->sc_link.adapter_buswidth = OOSIOP_NTGT;
249 sc->sc_link.adapter_target = sc->sc_id;
250 sc->sc_link.quirks = ADEV_NODOORLOCK;
251
252 bzero(&saa, sizeof(saa));
253 saa.saa_sc_link = &sc->sc_link;
254
255
256
257
258 config_found(&sc->sc_dev, &saa, scsiprint);
259 }
260
261 int
262 oosiop_alloc_cb(struct oosiop_softc *sc, int ncb)
263 {
264 struct oosiop_cb *cb;
265 struct oosiop_xfer *xfer;
266 bus_size_t xfersize;
267 bus_dma_segment_t seg;
268 int i, s, err, nseg;
269
270
271
272
273 cb = malloc(sizeof(struct oosiop_cb) * ncb, M_DEVBUF, M_NOWAIT);
274 if (cb == NULL) {
275 printf(": failed to allocate cb memory\n");
276 return (ENOMEM);
277 }
278 bzero(cb, sizeof(struct oosiop_cb) * ncb);
279
280
281
282
283 xfersize = sizeof(struct oosiop_xfer) * ncb;
284 err = bus_dmamem_alloc(sc->sc_dmat, xfersize, PAGE_SIZE, 0, &seg, 1,
285 &nseg, BUS_DMA_NOWAIT);
286 if (err) {
287 printf(": failed to allocate xfer block memory, err=%d\n", err);
288 return (err);
289 }
290 err = bus_dmamem_map(sc->sc_dmat, &seg, nseg, xfersize,
291 (caddr_t *)(void *)&xfer, BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
292 if (err) {
293 printf(": failed to map xfer block memory, err=%d\n", err);
294 return (err);
295 }
296
297
298 for (i = 0; i < ncb; i++) {
299 err = bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, 1, PAGE_SIZE,
300 0, BUS_DMA_NOWAIT, &cb->cmddma);
301 if (err) {
302 printf(": failed to create cmddma map, err=%d\n", err);
303 return (err);
304 }
305
306 err = bus_dmamap_create(sc->sc_dmat, OOSIOP_MAX_XFER,
307 OOSIOP_NSG, OOSIOP_DBC_MAX, 0, BUS_DMA_NOWAIT,
308 &cb->datadma);
309 if (err) {
310 printf(": failed to create datadma map, err=%d\n", err);
311 return (err);
312 }
313
314 err = bus_dmamap_create(sc->sc_dmat,
315 sizeof(struct oosiop_xfer), 1, sizeof(struct oosiop_xfer),
316 0, BUS_DMA_NOWAIT, &cb->xferdma);
317 if (err) {
318 printf(": failed to create xfer block map, err=%d\n",
319 err);
320 return (err);
321 }
322 err = bus_dmamap_load(sc->sc_dmat, cb->xferdma, xfer,
323 sizeof(struct oosiop_xfer), NULL, BUS_DMA_NOWAIT);
324 if (err) {
325 printf(": failed to load xfer block, err=%d\n", err);
326 return (err);
327 }
328
329 cb->xfer = xfer;
330
331 s = splbio();
332 TAILQ_INSERT_TAIL(&sc->sc_free_cb, cb, chain);
333 splx(s);
334
335 cb++;
336 xfer++;
337 }
338
339 return (0);
340 }
341
342 static __inline void
343 oosiop_relocate_io(struct oosiop_softc *sc, bus_addr_t addr)
344 {
345 u_int32_t dcmd;
346 int32_t dsps;
347
348 dcmd = letoh32(sc->sc_scr[addr / 4 + 0]);
349 dsps = letoh32(sc->sc_scr[addr / 4 + 1]);
350
351
352 if (dcmd & 0x04000000) {
353 dcmd &= ~0x04000000;
354 #if 0
355
356
357
358
359 dsps <<= 8;
360 dsps >>= 8;
361 #endif
362 sc->sc_scr[addr / 4 + 0] = htole32(dcmd);
363 dsps += addr + 8;
364 }
365
366 sc->sc_scr[addr / 4 + 1] = htole32(dsps + sc->sc_scrbase);
367 }
368
369 static __inline void
370 oosiop_relocate_tc(struct oosiop_softc *sc, bus_addr_t addr)
371 {
372 u_int32_t dcmd;
373 int32_t dsps;
374
375 dcmd = letoh32(sc->sc_scr[addr / 4 + 0]);
376 dsps = letoh32(sc->sc_scr[addr / 4 + 1]);
377
378
379 if (dcmd & 0x00800000) {
380 dcmd &= ~0x00800000;
381 sc->sc_scr[addr / 4] = htole32(dcmd);
382 #if 0
383
384
385
386
387 dsps <<= 8;
388 dsps >>= 8;
389 #endif
390 dsps += addr + 8;
391 }
392
393 sc->sc_scr[addr / 4 + 1] = htole32(dsps + sc->sc_scrbase);
394 }
395
396 static __inline void
397 oosiop_fixup_select(struct oosiop_softc *sc, bus_addr_t addr, int id)
398 {
399 u_int32_t dcmd;
400
401 dcmd = letoh32(sc->sc_scr[addr / 4]);
402 dcmd &= 0xff00ffff;
403 dcmd |= 0x00010000 << id;
404 sc->sc_scr[addr / 4] = htole32(dcmd);
405 }
406
407 static __inline void
408 oosiop_fixup_jump(struct oosiop_softc *sc, bus_addr_t addr, bus_addr_t dst)
409 {
410
411 sc->sc_scr[addr / 4 + 1] = htole32(dst);
412 }
413
414 static __inline void
415 oosiop_fixup_move(struct oosiop_softc *sc, bus_addr_t addr, bus_size_t dbc,
416 bus_addr_t dsps)
417 {
418 u_int32_t dcmd;
419
420 dcmd = letoh32(sc->sc_scr[addr / 4]);
421 dcmd &= 0xff000000;
422 dcmd |= dbc & 0x00ffffff;
423 sc->sc_scr[addr / 4 + 0] = htole32(dcmd);
424 sc->sc_scr[addr / 4 + 1] = htole32(dsps);
425 }
426
427 void
428 oosiop_load_script(struct oosiop_softc *sc)
429 {
430 int i;
431
432
433 for (i = 0; i < sizeof(oosiop_script) / sizeof(oosiop_script[0]); i++)
434 sc->sc_scr[i] = htole32(oosiop_script[i]);
435
436
437 for (i = 0; i < (sizeof(oosiop_script) / 8); i++) {
438 switch (oosiop_script[i * 2] >> 27) {
439 case 0x08:
440 case 0x0a:
441 oosiop_relocate_io(sc, i * 8);
442 break;
443 case 0x10:
444 case 0x11:
445 oosiop_relocate_tc(sc, i * 8);
446 break;
447 }
448 }
449
450 oosiop_fixup_move(sc, Ent_p_resel_msgin_move, 1, sc->sc_reselbuf);
451 OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_PREWRITE);
452 }
453
454 void
455 oosiop_setup_sgdma(struct oosiop_softc *sc, struct oosiop_cb *cb)
456 {
457 struct oosiop_xfer *xfer = cb->xfer;
458 struct scsi_xfer *xs = cb->xs;
459 int i, n, off;
460
461 OOSIOP_XFERSCR_SYNC(sc, cb,
462 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
463
464 off = cb->curdp;
465
466 if (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
467
468 for (i = 0; i < cb->datadma->dm_nsegs; i++) {
469 if (off < cb->datadma->dm_segs[i].ds_len)
470 break;
471 off -= cb->datadma->dm_segs[i].ds_len;
472 }
473
474
475 if (xs->flags & SCSI_DATA_IN) {
476 n = 0;
477 while (i < cb->datadma->dm_nsegs) {
478 xfer->datain_scr[n * 2 + 0] =
479 htole32(0x09000000 |
480 (cb->datadma->dm_segs[i].ds_len - off));
481 xfer->datain_scr[n * 2 + 1] =
482 htole32(cb->datadma->dm_segs[i].ds_addr +
483 off);
484 n++;
485 i++;
486 off = 0;
487 }
488 xfer->datain_scr[n * 2 + 0] = htole32(0x80080000);
489 xfer->datain_scr[n * 2 + 1] =
490 htole32(sc->sc_scrbase + Ent_phasedispatch);
491 }
492 if (xs->flags & SCSI_DATA_OUT) {
493 n = 0;
494 while (i < cb->datadma->dm_nsegs) {
495 xfer->dataout_scr[n * 2 + 0] =
496 htole32(0x08000000 |
497 (cb->datadma->dm_segs[i].ds_len - off));
498 xfer->dataout_scr[n * 2 + 1] =
499 htole32(cb->datadma->dm_segs[i].ds_addr +
500 off);
501 n++;
502 i++;
503 off = 0;
504 }
505 xfer->dataout_scr[n * 2 + 0] = htole32(0x80080000);
506 xfer->dataout_scr[n * 2 + 1] =
507 htole32(sc->sc_scrbase + Ent_phasedispatch);
508 }
509 }
510 if ((xs->flags & SCSI_DATA_IN) == 0) {
511 xfer->datain_scr[0] = htole32(0x98080000);
512 xfer->datain_scr[1] = htole32(DATAIN_TRAP);
513 }
514 if ((xs->flags & SCSI_DATA_OUT) == 0) {
515 xfer->dataout_scr[0] = htole32(0x98080000);
516 xfer->dataout_scr[1] = htole32(DATAOUT_TRAP);
517 }
518 OOSIOP_XFERSCR_SYNC(sc, cb,
519 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
520 }
521
522
523
524
525 void
526 oosiop_setup_dma(struct oosiop_softc *sc)
527 {
528 struct oosiop_cb *cb;
529 bus_addr_t xferbase;
530
531 cb = sc->sc_curcb;
532 xferbase = cb->xferdma->dm_segs[0].ds_addr;
533
534 OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_POSTWRITE);
535
536 oosiop_fixup_select(sc, Ent_p_select, cb->id);
537 oosiop_fixup_jump(sc, Ent_p_datain_jump, xferbase +
538 offsetof(struct oosiop_xfer, datain_scr[0]));
539 oosiop_fixup_jump(sc, Ent_p_dataout_jump, xferbase +
540 offsetof(struct oosiop_xfer, dataout_scr[0]));
541 oosiop_fixup_move(sc, Ent_p_msgin_move, 1, xferbase +
542 offsetof(struct oosiop_xfer, msgin[0]));
543 oosiop_fixup_move(sc, Ent_p_extmsglen_move, 1, xferbase +
544 offsetof(struct oosiop_xfer, msgin[1]));
545 oosiop_fixup_move(sc, Ent_p_msgout_move, cb->msgoutlen, xferbase +
546 offsetof(struct oosiop_xfer, msgout[0]));
547 oosiop_fixup_move(sc, Ent_p_status_move, 1, xferbase +
548 offsetof(struct oosiop_xfer, status));
549 oosiop_fixup_move(sc, Ent_p_cmdout_move, cb->cmdlen,
550 cb->cmddma->dm_segs[0].ds_addr);
551
552 OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_PREWRITE);
553 }
554
555 void
556 oosiop_flush_fifo(struct oosiop_softc *sc)
557 {
558
559 oosiop_write_1(sc, OOSIOP_DFIFO, oosiop_read_1(sc, OOSIOP_DFIFO) |
560 OOSIOP_DFIFO_FLF);
561 while ((oosiop_read_1(sc, OOSIOP_CTEST1) & OOSIOP_CTEST1_FMT) !=
562 OOSIOP_CTEST1_FMT)
563 ;
564 oosiop_write_1(sc, OOSIOP_DFIFO, oosiop_read_1(sc, OOSIOP_DFIFO) &
565 ~OOSIOP_DFIFO_FLF);
566 }
567
568 void
569 oosiop_clear_fifo(struct oosiop_softc *sc)
570 {
571
572 oosiop_write_1(sc, OOSIOP_DFIFO, oosiop_read_1(sc, OOSIOP_DFIFO) |
573 OOSIOP_DFIFO_CLF);
574 while ((oosiop_read_1(sc, OOSIOP_CTEST1) & OOSIOP_CTEST1_FMT) !=
575 OOSIOP_CTEST1_FMT)
576 ;
577 oosiop_write_1(sc, OOSIOP_DFIFO, oosiop_read_1(sc, OOSIOP_DFIFO) &
578 ~OOSIOP_DFIFO_CLF);
579 }
580
581 void
582 oosiop_phasemismatch(struct oosiop_softc *sc)
583 {
584 struct oosiop_cb *cb;
585 u_int32_t dsp, dbc, n, i, len;
586 u_int8_t dfifo, sstat1;
587
588 cb = sc->sc_curcb;
589 if (cb == NULL)
590 return;
591
592 dsp = oosiop_read_4(sc, OOSIOP_DSP);
593 dbc = oosiop_read_4(sc, OOSIOP_DBC) & OOSIOP_DBC_MAX;
594 len = 0;
595
596 n = dsp - cb->xferdma->dm_segs[0].ds_addr - 8;
597 if (n >= offsetof(struct oosiop_xfer, datain_scr[0]) &&
598 n < offsetof(struct oosiop_xfer, datain_scr[OOSIOP_NSG * 2])) {
599 n -= offsetof(struct oosiop_xfer, datain_scr[0]);
600 n >>= 3;
601 OOSIOP_DINSCR_SYNC(sc, cb,
602 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
603 for (i = 0; i <= n; i++)
604 len += letoh32(cb->xfer->datain_scr[i * 2]) &
605 0x00ffffff;
606 OOSIOP_DINSCR_SYNC(sc, cb,
607 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
608
609 } else if (n >= offsetof(struct oosiop_xfer, dataout_scr[0]) &&
610 n < offsetof(struct oosiop_xfer, dataout_scr[OOSIOP_NSG * 2])) {
611 n -= offsetof(struct oosiop_xfer, dataout_scr[0]);
612 n >>= 3;
613 OOSIOP_DOUTSCR_SYNC(sc, cb,
614 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
615 for (i = 0; i <= n; i++)
616 len += letoh32(cb->xfer->dataout_scr[i * 2]) &
617 0x00ffffff;
618 OOSIOP_DOUTSCR_SYNC(sc, cb,
619 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
620
621 dfifo = oosiop_read_1(sc, OOSIOP_DFIFO);
622 dbc += ((dfifo & OOSIOP_DFIFO_BO) - (dbc & OOSIOP_DFIFO_BO)) &
623 OOSIOP_DFIFO_BO;
624
625 sstat1 = oosiop_read_1(sc, OOSIOP_SSTAT1);
626 if (sstat1 & OOSIOP_SSTAT1_OLF)
627 dbc++;
628 if ((sc->sc_tgt[cb->id].sxfer != 0) &&
629 (sstat1 & OOSIOP_SSTAT1_ORF) != 0)
630 dbc++;
631
632 oosiop_clear_fifo(sc);
633 } else {
634 printf("%s: phase mismatch addr=%08x\n", sc->sc_dev.dv_xname,
635 oosiop_read_4(sc, OOSIOP_DSP) - 8);
636 oosiop_clear_fifo(sc);
637 return;
638 }
639
640 len -= dbc;
641 if (len) {
642 cb->curdp += len;
643 oosiop_setup_sgdma(sc, cb);
644 }
645 }
646
647 void
648 oosiop_setup_syncxfer(struct oosiop_softc *sc)
649 {
650 int id;
651
652 id = sc->sc_curcb->id;
653 if (sc->sc_chip != OOSIOP_700)
654 oosiop_write_1(sc, OOSIOP_SBCL, sc->sc_tgt[id].scf);
655
656 oosiop_write_1(sc, OOSIOP_SXFER, sc->sc_tgt[id].sxfer);
657 }
658
659 void
660 oosiop_set_syncparam(struct oosiop_softc *sc, int id, int period, int offset)
661 {
662 int i, p;
663
664 printf("%s: target %d now using 8 bit ", sc->sc_dev.dv_xname, id);
665
666 if (offset == 0) {
667
668 sc->sc_tgt[id].scf = 0;
669 sc->sc_tgt[id].sxfer = 0;
670 printf("asynchronous");
671 } else {
672
673 if (sc->sc_chip == OOSIOP_700) {
674 for (i = 4; i < 12; i++) {
675 p = oosiop_period(sc, i, sc->sc_ccf);
676 if (p >= period)
677 break;
678 }
679 if (i == 12) {
680 printf("%s: target %d period too large\n",
681 sc->sc_dev.dv_xname, id);
682 i = 11;
683 }
684 sc->sc_tgt[id].scf = 0;
685 sc->sc_tgt[id].sxfer = ((i - 4) << 4) | offset;
686 } else {
687 for (i = 0; i < NSYNCTBL; i++) {
688 p = oosiop_period(sc, synctbl[i].tp + 4,
689 (synctbl[i].scf + 1) * 5);
690 if (p >= period)
691 break;
692 }
693 if (i == NSYNCTBL) {
694 printf("%s: target %d period too large\n",
695 sc->sc_dev.dv_xname, id);
696 i = NSYNCTBL - 1;
697 }
698 sc->sc_tgt[id].scf = synctbl[i].scf;
699 sc->sc_tgt[id].sxfer = (synctbl[i].tp << 4) | offset;
700 }
701
702 printf(" synchronous");
703 }
704 printf(" xfers\n");
705 }
706
707 void
708 oosiop_minphys(struct buf *bp)
709 {
710
711 if (bp->b_bcount > OOSIOP_MAX_XFER)
712 bp->b_bcount = OOSIOP_MAX_XFER;
713 minphys(bp);
714 }
715
716 int
717 oosiop_scsicmd(struct scsi_xfer *xs)
718 {
719 struct oosiop_softc *sc;
720 struct oosiop_cb *cb;
721 struct oosiop_xfer *xfer;
722 int s, err;
723
724 sc = (struct oosiop_softc *)xs->sc_link->adapter_softc;
725
726 s = splbio();
727 cb = TAILQ_FIRST(&sc->sc_free_cb);
728 TAILQ_REMOVE(&sc->sc_free_cb, cb, chain);
729 splx(s);
730
731 cb->xs = xs;
732 cb->xsflags = xs->flags;
733 cb->cmdlen = xs->cmdlen;
734 cb->datalen = 0;
735 cb->flags = 0;
736 cb->id = xs->sc_link->target;
737 cb->lun = xs->sc_link->lun;
738 xfer = cb->xfer;
739
740
741 err = bus_dmamap_load(sc->sc_dmat, cb->cmddma, xs->cmd,
742 xs->cmdlen, NULL, ((xs->flags & SCSI_NOSLEEP) ?
743 BUS_DMA_NOWAIT : BUS_DMA_WAITOK) |
744 BUS_DMA_STREAMING | BUS_DMA_WRITE);
745 if (err) {
746 printf("%s: unable to load cmd DMA map: %d",
747 sc->sc_dev.dv_xname, err);
748 xs->error = XS_DRIVER_STUFFUP;
749 scsi_done(xs);
750 TAILQ_INSERT_TAIL(&sc->sc_free_cb, cb, chain);
751 return (COMPLETE);
752 }
753 bus_dmamap_sync(sc->sc_dmat, cb->cmddma, 0, xs->cmdlen,
754 BUS_DMASYNC_PREWRITE);
755
756
757 if (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
758 cb->datalen = xs->datalen;
759 err = bus_dmamap_load(sc->sc_dmat, cb->datadma,
760 xs->data, xs->datalen, NULL,
761 ((xs->flags & SCSI_NOSLEEP) ?
762 BUS_DMA_NOWAIT : BUS_DMA_WAITOK) |
763 BUS_DMA_STREAMING |
764 ((xs->flags & SCSI_DATA_IN) ? BUS_DMA_READ :
765 BUS_DMA_WRITE));
766 if (err) {
767 printf("%s: unable to load data DMA map: %d",
768 sc->sc_dev.dv_xname, err);
769 xs->error = XS_DRIVER_STUFFUP;
770 bus_dmamap_unload(sc->sc_dmat, cb->cmddma);
771 scsi_done(xs);
772 TAILQ_INSERT_TAIL(&sc->sc_free_cb, cb, chain);
773 return (COMPLETE);
774 }
775 bus_dmamap_sync(sc->sc_dmat, cb->datadma,
776 0, xs->datalen,
777 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
778 }
779
780 xfer->status = SCSI_OOSIOP_NOSTATUS;
781
782 oosiop_setup(sc, cb);
783
784 s = splbio();
785
786
787
788
789
790 timeout_set(&xs->stimeout, oosiop_timeout, cb);
791
792 TAILQ_INSERT_TAIL(&sc->sc_cbq, cb, chain);
793
794 if (!sc->sc_active) {
795
796 oosiop_write_1(sc, OOSIOP_ISTAT, OOSIOP_ISTAT_ABRT);
797 }
798 if (xs->flags & SCSI_POLL)
799 oosiop_poll(sc, cb);
800 else {
801
802 timeout_add(&xs->stimeout, (xs->timeout / 1000) * hz);
803 }
804
805 splx(s);
806
807 if ((xs->flags & ITSDONE) == 0)
808 return (SUCCESSFULLY_QUEUED);
809 else
810 return (COMPLETE);
811 }
812
813 void
814 oosiop_poll(struct oosiop_softc *sc, struct oosiop_cb *cb)
815 {
816 struct scsi_xfer *xs = cb->xs;
817 int i, s, to;
818 u_int8_t istat;
819
820 s = splbio();
821 to = xs->timeout / 1000;
822 for (;;) {
823 i = 1000;
824 while (((istat = oosiop_read_1(sc, OOSIOP_ISTAT)) &
825 (OOSIOP_ISTAT_SIP | OOSIOP_ISTAT_DIP)) == 0) {
826 if (i <= 0) {
827 i = 1000;
828 to--;
829 if (to <= 0) {
830 oosiop_reset(sc);
831 splx(s);
832 return;
833 }
834 }
835 delay(1000);
836 i--;
837 }
838 oosiop_processintr(sc, istat);
839
840 if (xs->flags & ITSDONE)
841 break;
842 }
843
844 splx(s);
845 }
846
847 void
848 oosiop_setup(struct oosiop_softc *sc, struct oosiop_cb *cb)
849 {
850 struct oosiop_xfer *xfer = cb->xfer;
851
852 cb->curdp = 0;
853 cb->savedp = 0;
854
855 oosiop_setup_sgdma(sc, cb);
856
857
858 OOSIOP_XFERMSG_SYNC(sc, cb,
859 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
860 xfer->msgout[0] = MSG_IDENTIFY(cb->lun,
861 (cb->xs->cmd->opcode != REQUEST_SENSE));
862 cb->msgoutlen = 1;
863
864 if (sc->sc_tgt[cb->id].flags & TGTF_SYNCNEG) {
865
866 xfer->msgout[1] = MSG_EXTENDED;
867 xfer->msgout[2] = MSG_EXT_SDTR_LEN;
868 xfer->msgout[3] = MSG_EXT_SDTR;
869 xfer->msgout[4] = sc->sc_minperiod;
870 xfer->msgout[5] = OOSIOP_MAX_OFFSET;
871 cb->msgoutlen = 6;
872 sc->sc_tgt[cb->id].flags &= ~TGTF_SYNCNEG;
873 sc->sc_tgt[cb->id].flags |= TGTF_WAITSDTR;
874 }
875
876 OOSIOP_XFERMSG_SYNC(sc, cb,
877 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
878 }
879
880 void
881 oosiop_done(struct oosiop_softc *sc, struct oosiop_cb *cb)
882 {
883 struct scsi_xfer *xs;
884 struct scsi_link *periph;
885 int autosense;
886
887 xs = cb->xs;
888 periph = xs->sc_link;
889
890
891
892
893
894
895 autosense = cb->flags & CBF_AUTOSENSE;
896 cb->flags &= ~CBF_AUTOSENSE;
897
898 bus_dmamap_sync(sc->sc_dmat, cb->cmddma, 0, cb->cmdlen,
899 BUS_DMASYNC_POSTWRITE);
900 bus_dmamap_unload(sc->sc_dmat, cb->cmddma);
901
902 if (cb->xsflags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
903 bus_dmamap_sync(sc->sc_dmat, cb->datadma, 0, cb->datalen,
904 (cb->xsflags & SCSI_DATA_IN) ?
905 BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
906 bus_dmamap_unload(sc->sc_dmat, cb->datadma);
907 }
908
909 timeout_del(&xs->stimeout);
910
911 xs->status = cb->xfer->status;
912
913 if (cb->flags & CBF_SELTOUT)
914 xs->error = XS_SELTIMEOUT;
915 else if (cb->flags & CBF_TIMEOUT)
916 xs->error = XS_TIMEOUT;
917 else switch (xs->status) {
918 case SCSI_OK:
919 if (autosense == 0)
920 xs->error = XS_NOERROR;
921 else
922 xs->error = XS_SENSE;
923 break;
924
925 case SCSI_BUSY:
926 xs->error = XS_BUSY;
927 break;
928 case SCSI_CHECK:
929 #ifdef notyet
930 if (autosense == 0)
931 cb->flags |= CBF_AUTOSENSE;
932 else
933 #endif
934 xs->error = XS_DRIVER_STUFFUP;
935 break;
936 case SCSI_OOSIOP_NOSTATUS:
937
938 xs->error = XS_SELTIMEOUT;
939 break;
940
941 default:
942 xs->error = XS_RESET;
943 break;
944 }
945
946 if ((cb->flags & CBF_AUTOSENSE) == 0) {
947
948 FREE:
949 xs->resid = 0;
950 xs->flags |= ITSDONE;
951 scsi_done(xs);
952 TAILQ_INSERT_TAIL(&sc->sc_free_cb, cb, chain);
953
954 if (cb == sc->sc_curcb)
955 sc->sc_curcb = NULL;
956 if (cb == sc->sc_lastcb)
957 sc->sc_lastcb = NULL;
958 sc->sc_tgt[cb->id].nexus = NULL;
959 } else {
960
961 struct scsi_sense *cmd = (struct scsi_sense *)xs->cmd;
962 int err;
963
964 bzero(cmd, sizeof(*cmd));
965 cmd->opcode = REQUEST_SENSE;
966 cmd->byte2 = xs->sc_link->lun << 5;
967 cb->cmdlen = cmd->length = sizeof(xs->sense);
968
969 cb->xsflags &= SCSI_POLL | SCSI_NOSLEEP;
970 cb->xsflags |= SCSI_DATA_IN;
971 cb->datalen = sizeof xs->sense;
972
973
974 err = bus_dmamap_load(sc->sc_dmat, cb->cmddma, cmd,
975 cb->cmdlen, NULL,
976 BUS_DMA_NOWAIT | BUS_DMA_STREAMING | BUS_DMA_WRITE);
977 if (err) {
978 printf("%s: unable to load REQUEST_SENSE cmd DMA map: %d",
979 sc->sc_dev.dv_xname, err);
980 xs->error = XS_DRIVER_STUFFUP;
981 goto FREE;
982 }
983 bus_dmamap_sync(sc->sc_dmat, cb->cmddma, 0, cb->cmdlen,
984 BUS_DMASYNC_PREWRITE);
985
986
987 err = bus_dmamap_load(sc->sc_dmat, cb->datadma,
988 &xs->sense, sizeof(xs->sense), NULL,
989 BUS_DMA_NOWAIT | BUS_DMA_STREAMING | BUS_DMA_READ);
990 if (err) {
991 printf("%s: unable to load REQUEST_SENSE data DMA map: %d",
992 sc->sc_dev.dv_xname, err);
993 xs->error = XS_DRIVER_STUFFUP;
994 bus_dmamap_unload(sc->sc_dmat, cb->cmddma);
995 goto FREE;
996 }
997 bus_dmamap_sync(sc->sc_dmat, cb->datadma,
998 0, sizeof(xs->sense), BUS_DMASYNC_PREREAD);
999
1000 oosiop_setup(sc, cb);
1001
1002 TAILQ_INSERT_HEAD(&sc->sc_cbq, cb, chain);
1003 if ((cb->xs->flags & SCSI_POLL) == 0) {
1004
1005 timeout_add(&xs->stimeout, (xs->timeout / 1000) * hz);
1006 }
1007 }
1008 }
1009
1010 void
1011 oosiop_timeout(void *arg)
1012 {
1013 struct oosiop_cb *cb = arg;
1014 struct scsi_xfer *xs = cb->xs;
1015 struct oosiop_softc *sc = xs->sc_link->adapter_softc;
1016 int s;
1017
1018 sc_print_addr(xs->sc_link);
1019 printf("command 0x%02x timeout on xs %p\n", xs->cmd->opcode, xs);
1020
1021 s = splbio();
1022
1023 oosiop_reset_bus(sc);
1024
1025 cb->flags |= CBF_TIMEOUT;
1026 oosiop_done(sc, cb);
1027
1028 splx(s);
1029 }
1030
1031 void
1032 oosiop_reset(struct oosiop_softc *sc)
1033 {
1034 int i, s;
1035
1036 s = splbio();
1037
1038
1039 oosiop_write_1(sc, OOSIOP_ISTAT, OOSIOP_ISTAT_ABRT);
1040 delay(100);
1041 oosiop_write_1(sc, OOSIOP_ISTAT, 0);
1042
1043
1044 oosiop_write_1(sc, OOSIOP_DCNTL, sc->sc_dcntl | OOSIOP_DCNTL_RST);
1045 delay(100);
1046 oosiop_write_1(sc, OOSIOP_DCNTL, sc->sc_dcntl);
1047 delay(10000);
1048
1049
1050 oosiop_write_1(sc, OOSIOP_SCNTL0, OOSIOP_ARB_FULL | OOSIOP_SCNTL0_EPG);
1051 oosiop_write_1(sc, OOSIOP_SCNTL1, OOSIOP_SCNTL1_ESR);
1052 oosiop_write_1(sc, OOSIOP_DCNTL, sc->sc_dcntl);
1053 oosiop_write_1(sc, OOSIOP_DMODE, OOSIOP_DMODE_BL_8);
1054 oosiop_write_1(sc, OOSIOP_SCID, OOSIOP_SCID_VALUE(sc->sc_id));
1055 oosiop_write_1(sc, OOSIOP_DWT, 0xff);
1056 oosiop_write_1(sc, OOSIOP_CTEST7, 0);
1057 oosiop_write_1(sc, OOSIOP_SXFER, 0);
1058
1059
1060 (void)oosiop_read_1(sc, OOSIOP_SSTAT0);
1061 (void)oosiop_read_1(sc, OOSIOP_SSTAT1);
1062 (void)oosiop_read_1(sc, OOSIOP_DSTAT);
1063
1064
1065 oosiop_write_1(sc, OOSIOP_SIEN,
1066 OOSIOP_SIEN_M_A | OOSIOP_SIEN_STO | OOSIOP_SIEN_SGE |
1067 OOSIOP_SIEN_UDC | OOSIOP_SIEN_RST | OOSIOP_SIEN_PAR);
1068 oosiop_write_1(sc, OOSIOP_DIEN,
1069 OOSIOP_DIEN_ABRT | OOSIOP_DIEN_SSI | OOSIOP_DIEN_SIR |
1070 OOSIOP_DIEN_WTD | OOSIOP_DIEN_IID);
1071
1072
1073 for (i = 0; i < OOSIOP_NTGT; i++) {
1074 sc->sc_tgt[i].flags = 0;
1075 sc->sc_tgt[i].scf = 0;
1076 sc->sc_tgt[i].sxfer = 0;
1077 }
1078
1079 splx(s);
1080 }
1081
1082 void
1083 oosiop_reset_bus(struct oosiop_softc *sc)
1084 {
1085 int s, i;
1086
1087 s = splbio();
1088
1089
1090 oosiop_write_1(sc, OOSIOP_SCNTL1, OOSIOP_SCNTL1_RST);
1091 delay(25);
1092 oosiop_write_1(sc, OOSIOP_SCNTL1, 0);
1093
1094
1095 for (i = 0; i < OOSIOP_NTGT; i++) {
1096 if (sc->sc_tgt[i].nexus) {
1097 sc->sc_tgt[i].nexus->xfer->status =
1098 SCSI_OOSIOP_NOSTATUS;
1099 oosiop_done(sc, sc->sc_tgt[i].nexus);
1100 }
1101 }
1102
1103 sc->sc_curcb = NULL;
1104
1105 delay(250000);
1106
1107 splx(s);
1108 }
1109
1110
1111
1112
1113 int
1114 oosiop_intr(struct oosiop_softc *sc)
1115 {
1116 u_int8_t istat;
1117
1118 istat = oosiop_read_1(sc, OOSIOP_ISTAT);
1119
1120 if ((istat & (OOSIOP_ISTAT_SIP | OOSIOP_ISTAT_DIP)) == 0)
1121 return (0);
1122
1123 oosiop_processintr(sc, istat);
1124 return (1);
1125 }
1126
1127 void
1128 oosiop_processintr(struct oosiop_softc *sc, u_int8_t istat)
1129 {
1130 struct oosiop_cb *cb;
1131 u_int32_t dcmd;
1132 u_int8_t dstat, sstat0;
1133
1134 sc->sc_nextdsp = Ent_wait_reselect;
1135
1136
1137 if (istat & OOSIOP_ISTAT_DIP) {
1138 oosiop_write_1(sc, OOSIOP_ISTAT, 0);
1139
1140 dstat = oosiop_read_1(sc, OOSIOP_DSTAT);
1141
1142 if (dstat & OOSIOP_DSTAT_ABRT) {
1143 sc->sc_nextdsp = oosiop_read_4(sc, OOSIOP_DSP) -
1144 sc->sc_scrbase - 8;
1145
1146 if (sc->sc_nextdsp == Ent_p_resel_msgin_move &&
1147 (oosiop_read_1(sc, OOSIOP_SBCL) & OOSIOP_ACK)) {
1148 if ((dstat & OOSIOP_DSTAT_DFE) == 0)
1149 oosiop_flush_fifo(sc);
1150 sc->sc_nextdsp += 8;
1151 }
1152 }
1153
1154 if (dstat & OOSIOP_DSTAT_SSI) {
1155 sc->sc_nextdsp = oosiop_read_4(sc, OOSIOP_DSP) -
1156 sc->sc_scrbase;
1157 printf("%s: single step %08x\n", sc->sc_dev.dv_xname,
1158 sc->sc_nextdsp);
1159 }
1160
1161 if (dstat & OOSIOP_DSTAT_SIR) {
1162 if ((dstat & OOSIOP_DSTAT_DFE) == 0)
1163 oosiop_flush_fifo(sc);
1164 oosiop_scriptintr(sc);
1165 }
1166
1167 if (dstat & OOSIOP_DSTAT_WTD) {
1168 printf("%s: DMA time out\n", sc->sc_dev.dv_xname);
1169 oosiop_reset(sc);
1170 }
1171
1172 if (dstat & OOSIOP_DSTAT_IID) {
1173 dcmd = oosiop_read_4(sc, OOSIOP_DBC);
1174 if ((dcmd & 0xf8000000) == 0x48000000) {
1175 printf("%s: REQ asserted on WAIT DISCONNECT\n",
1176 sc->sc_dev.dv_xname);
1177 sc->sc_nextdsp = Ent_phasedispatch;
1178 } else {
1179 printf("%s: invalid SCRIPTS instruction "
1180 "addr=%08x dcmd=%08x dsps=%08x\n",
1181 sc->sc_dev.dv_xname,
1182 oosiop_read_4(sc, OOSIOP_DSP) - 8, dcmd,
1183 oosiop_read_4(sc, OOSIOP_DSPS));
1184 oosiop_reset(sc);
1185 OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_POSTWRITE);
1186 oosiop_load_script(sc);
1187 }
1188 }
1189
1190 if ((dstat & OOSIOP_DSTAT_DFE) == 0)
1191 oosiop_clear_fifo(sc);
1192 }
1193
1194
1195 if (istat & OOSIOP_ISTAT_SIP) {
1196 if (istat & OOSIOP_ISTAT_DIP)
1197 delay(1);
1198 sstat0 = oosiop_read_1(sc, OOSIOP_SSTAT0);
1199
1200 if (sstat0 & OOSIOP_SSTAT0_M_A) {
1201
1202 oosiop_phasemismatch(sc);
1203 sc->sc_nextdsp = Ent_phasedispatch;
1204 }
1205
1206 if (sstat0 & OOSIOP_SSTAT0_STO) {
1207 if (sc->sc_curcb) {
1208 sc->sc_curcb->flags |= CBF_SELTOUT;
1209 oosiop_done(sc, sc->sc_curcb);
1210 }
1211 }
1212
1213 if (sstat0 & OOSIOP_SSTAT0_SGE) {
1214 printf("%s: SCSI gross error\n", sc->sc_dev.dv_xname);
1215 oosiop_reset(sc);
1216 }
1217
1218 if (sstat0 & OOSIOP_SSTAT0_UDC) {
1219
1220 if (sc->sc_curcb) {
1221 printf("%s: unexpected disconnect\n",
1222 sc->sc_dev.dv_xname);
1223 oosiop_done(sc, sc->sc_curcb);
1224 }
1225 }
1226
1227 if (sstat0 & OOSIOP_SSTAT0_RST)
1228 oosiop_reset(sc);
1229
1230 if (sstat0 & OOSIOP_SSTAT0_PAR)
1231 printf("%s: parity error\n", sc->sc_dev.dv_xname);
1232 }
1233
1234
1235 if (sc->sc_nextdsp == Ent_wait_reselect && TAILQ_FIRST(&sc->sc_cbq)) {
1236 cb = sc->sc_curcb = TAILQ_FIRST(&sc->sc_cbq);
1237 TAILQ_REMOVE(&sc->sc_cbq, cb, chain);
1238 sc->sc_tgt[cb->id].nexus = cb;
1239
1240 oosiop_setup_dma(sc);
1241 oosiop_setup_syncxfer(sc);
1242 sc->sc_lastcb = cb;
1243 sc->sc_nextdsp = Ent_start_select;
1244
1245
1246 if ((cb->xs->flags & SCSI_POLL) == 0) {
1247
1248 timeout_add(&cb->xs->stimeout,
1249 (cb->xs->timeout / 1000) * hz);
1250 }
1251 }
1252
1253 sc->sc_active = (sc->sc_nextdsp != Ent_wait_reselect);
1254
1255
1256 oosiop_write_4(sc, OOSIOP_DSP, sc->sc_nextdsp + sc->sc_scrbase);
1257 }
1258
1259 void
1260 oosiop_scriptintr(struct oosiop_softc *sc)
1261 {
1262 struct oosiop_cb *cb;
1263 u_int32_t icode;
1264 u_int32_t dsp;
1265 int i;
1266 u_int8_t sfbr, resid, resmsg;
1267
1268 cb = sc->sc_curcb;
1269 icode = oosiop_read_4(sc, OOSIOP_DSPS);
1270
1271 switch (icode) {
1272 case A_int_done:
1273 if (cb)
1274 oosiop_done(sc, cb);
1275 break;
1276
1277 case A_int_msgin:
1278 if (cb)
1279 oosiop_msgin(sc, cb);
1280 break;
1281
1282 case A_int_extmsg:
1283
1284 sfbr = oosiop_read_1(sc, OOSIOP_SFBR);
1285 OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_POSTWRITE);
1286 oosiop_fixup_move(sc, Ent_p_extmsgin_move, sfbr,
1287 cb->xferdma->dm_segs[0].ds_addr +
1288 offsetof(struct oosiop_xfer, msgin[2]));
1289 OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_PREWRITE);
1290 sc->sc_nextdsp = Ent_rcv_extmsg;
1291 break;
1292
1293 case A_int_resel:
1294
1295 resid = oosiop_read_1(sc, OOSIOP_SFBR);
1296 for (i = 0; i < OOSIOP_NTGT; i++)
1297 if (resid & (1 << i))
1298 break;
1299 if (i == OOSIOP_NTGT) {
1300 printf("%s: missing reselection target id\n",
1301 sc->sc_dev.dv_xname);
1302 break;
1303 }
1304 sc->sc_resid = i;
1305 sc->sc_nextdsp = Ent_wait_resel_identify;
1306
1307 if (cb) {
1308
1309 sc->sc_tgt[cb->id].nexus = NULL;
1310 TAILQ_INSERT_HEAD(&sc->sc_cbq, cb, chain);
1311 sc->sc_curcb = NULL;
1312 }
1313
1314 break;
1315
1316 case A_int_res_id:
1317 cb = sc->sc_tgt[sc->sc_resid].nexus;
1318 resmsg = oosiop_read_1(sc, OOSIOP_SFBR);
1319 if (MSG_ISIDENTIFY(resmsg) && cb &&
1320 (resmsg & MSG_IDENTIFY_LUNMASK) == cb->lun) {
1321 sc->sc_curcb = cb;
1322 if (cb != sc->sc_lastcb) {
1323 oosiop_setup_dma(sc);
1324 oosiop_setup_syncxfer(sc);
1325 sc->sc_lastcb = cb;
1326 }
1327 if (cb->curdp != cb->savedp) {
1328 cb->curdp = cb->savedp;
1329 oosiop_setup_sgdma(sc, cb);
1330 }
1331 sc->sc_nextdsp = Ent_ack_msgin;
1332 } else {
1333
1334 oosiop_reset_bus(sc);
1335 }
1336 break;
1337
1338 case A_int_resfail:
1339
1340 break;
1341
1342 case A_int_disc:
1343
1344 sc->sc_curcb = NULL;
1345 break;
1346
1347 case A_int_err:
1348
1349 dsp = oosiop_read_4(sc, OOSIOP_DSP);
1350 printf("%s: script error at 0x%08x\n", sc->sc_dev.dv_xname,
1351 dsp - 8);
1352 sc->sc_curcb = NULL;
1353 break;
1354
1355 case DATAIN_TRAP:
1356 printf("%s: unexpected datain\n", sc->sc_dev.dv_xname);
1357
1358 break;
1359
1360 case DATAOUT_TRAP:
1361 printf("%s: unexpected dataout\n", sc->sc_dev.dv_xname);
1362
1363 break;
1364
1365 default:
1366 printf("%s: unknown intr code %08x\n", sc->sc_dev.dv_xname,
1367 icode);
1368 break;
1369 }
1370 }
1371
1372 void
1373 oosiop_msgin(struct oosiop_softc *sc, struct oosiop_cb *cb)
1374 {
1375 struct oosiop_xfer *xfer;
1376 int msgout;
1377
1378 xfer = cb->xfer;
1379 sc->sc_nextdsp = Ent_ack_msgin;
1380 msgout = 0;
1381
1382 OOSIOP_XFERMSG_SYNC(sc, cb,
1383 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1384
1385 switch (xfer->msgin[0]) {
1386 case MSG_EXTENDED:
1387 switch (xfer->msgin[2]) {
1388 case MSG_EXT_SDTR:
1389 if (sc->sc_tgt[cb->id].flags & TGTF_WAITSDTR) {
1390
1391 sc->sc_tgt[cb->id].flags &= ~TGTF_WAITSDTR;
1392 } else {
1393
1394 if (xfer->msgin[3] < sc->sc_minperiod)
1395 xfer->msgin[3] = sc->sc_minperiod;
1396 if (xfer->msgin[4] > OOSIOP_MAX_OFFSET)
1397 xfer->msgin[4] = OOSIOP_MAX_OFFSET;
1398 xfer->msgout[0] = MSG_EXTENDED;
1399 xfer->msgout[1] = MSG_EXT_SDTR_LEN;
1400 xfer->msgout[2] = MSG_EXT_SDTR;
1401 xfer->msgout[3] = xfer->msgin[3];
1402 xfer->msgout[4] = xfer->msgin[4];
1403 cb->msgoutlen = 5;
1404 msgout = 1;
1405 }
1406 oosiop_set_syncparam(sc, cb->id, (int)xfer->msgin[3],
1407 (int)xfer->msgin[4]);
1408 oosiop_setup_syncxfer(sc);
1409 break;
1410
1411 default:
1412
1413 xfer->msgout[0] = MSG_MESSAGE_REJECT;
1414 cb->msgoutlen = 1;
1415 msgout = 1;
1416 break;
1417 }
1418 break;
1419
1420 case MSG_SAVEDATAPOINTER:
1421 cb->savedp = cb->curdp;
1422 break;
1423
1424 case MSG_RESTOREPOINTERS:
1425 if (cb->curdp != cb->savedp) {
1426 cb->curdp = cb->savedp;
1427 oosiop_setup_sgdma(sc, cb);
1428 }
1429 break;
1430
1431 case MSG_MESSAGE_REJECT:
1432 if (sc->sc_tgt[cb->id].flags & TGTF_WAITSDTR) {
1433
1434 sc->sc_tgt[cb->id].flags &= ~TGTF_WAITSDTR;
1435 oosiop_set_syncparam(sc, cb->id, 0, 0);
1436 oosiop_setup_syncxfer(sc);
1437 }
1438 break;
1439
1440 default:
1441
1442 xfer->msgout[0] = MSG_MESSAGE_REJECT;
1443 cb->msgoutlen = 1;
1444 msgout = 1;
1445 }
1446
1447 OOSIOP_XFERMSG_SYNC(sc, cb,
1448 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1449
1450 if (msgout) {
1451 OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_POSTWRITE);
1452 oosiop_fixup_move(sc, Ent_p_msgout_move, cb->msgoutlen,
1453 cb->xferdma->dm_segs[0].ds_addr +
1454 offsetof(struct oosiop_xfer, msgout[0]));
1455 OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_PREWRITE);
1456 sc->sc_nextdsp = Ent_sendmsg;
1457 }
1458 }