Home | History | Annotate | Line # | Download | only in ic
aic79xx_osm.c revision 1.2
      1  1.2  fvdl /*	$NetBSD: aic79xx_osm.c,v 1.2 2003/04/21 16:52:07 fvdl 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.1  fvdl  * $FreeBSD: src/sys/dev/aic7xxx/aic79xx_osm.c,v 1.8 2003/02/27 23:23:16 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.1  fvdl 
     43  1.1  fvdl #include <dev/ic/aic79xx_osm.h>
     44  1.1  fvdl #include <dev/ic/aic7xxx_cam.h>
     45  1.1  fvdl #include <dev/ic/aic79xx_inline.h>
     46  1.1  fvdl 
     47  1.1  fvdl #ifndef AHD_TMODE_ENABLE
     48  1.1  fvdl #define AHD_TMODE_ENABLE 0
     49  1.1  fvdl #endif
     50  1.1  fvdl 
     51  1.1  fvdl static int	ahd_ioctl(struct scsipi_channel *channel, u_long cmd,
     52  1.1  fvdl 			  caddr_t addr, int flag, struct proc *p);
     53  1.1  fvdl static void	ahd_action(struct scsipi_channel *chan,
     54  1.1  fvdl 			   scsipi_adapter_req_t req, void *arg);
     55  1.1  fvdl static void	ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs,
     56  1.1  fvdl 				int nsegments);
     57  1.1  fvdl static int	ahd_poll(struct ahd_softc *ahd, int wait);
     58  1.1  fvdl static void	ahd_setup_data(struct ahd_softc *ahd, struct scsipi_xfer *xs,
     59  1.1  fvdl 			       struct scb *scb);
     60  1.1  fvdl 
     61  1.1  fvdl #if NOT_YET
     62  1.1  fvdl static void	ahd_set_recoveryscb(struct ahd_softc *ahd, struct scb *scb);
     63  1.1  fvdl #endif
     64  1.1  fvdl 
     65  1.1  fvdl /*
     66  1.1  fvdl  * Attach all the sub-devices we can find
     67  1.1  fvdl  */
     68  1.1  fvdl int
     69  1.1  fvdl ahd_attach(struct ahd_softc *ahd)
     70  1.1  fvdl {
     71  1.1  fvdl 	int 	s;
     72  1.1  fvdl 	char	ahd_info[256];
     73  1.1  fvdl 
     74  1.1  fvdl 	ahd_controller_info(ahd, ahd_info);
     75  1.1  fvdl         printf("%s: %s\n", ahd->sc_dev.dv_xname, ahd_info);
     76  1.1  fvdl 
     77  1.1  fvdl         ahd_lock(ahd, &s);
     78  1.1  fvdl 
     79  1.1  fvdl 	ahd->sc_adapter.adapt_dev = &ahd->sc_dev;
     80  1.1  fvdl 	ahd->sc_adapter.adapt_nchannels = 1;
     81  1.1  fvdl 
     82  1.1  fvdl 	ahd->sc_adapter.adapt_openings = AHD_MAX_QUEUE;
     83  1.1  fvdl 	ahd->sc_adapter.adapt_max_periph = 32;
     84  1.1  fvdl 
     85  1.1  fvdl 	ahd->sc_adapter.adapt_ioctl = ahd_ioctl;
     86  1.1  fvdl 	ahd->sc_adapter.adapt_minphys = ahd_minphys;
     87  1.1  fvdl 	ahd->sc_adapter.adapt_request = ahd_action;
     88  1.1  fvdl 
     89  1.1  fvdl 	ahd->sc_channel.chan_adapter = &ahd->sc_adapter;
     90  1.1  fvdl         ahd->sc_channel.chan_bustype = &scsi_bustype;
     91  1.1  fvdl         ahd->sc_channel.chan_channel = 0;
     92  1.1  fvdl         ahd->sc_channel.chan_ntargets = AHD_NUM_TARGETS;
     93  1.1  fvdl         ahd->sc_channel.chan_nluns = 8 /*AHD_NUM_LUNS*/;
     94  1.1  fvdl         ahd->sc_channel.chan_id = ahd->our_id;
     95  1.1  fvdl 
     96  1.1  fvdl 	ahd->sc_child = config_found((void *)ahd, &ahd->sc_channel, scsiprint);
     97  1.1  fvdl 
     98  1.1  fvdl 	ahd_intr_enable(ahd, TRUE);
     99  1.1  fvdl 
    100  1.1  fvdl         ahd_unlock(ahd, &s);
    101  1.1  fvdl 
    102  1.1  fvdl 	return (1);
    103  1.1  fvdl }
    104  1.1  fvdl 
    105  1.1  fvdl static int
    106  1.1  fvdl ahd_ioctl(struct scsipi_channel *channel, u_long cmd,
    107  1.1  fvdl 	  caddr_t addr, int flag, struct proc *p)
    108  1.1  fvdl {
    109  1.1  fvdl         struct ahd_softc *ahd = (void *)channel->chan_adapter->adapt_dev;
    110  1.1  fvdl         int s, ret = ENOTTY;
    111  1.1  fvdl 
    112  1.1  fvdl         switch (cmd) {
    113  1.1  fvdl         case SCBUSIORESET:
    114  1.1  fvdl                 s = splbio();
    115  1.1  fvdl                 ahd_reset_channel(ahd, channel->chan_channel == 1 ? 'B' : 'A', TRUE);
    116  1.1  fvdl                 splx(s);
    117  1.1  fvdl                 ret = 0;
    118  1.1  fvdl                 break;
    119  1.1  fvdl         default:
    120  1.1  fvdl                 break;
    121  1.1  fvdl         }
    122  1.1  fvdl 
    123  1.1  fvdl         return ret;
    124  1.1  fvdl }
    125  1.1  fvdl 
    126  1.1  fvdl /*
    127  1.1  fvdl  * Catch an interrupt from the adapter
    128  1.1  fvdl  */
    129  1.1  fvdl void
    130  1.1  fvdl ahd_platform_intr(void *arg)
    131  1.1  fvdl {
    132  1.1  fvdl 	struct	ahd_softc *ahd;
    133  1.1  fvdl 
    134  1.1  fvdl 	ahd = (struct ahd_softc *)arg;
    135  1.1  fvdl 
    136  1.1  fvdl 	printf("%s; ahd_platform_intr\n", ahd_name(ahd));
    137  1.1  fvdl 
    138  1.1  fvdl 	ahd_intr(ahd);
    139  1.1  fvdl }
    140  1.1  fvdl 
    141  1.1  fvdl /*
    142  1.1  fvdl  * We have an scb which has been processed by the
    143  1.1  fvdl  * adaptor, now we look to see how the operation * went.
    144  1.1  fvdl  */
    145  1.1  fvdl void
    146  1.1  fvdl ahd_done(struct ahd_softc *ahd, struct scb *scb)
    147  1.1  fvdl {
    148  1.1  fvdl 	struct scsipi_xfer	*xs;
    149  1.1  fvdl 	struct scsipi_periph	*periph;
    150  1.1  fvdl 	int			target;
    151  1.1  fvdl 	int			s;
    152  1.1  fvdl 
    153  1.1  fvdl 	LIST_REMOVE(scb, pending_links);
    154  1.1  fvdl 
    155  1.1  fvdl 	xs = scb->xs;
    156  1.1  fvdl 	periph = xs->xs_periph;
    157  1.1  fvdl 
    158  1.1  fvdl 	callout_stop(&scb->xs->xs_callout);
    159  1.1  fvdl 
    160  1.1  fvdl 	target = periph->periph_target;
    161  1.1  fvdl 
    162  1.1  fvdl 	if (xs->datalen) {
    163  1.1  fvdl 		int op;
    164  1.1  fvdl 
    165  1.1  fvdl 		if (xs->xs_control & XS_CTL_DATA_IN)
    166  1.1  fvdl 		  op = BUS_DMASYNC_POSTREAD;
    167  1.1  fvdl 		else
    168  1.1  fvdl 		  op = BUS_DMASYNC_POSTWRITE;
    169  1.1  fvdl 
    170  1.1  fvdl 		bus_dmamap_sync(ahd->parent_dmat, scb->dmamap, 0,
    171  1.1  fvdl 				scb->dmamap->dm_mapsize, op);
    172  1.1  fvdl                 bus_dmamap_unload(ahd->parent_dmat, scb->dmamap);
    173  1.1  fvdl         }
    174  1.1  fvdl 
    175  1.1  fvdl 	/*
    176  1.1  fvdl 	 * If the recovery SCB completes, we have to be
    177  1.1  fvdl 	 * out of our timeout.
    178  1.1  fvdl 	 */
    179  1.1  fvdl 	if ((scb->flags & SCB_RECOVERY_SCB) != 0) {
    180  1.1  fvdl 		struct	scb *list_scb;
    181  1.1  fvdl 
    182  1.1  fvdl 		/*
    183  1.1  fvdl 		 * We were able to complete the command successfully,
    184  1.1  fvdl 		 * so reinstate the timeouts for all other pending
    185  1.1  fvdl 		 * commands.
    186  1.1  fvdl 		 */
    187  1.1  fvdl 		LIST_FOREACH(list_scb, &ahd->pending_scbs, pending_links) {
    188  1.1  fvdl 			struct scsipi_xfer	*txs = list_scb->xs;
    189  1.1  fvdl 
    190  1.1  fvdl 			if (!(txs->xs_control & XS_CTL_POLL)) {
    191  1.1  fvdl                                 callout_reset(&txs->xs_callout,
    192  1.1  fvdl                                     (txs->timeout > 1000000) ?
    193  1.1  fvdl                                     (txs->timeout / 1000) * hz :
    194  1.1  fvdl                                     (txs->timeout * hz) / 1000,
    195  1.1  fvdl                                     ahd_timeout, list_scb);
    196  1.1  fvdl                         }
    197  1.1  fvdl 		}
    198  1.1  fvdl 
    199  1.1  fvdl 		if (ahd_get_transaction_status(scb) != XS_NOERROR)
    200  1.1  fvdl 		  ahd_set_transaction_status(scb, XS_TIMEOUT);
    201  1.1  fvdl                 scsipi_printaddr(xs->xs_periph);
    202  1.1  fvdl 		printf("%s: no longer in timeout, status = %x\n",
    203  1.1  fvdl 		       ahd_name(ahd), xs->status);
    204  1.1  fvdl 	}
    205  1.1  fvdl 
    206  1.1  fvdl 	if (xs->error != XS_NOERROR) {
    207  1.1  fvdl                 /* Don't clobber any existing error state */
    208  1.1  fvdl 	} else if ((xs->status == SCSI_STATUS_BUSY) ||
    209  1.1  fvdl 		   (xs->status == SCSI_STATUS_QUEUE_FULL)) {
    210  1.1  fvdl 	  	ahd_set_transaction_status(scb, XS_BUSY);
    211  1.1  fvdl 		printf("%s: drive (ID %d, LUN %d) queue full (SCB 0x%x)\n",
    212  1.1  fvdl 		       ahd_name(ahd), SCB_GET_TARGET(ahd,scb), SCB_GET_LUN(scb), SCB_GET_TAG(scb));
    213  1.1  fvdl         } else if ((scb->flags & SCB_SENSE) != 0) {
    214  1.1  fvdl                 /*
    215  1.1  fvdl                  * We performed autosense retrieval.
    216  1.1  fvdl                  *
    217  1.1  fvdl                  * zero the sense data before having
    218  1.1  fvdl                  * the drive fill it.  The SCSI spec mandates
    219  1.1  fvdl                  * that any untransferred data should be
    220  1.1  fvdl                  * assumed to be zero.  Complete the 'bounce'
    221  1.1  fvdl                  * of sense information through buffers accessible
    222  1.1  fvdl                  * via bus-space by copying it into the clients
    223  1.1  fvdl                  * csio.
    224  1.1  fvdl                  */
    225  1.1  fvdl                 memset(&xs->sense.scsi_sense, 0, sizeof(xs->sense.scsi_sense));
    226  1.1  fvdl                 memcpy(&xs->sense.scsi_sense, ahd_get_sense_buf(ahd, scb),
    227  1.1  fvdl 		       sizeof(struct scsipi_sense_data));
    228  1.1  fvdl 
    229  1.1  fvdl                 ahd_set_transaction_status(scb, XS_SENSE);
    230  1.1  fvdl         } else if ((scb->flags & SCB_PKT_SENSE) != 0) {
    231  1.1  fvdl 		struct scsi_status_iu_header *siu;
    232  1.1  fvdl 		u_int sense_len;
    233  1.1  fvdl 		int i;
    234  1.1  fvdl 
    235  1.1  fvdl 		/*
    236  1.1  fvdl 		 * Copy only the sense data into the provided buffer.
    237  1.1  fvdl 		 */
    238  1.1  fvdl 		siu = (struct scsi_status_iu_header *)scb->sense_data;
    239  1.1  fvdl 		sense_len = MIN(scsi_4btoul(siu->sense_length),
    240  1.1  fvdl 				sizeof(&xs->sense.scsi_sense));
    241  1.1  fvdl 		memset(&xs->sense.scsi_sense, 0, sizeof(xs->sense.scsi_sense));
    242  1.1  fvdl 		memcpy(&xs->sense.scsi_sense,
    243  1.1  fvdl 		       scb->sense_data + SIU_SENSE_OFFSET(siu), sense_len);
    244  1.1  fvdl 		printf("Copied %d bytes of sense data offset %d:", sense_len,
    245  1.1  fvdl 		       SIU_SENSE_OFFSET(siu));
    246  1.1  fvdl 		for (i = 0; i < sense_len; i++)
    247  1.1  fvdl 			printf(" 0x%x", ((uint8_t *)&xs->sense.scsi_sense)[i]);
    248  1.1  fvdl 		printf("\n");
    249  1.1  fvdl 
    250  1.1  fvdl                 ahd_set_transaction_status(scb, XS_SENSE);
    251  1.1  fvdl 	}
    252  1.1  fvdl 
    253  1.1  fvdl 	if (scb->flags & SCB_FREEZE_QUEUE) {
    254  1.1  fvdl 	        scsipi_periph_thaw(periph, 1);
    255  1.1  fvdl                 scb->flags &= ~SCB_FREEZE_QUEUE;
    256  1.1  fvdl         }
    257  1.1  fvdl 
    258  1.1  fvdl         if (scb->flags & SCB_REQUEUE)
    259  1.1  fvdl                 ahd_set_transaction_status(scb, XS_REQUEUE);
    260  1.1  fvdl 
    261  1.1  fvdl         ahd_lock(ahd, &s);
    262  1.1  fvdl         ahd_free_scb(ahd, scb);
    263  1.1  fvdl         ahd_unlock(ahd, &s);
    264  1.1  fvdl 
    265  1.1  fvdl         scsipi_done(xs);
    266  1.1  fvdl }
    267  1.1  fvdl 
    268  1.1  fvdl static void
    269  1.1  fvdl ahd_action(struct scsipi_channel *chan, scsipi_adapter_req_t req, void *arg)
    270  1.1  fvdl {
    271  1.1  fvdl         struct ahd_softc *ahd;
    272  1.1  fvdl 	struct ahd_initiator_tinfo *tinfo;
    273  1.1  fvdl 	struct ahd_tmode_tstate *tstate;
    274  1.1  fvdl 	int s;
    275  1.1  fvdl 
    276  1.1  fvdl 	ahd = (void *)chan->chan_adapter->adapt_dev;
    277  1.1  fvdl 
    278  1.1  fvdl 	if (ahd->inited_channels[0] == 0) {
    279  1.1  fvdl 		if (ahd->flags & AHD_RESET_BUS_A) {
    280  1.1  fvdl 			s = splbio();
    281  1.1  fvdl 			ahd_reset_channel(ahd, 'A', TRUE);
    282  1.1  fvdl 			splx(s);
    283  1.1  fvdl 		}
    284  1.1  fvdl 		ahd->inited_channels[0] = 1;
    285  1.1  fvdl 	}
    286  1.1  fvdl 
    287  1.1  fvdl 	switch(req) {
    288  1.1  fvdl 
    289  1.1  fvdl 	case ADAPTER_REQ_RUN_XFER:
    290  1.1  fvdl 	  {
    291  1.1  fvdl 		struct scsipi_xfer *xs;
    292  1.1  fvdl         	struct scsipi_periph *periph;
    293  1.1  fvdl 	        struct scb *scb;
    294  1.1  fvdl         	struct hardware_scb *hscb;
    295  1.1  fvdl 		u_int target_id;
    296  1.1  fvdl 		u_int our_id;
    297  1.1  fvdl 		u_int col_idx;
    298  1.1  fvdl 		char channel;
    299  1.1  fvdl 		int s;
    300  1.1  fvdl 
    301  1.1  fvdl 	  	xs = arg;
    302  1.1  fvdl                 periph = xs->xs_periph;
    303  1.1  fvdl 
    304  1.1  fvdl                 SC_DEBUG(periph, SCSIPI_DB3, ("ahd_action\n"));
    305  1.1  fvdl 
    306  1.1  fvdl 		target_id = periph->periph_target;
    307  1.1  fvdl                 our_id = ahd->our_id;
    308  1.1  fvdl                 channel = (chan->chan_channel == 1) ? 'B' : 'A';
    309  1.1  fvdl 
    310  1.1  fvdl                 /*
    311  1.1  fvdl 		 * get an scb to use.
    312  1.1  fvdl 		 */
    313  1.1  fvdl 		ahd_lock(ahd, &s);
    314  1.1  fvdl 		tinfo = ahd_fetch_transinfo(ahd, channel, our_id,
    315  1.1  fvdl 					    target_id, &tstate);
    316  1.1  fvdl 
    317  1.1  fvdl 		col_idx = AHD_NEVER_COL_IDX; /* ??? */
    318  1.1  fvdl 
    319  1.1  fvdl 		if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) {
    320  1.1  fvdl 			xs->error = XS_RESOURCE_SHORTAGE;
    321  1.1  fvdl 			ahd_unlock(ahd, &s);
    322  1.1  fvdl 			scsipi_done(xs);
    323  1.1  fvdl 			return;
    324  1.1  fvdl 		}
    325  1.1  fvdl 		ahd_unlock(ahd, &s);
    326  1.1  fvdl 
    327  1.1  fvdl 		hscb = scb->hscb;
    328  1.1  fvdl 
    329  1.1  fvdl 		SC_DEBUG(periph, SCSIPI_DB3, ("start scb(%p)\n", scb));
    330  1.1  fvdl 		scb->xs = xs;
    331  1.1  fvdl 
    332  1.1  fvdl 		/*
    333  1.1  fvdl 		 * Put all the arguments for the xfer in the scb
    334  1.1  fvdl 		 */
    335  1.1  fvdl 		hscb->control = 0;
    336  1.1  fvdl 		hscb->scsiid = BUILD_SCSIID(ahd, sim, target_id, our_id);
    337  1.1  fvdl 		hscb->lun = periph->periph_lun;
    338  1.1  fvdl 		if (xs->xs_control & XS_CTL_RESET) {
    339  1.1  fvdl 			hscb->cdb_len = 0;
    340  1.1  fvdl 			scb->flags |= SCB_DEVICE_RESET;
    341  1.1  fvdl 			hscb->control |= MK_MESSAGE;
    342  1.1  fvdl 			hscb->task_management = SIU_TASKMGMT_LUN_RESET;
    343  1.1  fvdl 			ahd_execute_scb(scb, NULL, 0);
    344  1.1  fvdl 		} else {
    345  1.1  fvdl 			hscb->task_management = 0;
    346  1.1  fvdl 		}
    347  1.1  fvdl 
    348  1.1  fvdl 		ahd_setup_data(ahd, xs, scb);
    349  1.1  fvdl 		break;
    350  1.1  fvdl 	  }
    351  1.1  fvdl 
    352  1.1  fvdl 	case ADAPTER_REQ_GROW_RESOURCES:
    353  1.1  fvdl 		printf("%s: ADAPTER_REQ_GROW_RESOURCES\n", ahd_name(ahd));
    354  1.1  fvdl 		break;
    355  1.1  fvdl 
    356  1.1  fvdl 	case ADAPTER_REQ_SET_XFER_MODE:
    357  1.1  fvdl 	    {
    358  1.1  fvdl 		struct scsipi_xfer_mode *xm = arg;
    359  1.1  fvdl 		struct ahd_devinfo devinfo;
    360  1.1  fvdl 		int target_id, our_id, first;
    361  1.1  fvdl 		u_int width;
    362  1.1  fvdl 		int s;
    363  1.1  fvdl 		char channel;
    364  1.1  fvdl 
    365  1.1  fvdl 		target_id = xm->xm_target;
    366  1.1  fvdl 		our_id = chan->chan_id;
    367  1.1  fvdl 		channel = 'A';
    368  1.1  fvdl 		s = splbio();
    369  1.1  fvdl 		tinfo = ahd_fetch_transinfo(ahd, channel, our_id, target_id,
    370  1.1  fvdl 		    &tstate);
    371  1.1  fvdl 		ahd_compile_devinfo(&devinfo, our_id, target_id,
    372  1.1  fvdl 		    0, channel, ROLE_INITIATOR);
    373  1.1  fvdl 
    374  1.1  fvdl 		/*
    375  1.1  fvdl 		 * XXX since the period and offset are not provided here,
    376  1.1  fvdl 		 * fake things by forcing a renegotiation using the user
    377  1.1  fvdl 		 * settings if this is called for the first time (i.e.
    378  1.1  fvdl 		 * during probe). Also, cap various values at the user
    379  1.1  fvdl 		 * values, assuming that the user set it up that way.
    380  1.1  fvdl 		 */
    381  1.1  fvdl 		if (ahd->inited_target[target_id] == 0) {
    382  1.1  fvdl 			tinfo->goal = tinfo->user;
    383  1.1  fvdl 			tstate->tagenable |=
    384  1.1  fvdl 			    (ahd->user_tagenable & devinfo.target_mask);
    385  1.1  fvdl 			tstate->discenable |=
    386  1.1  fvdl 			    (ahd->user_discenable & devinfo.target_mask);
    387  1.1  fvdl 			ahd->inited_target[target_id] = 1;
    388  1.1  fvdl 			first = 1;
    389  1.1  fvdl 		} else
    390  1.1  fvdl 			first = 0;
    391  1.1  fvdl 
    392  1.2  fvdl 		if (xm->xm_mode & (PERIPH_CAP_WIDE16 | PERIPH_CAP_DT))
    393  1.1  fvdl 			width = MSG_EXT_WDTR_BUS_16_BIT;
    394  1.1  fvdl 		else
    395  1.1  fvdl 			width = MSG_EXT_WDTR_BUS_8_BIT;
    396  1.1  fvdl 
    397  1.1  fvdl 		ahd_validate_width(ahd, NULL, &width, ROLE_UNKNOWN);
    398  1.1  fvdl 		if (width > tinfo->user.width)
    399  1.1  fvdl 			width = tinfo->user.width;
    400  1.1  fvdl 		tinfo->goal.width = width;
    401  1.1  fvdl 
    402  1.2  fvdl 		if (!(xm->xm_mode & (PERIPH_CAP_SYNC | PERIPH_CAP_DT))) {
    403  1.1  fvdl 			tinfo->goal.period = 0;
    404  1.1  fvdl 			tinfo->goal.offset = 0;
    405  1.1  fvdl 			tinfo->goal.ppr_options = 0;
    406  1.1  fvdl 		}
    407  1.1  fvdl 
    408  1.1  fvdl 		if ((xm->xm_mode & PERIPH_CAP_DT) &&
    409  1.1  fvdl 		    (tinfo->user.ppr_options & MSG_EXT_PPR_DT_REQ))
    410  1.1  fvdl 			tinfo->goal.ppr_options |= MSG_EXT_PPR_DT_REQ;
    411  1.1  fvdl 		else
    412  1.1  fvdl 			tinfo->goal.ppr_options &= ~MSG_EXT_PPR_DT_REQ;
    413  1.1  fvdl 
    414  1.1  fvdl 		if ((xm->xm_mode & PERIPH_CAP_TQING) &&
    415  1.1  fvdl 		    (ahd->user_tagenable & devinfo.target_mask))
    416  1.1  fvdl 			tstate->tagenable |= devinfo.target_mask;
    417  1.1  fvdl 		else
    418  1.1  fvdl 			tstate->tagenable &= ~devinfo.target_mask;
    419  1.1  fvdl 
    420  1.1  fvdl 		/*
    421  1.1  fvdl 		 * If this is the first request, and no negotiation is
    422  1.1  fvdl 		 * needed, just confirm the state to the scsipi layer,
    423  1.1  fvdl 		 * so that it can print a message.
    424  1.1  fvdl 		 */
    425  1.1  fvdl 		if (!ahd_update_neg_request(ahd, &devinfo, tstate,
    426  1.1  fvdl 		    tinfo, AHD_NEG_IF_NON_ASYNC) && first)
    427  1.1  fvdl 			scsipi_async_event(chan, ASYNC_EVENT_XFER_MODE, xm);
    428  1.1  fvdl 		splx(s);
    429  1.1  fvdl 	    }
    430  1.1  fvdl 	}
    431  1.1  fvdl 
    432  1.1  fvdl 	return;
    433  1.1  fvdl }
    434  1.1  fvdl 
    435  1.1  fvdl static void
    436  1.1  fvdl ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments)
    437  1.1  fvdl {
    438  1.1  fvdl 	struct scb *scb;
    439  1.1  fvdl 	struct scsipi_xfer *xs;
    440  1.1  fvdl         struct ahd_softc *ahd;
    441  1.1  fvdl 	struct ahd_initiator_tinfo *tinfo;
    442  1.1  fvdl 	struct ahd_tmode_tstate *tstate;
    443  1.1  fvdl 	u_int  mask;
    444  1.1  fvdl         int    s;
    445  1.1  fvdl 
    446  1.1  fvdl 	scb = (struct scb*)arg;
    447  1.1  fvdl 	xs = scb->xs;
    448  1.1  fvdl 	xs->error = 0;
    449  1.1  fvdl 	xs->status = 0;
    450  1.1  fvdl 	xs->xs_status = 0;
    451  1.1  fvdl 	ahd = (void*)xs->xs_periph->periph_channel->chan_adapter->adapt_dev;
    452  1.1  fvdl 
    453  1.1  fvdl 	scb->sg_count = 0;
    454  1.1  fvdl 	if (nsegments != 0) {
    455  1.1  fvdl 		void *sg;
    456  1.1  fvdl 		int op;
    457  1.1  fvdl 		u_int i;
    458  1.1  fvdl 
    459  1.1  fvdl 		ahd_setup_data_scb(ahd, scb);
    460  1.1  fvdl 
    461  1.1  fvdl 		/* Copy the segments into our SG list */
    462  1.1  fvdl 		for (i = nsegments, sg = scb->sg_list; i > 0; i--) {
    463  1.1  fvdl 
    464  1.1  fvdl 			sg = ahd_sg_setup(ahd, scb, sg, dm_segs->ds_addr,
    465  1.1  fvdl 					  dm_segs->ds_len,
    466  1.1  fvdl 					  /*last*/i == 1);
    467  1.1  fvdl 			dm_segs++;
    468  1.1  fvdl 		}
    469  1.1  fvdl 
    470  1.1  fvdl 		if (xs->xs_control & XS_CTL_DATA_IN)
    471  1.1  fvdl 			op = BUS_DMASYNC_PREREAD;
    472  1.1  fvdl 		else
    473  1.1  fvdl 			op = BUS_DMASYNC_PREWRITE;
    474  1.1  fvdl 
    475  1.1  fvdl 		bus_dmamap_sync(ahd->parent_dmat, scb->dmamap, 0,
    476  1.1  fvdl 				scb->dmamap->dm_mapsize, op);
    477  1.1  fvdl 	}
    478  1.1  fvdl 
    479  1.1  fvdl 	ahd_lock(ahd, &s);
    480  1.1  fvdl 
    481  1.1  fvdl 	/*
    482  1.1  fvdl 	 * Last time we need to check if this SCB needs to
    483  1.1  fvdl 	 * be aborted.
    484  1.1  fvdl 	 */
    485  1.1  fvdl 	if (ahd_get_scsi_status(scb) == XS_STS_DONE) {
    486  1.1  fvdl 		if (nsegments != 0)
    487  1.1  fvdl 			bus_dmamap_unload(ahd->parent_dmat,
    488  1.1  fvdl 					  scb->dmamap);
    489  1.1  fvdl 		ahd_free_scb(ahd, scb);
    490  1.1  fvdl 		ahd_unlock(ahd, &s);
    491  1.1  fvdl 		return;
    492  1.1  fvdl 	}
    493  1.1  fvdl 
    494  1.1  fvdl 	tinfo = ahd_fetch_transinfo(ahd, SCSIID_CHANNEL(ahd, scb->hscb->scsiid),
    495  1.1  fvdl 				    SCSIID_OUR_ID(scb->hscb->scsiid),
    496  1.1  fvdl 				    SCSIID_TARGET(ahd, scb->hscb->scsiid),
    497  1.1  fvdl 				    &tstate);
    498  1.1  fvdl 
    499  1.1  fvdl 	mask = SCB_GET_TARGET_MASK(ahd, scb);
    500  1.1  fvdl 
    501  1.1  fvdl 	if ((tstate->discenable & mask) != 0)
    502  1.1  fvdl 		scb->hscb->control |= DISCENB;
    503  1.1  fvdl 
    504  1.1  fvdl 	if ((tstate->tagenable & mask) != 0)
    505  1.1  fvdl 		scb->hscb->control |= xs->xs_tag_type|TAG_ENB;
    506  1.1  fvdl 
    507  1.1  fvdl 	if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU) != 0) {
    508  1.1  fvdl 		scb->flags |= SCB_PACKETIZED;
    509  1.1  fvdl 		if (scb->hscb->task_management != 0)
    510  1.1  fvdl 			scb->hscb->control &= ~MK_MESSAGE;
    511  1.1  fvdl 	}
    512  1.1  fvdl 
    513  1.1  fvdl 	if ((xs->xs_control & XS_CTL_DISCOVERY) &&
    514  1.1  fvdl 	    (tinfo->goal.width != 0
    515  1.1  fvdl 	     || tinfo->goal.period != 0
    516  1.1  fvdl 	     || tinfo->goal.ppr_options != 0)) {
    517  1.1  fvdl 		scb->flags |= SCB_NEGOTIATE;
    518  1.1  fvdl 		scb->hscb->control |= MK_MESSAGE;
    519  1.1  fvdl 	} else if ((tstate->auto_negotiate & mask) != 0) {
    520  1.1  fvdl 	  	scb->flags |= SCB_AUTO_NEGOTIATE;
    521  1.1  fvdl 		scb->hscb->control |= MK_MESSAGE;
    522  1.1  fvdl 	}
    523  1.1  fvdl 
    524  1.1  fvdl 	LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);
    525  1.1  fvdl 
    526  1.1  fvdl 	scb->flags |= SCB_ACTIVE;
    527  1.1  fvdl 
    528  1.1  fvdl 	if (!(xs->xs_control & XS_CTL_POLL)) {
    529  1.1  fvdl 		callout_reset(&scb->xs->xs_callout, xs->timeout > 1000000 ?
    530  1.1  fvdl 			      (xs->timeout / 1000) * hz : (xs->timeout * hz) / 1000,
    531  1.1  fvdl 			      ahd_timeout, scb);
    532  1.1  fvdl 	}
    533  1.1  fvdl 
    534  1.1  fvdl 	if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) {
    535  1.1  fvdl 		/* Define a mapping from our tag to the SCB. */
    536  1.1  fvdl 		ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;
    537  1.1  fvdl 		ahd_pause(ahd);
    538  1.1  fvdl 		ahd_set_scbptr(ahd, SCB_GET_TAG(scb));
    539  1.1  fvdl 		ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_TARG);
    540  1.1  fvdl 		ahd_unpause(ahd);
    541  1.1  fvdl 	} else {
    542  1.1  fvdl 		ahd_queue_scb(ahd, scb);
    543  1.1  fvdl 	}
    544  1.1  fvdl 
    545  1.1  fvdl 	if (!(xs->xs_control & XS_CTL_POLL)) {
    546  1.1  fvdl                 ahd_unlock(ahd, &s);
    547  1.1  fvdl                 return;
    548  1.1  fvdl         }
    549  1.1  fvdl         /*
    550  1.1  fvdl          * If we can't use interrupts, poll for completion
    551  1.1  fvdl          */
    552  1.1  fvdl         SC_DEBUG(xs->xs_periph, SCSIPI_DB3, ("cmd_poll\n"));
    553  1.1  fvdl         do {
    554  1.1  fvdl                 if (ahd_poll(ahd, xs->timeout)) {
    555  1.1  fvdl                         if (!(xs->xs_control & XS_CTL_SILENT))
    556  1.1  fvdl                                 printf("cmd fail\n");
    557  1.1  fvdl                         ahd_timeout(scb);
    558  1.1  fvdl                         break;
    559  1.1  fvdl                 }
    560  1.1  fvdl         } while (!(xs->xs_status & XS_STS_DONE));
    561  1.1  fvdl 
    562  1.1  fvdl 	ahd_unlock(ahd, &s);
    563  1.1  fvdl }
    564  1.1  fvdl 
    565  1.1  fvdl static int
    566  1.1  fvdl ahd_poll(struct ahd_softc *ahd, int wait)
    567  1.1  fvdl {
    568  1.1  fvdl 
    569  1.1  fvdl 	while (--wait) {
    570  1.1  fvdl                 DELAY(1000);
    571  1.1  fvdl                 if (ahd_inb(ahd, INTSTAT) & INT_PEND)
    572  1.1  fvdl                         break;
    573  1.1  fvdl         }
    574  1.1  fvdl 
    575  1.1  fvdl         if (wait == 0) {
    576  1.1  fvdl                 printf("%s: board is not responding\n", ahd_name(ahd));
    577  1.1  fvdl                 return (EIO);
    578  1.1  fvdl         }
    579  1.1  fvdl 
    580  1.1  fvdl         ahd_intr((void *)ahd);
    581  1.1  fvdl         return (0);
    582  1.1  fvdl }
    583  1.1  fvdl 
    584  1.1  fvdl 
    585  1.1  fvdl static void
    586  1.1  fvdl ahd_setup_data(struct ahd_softc *ahd, struct scsipi_xfer *xs,
    587  1.1  fvdl 	       struct scb *scb)
    588  1.1  fvdl {
    589  1.1  fvdl 	struct hardware_scb *hscb;
    590  1.1  fvdl 
    591  1.1  fvdl 	hscb = scb->hscb;
    592  1.1  fvdl 	xs->resid = xs->status = 0;
    593  1.1  fvdl 
    594  1.1  fvdl 	hscb->cdb_len = xs->cmdlen;
    595  1.1  fvdl 	if (hscb->cdb_len > MAX_CDB_LEN) {
    596  1.1  fvdl 		int s;
    597  1.1  fvdl 		/*
    598  1.1  fvdl 		 * Should CAM start to support CDB sizes
    599  1.1  fvdl 		 * greater than 16 bytes, we could use
    600  1.1  fvdl 		 * the sense buffer to store the CDB.
    601  1.1  fvdl 		 */
    602  1.1  fvdl 		ahd_set_transaction_status(scb,
    603  1.1  fvdl 					   XS_DRIVER_STUFFUP);
    604  1.1  fvdl 
    605  1.1  fvdl 		ahd_lock(ahd, &s);
    606  1.1  fvdl 		ahd_free_scb(ahd, scb);
    607  1.1  fvdl 		ahd_unlock(ahd, &s);
    608  1.1  fvdl 		scsipi_done(xs);
    609  1.1  fvdl 	}
    610  1.1  fvdl 	memcpy(hscb->shared_data.idata.cdb, xs->cmd, hscb->cdb_len);
    611  1.1  fvdl 
    612  1.1  fvdl 	/* Only use S/G if there is a transfer */
    613  1.1  fvdl         if (xs->datalen) {
    614  1.1  fvdl                 int error;
    615  1.1  fvdl 
    616  1.1  fvdl                 error = bus_dmamap_load(ahd->parent_dmat,
    617  1.1  fvdl 					scb->dmamap, xs->data,
    618  1.1  fvdl 					xs->datalen, NULL,
    619  1.1  fvdl 					((xs->xs_control & XS_CTL_NOSLEEP) ?
    620  1.1  fvdl 					 BUS_DMA_NOWAIT : BUS_DMA_WAITOK) |
    621  1.1  fvdl 					BUS_DMA_STREAMING |
    622  1.1  fvdl 					((xs->xs_control & XS_CTL_DATA_IN) ?
    623  1.1  fvdl 					 BUS_DMA_READ : BUS_DMA_WRITE));
    624  1.1  fvdl                 if (error) {
    625  1.1  fvdl #ifdef AHD_DEBUG
    626  1.1  fvdl                         printf("%s: in ahc_setup_data(): bus_dmamap_load() "
    627  1.1  fvdl 			       "= %d\n",
    628  1.1  fvdl 			       ahd_name(ahd), error);
    629  1.1  fvdl #endif
    630  1.1  fvdl                         xs->error = XS_RESOURCE_SHORTAGE;
    631  1.1  fvdl                         scsipi_done(xs);
    632  1.1  fvdl                         return;
    633  1.1  fvdl                 }
    634  1.1  fvdl                 ahd_execute_scb(scb,
    635  1.1  fvdl 				scb->dmamap->dm_segs,
    636  1.1  fvdl 				scb->dmamap->dm_nsegs);
    637  1.1  fvdl         } else {
    638  1.1  fvdl                 ahd_execute_scb(scb, NULL, 0);
    639  1.1  fvdl         }
    640  1.1  fvdl }
    641  1.1  fvdl 
    642  1.1  fvdl void
    643  1.1  fvdl ahd_timeout(void *arg)
    644  1.1  fvdl {
    645  1.1  fvdl 	struct	scb	  *scb;
    646  1.1  fvdl 	struct	ahd_softc *ahd;
    647  1.1  fvdl 	ahd_mode_state	   saved_modes;
    648  1.1  fvdl 	int		   s;
    649  1.1  fvdl 	int		   target;
    650  1.1  fvdl 	int		   lun;
    651  1.1  fvdl 	char		   channel;
    652  1.1  fvdl 
    653  1.1  fvdl 	scb = (struct scb *)arg;
    654  1.1  fvdl 	ahd = (struct ahd_softc *)scb->ahd_softc;
    655  1.1  fvdl 
    656  1.1  fvdl 	printf("%s: ahd_timeout\n", ahd_name(ahd));
    657  1.1  fvdl 
    658  1.1  fvdl 	ahd_lock(ahd, &s);
    659  1.1  fvdl 
    660  1.1  fvdl 	ahd_pause_and_flushwork(ahd);
    661  1.1  fvdl 	saved_modes = ahd_save_modes(ahd);
    662  1.1  fvdl #if 0
    663  1.1  fvdl 	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
    664  1.1  fvdl 	ahd_outb(ahd, SCSISIGO, ACKO);
    665  1.1  fvdl 	printf("set ACK\n");
    666  1.1  fvdl 	ahd_outb(ahd, SCSISIGO, 0);
    667  1.1  fvdl 	printf("clearing Ack\n");
    668  1.1  fvdl 	ahd_restore_modes(ahd, saved_modes);
    669  1.1  fvdl #endif
    670  1.1  fvdl 	if ((scb->flags & SCB_ACTIVE) == 0) {
    671  1.1  fvdl 		/* Previous timeout took care of me already */
    672  1.1  fvdl 		printf("%s: Timedout SCB already complete. "
    673  1.1  fvdl 		       "Interrupts may not be functioning.\n", ahd_name(ahd));
    674  1.1  fvdl 		ahd_unpause(ahd);
    675  1.1  fvdl 		ahd_unlock(ahd, &s);
    676  1.1  fvdl 		return;
    677  1.1  fvdl 	}
    678  1.1  fvdl 
    679  1.1  fvdl 	target = SCB_GET_TARGET(ahd, scb);
    680  1.1  fvdl 	channel = SCB_GET_CHANNEL(ahd, scb);
    681  1.1  fvdl 	lun = SCB_GET_LUN(scb);
    682  1.1  fvdl 
    683  1.1  fvdl 	ahd_print_path(ahd, scb);
    684  1.1  fvdl 	printf("SCB 0x%x - timed out\n", SCB_GET_TAG(scb));
    685  1.1  fvdl 	ahd_dump_card_state(ahd);
    686  1.1  fvdl 	ahd_reset_channel(ahd, SIM_CHANNEL(ahd, sim),
    687  1.1  fvdl 			  /*initiate reset*/TRUE);
    688  1.1  fvdl 	ahd_unlock(ahd, &s);
    689  1.1  fvdl 	return;
    690  1.1  fvdl }
    691  1.1  fvdl 
    692  1.1  fvdl int
    693  1.1  fvdl ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg)
    694  1.1  fvdl {
    695  1.1  fvdl 	ahd->platform_data = malloc(sizeof(struct ahd_platform_data), M_DEVBUF,
    696  1.1  fvdl 				    M_NOWAIT /*| M_ZERO*/);
    697  1.1  fvdl 	if (ahd->platform_data == NULL)
    698  1.1  fvdl 		return (ENOMEM);
    699  1.1  fvdl 
    700  1.1  fvdl 	memset(ahd->platform_data, 0, sizeof(struct ahd_platform_data));
    701  1.1  fvdl 
    702  1.1  fvdl 	return (0);
    703  1.1  fvdl }
    704  1.1  fvdl 
    705  1.1  fvdl void
    706  1.1  fvdl ahd_platform_free(struct ahd_softc *ahd)
    707  1.1  fvdl {
    708  1.1  fvdl 	free(ahd->platform_data, M_DEVBUF);
    709  1.1  fvdl }
    710  1.1  fvdl 
    711  1.1  fvdl int
    712  1.1  fvdl ahd_softc_comp(struct ahd_softc *lahd, struct ahd_softc *rahd)
    713  1.1  fvdl {
    714  1.1  fvdl 	/* We don't sort softcs under NetBSD so report equal always */
    715  1.1  fvdl 	return (0);
    716  1.1  fvdl }
    717  1.1  fvdl 
    718  1.1  fvdl int
    719  1.1  fvdl ahd_detach(struct device *self, int flags)
    720  1.1  fvdl {
    721  1.1  fvdl 	int rv = 0;
    722  1.1  fvdl 
    723  1.1  fvdl 	struct ahd_softc *ahd = (struct ahd_softc*)self;
    724  1.1  fvdl 
    725  1.1  fvdl 	if (ahd->sc_child != NULL)
    726  1.1  fvdl 		rv = config_detach((void *)ahd->sc_child, flags);
    727  1.1  fvdl 
    728  1.1  fvdl 	shutdownhook_disestablish(ahd->shutdown_hook);
    729  1.1  fvdl 
    730  1.1  fvdl 	ahd_free(ahd);
    731  1.1  fvdl 
    732  1.1  fvdl 	return rv;
    733  1.1  fvdl }
    734  1.1  fvdl 
    735  1.1  fvdl void
    736  1.1  fvdl ahd_platform_set_tags(struct ahd_softc *ahd,
    737  1.1  fvdl 		      struct ahd_devinfo *devinfo, ahd_queue_alg alg)
    738  1.1  fvdl {
    739  1.1  fvdl 	struct ahd_initiator_tinfo *tinfo;
    740  1.1  fvdl         struct ahd_tmode_tstate *tstate;
    741  1.1  fvdl 
    742  1.1  fvdl         tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid,
    743  1.1  fvdl                                     devinfo->target, &tstate);
    744  1.1  fvdl 
    745  1.1  fvdl         if (alg != AHD_QUEUE_NONE)
    746  1.1  fvdl                 tstate->tagenable |= devinfo->target_mask;
    747  1.1  fvdl 	else
    748  1.1  fvdl 	  	tstate->tagenable &= ~devinfo->target_mask;
    749  1.1  fvdl }
    750  1.1  fvdl 
    751  1.1  fvdl void
    752  1.1  fvdl ahd_send_async(struct ahd_softc *ahc, char channel, u_int target, u_int lun,
    753  1.1  fvdl 	       ac_code code, void *opt_arg)
    754  1.1  fvdl {
    755  1.1  fvdl 	struct ahd_tmode_tstate *tstate;
    756  1.1  fvdl 	struct ahd_initiator_tinfo *tinfo;
    757  1.1  fvdl 	struct ahd_devinfo devinfo;
    758  1.1  fvdl 	struct scsipi_channel *chan;
    759  1.1  fvdl 	struct scsipi_xfer_mode xm;
    760  1.1  fvdl 
    761  1.1  fvdl #ifdef DIAGNOSTIC
    762  1.1  fvdl 	if (channel != 'A')
    763  1.1  fvdl 		panic("ahd_send_async: not channel A");
    764  1.1  fvdl #endif
    765  1.1  fvdl 	chan = &ahc->sc_channel;
    766  1.1  fvdl 	switch (code) {
    767  1.1  fvdl 	case AC_TRANSFER_NEG:
    768  1.1  fvdl 		tinfo = ahd_fetch_transinfo(ahc, channel, ahc->our_id, target,
    769  1.1  fvdl 			    &tstate);
    770  1.1  fvdl 		ahd_compile_devinfo(&devinfo, ahc->our_id, target, lun,
    771  1.1  fvdl 		    channel, ROLE_UNKNOWN);
    772  1.1  fvdl 		/*
    773  1.1  fvdl 		 * Don't bother if negotiating. XXX?
    774  1.1  fvdl 		 */
    775  1.1  fvdl 		if (tinfo->curr.period != tinfo->goal.period
    776  1.1  fvdl 		    || tinfo->curr.width != tinfo->goal.width
    777  1.1  fvdl 		    || tinfo->curr.offset != tinfo->goal.offset
    778  1.1  fvdl 		    || tinfo->curr.ppr_options != tinfo->goal.ppr_options)
    779  1.1  fvdl 			break;
    780  1.1  fvdl 		xm.xm_target = target;
    781  1.1  fvdl 		xm.xm_mode = 0;
    782  1.1  fvdl 		xm.xm_period = tinfo->curr.period;
    783  1.1  fvdl 		xm.xm_offset = tinfo->curr.offset;
    784  1.1  fvdl 		if (tinfo->goal.ppr_options & MSG_EXT_PPR_DT_REQ)
    785  1.1  fvdl 			xm.xm_mode |= PERIPH_CAP_DT;
    786  1.1  fvdl 		if (tinfo->curr.width == MSG_EXT_WDTR_BUS_16_BIT)
    787  1.1  fvdl 			xm.xm_mode |= PERIPH_CAP_WIDE16;
    788  1.1  fvdl 		if (tinfo->curr.period)
    789  1.1  fvdl 			xm.xm_mode |= PERIPH_CAP_SYNC;
    790  1.1  fvdl 		if (tstate->tagenable & devinfo.target_mask)
    791  1.1  fvdl 			xm.xm_mode |= PERIPH_CAP_TQING;
    792  1.1  fvdl 		scsipi_async_event(chan, ASYNC_EVENT_XFER_MODE, &xm);
    793  1.1  fvdl 		break;
    794  1.1  fvdl 	case AC_BUS_RESET:
    795  1.1  fvdl 		scsipi_async_event(chan, ASYNC_EVENT_RESET, NULL);
    796  1.1  fvdl 	case AC_SENT_BDR:
    797  1.1  fvdl 	default:
    798  1.1  fvdl 		break;
    799  1.1  fvdl 	}
    800  1.1  fvdl }
    801