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