Home | History | Annotate | Line # | Download | only in boot
siop.c revision 1.1.4.2
      1  1.1.4.2  mrg /*	$NetBSD: siop.c,v 1.1.4.2 2012/06/02 11:09:07 mrg Exp $	*/
      2  1.1.4.2  mrg /*
      3  1.1.4.2  mrg  * Copyright (c) 2010 KIYOHARA Takashi
      4  1.1.4.2  mrg  * All rights reserved.
      5  1.1.4.2  mrg  *
      6  1.1.4.2  mrg  * Redistribution and use in source and binary forms, with or without
      7  1.1.4.2  mrg  * modification, are permitted provided that the following conditions
      8  1.1.4.2  mrg  * are met:
      9  1.1.4.2  mrg  * 1. Redistributions of source code must retain the above copyright
     10  1.1.4.2  mrg  *    notice, this list of conditions and the following disclaimer.
     11  1.1.4.2  mrg  * 2. Redistributions in binary form must reproduce the above copyright
     12  1.1.4.2  mrg  *    notice, this list of conditions and the following disclaimer in the
     13  1.1.4.2  mrg  *    documentation and/or other materials provided with the distribution.
     14  1.1.4.2  mrg  *
     15  1.1.4.2  mrg  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     16  1.1.4.2  mrg  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     17  1.1.4.2  mrg  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     18  1.1.4.2  mrg  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
     19  1.1.4.2  mrg  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     20  1.1.4.2  mrg  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     21  1.1.4.2  mrg  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     22  1.1.4.2  mrg  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     23  1.1.4.2  mrg  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
     24  1.1.4.2  mrg  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     25  1.1.4.2  mrg  * POSSIBILITY OF SUCH DAMAGE.
     26  1.1.4.2  mrg  */
     27  1.1.4.2  mrg 
     28  1.1.4.2  mrg #include <lib/libsa/stand.h>
     29  1.1.4.2  mrg #include <lib/libkern/libkern.h>
     30  1.1.4.2  mrg 
     31  1.1.4.2  mrg #include <dev/microcode/siop/siop.out>
     32  1.1.4.2  mrg 
     33  1.1.4.2  mrg #include "boot.h"
     34  1.1.4.2  mrg #include "sdvar.h"
     35  1.1.4.2  mrg 
     36  1.1.4.2  mrg #define SIOP_DEFAULT_TARGET	7
     37  1.1.4.2  mrg 
     38  1.1.4.2  mrg #define ALLOC(T, A)	\
     39  1.1.4.2  mrg 		(T *)(((uint32_t)alloc(sizeof(T) + (A)) + (A)) & ~((A) - 1))
     40  1.1.4.2  mrg #define VTOPHYS(va)	(uint32_t)(va)
     41  1.1.4.2  mrg #define DEVTOV(pa)	(uint32_t)(pa)
     42  1.1.4.2  mrg #define wbinv(adr, siz)	_wbinv(VTOPHYS(adr), (uint32_t)(siz))
     43  1.1.4.2  mrg #define inv(adr, siz)	_inv(VTOPHYS(adr), (uint32_t)(siz))
     44  1.1.4.2  mrg 
     45  1.1.4.2  mrg /* 53c810 supports little endian */
     46  1.1.4.2  mrg #define htoc32(x)	htole32(x)
     47  1.1.4.2  mrg #define ctoh32(x)	le32toh(x)
     48  1.1.4.2  mrg 
     49  1.1.4.2  mrg static void siop_pci_reset(int);
     50  1.1.4.2  mrg 
     51  1.1.4.2  mrg static void siop_setuptables(struct siop_adapter *, struct siop_xfer *,
     52  1.1.4.2  mrg 			     struct scsi_xfer *);
     53  1.1.4.2  mrg static void siop_ma(struct siop_adapter *, struct scsi_xfer *);
     54  1.1.4.2  mrg static void siop_sdp(struct siop_adapter *, struct siop_xfer *,
     55  1.1.4.2  mrg 		     struct scsi_xfer *, int);
     56  1.1.4.2  mrg static void siop_update_resid(struct siop_adapter *, struct siop_xfer *,
     57  1.1.4.2  mrg 			      struct scsi_xfer *, int);
     58  1.1.4.2  mrg 
     59  1.1.4.2  mrg static int siop_intr(struct siop_adapter *);
     60  1.1.4.2  mrg static void siop_scsicmd_end(struct siop_adapter *, struct scsi_xfer *);
     61  1.1.4.2  mrg static int siop_scsi_request(struct siop_adapter *, struct scsi_xfer *);
     62  1.1.4.2  mrg static void siop_start(struct siop_adapter *, struct scsi_xfer *);
     63  1.1.4.2  mrg static void siop_xfer_setup(struct siop_xfer *, void *);
     64  1.1.4.2  mrg 
     65  1.1.4.2  mrg static int siop_add_reselsw(struct siop_adapter *, int, int);
     66  1.1.4.2  mrg static void siop_update_scntl3(struct siop_adapter *, int, int);
     67  1.1.4.2  mrg 
     68  1.1.4.2  mrg static int _scsi_inquire(struct siop_adapter *, int, int, int, char *);
     69  1.1.4.2  mrg static void scsi_request_sense(struct siop_adapter *, struct scsi_xfer *);
     70  1.1.4.2  mrg static int scsi_interpret_sense(struct siop_adapter *, struct scsi_xfer *);
     71  1.1.4.2  mrg static int scsi_probe(struct siop_adapter *);
     72  1.1.4.2  mrg 
     73  1.1.4.2  mrg static struct siop_adapter adapt;
     74  1.1.4.2  mrg 
     75  1.1.4.2  mrg 
     76  1.1.4.2  mrg static void
     77  1.1.4.2  mrg siop_pci_reset(int addr)
     78  1.1.4.2  mrg {
     79  1.1.4.2  mrg 	int dmode, ctest5;
     80  1.1.4.2  mrg 	const int maxburst = 4;			/* 53c810 */
     81  1.1.4.2  mrg 
     82  1.1.4.2  mrg 	dmode = readb(addr + SIOP_DMODE);
     83  1.1.4.2  mrg 
     84  1.1.4.2  mrg 	ctest5 = readb(addr + SIOP_CTEST5);
     85  1.1.4.2  mrg 	writeb(addr + SIOP_CTEST4, readb(addr + SIOP_CTEST4) & ~CTEST4_BDIS);
     86  1.1.4.2  mrg 	ctest5 &= ~CTEST5_BBCK;
     87  1.1.4.2  mrg 	ctest5 |= (maxburst - 1) & CTEST5_BBCK;
     88  1.1.4.2  mrg 	writeb(addr + SIOP_CTEST5, ctest5);
     89  1.1.4.2  mrg 
     90  1.1.4.2  mrg 	dmode |= DMODE_ERL;
     91  1.1.4.2  mrg 	dmode &= ~DMODE_BL_MASK;
     92  1.1.4.2  mrg 	dmode |= ((maxburst - 1) << DMODE_BL_SHIFT) & DMODE_BL_MASK;
     93  1.1.4.2  mrg 	writeb(addr + SIOP_DMODE, dmode);
     94  1.1.4.2  mrg }
     95  1.1.4.2  mrg 
     96  1.1.4.2  mrg 
     97  1.1.4.2  mrg static void
     98  1.1.4.2  mrg siop_setuptables(struct siop_adapter *adp, struct siop_xfer *xfer,
     99  1.1.4.2  mrg 		 struct scsi_xfer *xs)
    100  1.1.4.2  mrg {
    101  1.1.4.2  mrg 	int msgoffset = 1;
    102  1.1.4.2  mrg 
    103  1.1.4.2  mrg 	xfer->siop_tables.id =
    104  1.1.4.2  mrg 	    htoc32((adp->clock_div << 24) | (xs->target << 16));
    105  1.1.4.2  mrg 	memset(xfer->siop_tables.msg_out, 0, sizeof(xfer->siop_tables.msg_out));
    106  1.1.4.2  mrg 	/* request sense doesn't disconnect */
    107  1.1.4.2  mrg 	if (xs->cmd->opcode == SCSI_REQUEST_SENSE)
    108  1.1.4.2  mrg 		xfer->siop_tables.msg_out[0] = MSG_IDENTIFY(xs->lun, 0);
    109  1.1.4.2  mrg 	else
    110  1.1.4.2  mrg 		xfer->siop_tables.msg_out[0] = MSG_IDENTIFY(xs->lun, 1);
    111  1.1.4.2  mrg 
    112  1.1.4.2  mrg 	xfer->siop_tables.t_msgout.count = htoc32(msgoffset);
    113  1.1.4.2  mrg 	xfer->siop_tables.status =
    114  1.1.4.2  mrg 	    htoc32(SCSI_SIOP_NOSTATUS); /* set invalid status */
    115  1.1.4.2  mrg 
    116  1.1.4.2  mrg 	xfer->siop_tables.cmd.count = htoc32(xs->cmdlen);
    117  1.1.4.2  mrg 	xfer->siop_tables.cmd.addr = htoc32(local_to_PCI((u_long)xs->cmd));
    118  1.1.4.2  mrg 	if (xs->datalen != 0) {
    119  1.1.4.2  mrg 		xfer->siop_tables.data[0].count = htoc32(xs->datalen);
    120  1.1.4.2  mrg 		xfer->siop_tables.data[0].addr =
    121  1.1.4.2  mrg 		    htoc32(local_to_PCI((u_long)xs->data));
    122  1.1.4.2  mrg 	}
    123  1.1.4.2  mrg }
    124  1.1.4.2  mrg 
    125  1.1.4.2  mrg static void
    126  1.1.4.2  mrg siop_ma(struct siop_adapter *adp, struct scsi_xfer *xs)
    127  1.1.4.2  mrg {
    128  1.1.4.2  mrg 	int offset, dbc;
    129  1.1.4.2  mrg 
    130  1.1.4.2  mrg 	/*
    131  1.1.4.2  mrg 	 * compute how much of the current table didn't get handled when
    132  1.1.4.2  mrg 	 * a phase mismatch occurs
    133  1.1.4.2  mrg 	 */
    134  1.1.4.2  mrg 	if (xs->datalen == 0)
    135  1.1.4.2  mrg 	    return; /* no valid data transfer */
    136  1.1.4.2  mrg 
    137  1.1.4.2  mrg 	offset = readb(adp->addr + SIOP_SCRATCHA + 1);
    138  1.1.4.2  mrg 	if (offset >= SIOP_NSG) {
    139  1.1.4.2  mrg 		printf("bad offset in siop_sdp (%d)\n", offset);
    140  1.1.4.2  mrg 		return;
    141  1.1.4.2  mrg 	}
    142  1.1.4.2  mrg 	dbc = readl(adp->addr + SIOP_DBC) & 0x00ffffff;
    143  1.1.4.2  mrg 	xs->resid = dbc;
    144  1.1.4.2  mrg }
    145  1.1.4.2  mrg 
    146  1.1.4.2  mrg static void
    147  1.1.4.2  mrg siop_sdp(struct siop_adapter *adp, struct siop_xfer *xfer, struct scsi_xfer *xs,
    148  1.1.4.2  mrg 	 int offset)
    149  1.1.4.2  mrg {
    150  1.1.4.2  mrg 
    151  1.1.4.2  mrg 	if (xs->datalen == 0)
    152  1.1.4.2  mrg 	    return; /* no data pointers to save */
    153  1.1.4.2  mrg 
    154  1.1.4.2  mrg 	/*
    155  1.1.4.2  mrg 	 * offset == SIOP_NSG may be a valid condition if we get a Save data
    156  1.1.4.2  mrg 	 * pointer when the xfer is done. Just ignore the Save data pointer
    157  1.1.4.2  mrg 	 * in this case
    158  1.1.4.2  mrg 	 */
    159  1.1.4.2  mrg 	if (offset == SIOP_NSG)
    160  1.1.4.2  mrg 		return;
    161  1.1.4.2  mrg 	/*
    162  1.1.4.2  mrg 	 * Save data pointer. We do this by adjusting the tables to point
    163  1.1.4.2  mrg 	 * at the begginning of the data not yet transfered.
    164  1.1.4.2  mrg 	 * offset points to the first table with untransfered data.
    165  1.1.4.2  mrg 	 */
    166  1.1.4.2  mrg 
    167  1.1.4.2  mrg 	/*
    168  1.1.4.2  mrg 	 * before doing that we decrease resid from the ammount of data which
    169  1.1.4.2  mrg 	 * has been transfered.
    170  1.1.4.2  mrg 	 */
    171  1.1.4.2  mrg 	siop_update_resid(adp, xfer, xs, offset);
    172  1.1.4.2  mrg 
    173  1.1.4.2  mrg #if 0
    174  1.1.4.2  mrg 	/*
    175  1.1.4.2  mrg 	 * First let see if we have a resid from a phase mismatch. If so,
    176  1.1.4.2  mrg 	 * we have to adjst the table at offset to remove transfered data.
    177  1.1.4.2  mrg 	 */
    178  1.1.4.2  mrg 	if (siop_cmd->flags & CMDFL_RESID) {
    179  1.1.4.2  mrg 		scr_table_t *table;
    180  1.1.4.2  mrg 
    181  1.1.4.2  mrg 		siop_cmd->flags &= ~CMDFL_RESID;
    182  1.1.4.2  mrg 		table = &xfer->siop_tables.data[offset];
    183  1.1.4.2  mrg 		/* "cut" already transfered data from this table */
    184  1.1.4.2  mrg 		table->addr =
    185  1.1.4.2  mrg 		    htoc32(ctoh32(table->addr) + ctoh32(table->count) -
    186  1.1.4.2  mrg 							siop_cmd->resid);
    187  1.1.4.2  mrg 		table->count = htoc32(siop_cmd->resid);
    188  1.1.4.2  mrg 	}
    189  1.1.4.2  mrg #endif
    190  1.1.4.2  mrg 
    191  1.1.4.2  mrg 	/*
    192  1.1.4.2  mrg 	 * now we can remove entries which have been transfered.
    193  1.1.4.2  mrg 	 * We just move the entries with data left at the beggining of the
    194  1.1.4.2  mrg 	 * tables
    195  1.1.4.2  mrg 	 */
    196  1.1.4.2  mrg 	memmove(xfer->siop_tables.data, &xfer->siop_tables.data[offset],
    197  1.1.4.2  mrg 	    (SIOP_NSG - offset) * sizeof(scr_table_t));
    198  1.1.4.2  mrg }
    199  1.1.4.2  mrg 
    200  1.1.4.2  mrg static void
    201  1.1.4.2  mrg siop_update_resid(struct siop_adapter *adp, struct siop_xfer *xfer,
    202  1.1.4.2  mrg 		  struct scsi_xfer *xs, int offset)
    203  1.1.4.2  mrg {
    204  1.1.4.2  mrg 	int i;
    205  1.1.4.2  mrg 
    206  1.1.4.2  mrg 	if (xs->datalen == 0)
    207  1.1.4.2  mrg 	    return; /* no data to transfer */
    208  1.1.4.2  mrg 
    209  1.1.4.2  mrg 	/*
    210  1.1.4.2  mrg 	 * update resid. First account for the table entries which have
    211  1.1.4.2  mrg 	 * been fully completed.
    212  1.1.4.2  mrg 	 */
    213  1.1.4.2  mrg 	for (i = 0; i < offset; i++)
    214  1.1.4.2  mrg 		xs->resid -= ctoh32(xfer->siop_tables.data[i].count);
    215  1.1.4.2  mrg #if 0
    216  1.1.4.2  mrg 	/*
    217  1.1.4.2  mrg 	 * if CMDFL_RESID is set, the last table (pointed by offset) is a
    218  1.1.4.2  mrg 	 * partial transfers. If not, offset points to the entry folloing
    219  1.1.4.2  mrg 	 * the last full transfer.
    220  1.1.4.2  mrg 	 */
    221  1.1.4.2  mrg 	if (siop_cmd->flags & CMDFL_RESID) {
    222  1.1.4.2  mrg 		scr_table_t *table = &xfer->siop_tables.data[offset];
    223  1.1.4.2  mrg 
    224  1.1.4.2  mrg 		xs->resid -= ctoh32(table->count) - xs->resid;
    225  1.1.4.2  mrg 	}
    226  1.1.4.2  mrg #endif
    227  1.1.4.2  mrg }
    228  1.1.4.2  mrg 
    229  1.1.4.2  mrg 
    230  1.1.4.2  mrg #define CALL_SCRIPT(ent)	writel(adp->addr + SIOP_DSP, scriptaddr + ent);
    231  1.1.4.2  mrg 
    232  1.1.4.2  mrg static int
    233  1.1.4.2  mrg siop_intr(struct siop_adapter *adp)
    234  1.1.4.2  mrg {
    235  1.1.4.2  mrg 	struct siop_xfer *siop_xfer = NULL;
    236  1.1.4.2  mrg 	struct scsi_xfer *xs = NULL;
    237  1.1.4.2  mrg 	u_long scriptaddr = local_to_PCI((u_long)adp->script);
    238  1.1.4.2  mrg 	int offset, target, lun, tag, restart = 0, need_reset = 0;
    239  1.1.4.2  mrg 	uint32_t dsa, irqcode;
    240  1.1.4.2  mrg 	uint16_t sist;
    241  1.1.4.2  mrg 	uint8_t dstat, sstat1, istat;
    242  1.1.4.2  mrg 
    243  1.1.4.2  mrg 	istat = readb(adp->addr + SIOP_ISTAT);
    244  1.1.4.2  mrg 	if ((istat & (ISTAT_INTF | ISTAT_DIP | ISTAT_SIP)) == 0)
    245  1.1.4.2  mrg 		return 0;
    246  1.1.4.2  mrg 	if (istat & ISTAT_INTF) {
    247  1.1.4.2  mrg 		printf("INTRF\n");
    248  1.1.4.2  mrg 		writeb(adp->addr + SIOP_ISTAT, ISTAT_INTF);
    249  1.1.4.2  mrg 	}
    250  1.1.4.2  mrg 	if ((istat & (ISTAT_DIP | ISTAT_SIP | ISTAT_ABRT)) ==
    251  1.1.4.2  mrg 	    (ISTAT_DIP | ISTAT_ABRT))
    252  1.1.4.2  mrg 		/* clear abort */
    253  1.1.4.2  mrg 		writeb(adp->addr + SIOP_ISTAT, 0);
    254  1.1.4.2  mrg 	/* use DSA to find the current siop_cmd */
    255  1.1.4.2  mrg 	dsa = readl(adp->addr + SIOP_DSA);
    256  1.1.4.2  mrg 	if (dsa >= local_to_PCI((u_long)adp->xfer) &&
    257  1.1.4.2  mrg 	    dsa < local_to_PCI((u_long)adp->xfer) + SIOP_TABLE_SIZE) {
    258  1.1.4.2  mrg 		dsa -= local_to_PCI((u_long)adp->xfer);
    259  1.1.4.2  mrg 		siop_xfer = adp->xfer;
    260  1.1.4.2  mrg 		_inv((u_long)siop_xfer, sizeof(*siop_xfer));
    261  1.1.4.2  mrg 
    262  1.1.4.2  mrg 		xs = adp->xs;
    263  1.1.4.2  mrg 	}
    264  1.1.4.2  mrg 
    265  1.1.4.2  mrg 	if (istat & ISTAT_DIP)
    266  1.1.4.2  mrg 		dstat = readb(adp->addr + SIOP_DSTAT);
    267  1.1.4.2  mrg 	if (istat & ISTAT_SIP) {
    268  1.1.4.2  mrg 		if (istat & ISTAT_DIP)
    269  1.1.4.2  mrg 			delay(10);
    270  1.1.4.2  mrg 		/*
    271  1.1.4.2  mrg 		 * Can't read sist0 & sist1 independently, or we have to
    272  1.1.4.2  mrg 		 * insert delay
    273  1.1.4.2  mrg 		 */
    274  1.1.4.2  mrg 		sist = readw(adp->addr + SIOP_SIST0);
    275  1.1.4.2  mrg 		sstat1 = readb(adp->addr + SIOP_SSTAT1);
    276  1.1.4.2  mrg 
    277  1.1.4.2  mrg 		if ((sist & SIST0_MA) && need_reset == 0) {
    278  1.1.4.2  mrg 			if (siop_xfer) {
    279  1.1.4.2  mrg 				int scratcha0;
    280  1.1.4.2  mrg 
    281  1.1.4.2  mrg 				dstat = readb(adp->addr + SIOP_DSTAT);
    282  1.1.4.2  mrg 				/*
    283  1.1.4.2  mrg 				 * first restore DSA, in case we were in a S/G
    284  1.1.4.2  mrg 				 * operation.
    285  1.1.4.2  mrg 				 */
    286  1.1.4.2  mrg 				writel(adp->addr + SIOP_DSA,
    287  1.1.4.2  mrg 				    local_to_PCI((u_long)siop_xfer));
    288  1.1.4.2  mrg 				scratcha0 = readb(adp->addr + SIOP_SCRATCHA);
    289  1.1.4.2  mrg 				switch (sstat1 & SSTAT1_PHASE_MASK) {
    290  1.1.4.2  mrg 				case SSTAT1_PHASE_STATUS:
    291  1.1.4.2  mrg 				/*
    292  1.1.4.2  mrg 				 * previous phase may be aborted for any reason
    293  1.1.4.2  mrg 				 * ( for example, the target has less data to
    294  1.1.4.2  mrg 				 * transfer than requested). Compute resid and
    295  1.1.4.2  mrg 				 * just go to status, the command should
    296  1.1.4.2  mrg 				 * terminate.
    297  1.1.4.2  mrg 				 */
    298  1.1.4.2  mrg 					if (scratcha0 & A_flag_data)
    299  1.1.4.2  mrg 						siop_ma(adp, xs);
    300  1.1.4.2  mrg 					else if ((dstat & DSTAT_DFE) == 0)
    301  1.1.4.2  mrg printf("PHASE STATUS: siop_clearfifo...\n");
    302  1.1.4.2  mrg //						siop_clearfifo(adp);
    303  1.1.4.2  mrg 					CALL_SCRIPT(Ent_status);
    304  1.1.4.2  mrg 					return 1;
    305  1.1.4.2  mrg 				case SSTAT1_PHASE_MSGIN:
    306  1.1.4.2  mrg 				/*
    307  1.1.4.2  mrg 				 * target may be ready to disconnect
    308  1.1.4.2  mrg 				 * Compute resid which would be used later
    309  1.1.4.2  mrg 				 * if a save data pointer is needed.
    310  1.1.4.2  mrg 				 */
    311  1.1.4.2  mrg 					if (scratcha0 & A_flag_data)
    312  1.1.4.2  mrg 						siop_ma(adp, xs);
    313  1.1.4.2  mrg 					else if ((dstat & DSTAT_DFE) == 0)
    314  1.1.4.2  mrg printf("PHASE MSGIN: siop_clearfifo...\n");
    315  1.1.4.2  mrg //						siop_clearfifo(adp);
    316  1.1.4.2  mrg 					writeb(adp->addr + SIOP_SCRATCHA,
    317  1.1.4.2  mrg 					    scratcha0 & ~A_flag_data);
    318  1.1.4.2  mrg 					CALL_SCRIPT(Ent_msgin);
    319  1.1.4.2  mrg 					return 1;
    320  1.1.4.2  mrg 				}
    321  1.1.4.2  mrg 				printf("unexpected phase mismatch %d\n",
    322  1.1.4.2  mrg 				    sstat1 & SSTAT1_PHASE_MASK);
    323  1.1.4.2  mrg 			} else
    324  1.1.4.2  mrg 				printf("phase mismatch without command\n");
    325  1.1.4.2  mrg 			need_reset = 1;
    326  1.1.4.2  mrg 		}
    327  1.1.4.2  mrg 		if (sist & (SIST1_STO << 8)) {
    328  1.1.4.2  mrg 			/* selection time out, assume there's no device here */
    329  1.1.4.2  mrg 			if (siop_xfer) {
    330  1.1.4.2  mrg 				xs->error = XS_SELTIMEOUT;
    331  1.1.4.2  mrg 				goto end;
    332  1.1.4.2  mrg 			} else
    333  1.1.4.2  mrg 				printf("selection timeout without command\n");
    334  1.1.4.2  mrg 		}
    335  1.1.4.2  mrg 
    336  1.1.4.2  mrg 		/* Else it's an unhandled exception (for now). */
    337  1.1.4.2  mrg 		printf("unhandled scsi interrupt,"
    338  1.1.4.2  mrg 		    " sist=0x%x sstat1=0x%x DSA=0x%x DSP=0x%lx\n",
    339  1.1.4.2  mrg 		    sist, sstat1, dsa,
    340  1.1.4.2  mrg 		    readl(adp->addr + SIOP_DSP) - scriptaddr);
    341  1.1.4.2  mrg 		if (siop_xfer) {
    342  1.1.4.2  mrg 			xs->error = XS_SELTIMEOUT;
    343  1.1.4.2  mrg 			goto end;
    344  1.1.4.2  mrg 		}
    345  1.1.4.2  mrg 		need_reset = 1;
    346  1.1.4.2  mrg 	}
    347  1.1.4.2  mrg 	if (need_reset) {
    348  1.1.4.2  mrg reset:
    349  1.1.4.2  mrg 		printf("XXXXX: fatal error, need reset the bus...\n");
    350  1.1.4.2  mrg 		return 1;
    351  1.1.4.2  mrg 	}
    352  1.1.4.2  mrg 
    353  1.1.4.2  mrg //scintr:
    354  1.1.4.2  mrg 	if ((istat & ISTAT_DIP) && (dstat & DSTAT_SIR)) { /* script interrupt */
    355  1.1.4.2  mrg 		irqcode = readl(adp->addr + SIOP_DSPS);
    356  1.1.4.2  mrg 		/*
    357  1.1.4.2  mrg 		 * no command, or an inactive command is only valid for a
    358  1.1.4.2  mrg 		 * reselect interrupt
    359  1.1.4.2  mrg 		 */
    360  1.1.4.2  mrg 		if ((irqcode & 0x80) == 0) {
    361  1.1.4.2  mrg 			if (siop_xfer == NULL) {
    362  1.1.4.2  mrg 				printf(
    363  1.1.4.2  mrg 				    "script interrupt 0x%x with invalid DSA\n",
    364  1.1.4.2  mrg 				    irqcode);
    365  1.1.4.2  mrg 				goto reset;
    366  1.1.4.2  mrg 			}
    367  1.1.4.2  mrg 		}
    368  1.1.4.2  mrg 		switch(irqcode) {
    369  1.1.4.2  mrg 		case A_int_err:
    370  1.1.4.2  mrg 			printf("error, DSP=0x%lx\n",
    371  1.1.4.2  mrg 			    readl(adp->addr + SIOP_DSP) - scriptaddr);
    372  1.1.4.2  mrg 			if (xs) {
    373  1.1.4.2  mrg 				xs->error = XS_SELTIMEOUT;
    374  1.1.4.2  mrg 				goto end;
    375  1.1.4.2  mrg 			} else {
    376  1.1.4.2  mrg 				goto reset;
    377  1.1.4.2  mrg 			}
    378  1.1.4.2  mrg 		case A_int_reseltarg:
    379  1.1.4.2  mrg 			printf("reselect with invalid target\n");
    380  1.1.4.2  mrg 			goto reset;
    381  1.1.4.2  mrg 		case A_int_resellun:
    382  1.1.4.2  mrg 			target = readb(adp->addr + SIOP_SCRATCHA) & 0xf;
    383  1.1.4.2  mrg 			lun = readb(adp->addr + SIOP_SCRATCHA + 1);
    384  1.1.4.2  mrg 			tag = readb(adp->addr + SIOP_SCRATCHA + 2);
    385  1.1.4.2  mrg 			if (target != adp->xs->target ||
    386  1.1.4.2  mrg 			    lun != adp->xs->lun ||
    387  1.1.4.2  mrg 			    tag != 0) {
    388  1.1.4.2  mrg 				printf("unknwon resellun:"
    389  1.1.4.2  mrg 				    " target %d lun %d tag %d\n",
    390  1.1.4.2  mrg 				    target, lun, tag);
    391  1.1.4.2  mrg 				goto reset;
    392  1.1.4.2  mrg 			}
    393  1.1.4.2  mrg 			siop_xfer = adp->xfer;
    394  1.1.4.2  mrg 			dsa = local_to_PCI((u_long)siop_xfer);
    395  1.1.4.2  mrg 			writel(adp->addr + SIOP_DSP,
    396  1.1.4.2  mrg 			    dsa + sizeof(struct siop_common_xfer) +
    397  1.1.4.2  mrg 			    Ent_ldsa_reload_dsa);
    398  1.1.4.2  mrg 			_wbinv((u_long)siop_xfer, sizeof(*siop_xfer));
    399  1.1.4.2  mrg 			return 1;
    400  1.1.4.2  mrg 		case A_int_reseltag:
    401  1.1.4.2  mrg 			printf("reselect with invalid tag\n");
    402  1.1.4.2  mrg 			goto reset;
    403  1.1.4.2  mrg 		case A_int_disc:
    404  1.1.4.2  mrg 			offset = readb(adp->addr + SIOP_SCRATCHA + 1);
    405  1.1.4.2  mrg 			siop_sdp(adp, siop_xfer, xs, offset);
    406  1.1.4.2  mrg #if 0
    407  1.1.4.2  mrg 			/* we start again with no offset */
    408  1.1.4.2  mrg 			siop_cmd->saved_offset = SIOP_NOOFFSET;
    409  1.1.4.2  mrg #endif
    410  1.1.4.2  mrg 			_wbinv((u_long)siop_xfer, sizeof(*siop_xfer));
    411  1.1.4.2  mrg 			CALL_SCRIPT(Ent_script_sched);
    412  1.1.4.2  mrg 			return 1;
    413  1.1.4.2  mrg 		case A_int_resfail:
    414  1.1.4.2  mrg 			printf("reselect failed\n");
    415  1.1.4.2  mrg 			return  1;
    416  1.1.4.2  mrg 		case A_int_done:
    417  1.1.4.2  mrg 			if (xs == NULL) {
    418  1.1.4.2  mrg 				printf("done without command, DSA=0x%lx\n",
    419  1.1.4.2  mrg 				    local_to_PCI((u_long)adp->xfer));
    420  1.1.4.2  mrg 				return 1;
    421  1.1.4.2  mrg 			}
    422  1.1.4.2  mrg 			/* update resid.  */
    423  1.1.4.2  mrg 			offset = readb(adp->addr + SIOP_SCRATCHA + 1);
    424  1.1.4.2  mrg #if 0
    425  1.1.4.2  mrg 			/*
    426  1.1.4.2  mrg 			 * if we got a disconnect between the last data phase
    427  1.1.4.2  mrg 			 * and the status phase, offset will be 0. In this
    428  1.1.4.2  mrg 			 * case, siop_cmd->saved_offset will have the proper
    429  1.1.4.2  mrg 			 * value if it got updated by the controller
    430  1.1.4.2  mrg 			 */
    431  1.1.4.2  mrg 			if (offset == 0 &&
    432  1.1.4.2  mrg 			    siop_cmd->saved_offset != SIOP_NOOFFSET)
    433  1.1.4.2  mrg 				offset = siop_cmd->saved_offset;
    434  1.1.4.2  mrg #endif
    435  1.1.4.2  mrg 			siop_update_resid(adp, siop_xfer, xs, offset);
    436  1.1.4.2  mrg 			goto end;
    437  1.1.4.2  mrg 		default:
    438  1.1.4.2  mrg 			printf("unknown irqcode %x\n", irqcode);
    439  1.1.4.2  mrg 			if (xs) {
    440  1.1.4.2  mrg 				xs->error = XS_SELTIMEOUT;
    441  1.1.4.2  mrg 				goto end;
    442  1.1.4.2  mrg 			}
    443  1.1.4.2  mrg 			goto reset;
    444  1.1.4.2  mrg 		}
    445  1.1.4.2  mrg 		return 1;
    446  1.1.4.2  mrg 	}
    447  1.1.4.2  mrg 	/* We just should't get there */
    448  1.1.4.2  mrg 	panic("siop_intr: I shouldn't be there !");
    449  1.1.4.2  mrg 
    450  1.1.4.2  mrg 	return 1;
    451  1.1.4.2  mrg 
    452  1.1.4.2  mrg end:
    453  1.1.4.2  mrg 	/*
    454  1.1.4.2  mrg 	 * restart the script now if command completed properly
    455  1.1.4.2  mrg 	 * Otherwise wait for siop_scsicmd_end(), we may need to cleanup the
    456  1.1.4.2  mrg 	 * queue
    457  1.1.4.2  mrg 	 */
    458  1.1.4.2  mrg 	xs->status = ctoh32(siop_xfer->siop_tables.status);
    459  1.1.4.2  mrg 	if (xs->status == SCSI_OK)
    460  1.1.4.2  mrg 		writel(adp->addr + SIOP_DSP, scriptaddr + Ent_script_sched);
    461  1.1.4.2  mrg 	else
    462  1.1.4.2  mrg 		restart = 1;
    463  1.1.4.2  mrg 	siop_scsicmd_end(adp, xs);
    464  1.1.4.2  mrg 	if (restart)
    465  1.1.4.2  mrg 		writel(adp->addr + SIOP_DSP, scriptaddr + Ent_script_sched);
    466  1.1.4.2  mrg 
    467  1.1.4.2  mrg 	return 1;
    468  1.1.4.2  mrg }
    469  1.1.4.2  mrg 
    470  1.1.4.2  mrg static void
    471  1.1.4.2  mrg siop_scsicmd_end(struct siop_adapter *adp, struct scsi_xfer *xs)
    472  1.1.4.2  mrg {
    473  1.1.4.2  mrg 
    474  1.1.4.2  mrg 	switch(xs->status) {
    475  1.1.4.2  mrg 	case SCSI_OK:
    476  1.1.4.2  mrg 		xs->error = XS_NOERROR;
    477  1.1.4.2  mrg 		break;
    478  1.1.4.2  mrg 	case SCSI_BUSY:
    479  1.1.4.2  mrg 	case SCSI_CHECK:
    480  1.1.4.2  mrg 	case SCSI_QUEUE_FULL:
    481  1.1.4.2  mrg 		xs->error = XS_BUSY;
    482  1.1.4.2  mrg 		break;
    483  1.1.4.2  mrg 	case SCSI_SIOP_NOCHECK:
    484  1.1.4.2  mrg 		/*
    485  1.1.4.2  mrg 		 * don't check status, xs->error is already valid
    486  1.1.4.2  mrg 		 */
    487  1.1.4.2  mrg 		break;
    488  1.1.4.2  mrg 	case SCSI_SIOP_NOSTATUS:
    489  1.1.4.2  mrg 		/*
    490  1.1.4.2  mrg 		 * the status byte was not updated, cmd was
    491  1.1.4.2  mrg 		 * aborted
    492  1.1.4.2  mrg 		 */
    493  1.1.4.2  mrg 		xs->error = XS_SELTIMEOUT;
    494  1.1.4.2  mrg 		break;
    495  1.1.4.2  mrg 	default:
    496  1.1.4.2  mrg 		printf("invalid status code %d\n", xs->status);
    497  1.1.4.2  mrg 		xs->error = XS_DRIVER_STUFFUP;
    498  1.1.4.2  mrg 	}
    499  1.1.4.2  mrg 	_inv((u_long)xs->cmd, xs->cmdlen);
    500  1.1.4.2  mrg 	if (xs->datalen != 0)
    501  1.1.4.2  mrg 		_inv((u_long)xs->data, xs->datalen);
    502  1.1.4.2  mrg 	xs->xs_status = XS_STS_DONE;
    503  1.1.4.2  mrg }
    504  1.1.4.2  mrg 
    505  1.1.4.2  mrg static int
    506  1.1.4.2  mrg siop_scsi_request(struct siop_adapter *adp, struct scsi_xfer *xs)
    507  1.1.4.2  mrg {
    508  1.1.4.2  mrg 	void *xfer = adp->xfer;
    509  1.1.4.2  mrg 	int timo, error;
    510  1.1.4.2  mrg 
    511  1.1.4.2  mrg 	if (adp->sel_t != xs->target) {
    512  1.1.4.2  mrg 		const int free_lo = __arraycount(siop_script);
    513  1.1.4.2  mrg 		int i;
    514  1.1.4.2  mrg 		void *scriptaddr = (void *)local_to_PCI((u_long)adp->script);
    515  1.1.4.2  mrg 
    516  1.1.4.2  mrg 		if (adp->sel_t != -1)
    517  1.1.4.2  mrg 			adp->script[Ent_resel_targ0 / 4 + adp->sel_t * 2] =
    518  1.1.4.2  mrg 			    htoc32(0x800c00ff);
    519  1.1.4.2  mrg 
    520  1.1.4.2  mrg 		for (i = 0; i < __arraycount(lun_switch); i++)
    521  1.1.4.2  mrg 			adp->script[free_lo + i] = htoc32(lun_switch[i]);
    522  1.1.4.2  mrg 		adp->script[free_lo + E_abs_lunsw_return_Used[0]] =
    523  1.1.4.2  mrg 		    htoc32(scriptaddr + Ent_lunsw_return);
    524  1.1.4.2  mrg 
    525  1.1.4.2  mrg 		siop_add_reselsw(adp, xs->target, free_lo);
    526  1.1.4.2  mrg 
    527  1.1.4.2  mrg 		adp->sel_t = xs->target;
    528  1.1.4.2  mrg 	}
    529  1.1.4.2  mrg 
    530  1.1.4.2  mrg restart:
    531  1.1.4.2  mrg 
    532  1.1.4.2  mrg 	siop_setuptables(adp, xfer, xs);
    533  1.1.4.2  mrg 
    534  1.1.4.2  mrg 	/* load the DMA maps */
    535  1.1.4.2  mrg 	if (xs->datalen != 0)
    536  1.1.4.2  mrg 		_inv((u_long)xs->data, xs->datalen);
    537  1.1.4.2  mrg 	_wbinv((u_long)xs->cmd, xs->cmdlen);
    538  1.1.4.2  mrg 
    539  1.1.4.2  mrg 	_wbinv((u_long)xfer, sizeof(struct siop_xfer));
    540  1.1.4.2  mrg 	siop_start(adp, xs);
    541  1.1.4.2  mrg 
    542  1.1.4.2  mrg 	adp->xs = xs;
    543  1.1.4.2  mrg 	timo = 0;
    544  1.1.4.2  mrg 	while (!(xs->xs_status & XS_STS_DONE)) {
    545  1.1.4.2  mrg 		delay(1000);
    546  1.1.4.2  mrg 		siop_intr(adp);
    547  1.1.4.2  mrg 
    548  1.1.4.2  mrg 		if (timo++ > 3000) {		/* XXXX: 3sec */
    549  1.1.4.2  mrg 			printf("%s: timeout\n", __func__);
    550  1.1.4.2  mrg 			return ETIMEDOUT;
    551  1.1.4.2  mrg 		}
    552  1.1.4.2  mrg 	}
    553  1.1.4.2  mrg 
    554  1.1.4.2  mrg 	if (xs->error != XS_NOERROR) {
    555  1.1.4.2  mrg 		if (xs->error == XS_BUSY || xs->status == SCSI_CHECK)
    556  1.1.4.2  mrg 			scsi_request_sense(adp, xs);
    557  1.1.4.2  mrg 
    558  1.1.4.2  mrg 		switch (xs->error) {
    559  1.1.4.2  mrg 		case XS_SENSE:
    560  1.1.4.2  mrg 		case XS_SHORTSENSE:
    561  1.1.4.2  mrg 			error = scsi_interpret_sense(adp, xs);
    562  1.1.4.2  mrg 			break;
    563  1.1.4.2  mrg 		case XS_RESOURCE_SHORTAGE:
    564  1.1.4.2  mrg 			printf("adapter resource shortage\n");
    565  1.1.4.2  mrg 
    566  1.1.4.2  mrg 			/* FALLTHROUGH */
    567  1.1.4.2  mrg 		case XS_BUSY:
    568  1.1.4.2  mrg 			error = EBUSY;
    569  1.1.4.2  mrg 			break;
    570  1.1.4.2  mrg 		case XS_REQUEUE:
    571  1.1.4.2  mrg 			printf("XXXX: requeue...\n");
    572  1.1.4.2  mrg 			error = ERESTART;
    573  1.1.4.2  mrg 			break;
    574  1.1.4.2  mrg 		case XS_SELTIMEOUT:
    575  1.1.4.2  mrg 		case XS_TIMEOUT:
    576  1.1.4.2  mrg 			error = EIO;
    577  1.1.4.2  mrg 			break;
    578  1.1.4.2  mrg 		case XS_RESET:
    579  1.1.4.2  mrg 			error = EIO;
    580  1.1.4.2  mrg 			break;
    581  1.1.4.2  mrg 		case XS_DRIVER_STUFFUP:
    582  1.1.4.2  mrg 			printf("generic HBA error\n");
    583  1.1.4.2  mrg 			error = EIO;
    584  1.1.4.2  mrg 			break;
    585  1.1.4.2  mrg 		default:
    586  1.1.4.2  mrg 			printf("invalid return code from adapter: %d\n",
    587  1.1.4.2  mrg 			    xs->error);
    588  1.1.4.2  mrg 			error = EIO;
    589  1.1.4.2  mrg 			break;
    590  1.1.4.2  mrg 		}
    591  1.1.4.2  mrg 		if (error == ERESTART) {
    592  1.1.4.2  mrg 			xs->error = XS_NOERROR;
    593  1.1.4.2  mrg 			xs->status = SCSI_OK;
    594  1.1.4.2  mrg 			xs->xs_status &= ~XS_STS_DONE;
    595  1.1.4.2  mrg 			goto restart;
    596  1.1.4.2  mrg 		}
    597  1.1.4.2  mrg 		return error;
    598  1.1.4.2  mrg 	}
    599  1.1.4.2  mrg 	return 0;
    600  1.1.4.2  mrg }
    601  1.1.4.2  mrg 
    602  1.1.4.2  mrg static void
    603  1.1.4.2  mrg siop_start(struct siop_adapter *adp, struct scsi_xfer *xs)
    604  1.1.4.2  mrg {
    605  1.1.4.2  mrg 	struct siop_xfer *siop_xfer = adp->xfer;
    606  1.1.4.2  mrg 	uint32_t dsa, *script = adp->script;
    607  1.1.4.2  mrg 	int target, lun, slot;
    608  1.1.4.2  mrg 	void *scriptaddr = (void *)local_to_PCI((u_long)script);
    609  1.1.4.2  mrg 	const int siop_common_xfer_size = sizeof(struct siop_common_xfer);
    610  1.1.4.2  mrg 
    611  1.1.4.2  mrg 	/*
    612  1.1.4.2  mrg 	 * The queue management here is a bit tricky: the script always looks
    613  1.1.4.2  mrg 	 * at the slot from first to last, so if we always use the first
    614  1.1.4.2  mrg 	 * free slot commands can stay at the tail of the queue ~forever.
    615  1.1.4.2  mrg 	 * The algorithm used here is to restart from the head when we know
    616  1.1.4.2  mrg 	 * that the queue is empty, and only add commands after the last one.
    617  1.1.4.2  mrg 	 * When we're at the end of the queue wait for the script to clear it.
    618  1.1.4.2  mrg 	 * The best thing to do here would be to implement a circular queue,
    619  1.1.4.2  mrg 	 * but using only 53c720 features this can be "interesting".
    620  1.1.4.2  mrg 	 * A mid-way solution could be to implement 2 queues and swap orders.
    621  1.1.4.2  mrg 	 */
    622  1.1.4.2  mrg 	slot = adp->currschedslot;
    623  1.1.4.2  mrg 	/*
    624  1.1.4.2  mrg 	 * If the instruction is 0x80000000 (JUMP foo, IF FALSE) the slot is
    625  1.1.4.2  mrg 	 * free. As this is the last used slot, all previous slots are free,
    626  1.1.4.2  mrg 	 * we can restart from 0.
    627  1.1.4.2  mrg 	 */
    628  1.1.4.2  mrg 	if (ctoh32(script[(Ent_script_sched_slot0 / 4) + slot * 2]) ==
    629  1.1.4.2  mrg 	    0x80000000) {
    630  1.1.4.2  mrg 		slot = adp->currschedslot = 0;
    631  1.1.4.2  mrg 	} else {
    632  1.1.4.2  mrg 		slot++;
    633  1.1.4.2  mrg 	}
    634  1.1.4.2  mrg 	target = xs->target;
    635  1.1.4.2  mrg 	lun = xs->lun;
    636  1.1.4.2  mrg 	/*
    637  1.1.4.2  mrg 	 * find a free scheduler slot and load it.
    638  1.1.4.2  mrg 	 */
    639  1.1.4.2  mrg #define SIOP_NSLOTS	0x40
    640  1.1.4.2  mrg 	for (; slot < SIOP_NSLOTS; slot++) {
    641  1.1.4.2  mrg 		/*
    642  1.1.4.2  mrg 		 * If cmd if 0x80000000 the slot is free
    643  1.1.4.2  mrg 		 */
    644  1.1.4.2  mrg 		if (ctoh32(script[(Ent_script_sched_slot0 / 4) + slot * 2]) ==
    645  1.1.4.2  mrg 		    0x80000000)
    646  1.1.4.2  mrg 			break;
    647  1.1.4.2  mrg 	}
    648  1.1.4.2  mrg 	if (slot == SIOP_NSLOTS) {
    649  1.1.4.2  mrg 		/*
    650  1.1.4.2  mrg 		 * no more free slot, no need to continue. freeze the queue
    651  1.1.4.2  mrg 		 * and requeue this command.
    652  1.1.4.2  mrg 		 */
    653  1.1.4.2  mrg 		printf("no mode free slot\n");
    654  1.1.4.2  mrg 		return;
    655  1.1.4.2  mrg 	}
    656  1.1.4.2  mrg 
    657  1.1.4.2  mrg 	/* patch scripts with DSA addr */
    658  1.1.4.2  mrg 	dsa = local_to_PCI((u_long)siop_xfer);
    659  1.1.4.2  mrg 
    660  1.1.4.2  mrg 	/* CMD script: MOVE MEMORY addr */
    661  1.1.4.2  mrg 	siop_xfer->resel[E_ldsa_abs_slot_Used[0]] =
    662  1.1.4.2  mrg 	    htoc32(scriptaddr + Ent_script_sched_slot0 + slot * 8);
    663  1.1.4.2  mrg 	_wbinv((u_long)siop_xfer, sizeof(*siop_xfer));
    664  1.1.4.2  mrg 	/* scheduler slot: JUMP ldsa_select */
    665  1.1.4.2  mrg 	script[(Ent_script_sched_slot0 / 4) + slot * 2 + 1] =
    666  1.1.4.2  mrg 	    htoc32(dsa + siop_common_xfer_size + Ent_ldsa_select);
    667  1.1.4.2  mrg 	/*
    668  1.1.4.2  mrg 	 * Change JUMP cmd so that this slot will be handled
    669  1.1.4.2  mrg 	 */
    670  1.1.4.2  mrg 	script[(Ent_script_sched_slot0 / 4) + slot * 2] = htoc32(0x80080000);
    671  1.1.4.2  mrg 	adp->currschedslot = slot;
    672  1.1.4.2  mrg 
    673  1.1.4.2  mrg 	/* make sure SCRIPT processor will read valid data */
    674  1.1.4.2  mrg 	_wbinv((u_long)script, SIOP_SCRIPT_SIZE);
    675  1.1.4.2  mrg 	/* Signal script it has some work to do */
    676  1.1.4.2  mrg 	writeb(adp->addr + SIOP_ISTAT, ISTAT_SIGP);
    677  1.1.4.2  mrg 	/* and wait for IRQ */
    678  1.1.4.2  mrg }
    679  1.1.4.2  mrg 
    680  1.1.4.2  mrg static void
    681  1.1.4.2  mrg siop_xfer_setup(struct siop_xfer *xfer, void *scriptaddr)
    682  1.1.4.2  mrg {
    683  1.1.4.2  mrg 	const int off_msg_in = offsetof(struct siop_common_xfer, msg_in);
    684  1.1.4.2  mrg 	const int off_status = offsetof(struct siop_common_xfer, status);
    685  1.1.4.2  mrg 	uint32_t dsa, *scr;
    686  1.1.4.2  mrg 	int i;
    687  1.1.4.2  mrg 
    688  1.1.4.2  mrg 	memset(xfer, 0, sizeof(*xfer));
    689  1.1.4.2  mrg 	dsa = local_to_PCI((u_long)xfer);
    690  1.1.4.2  mrg 	xfer->siop_tables.t_msgout.count = htoc32(1);
    691  1.1.4.2  mrg 	xfer->siop_tables.t_msgout.addr = htoc32(dsa);
    692  1.1.4.2  mrg 	xfer->siop_tables.t_msgin.count = htoc32(1);
    693  1.1.4.2  mrg 	xfer->siop_tables.t_msgin.addr = htoc32(dsa + off_msg_in);
    694  1.1.4.2  mrg 	xfer->siop_tables.t_extmsgin.count = htoc32(2);
    695  1.1.4.2  mrg 	xfer->siop_tables.t_extmsgin.addr = htoc32(dsa + off_msg_in + 1);
    696  1.1.4.2  mrg 	xfer->siop_tables.t_extmsgdata.addr = htoc32(dsa + off_msg_in + 3);
    697  1.1.4.2  mrg 	xfer->siop_tables.t_status.count = htoc32(1);
    698  1.1.4.2  mrg 	xfer->siop_tables.t_status.addr = htoc32(dsa + off_status);
    699  1.1.4.2  mrg 
    700  1.1.4.2  mrg 	/* The select/reselect script */
    701  1.1.4.2  mrg 	scr = xfer->resel;
    702  1.1.4.2  mrg 	for (i = 0; i < __arraycount(load_dsa); i++)
    703  1.1.4.2  mrg 		scr[i] = htoc32(load_dsa[i]);
    704  1.1.4.2  mrg 
    705  1.1.4.2  mrg 	/*
    706  1.1.4.2  mrg 	 * 0x78000000 is a 'move data8 to reg'. data8 is the second
    707  1.1.4.2  mrg 	 * octet, reg offset is the third.
    708  1.1.4.2  mrg 	 */
    709  1.1.4.2  mrg 	scr[Ent_rdsa0 / 4] = htoc32(0x78100000 | ((dsa & 0x000000ff) <<  8));
    710  1.1.4.2  mrg 	scr[Ent_rdsa1 / 4] = htoc32(0x78110000 | ( dsa & 0x0000ff00       ));
    711  1.1.4.2  mrg 	scr[Ent_rdsa2 / 4] = htoc32(0x78120000 | ((dsa & 0x00ff0000) >>  8));
    712  1.1.4.2  mrg 	scr[Ent_rdsa3 / 4] = htoc32(0x78130000 | ((dsa & 0xff000000) >> 16));
    713  1.1.4.2  mrg 	scr[E_ldsa_abs_reselected_Used[0]] =
    714  1.1.4.2  mrg 	    htoc32(scriptaddr + Ent_reselected);
    715  1.1.4.2  mrg 	scr[E_ldsa_abs_reselect_Used[0]] = htoc32(scriptaddr + Ent_reselect);
    716  1.1.4.2  mrg 	scr[E_ldsa_abs_selected_Used[0]] = htoc32(scriptaddr + Ent_selected);
    717  1.1.4.2  mrg 	scr[E_ldsa_abs_data_Used[0]] =
    718  1.1.4.2  mrg 	    htoc32(dsa + sizeof(struct siop_common_xfer) + Ent_ldsa_data);
    719  1.1.4.2  mrg 	/* JUMP foo, IF FALSE - used by MOVE MEMORY to clear the slot */
    720  1.1.4.2  mrg 	scr[Ent_ldsa_data / 4] = htoc32(0x80000000);
    721  1.1.4.2  mrg }
    722  1.1.4.2  mrg 
    723  1.1.4.2  mrg static int
    724  1.1.4.2  mrg siop_add_reselsw(struct siop_adapter *adp, int target, int lunsw_off)
    725  1.1.4.2  mrg {
    726  1.1.4.2  mrg 	uint32_t *script = adp->script;
    727  1.1.4.2  mrg 	int reseloff;
    728  1.1.4.2  mrg 	void *scriptaddr = (void *)local_to_PCI((u_long)adp->script);
    729  1.1.4.2  mrg 
    730  1.1.4.2  mrg 	/*
    731  1.1.4.2  mrg 	 * add an entry to resel switch
    732  1.1.4.2  mrg 	 */
    733  1.1.4.2  mrg 	reseloff = Ent_resel_targ0 / 4 + target * 2;
    734  1.1.4.2  mrg 	if ((ctoh32(script[reseloff]) & 0xff) != 0xff) {
    735  1.1.4.2  mrg 		/* it's not free */
    736  1.1.4.2  mrg 		printf("siop: resel switch full\n");
    737  1.1.4.2  mrg 		return EBUSY;
    738  1.1.4.2  mrg 	}
    739  1.1.4.2  mrg 
    740  1.1.4.2  mrg 	/* JUMP abs_foo, IF target | 0x80; */
    741  1.1.4.2  mrg 	script[reseloff + 0] = htoc32(0x800c0080 | target);
    742  1.1.4.2  mrg 	script[reseloff + 1] =
    743  1.1.4.2  mrg 	    htoc32(scriptaddr + lunsw_off * 4 + Ent_lun_switch_entry);
    744  1.1.4.2  mrg 
    745  1.1.4.2  mrg 	siop_update_scntl3(adp, target, lunsw_off);
    746  1.1.4.2  mrg 	return 0;
    747  1.1.4.2  mrg }
    748  1.1.4.2  mrg 
    749  1.1.4.2  mrg static void
    750  1.1.4.2  mrg siop_update_scntl3(struct siop_adapter *adp, int target, int lunsw_off)
    751  1.1.4.2  mrg {
    752  1.1.4.2  mrg 	uint32_t *script = adp->script;
    753  1.1.4.2  mrg 
    754  1.1.4.2  mrg 	/* MOVE target->id >> 24 TO SCNTL3 */
    755  1.1.4.2  mrg 	script[lunsw_off + (Ent_restore_scntl3 / 4)] =
    756  1.1.4.2  mrg 	    htoc32(0x78030000 | ((adp->clock_div >> 16) & 0x0000ff00));
    757  1.1.4.2  mrg 	/* MOVE target->id >> 8 TO SXFER */
    758  1.1.4.2  mrg 	script[lunsw_off + (Ent_restore_scntl3 / 4) + 2] =
    759  1.1.4.2  mrg 	    htoc32(0x78050000 | (0x000000000 & 0x0000ff00));
    760  1.1.4.2  mrg 	_wbinv((u_long)script, SIOP_SCRIPT_SIZE);
    761  1.1.4.2  mrg }
    762  1.1.4.2  mrg 
    763  1.1.4.2  mrg 
    764  1.1.4.2  mrg /*
    765  1.1.4.2  mrg  * SCSI functions
    766  1.1.4.2  mrg  */
    767  1.1.4.2  mrg 
    768  1.1.4.2  mrg static int
    769  1.1.4.2  mrg _scsi_inquire(struct siop_adapter *adp, int t, int l, int buflen, char *buf)
    770  1.1.4.2  mrg {
    771  1.1.4.2  mrg 	struct scsipi_inquiry *cmd = (struct scsipi_inquiry *)adp->cmd;
    772  1.1.4.2  mrg 	struct scsipi_inquiry_data *inqbuf =
    773  1.1.4.2  mrg 	    (struct scsipi_inquiry_data *)adp->data;
    774  1.1.4.2  mrg 	struct scsi_xfer xs;
    775  1.1.4.2  mrg 	int error;
    776  1.1.4.2  mrg 
    777  1.1.4.2  mrg 	memset(cmd, 0, sizeof(*cmd));
    778  1.1.4.2  mrg 	cmd->opcode = INQUIRY;
    779  1.1.4.2  mrg 	cmd->length = SCSIPI_INQUIRY_LENGTH_SCSI2;
    780  1.1.4.2  mrg 	memset(inqbuf, 0, sizeof(*inqbuf));
    781  1.1.4.2  mrg 
    782  1.1.4.2  mrg 	memset(&xs, 0, sizeof(xs));
    783  1.1.4.2  mrg 	xs.target = t;
    784  1.1.4.2  mrg 	xs.lun = l;
    785  1.1.4.2  mrg 	xs.cmdlen = sizeof(*cmd);
    786  1.1.4.2  mrg 	xs.cmd = (void *)cmd;
    787  1.1.4.2  mrg 	xs.datalen = SCSIPI_INQUIRY_LENGTH_SCSI2;
    788  1.1.4.2  mrg 	xs.data = (void *)inqbuf;
    789  1.1.4.2  mrg 
    790  1.1.4.2  mrg 	xs.error = XS_NOERROR;
    791  1.1.4.2  mrg 	xs.resid = xs.datalen;
    792  1.1.4.2  mrg 	xs.status = SCSI_OK;
    793  1.1.4.2  mrg 
    794  1.1.4.2  mrg 	error = siop_scsi_request(adp, &xs);
    795  1.1.4.2  mrg 	if (error != 0)
    796  1.1.4.2  mrg 		return error;
    797  1.1.4.2  mrg 
    798  1.1.4.2  mrg 	memcpy(buf, inqbuf, buflen);
    799  1.1.4.2  mrg 	return 0;
    800  1.1.4.2  mrg }
    801  1.1.4.2  mrg 
    802  1.1.4.2  mrg static void
    803  1.1.4.2  mrg scsi_request_sense(struct siop_adapter *adp, struct scsi_xfer *xs)
    804  1.1.4.2  mrg {
    805  1.1.4.2  mrg 	struct scsi_request_sense *cmd = adp->sense;
    806  1.1.4.2  mrg 	struct scsi_sense_data *data = (struct scsi_sense_data *)adp->data;
    807  1.1.4.2  mrg 	struct scsi_xfer sense;
    808  1.1.4.2  mrg 	int error;
    809  1.1.4.2  mrg 
    810  1.1.4.2  mrg 	memset(cmd, 0, sizeof(struct scsi_request_sense));
    811  1.1.4.2  mrg 	cmd->opcode = SCSI_REQUEST_SENSE;
    812  1.1.4.2  mrg 	cmd->length = sizeof(struct scsi_sense_data);
    813  1.1.4.2  mrg 	memset(data, 0, sizeof(struct scsi_sense_data));
    814  1.1.4.2  mrg 
    815  1.1.4.2  mrg 	memset(&sense, 0, sizeof(sense));
    816  1.1.4.2  mrg 	sense.target = xs->target;
    817  1.1.4.2  mrg 	sense.lun = xs->lun;
    818  1.1.4.2  mrg 	sense.cmdlen = sizeof(struct scsi_request_sense);
    819  1.1.4.2  mrg 	sense.cmd = (void *)cmd;
    820  1.1.4.2  mrg 	sense.datalen = sizeof(struct scsi_sense_data);
    821  1.1.4.2  mrg 	sense.data = (void *)data;
    822  1.1.4.2  mrg 
    823  1.1.4.2  mrg 	sense.error = XS_NOERROR;
    824  1.1.4.2  mrg 	sense.resid = sense.datalen;
    825  1.1.4.2  mrg 	sense.status = SCSI_OK;
    826  1.1.4.2  mrg 
    827  1.1.4.2  mrg 	error = siop_scsi_request(adp, &sense);
    828  1.1.4.2  mrg 	switch (error) {
    829  1.1.4.2  mrg 	case 0:
    830  1.1.4.2  mrg 		/* we have a valid sense */
    831  1.1.4.2  mrg 		xs->error = XS_SENSE;
    832  1.1.4.2  mrg 		return;
    833  1.1.4.2  mrg 	case EINTR:
    834  1.1.4.2  mrg 		/* REQUEST_SENSE interrupted by bus reset. */
    835  1.1.4.2  mrg 		xs->error = XS_RESET;
    836  1.1.4.2  mrg 		return;
    837  1.1.4.2  mrg 	case EIO:
    838  1.1.4.2  mrg 		 /* request sense coudn't be performed */
    839  1.1.4.2  mrg 		/*
    840  1.1.4.2  mrg 		 * XXX this isn't quite right but we don't have anything
    841  1.1.4.2  mrg 		 * better for now
    842  1.1.4.2  mrg 		 */
    843  1.1.4.2  mrg 		xs->error = XS_DRIVER_STUFFUP;
    844  1.1.4.2  mrg 		return;
    845  1.1.4.2  mrg 	default:
    846  1.1.4.2  mrg 		 /* Notify that request sense failed. */
    847  1.1.4.2  mrg 		xs->error = XS_DRIVER_STUFFUP;
    848  1.1.4.2  mrg 		printf("request sense failed with error %d\n", error);
    849  1.1.4.2  mrg 		return;
    850  1.1.4.2  mrg 	}
    851  1.1.4.2  mrg }
    852  1.1.4.2  mrg 
    853  1.1.4.2  mrg /*
    854  1.1.4.2  mrg  * scsi_interpret_sense:
    855  1.1.4.2  mrg  *
    856  1.1.4.2  mrg  *	Look at the returned sense and act on the error, determining
    857  1.1.4.2  mrg  *	the unix error number to pass back.  (0 = report no error)
    858  1.1.4.2  mrg  *
    859  1.1.4.2  mrg  *	NOTE: If we return ERESTART, we are expected to haved
    860  1.1.4.2  mrg  *	thawed the device!
    861  1.1.4.2  mrg  *
    862  1.1.4.2  mrg  *	THIS IS THE DEFAULT ERROR HANDLER FOR SCSI DEVICES.
    863  1.1.4.2  mrg  */
    864  1.1.4.2  mrg static int
    865  1.1.4.2  mrg scsi_interpret_sense(struct siop_adapter *adp, struct scsi_xfer *xs)
    866  1.1.4.2  mrg {
    867  1.1.4.2  mrg 	struct scsi_sense_data *sense;
    868  1.1.4.2  mrg 	u_int8_t key;
    869  1.1.4.2  mrg 	int error;
    870  1.1.4.2  mrg 	uint32_t info;
    871  1.1.4.2  mrg 	static const char *error_mes[] = {
    872  1.1.4.2  mrg 		"soft error (corrected)",
    873  1.1.4.2  mrg 		"not ready", "medium error",
    874  1.1.4.2  mrg 		"non-media hardware failure", "illegal request",
    875  1.1.4.2  mrg 		"unit attention", "readonly device",
    876  1.1.4.2  mrg 		"no data found", "vendor unique",
    877  1.1.4.2  mrg 		"copy aborted", "command aborted",
    878  1.1.4.2  mrg 		"search returned equal", "volume overflow",
    879  1.1.4.2  mrg 		"verify miscompare", "unknown error key"
    880  1.1.4.2  mrg 	};
    881  1.1.4.2  mrg 
    882  1.1.4.2  mrg 	sense = (struct scsi_sense_data *)xs->data;
    883  1.1.4.2  mrg 
    884  1.1.4.2  mrg 	/* otherwise use the default */
    885  1.1.4.2  mrg 	switch (SSD_RCODE(sense->response_code)) {
    886  1.1.4.2  mrg 
    887  1.1.4.2  mrg 		/*
    888  1.1.4.2  mrg 		 * Old SCSI-1 and SASI devices respond with
    889  1.1.4.2  mrg 		 * codes other than 70.
    890  1.1.4.2  mrg 		 */
    891  1.1.4.2  mrg 	case 0x00:		/* no error (command completed OK) */
    892  1.1.4.2  mrg 		return 0;
    893  1.1.4.2  mrg 	case 0x04:		/* drive not ready after it was selected */
    894  1.1.4.2  mrg 		if (adp->sd->sc_flags & FLAGS_REMOVABLE)
    895  1.1.4.2  mrg 			adp->sd->sc_flags &= ~FLAGS_MEDIA_LOADED;
    896  1.1.4.2  mrg 		/* XXX - display some sort of error here? */
    897  1.1.4.2  mrg 		return EIO;
    898  1.1.4.2  mrg 	case 0x20:		/* invalid command */
    899  1.1.4.2  mrg 		return EINVAL;
    900  1.1.4.2  mrg 	case 0x25:		/* invalid LUN (Adaptec ACB-4000) */
    901  1.1.4.2  mrg 		return EACCES;
    902  1.1.4.2  mrg 
    903  1.1.4.2  mrg 		/*
    904  1.1.4.2  mrg 		 * If it's code 70, use the extended stuff and
    905  1.1.4.2  mrg 		 * interpret the key
    906  1.1.4.2  mrg 		 */
    907  1.1.4.2  mrg 	case 0x71:		/* delayed error */
    908  1.1.4.2  mrg 		key = SSD_SENSE_KEY(sense->flags);
    909  1.1.4.2  mrg 		printf(" DEFERRED ERROR, key = 0x%x\n", key);
    910  1.1.4.2  mrg 		/* FALLTHROUGH */
    911  1.1.4.2  mrg 	case 0x70:
    912  1.1.4.2  mrg 		if ((sense->response_code & SSD_RCODE_VALID) != 0)
    913  1.1.4.2  mrg 			info = _4btol(sense->info);
    914  1.1.4.2  mrg 		else
    915  1.1.4.2  mrg 			info = 0;
    916  1.1.4.2  mrg 		key = SSD_SENSE_KEY(sense->flags);
    917  1.1.4.2  mrg 
    918  1.1.4.2  mrg 		switch (key) {
    919  1.1.4.2  mrg 		case SKEY_NO_SENSE:
    920  1.1.4.2  mrg 		case SKEY_RECOVERED_ERROR:
    921  1.1.4.2  mrg 			if (xs->resid == xs->datalen && xs->datalen) {
    922  1.1.4.2  mrg 				/*
    923  1.1.4.2  mrg 				 * Why is this here?
    924  1.1.4.2  mrg 				 */
    925  1.1.4.2  mrg 				xs->resid = 0;	/* not short read */
    926  1.1.4.2  mrg 			}
    927  1.1.4.2  mrg 		case SKEY_EQUAL:
    928  1.1.4.2  mrg 			error = 0;
    929  1.1.4.2  mrg 			break;
    930  1.1.4.2  mrg 		case SKEY_NOT_READY:
    931  1.1.4.2  mrg 			if (adp->sd->sc_flags & FLAGS_REMOVABLE)
    932  1.1.4.2  mrg 				adp->sd->sc_flags &= ~FLAGS_MEDIA_LOADED;
    933  1.1.4.2  mrg 			if (sense->asc == 0x3A) {
    934  1.1.4.2  mrg 				error = ENODEV; /* Medium not present */
    935  1.1.4.2  mrg 			} else
    936  1.1.4.2  mrg 				error = EIO;
    937  1.1.4.2  mrg 			break;
    938  1.1.4.2  mrg 		case SKEY_ILLEGAL_REQUEST:
    939  1.1.4.2  mrg 			error = EINVAL;
    940  1.1.4.2  mrg 			break;
    941  1.1.4.2  mrg 		case SKEY_UNIT_ATTENTION:
    942  1.1.4.2  mrg 			if (sense->asc == 0x29 &&
    943  1.1.4.2  mrg 			    sense->ascq == 0x00) {
    944  1.1.4.2  mrg 				/* device or bus reset */
    945  1.1.4.2  mrg 				return ERESTART;
    946  1.1.4.2  mrg 			}
    947  1.1.4.2  mrg 			if (adp->sd->sc_flags & FLAGS_REMOVABLE)
    948  1.1.4.2  mrg 				adp->sd->sc_flags &= ~FLAGS_MEDIA_LOADED;
    949  1.1.4.2  mrg 			if (!(adp->sd->sc_flags & FLAGS_REMOVABLE))
    950  1.1.4.2  mrg 				return ERESTART;
    951  1.1.4.2  mrg 			error = EIO;
    952  1.1.4.2  mrg 			break;
    953  1.1.4.2  mrg 		case SKEY_DATA_PROTECT:
    954  1.1.4.2  mrg 			error = EROFS;
    955  1.1.4.2  mrg 			break;
    956  1.1.4.2  mrg 		case SKEY_BLANK_CHECK:
    957  1.1.4.2  mrg 			error = 0;
    958  1.1.4.2  mrg 			break;
    959  1.1.4.2  mrg 		case SKEY_ABORTED_COMMAND:
    960  1.1.4.2  mrg 			break;
    961  1.1.4.2  mrg 		case SKEY_VOLUME_OVERFLOW:
    962  1.1.4.2  mrg 			error = ENOSPC;
    963  1.1.4.2  mrg 			break;
    964  1.1.4.2  mrg 		default:
    965  1.1.4.2  mrg 			error = EIO;
    966  1.1.4.2  mrg 			break;
    967  1.1.4.2  mrg 		}
    968  1.1.4.2  mrg 
    969  1.1.4.2  mrg 		/* Print brief(er) sense information */
    970  1.1.4.2  mrg 		printf("%s", error_mes[key - 1]);
    971  1.1.4.2  mrg 		if ((sense->response_code & SSD_RCODE_VALID) != 0) {
    972  1.1.4.2  mrg 			switch (key) {
    973  1.1.4.2  mrg 			case SKEY_NOT_READY:
    974  1.1.4.2  mrg 			case SKEY_ILLEGAL_REQUEST:
    975  1.1.4.2  mrg 			case SKEY_UNIT_ATTENTION:
    976  1.1.4.2  mrg 			case SKEY_DATA_PROTECT:
    977  1.1.4.2  mrg 				break;
    978  1.1.4.2  mrg 			case SKEY_BLANK_CHECK:
    979  1.1.4.2  mrg 				printf(", requested size: %d (decimal)",
    980  1.1.4.2  mrg 				    info);
    981  1.1.4.2  mrg 				break;
    982  1.1.4.2  mrg 			case SKEY_ABORTED_COMMAND:
    983  1.1.4.2  mrg 				printf(", cmd 0x%x, info 0x%x",
    984  1.1.4.2  mrg 				    xs->cmd->opcode, info);
    985  1.1.4.2  mrg 				break;
    986  1.1.4.2  mrg 			default:
    987  1.1.4.2  mrg 				printf(", info = %d (decimal)", info);
    988  1.1.4.2  mrg 			}
    989  1.1.4.2  mrg 		}
    990  1.1.4.2  mrg 		if (sense->extra_len != 0) {
    991  1.1.4.2  mrg 			int n;
    992  1.1.4.2  mrg 			printf(", data =");
    993  1.1.4.2  mrg 			for (n = 0; n < sense->extra_len; n++)
    994  1.1.4.2  mrg 				printf(" %x", sense->csi[n]);
    995  1.1.4.2  mrg 		}
    996  1.1.4.2  mrg 		printf("\n");
    997  1.1.4.2  mrg 		return error;
    998  1.1.4.2  mrg 
    999  1.1.4.2  mrg 	/*
   1000  1.1.4.2  mrg 	 * Some other code, just report it
   1001  1.1.4.2  mrg 	 */
   1002  1.1.4.2  mrg 	default:
   1003  1.1.4.2  mrg 		printf("Sense Error Code 0x%x",
   1004  1.1.4.2  mrg 			SSD_RCODE(sense->response_code));
   1005  1.1.4.2  mrg 		if ((sense->response_code & SSD_RCODE_VALID) != 0) {
   1006  1.1.4.2  mrg 			struct scsi_sense_data_unextended *usense =
   1007  1.1.4.2  mrg 			    (struct scsi_sense_data_unextended *)sense;
   1008  1.1.4.2  mrg 			printf(" at block no. %d (decimal)",
   1009  1.1.4.2  mrg 			    _3btol(usense->block));
   1010  1.1.4.2  mrg 		}
   1011  1.1.4.2  mrg 		printf("\n");
   1012  1.1.4.2  mrg 		return EIO;
   1013  1.1.4.2  mrg 	}
   1014  1.1.4.2  mrg }
   1015  1.1.4.2  mrg 
   1016  1.1.4.2  mrg static int
   1017  1.1.4.2  mrg scsi_probe(struct siop_adapter *adp)
   1018  1.1.4.2  mrg {
   1019  1.1.4.2  mrg 	struct scsipi_inquiry_data *inqbuf;
   1020  1.1.4.2  mrg 	int found, t, l;
   1021  1.1.4.2  mrg 	uint8_t device;
   1022  1.1.4.2  mrg 	char buf[SCSIPI_INQUIRY_LENGTH_SCSI2],
   1023  1.1.4.2  mrg 	    product[sizeof(inqbuf->product) + 1];
   1024  1.1.4.2  mrg 
   1025  1.1.4.2  mrg 	found = 0;
   1026  1.1.4.2  mrg 	for (t = 0; t < 8; t++) {
   1027  1.1.4.2  mrg 		if (t == adp->id)
   1028  1.1.4.2  mrg 			continue;
   1029  1.1.4.2  mrg 		for (l = 0; l < 8; l++) {
   1030  1.1.4.2  mrg 			if (_scsi_inquire(adp, t, l, sizeof(buf), buf) != 0)
   1031  1.1.4.2  mrg 				continue;
   1032  1.1.4.2  mrg 
   1033  1.1.4.2  mrg 			inqbuf = (struct scsipi_inquiry_data *)buf;
   1034  1.1.4.2  mrg 			device = inqbuf->device & SID_TYPE;
   1035  1.1.4.2  mrg 			if (device == T_NODEVICE)
   1036  1.1.4.2  mrg 				continue;
   1037  1.1.4.2  mrg 			if (device != T_DIRECT &&
   1038  1.1.4.2  mrg 			    device != T_OPTICAL &&
   1039  1.1.4.2  mrg 			    device != T_SIMPLE_DIRECT)
   1040  1.1.4.2  mrg 				continue;
   1041  1.1.4.2  mrg 
   1042  1.1.4.2  mrg 			memset(product, 0, sizeof(product));
   1043  1.1.4.2  mrg 			strncpy(product, inqbuf->product, sizeof(product) - 1);
   1044  1.1.4.2  mrg 			printf("sd(%d,%d,[0-7]): <%s>\n", t, l, product);
   1045  1.1.4.2  mrg 			found++;
   1046  1.1.4.2  mrg 		}
   1047  1.1.4.2  mrg 	}
   1048  1.1.4.2  mrg 	return found;
   1049  1.1.4.2  mrg }
   1050  1.1.4.2  mrg 
   1051  1.1.4.2  mrg int
   1052  1.1.4.2  mrg scsi_inquire(struct sd_softc *sd, int buflen, void *buf)
   1053  1.1.4.2  mrg {
   1054  1.1.4.2  mrg 	struct siop_adapter *adp;
   1055  1.1.4.2  mrg 	int error;
   1056  1.1.4.2  mrg 
   1057  1.1.4.2  mrg 	if (sd->sc_bus != 0)
   1058  1.1.4.2  mrg 		return ENOTSUP;
   1059  1.1.4.2  mrg 	if (adapt.addr == 0xffffffff)
   1060  1.1.4.2  mrg 		return ENOENT;
   1061  1.1.4.2  mrg 	adp = &adapt;
   1062  1.1.4.2  mrg 
   1063  1.1.4.2  mrg 	adp->sd = sd;
   1064  1.1.4.2  mrg 	error = _scsi_inquire(adp, sd->sc_target, sd->sc_lun, buflen, buf);
   1065  1.1.4.2  mrg 	adp->sd = NULL;
   1066  1.1.4.2  mrg 
   1067  1.1.4.2  mrg 	return error;
   1068  1.1.4.2  mrg }
   1069  1.1.4.2  mrg 
   1070  1.1.4.2  mrg /*
   1071  1.1.4.2  mrg  * scsi_mode_sense
   1072  1.1.4.2  mrg  *	get a sense page from a device
   1073  1.1.4.2  mrg  */
   1074  1.1.4.2  mrg 
   1075  1.1.4.2  mrg int
   1076  1.1.4.2  mrg scsi_mode_sense(struct sd_softc *sd, int byte2, int page,
   1077  1.1.4.2  mrg 		  struct scsi_mode_parameter_header_6 *data, int len)
   1078  1.1.4.2  mrg {
   1079  1.1.4.2  mrg 	struct scsi_mode_sense_6 cmd;
   1080  1.1.4.2  mrg 
   1081  1.1.4.2  mrg 	memset(&cmd, 0, sizeof(cmd));
   1082  1.1.4.2  mrg 	cmd.opcode = SCSI_MODE_SENSE_6;
   1083  1.1.4.2  mrg 	cmd.byte2 = byte2;
   1084  1.1.4.2  mrg 	cmd.page = page;
   1085  1.1.4.2  mrg 	cmd.length = len & 0xff;
   1086  1.1.4.2  mrg 
   1087  1.1.4.2  mrg 	return scsi_command(sd, (void *)&cmd, sizeof(cmd), (void *)data, len);
   1088  1.1.4.2  mrg }
   1089  1.1.4.2  mrg 
   1090  1.1.4.2  mrg int
   1091  1.1.4.2  mrg scsi_command(struct sd_softc *sd, void *cmd, int cmdlen, void *data,
   1092  1.1.4.2  mrg 	     int datalen)
   1093  1.1.4.2  mrg {
   1094  1.1.4.2  mrg 	struct siop_adapter *adp;
   1095  1.1.4.2  mrg 	struct scsi_xfer xs;
   1096  1.1.4.2  mrg 	int error;
   1097  1.1.4.2  mrg 
   1098  1.1.4.2  mrg 	if (sd->sc_bus != 0)
   1099  1.1.4.2  mrg 		return ENOTSUP;
   1100  1.1.4.2  mrg 	if (adapt.addr == 0xffffffff)
   1101  1.1.4.2  mrg 		return ENOENT;
   1102  1.1.4.2  mrg 	adp = &adapt;
   1103  1.1.4.2  mrg 
   1104  1.1.4.2  mrg 	memcpy(adp->cmd, cmd, cmdlen);
   1105  1.1.4.2  mrg 	adp->sd = sd;
   1106  1.1.4.2  mrg 
   1107  1.1.4.2  mrg 	memset(&xs, 0, sizeof(xs));
   1108  1.1.4.2  mrg 	xs.target = sd->sc_target;
   1109  1.1.4.2  mrg 	xs.lun = sd->sc_lun;
   1110  1.1.4.2  mrg 	xs.cmdlen = cmdlen;
   1111  1.1.4.2  mrg 	xs.cmd = adp->cmd;
   1112  1.1.4.2  mrg 	xs.datalen = datalen;
   1113  1.1.4.2  mrg 	xs.data = adp->data;
   1114  1.1.4.2  mrg 
   1115  1.1.4.2  mrg 	xs.error = XS_NOERROR;
   1116  1.1.4.2  mrg 	xs.resid = datalen;
   1117  1.1.4.2  mrg 	xs.status = SCSI_OK;
   1118  1.1.4.2  mrg 
   1119  1.1.4.2  mrg 	error = siop_scsi_request(adp, &xs);
   1120  1.1.4.2  mrg 	adp->sd = NULL;
   1121  1.1.4.2  mrg 	if (error != 0)
   1122  1.1.4.2  mrg 		return error;
   1123  1.1.4.2  mrg 
   1124  1.1.4.2  mrg 	if (datalen > 0)
   1125  1.1.4.2  mrg 		memcpy(data, adp->data, datalen);
   1126  1.1.4.2  mrg 	return 0;
   1127  1.1.4.2  mrg }
   1128  1.1.4.2  mrg 
   1129  1.1.4.2  mrg /*
   1130  1.1.4.2  mrg  * Initialize the device.
   1131  1.1.4.2  mrg  */
   1132  1.1.4.2  mrg int
   1133  1.1.4.2  mrg siop_init(int bus, int dev, int func)
   1134  1.1.4.2  mrg {
   1135  1.1.4.2  mrg 	struct siop_adapter tmp;
   1136  1.1.4.2  mrg 	struct siop_xfer *xfer;
   1137  1.1.4.2  mrg 	struct scsipi_generic *cmd;
   1138  1.1.4.2  mrg 	struct scsi_request_sense *sense;
   1139  1.1.4.2  mrg 	uint32_t reg;
   1140  1.1.4.2  mrg 	u_long addr;
   1141  1.1.4.2  mrg 	uint32_t *script;
   1142  1.1.4.2  mrg 	int slot, id, i;
   1143  1.1.4.2  mrg 	void *scriptaddr;
   1144  1.1.4.2  mrg 	u_char *data;
   1145  1.1.4.2  mrg 	const int clock_div = 3;		/* 53c810 */
   1146  1.1.4.2  mrg 
   1147  1.1.4.2  mrg 	slot = PCISlotnum(bus, dev, func);
   1148  1.1.4.2  mrg 	if (slot == -1)
   1149  1.1.4.2  mrg 		return ENOENT;
   1150  1.1.4.2  mrg 
   1151  1.1.4.2  mrg 	addr = PCIAddress(slot, 1, PCI_MAPREG_TYPE_MEM);
   1152  1.1.4.2  mrg 	if (addr == 0xffffffff)
   1153  1.1.4.2  mrg 		return EINVAL;
   1154  1.1.4.2  mrg 	enablePCI(slot, 0, 1, 1);
   1155  1.1.4.2  mrg 
   1156  1.1.4.2  mrg 	script = ALLOC(uint32_t, SIOP_SCRIPT_SIZE);
   1157  1.1.4.2  mrg 	if (script == NULL)
   1158  1.1.4.2  mrg 		return ENOMEM;
   1159  1.1.4.2  mrg 	scriptaddr = (void *)local_to_PCI((u_long)script);
   1160  1.1.4.2  mrg 	cmd = ALLOC(struct scsipi_generic, SIOP_SCSI_COMMAND_SIZE);
   1161  1.1.4.2  mrg 	if (cmd == NULL)
   1162  1.1.4.2  mrg 		return ENOMEM;
   1163  1.1.4.2  mrg 	sense = ALLOC(struct scsi_request_sense, SIOP_SCSI_COMMAND_SIZE);
   1164  1.1.4.2  mrg 	if (sense == NULL)
   1165  1.1.4.2  mrg 		return ENOMEM;
   1166  1.1.4.2  mrg 	data = ALLOC(u_char, SIOP_SCSI_DATA_SIZE);
   1167  1.1.4.2  mrg 	if (data == NULL)
   1168  1.1.4.2  mrg 		return ENOMEM;
   1169  1.1.4.2  mrg 	xfer = ALLOC(struct siop_xfer, sizeof(struct siop_xfer));
   1170  1.1.4.2  mrg 	if (xfer == NULL)
   1171  1.1.4.2  mrg 		return ENOMEM;
   1172  1.1.4.2  mrg 	siop_xfer_setup(xfer, scriptaddr);
   1173  1.1.4.2  mrg 
   1174  1.1.4.2  mrg 	id = readb(addr + SIOP_SCID) & SCID_ENCID_MASK;
   1175  1.1.4.2  mrg 
   1176  1.1.4.2  mrg 	/* reset bus */
   1177  1.1.4.2  mrg 	reg = readb(addr + SIOP_SCNTL1);
   1178  1.1.4.2  mrg 	writeb(addr + SIOP_SCNTL1, reg | SCNTL1_RST);
   1179  1.1.4.2  mrg 	delay(100);
   1180  1.1.4.2  mrg 	writeb(addr + SIOP_SCNTL1, reg);
   1181  1.1.4.2  mrg 
   1182  1.1.4.2  mrg 	/* reset the chip */
   1183  1.1.4.2  mrg 	writeb(addr + SIOP_ISTAT, ISTAT_SRST);
   1184  1.1.4.2  mrg 	delay(1000);
   1185  1.1.4.2  mrg 	writeb(addr + SIOP_ISTAT, 0);
   1186  1.1.4.2  mrg 
   1187  1.1.4.2  mrg 	/* init registers */
   1188  1.1.4.2  mrg 	writeb(addr + SIOP_SCNTL0, SCNTL0_ARB_MASK | SCNTL0_EPC | SCNTL0_AAP);
   1189  1.1.4.2  mrg 	writeb(addr + SIOP_SCNTL1, 0);
   1190  1.1.4.2  mrg 	writeb(addr + SIOP_SCNTL3, clock_div);
   1191  1.1.4.2  mrg 	writeb(addr + SIOP_SXFER, 0);
   1192  1.1.4.2  mrg 	writeb(addr + SIOP_DIEN, 0xff);
   1193  1.1.4.2  mrg 	writeb(addr + SIOP_SIEN0, 0xff & ~(SIEN0_CMP | SIEN0_SEL | SIEN0_RSL));
   1194  1.1.4.2  mrg 	writeb(addr + SIOP_SIEN1, 0xff & ~(SIEN1_HTH | SIEN1_GEN));
   1195  1.1.4.2  mrg 	writeb(addr + SIOP_STEST2, 0);
   1196  1.1.4.2  mrg 	writeb(addr + SIOP_STEST3, STEST3_TE);
   1197  1.1.4.2  mrg 	writeb(addr + SIOP_STIME0, (0xb << STIME0_SEL_SHIFT));
   1198  1.1.4.2  mrg 	writeb(addr + SIOP_SCID, id | SCID_RRE);
   1199  1.1.4.2  mrg 	writeb(addr + SIOP_RESPID0, 1 << id);
   1200  1.1.4.2  mrg 	writeb(addr + SIOP_DCNTL, DCNTL_COM);
   1201  1.1.4.2  mrg 
   1202  1.1.4.2  mrg 	siop_pci_reset(addr);
   1203  1.1.4.2  mrg 
   1204  1.1.4.2  mrg 	/* copy and patch the script */
   1205  1.1.4.2  mrg 	for (i = 0; i < __arraycount(siop_script); i++)
   1206  1.1.4.2  mrg 		script[i] = htoc32(siop_script[i]);
   1207  1.1.4.2  mrg 	for (i = 0; i < __arraycount(E_abs_msgin_Used); i++)
   1208  1.1.4.2  mrg 		script[E_abs_msgin_Used[i]] =
   1209  1.1.4.2  mrg 		    htoc32(scriptaddr + Ent_msgin_space);
   1210  1.1.4.2  mrg 
   1211  1.1.4.2  mrg 	/* start script */
   1212  1.1.4.2  mrg 	_wbinv((u_long)script, SIOP_SCRIPT_SIZE);
   1213  1.1.4.2  mrg 	writel(addr + SIOP_DSP, (int)scriptaddr + Ent_reselect);
   1214  1.1.4.2  mrg 
   1215  1.1.4.2  mrg 	memset(&tmp, 0, sizeof(tmp));
   1216  1.1.4.2  mrg 	tmp.id = id;
   1217  1.1.4.2  mrg 	tmp.clock_div = clock_div;
   1218  1.1.4.2  mrg 	tmp.addr = addr;
   1219  1.1.4.2  mrg 	tmp.script = script;
   1220  1.1.4.2  mrg 	tmp.xfer = xfer;
   1221  1.1.4.2  mrg 	tmp.cmd = cmd;
   1222  1.1.4.2  mrg 	tmp.sense = sense;
   1223  1.1.4.2  mrg 	tmp.data = data;
   1224  1.1.4.2  mrg 	tmp.currschedslot = 0;
   1225  1.1.4.2  mrg 	tmp.sel_t = -1;
   1226  1.1.4.2  mrg 
   1227  1.1.4.2  mrg 	if (scsi_probe(&tmp) == 0) {
   1228  1.1.4.2  mrg 		adapt.addr = 0xffffffff;
   1229  1.1.4.2  mrg 		return ENXIO;
   1230  1.1.4.2  mrg 	}
   1231  1.1.4.2  mrg 	adapt = tmp;
   1232  1.1.4.2  mrg 	return 0;
   1233  1.1.4.2  mrg }
   1234