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