Home | History | Annotate | Line # | Download | only in dev
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