Home | History | Annotate | Line # | Download | only in ic
      1  1.36   thorpej /*	$NetBSD: aic79xx_osm.c,v 1.36 2021/08/07 16:19:12 thorpej Exp $	*/
      2   1.1      fvdl 
      3   1.1      fvdl /*
      4   1.1      fvdl  * Bus independent NetBSD shim for the aic7xxx based adaptec SCSI controllers
      5   1.1      fvdl  *
      6   1.1      fvdl  * Copyright (c) 1994-2002 Justin T. Gibbs.
      7   1.1      fvdl  * Copyright (c) 2001-2002 Adaptec Inc.
      8   1.1      fvdl  * All rights reserved.
      9   1.1      fvdl  *
     10   1.1      fvdl  * Redistribution and use in source and binary forms, with or without
     11   1.1      fvdl  * modification, are permitted provided that the following conditions
     12   1.1      fvdl  * are met:
     13   1.1      fvdl  * 1. Redistributions of source code must retain the above copyright
     14   1.1      fvdl  *    notice, this list of conditions, and the following disclaimer,
     15   1.1      fvdl  *    without modification.
     16   1.1      fvdl  * 2. The name of the author may not be used to endorse or promote products
     17   1.1      fvdl  *    derived from this software without specific prior written permission.
     18   1.1      fvdl  *
     19   1.1      fvdl  * Alternatively, this software may be distributed under the terms of the
     20   1.1      fvdl  * GNU Public License ("GPL").
     21   1.1      fvdl  *
     22   1.1      fvdl  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     23   1.1      fvdl  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24   1.1      fvdl  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25   1.1      fvdl  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
     26   1.1      fvdl  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27   1.1      fvdl  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28   1.1      fvdl  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29   1.1      fvdl  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30   1.1      fvdl  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31   1.1      fvdl  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32   1.1      fvdl  * SUCH DAMAGE.
     33   1.1      fvdl  *
     34   1.1      fvdl  * //depot/aic7xxx/freebsd/dev/aic7xxx/aic79xx_osm.c#26 $
     35   1.1      fvdl  *
     36   1.5   thorpej  * $FreeBSD: src/sys/dev/aic7xxx/aic79xx_osm.c,v 1.11 2003/05/04 00:20:07 gibbs Exp $
     37   1.1      fvdl  */
     38   1.1      fvdl /*
     39   1.1      fvdl  * Ported from FreeBSD by Pascal Renauld, Network Storage Solutions, Inc.
     40   1.1      fvdl  * - April 2003
     41   1.1      fvdl  */
     42   1.4     lukem 
     43   1.4     lukem #include <sys/cdefs.h>
     44  1.36   thorpej __KERNEL_RCSID(0, "$NetBSD: aic79xx_osm.c,v 1.36 2021/08/07 16:19:12 thorpej Exp $");
     45   1.1      fvdl 
     46   1.1      fvdl #include <dev/ic/aic79xx_osm.h>
     47   1.1      fvdl #include <dev/ic/aic79xx_inline.h>
     48   1.1      fvdl 
     49   1.1      fvdl #ifndef AHD_TMODE_ENABLE
     50   1.1      fvdl #define AHD_TMODE_ENABLE 0
     51   1.1      fvdl #endif
     52   1.1      fvdl 
     53  1.12     perry static int	ahd_ioctl(struct scsipi_channel *channel, u_long cmd,
     54  1.18  christos 			  void *addr, int flag, struct proc *p);
     55  1.12     perry static void	ahd_action(struct scsipi_channel *chan,
     56   1.1      fvdl 			   scsipi_adapter_req_t req, void *arg);
     57   1.1      fvdl static void	ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs,
     58   1.1      fvdl 				int nsegments);
     59   1.1      fvdl static int	ahd_poll(struct ahd_softc *ahd, int wait);
     60   1.1      fvdl static void	ahd_setup_data(struct ahd_softc *ahd, struct scsipi_xfer *xs,
     61   1.1      fvdl 			       struct scb *scb);
     62   1.1      fvdl 
     63   1.1      fvdl #if NOT_YET
     64   1.1      fvdl static void	ahd_set_recoveryscb(struct ahd_softc *ahd, struct scb *scb);
     65   1.1      fvdl #endif
     66   1.1      fvdl 
     67  1.31    dyoung static bool	ahd_pmf_suspend(device_t, const pmf_qual_t *);
     68  1.31    dyoung static bool	ahd_pmf_resume(device_t, const pmf_qual_t *);
     69  1.22   tsutsui static bool	ahd_pmf_shutdown(device_t, int);
     70  1.22   tsutsui 
     71   1.1      fvdl /*
     72   1.1      fvdl  * Attach all the sub-devices we can find
     73   1.1      fvdl  */
     74   1.1      fvdl int
     75   1.1      fvdl ahd_attach(struct ahd_softc *ahd)
     76   1.1      fvdl {
     77  1.23   tsutsui 	int	s;
     78   1.1      fvdl 	char	ahd_info[256];
     79   1.1      fvdl 
     80   1.8    itojun 	ahd_controller_info(ahd, ahd_info, sizeof(ahd_info));
     81  1.33   msaitoh 	aprint_normal("%s: %s\n", ahd_name(ahd), ahd_info);
     82   1.1      fvdl 
     83  1.23   tsutsui 	ahd_lock(ahd, &s);
     84   1.1      fvdl 
     85  1.29   tsutsui 	ahd->sc_adapter.adapt_dev = ahd->sc_dev;
     86   1.1      fvdl 	ahd->sc_adapter.adapt_nchannels = 1;
     87  1.12     perry 
     88  1.13    bouyer 	ahd->sc_adapter.adapt_openings = ahd->scb_data.numscbs - 1;
     89   1.1      fvdl 	ahd->sc_adapter.adapt_max_periph = 32;
     90   1.1      fvdl 
     91   1.1      fvdl 	ahd->sc_adapter.adapt_ioctl = ahd_ioctl;
     92   1.1      fvdl 	ahd->sc_adapter.adapt_minphys = ahd_minphys;
     93   1.1      fvdl 	ahd->sc_adapter.adapt_request = ahd_action;
     94   1.1      fvdl 
     95   1.1      fvdl 	ahd->sc_channel.chan_adapter = &ahd->sc_adapter;
     96  1.23   tsutsui 	ahd->sc_channel.chan_bustype = &scsi_bustype;
     97  1.23   tsutsui 	ahd->sc_channel.chan_channel = 0;
     98  1.23   tsutsui 	ahd->sc_channel.chan_ntargets = AHD_NUM_TARGETS;
     99  1.23   tsutsui 	ahd->sc_channel.chan_nluns = 8 /*AHD_NUM_LUNS*/;
    100  1.23   tsutsui 	ahd->sc_channel.chan_id = ahd->our_id;
    101  1.23   tsutsui 	ahd->sc_channel.chan_flags |= SCSIPI_CHAN_CANGROW;
    102   1.1      fvdl 
    103  1.35   thorpej 	ahd->sc_child = config_found(ahd->sc_dev, &ahd->sc_channel, scsiprint,
    104  1.36   thorpej 	    CFARGS_NONE);
    105   1.1      fvdl 
    106   1.1      fvdl 	ahd_intr_enable(ahd, TRUE);
    107   1.1      fvdl 
    108   1.3      fvdl 	if (ahd->flags & AHD_RESET_BUS_A)
    109   1.3      fvdl 		ahd_reset_channel(ahd, 'A', TRUE);
    110   1.3      fvdl 
    111  1.29   tsutsui 	if (!pmf_device_register1(ahd->sc_dev,
    112  1.22   tsutsui 	    ahd_pmf_suspend, ahd_pmf_resume, ahd_pmf_shutdown))
    113  1.29   tsutsui 		aprint_error_dev(ahd->sc_dev,
    114  1.22   tsutsui 		    "couldn't establish power handler\n");
    115  1.22   tsutsui 
    116  1.23   tsutsui 	ahd_unlock(ahd, &s);
    117   1.1      fvdl 
    118   1.1      fvdl 	return (1);
    119   1.1      fvdl }
    120   1.1      fvdl 
    121  1.22   tsutsui static bool
    122  1.31    dyoung ahd_pmf_suspend(device_t dev, const pmf_qual_t *qual)
    123  1.22   tsutsui {
    124  1.22   tsutsui 	struct ahd_softc *sc = device_private(dev);
    125  1.22   tsutsui #if 0
    126  1.22   tsutsui 	return (ahd_suspend(sc) == 0);
    127  1.22   tsutsui #else
    128  1.22   tsutsui 	ahd_shutdown(sc);
    129  1.22   tsutsui 	return true;
    130  1.22   tsutsui #endif
    131  1.22   tsutsui }
    132  1.22   tsutsui 
    133  1.22   tsutsui static bool
    134  1.31    dyoung ahd_pmf_resume(device_t dev, const pmf_qual_t *qual)
    135  1.22   tsutsui {
    136  1.22   tsutsui #if 0
    137  1.22   tsutsui 	struct ahd_softc *sc = device_private(dev);
    138  1.22   tsutsui 
    139  1.22   tsutsui 	return (ahd_resume(sc) == 0);
    140  1.22   tsutsui #else
    141  1.22   tsutsui 	return true;
    142  1.22   tsutsui #endif
    143  1.22   tsutsui }
    144  1.22   tsutsui 
    145  1.22   tsutsui static bool
    146  1.22   tsutsui ahd_pmf_shutdown(device_t dev, int howto)
    147  1.22   tsutsui {
    148  1.22   tsutsui 	struct ahd_softc *sc = device_private(dev);
    149  1.22   tsutsui 
    150  1.22   tsutsui 	/* Disable all interrupt sources by resetting the controller */
    151  1.22   tsutsui 	ahd_shutdown(sc);
    152  1.22   tsutsui 
    153  1.22   tsutsui 	return true;
    154  1.22   tsutsui }
    155  1.22   tsutsui 
    156   1.1      fvdl static int
    157  1.12     perry ahd_ioctl(struct scsipi_channel *channel, u_long cmd,
    158  1.18  christos 	  void *addr, int flag, struct proc *p)
    159   1.1      fvdl {
    160  1.27   tsutsui 	struct ahd_softc *ahd;
    161  1.23   tsutsui 	int s, ret = ENOTTY;
    162   1.1      fvdl 
    163  1.27   tsutsui 	ahd = device_private(channel->chan_adapter->adapt_dev);
    164  1.27   tsutsui 
    165  1.23   tsutsui 	switch (cmd) {
    166  1.23   tsutsui 	case SCBUSIORESET:
    167  1.23   tsutsui 		s = splbio();
    168  1.23   tsutsui 		ahd_reset_channel(ahd, channel->chan_channel == 1 ? 'B' : 'A', TRUE);
    169  1.23   tsutsui 		splx(s);
    170  1.23   tsutsui 		ret = 0;
    171  1.23   tsutsui 		break;
    172  1.23   tsutsui 	default:
    173  1.23   tsutsui 		break;
    174  1.23   tsutsui 	}
    175   1.1      fvdl 
    176  1.23   tsutsui 	return ret;
    177   1.1      fvdl }
    178   1.1      fvdl 
    179   1.1      fvdl /*
    180   1.1      fvdl  * Catch an interrupt from the adapter
    181   1.1      fvdl  */
    182   1.1      fvdl void
    183   1.1      fvdl ahd_platform_intr(void *arg)
    184   1.1      fvdl {
    185   1.1      fvdl 	struct	ahd_softc *ahd;
    186  1.12     perry 
    187  1.25   tsutsui 	ahd = arg;
    188   1.1      fvdl 
    189   1.1      fvdl 	printf("%s; ahd_platform_intr\n", ahd_name(ahd));
    190   1.1      fvdl 
    191   1.1      fvdl 	ahd_intr(ahd);
    192   1.1      fvdl }
    193   1.1      fvdl 
    194   1.1      fvdl /*
    195   1.1      fvdl  * We have an scb which has been processed by the
    196   1.1      fvdl  * adaptor, now we look to see how the operation * went.
    197   1.1      fvdl  */
    198   1.1      fvdl void
    199   1.1      fvdl ahd_done(struct ahd_softc *ahd, struct scb *scb)
    200   1.1      fvdl {
    201   1.1      fvdl 	struct scsipi_xfer	*xs;
    202   1.1      fvdl 	struct scsipi_periph	*periph;
    203   1.1      fvdl 	int			s;
    204   1.1      fvdl 
    205   1.1      fvdl 	LIST_REMOVE(scb, pending_links);
    206   1.1      fvdl 
    207   1.1      fvdl 	xs = scb->xs;
    208   1.1      fvdl 	periph = xs->xs_periph;
    209   1.1      fvdl 
    210   1.1      fvdl 	callout_stop(&scb->xs->xs_callout);
    211   1.1      fvdl 
    212   1.1      fvdl 	if (xs->datalen) {
    213   1.1      fvdl 		int op;
    214   1.1      fvdl 
    215   1.1      fvdl 		if (xs->xs_control & XS_CTL_DATA_IN)
    216  1.23   tsutsui 			op = BUS_DMASYNC_POSTREAD;
    217   1.1      fvdl 		else
    218  1.23   tsutsui 			op = BUS_DMASYNC_POSTWRITE;
    219   1.1      fvdl 
    220   1.1      fvdl 		bus_dmamap_sync(ahd->parent_dmat, scb->dmamap, 0,
    221   1.1      fvdl 				scb->dmamap->dm_mapsize, op);
    222  1.23   tsutsui 		bus_dmamap_unload(ahd->parent_dmat, scb->dmamap);
    223  1.23   tsutsui 	}
    224   1.1      fvdl 
    225   1.1      fvdl 	/*
    226   1.1      fvdl 	 * If the recovery SCB completes, we have to be
    227   1.1      fvdl 	 * out of our timeout.
    228   1.1      fvdl 	 */
    229   1.1      fvdl 	if ((scb->flags & SCB_RECOVERY_SCB) != 0) {
    230   1.1      fvdl 		struct	scb *list_scb;
    231   1.1      fvdl 
    232   1.1      fvdl 		/*
    233   1.1      fvdl 		 * We were able to complete the command successfully,
    234   1.1      fvdl 		 * so reinstate the timeouts for all other pending
    235   1.1      fvdl 		 * commands.
    236   1.1      fvdl 		 */
    237   1.1      fvdl 		LIST_FOREACH(list_scb, &ahd->pending_scbs, pending_links) {
    238   1.1      fvdl 			struct scsipi_xfer	*txs = list_scb->xs;
    239  1.12     perry 
    240   1.1      fvdl 			if (!(txs->xs_control & XS_CTL_POLL)) {
    241  1.23   tsutsui 				callout_reset(&txs->xs_callout,
    242  1.23   tsutsui 				    (txs->timeout > 1000000) ?
    243  1.23   tsutsui 				    (txs->timeout / 1000) * hz :
    244  1.23   tsutsui 				    (txs->timeout * hz) / 1000,
    245  1.23   tsutsui 				    ahd_timeout, list_scb);
    246  1.23   tsutsui 			}
    247   1.1      fvdl 		}
    248   1.1      fvdl 
    249   1.1      fvdl 		if (ahd_get_transaction_status(scb) != XS_NOERROR)
    250  1.23   tsutsui 			ahd_set_transaction_status(scb, XS_TIMEOUT);
    251  1.23   tsutsui 		scsipi_printaddr(xs->xs_periph);
    252  1.12     perry 		printf("%s: no longer in timeout, status = %x\n",
    253   1.1      fvdl 		       ahd_name(ahd), xs->status);
    254   1.1      fvdl 	}
    255   1.1      fvdl 
    256   1.1      fvdl 	if (xs->error != XS_NOERROR) {
    257  1.23   tsutsui 		/* Don't clobber any existing error state */
    258   1.1      fvdl 	} else if ((xs->status == SCSI_STATUS_BUSY) ||
    259   1.1      fvdl 		   (xs->status == SCSI_STATUS_QUEUE_FULL)) {
    260  1.23   tsutsui 		ahd_set_transaction_status(scb, XS_BUSY);
    261  1.12     perry 		printf("%s: drive (ID %d, LUN %d) queue full (SCB 0x%x)\n",
    262   1.1      fvdl 		       ahd_name(ahd), SCB_GET_TARGET(ahd,scb), SCB_GET_LUN(scb), SCB_GET_TAG(scb));
    263  1.23   tsutsui 	} else if ((scb->flags & SCB_SENSE) != 0) {
    264  1.23   tsutsui 		/*
    265  1.23   tsutsui 		 * We performed autosense retrieval.
    266  1.23   tsutsui 		 *
    267  1.23   tsutsui 		 * zero the sense data before having
    268  1.23   tsutsui 		 * the drive fill it.  The SCSI spec mandates
    269  1.23   tsutsui 		 * that any untransferred data should be
    270  1.23   tsutsui 		 * assumed to be zero.  Complete the 'bounce'
    271  1.23   tsutsui 		 * of sense information through buffers accessible
    272  1.23   tsutsui 		 * via bus-space by copying it into the clients
    273  1.23   tsutsui 		 * csio.
    274  1.23   tsutsui 		 */
    275  1.23   tsutsui 		memset(&xs->sense.scsi_sense, 0, sizeof(xs->sense.scsi_sense));
    276  1.23   tsutsui 		memcpy(&xs->sense.scsi_sense, ahd_get_sense_buf(ahd, scb),
    277  1.11   thorpej 		       sizeof(struct scsi_sense_data));
    278  1.12     perry 
    279  1.23   tsutsui 		ahd_set_transaction_status(scb, XS_SENSE);
    280  1.23   tsutsui 	} else if ((scb->flags & SCB_PKT_SENSE) != 0) {
    281   1.1      fvdl 		struct scsi_status_iu_header *siu;
    282   1.1      fvdl 		u_int sense_len;
    283   1.9      fvdl #ifdef AHD_DEBUG
    284   1.1      fvdl 		int i;
    285   1.9      fvdl #endif
    286   1.1      fvdl 		/*
    287   1.1      fvdl 		 * Copy only the sense data into the provided buffer.
    288   1.1      fvdl 		 */
    289   1.1      fvdl 		siu = (struct scsi_status_iu_header *)scb->sense_data;
    290   1.1      fvdl 		sense_len = MIN(scsi_4btoul(siu->sense_length),
    291  1.10      fvdl 				sizeof(xs->sense.scsi_sense));
    292   1.1      fvdl 		memset(&xs->sense.scsi_sense, 0, sizeof(xs->sense.scsi_sense));
    293  1.12     perry 		memcpy(&xs->sense.scsi_sense,
    294   1.1      fvdl 		       scb->sense_data + SIU_SENSE_OFFSET(siu), sense_len);
    295   1.9      fvdl #ifdef AHD_DEBUG
    296   1.1      fvdl 		printf("Copied %d bytes of sense data offset %d:", sense_len,
    297   1.1      fvdl 		       SIU_SENSE_OFFSET(siu));
    298   1.1      fvdl 		for (i = 0; i < sense_len; i++)
    299   1.1      fvdl 			printf(" 0x%x", ((uint8_t *)&xs->sense.scsi_sense)[i]);
    300   1.1      fvdl 		printf("\n");
    301   1.9      fvdl #endif
    302  1.23   tsutsui 		ahd_set_transaction_status(scb, XS_SENSE);
    303   1.1      fvdl 	}
    304   1.1      fvdl 
    305   1.1      fvdl 	if (scb->flags & SCB_FREEZE_QUEUE) {
    306  1.23   tsutsui 		scsipi_periph_thaw(periph, 1);
    307  1.23   tsutsui 		scb->flags &= ~SCB_FREEZE_QUEUE;
    308  1.23   tsutsui 	}
    309   1.1      fvdl 
    310  1.23   tsutsui 	if (scb->flags & SCB_REQUEUE)
    311  1.23   tsutsui 		ahd_set_transaction_status(scb, XS_REQUEUE);
    312  1.23   tsutsui 
    313  1.23   tsutsui 	ahd_lock(ahd, &s);
    314  1.23   tsutsui 	ahd_free_scb(ahd, scb);
    315  1.23   tsutsui 	ahd_unlock(ahd, &s);
    316  1.23   tsutsui 
    317  1.23   tsutsui 	scsipi_done(xs);
    318   1.1      fvdl }
    319   1.1      fvdl 
    320   1.1      fvdl static void
    321   1.1      fvdl ahd_action(struct scsipi_channel *chan, scsipi_adapter_req_t req, void *arg)
    322   1.1      fvdl {
    323  1.23   tsutsui 	struct ahd_softc *ahd;
    324   1.1      fvdl 	struct ahd_initiator_tinfo *tinfo;
    325   1.1      fvdl 	struct ahd_tmode_tstate *tstate;
    326   1.1      fvdl 
    327  1.27   tsutsui 	ahd = device_private(chan->chan_adapter->adapt_dev);
    328   1.1      fvdl 
    329   1.1      fvdl 	switch(req) {
    330   1.1      fvdl 
    331   1.1      fvdl 	case ADAPTER_REQ_RUN_XFER:
    332   1.1      fvdl 	  {
    333   1.1      fvdl 		struct scsipi_xfer *xs;
    334  1.23   tsutsui 		struct scsipi_periph *periph;
    335  1.23   tsutsui 		struct scb *scb;
    336  1.23   tsutsui 		struct hardware_scb *hscb;
    337   1.1      fvdl 		u_int target_id;
    338   1.1      fvdl 		u_int our_id;
    339   1.1      fvdl 		u_int col_idx;
    340   1.1      fvdl 		char channel;
    341   1.1      fvdl 		int s;
    342   1.1      fvdl 
    343  1.23   tsutsui 		xs = arg;
    344  1.23   tsutsui 		periph = xs->xs_periph;
    345   1.1      fvdl 
    346  1.23   tsutsui 		SC_DEBUG(periph, SCSIPI_DB3, ("ahd_action\n"));
    347   1.1      fvdl 
    348   1.1      fvdl 		target_id = periph->periph_target;
    349  1.23   tsutsui 		our_id = ahd->our_id;
    350  1.23   tsutsui 		channel = (chan->chan_channel == 1) ? 'B' : 'A';
    351   1.1      fvdl 
    352  1.23   tsutsui 		/*
    353   1.1      fvdl 		 * get an scb to use.
    354   1.1      fvdl 		 */
    355   1.1      fvdl 		ahd_lock(ahd, &s);
    356   1.1      fvdl 		tinfo = ahd_fetch_transinfo(ahd, channel, our_id,
    357   1.1      fvdl 					    target_id, &tstate);
    358   1.1      fvdl 
    359   1.6      fvdl 		if (xs->xs_tag_type != 0 ||
    360   1.6      fvdl 		    (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0)
    361   1.6      fvdl 			col_idx = AHD_NEVER_COL_IDX;
    362   1.6      fvdl 		else
    363   1.6      fvdl 			col_idx = AHD_BUILD_COL_IDX(target_id,
    364   1.6      fvdl 			    periph->periph_lun);
    365   1.1      fvdl 
    366   1.1      fvdl 		if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) {
    367   1.1      fvdl 			xs->error = XS_RESOURCE_SHORTAGE;
    368   1.1      fvdl 			ahd_unlock(ahd, &s);
    369   1.1      fvdl 			scsipi_done(xs);
    370   1.1      fvdl 			return;
    371   1.1      fvdl 		}
    372   1.1      fvdl 		ahd_unlock(ahd, &s);
    373   1.1      fvdl 
    374   1.1      fvdl 		hscb = scb->hscb;
    375   1.1      fvdl 
    376   1.1      fvdl 		SC_DEBUG(periph, SCSIPI_DB3, ("start scb(%p)\n", scb));
    377   1.1      fvdl 		scb->xs = xs;
    378   1.1      fvdl 
    379   1.1      fvdl 		/*
    380   1.1      fvdl 		 * Put all the arguments for the xfer in the scb
    381   1.1      fvdl 		 */
    382   1.1      fvdl 		hscb->control = 0;
    383   1.1      fvdl 		hscb->scsiid = BUILD_SCSIID(ahd, sim, target_id, our_id);
    384   1.1      fvdl 		hscb->lun = periph->periph_lun;
    385   1.1      fvdl 		if (xs->xs_control & XS_CTL_RESET) {
    386   1.1      fvdl 			hscb->cdb_len = 0;
    387   1.1      fvdl 			scb->flags |= SCB_DEVICE_RESET;
    388   1.1      fvdl 			hscb->control |= MK_MESSAGE;
    389   1.1      fvdl 			hscb->task_management = SIU_TASKMGMT_LUN_RESET;
    390   1.1      fvdl 			ahd_execute_scb(scb, NULL, 0);
    391   1.1      fvdl 		} else {
    392   1.1      fvdl 			hscb->task_management = 0;
    393   1.1      fvdl 		}
    394   1.1      fvdl 
    395   1.1      fvdl 		ahd_setup_data(ahd, xs, scb);
    396   1.1      fvdl 		break;
    397   1.1      fvdl 	  }
    398   1.1      fvdl 
    399   1.1      fvdl 	case ADAPTER_REQ_GROW_RESOURCES:
    400  1.14    bouyer #ifdef AHC_DEBUG
    401   1.1      fvdl 		printf("%s: ADAPTER_REQ_GROW_RESOURCES\n", ahd_name(ahd));
    402  1.14    bouyer #endif
    403  1.13    bouyer 		chan->chan_adapter->adapt_openings += ahd_alloc_scbs(ahd);
    404  1.13    bouyer 		if (ahd->scb_data.numscbs >= AHD_SCB_MAX_ALLOC)
    405  1.13    bouyer 			chan->chan_flags &= ~SCSIPI_CHAN_CANGROW;
    406   1.1      fvdl 		break;
    407   1.1      fvdl 
    408   1.1      fvdl 	case ADAPTER_REQ_SET_XFER_MODE:
    409   1.1      fvdl 	    {
    410   1.1      fvdl 		struct scsipi_xfer_mode *xm = arg;
    411   1.1      fvdl 		struct ahd_devinfo devinfo;
    412   1.1      fvdl 		int target_id, our_id, first;
    413   1.1      fvdl 		u_int width;
    414   1.1      fvdl 		int s;
    415   1.1      fvdl 		char channel;
    416  1.15    bouyer 		u_int ppr_options = 0, period, offset;
    417   1.6      fvdl 		uint16_t old_autoneg;
    418   1.1      fvdl 
    419  1.12     perry 		target_id = xm->xm_target;
    420   1.1      fvdl 		our_id = chan->chan_id;
    421   1.1      fvdl 		channel = 'A';
    422   1.1      fvdl 		s = splbio();
    423   1.1      fvdl 		tinfo = ahd_fetch_transinfo(ahd, channel, our_id, target_id,
    424   1.1      fvdl 		    &tstate);
    425   1.1      fvdl 		ahd_compile_devinfo(&devinfo, our_id, target_id,
    426   1.1      fvdl 		    0, channel, ROLE_INITIATOR);
    427   1.1      fvdl 
    428   1.6      fvdl 		old_autoneg = tstate->auto_negotiate;
    429   1.6      fvdl 
    430   1.1      fvdl 		/*
    431   1.1      fvdl 		 * XXX since the period and offset are not provided here,
    432   1.1      fvdl 		 * fake things by forcing a renegotiation using the user
    433   1.1      fvdl 		 * settings if this is called for the first time (i.e.
    434   1.1      fvdl 		 * during probe). Also, cap various values at the user
    435   1.1      fvdl 		 * values, assuming that the user set it up that way.
    436   1.1      fvdl 		 */
    437   1.1      fvdl 		if (ahd->inited_target[target_id] == 0) {
    438   1.6      fvdl 			period = tinfo->user.period;
    439   1.6      fvdl 			offset = tinfo->user.offset;
    440   1.6      fvdl 			ppr_options = tinfo->user.ppr_options;
    441   1.6      fvdl 			width = tinfo->user.width;
    442   1.1      fvdl 			tstate->tagenable |=
    443   1.1      fvdl 			    (ahd->user_tagenable & devinfo.target_mask);
    444   1.1      fvdl 			tstate->discenable |=
    445   1.1      fvdl 			    (ahd->user_discenable & devinfo.target_mask);
    446   1.1      fvdl 			ahd->inited_target[target_id] = 1;
    447   1.1      fvdl 			first = 1;
    448   1.1      fvdl 		} else
    449   1.1      fvdl 			first = 0;
    450   1.1      fvdl 
    451   1.2      fvdl 		if (xm->xm_mode & (PERIPH_CAP_WIDE16 | PERIPH_CAP_DT))
    452   1.1      fvdl 			width = MSG_EXT_WDTR_BUS_16_BIT;
    453   1.1      fvdl 		else
    454   1.1      fvdl 			width = MSG_EXT_WDTR_BUS_8_BIT;
    455   1.1      fvdl 
    456   1.1      fvdl 		ahd_validate_width(ahd, NULL, &width, ROLE_UNKNOWN);
    457   1.1      fvdl 		if (width > tinfo->user.width)
    458   1.1      fvdl 			width = tinfo->user.width;
    459   1.6      fvdl 		ahd_set_width(ahd, &devinfo, width, AHD_TRANS_GOAL, FALSE);
    460   1.1      fvdl 
    461   1.2      fvdl 		if (!(xm->xm_mode & (PERIPH_CAP_SYNC | PERIPH_CAP_DT))) {
    462   1.6      fvdl 			period = 0;
    463   1.6      fvdl 			offset = 0;
    464   1.6      fvdl 			ppr_options = 0;
    465   1.1      fvdl 		}
    466   1.1      fvdl 
    467   1.1      fvdl 		if ((xm->xm_mode & PERIPH_CAP_DT) &&
    468   1.1      fvdl 		    (tinfo->user.ppr_options & MSG_EXT_PPR_DT_REQ))
    469   1.6      fvdl 			ppr_options |= MSG_EXT_PPR_DT_REQ;
    470   1.1      fvdl 		else
    471   1.6      fvdl 			ppr_options &= ~MSG_EXT_PPR_DT_REQ;
    472   1.6      fvdl 
    473   1.6      fvdl 		if ((tstate->discenable & devinfo.target_mask) == 0 ||
    474   1.6      fvdl 		    (tstate->tagenable & devinfo.target_mask) == 0)
    475   1.6      fvdl 			ppr_options &= ~MSG_EXT_PPR_IU_REQ;
    476   1.1      fvdl 
    477   1.1      fvdl 		if ((xm->xm_mode & PERIPH_CAP_TQING) &&
    478   1.1      fvdl 		    (ahd->user_tagenable & devinfo.target_mask))
    479   1.1      fvdl 			tstate->tagenable |= devinfo.target_mask;
    480   1.1      fvdl 		else
    481   1.1      fvdl 			tstate->tagenable &= ~devinfo.target_mask;
    482   1.1      fvdl 
    483   1.6      fvdl 		ahd_find_syncrate(ahd, &period, &ppr_options, AHD_SYNCRATE_MAX);
    484   1.6      fvdl 		ahd_validate_offset(ahd, NULL, period, &offset,
    485   1.6      fvdl 		    MSG_EXT_WDTR_BUS_8_BIT, ROLE_UNKNOWN);
    486   1.6      fvdl 		if (offset == 0) {
    487   1.6      fvdl 			period = 0;
    488   1.6      fvdl 			ppr_options = 0;
    489   1.6      fvdl 		}
    490   1.6      fvdl 		if (ppr_options != 0
    491   1.6      fvdl 		    && tinfo->user.transport_version >= 3) {
    492   1.6      fvdl 			tinfo->goal.transport_version =
    493   1.6      fvdl 			    tinfo->user.transport_version;
    494   1.6      fvdl 			tinfo->curr.transport_version =
    495   1.6      fvdl 			    tinfo->user.transport_version;
    496   1.6      fvdl 		}
    497   1.6      fvdl 
    498   1.6      fvdl 		ahd_set_syncrate(ahd, &devinfo, period, offset,
    499   1.6      fvdl 		    ppr_options, AHD_TRANS_GOAL, FALSE);
    500   1.6      fvdl 
    501   1.1      fvdl 		/*
    502   1.1      fvdl 		 * If this is the first request, and no negotiation is
    503   1.1      fvdl 		 * needed, just confirm the state to the scsipi layer,
    504   1.1      fvdl 		 * so that it can print a message.
    505   1.1      fvdl 		 */
    506   1.6      fvdl 		if (old_autoneg == tstate->auto_negotiate && first) {
    507   1.6      fvdl 			xm->xm_mode = 0;
    508   1.6      fvdl 			xm->xm_period = tinfo->curr.period;
    509   1.6      fvdl 			xm->xm_offset = tinfo->curr.offset;
    510   1.6      fvdl 			if (tinfo->curr.width == MSG_EXT_WDTR_BUS_16_BIT)
    511   1.6      fvdl 				xm->xm_mode |= PERIPH_CAP_WIDE16;
    512   1.6      fvdl 			if (tinfo->curr.period)
    513   1.6      fvdl 				xm->xm_mode |= PERIPH_CAP_SYNC;
    514   1.6      fvdl 			if (tstate->tagenable & devinfo.target_mask)
    515   1.6      fvdl 				xm->xm_mode |= PERIPH_CAP_TQING;
    516   1.6      fvdl 			if (tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ)
    517   1.6      fvdl 				xm->xm_mode |= PERIPH_CAP_DT;
    518   1.1      fvdl 			scsipi_async_event(chan, ASYNC_EVENT_XFER_MODE, xm);
    519   1.6      fvdl 		}
    520   1.1      fvdl 		splx(s);
    521   1.1      fvdl 	    }
    522   1.1      fvdl 	}
    523  1.12     perry 
    524   1.1      fvdl 	return;
    525   1.1      fvdl }
    526   1.1      fvdl 
    527   1.1      fvdl static void
    528   1.1      fvdl ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments)
    529   1.1      fvdl {
    530   1.1      fvdl 	struct scb *scb;
    531   1.1      fvdl 	struct scsipi_xfer *xs;
    532  1.23   tsutsui 	struct ahd_softc *ahd;
    533   1.1      fvdl 	struct ahd_initiator_tinfo *tinfo;
    534   1.1      fvdl 	struct ahd_tmode_tstate *tstate;
    535   1.1      fvdl 	u_int  mask;
    536  1.23   tsutsui 	int    s;
    537   1.1      fvdl 
    538  1.25   tsutsui 	scb = arg;
    539   1.1      fvdl 	xs = scb->xs;
    540   1.1      fvdl 	xs->error = 0;
    541   1.1      fvdl 	xs->status = 0;
    542   1.1      fvdl 	xs->xs_status = 0;
    543  1.27   tsutsui 	ahd = device_private(
    544  1.27   tsutsui 	    xs->xs_periph->periph_channel->chan_adapter->adapt_dev);
    545   1.1      fvdl 
    546   1.1      fvdl 	scb->sg_count = 0;
    547   1.1      fvdl 	if (nsegments != 0) {
    548   1.1      fvdl 		void *sg;
    549   1.1      fvdl 		int op;
    550   1.1      fvdl 		u_int i;
    551   1.1      fvdl 
    552   1.1      fvdl 		ahd_setup_data_scb(ahd, scb);
    553   1.1      fvdl 
    554   1.1      fvdl 		/* Copy the segments into our SG list */
    555   1.1      fvdl 		for (i = nsegments, sg = scb->sg_list; i > 0; i--) {
    556   1.1      fvdl 
    557   1.1      fvdl 			sg = ahd_sg_setup(ahd, scb, sg, dm_segs->ds_addr,
    558   1.1      fvdl 					  dm_segs->ds_len,
    559   1.1      fvdl 					  /*last*/i == 1);
    560   1.1      fvdl 			dm_segs++;
    561   1.1      fvdl 		}
    562  1.12     perry 
    563   1.1      fvdl 		if (xs->xs_control & XS_CTL_DATA_IN)
    564   1.1      fvdl 			op = BUS_DMASYNC_PREREAD;
    565   1.1      fvdl 		else
    566   1.1      fvdl 			op = BUS_DMASYNC_PREWRITE;
    567   1.1      fvdl 
    568  1.12     perry 		bus_dmamap_sync(ahd->parent_dmat, scb->dmamap, 0,
    569   1.1      fvdl 				scb->dmamap->dm_mapsize, op);
    570   1.1      fvdl 	}
    571   1.1      fvdl 
    572   1.1      fvdl 	ahd_lock(ahd, &s);
    573   1.1      fvdl 
    574   1.1      fvdl 	/*
    575   1.1      fvdl 	 * Last time we need to check if this SCB needs to
    576   1.1      fvdl 	 * be aborted.
    577   1.1      fvdl 	 */
    578   1.1      fvdl 	if (ahd_get_scsi_status(scb) == XS_STS_DONE) {
    579   1.1      fvdl 		if (nsegments != 0)
    580   1.1      fvdl 			bus_dmamap_unload(ahd->parent_dmat,
    581   1.1      fvdl 					  scb->dmamap);
    582   1.1      fvdl 		ahd_free_scb(ahd, scb);
    583   1.1      fvdl 		ahd_unlock(ahd, &s);
    584   1.1      fvdl 		return;
    585   1.1      fvdl 	}
    586   1.1      fvdl 
    587   1.1      fvdl 	tinfo = ahd_fetch_transinfo(ahd, SCSIID_CHANNEL(ahd, scb->hscb->scsiid),
    588   1.1      fvdl 				    SCSIID_OUR_ID(scb->hscb->scsiid),
    589   1.1      fvdl 				    SCSIID_TARGET(ahd, scb->hscb->scsiid),
    590   1.1      fvdl 				    &tstate);
    591   1.1      fvdl 
    592   1.1      fvdl 	mask = SCB_GET_TARGET_MASK(ahd, scb);
    593   1.1      fvdl 
    594   1.1      fvdl 	if ((tstate->discenable & mask) != 0)
    595   1.1      fvdl 		scb->hscb->control |= DISCENB;
    596   1.1      fvdl 
    597   1.1      fvdl 	if ((tstate->tagenable & mask) != 0)
    598   1.1      fvdl 		scb->hscb->control |= xs->xs_tag_type|TAG_ENB;
    599   1.1      fvdl 
    600   1.1      fvdl 	if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU) != 0) {
    601   1.1      fvdl 		scb->flags |= SCB_PACKETIZED;
    602   1.1      fvdl 		if (scb->hscb->task_management != 0)
    603   1.1      fvdl 			scb->hscb->control &= ~MK_MESSAGE;
    604   1.1      fvdl 	}
    605   1.1      fvdl 
    606   1.6      fvdl #if 0	/* This looks like it makes sense at first, but it can loop */
    607   1.1      fvdl 	if ((xs->xs_control & XS_CTL_DISCOVERY) &&
    608   1.1      fvdl 	    (tinfo->goal.width != 0
    609   1.1      fvdl 	     || tinfo->goal.period != 0
    610   1.1      fvdl 	     || tinfo->goal.ppr_options != 0)) {
    611   1.1      fvdl 		scb->flags |= SCB_NEGOTIATE;
    612   1.1      fvdl 		scb->hscb->control |= MK_MESSAGE;
    613   1.6      fvdl 	} else
    614   1.6      fvdl #endif
    615   1.6      fvdl 	if ((tstate->auto_negotiate & mask) != 0) {
    616  1.23   tsutsui 		scb->flags |= SCB_AUTO_NEGOTIATE;
    617   1.1      fvdl 		scb->hscb->control |= MK_MESSAGE;
    618   1.1      fvdl 	}
    619   1.1      fvdl 
    620   1.1      fvdl 	LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);
    621   1.1      fvdl 
    622   1.1      fvdl 	scb->flags |= SCB_ACTIVE;
    623   1.1      fvdl 
    624   1.1      fvdl 	if (!(xs->xs_control & XS_CTL_POLL)) {
    625   1.1      fvdl 		callout_reset(&scb->xs->xs_callout, xs->timeout > 1000000 ?
    626   1.1      fvdl 			      (xs->timeout / 1000) * hz : (xs->timeout * hz) / 1000,
    627   1.1      fvdl 			      ahd_timeout, scb);
    628   1.1      fvdl 	}
    629   1.1      fvdl 
    630   1.1      fvdl 	if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) {
    631   1.1      fvdl 		/* Define a mapping from our tag to the SCB. */
    632   1.1      fvdl 		ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;
    633   1.1      fvdl 		ahd_pause(ahd);
    634   1.1      fvdl 		ahd_set_scbptr(ahd, SCB_GET_TAG(scb));
    635   1.1      fvdl 		ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_TARG);
    636   1.1      fvdl 		ahd_unpause(ahd);
    637   1.1      fvdl 	} else {
    638   1.1      fvdl 		ahd_queue_scb(ahd, scb);
    639   1.1      fvdl 	}
    640   1.1      fvdl 
    641   1.1      fvdl 	if (!(xs->xs_control & XS_CTL_POLL)) {
    642  1.23   tsutsui 		ahd_unlock(ahd, &s);
    643  1.23   tsutsui 		return;
    644  1.23   tsutsui 	}
    645  1.23   tsutsui 	/*
    646  1.23   tsutsui 	 * If we can't use interrupts, poll for completion
    647  1.23   tsutsui 	 */
    648  1.23   tsutsui 	SC_DEBUG(xs->xs_periph, SCSIPI_DB3, ("cmd_poll\n"));
    649  1.23   tsutsui 	do {
    650  1.23   tsutsui 		if (ahd_poll(ahd, xs->timeout)) {
    651  1.23   tsutsui 			if (!(xs->xs_control & XS_CTL_SILENT))
    652  1.23   tsutsui 				printf("cmd fail\n");
    653  1.23   tsutsui 			ahd_timeout(scb);
    654  1.23   tsutsui 			break;
    655  1.23   tsutsui 		}
    656  1.23   tsutsui 	} while (!(xs->xs_status & XS_STS_DONE));
    657   1.1      fvdl 
    658   1.1      fvdl 	ahd_unlock(ahd, &s);
    659   1.1      fvdl }
    660   1.1      fvdl 
    661   1.1      fvdl static int
    662   1.1      fvdl ahd_poll(struct ahd_softc *ahd, int wait)
    663   1.1      fvdl {
    664   1.1      fvdl 
    665   1.1      fvdl 	while (--wait) {
    666  1.23   tsutsui 		DELAY(1000);
    667  1.23   tsutsui 		if (ahd_inb(ahd, INTSTAT) & INT_PEND)
    668  1.23   tsutsui 			break;
    669  1.23   tsutsui 	}
    670  1.23   tsutsui 
    671  1.23   tsutsui 	if (wait == 0) {
    672  1.23   tsutsui 		printf("%s: board is not responding\n", ahd_name(ahd));
    673  1.23   tsutsui 		return (EIO);
    674  1.23   tsutsui 	}
    675   1.1      fvdl 
    676  1.25   tsutsui 	ahd_intr(ahd);
    677  1.23   tsutsui 	return (0);
    678   1.1      fvdl }
    679   1.1      fvdl 
    680   1.1      fvdl 
    681   1.1      fvdl static void
    682   1.1      fvdl ahd_setup_data(struct ahd_softc *ahd, struct scsipi_xfer *xs,
    683   1.1      fvdl 	       struct scb *scb)
    684   1.1      fvdl {
    685   1.1      fvdl 	struct hardware_scb *hscb;
    686   1.1      fvdl 
    687   1.1      fvdl 	hscb = scb->hscb;
    688   1.1      fvdl 	xs->resid = xs->status = 0;
    689   1.1      fvdl 
    690   1.1      fvdl 	hscb->cdb_len = xs->cmdlen;
    691   1.1      fvdl 	if (hscb->cdb_len > MAX_CDB_LEN) {
    692   1.1      fvdl 		int s;
    693   1.1      fvdl 		/*
    694   1.1      fvdl 		 * Should CAM start to support CDB sizes
    695   1.1      fvdl 		 * greater than 16 bytes, we could use
    696   1.1      fvdl 		 * the sense buffer to store the CDB.
    697   1.1      fvdl 		 */
    698  1.12     perry 		ahd_set_transaction_status(scb,
    699   1.1      fvdl 					   XS_DRIVER_STUFFUP);
    700   1.1      fvdl 
    701   1.1      fvdl 		ahd_lock(ahd, &s);
    702   1.1      fvdl 		ahd_free_scb(ahd, scb);
    703   1.1      fvdl 		ahd_unlock(ahd, &s);
    704   1.1      fvdl 		scsipi_done(xs);
    705   1.1      fvdl 	}
    706   1.1      fvdl 	memcpy(hscb->shared_data.idata.cdb, xs->cmd, hscb->cdb_len);
    707  1.12     perry 
    708   1.1      fvdl 	/* Only use S/G if there is a transfer */
    709  1.23   tsutsui 	if (xs->datalen) {
    710  1.23   tsutsui 		int error;
    711   1.1      fvdl 
    712  1.23   tsutsui 		error = bus_dmamap_load(ahd->parent_dmat,
    713   1.1      fvdl 					scb->dmamap, xs->data,
    714   1.1      fvdl 					xs->datalen, NULL,
    715   1.1      fvdl 					((xs->xs_control & XS_CTL_NOSLEEP) ?
    716   1.1      fvdl 					 BUS_DMA_NOWAIT : BUS_DMA_WAITOK) |
    717   1.1      fvdl 					BUS_DMA_STREAMING |
    718   1.1      fvdl 					((xs->xs_control & XS_CTL_DATA_IN) ?
    719   1.1      fvdl 					 BUS_DMA_READ : BUS_DMA_WRITE));
    720  1.23   tsutsui 		if (error) {
    721   1.1      fvdl #ifdef AHD_DEBUG
    722  1.24   tsutsui 			printf("%s: in ahd_setup_data(): bus_dmamap_load() "
    723   1.1      fvdl 			       "= %d\n",
    724   1.1      fvdl 			       ahd_name(ahd), error);
    725   1.1      fvdl #endif
    726  1.23   tsutsui 			xs->error = XS_RESOURCE_SHORTAGE;
    727  1.23   tsutsui 			scsipi_done(xs);
    728  1.23   tsutsui 			return;
    729  1.23   tsutsui 		}
    730  1.23   tsutsui 		ahd_execute_scb(scb,
    731   1.1      fvdl 				scb->dmamap->dm_segs,
    732   1.1      fvdl 				scb->dmamap->dm_nsegs);
    733  1.23   tsutsui 	} else {
    734  1.23   tsutsui 		ahd_execute_scb(scb, NULL, 0);
    735  1.23   tsutsui 	}
    736   1.1      fvdl }
    737   1.1      fvdl 
    738   1.1      fvdl void
    739   1.1      fvdl ahd_timeout(void *arg)
    740   1.1      fvdl {
    741   1.1      fvdl 	struct	scb	  *scb;
    742   1.1      fvdl 	struct	ahd_softc *ahd;
    743   1.1      fvdl 	int		   s;
    744   1.1      fvdl 
    745  1.25   tsutsui 	scb = arg;
    746  1.25   tsutsui 	ahd = scb->ahd_softc;
    747   1.1      fvdl 
    748   1.1      fvdl 	printf("%s: ahd_timeout\n", ahd_name(ahd));
    749   1.1      fvdl 
    750   1.1      fvdl 	ahd_lock(ahd, &s);
    751   1.1      fvdl 
    752   1.1      fvdl 	ahd_pause_and_flushwork(ahd);
    753  1.32  christos 	(void)ahd_save_modes(ahd);
    754   1.1      fvdl #if 0
    755   1.1      fvdl 	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
    756   1.1      fvdl 	ahd_outb(ahd, SCSISIGO, ACKO);
    757   1.1      fvdl 	printf("set ACK\n");
    758   1.1      fvdl 	ahd_outb(ahd, SCSISIGO, 0);
    759   1.1      fvdl 	printf("clearing Ack\n");
    760   1.1      fvdl 	ahd_restore_modes(ahd, saved_modes);
    761   1.1      fvdl #endif
    762   1.1      fvdl 	if ((scb->flags & SCB_ACTIVE) == 0) {
    763   1.1      fvdl 		/* Previous timeout took care of me already */
    764   1.1      fvdl 		printf("%s: Timedout SCB already complete. "
    765   1.1      fvdl 		       "Interrupts may not be functioning.\n", ahd_name(ahd));
    766   1.1      fvdl 		ahd_unpause(ahd);
    767   1.1      fvdl 		ahd_unlock(ahd, &s);
    768   1.1      fvdl 		return;
    769   1.1      fvdl 	}
    770   1.1      fvdl 
    771   1.1      fvdl 	ahd_print_path(ahd, scb);
    772   1.1      fvdl 	printf("SCB 0x%x - timed out\n", SCB_GET_TAG(scb));
    773   1.1      fvdl 	ahd_dump_card_state(ahd);
    774   1.1      fvdl 	ahd_reset_channel(ahd, SIM_CHANNEL(ahd, sim),
    775   1.1      fvdl 			  /*initiate reset*/TRUE);
    776   1.1      fvdl 	ahd_unlock(ahd, &s);
    777   1.1      fvdl 	return;
    778   1.1      fvdl }
    779   1.1      fvdl 
    780   1.1      fvdl int
    781  1.17  christos ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg)
    782   1.1      fvdl {
    783   1.1      fvdl 	ahd->platform_data = malloc(sizeof(struct ahd_platform_data), M_DEVBUF,
    784  1.34       chs 				    M_WAITOK | M_ZERO);
    785   1.1      fvdl 	return (0);
    786   1.1      fvdl }
    787   1.1      fvdl 
    788   1.1      fvdl void
    789   1.1      fvdl ahd_platform_free(struct ahd_softc *ahd)
    790   1.1      fvdl {
    791   1.1      fvdl 	free(ahd->platform_data, M_DEVBUF);
    792   1.1      fvdl }
    793   1.1      fvdl 
    794   1.1      fvdl int
    795  1.17  christos ahd_softc_comp(struct ahd_softc *lahd, struct ahd_softc *rahd)
    796   1.1      fvdl {
    797   1.1      fvdl 	/* We don't sort softcs under NetBSD so report equal always */
    798   1.1      fvdl 	return (0);
    799   1.1      fvdl }
    800   1.1      fvdl 
    801   1.1      fvdl int
    802  1.28   tsutsui ahd_detach(struct ahd_softc *ahd, int flags)
    803   1.1      fvdl {
    804   1.1      fvdl 	int rv = 0;
    805   1.1      fvdl 
    806   1.1      fvdl 	if (ahd->sc_child != NULL)
    807  1.26   tsutsui 		rv = config_detach(ahd->sc_child, flags);
    808   1.1      fvdl 
    809  1.29   tsutsui 	pmf_device_deregister(ahd->sc_dev);
    810   1.1      fvdl 
    811   1.1      fvdl 	ahd_free(ahd);
    812   1.1      fvdl 
    813   1.1      fvdl 	return rv;
    814   1.1      fvdl }
    815   1.1      fvdl 
    816   1.1      fvdl void
    817   1.1      fvdl ahd_platform_set_tags(struct ahd_softc *ahd,
    818   1.1      fvdl 		      struct ahd_devinfo *devinfo, ahd_queue_alg alg)
    819   1.1      fvdl {
    820  1.23   tsutsui 	struct ahd_tmode_tstate *tstate;
    821   1.1      fvdl 
    822  1.23   tsutsui 	ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid,
    823  1.23   tsutsui 			    devinfo->target, &tstate);
    824   1.1      fvdl 
    825  1.23   tsutsui 	if (alg != AHD_QUEUE_NONE)
    826  1.23   tsutsui 		tstate->tagenable |= devinfo->target_mask;
    827   1.1      fvdl 	else
    828  1.23   tsutsui 		tstate->tagenable &= ~devinfo->target_mask;
    829   1.1      fvdl }
    830   1.1      fvdl 
    831   1.1      fvdl void
    832  1.24   tsutsui ahd_send_async(struct ahd_softc *ahd, char channel, u_int target, u_int lun,
    833  1.17  christos 	       ac_code code, void *opt_arg)
    834   1.1      fvdl {
    835   1.1      fvdl 	struct ahd_tmode_tstate *tstate;
    836   1.1      fvdl 	struct ahd_initiator_tinfo *tinfo;
    837   1.1      fvdl 	struct ahd_devinfo devinfo;
    838   1.1      fvdl 	struct scsipi_channel *chan;
    839   1.1      fvdl 	struct scsipi_xfer_mode xm;
    840   1.1      fvdl 
    841   1.1      fvdl #ifdef DIAGNOSTIC
    842   1.1      fvdl 	if (channel != 'A')
    843   1.1      fvdl 		panic("ahd_send_async: not channel A");
    844   1.1      fvdl #endif
    845  1.24   tsutsui 	chan = &ahd->sc_channel;
    846   1.1      fvdl 	switch (code) {
    847   1.1      fvdl 	case AC_TRANSFER_NEG:
    848  1.24   tsutsui 		tinfo = ahd_fetch_transinfo(ahd, channel, ahd->our_id, target,
    849   1.1      fvdl 			    &tstate);
    850  1.24   tsutsui 		ahd_compile_devinfo(&devinfo, ahd->our_id, target, lun,
    851   1.1      fvdl 		    channel, ROLE_UNKNOWN);
    852   1.1      fvdl 		/*
    853   1.1      fvdl 		 * Don't bother if negotiating. XXX?
    854   1.1      fvdl 		 */
    855   1.1      fvdl 		if (tinfo->curr.period != tinfo->goal.period
    856   1.1      fvdl 		    || tinfo->curr.width != tinfo->goal.width
    857   1.1      fvdl 		    || tinfo->curr.offset != tinfo->goal.offset
    858   1.1      fvdl 		    || tinfo->curr.ppr_options != tinfo->goal.ppr_options)
    859   1.1      fvdl 			break;
    860   1.1      fvdl 		xm.xm_target = target;
    861   1.1      fvdl 		xm.xm_mode = 0;
    862   1.1      fvdl 		xm.xm_period = tinfo->curr.period;
    863   1.1      fvdl 		xm.xm_offset = tinfo->curr.offset;
    864   1.1      fvdl 		if (tinfo->goal.ppr_options & MSG_EXT_PPR_DT_REQ)
    865   1.1      fvdl 			xm.xm_mode |= PERIPH_CAP_DT;
    866   1.1      fvdl 		if (tinfo->curr.width == MSG_EXT_WDTR_BUS_16_BIT)
    867   1.1      fvdl 			xm.xm_mode |= PERIPH_CAP_WIDE16;
    868   1.1      fvdl 		if (tinfo->curr.period)
    869   1.1      fvdl 			xm.xm_mode |= PERIPH_CAP_SYNC;
    870   1.1      fvdl 		if (tstate->tagenable & devinfo.target_mask)
    871   1.1      fvdl 			xm.xm_mode |= PERIPH_CAP_TQING;
    872   1.1      fvdl 		scsipi_async_event(chan, ASYNC_EVENT_XFER_MODE, &xm);
    873   1.1      fvdl 		break;
    874   1.1      fvdl 	case AC_BUS_RESET:
    875   1.1      fvdl 		scsipi_async_event(chan, ASYNC_EVENT_RESET, NULL);
    876   1.1      fvdl 	case AC_SENT_BDR:
    877   1.1      fvdl 	default:
    878   1.1      fvdl 		break;
    879   1.1      fvdl 	}
    880   1.1      fvdl }
    881