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