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