1 /* $NetBSD: sc_wrap.c,v 1.34 2023/12/20 15:29:05 thorpej Exp $ */
2
3 /*
4 * This driver is slow! Need to rewrite.
5 */
6
7 #include <sys/cdefs.h>
8 __KERNEL_RCSID(0, "$NetBSD: sc_wrap.c,v 1.34 2023/12/20 15:29:05 thorpej Exp $");
9
10 #include <sys/types.h>
11 #include <sys/param.h>
12 #include <sys/systm.h>
13 #include <sys/kernel.h>
14 #include <sys/device.h>
15 #include <sys/proc.h>
16 #include <sys/buf.h>
17
18 #include <uvm/uvm_extern.h>
19
20 #include <dev/scsipi/scsi_all.h>
21 #include <dev/scsipi/scsipi_all.h>
22 #include <dev/scsipi/scsiconf.h>
23 #include <dev/scsipi/scsi_message.h>
24
25 #include <newsmips/dev/hbvar.h>
26 #include <newsmips/dev/scsireg.h>
27 #include <newsmips/dev/dmac_0448.h>
28 #include <newsmips/dev/screg_1185.h>
29
30 #include <machine/adrsmap.h>
31 #include <machine/autoconf.h>
32 #include <machine/machConst.h>
33
34 #include <mips/cache.h>
35
36 static int cxd1185_match(device_t, cfdata_t, void *);
37 static void cxd1185_attach(device_t, device_t, void *);
38
39 CFATTACH_DECL_NEW(sc, sizeof(struct sc_softc),
40 cxd1185_match, cxd1185_attach, NULL, NULL);
41
42 void cxd1185_init(struct sc_softc *);
43 static void free_scb(struct sc_softc *, struct sc_scb *);
44 static struct sc_scb *get_scb(struct sc_softc *, int);
45 static void sc_scsipi_request(struct scsipi_channel *,
46 scsipi_adapter_req_t, void *);
47 static int sc_poll(struct sc_softc *, int, int);
48 static void sc_sched(struct sc_softc *);
49 void sc_done(struct sc_scb *);
50 int sc_intr(void *);
51 static void cxd1185_timeout(void *);
52
53 extern void sc_send(struct sc_scb *, int, int);
54 extern int scintr(void);
55 extern void scsi_hardreset(void);
56 extern int sc_busy(struct sc_softc *, int);
57 extern paddr_t kvtophys(vaddr_t);
58
59 static int sc_disconnect = IDT_DISCON;
60
61 int
cxd1185_match(device_t parent,cfdata_t cf,void * aux)62 cxd1185_match(device_t parent, cfdata_t cf, void *aux)
63 {
64 struct hb_attach_args *ha = aux;
65
66 if (strcmp(ha->ha_name, "sc"))
67 return 0;
68
69 return 1;
70 }
71
72 void
cxd1185_attach(device_t parent,device_t self,void * aux)73 cxd1185_attach(device_t parent, device_t self, void *aux)
74 {
75 struct sc_softc *sc = device_private(self);
76 struct hb_attach_args *ha = aux;
77 struct sc_scb *scb;
78 int i, intlevel;
79
80 sc->sc_dev = self;
81
82 intlevel = ha->ha_level;
83 if (intlevel == -1) {
84 #if 0
85 aprint_error(": interrupt level not configured\n");
86 return;
87 #else
88 aprint_normal(": interrupt level not configured; using");
89 intlevel = 0;
90 #endif
91 }
92 aprint_normal(" level %d\n", intlevel);
93
94 if (sc_idenr & 0x08)
95 sc->scsi_1185AQ = 1;
96 else
97 sc->scsi_1185AQ = 0;
98
99 sc->sc_adapter.adapt_dev = self;
100 sc->sc_adapter.adapt_nchannels = 1;
101 sc->sc_adapter.adapt_openings = 7;
102 sc->sc_adapter.adapt_max_periph = 1;
103 sc->sc_adapter.adapt_ioctl = NULL;
104 sc->sc_adapter.adapt_minphys = minphys;
105 sc->sc_adapter.adapt_request = sc_scsipi_request;
106
107 memset(&sc->sc_channel, 0, sizeof(sc->sc_channel));
108 sc->sc_channel.chan_adapter = &sc->sc_adapter;
109 sc->sc_channel.chan_bustype = &scsi_bustype;
110 sc->sc_channel.chan_channel = 0;
111 sc->sc_channel.chan_ntargets = 8;
112 sc->sc_channel.chan_nluns = 8;
113 sc->sc_channel.chan_id = 7;
114
115 TAILQ_INIT(&sc->ready_list);
116 TAILQ_INIT(&sc->free_list);
117
118 scb = sc->sc_scb;
119 for (i = 0; i < 24; i++) { /* XXX 24 */
120 TAILQ_INSERT_TAIL(&sc->free_list, scb, chain);
121 scb++;
122 }
123
124 cxd1185_init(sc);
125 DELAY(100000);
126
127 hb_intr_establish(intlevel, INTEN1_DMA, IPL_BIO, sc_intr, sc);
128
129 config_found(self, &sc->sc_channel, scsiprint, CFARGS_NONE);
130 }
131
132 void
cxd1185_init(struct sc_softc * sc)133 cxd1185_init(struct sc_softc *sc)
134 {
135 int i;
136
137 for (i = 0; i < 8; i++)
138 sc->inuse[i] = 0;
139
140 scsi_hardreset();
141 }
142
143 void
free_scb(struct sc_softc * sc,struct sc_scb * scb)144 free_scb(struct sc_softc *sc, 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 *
get_scb(struct sc_softc * sc,int flags)163 get_scb(struct sc_softc *sc, int flags)
164 {
165 int s;
166 struct sc_scb *scb;
167
168 s = splbio();
169
170 while ((scb = sc->free_list.tqh_first) == NULL &&
171 (flags & XS_CTL_NOSLEEP) == 0)
172 tsleep(&sc->free_list, PRIBIO, "sc_scb", 0);
173 if (scb) {
174 TAILQ_REMOVE(&sc->free_list, scb, chain);
175 }
176
177 splx(s);
178 return scb;
179 }
180
181 void
sc_scsipi_request(struct scsipi_channel * chan,scsipi_adapter_req_t req,void * arg)182 sc_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req,
183 void *arg)
184 {
185 struct scsipi_xfer *xs;
186 struct scsipi_periph *periph;
187 struct sc_softc *sc = device_private(chan->chan_adapter->adapt_dev);
188 struct sc_scb *scb;
189 int flags, s;
190 int target;
191
192 switch (req) {
193 case ADAPTER_REQ_RUN_XFER:
194 xs = arg;
195 periph = xs->xs_periph;
196
197 flags = xs->xs_control;
198 if ((scb = get_scb(sc, flags)) == NULL)
199 panic("%s: no scb", __func__);
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 memset(scb->msgbuf, 0, 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) {
217 target = periph->periph_target;
218 if (sc_poll(sc, target, xs->timeout)) {
219 printf("sc: timeout (retry)\n");
220 if (sc_poll(sc, target, xs->timeout)) {
221 printf("sc: timeout\n");
222 }
223 }
224 /* called during autoconfig only... */
225 mips_dcache_wbinv_all(); /* Flush DCache */
226 }
227 return;
228 case ADAPTER_REQ_GROW_RESOURCES:
229 /* XXX Not supported. */
230 return;
231 case ADAPTER_REQ_SET_XFER_MODE:
232 /* XXX Not supported. */
233 return;
234 }
235 }
236
237 /*
238 * Used when interrupt driven I/O isn't allowed, e.g. during boot.
239 */
240 int
sc_poll(struct sc_softc * sc,int chan,int count)241 sc_poll(struct sc_softc *sc, int chan, int count)
242 {
243 volatile uint8_t *int_stat = (void *)INTST1;
244 volatile uint8_t *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
sc_sched(struct sc_softc * sc)268 sc_sched(struct sc_softc *sc)
269 {
270 struct scsipi_xfer *xs;
271 struct scsipi_periph *periph;
272 int ie = 0;
273 int flags;
274 int chan, lun;
275 struct sc_scb *scb, *nextscb;
276
277 scb = sc->ready_list.tqh_first;
278 start:
279 if (scb == NULL)
280 return;
281
282 xs = scb->xs;
283 periph = xs->xs_periph;
284 chan = periph->periph_target;
285 flags = xs->xs_control;
286
287 if (sc->inuse[chan]) {
288 scb = scb->chain.tqe_next;
289 goto start;
290 }
291 sc->inuse[chan] = 1;
292
293 if (flags & XS_CTL_RESET)
294 printf("SCSI RESET\n");
295
296 lun = periph->periph_lun;
297
298 scb->identify = MSG_IDENT | sc_disconnect | (lun & IDT_DRMASK);
299 scb->sc_ctrnscnt = xs->datalen;
300
301 /* make va->pa mapping table for DMA */
302 if (xs->datalen > 0) {
303 uint32_t pn, pages, offset;
304 int i;
305 vaddr_t va;
306
307 #if 0
308 memset(&sc->sc_map[chan], 0, sizeof(struct sc_map));
309 #endif
310
311 va = (vaddr_t)xs->data;
312
313 offset = va & PGOFSET;
314 pages = (offset + xs->datalen + PAGE_SIZE -1 ) >> PGSHIFT;
315 if (pages >= NSCMAP)
316 panic("sc_map: Too many pages");
317
318 for (i = 0; i < pages; i++) {
319 pn = kvtophys(va) >> PGSHIFT;
320 sc->sc_map[chan].mp_addr[i] = pn;
321 va += PAGE_SIZE;
322 }
323
324 sc->sc_map[chan].mp_offset = offset;
325 sc->sc_map[chan].mp_pages = pages;
326 scb->sc_map = &sc->sc_map[chan];
327 }
328
329 if ((flags & XS_CTL_POLL) == 0)
330 ie = SCSI_INTEN;
331
332 if (xs->data)
333 scb->sc_cpoint = (void *)xs->data;
334 else
335 scb->sc_cpoint = scb->msgbuf;
336 scb->scb_softc = sc;
337
338 callout_reset(&scb->xs->xs_callout, hz * 10, cxd1185_timeout, scb);
339 sc_send(scb, chan, ie);
340 callout_stop(&scb->xs->xs_callout);
341
342 nextscb = scb->chain.tqe_next;
343
344 TAILQ_REMOVE(&sc->ready_list, scb, chain);
345
346 scb = nextscb;
347
348 goto start;
349 }
350
351 void
sc_done(struct sc_scb * scb)352 sc_done(struct sc_scb *scb)
353 {
354 struct scsipi_xfer *xs = scb->xs;
355 struct scsipi_periph *periph = xs->xs_periph;
356 struct sc_softc *sc;
357
358 sc = device_private(periph->periph_channel->chan_adapter->adapt_dev);
359 xs->resid = 0;
360 xs->status = 0;
361
362 if (scb->istatus != INST_EP) {
363 if (scb->istatus == (INST_EP|INST_TO))
364 xs->error = XS_SELTIMEOUT;
365 else {
366 printf("SC(i): [istatus=0x%x, tstatus=0x%x]\n",
367 scb->istatus, scb->tstatus);
368 xs->error = XS_DRIVER_STUFFUP;
369 }
370 }
371
372 switch (scb->tstatus) {
373
374 case TGST_GOOD:
375 break;
376
377 case TGST_CC:
378 xs->status = SCSI_CHECK;
379 if (xs->error == 0)
380 xs->error = XS_BUSY;
381 break;
382
383 default:
384 printf("SC(t): [istatus=0x%x, tstatus=0x%x]\n",
385 scb->istatus, scb->tstatus);
386 break;
387 }
388
389 scsipi_done(xs);
390 free_scb(sc, scb);
391 sc->inuse[periph->periph_target] = 0;
392 sc_sched(sc);
393 }
394
395 int
sc_intr(void * v)396 sc_intr(void *v)
397 {
398 /* struct sc_softc *sc = v; */
399 volatile uint8_t *gsp = (uint8_t *)DMAC_GSTAT;
400 u_int gstat = *gsp;
401 int mrqb, i;
402
403 if ((gstat & CH_INT(CH_SCSI)) == 0)
404 return 0;
405
406 /*
407 * when DMA interrupt occurs there remain some untransferred data.
408 * wait data transfer completion.
409 */
410 mrqb = (gstat & CH_INT(CH_SCSI)) << 1;
411 if (gstat & mrqb) {
412 /*
413 * XXX SHOULD USE DELAY()
414 */
415 for (i = 0; i < 50; i++)
416 ;
417 if (*gsp & mrqb)
418 printf("%s: MRQ\n", __func__);
419 }
420 scintr();
421
422 return 1;
423 }
424
425
426 #if 0
427 /*
428 * SCOP_RSENSE request
429 */
430 void
431 scop_rsense(int intr, struct scsi *sc_param, int lun, int ie, int count,
432 void *param)
433 {
434
435 memset(sc_param, 0, sizeof(struct scsi));
436 sc_param->identify = MSG_IDENT | sc_disconnect | (lun & IDT_DRMASK);
437 sc_param->sc_lun = lun;
438
439 sc_param->sc_cpoint = (uint8_t *)param;
440 sc_param->sc_ctrnscnt = count;
441
442 /* sc_cdb */
443 sc_param->sc_opcode = SCOP_RSENSE;
444 sc_param->sc_count = count;
445
446 sc_go(intr, sc_param, ie, sc_param);
447 }
448 #endif
449
450 void
cxd1185_timeout(void * arg)451 cxd1185_timeout(void *arg)
452 {
453 struct sc_scb *scb = arg;
454 struct scsipi_xfer *xs = scb->xs;
455 struct scsipi_periph *periph = xs->xs_periph;
456 int chan;
457
458 chan = periph->periph_target;
459
460 printf("sc: timeout ch=%d\n", chan);
461
462 /* XXX abort transfer and ... */
463 }
464