Home | History | Annotate | Line # | Download | only in dev
siop.c revision 1.2
      1 /*
      2  * Copyright (c) 1990 The Regents of the University of California.
      3  * All rights reserved.
      4  *
      5  * This code is derived from software contributed to Berkeley by
      6  * Van Jacobson of Lawrence Berkeley Laboratory.
      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  *	@(#)siop.c	7.5 (Berkeley) 5/4/91
     37  *
     38  * MULTICONTROLLER support only working for multiple controllers of the
     39  * same kind at the moment !!
     40  *
     41  */
     42 
     43 /*
     44  * AMIGA 53C710 scsi adaptor driver
     45  */
     46 
     47 #include "zeusscsi.h"
     48 #include "magnumscsi.h"
     49 #define NSIOP (NZEUSSCSI + NMAGNUMSCSI)
     50 #if NSIOP > 0
     51 
     52 #ifndef lint
     53 static char rcsid[] = "$Header: /tank/opengrok/rsync2/NetBSD/src/sys/arch/amiga/dev/siop.c,v 1.2 1994/02/01 11:52:35 chopps Exp $";
     54 #endif
     55 
     56 /* need to know if any tapes have been configured */
     57 #include "st.h"
     58 
     59 #include "sys/param.h"
     60 #include "sys/systm.h"
     61 #include "sys/buf.h"
     62 #include "device.h"
     63 
     64 #include "scsidefs.h"
     65 #include "siopvar.h"
     66 #include "siopreg.h"
     67 
     68 #include "../amiga/custom.h"
     69 
     70 #include "machine/cpu.h"
     71 
     72 extern u_int	kvtop();
     73 
     74 /*
     75  * SCSI delays
     76  * In u-seconds, primarily for state changes on the SPC.
     77  */
     78 #define	SCSI_CMD_WAIT	50000	/* wait per step of 'immediate' cmds */
     79 #define	SCSI_DATA_WAIT	50000	/* wait per data in/out step */
     80 #define	SCSI_INIT_WAIT	50000	/* wait per step (both) during init */
     81 
     82 void siopstart (int unit);
     83 int siopgo (int ctlr, int slave, int unit, struct buf *bp, struct scsi_fmt_cdb *cdb, int pad);
     84 int siopintr2 (void);
     85 void siopdone (int unit);
     86 int siopustart (int unit);
     87 int siopreq (register struct devqueue *dq);
     88 void siopfree (register struct devqueue *dq);
     89 void siopreset (int unit);
     90 void siop_delay (int delay);
     91 int siop_test_unit_rdy (int ctlr, int slave, int unit);
     92 int siop_start_stop_unit (int ctlr, int slave, int unit, int start);
     93 int siop_request_sense (int ctlr, int slave, int unit, u_char *buf, unsigned int len);
     94 int siop_immed_command (int ctlr, int slave, int unit, struct scsi_fmt_cdb *cdb, u_char *buf, unsigned int len, int rd);
     95 int siop_tt_read (int ctlr, int slave, int unit, u_char *buf, u_int len, daddr_t blk, int bshift);
     96 int siop_tt_write (int ctlr, int slave, int unit, u_char *buf, u_int len, daddr_t blk, int bshift);
     97 #if NST > 0
     98 int siop_tt_oddio (int ctlr, int slave, int unit, u_char *buf, u_int len, int b_flags, int freedma);
     99 #endif
    100 
    101 #if NZEUSSCSI > 0
    102 int zeusscsiinit();
    103 
    104 struct driver zeusscsidriver = {
    105 	zeusscsiinit, "Zeusscsi", (int (*)())siopstart, (int (*)())siopgo,
    106 	(int (*)())siopintr2, (int (*)())siopdone,
    107 	siopustart, siopreq, siopfree, siopreset,
    108 	siop_delay, siop_test_unit_rdy, siop_start_stop_unit,
    109 	siop_request_sense, siop_immed_command, siop_tt_read, siop_tt_write,
    110 #if NST > 0
    111 	siop_tt_oddio
    112 #else
    113 	0
    114 #endif
    115 };
    116 #endif
    117 
    118 #if NMAGNUMSCSI > 0
    119 int magnumscsiinit();
    120 
    121 struct driver magnumscsidriver = {
    122 	magnumscsiinit, "Magnumscsi", (int (*)())siopstart, (int (*)())siopgo,
    123 	(int (*)())siopintr2, (int (*)())siopdone,
    124 	siopustart, siopreq, siopfree, siopreset,
    125 	siop_delay, siop_test_unit_rdy, siop_start_stop_unit,
    126 	siop_request_sense, siop_immed_command, siop_tt_read, siop_tt_write,
    127 #if NST > 0
    128 	siop_tt_oddio
    129 #else
    130 	0
    131 #endif
    132 };
    133 #endif
    134 
    135 /* 53C710 script */
    136 unsigned long scripts[] = {
    137 	0x47000000, 0x00000298,	/* 000 -   0 */
    138 	0x838b0000, 0x000000d0,	/* 008 -   8 */
    139 	0x7a1b1000, 0x00000000,	/* 010 -  16 */
    140 	0x828a0000, 0x00000088,	/* 018 -  24 */
    141 	0x9e020000, 0x0000ff01,	/* 020 -  32 */
    142 	0x72350000, 0x00000000,	/* 028 -  40 */
    143 	0x808c0000, 0x00000048,	/* 030 -  48 */
    144 	0x58000008, 0x00000000,	/* 038 -  56 */
    145 	0x1e000024, 0x00000024,	/* 040 -  64 */
    146 	0x838b0000, 0x00000090,	/* 048 -  72 */
    147 	0x1f00002c, 0x0000002c,	/* 050 -  80 */
    148 	0x838b0000, 0x00000080,	/* 058 -  88 */
    149 	0x868a0000, 0xffffffd0,	/* 060 -  96 */
    150 	0x838a0000, 0x00000070,	/* 068 - 104 */
    151 	0x878a0000, 0x00000120,	/* 070 - 112 */
    152 	0x80880000, 0x00000028,	/* 078 - 120 */
    153 	0x1e000004, 0x00000004,	/* 080 - 128 */
    154 	0x838b0000, 0x00000050,	/* 088 - 136 */
    155 	0x868a0000, 0xffffffe8,	/* 090 - 144 */
    156 	0x838a0000, 0x00000040,	/* 098 - 152 */
    157 	0x878a0000, 0x000000f0,	/* 0a0 - 160 */
    158 	0x9a020000, 0x0000ff02,	/* 0a8 - 168 */
    159 	0x1a00000c, 0x0000000c,	/* 0b0 - 176 */
    160 	0x878b0000, 0x00000130,	/* 0b8 - 184 */
    161 	0x838a0000, 0x00000018,	/* 0c0 - 192 */
    162 	0x818a0000, 0x000000b0,	/* 0c8 - 200 */
    163 	0x808a0000, 0x00000080,	/* 0d0 - 208 */
    164 	0x98080000, 0x0000ff03,	/* 0d8 - 216 */
    165 	0x1b000014, 0x00000014,	/* 0e0 - 224 */
    166 	0x72090000, 0x00000000,	/* 0e8 - 232 */
    167 	0x6a340000, 0x00000000,	/* 0f0 - 240 */
    168 	0x9f030000, 0x0000ff04,	/* 0f8 - 248 */
    169 	0x1f00001c, 0x0000001c,	/* 100 - 256 */
    170 	0x98040000, 0x0000ff26,	/* 108 - 264 */
    171 	0x60000040, 0x00000000,	/* 110 - 272 */
    172 	0x48000000, 0x00000000,	/* 118 - 280 */
    173 	0x7c1bef00, 0x00000000,	/* 120 - 288 */
    174 	0x72340000, 0x00000000,	/* 128 - 296 */
    175 	0x980c0002, 0x0000fffc,	/* 130 - 304 */
    176 	0x980c0008, 0x0000fffb,	/* 138 - 312 */
    177 	0x980c0018, 0x0000fffd,	/* 140 - 320 */
    178 	0x98040000, 0x0000fffe,	/* 148 - 328 */
    179 	0x98080000, 0x0000ff00,	/* 150 - 336 */
    180 	0x18000034, 0x00000034,	/* 158 - 344 */
    181 	0x808b0000, 0x000001c0,	/* 160 - 352 */
    182 	0x838b0000, 0xffffff70,	/* 168 - 360 */
    183 	0x878a0000, 0x000000d0,	/* 170 - 368 */
    184 	0x98080000, 0x0000ff05,	/* 178 - 376 */
    185 	0x19000034, 0x00000034,	/* 180 - 384 */
    186 	0x818b0000, 0x00000160,	/* 188 - 392 */
    187 	0x80880000, 0xffffffd0,	/* 190 - 400 */
    188 	0x1f00001c, 0x0000001c,	/* 198 - 408 */
    189 	0x808c0001, 0x00000018,	/* 1a0 - 416 */
    190 	0x980c0002, 0x0000ff08,	/* 1a8 - 424 */
    191 	0x808c0004, 0x00000020,	/* 1b0 - 432 */
    192 	0x98080000, 0x0000ff06,	/* 1b8 - 440 */
    193 	0x60000040, 0x00000000,	/* 1c0 - 448 */
    194 	0x1f00002c, 0x0000002c,	/* 1c8 - 456 */
    195 	0x98080000, 0x0000ff07,	/* 1d0 - 464 */
    196 	0x60000040, 0x00000000,	/* 1d8 - 472 */
    197 	0x48000000, 0x00000000,	/* 1e0 - 480 */
    198 	0x98080000, 0x0000ff09,	/* 1e8 - 488 */
    199 	0x1f00001c, 0x0000001c,	/* 1f0 - 496 */
    200 	0x808c0001, 0x00000018,	/* 1f8 - 504 */
    201 	0x980c0002, 0x0000ff10,	/* 200 - 512 */
    202 	0x808c0004, 0x00000020,	/* 208 - 520 */
    203 	0x98080000, 0x0000ff11,	/* 210 - 528 */
    204 	0x60000040, 0x00000000,	/* 218 - 536 */
    205 	0x1f00002c, 0x0000002c,	/* 220 - 544 */
    206 	0x98080000, 0x0000ff12,	/* 228 - 552 */
    207 	0x60000040, 0x00000000,	/* 230 - 560 */
    208 	0x48000000, 0x00000000,	/* 238 - 568 */
    209 	0x98080000, 0x0000ff13,	/* 240 - 576 */
    210 	0x1f00001c, 0x0000001c,	/* 248 - 584 */
    211 	0x808c0001, 0x00000018,	/* 250 - 592 */
    212 	0x980c0002, 0x0000ff14,	/* 258 - 600 */
    213 	0x808c0004, 0x00000020,	/* 260 - 608 */
    214 	0x98080000, 0x0000ff15,	/* 268 - 616 */
    215 	0x60000040, 0x00000000,	/* 270 - 624 */
    216 	0x1f00002c, 0x0000002c,	/* 278 - 632 */
    217 	0x98080000, 0x0000ff16,	/* 280 - 640 */
    218 	0x60000040, 0x00000000,	/* 288 - 648 */
    219 	0x48000000, 0x00000000,	/* 290 - 656 */
    220 	0x98080000, 0x0000ff17,	/* 298 - 664 */
    221 	0x54000000, 0x00000040,	/* 2a0 - 672 */
    222 	0x9f030000, 0x0000ff18,	/* 2a8 - 680 */
    223 	0x1f00001c, 0x0000001c,	/* 2b0 - 688 */
    224 	0x990b0000, 0x0000ff19,	/* 2b8 - 696 */
    225 	0x980a0000, 0x0000ff20,	/* 2c0 - 704 */
    226 	0x9f0a0000, 0x0000ff21,	/* 2c8 - 712 */
    227 	0x9b0a0000, 0x0000ff22,	/* 2d0 - 720 */
    228 	0x9e0a0000, 0x0000ff23,	/* 2d8 - 728 */
    229 	0x98080000, 0x0000ff24,	/* 2e0 - 736 */
    230 	0x98080000, 0x0000ff25,	/* 2e8 - 744 */
    231 	0x76100800, 0x00000000,	/* 2f0 - 752 */
    232 	0x80840700, 0x00000008,	/* 2f8 - 760 */
    233 	0x7e110100, 0x00000000,	/* 300 - 768 */
    234 	0x6a100000, 0x00000000,	/* 308 - 776 */
    235 	0x19000034, 0x00000034,	/* 310 - 784 */
    236 	0x818b0000, 0xffffffd0,	/* 318 - 792 */
    237 	0x98080000, 0x0000ff27,	/* 320 - 800 */
    238 	0x76100800, 0x00000000,	/* 328 - 808 */
    239 	0x80840700, 0x00000008,	/* 330 - 816 */
    240 	0x7e110100, 0x00000000,	/* 338 - 824 */
    241 	0x6a100000, 0x00000000,	/* 340 - 832 */
    242 	0x18000034, 0x00000034,	/* 348 - 840 */
    243 	0x808b0000, 0xffffffd0,	/* 350 - 848 */
    244 	0x98080000, 0x0000ff27	/* 358 - 856 */
    245 };
    246 
    247 #define	Ent_msgout	0x00000018
    248 #define	Ent_cmd		0x000000a8
    249 #define	Ent_status	0x000000e0
    250 #define	Ent_msgin	0x000000f8
    251 #define	Ent_dataout	0x00000158
    252 #define	Ent_datain	0x00000180
    253 
    254 struct	siop_softc siop_softc[NSIOP];
    255 
    256 int siop_cmd_wait = SCSI_CMD_WAIT;
    257 int siop_data_wait = SCSI_DATA_WAIT;
    258 int siop_init_wait = SCSI_INIT_WAIT;
    259 
    260 static struct {
    261 	unsigned char x;	/* period from sync request message */
    262 	unsigned char y;	/* siop_period << 4 | sbcl */
    263 } xxx[] = {
    264 	{0x0f, 0x01},
    265 	{0x13, 0x11},
    266 	{0x17, 0x21},
    267 /*	{0x17, 0x02},	*/
    268 	{0x1b, 0x31},
    269 	{0x1d, 0x12},
    270 	{0x1e, 0x41},
    271 /*	{0x1e, 0x03},	*/
    272 	{0x22, 0x51},
    273 	{0x23, 0x22},
    274 	{0x26, 0x61},
    275 /*	{0x26, 0x13},	*/
    276 	{0x29, 0x32},
    277 	{0x2a, 0x71},
    278 	{0x2d, 0x23},
    279 	{0x2e, 0x42},
    280 	{0x34, 0x52},
    281 	{0x35, 0x33},
    282 	{0x3a, 0x62},
    283 	{0x3c, 0x43},
    284 	{0x40, 0x72},
    285 	{0x44, 0x53},
    286 	{0x4b, 0x63},
    287 	{0x53, 0x73}
    288 };
    289 
    290 scsi_period_to_siop (dev, target)
    291 	struct siop_softc *dev;
    292 {
    293 	int period, offset, i, sxfer;
    294 
    295 	period = dev->sc_msg[4];
    296 	offset = dev->sc_msg[5];
    297 	sxfer = 0;
    298 	if (offset <= SIOP_MAX_OFFSET)
    299 		sxfer = offset;
    300 	for (i = 0; i < sizeof (xxx) / 2; ++i) {
    301 		if (period <= xxx[i].x) {
    302 			sxfer |= xxx[i].y & 0x70;
    303 			offset = xxx[i].y & 0x03;
    304 			break;
    305 		}
    306 	}
    307 	dev->sc_sync[target].period = sxfer;
    308 	dev->sc_sync[target].offset = offset;
    309 #ifdef DEBUG
    310 	printf ("sync: siop_sxfr %02x, siop_sbcl %02x\n", sxfer, offset);
    311 #endif
    312 }
    313 
    314 /* default to not inhibit sync negotiation on any drive */
    315 u_char siop_inhibit_sync[NSIOP][8] = { 0, 0, 1, 0, 0, 0, 0 }; /* initialize, so patchable */
    316 int siop_no_dma = 0;
    317 
    318 /*
    319  * XXX Set/reset long delays.
    320  *
    321  * if delay == 0, reset default delays
    322  * if delay < 0,  set both delays to default long initialization values
    323  * if delay > 0,  set both delays to this value
    324  *
    325  * Used when a devices is expected to respond slowly (e.g. during
    326  * initialization).
    327  */
    328 void
    329 siop_delay(delay)
    330 	int delay;
    331 {
    332 	static int saved_cmd_wait, saved_data_wait;
    333 
    334 	if (delay) {
    335 		saved_cmd_wait = siop_cmd_wait;
    336 		saved_data_wait = siop_data_wait;
    337 		if (delay > 0)
    338 			siop_cmd_wait = siop_data_wait = delay;
    339 		else
    340 			siop_cmd_wait = siop_data_wait = siop_init_wait;
    341 	} else {
    342 		siop_cmd_wait = saved_cmd_wait;
    343 		siop_data_wait = saved_data_wait;
    344 	}
    345 }
    346 
    347 static int initialized[NSIOP];
    348 
    349 #ifdef DEBUG
    350 /*	0x01 - full debug	*/
    351 /*	0x02 - DMA chaining	*/
    352 /*	0x04 - siopintr		*/
    353 /*	0x08 - phase mismatch	*/
    354 int	siop_debug = 0;
    355 int	siopsync_debug = 0;
    356 int	siopdma_hits = 0;
    357 int	siopdma_misses = 0;
    358 #endif
    359 
    360 static void
    361 siopabort(dev, regs, where)
    362 	register struct siop_softc *dev;
    363 	volatile register siop_regmap_t *regs;
    364 	char *where;
    365 {
    366 
    367 	printf ("siop%d: abort %s: dstat %02x, sstat0 %02x sbcl %02x\n",
    368 	    dev->sc_ac->amiga_unit,
    369 	    where, regs->siop_dstat, regs->siop_sstat0, regs->siop_sbcl);
    370 
    371 	if (dev->sc_flags & SIOP_SELECTED) {
    372 #ifdef TODO
    373       SET_SBIC_cmd (regs, SBIC_CMD_ABORT);
    374       WAIT_CIP (regs);
    375 
    376       GET_SBIC_asr (regs, asr);
    377       if (asr & (SBIC_ASR_BSY|SBIC_ASR_LCI))
    378         {
    379           /* ok, get more drastic.. */
    380 
    381 	  SET_SBIC_cmd (regs, SBIC_CMD_RESET);
    382 	  DELAY(25);
    383 	  SBIC_WAIT(regs, SBIC_ASR_INT, 0);
    384 	  GET_SBIC_csr (regs, csr);       /* clears interrupt also */
    385 
    386           dev->sc_flags &= ~SIOP_SELECTED;
    387           return;
    388         }
    389 
    390       do
    391         {
    392           SBIC_WAIT (regs, SBIC_ASR_INT, 0);
    393           GET_SBIC_csr (regs, csr);
    394         }
    395       while ((csr != SBIC_CSR_DISC) && (csr != SBIC_CSR_DISC_1)
    396 	      && (csr != SBIC_CSR_CMD_INVALID));
    397 #endif
    398 
    399 		/* lets just hope it worked.. */
    400 		dev->sc_flags &= ~SIOP_SELECTED;
    401 	}
    402 }
    403 
    404 #if NZEUSSCSI > 0
    405 int
    406 zeusscsiinit(ac)
    407 	register struct amiga_ctlr *ac;
    408 {
    409 	register struct siop_softc *dev = &siop_softc[ac->amiga_unit];
    410 
    411 #ifdef DEBUG
    412 	if (siop_debug)
    413 		printf ("zeusscsiinit: addr %x unit %d scripts %x ds %x\n",
    414 		    ac->amiga_addr, ac->amiga_unit, scripts, &dev->sc_ds);
    415 #endif
    416 	if ((int) scripts & 3)
    417   		panic ("zeusscsiinit: scripts not on a longword boundary");
    418 	if ((long)&dev->sc_ds & 3)
    419 		panic("zeusscsiinit: data storage alignment error\n");
    420 	if (! ac->amiga_addr)
    421 		return 0;
    422 
    423 	if (initialized[ac->amiga_unit])
    424 		return 0;
    425 
    426 	initialized[ac->amiga_unit] = 1;
    427 
    428 	/* advance ac->amiga_addr to point to the real siop-registers */
    429 	ac->amiga_addr = (caddr_t) ((int)ac->amiga_addr + 0x4000);
    430 	dev->sc_clock_freq = 0xc0;
    431 
    432 	/* hardwired IPL */
    433 	ac->amiga_ipl = 6;
    434 	dev->sc_ac = ac;
    435 	dev->sc_dq.dq_driver = &zeusscsidriver;
    436 	dev->sc_sq.dq_forw = dev->sc_sq.dq_back = &dev->sc_sq;
    437 	siopreset (ac->amiga_unit);
    438 
    439 	/* For the ZEUS SCSI, both IPL6 and IPL2 interrupts have to be
    440 	   enabled.  The ZEUS SCSI generates IPL6 interrupts, which are
    441 	   not blocked by splbio().  The ZEUS interrupt handler saves the
    442 	   siop interrupt status information in siop_softc and sets the
    443 	   PORTS interrupt to process the interrupt at IPL2.
    444 
    445 	   make sure IPL2 interrupts are delivered to the cpu when siopintr6
    446 	   generates some. Note that this does not yet enable siop-interrupts,
    447 	   this is handled in siopgo, which selectively enables interrupts only
    448 	   while DMA requests are pending.
    449 
    450 	   Note that enabling PORTS interrupts also enables keyboard interrupts
    451 	   as soon as the corresponding int-enable bit in CIA-A is set. */
    452 
    453 #if 0	/* EXTER interrupts are enabled in the clock initialization */
    454 	custom.intreq = INTF_EXTER;
    455 	custom.intena = INTF_SETCLR | INTF_EXTER;
    456 #endif
    457 	custom.intreq = INTF_PORTS;
    458 	custom.intena = INTF_SETCLR | INTF_PORTS;
    459 	return(1);
    460 }
    461 #endif
    462 
    463 #if NMAGNUMSCSI > 0
    464 int
    465 magnumscsiinit(ac)
    466 	register struct amiga_ctlr *ac;
    467 {
    468 	register struct siop_softc *dev = &siop_softc[ac->amiga_unit];
    469 
    470 #ifdef DEBUG
    471 	if (siop_debug)
    472 		printf ("magnumscsiinit: addr %x unit %d scripts %x ds %x\n",
    473 		    ac->amiga_addr, ac->amiga_unit, scripts, &dev->sc_ds);
    474 #endif
    475 	if ((int) scripts & 3)
    476   		panic ("magnumscsiinit: scripts not on a longword boundary");
    477 	if ((long)&dev->sc_ds & 3)
    478 		panic("magnumscsiinit: data storage alignment error\n");
    479 	if (! ac->amiga_addr)
    480 		return 0;
    481 
    482 	if (initialized[ac->amiga_unit])
    483 		return 0;
    484 
    485 	initialized[ac->amiga_unit] = 1;
    486 
    487 	/* advance ac->amiga_addr to point to the real siop-registers */
    488 	ac->amiga_addr = (caddr_t) ((int)ac->amiga_addr + 0x8000);
    489 	dev->sc_clock_freq = 0x40;	/* DCNTL = 25.01->37.5MHZ / SCLK/1.5 */
    490 
    491 	/* hardwired IPL */
    492 	ac->amiga_ipl = 2;
    493 	dev->sc_ac = ac;
    494 	dev->sc_dq.dq_driver = &magnumscsidriver;
    495 	dev->sc_sq.dq_forw = dev->sc_sq.dq_back = &dev->sc_sq;
    496 	siopreset (ac->amiga_unit);
    497 
    498 	/* make sure IPL2 interrupts are delivered to the cpu when the siop
    499 	   generates some. Note that this does not yet enable siop-interrupts,
    500 	   this is handled in siopgo, which selectively enables interrupts only
    501 	   while DMA requests are pending.
    502 
    503 	   Note that enabling PORTS interrupts also enables keyboard interrupts
    504 	   as soon as the corresponding int-enable bit in CIA-A is set. */
    505 
    506 	custom.intreq = INTF_PORTS;
    507 	custom.intena = INTF_SETCLR | INTF_PORTS;
    508 	return(1);
    509 }
    510 #endif
    511 
    512 
    513 void
    514 siopreset(unit)
    515 	register int unit;
    516 {
    517 	register struct siop_softc *dev = &siop_softc[unit];
    518 	volatile register siop_regmap_t *regs =
    519 				(siop_regmap_t *)dev->sc_ac->amiga_addr;
    520 	u_int i, s;
    521 	u_char  my_id, csr;
    522 
    523 	if (dev->sc_flags & SIOP_ALIVE)
    524 		siopabort(dev, regs, "reset");
    525 
    526 	printf("siop%d: ", unit);
    527 
    528 	s = splbio();
    529 	my_id = 7;
    530 
    531 	/*
    532 	 * Reset the chip
    533 	 * XXX - is this really needed?
    534 	 */
    535 	regs->siop_sien &= ~SIOP_SIEN_RST;
    536 	regs->siop_scntl1 |= SIOP_SCNTL1_RST;
    537 	for (i = 0; i < 1000; ++i)
    538 		;
    539 	regs->siop_scntl1 &= ~SIOP_SCNTL1_RST;
    540 	regs->siop_sien |= SIOP_SIEN_RST;
    541 
    542 	/*
    543 	 * Set up various chip parameters
    544 	 */
    545 	regs->siop_istat = 0x40;
    546 	for (i = 0; i < 1000; ++i)
    547 		;
    548 	regs->siop_istat = 0x00;
    549 	regs->siop_scntl0 = SIOP_ARB_FULL | SIOP_SCNTL0_EPC | SIOP_SCNTL0_EPG;
    550 	regs->siop_dcntl = dev->sc_clock_freq;
    551 	regs->siop_dmode = 0x80;
    552 	regs->siop_sien = 0x00;	/* don't enable interrupts yet */
    553 	regs->siop_dien = 0x00;	/* don't enable interrupts yet */
    554 	regs->siop_scid = 1 << my_id;
    555 	regs->siop_dwt = 0x00;
    556 	regs->siop_ctest0 |= 0x20;	/* Enable Active Negation ?? */
    557 	regs->siop_ctest7 |= 0x02;	/* TT1 */
    558 
    559 	/* will need to re-negotiate sync xfers */
    560 	bzero(&dev->sc_sync, sizeof (dev->sc_sync));
    561 
    562 	splx (s);
    563 
    564 	printf("siop id %d\n", my_id);
    565 	dev->sc_flags |= SIOP_ALIVE;
    566 	dev->sc_flags &= ~(SIOP_SELECTED | SIOP_DMA);
    567 }
    568 
    569 /*
    570  * Setup Data Storage for 53C710 and start SCRIPTS processing
    571  */
    572 
    573 static void
    574 siop_setup (dev, target, cbuf, clen, buf, len)
    575 	struct siop_softc *dev;
    576 	int target;
    577 	u_char *cbuf;
    578 	int clen;
    579 	u_char *buf;
    580 	int len;
    581 {
    582 	volatile register siop_regmap_t *regs =
    583 		(siop_regmap_t *)dev->sc_ac->amiga_addr;
    584 	int i;
    585 	int nchain;
    586 	int count, tcount;
    587 	char *addr, *dmaend;
    588 
    589 	dev->sc_istat = 0;
    590 	dev->sc_lun = 0x80;			/* XXX */
    591 	dev->sc_stat[0] = -1;
    592 	dev->sc_msg[0] = -1;
    593 	dev->sc_ds.scsi_addr = (0x10000 << target) | (dev->sc_sync[target].period << 8);
    594 	dev->sc_ds.idlen = 1;
    595 	dev->sc_ds.idbuf = (char *) kvtop(&dev->sc_lun);
    596 	dev->sc_ds.cmdlen = clen;
    597 	dev->sc_ds.cmdbuf = (char *) kvtop(cbuf);
    598 	dev->sc_ds.stslen = 1;
    599 	dev->sc_ds.stsbuf = (char *) kvtop(&dev->sc_stat[0]);
    600 	dev->sc_ds.msglen = 1;
    601 	dev->sc_ds.msgbuf = (char *) kvtop(&dev->sc_msg[0]);
    602 	dev->sc_ds.sdtrolen = 0;
    603 	dev->sc_ds.sdtrilen = 0;
    604 	dev->sc_ds.chain[0].datalen = len;
    605 	dev->sc_ds.chain[0].databuf = (char *) kvtop(buf);
    606 
    607 	if (dev->sc_sync[target].state == SYNC_START) {
    608 		if (siop_inhibit_sync[dev->sc_ac->amiga_unit][target]) {
    609 			dev->sc_sync[target].state = SYNC_DONE;
    610 			dev->sc_sync[target].offset = 0;
    611 			dev->sc_sync[target].period = 0;
    612 #ifdef DEBUG
    613 			if (siopsync_debug)
    614 				printf ("Forcing target %d asynchronous\n", target);
    615 #endif
    616 		}
    617 		else {
    618 			dev->sc_msg[1] = MSG_IDENTIFY;
    619 			dev->sc_msg[2] = MSG_EXT_MESSAGE;
    620 			dev->sc_msg[3] = 3;
    621 			dev->sc_msg[4] = MSG_SYNC_REQ;
    622 			dev->sc_msg[5] = 100/4;		/* min period = 100 nsec */
    623 			dev->sc_msg[6] = SIOP_MAX_OFFSET;
    624 			dev->sc_ds.sdtrolen = 6;
    625 			dev->sc_ds.sdtrilen = sizeof (dev->sc_msg) - 1;
    626 			dev->sc_ds.sdtrobuf = dev->sc_ds.sdtribuf = (char *) kvtop(dev->sc_msg + 1);
    627 			dev->sc_sync[target].state = SYNC_SENT;
    628 #ifdef DEBUG
    629 			if (siopsync_debug)
    630 				printf ("Sending sync request to target %d\n", target);
    631 #endif
    632 		}
    633 	}
    634 
    635 /*
    636  * If length is > 1 page, check for consecutive physical pages
    637  * Need to set up chaining if not
    638  */
    639 	nchain = 0;
    640 	count = len;
    641 	addr = buf;
    642 	dmaend = NULL;
    643 	while (count > 0) {
    644 		dev->sc_ds.chain[nchain].databuf = (char *) kvtop (addr);
    645 		if (count < (tcount = NBPG - ((int) addr & PGOFSET)))
    646 			tcount = count;
    647 		dev->sc_ds.chain[nchain].datalen = tcount;
    648 		addr += tcount;
    649 		count -= tcount;
    650 		if (dev->sc_ds.chain[nchain].databuf == dmaend) {
    651 			dmaend += dev->sc_ds.chain[nchain].datalen;
    652 			dev->sc_ds.chain[--nchain].datalen += tcount;
    653 #ifdef DEBUG
    654 			++siopdma_hits;
    655 #endif
    656 		}
    657 		else {
    658 			dmaend = dev->sc_ds.chain[nchain].databuf +
    659 			    dev->sc_ds.chain[nchain].datalen;
    660 			dev->sc_ds.chain[nchain].datalen = tcount;
    661 #ifdef DEBUG
    662 			++siopdma_misses;
    663 #endif
    664 		}
    665 		++nchain;
    666 	}
    667 #ifdef DEBUG
    668 	if (nchain != 1 && len != 0 && siop_debug & 3) {
    669 		printf ("DMA chaining set: %d\n", nchain);
    670 		for (i = 0; i < nchain; ++i) {
    671 			printf ("  [%d] %8x %4x\n", i, dev->sc_ds.chain[i].databuf,
    672 			    dev->sc_ds.chain[i].datalen);
    673 		}
    674 	}
    675 #endif
    676 
    677 	regs->siop_sbcl = dev->sc_sync[target].offset;
    678 	if (dev->sc_ds.sdtrolen)
    679 		regs->siop_scratch = regs->siop_scratch | 0x100;
    680 	else
    681 		regs->siop_scratch = regs->siop_scratch & ~0xff00;
    682 	regs->siop_dsa = (long) kvtop(&dev->sc_ds);
    683 	DCIS();				/* push data cache */
    684 	regs->siop_dsp = (long) kvtop(scripts);
    685 }
    686 
    687 /*
    688  * Process a DMA or SCSI interrupt from the 53C710 SIOP
    689  */
    690 
    691 static int
    692 siop_checkintr(dev, istat, dstat, sstat0, status)
    693 	struct	siop_softc *dev;
    694 	u_char	istat;
    695 	u_char	dstat;
    696 	u_char	sstat0;
    697 	int	*status;
    698 {
    699 	volatile register siop_regmap_t *regs =
    700 		(siop_regmap_t *)dev->sc_ac->amiga_addr;
    701 	int	target;
    702 
    703 	regs->siop_ctest8 |= 0x04;
    704 	while ((regs->siop_ctest1 & SIOP_CTEST1_FMT) == 0)
    705 		;
    706 	regs->siop_ctest8 &= ~0x04;
    707 #ifdef DEBUG
    708 	if (siop_debug & 1) {
    709 		DCIAS(kvtop(&dev->sc_stat));	/* XXX */
    710 		printf ("siopchkintr: istat %x dstat %x sstat0 %x dsps %x sbcl %x sts %x msg %x\n",
    711 		    istat, dstat, sstat0, regs->siop_dsps, regs->siop_sbcl, dev->sc_stat[0], dev->sc_msg[0]);
    712 	}
    713 #endif
    714 	if (dstat & SIOP_DSTAT_SIR && (regs->siop_dsps == 0xff00 ||
    715 	    regs->siop_dsps == 0xfffc)) {
    716 		/* Normal completion status, or check condition */
    717 		if (regs->siop_dsa != (long) kvtop(&dev->sc_ds)) {
    718 			printf ("siop: invalid dsa: %x %x\n", regs->siop_dsa,
    719 			    kvtop(&dev->sc_ds));
    720 			panic("*** siop DSA invalid ***");
    721 		}
    722 		target = dev->sc_slave;
    723 		if (dev->sc_sync[target].state == SYNC_SENT) {
    724 #ifdef DEBUG
    725 			if (siopsync_debug)
    726 				printf ("sync msg in: %02x %02x %02x %02x %02x %02x\n",
    727 				    dev->sc_msg[1], dev->sc_msg[2], dev->sc_msg[3],
    728 				    dev->sc_msg[4], dev->sc_msg[5], dev->sc_msg[6]);
    729 #endif
    730 			dev->sc_sync[target].state = SYNC_DONE;
    731 			dev->sc_sync[target].period = 0;
    732 			dev->sc_sync[target].offset = 0;
    733 			if (dev->sc_msg[1] == MSG_EXT_MESSAGE &&
    734 			    dev->sc_msg[2] == 3 &&
    735 			    dev->sc_msg[3] == MSG_SYNC_REQ) {
    736 				printf ("siop%d: target %d now synchronous, period=%dns, offset=%d\n",
    737 				    dev->sc_ac->amiga_unit, target,
    738 				    dev->sc_msg[4] * 4, dev->sc_msg[5]);
    739 				scsi_period_to_siop (dev, target);
    740 			}
    741 		}
    742 		DCIAS(kvtop(&dev->sc_stat));	/* XXX */
    743 		*status = dev->sc_stat[0];
    744 		return 1;
    745 	}
    746 	if (sstat0 & SIOP_SSTAT0_M_A) {		/* Phase mismatch */
    747 #ifdef DEBUG
    748 		if (siop_debug & 9)
    749 			printf ("Phase mismatch: %x dsp +%x\n", regs->siop_sbcl,
    750 			    regs->siop_dsp - kvtop(scripts));
    751 #endif
    752 		if ((regs->siop_sbcl & SIOP_REQ) == 0)
    753 			printf ("Phase mismatch: REQ not asserted! %02x\n",
    754 			    regs->siop_sbcl);
    755 		switch (regs->siop_sbcl & 7) {
    756 /*
    757  * For data out and data in phase, check for DMA chaining
    758  */
    759 
    760 /*
    761  * for message in, check for possible reject for sync request
    762  */
    763 		case 0:
    764 			regs->siop_dsp = kvtop(scripts) + Ent_dataout;
    765 			break;
    766 		case 1:
    767 			regs->siop_dsp = kvtop(scripts) + Ent_datain;
    768 			break;
    769 		case 2:
    770 			regs->siop_dsp = kvtop(scripts) + Ent_cmd;
    771 			break;
    772 		case 3:
    773 			regs->siop_dsp = kvtop(scripts) + Ent_status;
    774 			break;
    775 		case 6:
    776 			regs->siop_dsp = kvtop(scripts) + Ent_msgout;
    777 			break;
    778 		case 7:
    779 			regs->siop_dsp = kvtop(scripts) + Ent_msgin;
    780 			break;
    781 		default:
    782 			goto bad_phase;
    783 		}
    784 		return 0;
    785 	}
    786 	if (sstat0 & SIOP_SSTAT0_STO) {		/* Select timed out */
    787 		*status = -1;
    788 		return 1;
    789 	}
    790 	if (dstat & SIOP_DSTAT_SIR && regs->siop_dsps == 0xff05 &&
    791 	    (regs->siop_sbcl & (SIOP_MSG | SIOP_CD)) == 0) {
    792 		printf ("DMA chaining failed\n");
    793 		siopreset (dev->sc_ac->amiga_unit);
    794 		*status = -1;
    795 		return 1;
    796 	}
    797 	if (dstat & SIOP_DSTAT_SIR && regs->siop_dsps == 0xff27) {
    798 #ifdef DEBUG
    799 		if (siop_debug & 3)
    800 			printf ("DMA chaining completed: dsa %x dnad %x addr %x\n",
    801 				regs->siop_dsa,	regs->siop_dnad, regs->siop_addr);
    802 #endif
    803 		regs->siop_dsa = kvtop (&dev->sc_ds);
    804 		regs->siop_dsp = kvtop (scripts) + Ent_status;
    805 		return 0;
    806 	}
    807 	target = dev->sc_slave;
    808 	if (dstat & SIOP_DSTAT_SIR && regs->siop_dsps == 0xff26 &&
    809 	    dev->sc_msg[0] == MSG_REJECT && dev->sc_sync[target].state == SYNC_SENT) {
    810 		dev->sc_sync[target].state = SYNC_DONE;
    811 		dev->sc_sync[target].period = 0;
    812 		dev->sc_sync[target].offset = 0;
    813 		dev->sc_ds.sdtrolen = 0;
    814 		dev->sc_ds.sdtrilen = 0;
    815 #ifdef DEBUG
    816 		if (siopsync_debug || 1)
    817 			printf ("target %d rejected sync, going asynchronous\n", target);
    818 #endif
    819 		siop_inhibit_sync[dev->sc_ac->amiga_unit][target] = -1;
    820 		if ((regs->siop_sbcl & 7) == 6) {
    821 			regs->siop_dsp = kvtop(scripts) + Ent_msgout;
    822 			return (0);
    823 		}
    824 	}
    825 	if (sstat0 == 0 && dstat & SIOP_DSTAT_SIR) {
    826 		DCIAS(kvtop(&dev->sc_stat));
    827 		printf ("SIOP interrupt: %x sts %x msg %x sbcl %x\n",
    828 		    regs->siop_dsps, dev->sc_stat[0], dev->sc_msg[0],
    829 		    regs->siop_sbcl);
    830 		siopreset (dev->sc_ac->amiga_unit);
    831 		*status = -1;
    832 		return 1;
    833 	}
    834 bad_phase:
    835 /*
    836  * temporary panic for unhandled conditions
    837  * displays various things about the 53C710 status and registers
    838  * then panics
    839  */
    840 printf ("siopchkintr: target %x ds %x\n", target, &dev->sc_ds);
    841 printf ("scripts %x ds %x regs %x dsp %x dcmd %x\n", kvtop(scripts),
    842     kvtop(&dev->sc_ds), kvtop(regs), regs->siop_dsp, *((long *)&regs->siop_dcmd));
    843 printf ("siopchkintr: istat %x dstat %x sstat0 %x dsps %x dsa %x sbcl %x sts %x msg %x\n",
    844     istat, dstat, sstat0, regs->siop_dsps, regs->siop_dsa, regs->siop_sbcl,
    845     dev->sc_stat[0], dev->sc_msg[0]);
    846 panic("siopchkintr: **** temp ****");
    847 }
    848 
    849 /*
    850  * SCSI 'immediate' command:  issue a command to some SCSI device
    851  * and get back an 'immediate' response (i.e., do programmed xfer
    852  * to get the response data).  'cbuf' is a buffer containing a scsi
    853  * command of length clen bytes.  'buf' is a buffer of length 'len'
    854  * bytes for data.  The transfer direction is determined by the device
    855  * (i.e., by the scsi bus data xfer phase).  If 'len' is zero, the
    856  * command must supply no data.  'xferphase' is the bus phase the
    857  * caller expects to happen after the command is issued.  It should
    858  * be one of DATA_IN_PHASE, DATA_OUT_PHASE or STATUS_PHASE.
    859  *
    860  * XXX - 53C710 will use DMA, but no interrupts (it's a heck of a
    861  * lot easier to do than to use programmed I/O).
    862  *
    863  */
    864 static int
    865 siopicmd(dev, target, cbuf, clen, buf, len)
    866 	struct siop_softc *dev;
    867 	int target;
    868 	u_char *cbuf;
    869 	int clen;
    870 	u_char *buf;
    871 	int len;
    872 {
    873 	volatile register siop_regmap_t *regs =
    874 		(siop_regmap_t *)dev->sc_ac->amiga_addr;
    875 	int i;
    876 	int status;
    877 	u_char istat;
    878 	u_char dstat;
    879 	u_char sstat0;
    880 
    881 	if (dev->sc_flags & SIOP_SELECTED) {
    882 		printf ("siopicmd%d: bus busy\n", target);
    883 		return -1;
    884 	}
    885 	regs->siop_sien = 0x00;		/* disable SCSI and DMA interrupts */
    886 	regs->siop_dien = 0x00;
    887 	dev->sc_flags |= SIOP_SELECTED;
    888 	dev->sc_slave = target;
    889 #ifdef DEBUG
    890 	if (siop_debug & 1)
    891 		printf ("siopicmd: target %x cmd %02x ds %x\n", target,
    892 		    cbuf[0], &dev->sc_ds);
    893 #endif
    894 	siop_setup (dev, target, cbuf, clen, buf, len);
    895 
    896 	for (;;) {
    897 		/* use cmd_wait values? */
    898 		i = siop_cmd_wait << 1;
    899 		while (((istat = regs->siop_istat) &
    900 		    (SIOP_ISTAT_SIP | SIOP_ISTAT_DIP)) == 0) {
    901 			if (--i <= 0) {
    902 				printf ("waiting: tgt %d cmd %02x sbcl %02x dsp %x (+%x) dcmd %x ds %x\n",
    903 				    target, cbuf[0],
    904 				    regs->siop_sbcl, regs->siop_dsp,
    905 				    regs->siop_dsp - kvtop(scripts),
    906 				    *((long *)&regs->siop_dcmd), &dev->sc_ds);
    907 				i = siop_cmd_wait << 2;
    908 			}
    909 			DELAY(1);
    910 		}
    911 		dstat = regs->siop_dstat;
    912 		sstat0 = regs->siop_sstat0;
    913 #ifdef DEBUG
    914 		if (siop_debug & 1) {
    915 			DCIAS(kvtop(&dev->sc_stat));	/* XXX should just invalidate dev->sc_stat */
    916 			printf ("siopicmd: istat %x dstat %x sstat0 %x dsps %x sbcl %x sts %x msg %x\n",
    917 			    istat, dstat, sstat0, regs->siop_dsps, regs->siop_sbcl,
    918 			    dev->sc_stat[0], dev->sc_msg[0]);
    919 		}
    920 #endif
    921 		if (siop_checkintr(dev, istat, dstat, sstat0, &status)) {
    922 			dev->sc_flags &= ~SIOP_SELECTED;
    923 			return (status);
    924 		}
    925 	}
    926 }
    927 
    928 int
    929 siop_test_unit_rdy(ctlr, slave, unit)
    930 	int ctlr, slave, unit;
    931 {
    932 	register struct siop_softc *dev = &siop_softc[ctlr];
    933 	static struct scsi_cdb6 cdb = { CMD_TEST_UNIT_READY };
    934 
    935 	cdb.lun = unit;
    936 	return (siopicmd(dev, slave, (u_char *)&cdb, sizeof(cdb), (u_char *)0, 0));
    937 }
    938 
    939 int
    940 siop_start_stop_unit (ctlr, slave, unit, start)
    941 	int ctlr, slave, unit;
    942 {
    943 	register struct siop_softc *dev = &siop_softc[ctlr];
    944 	static struct scsi_cdb6 cdb = { CMD_LOADUNLOAD };
    945 
    946 	cdb.lun = unit;
    947 	/* we don't set the immediate bit, so we wait for the
    948 	   command to succeed.
    949 	   We also don't touch the LoEj bit, which is primarily meant
    950 	   for floppies. */
    951 	cdb.len = start & 0x01;
    952 	return (siopicmd(dev, slave, (u_char *)&cdb, sizeof(cdb), (u_char *)0, 0));
    953 }
    954 
    955 
    956 int
    957 siop_request_sense(ctlr, slave, unit, buf, len)
    958 	int ctlr, slave, unit;
    959 	u_char *buf;
    960 	unsigned len;
    961 {
    962 	register struct siop_softc *dev = &siop_softc[ctlr];
    963 	static struct scsi_cdb6 cdb = { CMD_REQUEST_SENSE };
    964 
    965 	cdb.lun = unit;
    966 	cdb.len = len;
    967 	return (siopicmd(dev, slave, (u_char *)&cdb, sizeof(cdb), buf, len));
    968 }
    969 
    970 int
    971 siop_immed_command(ctlr, slave, unit, cdb, buf, len, rd)
    972 	int ctlr, slave, unit;
    973 	struct scsi_fmt_cdb *cdb;
    974 	u_char *buf;
    975 	unsigned len;
    976 {
    977 	register struct siop_softc *dev = &siop_softc[ctlr];
    978 
    979 	cdb->cdb[1] |= (unit << 5);
    980 	return (siopicmd(dev, slave, (u_char *) cdb->cdb, cdb->len, buf, len));
    981 }
    982 
    983 /*
    984  * The following routines are test-and-transfer i/o versions of read/write
    985  * for things like reading disk labels and writing core dumps.  The
    986  * routine scsigo should be used for normal data transfers, NOT these
    987  * routines.
    988  */
    989 int
    990 siop_tt_read(ctlr, slave, unit, buf, len, blk, bshift)
    991 	int ctlr, slave, unit;
    992 	u_char *buf;
    993 	u_int len;
    994 	daddr_t blk;
    995 	int bshift;
    996 {
    997 	register struct siop_softc *dev = &siop_softc[ctlr];
    998 	struct scsi_cdb10 cdb;
    999 	int stat;
   1000 	int old_wait = siop_data_wait;
   1001 
   1002 #ifdef DEBUG
   1003 	if (siop_debug & 1)
   1004 		printf ("siop%d: tt_read blk %x\n", slave, blk);
   1005 #endif
   1006 	siop_data_wait = 300000;
   1007 	bzero(&cdb, sizeof(cdb));
   1008 	cdb.cmd = CMD_READ_EXT;
   1009 	cdb.lun = unit;
   1010 	blk >>= bshift;
   1011 	cdb.lbah = blk >> 24;
   1012 	cdb.lbahm = blk >> 16;
   1013 	cdb.lbalm = blk >> 8;
   1014 	cdb.lbal = blk;
   1015 	cdb.lenh = len >> (8 + DEV_BSHIFT + bshift);
   1016 	cdb.lenl = len >> (DEV_BSHIFT + bshift);
   1017 	stat = siopicmd(dev, slave, (u_char *) &cdb, sizeof(cdb), buf, len);
   1018 	siop_data_wait = old_wait;
   1019 	return (stat);
   1020 }
   1021 
   1022 int
   1023 siop_tt_write(ctlr, slave, unit, buf, len, blk, bshift)
   1024 	int ctlr, slave, unit;
   1025 	u_char *buf;
   1026 	u_int len;
   1027 	daddr_t blk;
   1028 	int bshift;
   1029 {
   1030 	register struct siop_softc *dev = &siop_softc[ctlr];
   1031 	struct scsi_cdb10 cdb;
   1032 	int stat;
   1033 	int old_wait = siop_data_wait;
   1034 
   1035 #ifdef DEBUG
   1036 	if (siop_debug)
   1037 		printf ("siop%d: tt_write blk %d from %08x\n", slave,
   1038 		   blk, kvtop(buf));
   1039 	if (blk < 604)
   1040 		panic("siop_tt_write: writing block < 604");
   1041 #endif
   1042 	siop_data_wait = 300000;
   1043 
   1044 	bzero(&cdb, sizeof(cdb));
   1045 	cdb.cmd = CMD_WRITE_EXT;
   1046 	cdb.lun = unit;
   1047 	blk >>= bshift;
   1048 	cdb.lbah = blk >> 24;
   1049 	cdb.lbahm = blk >> 16;
   1050 	cdb.lbalm = blk >> 8;
   1051 	cdb.lbal = blk;
   1052 	cdb.lenh = len >> (8 + DEV_BSHIFT + bshift);
   1053 	cdb.lenl = len >> (DEV_BSHIFT + bshift);
   1054 	stat = siopicmd(dev, slave, (u_char *) &cdb, sizeof(cdb), buf, len);
   1055 	siop_data_wait = old_wait;
   1056 	return (stat);
   1057 }
   1058 
   1059 int
   1060 siopreq(dq)
   1061 	register struct devqueue *dq;
   1062 {
   1063 	register struct devqueue *hq;
   1064 
   1065 	hq = &siop_softc[dq->dq_ctlr].sc_sq;
   1066 	insque(dq, hq->dq_back);
   1067 #ifdef DEBUG
   1068 	if (siop_debug & 1)
   1069 		printf ("siopreq %d ", dq->dq_back == hq ? 1 : 0);
   1070 #endif
   1071 	if (dq->dq_back == hq)
   1072 		return(1);
   1073 	return(0);
   1074 }
   1075 
   1076 int
   1077 siopustart (int unit)
   1078 {
   1079 	register struct siop_softc *dev = &siop_softc[unit];
   1080 
   1081 #ifdef DEBUG
   1082 	if (siop_debug & 1)
   1083 		printf ("siop%d: ustart ", unit);
   1084 #endif
   1085 	return(1);
   1086 }
   1087 
   1088 void
   1089 siopstart (int unit)
   1090 {
   1091 	register struct devqueue *dq;
   1092 
   1093 #ifdef DEBUG
   1094 	if (siop_debug & 1)
   1095 		printf ("siop%d: start ", unit);
   1096 #endif
   1097 	dq = siop_softc[unit].sc_sq.dq_forw;
   1098 	(dq->dq_driver->d_go)(dq->dq_unit);
   1099 }
   1100 
   1101 int
   1102 siopgo(ctlr, slave, unit, bp, cdb, pad)
   1103 	int ctlr, slave, unit;
   1104 	struct buf *bp;
   1105 	struct scsi_fmt_cdb *cdb;
   1106 	int pad;
   1107 {
   1108 	register struct siop_softc *dev = &siop_softc[ctlr];
   1109 	volatile register siop_regmap_t *regs =
   1110 			(siop_regmap_t *)dev->sc_ac->amiga_addr;
   1111 	int i;
   1112 	int nchain;
   1113 	int count, tcount;
   1114 	char *addr, *dmaend;
   1115 
   1116 #ifdef DEBUG
   1117 	if (siop_debug & 1)
   1118 		printf ("siop%d: go ", slave);
   1119 	if ((cdb->cdb[1] & 1) == 0 &&
   1120 	    ((cdb->cdb[0] == CMD_WRITE && cdb->cdb[2] == 0 && cdb->cdb[3] == 0) ||
   1121 	    (cdb->cdb[0] == CMD_WRITE_EXT && cdb->cdb[2] == 0 && cdb->cdb[3] == 0
   1122 	    && cdb->cdb[4] == 0)))
   1123 		panic ("siopgo: attempted write to block < 0x100");
   1124 #endif
   1125 	cdb->cdb[1] |= unit << 5;
   1126 
   1127 	if (dev->sc_flags & SIOP_SELECTED) {
   1128 		printf ("siopgo%d: bus busy\n", slave);
   1129 		return 1;
   1130 	}
   1131 
   1132 	if (siop_no_dma) {
   1133 		register struct devqueue *dq;
   1134 
   1135 		/* in this case do the transfer with programmed I/O :-( This is
   1136 		probably still faster than doing the transfer with DMA into a
   1137 		buffer and copying it later to its final destination, comments? */
   1138 		/* XXX - 53C710 uses DMA, but non-interrupt */
   1139 		siopicmd (dev, slave, (u_char *) cdb->cdb, cdb->len,
   1140 			bp->b_un.b_addr, bp->b_bcount);
   1141 
   1142 		dq = dev->sc_sq.dq_forw;
   1143 		(dq->dq_driver->d_intr)(dq->dq_unit, dev->sc_stat[0]);
   1144 		return dev->sc_stat[0];
   1145 	}
   1146 
   1147 	dev->sc_flags |= SIOP_SELECTED | SIOP_DMA;
   1148 	dev->sc_slave = slave;
   1149 	/* enable SCSI and DMA interrupts */
   1150 	regs->siop_sien = SIOP_SIEN_M_A | SIOP_SIEN_STO | SIOP_SIEN_SEL | SIOP_SIEN_SGE |
   1151 	    SIOP_SIEN_UDC | SIOP_SIEN_RST | SIOP_SIEN_PAR;
   1152 	regs->siop_dien = 0x20 | SIOP_DIEN_ABRT | SIOP_DIEN_SIR | SIOP_DIEN_WTD |
   1153 	    SIOP_DIEN_OPC;
   1154 #ifdef DEBUG
   1155 	if (siop_debug & 1)
   1156 		printf ("siopgo: target %x cmd %02x ds %x\n", slave, cdb->cdb[0], &dev->sc_ds);
   1157 #endif
   1158 
   1159 	siop_setup(dev, slave, cdb->cdb, cdb->len, bp->b_un.b_addr, bp->b_bcount);
   1160 
   1161 	return (0);
   1162 }
   1163 
   1164 void
   1165 siopdone (int unit)
   1166 {
   1167 	volatile register siop_regmap_t *regs =
   1168 			(siop_regmap_t *)siop_softc[unit].sc_ac->amiga_addr;
   1169 
   1170 #ifdef DEBUG
   1171 	if (siop_debug & 1)
   1172 		printf("siop%d: done called!\n", unit);
   1173 #endif
   1174 }
   1175 
   1176 /*
   1177  * Level 6 interrupt processing for the Progressive Peripherals Inc
   1178  * Zeus SCSI.  Because the level 6 interrupt is above splbio, the
   1179  * interrupt status is saved and the INTF_PORTS interrupt is set.
   1180  * This way, the actual processing of the interrupt can be deferred
   1181  * until splbio is unblocked
   1182  */
   1183 
   1184 #if NZEUSSCSI > 0
   1185 int
   1186 siopintr6 ()
   1187 {
   1188 	register struct siop_softc *dev;
   1189 	volatile register siop_regmap_t *regs;
   1190 	register u_char istat;
   1191 	int unit;
   1192 	int found = 0;
   1193 
   1194 	for (unit = 0, dev = siop_softc; unit < NSIOP; unit++, dev++) {
   1195 		if (!initialized[dev->sc_ac->amiga_unit])
   1196 			continue;
   1197 		if (dev->sc_ac->amiga_ipl != 6)
   1198 			continue;
   1199 		regs = (siop_regmap_t *)dev->sc_ac->amiga_addr;
   1200 		istat = regs->siop_istat;
   1201 		if ((istat & (SIOP_ISTAT_SIP | SIOP_ISTAT_DIP)) == 0)
   1202 			continue;
   1203 		if ((dev->sc_flags & (SIOP_DMA | SIOP_SELECTED)) == SIOP_SELECTED)
   1204 			continue;	/* doing non-interrupt I/O */
   1205 		found++;
   1206 		dev->sc_istat = istat;
   1207 		dev->sc_dstat = regs->siop_dstat;
   1208 		dev->sc_sstat0 = regs->siop_sstat0;
   1209 		custom.intreq = INTF_EXTER;
   1210 		custom.intreq = INTF_SETCLR | INTF_PORTS;
   1211 	}
   1212 	return (found);
   1213 }
   1214 #endif
   1215 
   1216 /*
   1217  * Check for 53C710 interrupts
   1218  */
   1219 
   1220 int
   1221 siopintr2 ()
   1222 {
   1223 	register struct siop_softc *dev;
   1224 	volatile register siop_regmap_t *regs;
   1225 	register u_char istat, dstat, sstat0;
   1226 	register struct devqueue *dq;
   1227 	int unit;
   1228 	int status;
   1229 	int found = 0;
   1230 
   1231 	for (unit = 0, dev = siop_softc; unit < NSIOP; unit++, dev++) {
   1232 		if (!initialized[dev->sc_ac->amiga_unit])
   1233 			continue;
   1234 		regs = (siop_regmap_t *)dev->sc_ac->amiga_addr;
   1235 		if (dev->sc_ac->amiga_ipl == 6)
   1236 			istat = dev->sc_istat;
   1237 		else
   1238 			istat = regs->siop_istat;
   1239 		if ((istat & (SIOP_ISTAT_SIP | SIOP_ISTAT_DIP)) == 0)
   1240 			continue;
   1241 		if ((dev->sc_flags & (SIOP_DMA | SIOP_SELECTED)) == SIOP_SELECTED)
   1242 			continue;	/* doing non-interrupt I/O */
   1243 		/* Got a valid interrupt on this device */
   1244 		found++;
   1245 		if (dev->sc_ac->amiga_ipl == 6) {
   1246 			dstat = dev->sc_dstat;
   1247 			sstat0 = dev->sc_sstat0;
   1248 			dev->sc_istat = 0;
   1249 		}
   1250 		else {
   1251 			dstat = regs->siop_dstat;
   1252 			sstat0 = regs->siop_sstat0;
   1253 		}
   1254 #ifdef DEBUG
   1255 		if (siop_debug & 1)
   1256 			printf ("siop%d: intr istat %x dstat %x sstat0 %x\n",
   1257 			    unit, istat, dstat, sstat0);
   1258 		if ((dev->sc_flags & SIOP_DMA) == 0) {
   1259 			printf ("siop%d: spurious interrupt? istat %x dstat %x sstat0 %x\n",
   1260 			    unit, istat, dstat, sstat0);
   1261 		}
   1262 #endif
   1263 
   1264 #ifdef DEBUG
   1265 		if (siop_debug & 5) {
   1266 			DCIAS(kvtop(&dev->sc_stat));
   1267 			printf ("siopintr%d: istat %x dstat %x sstat0 %x dsps %x sbcl %x sts %x msg %x\n",
   1268 			    unit, istat, dstat, sstat0, regs->siop_dsps,
   1269 			    regs->siop_sbcl, dev->sc_stat[0], dev->sc_msg[0]);
   1270 		}
   1271 #endif
   1272 		if (siop_checkintr (dev, istat, dstat, sstat0, &status)) {
   1273 #if 1
   1274 			regs->siop_sien = 0;
   1275 			regs->siop_dien = 0;
   1276 			if (status == 0xff)
   1277 				printf ("siopintr: status == 0xff\n");
   1278 #endif
   1279 			dev->sc_flags &= ~(SIOP_DMA | SIOP_SELECTED);
   1280 			dq = dev->sc_sq.dq_forw;
   1281 			(dq->dq_driver->d_intr)(dq->dq_unit, status);
   1282 		}
   1283 	}
   1284 	return (found);
   1285 }
   1286 
   1287 void
   1288 siopfree(dq)
   1289 	register struct devqueue *dq;
   1290 {
   1291 	register struct devqueue *hq;
   1292 
   1293 #ifdef DEBUG
   1294 	if (siop_debug & 1)
   1295 		printf ("siopfree\n");
   1296 #endif
   1297 	hq = &siop_softc[dq->dq_ctlr].sc_sq;
   1298 	remque(dq);
   1299 	if ((dq = hq->dq_forw) != hq)
   1300 		(dq->dq_driver->d_start)(dq->dq_unit);
   1301 }
   1302 
   1303 /*
   1304  * (XXX) The following routine is needed for the SCSI tape driver
   1305  * to read odd-size records.
   1306  */
   1307 
   1308 /* XXX - probably not needed for the 53C710 (and not implemented yet!) */
   1309 
   1310 #if NST > 0
   1311 int
   1312 siop_tt_oddio(ctlr, slave, unit, buf, len, b_flags, freedma)
   1313 	int ctlr, slave, unit, b_flags;
   1314 	u_char *buf;
   1315 	u_int len;
   1316 {
   1317 	register struct siop_softc *dev = &siop_softc[ctlr];
   1318 	struct scsi_cdb6 cdb;
   1319 	u_char iphase;
   1320 	int stat;
   1321 
   1322 printf ("siop%d: tt_oddio\n", slave);
   1323 #if 0
   1324 	/*
   1325 	 * First free any DMA channel that was allocated.
   1326 	 * We can't use DMA to do this transfer.
   1327 	 */
   1328 	if (freedma)
   1329 		dev->dmafree(&dev->sc_dq);
   1330 	/*
   1331 	 * Initialize command block
   1332 	 */
   1333 	bzero(&cdb, sizeof(cdb));
   1334 	cdb.lun  = unit;
   1335 	cdb.lbam = (len >> 16) & 0xff;
   1336 	cdb.lbal = (len >> 8) & 0xff;
   1337 	cdb.len = len & 0xff;
   1338 	if (buf == 0) {
   1339 		cdb.cmd = CMD_SPACE;
   1340 		cdb.lun |= 0x00;
   1341 		len = 0;
   1342 		iphase = MESG_IN_PHASE;
   1343 	} else if (b_flags & B_READ) {
   1344 		cdb.cmd = CMD_READ;
   1345 		iphase = DATA_IN_PHASE;
   1346 	} else {
   1347 		cdb.cmd = CMD_WRITE;
   1348 		iphase = DATA_OUT_PHASE;
   1349 	}
   1350 	/*
   1351 	 * Perform command (with very long delays)
   1352 	 */
   1353 	scsi_delay(30000000);
   1354 	stat = siopicmd(dev, slave, (u_char *) &cdb, sizeof(cdb), buf, len, iphase);
   1355 	scsi_delay(0);
   1356 	return (stat);
   1357 #endif
   1358 	return -1;
   1359 }
   1360 #endif
   1361 #endif
   1362