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