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
36static int cxd1185_match(device_t, cfdata_t, void *);
37static void cxd1185_attach(device_t, device_t, void *);
38
39CFATTACH_DECL_NEW(sc, sizeof(struct sc_softc),
40    cxd1185_match, cxd1185_attach, NULL, NULL);
41
42void cxd1185_init(struct sc_softc *);
43static void free_scb(struct sc_softc *, struct sc_scb *);
44static struct sc_scb *get_scb(struct sc_softc *, int);
45static void sc_scsipi_request(struct scsipi_channel *,
46    scsipi_adapter_req_t, void *);
47static int sc_poll(struct sc_softc *, int, int);
48static void sc_sched(struct sc_softc *);
49void sc_done(struct sc_scb *);
50int sc_intr(void *);
51static void cxd1185_timeout(void *);
52
53extern void sc_send(struct sc_scb *, int, int);
54extern int scintr(void);
55extern void scsi_hardreset(void);
56extern int sc_busy(struct sc_softc *, int);
57extern paddr_t kvtophys(vaddr_t);
58
59static int sc_disconnect = IDT_DISCON;
60
61int
62cxd1185_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
72void
73cxd1185_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
132void
133cxd1185_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
143void
144free_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
162struct sc_scb *
163get_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
181void
182sc_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 */
240int
241sc_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
267void
268sc_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;
278start:
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
351void
352sc_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
395int
396sc_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 */
430void
431scop_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
450void
451cxd1185_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