Home | History | Annotate | Line # | Download | only in ic
isp_netbsd.c revision 1.18.2.2
      1  1.18.2.2  thorpej /* $NetBSD: isp_netbsd.c,v 1.18.2.2 1999/10/19 20:02:23 thorpej Exp $ */
      2       1.1   mjacob /*
      3       1.1   mjacob  * Platform (NetBSD) dependent common attachment code for Qlogic adapters.
      4      1.15   mjacob  * Matthew Jacob <mjacob (at) nas.nasa.gov>
      5      1.15   mjacob  */
      6      1.15   mjacob /*
      7      1.15   mjacob  * Copyright (C) 1997, 1998, 1999 National Aeronautics & Space Administration
      8       1.1   mjacob  * All rights reserved.
      9       1.1   mjacob  *
     10       1.1   mjacob  * Redistribution and use in source and binary forms, with or without
     11       1.1   mjacob  * modification, are permitted provided that the following conditions
     12       1.1   mjacob  * are met:
     13       1.1   mjacob  * 1. Redistributions of source code must retain the above copyright
     14      1.15   mjacob  *    notice, this list of conditions and the following disclaimer.
     15       1.1   mjacob  * 2. Redistributions in binary form must reproduce the above copyright
     16       1.1   mjacob  *    notice, this list of conditions and the following disclaimer in the
     17       1.1   mjacob  *    documentation and/or other materials provided with the distribution.
     18       1.1   mjacob  * 3. The name of the author may not be used to endorse or promote products
     19      1.15   mjacob  *    derived from this software without specific prior written permission
     20       1.1   mjacob  *
     21      1.15   mjacob  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     22      1.15   mjacob  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     23      1.15   mjacob  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     24      1.15   mjacob  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     25      1.15   mjacob  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     26      1.15   mjacob  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27      1.15   mjacob  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28      1.15   mjacob  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29      1.15   mjacob  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     30      1.15   mjacob  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31       1.1   mjacob  */
     32       1.1   mjacob 
     33       1.1   mjacob #include <dev/ic/isp_netbsd.h>
     34      1.17   mjacob #include <sys/scsiio.h>
     35       1.1   mjacob 
     36       1.1   mjacob static void ispminphys __P((struct buf *));
     37  1.18.2.1  thorpej static void isp_scsipi_request __P((struct scsipi_channel *,
     38  1.18.2.1  thorpej 	scsipi_adapter_req_t, void *));
     39      1.17   mjacob static int
     40  1.18.2.1  thorpej ispioctl __P((struct scsipi_channel *, u_long, caddr_t, int, struct proc *));
     41       1.1   mjacob 
     42       1.1   mjacob static int isp_poll __P((struct ispsoftc *, ISP_SCSI_XFER_T *, int));
     43      1.10   mjacob static void isp_watch __P((void *));
     44      1.17   mjacob static void isp_command_requeue __P((void *));
     45      1.10   mjacob static void isp_internal_restart __P((void *));
     46      1.10   mjacob 
     47       1.1   mjacob /*
     48       1.1   mjacob  * Complete attachment of hardware, include subdevices.
     49       1.1   mjacob  */
     50       1.1   mjacob void
     51       1.1   mjacob isp_attach(isp)
     52       1.1   mjacob 	struct ispsoftc *isp;
     53       1.1   mjacob {
     54  1.18.2.1  thorpej 	struct scsipi_adapter *adapt = &isp->isp_osinfo._adapter;
     55  1.18.2.1  thorpej 	struct scsipi_channel *chan;
     56  1.18.2.1  thorpej 	int i;
     57       1.6  thorpej 
     58       1.1   mjacob 	isp->isp_state = ISP_RUNSTATE;
     59      1.18   mjacob 	TAILQ_INIT(&isp->isp_osinfo.waitq);	/* XXX 2nd Bus? */
     60       1.1   mjacob 
     61  1.18.2.1  thorpej 	/*
     62  1.18.2.1  thorpej 	 * Fill in the scsipi_adapter.
     63  1.18.2.1  thorpej 	 */
     64  1.18.2.1  thorpej 	adapt->adapt_dev = &isp->isp_osinfo._dev;
     65  1.18.2.1  thorpej 	if (IS_FC(isp) == 0 && IS_12X0(isp) != 0)
     66  1.18.2.1  thorpej 		adapt->adapt_nchannels = 2;
     67  1.18.2.1  thorpej 	else
     68  1.18.2.1  thorpej 		adapt->adapt_nchannels = 1;
     69  1.18.2.1  thorpej 	adapt->adapt_openings = isp->isp_maxcmds;
     70  1.18.2.1  thorpej 	adapt->adapt_max_periph = adapt->adapt_openings;
     71  1.18.2.1  thorpej 	adapt->adapt_request = isp_scsipi_request;
     72  1.18.2.1  thorpej 	adapt->adapt_minphys = ispminphys;
     73  1.18.2.1  thorpej 	adapt->adapt_ioctl = ispioctl;
     74  1.18.2.1  thorpej 
     75  1.18.2.1  thorpej 	/*
     76  1.18.2.1  thorpej 	 * Fill in the scsipi_channel(s).
     77  1.18.2.1  thorpej 	 */
     78  1.18.2.1  thorpej 	for (i = 0; i < adapt->adapt_nchannels; i++) {
     79  1.18.2.1  thorpej 		chan = &isp->isp_osinfo._channels[i];
     80  1.18.2.1  thorpej 		chan->chan_adapter = adapt;
     81  1.18.2.1  thorpej 		chan->chan_bustype = &scsi_bustype;
     82  1.18.2.1  thorpej 		chan->chan_channel = i;
     83  1.18.2.1  thorpej 
     84  1.18.2.1  thorpej 		if (IS_FC(isp)) {
     85  1.18.2.1  thorpej 			fcparam *fcp = isp->isp_param;
     86  1.18.2.1  thorpej 			fcp = &fcp[i];
     87  1.18.2.1  thorpej 
     88  1.18.2.1  thorpej 			/*
     89  1.18.2.1  thorpej 			 * Give it another chance here to come alive...
     90  1.18.2.1  thorpej 			 */
     91  1.18.2.1  thorpej 			if (fcp->isp_fwstate != FW_READY) {
     92  1.18.2.1  thorpej 				(void) isp_control(isp, ISPCTL_FCLINK_TEST,
     93  1.18.2.1  thorpej 				    NULL);
     94  1.18.2.1  thorpej 			}
     95  1.18.2.1  thorpej 			chan->chan_ntargets = MAX_FC_TARG;
     96      1.11   mjacob #ifdef	ISP2100_SCCLUN
     97  1.18.2.1  thorpej 			/*
     98  1.18.2.1  thorpej 			 * 16 bits worth, but let's be reasonable..
     99  1.18.2.1  thorpej 			 */
    100  1.18.2.1  thorpej 			chan->chan_nluns = 256;
    101       1.7   mjacob #else
    102  1.18.2.1  thorpej 			chan->chan_nluns = 16;
    103       1.7   mjacob #endif
    104  1.18.2.1  thorpej 			chan->chan_id = fcp->isp_loopid;
    105       1.7   mjacob 		} else {
    106  1.18.2.1  thorpej 			sdparam *sdp = isp->isp_param;
    107  1.18.2.1  thorpej 			sdp = &sdp[i];
    108  1.18.2.1  thorpej 
    109  1.18.2.1  thorpej 			chan->chan_ntargets = MAX_TARGETS;
    110  1.18.2.1  thorpej 			if (isp->isp_bustype == ISP_BT_SBUS)
    111  1.18.2.1  thorpej 				chan->chan_nluns = 8;
    112  1.18.2.1  thorpej 			else {
    113  1.18.2.1  thorpej #if 0
    114  1.18.2.1  thorpej 				/* Too many broken targets... */
    115  1.18.2.1  thorpej 				if (isp->isp_fwrev >= ISP_FW_REV(7,55,0))
    116  1.18.2.1  thorpej 					chan->chan_nluns = 32;
    117  1.18.2.1  thorpej 				else
    118       1.7   mjacob #endif
    119  1.18.2.1  thorpej 					chan->chan_nluns = 7;
    120  1.18.2.1  thorpej 			}
    121  1.18.2.1  thorpej 			chan->chan_id = sdp->isp_initiator_id;
    122      1.14   mjacob 		}
    123       1.1   mjacob 	}
    124       1.8   mjacob 
    125       1.8   mjacob 	/*
    126      1.10   mjacob 	 * Send a SCSI Bus Reset (used to be done as part of attach,
    127      1.10   mjacob 	 * but now left to the OS outer layers).
    128      1.10   mjacob 	 */
    129      1.14   mjacob 	if (IS_SCSI(isp)) {
    130  1.18.2.1  thorpej 		for (i = 0; i < adapt->adapt_nchannels; i++)
    131  1.18.2.1  thorpej 			(void) isp_control(isp, ISPCTL_RESET_BUS, &i);
    132      1.11   mjacob 		SYS_DELAY(2*1000000);
    133      1.11   mjacob 	}
    134      1.10   mjacob 
    135      1.10   mjacob 	/*
    136       1.8   mjacob 	 * Start the watchdog.
    137       1.8   mjacob 	 */
    138       1.8   mjacob 	isp->isp_dogactive = 1;
    139      1.17   mjacob 	timeout(isp_watch, isp, WATCH_INTERVAL * hz);
    140       1.8   mjacob 
    141       1.8   mjacob 	/*
    142       1.8   mjacob 	 * And attach children (if any).
    143       1.8   mjacob 	 */
    144  1.18.2.1  thorpej 	for (i = 0; i < adapt->adapt_nchannels; i++)
    145  1.18.2.1  thorpej 		(void) config_found((void *)isp, &isp->isp_osinfo._channels[i],
    146  1.18.2.1  thorpej 		    scsiprint);
    147       1.1   mjacob }
    148       1.1   mjacob 
    149       1.1   mjacob /*
    150       1.1   mjacob  * minphys our xfers
    151       1.1   mjacob  *
    152       1.1   mjacob  * Unfortunately, the buffer pointer describes the target device- not the
    153       1.1   mjacob  * adapter device, so we can't use the pointer to find out what kind of
    154       1.1   mjacob  * adapter we are and adjust accordingly.
    155       1.1   mjacob  */
    156       1.1   mjacob 
    157       1.1   mjacob static void
    158       1.1   mjacob ispminphys(bp)
    159       1.1   mjacob 	struct buf *bp;
    160       1.1   mjacob {
    161       1.1   mjacob 	/*
    162       1.1   mjacob 	 * XX: Only the 1020 has a 24 bit limit.
    163       1.1   mjacob 	 */
    164       1.1   mjacob 	if (bp->b_bcount >= (1 << 24)) {
    165       1.1   mjacob 		bp->b_bcount = (1 << 24);
    166       1.1   mjacob 	}
    167       1.1   mjacob 	minphys(bp);
    168       1.1   mjacob }
    169       1.1   mjacob 
    170      1.17   mjacob static int
    171  1.18.2.1  thorpej ispioctl(chan, cmd, addr, flag, p)
    172  1.18.2.1  thorpej 	struct scsipi_channel *chan;
    173      1.17   mjacob 	u_long cmd;
    174      1.17   mjacob 	caddr_t addr;
    175      1.17   mjacob 	int flag;
    176      1.17   mjacob 	struct proc *p;
    177      1.17   mjacob {
    178  1.18.2.1  thorpej 	struct ispsoftc *isp = (void *)chan->chan_adapter->adapt_dev;
    179  1.18.2.1  thorpej 	int s, ch, retval = ENOTTY;
    180      1.17   mjacob 
    181      1.17   mjacob 	switch (cmd) {
    182      1.17   mjacob 	case SCBUSIORESET:
    183  1.18.2.1  thorpej 		ch = chan->chan_channel;
    184      1.17   mjacob 		s = splbio();
    185  1.18.2.1  thorpej 		if (isp_control(isp, ISPCTL_RESET_BUS, &ch))
    186      1.17   mjacob 			retval = EIO;
    187      1.17   mjacob 		else
    188      1.17   mjacob 			retval = 0;
    189      1.17   mjacob 		(void) splx(s);
    190      1.17   mjacob 		break;
    191      1.17   mjacob 	default:
    192      1.17   mjacob 		break;
    193       1.3   mjacob 	}
    194      1.17   mjacob 	return (retval);
    195      1.17   mjacob }
    196      1.17   mjacob 
    197  1.18.2.1  thorpej static void
    198  1.18.2.1  thorpej isp_scsipi_request(chan, req, arg)
    199  1.18.2.1  thorpej 	struct scsipi_channel *chan;
    200  1.18.2.1  thorpej 	scsipi_adapter_req_t req;
    201  1.18.2.1  thorpej 	void *arg;
    202      1.17   mjacob {
    203  1.18.2.1  thorpej 	struct scsipi_xfer *xs;
    204  1.18.2.1  thorpej 	struct ispsoftc *isp = (void *)chan->chan_adapter->adapt_dev;
    205      1.17   mjacob 	int result, s;
    206      1.11   mjacob 
    207  1.18.2.1  thorpej 	switch (req) {
    208  1.18.2.1  thorpej 	case ADAPTER_REQ_RUN_XFER:
    209  1.18.2.2  thorpej 		xs = arg;
    210  1.18.2.1  thorpej 		s = splbio();
    211  1.18.2.1  thorpej 		if (isp->isp_state < ISP_RUNSTATE) {
    212  1.18.2.1  thorpej 			DISABLE_INTS(isp);
    213  1.18.2.1  thorpej 			isp_init(isp);
    214  1.18.2.1  thorpej 			if (isp->isp_state != ISP_INITSTATE) {
    215  1.18.2.1  thorpej 				ENABLE_INTS(isp);
    216  1.18.2.1  thorpej 				(void) splx(s);
    217  1.18.2.1  thorpej 				XS_SETERR(xs, HBA_BOTCH);
    218  1.18.2.1  thorpej 				XS_CMD_DONE(xs);
    219  1.18.2.1  thorpej 				return;
    220  1.18.2.1  thorpej 			}
    221  1.18.2.1  thorpej 			isp->isp_state = ISP_RUNSTATE;
    222      1.11   mjacob 			ENABLE_INTS(isp);
    223  1.18.2.1  thorpej 		}
    224      1.11   mjacob 
    225  1.18.2.1  thorpej 		/*
    226  1.18.2.1  thorpej 		 * Check for queue blockage...
    227  1.18.2.1  thorpej 		 * XXX Should be done in the mid-layer.
    228  1.18.2.1  thorpej 		 */
    229  1.18.2.1  thorpej 		if (isp->isp_osinfo.blocked) {
    230  1.18.2.1  thorpej 			if (xs->xs_control & XS_CTL_POLL) {
    231  1.18.2.1  thorpej 				xs->error = XS_BUSY;
    232  1.18.2.1  thorpej 				scsipi_done(xs);
    233  1.18.2.1  thorpej 				splx(s);
    234  1.18.2.1  thorpej 				return;
    235  1.18.2.1  thorpej 			}
    236  1.18.2.1  thorpej 			TAILQ_INSERT_TAIL(&isp->isp_osinfo.waitq, xs,
    237  1.18.2.1  thorpej 			    channel_q);
    238      1.10   mjacob 			splx(s);
    239  1.18.2.1  thorpej 			return;
    240      1.10   mjacob 		}
    241      1.17   mjacob 
    242  1.18.2.1  thorpej 		DISABLE_INTS(isp);
    243  1.18.2.1  thorpej 		result = ispscsicmd(xs);
    244  1.18.2.1  thorpej 		ENABLE_INTS(isp);
    245  1.18.2.1  thorpej 
    246      1.17   mjacob 		switch (result) {
    247      1.17   mjacob 		case CMD_QUEUED:
    248  1.18.2.1  thorpej 			/*
    249  1.18.2.1  thorpej 			 * If we're not polling for completion, just return.
    250  1.18.2.1  thorpej 			 */
    251  1.18.2.1  thorpej 			if ((xs->xs_control & XS_CTL_POLL) == 0) {
    252  1.18.2.1  thorpej 				(void) splx(s);
    253  1.18.2.1  thorpej 				return;
    254  1.18.2.1  thorpej 			}
    255      1.17   mjacob 			break;
    256  1.18.2.1  thorpej 
    257      1.17   mjacob 		case CMD_EAGAIN:
    258  1.18.2.1  thorpej 			/*
    259  1.18.2.1  thorpej 			 * Adapter resource shortage of some sort.  Should
    260  1.18.2.1  thorpej 			 * retry later.
    261  1.18.2.1  thorpej 			 */
    262  1.18.2.1  thorpej 			XS_SETERR(xs, XS_RESOURCE_SHORTAGE);
    263  1.18.2.1  thorpej 			XS_CMD_DONE(xs);
    264  1.18.2.1  thorpej 			(void) splx(s);
    265  1.18.2.1  thorpej 			return;
    266  1.18.2.1  thorpej 
    267      1.17   mjacob 		case CMD_RQLATER:
    268  1.18.2.1  thorpej 			/*
    269  1.18.2.1  thorpej 			 * XXX I think what we should do here is freeze
    270  1.18.2.1  thorpej 			 * XXX the channel queue, and do a timed thaw
    271  1.18.2.1  thorpej 			 * XXX of it.  Need to add this to the mid-layer.
    272  1.18.2.1  thorpej 			 */
    273  1.18.2.1  thorpej 			if ((xs->xs_control & XS_CTL_POLL) != 0) {
    274  1.18.2.1  thorpej 				XS_SETERR(xs, XS_DRIVER_STUFFUP);
    275  1.18.2.1  thorpej 				XS_CMD_DONE(xs);
    276  1.18.2.1  thorpej 			} else
    277  1.18.2.1  thorpej 				timeout(isp_command_requeue, xs, hz);
    278  1.18.2.1  thorpej 			(void) splx(s);
    279  1.18.2.1  thorpej 			return;
    280  1.18.2.1  thorpej 
    281      1.17   mjacob 		case CMD_COMPLETE:
    282  1.18.2.1  thorpej 			/*
    283  1.18.2.1  thorpej 			 * Something went horribly wrong, xs->error is set,
    284  1.18.2.1  thorpej 			 * and we just need to finish it off.
    285  1.18.2.1  thorpej 			 */
    286  1.18.2.1  thorpej 			XS_CMD_DONE(xs);
    287  1.18.2.1  thorpej 			(void) splx(s);
    288  1.18.2.1  thorpej 			return;
    289      1.17   mjacob 		}
    290       1.1   mjacob 
    291  1.18.2.1  thorpej 		/*
    292  1.18.2.1  thorpej 		 * If we can't use interrupts, poll on completion.
    293  1.18.2.1  thorpej 		 */
    294      1.17   mjacob 		if (isp_poll(isp, xs, XS_TIME(xs))) {
    295      1.17   mjacob 			/*
    296      1.17   mjacob 			 * If no other error occurred but we didn't finish,
    297      1.17   mjacob 			 * something bad happened.
    298      1.17   mjacob 			 */
    299      1.17   mjacob 			if (XS_IS_CMD_DONE(xs) == 0) {
    300      1.17   mjacob 				if (isp_control(isp, ISPCTL_ABORT_CMD, xs)) {
    301      1.17   mjacob 					isp_restart(isp);
    302      1.17   mjacob 				}
    303      1.17   mjacob 				if (XS_NOERR(xs)) {
    304      1.17   mjacob 					XS_SETERR(xs, HBA_BOTCH);
    305      1.17   mjacob 				}
    306  1.18.2.1  thorpej 				XS_CMD_DONE(xs);
    307       1.1   mjacob 			}
    308       1.1   mjacob 		}
    309  1.18.2.1  thorpej 		(void) splx(s);
    310  1.18.2.1  thorpej 		return;
    311  1.18.2.1  thorpej 
    312  1.18.2.1  thorpej 	case ADAPTER_REQ_GROW_RESOURCES:
    313  1.18.2.1  thorpej 		/* XXX Not supported. */
    314  1.18.2.1  thorpej 		return;
    315  1.18.2.1  thorpej 
    316  1.18.2.1  thorpej 	case ADAPTER_REQ_SET_XFER_MODE:
    317  1.18.2.1  thorpej 		if (isp->isp_type & ISP_HA_SCSI) {
    318  1.18.2.1  thorpej 			sdparam *sdp = isp->isp_param;
    319  1.18.2.1  thorpej 			struct scsipi_periph *periph = arg;
    320  1.18.2.1  thorpej 			u_int16_t flags;
    321  1.18.2.1  thorpej 
    322  1.18.2.1  thorpej 			sdp = &sdp[periph->periph_channel->chan_channel];
    323  1.18.2.1  thorpej 
    324  1.18.2.1  thorpej 			flags =
    325  1.18.2.1  thorpej 			    sdp->isp_devparam[periph->periph_target].dev_flags;
    326  1.18.2.1  thorpej 			flags &= ~(DPARM_WIDE|DPARM_SYNC|DPARM_TQING);
    327  1.18.2.1  thorpej 
    328  1.18.2.1  thorpej 			if (periph->periph_cap & PERIPH_CAP_SYNC)
    329  1.18.2.1  thorpej 				flags |= DPARM_SYNC;
    330  1.18.2.1  thorpej 
    331  1.18.2.1  thorpej 			if (periph->periph_cap & PERIPH_CAP_WIDE16)
    332  1.18.2.1  thorpej 				flags |= DPARM_WIDE;
    333  1.18.2.1  thorpej 
    334  1.18.2.1  thorpej 			if (periph->periph_cap & PERIPH_CAP_TQING)
    335  1.18.2.1  thorpej 				flags |= DPARM_TQING;
    336  1.18.2.1  thorpej 
    337  1.18.2.1  thorpej 			sdp->isp_devparam[periph->periph_target].dev_flags =
    338  1.18.2.1  thorpej 			    flags;
    339  1.18.2.1  thorpej 			sdp->isp_devparam[periph->periph_target].dev_update = 1;
    340  1.18.2.1  thorpej 			isp->isp_update |=
    341  1.18.2.1  thorpej 			    (1 << periph->periph_channel->chan_channel);
    342  1.18.2.1  thorpej 			(void) isp_control(isp, ISPCTL_UPDATE_PARAMS, NULL);
    343  1.18.2.1  thorpej 		}
    344  1.18.2.1  thorpej 		return;
    345  1.18.2.1  thorpej 
    346  1.18.2.1  thorpej 	case ADAPTER_REQ_GET_XFER_MODE:
    347  1.18.2.1  thorpej 		if (isp->isp_type & ISP_HA_SCSI) {
    348  1.18.2.1  thorpej 			sdparam *sdp = isp->isp_param;
    349  1.18.2.1  thorpej 			struct scsipi_periph *periph = arg;
    350  1.18.2.1  thorpej 			u_int16_t flags;
    351  1.18.2.1  thorpej 
    352  1.18.2.1  thorpej 			sdp = &sdp[periph->periph_channel->chan_channel];
    353  1.18.2.1  thorpej 
    354  1.18.2.1  thorpej 			periph->periph_mode = 0;
    355  1.18.2.1  thorpej 			periph->periph_period = 0;
    356  1.18.2.1  thorpej 			periph->periph_offset = 0;
    357  1.18.2.1  thorpej 
    358  1.18.2.1  thorpej 			flags =
    359  1.18.2.1  thorpej 			    sdp->isp_devparam[periph->periph_target].cur_dflags;
    360  1.18.2.1  thorpej 
    361  1.18.2.1  thorpej 			if (flags & DPARM_SYNC) {
    362  1.18.2.1  thorpej 				periph->periph_mode |= PERIPH_CAP_SYNC;
    363  1.18.2.1  thorpej 				periph->periph_period =
    364  1.18.2.1  thorpej 			    sdp->isp_devparam[periph->periph_target].cur_period;
    365  1.18.2.1  thorpej 				periph->periph_offset =
    366  1.18.2.1  thorpej 			    sdp->isp_devparam[periph->periph_target].cur_offset;
    367  1.18.2.1  thorpej 			}
    368  1.18.2.1  thorpej 			if (flags & DPARM_WIDE)
    369  1.18.2.1  thorpej 				periph->periph_mode |= PERIPH_CAP_WIDE16;
    370  1.18.2.1  thorpej 			if (flags & DPARM_TQING)
    371  1.18.2.1  thorpej 				periph->periph_mode |= PERIPH_CAP_TQING;
    372  1.18.2.1  thorpej 
    373  1.18.2.1  thorpej 			periph->periph_flags |= PERIPH_MODE_VALID;
    374  1.18.2.1  thorpej 		}
    375  1.18.2.1  thorpej 		return;
    376       1.1   mjacob 	}
    377       1.1   mjacob }
    378       1.1   mjacob 
    379       1.1   mjacob static int
    380       1.1   mjacob isp_poll(isp, xs, mswait)
    381       1.1   mjacob 	struct ispsoftc *isp;
    382       1.1   mjacob 	ISP_SCSI_XFER_T *xs;
    383       1.1   mjacob 	int mswait;
    384       1.1   mjacob {
    385       1.1   mjacob 
    386       1.1   mjacob 	while (mswait) {
    387       1.1   mjacob 		/* Try the interrupt handling routine */
    388       1.1   mjacob 		(void)isp_intr((void *)isp);
    389       1.1   mjacob 
    390       1.1   mjacob 		/* See if the xs is now done */
    391       1.1   mjacob 		if (XS_IS_CMD_DONE(xs)) {
    392       1.1   mjacob 			return (0);
    393       1.1   mjacob 		}
    394       1.1   mjacob 		SYS_DELAY(1000);	/* wait one millisecond */
    395       1.1   mjacob 		mswait--;
    396       1.1   mjacob 	}
    397       1.1   mjacob 	return (1);
    398       1.8   mjacob }
    399       1.8   mjacob 
    400       1.8   mjacob static void
    401       1.8   mjacob isp_watch(arg)
    402       1.8   mjacob 	void *arg;
    403       1.8   mjacob {
    404       1.8   mjacob 	int i;
    405       1.8   mjacob 	struct ispsoftc *isp = arg;
    406      1.17   mjacob 	struct scsipi_xfer *xs;
    407      1.17   mjacob 	int s;
    408       1.8   mjacob 
    409       1.8   mjacob 	/*
    410       1.8   mjacob 	 * Look for completely dead commands (but not polled ones).
    411       1.8   mjacob 	 */
    412      1.17   mjacob 	s = splbio();
    413      1.17   mjacob 	for (i = 0; i < isp->isp_maxcmds; i++) {
    414      1.17   mjacob 		xs = isp->isp_xflist[i];
    415      1.17   mjacob 		if (xs == NULL) {
    416       1.8   mjacob 			continue;
    417       1.8   mjacob 		}
    418      1.17   mjacob 		if (xs->timeout == 0 || (xs->xs_control & XS_CTL_POLL)) {
    419       1.8   mjacob 			continue;
    420       1.8   mjacob 		}
    421      1.17   mjacob 		xs->timeout -= (WATCH_INTERVAL * 1000);
    422       1.8   mjacob 		/*
    423       1.8   mjacob 		 * Avoid later thinking that this
    424       1.8   mjacob 		 * transaction is not being timed.
    425       1.8   mjacob 		 * Then give ourselves to watchdog
    426       1.8   mjacob 		 * periods of grace.
    427       1.8   mjacob 		 */
    428      1.17   mjacob 		if (xs->timeout == 0) {
    429      1.17   mjacob 			xs->timeout = 1;
    430      1.17   mjacob 		} else if (xs->timeout > -(2 * WATCH_INTERVAL * 1000)) {
    431       1.8   mjacob 			continue;
    432       1.8   mjacob 		}
    433       1.8   mjacob 		if (isp_control(isp, ISPCTL_ABORT_CMD, xs)) {
    434       1.8   mjacob 			printf("%s: isp_watch failed to abort command\n",
    435       1.8   mjacob 			    isp->isp_name);
    436       1.8   mjacob 			isp_restart(isp);
    437       1.8   mjacob 			break;
    438       1.8   mjacob 		}
    439       1.8   mjacob 	}
    440       1.8   mjacob 	timeout(isp_watch, isp, WATCH_INTERVAL * hz);
    441       1.8   mjacob 	isp->isp_dogactive = 1;
    442      1.17   mjacob 	(void) splx(s);
    443       1.8   mjacob }
    444       1.8   mjacob 
    445       1.8   mjacob /*
    446       1.8   mjacob  * Free any associated resources prior to decommissioning and
    447       1.8   mjacob  * set the card to a known state (so it doesn't wake up and kick
    448       1.8   mjacob  * us when we aren't expecting it to).
    449       1.8   mjacob  *
    450       1.8   mjacob  * Locks are held before coming here.
    451       1.8   mjacob  */
    452       1.8   mjacob void
    453       1.8   mjacob isp_uninit(isp)
    454       1.8   mjacob 	struct ispsoftc *isp;
    455       1.8   mjacob {
    456       1.8   mjacob 	ISP_ILOCKVAL_DECL;
    457       1.8   mjacob 	ISP_ILOCK(isp);
    458       1.8   mjacob 	/*
    459       1.8   mjacob 	 * Leave with interrupts disabled.
    460       1.8   mjacob 	 */
    461       1.8   mjacob 	DISABLE_INTS(isp);
    462       1.8   mjacob 
    463       1.8   mjacob 	/*
    464       1.8   mjacob 	 * Turn off the watchdog (if active).
    465       1.8   mjacob 	 */
    466       1.8   mjacob 	if (isp->isp_dogactive) {
    467       1.8   mjacob 		untimeout(isp_watch, isp);
    468       1.8   mjacob 		isp->isp_dogactive = 0;
    469       1.8   mjacob 	}
    470       1.8   mjacob 
    471       1.8   mjacob 	ISP_IUNLOCK(isp);
    472       1.9   mjacob }
    473       1.9   mjacob 
    474      1.10   mjacob /*
    475      1.17   mjacob  * Restart function for a command to be requeued later.
    476      1.17   mjacob  */
    477      1.17   mjacob static void
    478      1.17   mjacob isp_command_requeue(arg)
    479      1.17   mjacob 	void *arg;
    480      1.17   mjacob {
    481      1.17   mjacob 	struct scsipi_xfer *xs = arg;
    482  1.18.2.1  thorpej 	int s;
    483  1.18.2.1  thorpej 
    484  1.18.2.1  thorpej 	s = splbio();
    485  1.18.2.1  thorpej 	scsipi_adapter_request(xs->xs_periph->periph_channel,
    486  1.18.2.1  thorpej 	    ADAPTER_REQ_RUN_XFER, xs);
    487      1.17   mjacob 	(void) splx(s);
    488      1.17   mjacob }
    489      1.18   mjacob 
    490      1.17   mjacob /*
    491      1.10   mjacob  * Restart function after a LOOP UP event (e.g.),
    492      1.10   mjacob  * done as a timeout for some hysteresis.
    493      1.10   mjacob  */
    494      1.10   mjacob static void
    495      1.10   mjacob isp_internal_restart(arg)
    496      1.10   mjacob 	void *arg;
    497      1.10   mjacob {
    498      1.10   mjacob 	struct ispsoftc *isp = arg;
    499      1.11   mjacob 	int result, nrestarted = 0, s;
    500      1.10   mjacob 
    501      1.11   mjacob 	s = splbio();
    502      1.10   mjacob 	if (isp->isp_osinfo.blocked == 0) {
    503      1.10   mjacob 		struct scsipi_xfer *xs;
    504      1.10   mjacob 		while ((xs = TAILQ_FIRST(&isp->isp_osinfo.waitq)) != NULL) {
    505  1.18.2.1  thorpej 			TAILQ_REMOVE(&isp->isp_osinfo.waitq, xs, channel_q);
    506      1.11   mjacob 			DISABLE_INTS(isp);
    507      1.11   mjacob 			result = ispscsicmd(xs);
    508      1.11   mjacob 			ENABLE_INTS(isp);
    509      1.11   mjacob 			if (result != CMD_QUEUED) {
    510      1.10   mjacob 				printf("%s: botched command restart (0x%x)\n",
    511      1.10   mjacob 				    isp->isp_name, result);
    512  1.18.2.1  thorpej 				if (XS_ERR(xs) == XS_NOERROR)
    513  1.18.2.1  thorpej 					XS_SETERR(xs, HBA_BOTCH);
    514  1.18.2.1  thorpej 				XS_CMD_DONE(xs);
    515      1.10   mjacob 			}
    516      1.10   mjacob 			nrestarted++;
    517      1.10   mjacob 		}
    518      1.10   mjacob 		printf("%s: requeued %d commands\n", isp->isp_name, nrestarted);
    519      1.10   mjacob 	}
    520      1.10   mjacob 	(void) splx(s);
    521      1.10   mjacob }
    522      1.18   mjacob 
    523       1.9   mjacob int
    524       1.9   mjacob isp_async(isp, cmd, arg)
    525       1.9   mjacob 	struct ispsoftc *isp;
    526       1.9   mjacob 	ispasync_t cmd;
    527       1.9   mjacob 	void *arg;
    528       1.9   mjacob {
    529  1.18.2.1  thorpej 	int bus;
    530      1.10   mjacob 	int s = splbio();
    531       1.9   mjacob 	switch (cmd) {
    532       1.9   mjacob 	case ISPASYNC_NEW_TGT_PARAMS:
    533  1.18.2.1  thorpej 		/*
    534  1.18.2.1  thorpej 		 * XXX Should we really do anything here?
    535  1.18.2.1  thorpej 		 */
    536      1.11   mjacob 		break;
    537      1.11   mjacob 	case ISPASYNC_BUS_RESET:
    538      1.14   mjacob 		if (arg)
    539      1.14   mjacob 			bus = *((int *) arg);
    540      1.14   mjacob 		else
    541      1.14   mjacob 			bus = 0;
    542      1.14   mjacob 		printf("%s: SCSI bus %d reset detected\n", isp->isp_name, bus);
    543      1.11   mjacob 		break;
    544      1.11   mjacob 	case ISPASYNC_LOOP_DOWN:
    545      1.11   mjacob 		/*
    546      1.11   mjacob 		 * Hopefully we get here in time to minimize the number
    547      1.11   mjacob 		 * of commands we are firing off that are sure to die.
    548      1.11   mjacob 		 */
    549      1.11   mjacob 		isp->isp_osinfo.blocked = 1;
    550      1.11   mjacob 		printf("%s: Loop DOWN\n", isp->isp_name);
    551      1.11   mjacob 		break;
    552      1.11   mjacob         case ISPASYNC_LOOP_UP:
    553      1.11   mjacob 		isp->isp_osinfo.blocked = 0;
    554      1.11   mjacob 		timeout(isp_internal_restart, isp, 1);
    555      1.11   mjacob 		printf("%s: Loop UP\n", isp->isp_name);
    556      1.11   mjacob 		break;
    557      1.15   mjacob 	case ISPASYNC_PDB_CHANGED:
    558      1.17   mjacob 	if (IS_FC(isp) && isp->isp_dblev) {
    559      1.15   mjacob 		const char *fmt = "%s: Target %d (Loop 0x%x) Port ID 0x%x "
    560      1.15   mjacob 		    "role %s %s\n Port WWN 0x%08x%08x\n Node WWN 0x%08x%08x\n";
    561      1.15   mjacob 		const static char *roles[4] = {
    562      1.11   mjacob 		    "No", "Target", "Initiator", "Target/Initiator"
    563      1.11   mjacob 		};
    564      1.15   mjacob 		char *ptr;
    565      1.15   mjacob 		fcparam *fcp = isp->isp_param;
    566      1.15   mjacob 		int tgt = *((int *) arg);
    567      1.15   mjacob 		struct lportdb *lp = &fcp->portdb[tgt];
    568      1.15   mjacob 
    569      1.15   mjacob 		if (lp->valid) {
    570      1.15   mjacob 			ptr = "arrived";
    571      1.15   mjacob 		} else {
    572      1.15   mjacob 			ptr = "disappeared";
    573      1.11   mjacob 		}
    574      1.15   mjacob 		printf(fmt, isp->isp_name, tgt, lp->loopid, lp->portid,
    575      1.15   mjacob 		    roles[lp->roles & 0x3], ptr,
    576      1.15   mjacob 		    (u_int32_t) (lp->port_wwn >> 32),
    577      1.15   mjacob 		    (u_int32_t) (lp->port_wwn & 0xffffffffLL),
    578      1.15   mjacob 		    (u_int32_t) (lp->node_wwn >> 32),
    579      1.15   mjacob 		    (u_int32_t) (lp->node_wwn & 0xffffffffLL));
    580      1.11   mjacob 		break;
    581      1.11   mjacob 	}
    582      1.15   mjacob #ifdef	ISP2100_FABRIC
    583      1.11   mjacob 	case ISPASYNC_CHANGE_NOTIFY:
    584      1.11   mjacob 		printf("%s: Name Server Database Changed\n", isp->isp_name);
    585       1.9   mjacob 		break;
    586      1.15   mjacob 	case ISPASYNC_FABRIC_DEV:
    587      1.15   mjacob 	{
    588      1.15   mjacob 		int target;
    589      1.15   mjacob 		struct lportdb *lp;
    590      1.15   mjacob 		sns_scrsp_t *resp = (sns_scrsp_t *) arg;
    591      1.15   mjacob 		u_int32_t portid;
    592      1.15   mjacob 		u_int64_t wwn;
    593      1.15   mjacob 		fcparam *fcp = isp->isp_param;
    594      1.15   mjacob 
    595      1.15   mjacob 		portid =
    596      1.15   mjacob 		    (((u_int32_t) resp->snscb_port_id[0]) << 16) |
    597      1.15   mjacob 		    (((u_int32_t) resp->snscb_port_id[1]) << 8) |
    598      1.15   mjacob 		    (((u_int32_t) resp->snscb_port_id[2]));
    599      1.15   mjacob 		wwn =
    600      1.15   mjacob 		    (((u_int64_t)resp->snscb_portname[0]) << 56) |
    601      1.15   mjacob 		    (((u_int64_t)resp->snscb_portname[1]) << 48) |
    602      1.15   mjacob 		    (((u_int64_t)resp->snscb_portname[2]) << 40) |
    603      1.15   mjacob 		    (((u_int64_t)resp->snscb_portname[3]) << 32) |
    604      1.15   mjacob 		    (((u_int64_t)resp->snscb_portname[4]) << 24) |
    605      1.15   mjacob 		    (((u_int64_t)resp->snscb_portname[5]) << 16) |
    606      1.15   mjacob 		    (((u_int64_t)resp->snscb_portname[6]) <<  8) |
    607      1.15   mjacob 		    (((u_int64_t)resp->snscb_portname[7]));
    608      1.15   mjacob 		printf("%s: Fabric Device (Type 0x%x)@PortID 0x%x WWN "
    609      1.15   mjacob 		    "0x%08x%08x\n", isp->isp_name, resp->snscb_port_type,
    610      1.15   mjacob 		    portid, ((u_int32_t)(wwn >> 32)),
    611      1.15   mjacob 		    ((u_int32_t)(wwn & 0xffffffff)));
    612      1.15   mjacob 		if (resp->snscb_port_type != 2)
    613      1.15   mjacob 			break;
    614      1.15   mjacob 		for (target = FC_SNS_ID+1; target < MAX_FC_TARG; target++) {
    615      1.15   mjacob 			lp = &fcp->portdb[target];
    616      1.15   mjacob 			if (lp->port_wwn == wwn)
    617      1.15   mjacob 				break;
    618      1.15   mjacob 		}
    619      1.15   mjacob 		if (target < MAX_FC_TARG) {
    620      1.15   mjacob 			break;
    621      1.15   mjacob 		}
    622      1.15   mjacob 		for (target = FC_SNS_ID+1; target < MAX_FC_TARG; target++) {
    623      1.15   mjacob 			lp = &fcp->portdb[target];
    624      1.15   mjacob 			if (lp->port_wwn == 0)
    625      1.15   mjacob 				break;
    626      1.15   mjacob 		}
    627      1.15   mjacob 		if (target == MAX_FC_TARG) {
    628      1.15   mjacob 			printf("%s: no more space for fabric devices\n",
    629      1.15   mjacob 			    isp->isp_name);
    630      1.15   mjacob 			return (-1);
    631      1.15   mjacob 		}
    632      1.15   mjacob 		lp->port_wwn = lp->node_wwn = wwn;
    633      1.15   mjacob 		lp->portid = portid;
    634      1.15   mjacob 		break;
    635      1.15   mjacob 	}
    636      1.15   mjacob #endif
    637       1.9   mjacob 	default:
    638       1.9   mjacob 		break;
    639       1.9   mjacob 	}
    640      1.10   mjacob 	(void) splx(s);
    641       1.9   mjacob 	return (0);
    642       1.1   mjacob }
    643