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