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