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