sc_wrap.c revision 1.3 1 /* $NetBSD: sc_wrap.c,v 1.3 1998/06/01 19:31:05 tsubai Exp $ */
2
3 /*
4 This driver is slow! Need to rewrite.
5 */
6
7 #include <sys/types.h>
8 #include <sys/param.h>
9 #include <sys/systm.h>
10 #include <sys/kernel.h>
11 #include <sys/device.h>
12 #include <sys/proc.h>
13 #include <sys/buf.h>
14 #include <sys/malloc.h>
15
16 #include <dev/scsipi/scsi_all.h>
17 #include <dev/scsipi/scsipi_all.h>
18 #include <dev/scsipi/scsiconf.h>
19 #include <dev/scsipi/scsi_message.h>
20
21 #include <newsmips/dev/scsireg.h>
22 #include <newsmips/dev/scsic.h>
23 #include <newsmips/dev/dmac_0448.h>
24 #include <newsmips/dev/screg_1185.h>
25
26 #include <machine/locore.h>
27 #include <machine/adrsmap.h>
28 #include <machine/autoconf.h>
29 #include <machine/machConst.h>
30
31 extern int cold;
32
33 /* XXX shared data area with scsi_1185.c */
34 struct sc_data sc_data[8];
35
36 static int sc_disconnect = IDT_DISCON;
37
38 struct sc_scb {
39 TAILQ_ENTRY(sc_scb) chain;
40 struct scsipi_xfer *xs;
41 int flags;
42 };
43
44 struct sc_softc {
45 struct device sc_dev;
46 struct scsipi_link sc_link;
47
48 TAILQ_HEAD(scb_list, sc_scb) ready_list, free_list;
49 struct sc_scb sc_scb[3*8];
50
51 struct scsi scsi_xxx[8];
52 int inuse[8];
53 struct sc_map sc_map[8];
54 };
55
56
57 static int cxd1185_match __P((struct device *, struct cfdata *, void *));
58 static void cxd1185_attach __P((struct device *, struct device *, void *));
59
60 struct cfattach sc_ca = {
61 sizeof(struct sc_softc), cxd1185_match, cxd1185_attach
62 };
63
64 extern struct cfdriver sc_cd;
65
66 void cxd1185_init __P((struct sc_softc *));
67 static void free_scb __P((struct sc_softc *, struct sc_scb *, int));
68 static struct sc_scb *get_scb __P((struct sc_softc *, int));
69 static int sc_scsi_cmd __P((struct scsipi_xfer *));
70 static int sc_poll __P((int, int));
71 static void sc_sched __P((struct sc_softc *));
72 static void sc_go __P((int, struct scsi *, int));
73 void sc_done __P((struct scsi *));
74 int sc_intr __P((struct sc_softc *));
75 static void cxd1185_timeout __P((void *));
76
77 extern int sc_send __P((int, int, struct scsi *));
78 extern int scintr __P((void));
79 extern void scsi_hardreset __P((void));
80 extern int sc_busy __P((int));
81 extern vm_offset_t kvtophys __P((vm_offset_t));
82
83 struct scsipi_adapter cxd1185_switch = {
84 sc_scsi_cmd,
85 minphys,
86 NULL,
87 NULL
88 };
89
90 struct scsipi_device cxd1185_dev = {
91 NULL,
92 NULL,
93 NULL,
94 NULL
95 };
96
97 int
98 cxd1185_match(parent, cf, aux)
99 struct device *parent;
100 struct cfdata *cf;
101 void *aux;
102 {
103 struct confargs *ca = aux;
104
105 if (strcmp(ca->ca_name, "sc"))
106 return 0;
107
108 return 1;
109 }
110
111 void
112 cxd1185_attach(parent, self, aux)
113 struct device *parent, *self;
114 void *aux;
115 {
116 struct sc_softc *sc = (void *)self;
117 struct sc_scb *scb;
118 int i;
119 extern int scsi_1185AQ;
120
121 if (sc_idenr & 0x08)
122 scsi_1185AQ = 1;
123
124 sc->sc_link.scsipi_scsi.channel = SCSI_CHANNEL_ONLY_ONE;
125 sc->sc_link.adapter_softc = sc;
126 sc->sc_link.scsipi_scsi.adapter_target = 7;
127 sc->sc_link.adapter = &cxd1185_switch;
128 sc->sc_link.device = &cxd1185_dev;
129 sc->sc_link.openings = 2;
130 sc->sc_link.scsipi_scsi.max_target = 7;
131 sc->sc_link.type = BUS_SCSI;
132
133 TAILQ_INIT(&sc->ready_list);
134 TAILQ_INIT(&sc->free_list);
135
136 scb = sc->sc_scb;
137 for (i = 0; i < 24; i++) { /* XXX 24 */
138 TAILQ_INSERT_TAIL(&sc->free_list, scb, chain);
139 scb++;
140 }
141
142 cxd1185_init(sc);
143 DELAY(100000);
144
145 printf("\n");
146 config_found(&sc->sc_dev, &sc->sc_link, scsiprint);
147 }
148
149 void
150 cxd1185_init(sc)
151 struct sc_softc *sc;
152 {
153 int i;
154
155 for (i = 0; i < 8; i++)
156 sc->inuse[i] = 0;
157
158 scsi_hardreset();
159 }
160
161 void
162 free_scb(sc, scb, flags)
163 struct sc_softc *sc;
164 struct sc_scb *scb;
165 int flags;
166 {
167 int s;
168
169 s = splbio();
170
171 TAILQ_INSERT_HEAD(&sc->free_list, scb, chain);
172
173 /*
174 * If there were none, wake anybody waiting for one to come free,
175 * starting with queued entries.
176 */
177 if (scb->chain.tqe_next == 0)
178 wakeup(&sc->free_list);
179
180 splx(s);
181 }
182
183 struct sc_scb *
184 get_scb(sc, flags)
185 struct sc_softc *sc;
186 int flags;
187 {
188 int s;
189 struct sc_scb *scb;
190
191 s = splbio();
192
193 while ((scb = sc->free_list.tqh_first) == NULL &&
194 (flags & SCSI_NOSLEEP) == 0)
195 tsleep(&sc->free_list, PRIBIO, "sc_scb", 0);
196 if (scb) {
197 TAILQ_REMOVE(&sc->free_list, scb, chain);
198 }
199
200 splx(s);
201 return scb;
202 }
203
204 int
205 sc_scsi_cmd(xs)
206 struct scsipi_xfer *xs;
207 {
208 struct scsipi_link *sc_link = xs->sc_link;
209 struct sc_softc *sc = sc_link->adapter_softc;
210 struct sc_scb *scb;
211 int flags, s;
212 int intr;
213 struct sc_data *scdp;
214
215 flags = xs->flags;
216 if ((scb = get_scb(sc, flags)) == NULL)
217 return TRY_AGAIN_LATER;
218
219 scb->xs = xs;
220
221 s = splbio();
222
223 TAILQ_INSERT_TAIL(&sc->ready_list, scb, chain);
224 sc_sched(sc);
225 splx(s);
226
227 if ((flags & SCSI_POLL) == 0)
228 return SUCCESSFULLY_QUEUED;
229
230 intr = sc_link->scsipi_scsi.target;
231
232 if (sc_poll(intr, xs->timeout)) {
233 printf("sc: timeout (retry)\n");
234 if (sc_poll(intr, xs->timeout)) {
235 printf("sc: timeout\n");
236 return COMPLETE;
237 }
238 }
239
240 scdp = &sc_data[intr];
241
242 /* if (DATAIN_PHASE_FINISHED) */
243 MachFlushDCache((vm_offset_t)scdp->scd_scaddr, sizeof (struct scsi));
244 if (MACH_IS_USPACE(scdp->scd_vaddr))
245 panic("sc_scsi_cmd: user address is not supported");
246 else if (MACH_IS_CACHED(scdp->scd_vaddr))
247 MachFlushDCache(scdp->scd_vaddr, scdp->scd_count);
248 else if (MACH_IS_MAPPED(scdp->scd_vaddr))
249 MachFlushCache(); /* Flush all caches */
250
251 return COMPLETE;
252 }
253
254 /*
255 * Used when interrupt driven I/O isn't allowed, e.g. during boot.
256 */
257 int
258 sc_poll(intr, count)
259 int intr, count;
260 {
261 volatile u_char *int_stat = (void *)INTST1;
262 volatile u_char *int_clear = (void *)INTCLR1;
263
264 while (sc_busy(intr)) {
265 if (*int_stat & INTST1_DMA) {
266 *int_clear = INTST1_DMA;
267 if (dmac_gstat & CH_INT(CH_SCSI)) {
268 if (dmac_gstat & CH_MRQ(CH_SCSI)) {
269 DELAY(50);
270 if (dmac_gstat & CH_MRQ(CH_SCSI))
271 printf("dma_poll\n");
272 }
273 DELAY(10);
274 scintr();
275 }
276 }
277 DELAY(1000);
278 count--;
279 if (count <= 0)
280 return 1;
281 }
282 return 0;
283 }
284
285 void
286 sc_sched(sc)
287 struct sc_softc *sc;
288 {
289 struct scsipi_xfer *xs;
290 struct scsipi_link *sc_link;
291 struct scsi *sc_param;
292 int ie = 0;
293 int flags;
294 int chan, lun;
295 struct sc_scb *scb, *nextscb;
296
297 scb = sc->ready_list.tqh_first;
298 start:
299
300 if (scb == NULL)
301 return;
302
303 xs = scb->xs;
304 sc_link = xs->sc_link;
305 chan = sc_link->scsipi_scsi.target;
306 flags = xs->flags;
307
308 if (cold)
309 flags |= SCSI_POLL;
310
311 if (sc->inuse[chan]) {
312 scb = scb->chain.tqe_next;
313 goto start;
314 }
315 sc->inuse[chan] = 1;
316
317 if (flags & SCSI_RESET)
318 printf("SCSI RESET\n");
319
320 sc_param = &sc->scsi_xxx[chan];
321
322 bzero(sc_param, sizeof(struct scsi));
323 lun = sc_link->scsipi_scsi.lun;
324 sc_param->sc_xs = xs;
325 sc_param->sc_identify = MSG_IDENT | sc_disconnect | (lun & IDT_DRMASK);
326 sc_param->sc_bytesec = DEV_BSIZE;
327 sc_param->sc_lun = lun;
328
329 sc_param->sc_cpoint = xs->data;
330 sc_param->sc_ctrnscnt = xs->datalen;
331
332 bcopy(xs->cmd, &sc_param->sc_cdb, xs->cmdlen);
333
334 /* make va->pa mapping table for dma */
335 if (xs->datalen > 0) {
336 int pages, offset;
337 int i, pn;
338 u_int va;
339
340 bzero(&sc->sc_map[chan], sizeof(struct sc_map));
341
342 va = (u_int)xs->data;
343
344 offset = va & PGOFSET;
345 pages = (offset + xs->datalen + NBPG -1 ) >> PGSHIFT;
346 if (pages >= NSCMAP)
347 panic("sc_map: Too many pages");
348
349 for (i = 0; i < pages; i++) {
350 pn = kvtophys((vm_offset_t)va) >> PGSHIFT;
351 sc->sc_map[chan].mp_addr[i] = pn;
352 va += NBPG;
353 }
354
355 sc->sc_map[chan].mp_offset = offset;
356 sc->sc_map[chan].mp_pages = pages;
357 sc_param->sc_map = &sc->sc_map[chan];
358 }
359
360 if ((flags & SCSI_POLL) == 0)
361 ie = SCSI_INTEN;
362
363 timeout(cxd1185_timeout, scb, hz * 10);
364
365 sc_go(chan, sc_param, ie);
366
367 untimeout(cxd1185_timeout, scb);
368
369 nextscb = scb->chain.tqe_next;
370
371 TAILQ_REMOVE(&sc->ready_list, scb, chain);
372 free_scb(sc, scb, flags);
373
374 scb = nextscb;
375
376 goto start;
377 }
378
379
380 void
381 sc_go(chan, sc_param, ie)
382 int chan;
383 struct scsi *sc_param;
384 int ie;
385 {
386 register struct sc_data *scdp;
387
388 scdp = &sc_data[chan];
389
390 if (sc_param->sc_cpoint)
391 scdp->scd_vaddr = (vm_offset_t)sc_param->sc_cpoint;
392 else
393 scdp->scd_vaddr = (vm_offset_t)sc_param->sc_param;
394 scdp->scd_scaddr = sc_param;
395 scdp->scd_count = sc_param->sc_ctrnscnt;
396 sc_param->sc_cpoint = (u_char *)ipc_phys(scdp->scd_vaddr);
397
398 sc_send(chan, ie, sc_param);
399 }
400
401 /*static*/ void scop_rsense();
402
403 void
404 sc_done(sc_param)
405 struct scsi *sc_param;
406 {
407 struct scsipi_xfer *xs = sc_param->sc_xs;
408 struct scsipi_link *sc_link = xs->sc_link;
409 struct sc_softc *sc = sc_link->adapter_softc;
410
411 xs->flags |= ITSDONE;
412 xs->resid = 0;
413 xs->status = 0;
414
415 if (sc_param->sc_istatus != INST_EP) {
416 if (! cold)
417 printf("SC(i): [istatus=0x%x, tstatus=0x%x]\n",
418 sc_param->sc_istatus, sc_param->sc_tstatus);
419 xs->error = XS_DRIVER_STUFFUP;
420 }
421
422 switch (sc_param->sc_tstatus) {
423
424 case TGST_GOOD:
425 break;
426
427 case TGST_CC:
428 break; /* XXX */
429 #if 0
430 chan = sc_link->scsipi_scsi.target;
431 lun = sc_link->scsipi_scsi.lun;
432 scop_rsense(chan, sc_param, lun, SCSI_INTDIS, 18, 0);
433 if (sc_param->sc_tstatus != TGST_GOOD) {
434 printf("SC(t2): [istatus=0x%x, tstatus=0x%x]\n",
435 sc_param->sc_istatus, sc_param->sc_tstatus);
436 }
437 #endif
438
439 default:
440 printf("SC(t): [istatus=0x%x, tstatus=0x%x]\n",
441 sc_param->sc_istatus, sc_param->sc_tstatus);
442 break;
443 }
444
445 scsipi_done(xs);
446 sc->inuse[sc_link->scsipi_scsi.target] = 0;
447
448 sc_sched(sc);
449 }
450
451 int
452 sc_intr(sc)
453 struct sc_softc *sc;
454 {
455 return scintr();
456 }
457
458
459 /*
460 * SCOP_RSENSE request
461 */
462 void
463 scop_rsense(intr, sc_param, lun, ie, count, param)
464 register int intr;
465 register struct scsi *sc_param;
466 register int lun;
467 register int ie;
468 register int count;
469 register caddr_t param;
470 {
471 bzero(sc_param, sizeof(struct scsi));
472 sc_param->sc_identify = MSG_IDENT | sc_disconnect | (lun & IDT_DRMASK);
473 sc_param->sc_bytesec = DEV_BSIZE;
474 sc_param->sc_lun = lun;
475
476 sc_param->sc_cpoint = (u_char *)param;
477 sc_param->sc_ctrnscnt = count;
478
479 /* sc_cdb */
480 sc_param->sc_opcode = SCOP_RSENSE;
481 sc_param->sc_count = count;
482
483 sc_go(intr, sc_param, ie);
484 }
485
486 void
487 cxd1185_timeout(arg)
488 void *arg;
489 {
490 struct sc_scb *scb = arg;
491 struct scsipi_xfer *xs = scb->xs;
492 struct scsipi_link *sc_link = xs->sc_link;
493 int chan;
494
495 chan = sc_link->scsipi_scsi.target;
496
497 printf("sc: timeout ch=%d\n", chan);
498
499 /* XXX abort transfer and ... */
500 }
501