Home | History | Annotate | Line # | Download | only in dev
wstsc.c revision 1.18
      1 /*	$NetBSD: wstsc.c,v 1.18 1996/12/23 09:10:31 veego Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1994 Michael L. Hitch
      5  * Copyright (c) 1982, 1990 The Regents of the University of California.
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  * 3. All advertising materials mentioning features or use of this software
     17  *    must display the following acknowledgement:
     18  *	This product includes software developed by the University of
     19  *	California, Berkeley and its contributors.
     20  * 4. Neither the name of the University nor the names of its contributors
     21  *    may be used to endorse or promote products derived from this software
     22  *    without specific prior written permission.
     23  *
     24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34  * SUCH DAMAGE.
     35  *
     36  *	@(#)supradma.c
     37  */
     38 #include <sys/param.h>
     39 #include <sys/systm.h>
     40 #include <sys/kernel.h>
     41 #include <sys/device.h>
     42 #include <scsi/scsi_all.h>
     43 #include <scsi/scsiconf.h>
     44 #include <amiga/amiga/device.h>
     45 #include <amiga/amiga/isr.h>
     46 #include <amiga/dev/scireg.h>
     47 #include <amiga/dev/scivar.h>
     48 #include <amiga/dev/zbusvar.h>
     49 
     50 void wstscattach __P((struct device *, struct device *, void *));
     51 int wstscmatch __P((struct device *, struct cfdata *, void *));
     52 
     53 int wstsc_dma_xfer_in __P((struct sci_softc *dev, int len,
     54     register u_char *buf, int phase));
     55 int wstsc_dma_xfer_out __P((struct sci_softc *dev, int len,
     56     register u_char *buf, int phase));
     57 int wstsc_dma_xfer_in2 __P((struct sci_softc *dev, int len,
     58     register u_short *buf, int phase));
     59 int wstsc_dma_xfer_out2 __P((struct sci_softc *dev, int len,
     60     register u_short *buf, int phase));
     61 int wstsc_intr __P((void *));
     62 
     63 struct scsi_adapter wstsc_scsiswitch = {
     64 	sci_scsicmd,
     65 	sci_minphys,
     66 	0,			/* no lun support */
     67 	0,			/* no lun support */
     68 };
     69 
     70 struct scsi_device wstsc_scsidev = {
     71 	NULL,		/* use default error handler */
     72 	NULL,		/* do not have a start functio */
     73 	NULL,		/* have no async handler */
     74 	NULL,		/* Use default done routine */
     75 };
     76 
     77 #ifdef DEBUG
     78 extern int sci_debug;
     79 #define QPRINTF(a) if (sci_debug > 1) printf a
     80 #else
     81 #define QPRINTF(a)
     82 #endif
     83 
     84 extern int sci_data_wait;
     85 
     86 int supradma_pseudo = 0;	/* 0=none, 1=byte, 2=word */
     87 
     88 struct cfattach wstsc_ca = {
     89 	sizeof(struct sci_softc), wstscmatch, wstscattach
     90 };
     91 
     92 struct cfdriver wstsc_cd = {
     93 	NULL, "wstsc", DV_DULL, NULL, 0
     94 };
     95 
     96 /*
     97  * if this a Supra WordSync board
     98  */
     99 int
    100 wstscmatch(pdp, cfp, auxp)
    101 	struct device *pdp;
    102 	struct cfdata *cfp;
    103 	void *auxp;
    104 {
    105 	struct zbus_args *zap;
    106 
    107 	zap = auxp;
    108 
    109 	/*
    110 	 * Check manufacturer and product id.
    111 	 */
    112 	if (zap->manid == 1056 && (
    113 	    zap->prodid == 12 ||	/* WordSync */
    114 	    zap->prodid == 13))		/* ByteSync */
    115 		return(1);
    116 	else
    117 		return(0);
    118 }
    119 
    120 void
    121 wstscattach(pdp, dp, auxp)
    122 	struct device *pdp, *dp;
    123 	void *auxp;
    124 {
    125 	volatile u_char *rp;
    126 	struct sci_softc *sc;
    127 	struct zbus_args *zap;
    128 
    129 	printf("\n");
    130 
    131 	zap = auxp;
    132 
    133 	sc = (struct sci_softc *)dp;
    134 	rp = zap->va;
    135 	/*
    136 	 * set up 5380 register pointers
    137 	 * (Needs check on which Supra board this is - for now,
    138 	 *  just do the WordSync)
    139 	 */
    140 	sc->sci_data = rp + 0;
    141 	sc->sci_odata = rp + 0;
    142 	sc->sci_icmd = rp + 2;
    143 	sc->sci_mode = rp + 4;
    144 	sc->sci_tcmd = rp + 6;
    145 	sc->sci_bus_csr = rp + 8;
    146 	sc->sci_sel_enb = rp + 8;
    147 	sc->sci_csr = rp + 10;
    148 	sc->sci_dma_send = rp + 10;
    149 	sc->sci_idata = rp + 12;
    150 	sc->sci_trecv = rp + 12;
    151 	sc->sci_iack = rp + 14;
    152 	sc->sci_irecv = rp + 14;
    153 
    154 	if (supradma_pseudo == 2) {
    155 		sc->dma_xfer_in = (int(*)(struct sci_softc *, int, u_char *, int))wstsc_dma_xfer_in2;
    156 		sc->dma_xfer_out = (int(*)(struct sci_softc *, int, u_char *, int))wstsc_dma_xfer_out2;
    157 	}
    158 	else if (supradma_pseudo == 1) {
    159 		sc->dma_xfer_in = wstsc_dma_xfer_in;
    160 		sc->dma_xfer_out = wstsc_dma_xfer_out;
    161 	}
    162 
    163 	sc->sc_isr.isr_intr = wstsc_intr;
    164 	sc->sc_isr.isr_arg = sc;
    165 	sc->sc_isr.isr_ipl = 2;
    166 	add_isr(&sc->sc_isr);
    167 
    168 	scireset(sc);
    169 
    170 	sc->sc_link.channel = SCSI_CHANNEL_ONLY_ONE;
    171 	sc->sc_link.adapter_softc = sc;
    172 	sc->sc_link.adapter_target = 7;
    173 	sc->sc_link.adapter = &wstsc_scsiswitch;
    174 	sc->sc_link.device = &wstsc_scsidev;
    175 	sc->sc_link.openings = 1;
    176 	sc->sc_link.max_target = 7;
    177 	TAILQ_INIT(&sc->sc_xslist);
    178 
    179 	/*
    180 	 * attach all scsi units on us
    181 	 */
    182 	config_found(dp, &sc->sc_link, scsiprint);
    183 }
    184 
    185 int
    186 wstsc_dma_xfer_in (dev, len, buf, phase)
    187 	struct sci_softc *dev;
    188 	int len;
    189 	register u_char *buf;
    190 	int phase;
    191 {
    192 	int wait = sci_data_wait;
    193 	volatile register u_char *sci_dma = dev->sci_idata;
    194 	volatile register u_char *sci_csr = dev->sci_csr;
    195 #ifdef DEBUG
    196 	u_char *obp = (u_char *) buf;
    197 #endif
    198 
    199 	QPRINTF(("supradma_in %d, csr=%02x\n", len, *dev->sci_bus_csr));
    200 
    201 	*dev->sci_tcmd = phase;
    202 	*dev->sci_icmd = 0;
    203 	*dev->sci_mode = SCI_MODE_DMA;
    204 	*dev->sci_irecv = 0;
    205 
    206 	while (len >= 128) {
    207 		wait = sci_data_wait;
    208 		while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) !=
    209 		  (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) {
    210 			if (!(*sci_csr & SCI_CSR_PHASE_MATCH)
    211 			  || !(*dev->sci_bus_csr & SCI_BUS_BSY)
    212 			  || --wait < 0) {
    213 #ifdef DEBUG
    214 				if (sci_debug | 1)
    215 					printf("supradma2_in fail: l%d i%x w%d\n",
    216 					len, *dev->sci_bus_csr, wait);
    217 #endif
    218 				*dev->sci_mode = 0;
    219 				return 0;
    220 			}
    221 		}
    222 
    223 #define R1	(*buf++ = *sci_dma)
    224 		R1; R1; R1; R1; R1; R1; R1; R1;
    225 		R1; R1; R1; R1; R1; R1; R1; R1;
    226 		R1; R1; R1; R1; R1; R1; R1; R1;
    227 		R1; R1; R1; R1; R1; R1; R1; R1;
    228 		R1; R1; R1; R1; R1; R1; R1; R1;
    229 		R1; R1; R1; R1; R1; R1; R1; R1;
    230 		R1; R1; R1; R1; R1; R1; R1; R1;
    231 		R1; R1; R1; R1; R1; R1; R1; R1;
    232 		R1; R1; R1; R1; R1; R1; R1; R1;
    233 		R1; R1; R1; R1; R1; R1; R1; R1;
    234 		R1; R1; R1; R1; R1; R1; R1; R1;
    235 		R1; R1; R1; R1; R1; R1; R1; R1;
    236 		R1; R1; R1; R1; R1; R1; R1; R1;
    237 		R1; R1; R1; R1; R1; R1; R1; R1;
    238 		R1; R1; R1; R1; R1; R1; R1; R1;
    239 		R1; R1; R1; R1; R1; R1; R1; R1;
    240 		len -= 128;
    241 	}
    242 
    243 	while (len > 0) {
    244 		wait = sci_data_wait;
    245 		while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) !=
    246 		  (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) {
    247 			if (!(*sci_csr & SCI_CSR_PHASE_MATCH)
    248 			  || !(*dev->sci_bus_csr & SCI_BUS_BSY)
    249 			  || --wait < 0) {
    250 #ifdef DEBUG
    251 				if (sci_debug | 1)
    252 					printf("supradma1_in fail: l%d i%x w%d\n",
    253 					len, *dev->sci_bus_csr, wait);
    254 #endif
    255 				*dev->sci_mode = 0;
    256 				return 0;
    257 			}
    258 		}
    259 
    260 		*buf++ = *sci_dma;
    261 		len--;
    262 	}
    263 
    264 	QPRINTF(("supradma_in {%d} %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
    265 	  len, obp[0], obp[1], obp[2], obp[3], obp[4], obp[5],
    266 	  obp[6], obp[7], obp[8], obp[9]));
    267 
    268 	*dev->sci_mode = 0;
    269 	return 0;
    270 }
    271 
    272 int
    273 wstsc_dma_xfer_out (dev, len, buf, phase)
    274 	struct sci_softc *dev;
    275 	int len;
    276 	register u_char *buf;
    277 	int phase;
    278 {
    279 	int wait = sci_data_wait;
    280 	volatile register u_char *sci_dma = dev->sci_data;
    281 	volatile register u_char *sci_csr = dev->sci_csr;
    282 
    283 	QPRINTF(("supradma_out %d, csr=%02x\n", len, *dev->sci_bus_csr));
    284 
    285 	QPRINTF(("supradma_out {%d} %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
    286   	 len, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5],
    287 	 buf[6], buf[7], buf[8], buf[9]));
    288 
    289 	*dev->sci_tcmd = phase;
    290 	*dev->sci_mode = SCI_MODE_DMA;
    291 	*dev->sci_icmd = SCI_ICMD_DATA;
    292 	*dev->sci_dma_send = 0;
    293 	while (len > 0) {
    294 		wait = sci_data_wait;
    295 		while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) !=
    296 		  (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) {
    297 			if (!(*sci_csr & SCI_CSR_PHASE_MATCH)
    298 			  || !(*dev->sci_bus_csr & SCI_BUS_BSY)
    299 			  || --wait < 0) {
    300 #ifdef DEBUG
    301 				if (sci_debug)
    302 					printf("supradma_out fail: l%d i%x w%d\n",
    303 					len, *dev->sci_bus_csr, wait);
    304 #endif
    305 				*dev->sci_mode = 0;
    306 				return 0;
    307 			}
    308 		}
    309 
    310 		*sci_dma = *buf++;
    311 		len--;
    312 	}
    313 
    314 	wait = sci_data_wait;
    315 	while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) ==
    316 	  SCI_CSR_PHASE_MATCH && --wait);
    317 
    318 
    319 	*dev->sci_mode = 0;
    320 	*dev->sci_icmd = 0;
    321 	return 0;
    322 }
    323 
    324 
    325 int
    326 wstsc_dma_xfer_in2 (dev, len, buf, phase)
    327 	struct sci_softc *dev;
    328 	int len;
    329 	register u_short *buf;
    330 	int phase;
    331 {
    332 	volatile register u_short *sci_dma = (u_short *)(dev->sci_idata + 0x10);
    333 	volatile register u_char *sci_csr = dev->sci_csr + 0x10;
    334 #ifdef DEBUG
    335 	u_char *obp = (u_char *) buf;
    336 #endif
    337 #if 0
    338 	int wait = sci_data_wait;
    339 #endif
    340 
    341 	QPRINTF(("supradma_in2 %d, csr=%02x\n", len, *dev->sci_bus_csr));
    342 
    343 	*dev->sci_tcmd = phase;
    344 	*dev->sci_mode = SCI_MODE_DMA;
    345 	*dev->sci_icmd = 0;
    346 	*(dev->sci_irecv + 16) = 0;
    347 	while (len >= 128) {
    348 #if 0
    349 		wait = sci_data_wait;
    350 		while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) !=
    351 		  (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) {
    352 			if (!(*sci_csr & SCI_CSR_PHASE_MATCH)
    353 			  || !(*dev->sci_bus_csr & SCI_BUS_BSY)
    354 			  || --wait < 0) {
    355 #ifdef DEBUG
    356 				if (sci_debug | 1)
    357 					printf("supradma2_in2 fail: l%d i%x w%d\n",
    358 					len, *dev->sci_bus_csr, wait);
    359 #endif
    360 				*dev->sci_mode &= ~SCI_MODE_DMA;
    361 				return 0;
    362 			}
    363 		}
    364 #else
    365 		while (!(*sci_csr & SCI_CSR_DREQ))
    366 			;
    367 #endif
    368 
    369 #define R2	(*buf++ = *sci_dma)
    370 		R2; R2; R2; R2; R2; R2; R2; R2;
    371 		R2; R2; R2; R2; R2; R2; R2; R2;
    372 		R2; R2; R2; R2; R2; R2; R2; R2;
    373 		R2; R2; R2; R2; R2; R2; R2; R2;
    374 		R2; R2; R2; R2; R2; R2; R2; R2;
    375 		R2; R2; R2; R2; R2; R2; R2; R2;
    376 		R2; R2; R2; R2; R2; R2; R2; R2;
    377 		R2; R2; R2; R2; R2; R2; R2; R2;
    378 		len -= 128;
    379 	}
    380 	while (len > 0) {
    381 #if 0
    382 		wait = sci_data_wait;
    383 		while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) !=
    384 		  (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) {
    385 			if (!(*sci_csr & SCI_CSR_PHASE_MATCH)
    386 			  || !(*dev->sci_bus_csr & SCI_BUS_BSY)
    387 			  || --wait < 0) {
    388 #ifdef DEBUG
    389 				if (sci_debug | 1)
    390 					printf("supradma1_in2 fail: l%d i%x w%d\n",
    391 					len, *dev->sci_bus_csr, wait);
    392 #endif
    393 				*dev->sci_mode &= ~SCI_MODE_DMA;
    394 				return 0;
    395 			}
    396 		}
    397 #else
    398 		while (!(*sci_csr * SCI_CSR_DREQ))
    399 			;
    400 #endif
    401 
    402 		*buf++ = *sci_dma;
    403 		len -= 2;
    404 	}
    405 
    406 	QPRINTF(("supradma_in2 {%d} %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
    407 	  len, obp[0], obp[1], obp[2], obp[3], obp[4], obp[5],
    408 	  obp[6], obp[7], obp[8], obp[9]));
    409 
    410 	*dev->sci_irecv = 0;
    411 	*dev->sci_mode = 0;
    412 	return 0;
    413 }
    414 
    415 int
    416 wstsc_dma_xfer_out2 (dev, len, buf, phase)
    417 	struct sci_softc *dev;
    418 	int len;
    419 	register u_short *buf;
    420 	int phase;
    421 {
    422 	volatile register u_short *sci_dma = (ushort *)(dev->sci_data + 0x10);
    423 	volatile register u_char *sci_bus_csr = dev->sci_bus_csr;
    424 #ifdef DEBUG
    425 	u_char *obp = (u_char *) buf;
    426 #endif
    427 #if 0
    428 	int wait = sci_data_wait;
    429 #endif
    430 
    431 	QPRINTF(("supradma_out2 %d, csr=%02x\n", len, *dev->sci_bus_csr));
    432 
    433 	QPRINTF(("supradma_out2 {%d} %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
    434   	 len, obp[0], obp[1], obp[2], obp[3], obp[4], obp[5],
    435 	 obp[6], obp[7], obp[8], obp[9]));
    436 
    437 	*dev->sci_tcmd = phase;
    438 	*dev->sci_mode = SCI_MODE_DMA;
    439 	*dev->sci_icmd = SCI_ICMD_DATA;
    440 	*dev->sci_dma_send = 0;
    441 	while (len > 64) {
    442 #if 0
    443 		wait = sci_data_wait;
    444 		while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) !=
    445 		  (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) {
    446 			if (!(*sci_csr & SCI_CSR_PHASE_MATCH)
    447 			  || !(*dev->sci_bus_csr & SCI_BUS_BSY)
    448 			  || --wait < 0) {
    449 #ifdef DEBUG
    450 				if (sci_debug)
    451 					printf("supradma_out2 fail: l%d i%x w%d\n",
    452 					len, csr, wait);
    453 #endif
    454 				*dev->sci_mode = 0;
    455 				return 0;
    456 			}
    457 		}
    458 #else
    459 		*dev->sci_mode = 0;
    460 		*dev->sci_icmd &= ~SCI_ICMD_ACK;
    461 		while (!(*sci_bus_csr & SCI_BUS_REQ))
    462 			;
    463 		*dev->sci_mode = SCI_MODE_DMA;
    464 		*dev->sci_dma_send = 0;
    465 #endif
    466 
    467 #define W2	(*sci_dma = *buf++)
    468 		W2; W2; W2; W2; W2; W2; W2; W2;
    469 		W2; W2; W2; W2; W2; W2; W2; W2;
    470 		if (*(sci_bus_csr + 0x10) & SCI_BUS_REQ)
    471 			;
    472 		len -= 64;
    473 	}
    474 
    475 	while (len > 0) {
    476 #if 0
    477 		wait = sci_data_wait;
    478 		while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) !=
    479 		  (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) {
    480 			if (!(*sci_csr & SCI_CSR_PHASE_MATCH)
    481 			  || !(*dev->sci_bus_csr & SCI_BUS_BSY)
    482 			  || --wait < 0) {
    483 #ifdef DEBUG
    484 				if (sci_debug)
    485 					printf("supradma_out2 fail: l%d i%x w%d\n",
    486 					len, csr, wait);
    487 #endif
    488 				*dev->sci_mode = 0;
    489 				return 0;
    490 			}
    491 		}
    492 #else
    493 		*dev->sci_mode = 0;
    494 		*dev->sci_icmd &= ~SCI_ICMD_ACK;
    495 		while (!(*sci_bus_csr & SCI_BUS_REQ))
    496 			;
    497 		*dev->sci_mode = SCI_MODE_DMA;
    498 		*dev->sci_dma_send = 0;
    499 #endif
    500 
    501 		*sci_dma = *buf++;
    502 		if (*(sci_bus_csr + 0x10) & SCI_BUS_REQ)
    503 			;
    504 		len -= 2;
    505 	}
    506 
    507 #if 0
    508 	wait = sci_data_wait;
    509 	while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) ==
    510 	  SCI_CSR_PHASE_MATCH && --wait);
    511 #endif
    512 
    513 
    514 	*dev->sci_irecv = 0;
    515 	*dev->sci_icmd &= ~SCI_ICMD_ACK;
    516 	*dev->sci_mode = 0;
    517 	*dev->sci_icmd = 0;
    518 	return 0;
    519 }
    520 
    521 int
    522 wstsc_intr(arg)
    523 	void *arg;
    524 {
    525 	struct sci_softc *dev = arg;
    526 	u_char stat;
    527 
    528 	if ((*(dev->sci_csr + 0x10) & SCI_CSR_INT) == 0)
    529 		return (0);
    530 	stat = *(dev->sci_iack + 0x10);
    531 	return (1);
    532 }
    533