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