Home | History | Annotate | Line # | Download | only in ic
dpt.c revision 1.51
      1  1.51  christos /*	$NetBSD: dpt.c,v 1.51 2006/10/04 15:41:25 christos Exp $	*/
      2   1.1        ad 
      3   1.1        ad /*-
      4  1.29    bouyer  * Copyright (c) 1997, 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc.
      5   1.1        ad  * All rights reserved.
      6   1.1        ad  *
      7   1.1        ad  * This code is derived from software contributed to The NetBSD Foundation
      8  1.22        ad  * by Andrew Doran, Charles M. Hannum and by Jason R. Thorpe of the Numerical
      9   1.1        ad  * Aerospace Simulation Facility, NASA Ames Research Center.
     10   1.1        ad  *
     11   1.1        ad  * Redistribution and use in source and binary forms, with or without
     12   1.1        ad  * modification, are permitted provided that the following conditions
     13   1.1        ad  * are met:
     14   1.1        ad  * 1. Redistributions of source code must retain the above copyright
     15   1.1        ad  *    notice, this list of conditions and the following disclaimer.
     16   1.1        ad  * 2. Redistributions in binary form must reproduce the above copyright
     17   1.1        ad  *    notice, this list of conditions and the following disclaimer in the
     18   1.1        ad  *    documentation and/or other materials provided with the distribution.
     19   1.1        ad  * 3. All advertising materials mentioning features or use of this software
     20   1.1        ad  *    must display the following acknowledgement:
     21   1.1        ad  *	This product includes software developed by the NetBSD
     22   1.1        ad  *	Foundation, Inc. and its contributors.
     23   1.1        ad  * 4. Neither the name of The NetBSD Foundation nor the names of its
     24   1.1        ad  *    contributors may be used to endorse or promote products derived
     25   1.1        ad  *    from this software without specific prior written permission.
     26   1.1        ad  *
     27   1.1        ad  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     28   1.1        ad  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     29   1.1        ad  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     30   1.1        ad  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     31   1.1        ad  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     32   1.1        ad  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     33   1.1        ad  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     34   1.1        ad  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     35   1.1        ad  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     36   1.1        ad  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     37   1.1        ad  * POSSIBILITY OF SUCH DAMAGE.
     38   1.1        ad  */
     39   1.1        ad 
     40   1.1        ad /*
     41  1.33        ad  * Copyright (c) 1996-2000 Distributed Processing Technology Corporation
     42  1.33        ad  * Copyright (c) 2000 Adaptec Corporation
     43  1.33        ad  * All rights reserved.
     44  1.33        ad  *
     45  1.33        ad  * TERMS AND CONDITIONS OF USE
     46  1.33        ad  *
     47  1.33        ad  * Redistribution and use in source form, with or without modification, are
     48  1.33        ad  * permitted provided that redistributions of source code must retain the
     49  1.33        ad  * above copyright notice, this list of conditions and the following disclaimer.
     50  1.33        ad  *
     51  1.33        ad  * This software is provided `as is' by Adaptec and any express or implied
     52  1.33        ad  * warranties, including, but not limited to, the implied warranties of
     53  1.33        ad  * merchantability and fitness for a particular purpose, are disclaimed. In no
     54  1.33        ad  * event shall Adaptec be liable for any direct, indirect, incidental, special,
     55  1.33        ad  * exemplary or consequential damages (including, but not limited to,
     56  1.33        ad  * procurement of substitute goods or services; loss of use, data, or profits;
     57  1.33        ad  * or business interruptions) however caused and on any theory of liability,
     58  1.33        ad  * whether in contract, strict liability, or tort (including negligence or
     59  1.33        ad  * otherwise) arising in any way out of the use of this driver software, even
     60  1.33        ad  * if advised of the possibility of such damage.
     61  1.33        ad  */
     62  1.33        ad 
     63  1.33        ad /*
     64   1.1        ad  * Portions of this code fall under the following copyright:
     65   1.1        ad  *
     66   1.1        ad  * Originally written by Julian Elischer (julian (at) tfs.com)
     67   1.1        ad  * for TRW Financial Systems for use under the MACH(2.5) operating system.
     68   1.1        ad  *
     69   1.1        ad  * TRW Financial Systems, in accordance with their agreement with Carnegie
     70   1.1        ad  * Mellon University, makes this software available to CMU to distribute
     71   1.1        ad  * or use in any manner that they see fit as long as this message is kept with
     72   1.1        ad  * the software. For this reason TFS also grants any other persons or
     73   1.1        ad  * organisations permission to use or modify this software.
     74   1.1        ad  *
     75   1.1        ad  * TFS supplies this software to be publicly redistributed
     76   1.1        ad  * on the understanding that TFS is not responsible for the correct
     77   1.1        ad  * functioning of this software in any circumstances.
     78   1.1        ad  */
     79  1.31     lukem 
     80  1.31     lukem #include <sys/cdefs.h>
     81  1.51  christos __KERNEL_RCSID(0, "$NetBSD: dpt.c,v 1.51 2006/10/04 15:41:25 christos Exp $");
     82   1.1        ad 
     83   1.1        ad #include <sys/param.h>
     84   1.1        ad #include <sys/systm.h>
     85   1.1        ad #include <sys/device.h>
     86   1.1        ad #include <sys/queue.h>
     87   1.1        ad #include <sys/buf.h>
     88  1.13        ad #include <sys/endian.h>
     89  1.33        ad #include <sys/conf.h>
     90   1.1        ad 
     91  1.24   thorpej #include <uvm/uvm_extern.h>
     92  1.24   thorpej 
     93   1.1        ad #include <machine/bus.h>
     94  1.33        ad #ifdef i386
     95  1.33        ad #include <machine/pio.h>
     96  1.33        ad #endif
     97   1.1        ad 
     98   1.1        ad #include <dev/scsipi/scsi_all.h>
     99   1.1        ad #include <dev/scsipi/scsipi_all.h>
    100   1.1        ad #include <dev/scsipi/scsiconf.h>
    101   1.1        ad 
    102   1.1        ad #include <dev/ic/dptreg.h>
    103   1.1        ad #include <dev/ic/dptvar.h>
    104   1.1        ad 
    105  1.33        ad #include <dev/i2o/dptivar.h>
    106  1.33        ad 
    107  1.33        ad #ifdef DEBUG
    108  1.33        ad #define	DPRINTF(x)		printf x
    109  1.33        ad #else
    110  1.33        ad #define	DPRINTF(x)
    111  1.33        ad #endif
    112  1.33        ad 
    113  1.29    bouyer #define dpt_inb(x, o)		\
    114  1.29    bouyer     bus_space_read_1((x)->sc_iot, (x)->sc_ioh, (o))
    115  1.29    bouyer #define dpt_outb(x, o, d)	\
    116  1.29    bouyer     bus_space_write_1((x)->sc_iot, (x)->sc_ioh, (o), (d))
    117  1.29    bouyer 
    118  1.29    bouyer static const char * const dpt_cname[] = {
    119  1.29    bouyer 	"3334", "SmartRAID IV",
    120  1.29    bouyer 	"3332", "SmartRAID IV",
    121  1.29    bouyer 	"2144", "SmartCache IV",
    122  1.29    bouyer 	"2044", "SmartCache IV",
    123  1.29    bouyer 	"2142", "SmartCache IV",
    124  1.29    bouyer 	"2042", "SmartCache IV",
    125  1.29    bouyer 	"2041", "SmartCache IV",
    126  1.29    bouyer 	"3224", "SmartRAID III",
    127  1.44     perry 	"3222", "SmartRAID III",
    128  1.29    bouyer 	"3021", "SmartRAID III",
    129  1.29    bouyer 	"2124", "SmartCache III",
    130  1.29    bouyer 	"2024", "SmartCache III",
    131  1.29    bouyer 	"2122", "SmartCache III",
    132  1.29    bouyer 	"2022", "SmartCache III",
    133  1.29    bouyer 	"2021", "SmartCache III",
    134  1.44     perry 	"2012", "SmartCache Plus",
    135  1.29    bouyer 	"2011", "SmartCache Plus",
    136  1.29    bouyer 	NULL,   "<unknown>",
    137   1.1        ad };
    138   1.1        ad 
    139  1.29    bouyer static void	*dpt_sdh;
    140  1.29    bouyer 
    141  1.33        ad dev_type_open(dptopen);
    142  1.33        ad dev_type_ioctl(dptioctl);
    143  1.33        ad 
    144  1.33        ad const struct cdevsw dpt_cdevsw = {
    145  1.33        ad 	dptopen, nullclose, noread, nowrite, dptioctl,
    146  1.50  christos 	nostop, notty, nopoll, nommap, nokqfilter, D_OTHER,
    147  1.33        ad };
    148  1.33        ad 
    149  1.33        ad extern struct cfdriver dpt_cd;
    150  1.33        ad 
    151  1.33        ad static struct dpt_sig dpt_sig = {
    152  1.33        ad 	{ 'd', 'P', 't', 'S', 'i', 'G'},
    153  1.33        ad 	SIG_VERSION,
    154  1.33        ad #if defined(i386)
    155  1.33        ad 	PROC_INTEL,
    156  1.33        ad #elif defined(powerpc)
    157  1.33        ad 	PROC_POWERPC,
    158  1.33        ad #elif defined(alpha)
    159  1.33        ad 	PROC_ALPHA,
    160  1.33        ad #elif defined(__mips__)
    161  1.33        ad 	PROC_MIPS,
    162  1.33        ad #elif defined(sparc64)
    163  1.33        ad 	PROC_ULTRASPARC,
    164  1.35      fvdl #else
    165  1.35      fvdl 	0xff,
    166  1.33        ad #endif
    167  1.33        ad #if defined(i386)
    168  1.33        ad 	PROC_386 | PROC_486 | PROC_PENTIUM | PROC_SEXIUM,
    169  1.33        ad #else
    170  1.33        ad 	0,
    171  1.33        ad #endif
    172  1.33        ad 	FT_HBADRVR,
    173  1.33        ad 	0,
    174  1.33        ad 	OEM_DPT,
    175  1.33        ad 	OS_FREE_BSD,	/* XXX */
    176  1.33        ad 	CAP_ABOVE16MB,
    177  1.33        ad 	DEV_ALL,
    178  1.33        ad 	ADF_ALL_EATA,
    179  1.33        ad 	0,
    180  1.33        ad 	0,
    181  1.33        ad 	DPT_VERSION,
    182  1.33        ad 	DPT_REVISION,
    183  1.33        ad 	DPT_SUBREVISION,
    184  1.33        ad 	DPT_MONTH,
    185  1.33        ad 	DPT_DAY,
    186  1.33        ad 	DPT_YEAR,
    187  1.33        ad 	""		/* Will be filled later */
    188  1.33        ad };
    189  1.33        ad 
    190  1.29    bouyer static void	dpt_ccb_abort(struct dpt_softc *, struct dpt_ccb *);
    191  1.29    bouyer static void	dpt_ccb_done(struct dpt_softc *, struct dpt_ccb *);
    192  1.29    bouyer static int	dpt_ccb_map(struct dpt_softc *, struct dpt_ccb *);
    193  1.29    bouyer static int	dpt_ccb_poll(struct dpt_softc *, struct dpt_ccb *);
    194  1.29    bouyer static void	dpt_ccb_unmap(struct dpt_softc *, struct dpt_ccb *);
    195  1.29    bouyer static int	dpt_cmd(struct dpt_softc *, struct dpt_ccb *, int, int);
    196  1.33        ad static void	dpt_ctlrinfo(struct dpt_softc *, struct dpt_eata_ctlrinfo *);
    197  1.29    bouyer static void	dpt_hba_inquire(struct dpt_softc *, struct eata_inquiry_data **);
    198  1.29    bouyer static void	dpt_minphys(struct buf *);
    199  1.34        ad static int	dpt_passthrough(struct dpt_softc *, struct eata_ucp *,
    200  1.45  christos 				struct lwp *);
    201  1.29    bouyer static void	dpt_scsipi_request(struct scsipi_channel *,
    202  1.29    bouyer 				   scsipi_adapter_req_t, void *);
    203  1.29    bouyer static void	dpt_shutdown(void *);
    204  1.33        ad static void	dpt_sysinfo(struct dpt_softc *, struct dpt_sysinfo *);
    205  1.29    bouyer static int	dpt_wait(struct dpt_softc *, u_int8_t, u_int8_t, int);
    206  1.29    bouyer 
    207  1.46     perry static inline struct dpt_ccb	*dpt_ccb_alloc(struct dpt_softc *);
    208  1.46     perry static inline void	dpt_ccb_free(struct dpt_softc *, struct dpt_ccb *);
    209  1.29    bouyer 
    210  1.46     perry static inline struct dpt_ccb *
    211  1.29    bouyer dpt_ccb_alloc(struct dpt_softc *sc)
    212  1.29    bouyer {
    213  1.29    bouyer 	struct dpt_ccb *ccb;
    214  1.29    bouyer 	int s;
    215  1.29    bouyer 
    216  1.29    bouyer 	s = splbio();
    217  1.29    bouyer 	ccb = SLIST_FIRST(&sc->sc_ccb_free);
    218  1.29    bouyer 	SLIST_REMOVE_HEAD(&sc->sc_ccb_free, ccb_chain);
    219  1.29    bouyer 	splx(s);
    220  1.29    bouyer 
    221  1.29    bouyer 	return (ccb);
    222  1.29    bouyer }
    223  1.29    bouyer 
    224  1.46     perry static inline void
    225  1.29    bouyer dpt_ccb_free(struct dpt_softc *sc, struct dpt_ccb *ccb)
    226  1.29    bouyer {
    227  1.29    bouyer 	int s;
    228   1.1        ad 
    229  1.29    bouyer 	ccb->ccb_flg = 0;
    230  1.33        ad 	ccb->ccb_savesp = NULL;
    231  1.29    bouyer 	s = splbio();
    232  1.29    bouyer 	SLIST_INSERT_HEAD(&sc->sc_ccb_free, ccb, ccb_chain);
    233  1.29    bouyer 	splx(s);
    234  1.29    bouyer }
    235  1.19        ad 
    236   1.1        ad /*
    237   1.1        ad  * Handle an interrupt from the HBA.
    238   1.1        ad  */
    239   1.1        ad int
    240  1.29    bouyer dpt_intr(void *cookie)
    241   1.1        ad {
    242   1.1        ad 	struct dpt_softc *sc;
    243   1.1        ad 	struct dpt_ccb *ccb;
    244   1.1        ad 	struct eata_sp *sp;
    245  1.19        ad 	volatile int junk;
    246  1.29    bouyer 	int forus;
    247   1.1        ad 
    248  1.29    bouyer 	sc = cookie;
    249  1.19        ad 	sp = sc->sc_stp;
    250  1.29    bouyer 	forus = 0;
    251  1.19        ad 
    252   1.7        ad 	for (;;) {
    253   1.7        ad 		/*
    254   1.7        ad 		 * HBA might have interrupted while we were dealing with the
    255  1.44     perry 		 * last completed command, since we ACK before we deal; keep
    256  1.19        ad 		 * polling.
    257  1.29    bouyer 		 */
    258  1.19        ad 		if ((dpt_inb(sc, HA_AUX_STATUS) & HA_AUX_INTR) == 0)
    259   1.7        ad 			break;
    260  1.29    bouyer 		forus = 1;
    261  1.29    bouyer 
    262  1.19        ad 		bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, sc->sc_stpoff,
    263   1.1        ad 		    sizeof(struct eata_sp), BUS_DMASYNC_POSTREAD);
    264   1.1        ad 
    265  1.29    bouyer 		/* Might have looped before HBA can reset HBA_AUX_INTR. */
    266   1.1        ad 		if (sp->sp_ccbid == -1) {
    267   1.1        ad 			DELAY(50);
    268  1.19        ad 
    269   1.1        ad 			if ((dpt_inb(sc, HA_AUX_STATUS) & HA_AUX_INTR) == 0)
    270   1.1        ad 				return (0);
    271  1.19        ad 
    272  1.19        ad 			printf("%s: no status\n", sc->sc_dv.dv_xname);
    273  1.19        ad 
    274   1.1        ad 			/* Re-sync DMA map */
    275  1.29    bouyer 			bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap,
    276  1.19        ad 			    sc->sc_stpoff, sizeof(struct eata_sp),
    277   1.1        ad 			    BUS_DMASYNC_POSTREAD);
    278   1.1        ad 		}
    279   1.1        ad 
    280  1.29    bouyer 		/* Make sure CCB ID from status packet is realistic. */
    281  1.29    bouyer 		if ((u_int)sp->sp_ccbid >= sc->sc_nccbs) {
    282  1.44     perry 			printf("%s: bogus status (returned CCB id %d)\n",
    283   1.1        ad 			    sc->sc_dv.dv_xname, sp->sp_ccbid);
    284   1.1        ad 
    285   1.1        ad 			/* Ack the interrupt */
    286  1.20        ad 			sp->sp_ccbid = -1;
    287  1.19        ad 			junk = dpt_inb(sc, HA_STATUS);
    288  1.29    bouyer 			continue;
    289   1.1        ad 		}
    290  1.29    bouyer 
    291  1.29    bouyer 		/* Sync up DMA map and cache cmd status. */
    292  1.29    bouyer 		ccb = sc->sc_ccbs + sp->sp_ccbid;
    293  1.29    bouyer 
    294  1.29    bouyer 		bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, CCB_OFF(sc, ccb),
    295  1.29    bouyer 		    sizeof(struct dpt_ccb), BUS_DMASYNC_POSTWRITE);
    296  1.29    bouyer 
    297  1.29    bouyer 		ccb->ccb_hba_status = sp->sp_hba_status & 0x7f;
    298  1.29    bouyer 		ccb->ccb_scsi_status = sp->sp_scsi_status;
    299  1.33        ad 		if (ccb->ccb_savesp != NULL)
    300  1.33        ad 			memcpy(ccb->ccb_savesp, sp, sizeof(*sp));
    301  1.29    bouyer 
    302  1.44     perry 		/*
    303  1.29    bouyer 		 * Ack the interrupt and process the CCB.  If this
    304  1.29    bouyer 		 * is a private CCB it's up to dpt_ccb_poll() to
    305  1.29    bouyer 		 * notice.
    306  1.29    bouyer 		 */
    307  1.29    bouyer 		sp->sp_ccbid = -1;
    308  1.29    bouyer 		ccb->ccb_flg |= CCB_INTR;
    309  1.29    bouyer 		junk = dpt_inb(sc, HA_STATUS);
    310  1.29    bouyer 		if ((ccb->ccb_flg & CCB_PRIVATE) == 0)
    311  1.29    bouyer 			dpt_ccb_done(sc, ccb);
    312  1.33        ad 		else if ((ccb->ccb_flg & CCB_WAIT) != 0)
    313  1.33        ad 			wakeup(ccb);
    314   1.1        ad 	}
    315   1.1        ad 
    316  1.29    bouyer 	return (forus);
    317   1.1        ad }
    318   1.1        ad 
    319   1.1        ad /*
    320  1.29    bouyer  * Initialize and attach the HBA.  This is the entry point from bus
    321   1.1        ad  * specific probe-and-attach code.
    322   1.1        ad  */
    323   1.1        ad void
    324  1.29    bouyer dpt_init(struct dpt_softc *sc, const char *intrstr)
    325   1.1        ad {
    326  1.29    bouyer 	struct scsipi_adapter *adapt;
    327  1.29    bouyer 	struct scsipi_channel *chan;
    328   1.1        ad 	struct eata_inquiry_data *ei;
    329  1.29    bouyer 	int i, j, rv, rseg, maxchannel, maxtarget, mapsize;
    330   1.1        ad 	bus_dma_segment_t seg;
    331   1.4        ad 	struct eata_cfg *ec;
    332  1.29    bouyer 	struct dpt_ccb *ccb;
    333  1.47  christos 	char model[__arraycount(ei->ei_model) + __arraycount(ei->ei_suffix) + 1];
    334  1.47  christos 	char vendor[__arraycount(ei->ei_vendor) + 1];
    335  1.29    bouyer 
    336   1.4        ad 	ec = &sc->sc_ec;
    337  1.43    itojun 	snprintf(dpt_sig.dsDescription, sizeof(dpt_sig.dsDescription),
    338  1.43    itojun 	    "NetBSD %s DPT driver", osrelease);
    339  1.33        ad 
    340  1.29    bouyer 	/*
    341  1.29    bouyer 	 * Allocate the CCB/status packet/scratch DMA map and load.
    342  1.29    bouyer 	 */
    343  1.44     perry 	sc->sc_nccbs =
    344  1.19        ad 	    min(be16toh(*(int16_t *)ec->ec_queuedepth), DPT_MAX_CCBS);
    345  1.19        ad 	sc->sc_stpoff = sc->sc_nccbs * sizeof(struct dpt_ccb);
    346  1.19        ad 	sc->sc_scroff = sc->sc_stpoff + sizeof(struct eata_sp);
    347  1.44     perry 	mapsize = sc->sc_nccbs * sizeof(struct dpt_ccb) +
    348  1.29    bouyer 	    DPT_SCRATCH_SIZE + sizeof(struct eata_sp);
    349  1.29    bouyer 
    350  1.29    bouyer 	if ((rv = bus_dmamem_alloc(sc->sc_dmat, mapsize,
    351  1.24   thorpej 	    PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) {
    352  1.39   thorpej 		aprint_error("%s: unable to allocate CCBs, rv = %d\n",
    353  1.29    bouyer 		    sc->sc_dv.dv_xname, rv);
    354   1.1        ad 		return;
    355   1.1        ad 	}
    356   1.1        ad 
    357  1.29    bouyer 	if ((rv = bus_dmamem_map(sc->sc_dmat, &seg, rseg, mapsize,
    358   1.1        ad 	    (caddr_t *)&sc->sc_ccbs, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
    359  1.39   thorpej 		aprint_error("%s: unable to map CCBs, rv = %d\n",
    360  1.29    bouyer 		    sc->sc_dv.dv_xname, rv);
    361   1.1        ad 		return;
    362   1.1        ad 	}
    363   1.1        ad 
    364  1.29    bouyer 	if ((rv = bus_dmamap_create(sc->sc_dmat, mapsize,
    365  1.29    bouyer 	    mapsize, 1, 0, BUS_DMA_NOWAIT, &sc->sc_dmamap)) != 0) {
    366  1.39   thorpej 		aprint_error("%s: unable to create CCB DMA map, rv = %d\n",
    367  1.29    bouyer 		    sc->sc_dv.dv_xname, rv);
    368   1.1        ad 		return;
    369   1.1        ad 	}
    370   1.1        ad 
    371  1.29    bouyer 	if ((rv = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap,
    372  1.29    bouyer 	    sc->sc_ccbs, mapsize, NULL, BUS_DMA_NOWAIT)) != 0) {
    373  1.39   thorpej 		aprint_error("%s: unable to load CCB DMA map, rv = %d\n",
    374  1.29    bouyer 		    sc->sc_dv.dv_xname, rv);
    375   1.1        ad 		return;
    376   1.1        ad 	}
    377   1.1        ad 
    378  1.19        ad 	sc->sc_stp = (struct eata_sp *)((caddr_t)sc->sc_ccbs + sc->sc_stpoff);
    379  1.19        ad 	sc->sc_stppa = sc->sc_dmamap->dm_segs[0].ds_addr + sc->sc_stpoff;
    380   1.1        ad 	sc->sc_scr = (caddr_t)sc->sc_ccbs + sc->sc_scroff;
    381  1.19        ad 	sc->sc_scrpa = sc->sc_dmamap->dm_segs[0].ds_addr + sc->sc_scroff;
    382  1.19        ad 	sc->sc_stp->sp_ccbid = -1;
    383   1.4        ad 
    384  1.29    bouyer 	/*
    385  1.29    bouyer 	 * Create the CCBs.
    386  1.29    bouyer 	 */
    387  1.29    bouyer 	SLIST_INIT(&sc->sc_ccb_free);
    388  1.29    bouyer 	memset(sc->sc_ccbs, 0, sizeof(struct dpt_ccb) * sc->sc_nccbs);
    389  1.29    bouyer 
    390  1.29    bouyer 	for (i = 0, ccb = sc->sc_ccbs; i < sc->sc_nccbs; i++, ccb++) {
    391  1.29    bouyer 		rv = bus_dmamap_create(sc->sc_dmat, DPT_MAX_XFER,
    392  1.29    bouyer 		    DPT_SG_SIZE, DPT_MAX_XFER, 0,
    393  1.29    bouyer 		    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
    394  1.29    bouyer 		    &ccb->ccb_dmamap_xfer);
    395  1.29    bouyer 		if (rv) {
    396  1.44     perry 			aprint_error("%s: can't create ccb dmamap (%d)\n",
    397  1.29    bouyer 			    sc->sc_dv.dv_xname, rv);
    398  1.29    bouyer 			break;
    399  1.29    bouyer 		}
    400  1.29    bouyer 
    401  1.29    bouyer 		ccb->ccb_id = i;
    402  1.29    bouyer 		ccb->ccb_ccbpa = sc->sc_dmamap->dm_segs[0].ds_addr +
    403  1.29    bouyer 		    CCB_OFF(sc, ccb);
    404  1.29    bouyer 		SLIST_INSERT_HEAD(&sc->sc_ccb_free, ccb, ccb_chain);
    405  1.29    bouyer 	}
    406   1.1        ad 
    407   1.1        ad 	if (i == 0) {
    408  1.39   thorpej 		aprint_error("%s: unable to create CCBs\n", sc->sc_dv.dv_xname);
    409   1.1        ad 		return;
    410   1.1        ad 	} else if (i != sc->sc_nccbs) {
    411  1.39   thorpej 		aprint_error("%s: %d/%d CCBs created!\n", sc->sc_dv.dv_xname,
    412  1.39   thorpej 		    i, sc->sc_nccbs);
    413   1.1        ad 		sc->sc_nccbs = i;
    414   1.1        ad 	}
    415   1.1        ad 
    416  1.29    bouyer 	/* Set shutdownhook before we start any device activity. */
    417  1.23        ad 	if (dpt_sdh == NULL)
    418  1.19        ad 		dpt_sdh = shutdownhook_establish(dpt_shutdown, NULL);
    419   1.1        ad 
    420  1.29    bouyer 	/* Get the inquiry data from the HBA. */
    421   1.1        ad 	dpt_hba_inquire(sc, &ei);
    422   1.1        ad 
    423  1.44     perry 	/*
    424   1.1        ad 	 * dpt0 at pci0 dev 12 function 0: DPT SmartRAID III (PM3224A/9X-R)
    425   1.1        ad 	 * dpt0: interrupting at irq 10
    426   1.1        ad 	 * dpt0: 64 queued commands, 1 channel(s), adapter on ID(s) 7
    427   1.1        ad 	 */
    428  1.47  christos 	for (i = 0; ei->ei_vendor[i] != ' ' && i < __arraycount(ei->ei_vendor);
    429  1.47  christos 	    i++)
    430  1.47  christos 		vendor[i] = ei->ei_vendor[i];
    431  1.47  christos 	vendor[i] = '\0';
    432   1.1        ad 
    433  1.47  christos 	for (i = 0; ei->ei_model[i] != ' ' && i < __arraycount(ei->ei_model);
    434  1.47  christos 	    i++)
    435  1.25       cgd 		model[i] = ei->ei_model[i];
    436  1.47  christos 	for (j = 0; ei->ei_suffix[j] != ' ' && j < __arraycount(ei->ei_suffix);
    437  1.47  christos 	    i++, j++)
    438  1.47  christos 		model[i] = ei->ei_suffix[j];
    439   1.1        ad 	model[i] = '\0';
    440   1.1        ad 
    441  1.29    bouyer 	/* Find the marketing name for the board. */
    442   1.9        ad 	for (i = 0; dpt_cname[i] != NULL; i += 2)
    443  1.29    bouyer 		if (memcmp(ei->ei_model + 2, dpt_cname[i], 4) == 0)
    444   1.1        ad 			break;
    445  1.29    bouyer 
    446  1.47  christos 	aprint_normal("%s %s (%s)\n", vendor, dpt_cname[i + 1], model);
    447   1.1        ad 
    448   1.1        ad 	if (intrstr != NULL)
    449  1.39   thorpej 		aprint_normal("%s: interrupting at %s\n", sc->sc_dv.dv_xname,
    450  1.29    bouyer 		    intrstr);
    451   1.1        ad 
    452  1.19        ad 	maxchannel = (ec->ec_feat3 & EC_F3_MAX_CHANNEL_MASK) >>
    453  1.19        ad 	    EC_F3_MAX_CHANNEL_SHIFT;
    454  1.19        ad 	maxtarget = (ec->ec_feat3 & EC_F3_MAX_TARGET_MASK) >>
    455  1.19        ad 	    EC_F3_MAX_TARGET_SHIFT;
    456  1.19        ad 
    457  1.39   thorpej 	aprint_normal("%s: %d queued commands, %d channel(s), adapter on ID(s)",
    458  1.19        ad 	    sc->sc_dv.dv_xname, sc->sc_nccbs, maxchannel + 1);
    459   1.1        ad 
    460  1.19        ad 	for (i = 0; i <= maxchannel; i++) {
    461  1.19        ad 		sc->sc_hbaid[i] = ec->ec_hba[3 - i];
    462  1.39   thorpej 		aprint_normal(" %d", sc->sc_hbaid[i]);
    463  1.19        ad 	}
    464  1.39   thorpej 	aprint_normal("\n");
    465   1.1        ad 
    466  1.29    bouyer 	/*
    467  1.29    bouyer 	 * Reset the SCSI controller chip(s) and bus.  XXX Do we need to do
    468  1.29    bouyer 	 * this for each bus?
    469  1.29    bouyer 	 */
    470  1.29    bouyer 	if (dpt_cmd(sc, NULL, CP_IMMEDIATE, CPI_BUS_RESET))
    471   1.4        ad 		panic("%s: dpt_cmd failed", sc->sc_dv.dv_xname);
    472  1.29    bouyer 
    473  1.29    bouyer 	/* Fill in the scsipi_adapter. */
    474  1.29    bouyer 	adapt = &sc->sc_adapt;
    475  1.29    bouyer 	memset(adapt, 0, sizeof(*adapt));
    476  1.29    bouyer 	adapt->adapt_dev = &sc->sc_dv;
    477  1.29    bouyer 	adapt->adapt_nchannels = maxchannel + 1;
    478  1.33        ad 	adapt->adapt_openings = sc->sc_nccbs - 1;
    479  1.33        ad 	adapt->adapt_max_periph = sc->sc_nccbs - 1;
    480  1.29    bouyer 	adapt->adapt_request = dpt_scsipi_request;
    481  1.29    bouyer 	adapt->adapt_minphys = dpt_minphys;
    482   1.1        ad 
    483  1.19        ad 	for (i = 0; i <= maxchannel; i++) {
    484  1.29    bouyer 		/* Fill in the scsipi_channel. */
    485  1.29    bouyer 		chan = &sc->sc_chans[i];
    486  1.29    bouyer 		memset(chan, 0, sizeof(*chan));
    487  1.29    bouyer 		chan->chan_adapter = adapt;
    488  1.29    bouyer 		chan->chan_bustype = &scsi_bustype;
    489  1.29    bouyer 		chan->chan_channel = i;
    490  1.29    bouyer 		chan->chan_ntargets = maxtarget + 1;
    491  1.29    bouyer 		chan->chan_nluns = ec->ec_maxlun + 1;
    492  1.29    bouyer 		chan->chan_id = sc->sc_hbaid[i];
    493  1.29    bouyer 		config_found(&sc->sc_dv, chan, scsiprint);
    494  1.23        ad 	}
    495   1.1        ad }
    496   1.1        ad 
    497   1.1        ad /*
    498   1.1        ad  * Read the EATA configuration from the HBA and perform some sanity checks.
    499   1.1        ad  */
    500   1.1        ad int
    501  1.29    bouyer dpt_readcfg(struct dpt_softc *sc)
    502   1.1        ad {
    503   1.4        ad 	struct eata_cfg *ec;
    504   1.1        ad 	int i, j, stat;
    505   1.1        ad 	u_int16_t *p;
    506   1.1        ad 
    507   1.4        ad 	ec = &sc->sc_ec;
    508   1.4        ad 
    509  1.29    bouyer 	/* Older firmware may puke if we talk to it too soon after reset. */
    510   1.4        ad 	dpt_outb(sc, HA_COMMAND, CP_RESET);
    511  1.19        ad 	DELAY(750000);
    512   1.4        ad 
    513   1.4        ad 	for (i = 1000; i; i--) {
    514   1.4        ad 		if ((dpt_inb(sc, HA_STATUS) & HA_ST_READY) != 0)
    515   1.4        ad 			break;
    516   1.4        ad 		DELAY(2000);
    517   1.4        ad 	}
    518  1.29    bouyer 
    519   1.4        ad 	if (i == 0) {
    520  1.17        ad 		printf("%s: HBA not ready after reset (hba status:%02x)\n",
    521   1.4        ad 		    sc->sc_dv.dv_xname, dpt_inb(sc, HA_STATUS));
    522   1.4        ad 		return (-1);
    523   1.4        ad 	}
    524   1.4        ad 
    525   1.1        ad 	while((((stat = dpt_inb(sc, HA_STATUS))
    526  1.19        ad 	    != (HA_ST_READY|HA_ST_SEEK_COMPLETE))
    527  1.19        ad 	    && (stat != (HA_ST_READY|HA_ST_SEEK_COMPLETE|HA_ST_ERROR))
    528  1.19        ad 	    && (stat != (HA_ST_READY|HA_ST_SEEK_COMPLETE|HA_ST_ERROR|HA_ST_DRQ)))
    529  1.29    bouyer 	    || (dpt_wait(sc, HA_ST_BUSY, 0, 2000))) {
    530  1.19        ad 		/* RAID drives still spinning up? */
    531  1.29    bouyer 		if(dpt_inb(sc, HA_ERROR) != 'D' ||
    532  1.29    bouyer 		   dpt_inb(sc, HA_ERROR + 1) != 'P' ||
    533  1.29    bouyer 		   dpt_inb(sc, HA_ERROR + 2) != 'T') {
    534  1.29    bouyer 			printf("%s: HBA not ready\n", sc->sc_dv.dv_xname);
    535  1.19        ad 			return (-1);
    536   1.2        ad 		}
    537  1.19        ad 	}
    538   1.1        ad 
    539  1.44     perry 	/*
    540  1.44     perry 	 * Issue the read-config command and wait for the data to appear.
    541  1.29    bouyer 	 *
    542  1.29    bouyer 	 * Apparently certian firmware revisions won't DMA later on if we
    543  1.29    bouyer 	 * request the config data using PIO, but it makes it a lot easier
    544  1.29    bouyer 	 * as no DMA setup is required.
    545   1.1        ad 	 */
    546   1.1        ad 	dpt_outb(sc, HA_COMMAND, CP_PIO_GETCFG);
    547   1.4        ad 	memset(ec, 0, sizeof(*ec));
    548  1.44     perry 	i = ((int)&((struct eata_cfg *)0)->ec_cfglen +
    549   1.4        ad 	    sizeof(ec->ec_cfglen)) >> 1;
    550   1.4        ad 	p = (u_int16_t *)ec;
    551  1.44     perry 
    552   1.4        ad 	if (dpt_wait(sc, 0xFF, HA_ST_DATA_RDY, 2000)) {
    553  1.29    bouyer 		printf("%s: cfg data didn't appear (hba status:%02x)\n",
    554   1.9        ad 		    sc->sc_dv.dv_xname, dpt_inb(sc, HA_STATUS));
    555  1.29    bouyer 		return (-1);
    556  1.29    bouyer 	}
    557   1.1        ad 
    558  1.29    bouyer 	/* Begin reading. */
    559  1.29    bouyer 	while (i--)
    560  1.27    briggs 		*p++ = bus_space_read_stream_2(sc->sc_iot, sc->sc_ioh, HA_DATA);
    561   1.1        ad 
    562  1.19        ad 	if ((i = ec->ec_cfglen) > (sizeof(struct eata_cfg)
    563  1.19        ad 	    - (int)(&(((struct eata_cfg *)0L)->ec_cfglen))
    564  1.19        ad 	    - sizeof(ec->ec_cfglen)))
    565  1.19        ad 		i = sizeof(struct eata_cfg)
    566  1.19        ad 		  - (int)(&(((struct eata_cfg *)0L)->ec_cfglen))
    567  1.19        ad 		  - sizeof(ec->ec_cfglen);
    568  1.19        ad 
    569  1.44     perry 	j = i + (int)(&(((struct eata_cfg *)0L)->ec_cfglen)) +
    570  1.19        ad 	    sizeof(ec->ec_cfglen);
    571  1.19        ad 	i >>= 1;
    572   1.1        ad 
    573   1.1        ad 	while (i--)
    574  1.27    briggs 		*p++ = bus_space_read_stream_2(sc->sc_iot, sc->sc_ioh, HA_DATA);
    575  1.29    bouyer 
    576  1.19        ad 	/* Flush until we have read 512 bytes. */
    577  1.19        ad 	i = (512 - j + 1) >> 1;
    578   1.1        ad 	while (i--)
    579  1.48  christos 		(void)bus_space_read_stream_2(sc->sc_iot, sc->sc_ioh, HA_DATA);
    580  1.44     perry 
    581  1.29    bouyer 	/* Defaults for older firmware... */
    582   1.4        ad 	if (p <= (u_short *)&ec->ec_hba[DPT_MAX_CHANNELS - 1])
    583   1.4        ad 		ec->ec_hba[DPT_MAX_CHANNELS - 1] = 7;
    584   1.1        ad 
    585  1.19        ad 	if ((dpt_inb(sc, HA_STATUS) & HA_ST_ERROR) != 0) {
    586  1.19        ad 		printf("%s: HBA error\n", sc->sc_dv.dv_xname);
    587  1.19        ad 		return (-1);
    588  1.19        ad 	}
    589  1.29    bouyer 
    590  1.15        ad 	if (memcmp(ec->ec_eatasig, "EATA", 4) != 0) {
    591  1.29    bouyer 		printf("%s: EATA signature mismatch\n", sc->sc_dv.dv_xname);
    592   1.1        ad 		return (-1);
    593   1.1        ad 	}
    594  1.29    bouyer 
    595  1.19        ad 	if ((ec->ec_feat0 & EC_F0_HBA_VALID) == 0) {
    596  1.19        ad 		printf("%s: ec_hba field invalid\n", sc->sc_dv.dv_xname);
    597   1.1        ad 		return (-1);
    598   1.1        ad 	}
    599  1.29    bouyer 
    600  1.19        ad 	if ((ec->ec_feat0 & EC_F0_DMA_SUPPORTED) == 0) {
    601  1.29    bouyer 		printf("%s: DMA not supported\n", sc->sc_dv.dv_xname);
    602   1.1        ad 		return (-1);
    603   1.1        ad 	}
    604   1.1        ad 
    605   1.1        ad 	return (0);
    606   1.1        ad }
    607   1.1        ad 
    608   1.1        ad /*
    609  1.29    bouyer  * Our `shutdownhook' to cleanly shut down the HBA.  The HBA must flush all
    610  1.29    bouyer  * data from it's cache and mark array groups as clean.
    611  1.29    bouyer  *
    612  1.29    bouyer  * XXX This doesn't always work (i.e., the HBA may still be flushing after
    613  1.29    bouyer  * we tell root that it's safe to power off).
    614   1.1        ad  */
    615  1.29    bouyer static void
    616  1.29    bouyer dpt_shutdown(void *cookie)
    617   1.1        ad {
    618  1.29    bouyer 	extern struct cfdriver dpt_cd;
    619  1.29    bouyer 	struct dpt_softc *sc;
    620  1.29    bouyer 	int i;
    621  1.29    bouyer 
    622  1.29    bouyer 	printf("shutting down dpt devices...");
    623  1.29    bouyer 
    624  1.29    bouyer 	for (i = 0; i < dpt_cd.cd_ndevs; i++) {
    625  1.29    bouyer 		if ((sc = device_lookup(&dpt_cd, i)) == NULL)
    626  1.29    bouyer 			continue;
    627  1.29    bouyer 		dpt_cmd(sc, NULL, CP_IMMEDIATE, CPI_POWEROFF_WARN);
    628  1.29    bouyer 	}
    629   1.1        ad 
    630  1.29    bouyer 	delay(10000*1000);
    631  1.29    bouyer 	printf(" done\n");
    632   1.1        ad }
    633   1.1        ad 
    634   1.1        ad /*
    635  1.29    bouyer  * Send an EATA command to the HBA.
    636   1.1        ad  */
    637  1.29    bouyer static int
    638  1.29    bouyer dpt_cmd(struct dpt_softc *sc, struct dpt_ccb *ccb, int eatacmd, int icmd)
    639   1.1        ad {
    640  1.29    bouyer 	u_int32_t pa;
    641  1.29    bouyer 	int i, s;
    642   1.1        ad 
    643   1.1        ad 	s = splbio();
    644   1.1        ad 
    645  1.29    bouyer 	for (i = 20000; i != 0; i--) {
    646  1.29    bouyer 		if ((dpt_inb(sc, HA_AUX_STATUS) & HA_AUX_BUSY) == 0)
    647  1.29    bouyer 			break;
    648  1.29    bouyer 		DELAY(50);
    649  1.29    bouyer 	}
    650  1.29    bouyer 	if (i == 0) {
    651  1.29    bouyer 		splx(s);
    652  1.29    bouyer 		return (-1);
    653  1.29    bouyer 	}
    654  1.29    bouyer 
    655  1.29    bouyer 	pa = (ccb != NULL ? ccb->ccb_ccbpa : 0);
    656  1.29    bouyer 	dpt_outb(sc, HA_DMA_BASE + 0, (pa      ) & 0xff);
    657  1.29    bouyer 	dpt_outb(sc, HA_DMA_BASE + 1, (pa >>  8) & 0xff);
    658  1.29    bouyer 	dpt_outb(sc, HA_DMA_BASE + 2, (pa >> 16) & 0xff);
    659  1.29    bouyer 	dpt_outb(sc, HA_DMA_BASE + 3, (pa >> 24) & 0xff);
    660  1.29    bouyer 
    661  1.29    bouyer 	if (eatacmd == CP_IMMEDIATE)
    662  1.29    bouyer 		dpt_outb(sc, HA_ICMD, icmd);
    663   1.1        ad 
    664  1.29    bouyer 	dpt_outb(sc, HA_COMMAND, eatacmd);
    665   1.1        ad 
    666  1.29    bouyer 	splx(s);
    667   1.1        ad 	return (0);
    668   1.1        ad }
    669   1.1        ad 
    670   1.1        ad /*
    671  1.29    bouyer  * Wait for the HBA status register to reach a specific state.
    672   1.1        ad  */
    673  1.29    bouyer static int
    674  1.29    bouyer dpt_wait(struct dpt_softc *sc, u_int8_t mask, u_int8_t state, int ms)
    675   1.1        ad {
    676   1.1        ad 
    677  1.29    bouyer 	for (ms *= 10; ms != 0; ms--) {
    678  1.29    bouyer 		if ((dpt_inb(sc, HA_STATUS) & mask) == state)
    679  1.29    bouyer 			return (0);
    680  1.29    bouyer 		DELAY(100);
    681   1.1        ad 	}
    682   1.1        ad 
    683  1.29    bouyer 	return (-1);
    684   1.1        ad }
    685   1.1        ad 
    686   1.1        ad /*
    687  1.29    bouyer  * Spin waiting for a command to finish.  The timeout value from the CCB is
    688  1.29    bouyer  * used.  The CCB must be marked with CCB_PRIVATE, otherwise it'll will get
    689  1.29    bouyer  * recycled before we get a look at it.
    690   1.1        ad  */
    691  1.29    bouyer static int
    692  1.29    bouyer dpt_ccb_poll(struct dpt_softc *sc, struct dpt_ccb *ccb)
    693   1.1        ad {
    694  1.29    bouyer 	int i, s;
    695  1.29    bouyer 
    696  1.29    bouyer #ifdef DEBUG
    697  1.29    bouyer 	if ((ccb->ccb_flg & CCB_PRIVATE) == 0)
    698  1.32    provos 		panic("dpt_ccb_poll: called for non-CCB_PRIVATE request");
    699  1.29    bouyer #endif
    700   1.1        ad 
    701   1.1        ad 	s = splbio();
    702   1.1        ad 
    703  1.29    bouyer 	if ((ccb->ccb_flg & CCB_INTR) != 0) {
    704  1.29    bouyer 		splx(s);
    705  1.29    bouyer 		return (0);
    706  1.29    bouyer 	}
    707  1.29    bouyer 
    708  1.29    bouyer 	for (i = ccb->ccb_timeout * 20; i != 0; i--) {
    709  1.29    bouyer 		if ((dpt_inb(sc, HA_AUX_STATUS) & HA_AUX_INTR) != 0)
    710  1.29    bouyer 			dpt_intr(sc);
    711  1.29    bouyer 		if ((ccb->ccb_flg & CCB_INTR) != 0)
    712   1.1        ad 			break;
    713  1.29    bouyer 		DELAY(50);
    714   1.1        ad 	}
    715   1.1        ad 
    716   1.1        ad 	splx(s);
    717  1.29    bouyer 	return (i == 0);
    718   1.1        ad }
    719   1.1        ad 
    720   1.1        ad /*
    721  1.29    bouyer  * We have a command which has been processed by the HBA, so now we look to
    722  1.29    bouyer  * see how the operation went.  CCBs marked CCB_PRIVATE are not passed here
    723  1.29    bouyer  * by dpt_intr().
    724   1.1        ad  */
    725  1.29    bouyer static void
    726  1.29    bouyer dpt_ccb_done(struct dpt_softc *sc, struct dpt_ccb *ccb)
    727   1.1        ad {
    728   1.1        ad 	struct scsipi_xfer *xs;
    729  1.29    bouyer 
    730   1.1        ad 	xs = ccb->ccb_xs;
    731   1.1        ad 
    732  1.29    bouyer 	SC_DEBUG(xs->xs_periph, SCSIPI_DB2, ("dpt_ccb_done\n"));
    733   1.1        ad 
    734   1.1        ad 	/*
    735  1.44     perry 	 * If we were a data transfer, unload the map that described the
    736   1.1        ad 	 * data buffer.
    737   1.1        ad 	 */
    738  1.29    bouyer 	if (xs->datalen != 0)
    739  1.29    bouyer 		dpt_ccb_unmap(sc, ccb);
    740   1.1        ad 
    741   1.1        ad 	if (xs->error == XS_NOERROR) {
    742  1.19        ad 		if (ccb->ccb_hba_status != SP_HBA_NO_ERROR) {
    743   1.1        ad 			switch (ccb->ccb_hba_status) {
    744  1.19        ad 			case SP_HBA_ERROR_SEL_TO:
    745   1.1        ad 				xs->error = XS_SELTIMEOUT;
    746   1.1        ad 				break;
    747  1.19        ad 			case SP_HBA_ERROR_RESET:
    748   1.1        ad 				xs->error = XS_RESET;
    749   1.1        ad 				break;
    750  1.29    bouyer 			default:
    751   1.1        ad 				printf("%s: HBA status %x\n",
    752   1.1        ad 				    sc->sc_dv.dv_xname, ccb->ccb_hba_status);
    753   1.1        ad 				xs->error = XS_DRIVER_STUFFUP;
    754  1.29    bouyer 				break;
    755   1.1        ad 			}
    756   1.1        ad 		} else if (ccb->ccb_scsi_status != SCSI_OK) {
    757   1.1        ad 			switch (ccb->ccb_scsi_status) {
    758   1.1        ad 			case SCSI_CHECK:
    759  1.29    bouyer 				memcpy(&xs->sense.scsi_sense, &ccb->ccb_sense,
    760  1.29    bouyer 				    sizeof(xs->sense.scsi_sense));
    761   1.1        ad 				xs->error = XS_SENSE;
    762   1.1        ad 				break;
    763   1.1        ad 			case SCSI_BUSY:
    764  1.29    bouyer 			case SCSI_QUEUE_FULL:
    765   1.1        ad 				xs->error = XS_BUSY;
    766   1.1        ad 				break;
    767   1.1        ad 			default:
    768  1.29    bouyer 				scsipi_printaddr(xs->xs_periph);
    769  1.29    bouyer 				printf("SCSI status %x\n",
    770  1.29    bouyer 				    ccb->ccb_scsi_status);
    771   1.1        ad 				xs->error = XS_DRIVER_STUFFUP;
    772  1.29    bouyer 				break;
    773   1.1        ad 			}
    774   1.1        ad 		} else
    775   1.1        ad 			xs->resid = 0;
    776  1.29    bouyer 
    777   1.7        ad 		xs->status = ccb->ccb_scsi_status;
    778   1.1        ad 	}
    779   1.1        ad 
    780  1.29    bouyer 	/* Free up the CCB and mark the command as done. */
    781  1.29    bouyer 	dpt_ccb_free(sc, ccb);
    782   1.1        ad 	scsipi_done(xs);
    783   1.1        ad }
    784   1.1        ad 
    785   1.1        ad /*
    786  1.29    bouyer  * Specified CCB has timed out, abort it.
    787   1.1        ad  */
    788  1.29    bouyer static void
    789  1.29    bouyer dpt_ccb_abort(struct dpt_softc *sc, struct dpt_ccb *ccb)
    790  1.29    bouyer {
    791  1.29    bouyer 	struct scsipi_periph *periph;
    792   1.1        ad 	struct scsipi_xfer *xs;
    793  1.29    bouyer 	int s;
    794   1.1        ad 
    795  1.29    bouyer 	xs = ccb->ccb_xs;
    796  1.29    bouyer 	periph = xs->xs_periph;
    797   1.1        ad 
    798  1.29    bouyer 	scsipi_printaddr(periph);
    799  1.44     perry 	printf("timed out (status:%02x aux status:%02x)",
    800  1.29    bouyer 	    dpt_inb(sc, HA_STATUS), dpt_inb(sc, HA_AUX_STATUS));
    801   1.1        ad 
    802   1.1        ad 	s = splbio();
    803   1.1        ad 
    804  1.29    bouyer 	if ((ccb->ccb_flg & CCB_ABORT) != 0) {
    805  1.29    bouyer 		/* Abort timed out, reset the HBA */
    806  1.29    bouyer 		printf(" AGAIN, resetting HBA\n");
    807  1.29    bouyer 		dpt_outb(sc, HA_COMMAND, CP_RESET);
    808  1.29    bouyer 		DELAY(750000);
    809   1.1        ad 	} else {
    810  1.29    bouyer 		/* Abort the operation that has timed out */
    811  1.29    bouyer 		printf("\n");
    812  1.29    bouyer 		xs->error = XS_TIMEOUT;
    813  1.29    bouyer 		ccb->ccb_timeout = DPT_ABORT_TIMEOUT;
    814  1.29    bouyer 		ccb->ccb_flg |= CCB_ABORT;
    815  1.29    bouyer 		/* Start the abort */
    816  1.29    bouyer 		if (dpt_cmd(sc, ccb, CP_IMMEDIATE, CPI_SPEC_ABORT))
    817  1.29    bouyer 			printf("%s: dpt_cmd failed\n", sc->sc_dv.dv_xname);
    818  1.29    bouyer 	}
    819  1.29    bouyer 
    820  1.29    bouyer 	splx(s);
    821  1.29    bouyer }
    822   1.1        ad 
    823  1.29    bouyer /*
    824  1.29    bouyer  * Map a data transfer.
    825  1.29    bouyer  */
    826  1.29    bouyer static int
    827  1.29    bouyer dpt_ccb_map(struct dpt_softc *sc, struct dpt_ccb *ccb)
    828  1.29    bouyer {
    829  1.29    bouyer 	struct scsipi_xfer *xs;
    830  1.29    bouyer 	bus_dmamap_t xfer;
    831  1.29    bouyer 	bus_dma_segment_t *ds;
    832  1.29    bouyer 	struct eata_sg *sg;
    833  1.29    bouyer 	struct eata_cp *cp;
    834  1.29    bouyer 	int rv, i;
    835   1.1        ad 
    836  1.29    bouyer 	xs = ccb->ccb_xs;
    837  1.29    bouyer 	xfer = ccb->ccb_dmamap_xfer;
    838  1.29    bouyer 	cp = &ccb->ccb_eata_cp;
    839   1.1        ad 
    840  1.29    bouyer 	rv = bus_dmamap_load(sc->sc_dmat, xfer, xs->data, xs->datalen, NULL,
    841  1.44     perry 	    ((xs->xs_control & XS_CTL_NOSLEEP) != 0 ?
    842  1.30   thorpej 	    BUS_DMA_NOWAIT : BUS_DMA_WAITOK) | BUS_DMA_STREAMING |
    843  1.30   thorpej 	    ((xs->xs_control & XS_CTL_DATA_IN) ? BUS_DMA_READ : BUS_DMA_WRITE));
    844  1.29    bouyer 
    845  1.29    bouyer 	switch (rv) {
    846  1.29    bouyer 	case 0:
    847  1.29    bouyer 		break;
    848  1.29    bouyer 	case ENOMEM:
    849  1.29    bouyer 	case EAGAIN:
    850  1.29    bouyer 		xs->error = XS_RESOURCE_SHORTAGE;
    851  1.29    bouyer 		break;
    852  1.29    bouyer 	default:
    853  1.29    bouyer 		xs->error = XS_DRIVER_STUFFUP;
    854  1.29    bouyer 		printf("%s: error %d loading map\n", sc->sc_dv.dv_xname, rv);
    855  1.29    bouyer 		break;
    856  1.29    bouyer 	}
    857   1.1        ad 
    858  1.29    bouyer 	if (xs->error != XS_NOERROR) {
    859  1.29    bouyer 		dpt_ccb_free(sc, ccb);
    860  1.29    bouyer 		scsipi_done(xs);
    861  1.29    bouyer 		return (-1);
    862   1.1        ad 	}
    863   1.1        ad 
    864  1.29    bouyer 	bus_dmamap_sync(sc->sc_dmat, xfer, 0, xfer->dm_mapsize,
    865  1.29    bouyer 	    (xs->xs_control & XS_CTL_DATA_IN) != 0 ? BUS_DMASYNC_PREREAD :
    866  1.29    bouyer 	    BUS_DMASYNC_PREWRITE);
    867  1.29    bouyer 
    868  1.29    bouyer 	/* Don't bother using scatter/gather for just 1 seg */
    869  1.29    bouyer 	if (xfer->dm_nsegs == 1) {
    870  1.29    bouyer 		cp->cp_dataaddr = htobe32(xfer->dm_segs[0].ds_addr);
    871  1.29    bouyer 		cp->cp_datalen = htobe32(xfer->dm_segs[0].ds_len);
    872  1.29    bouyer 	} else {
    873  1.29    bouyer 		/*
    874  1.44     perry 		 * Load the hardware scatter/gather map with
    875  1.29    bouyer 		 * the contents of the DMA map.
    876   1.1        ad 		 */
    877  1.29    bouyer 		sg = ccb->ccb_sg;
    878  1.29    bouyer 		ds = xfer->dm_segs;
    879  1.29    bouyer 		for (i = 0; i < xfer->dm_nsegs; i++, sg++, ds++) {
    880  1.29    bouyer  			sg->sg_addr = htobe32(ds->ds_addr);
    881  1.29    bouyer  			sg->sg_len =  htobe32(ds->ds_len);
    882  1.29    bouyer  		}
    883  1.44     perry 	 	cp->cp_dataaddr = htobe32(CCB_OFF(sc, ccb) +
    884  1.29    bouyer 		    sc->sc_dmamap->dm_segs[0].ds_addr +
    885  1.29    bouyer 		    offsetof(struct dpt_ccb, ccb_sg));
    886  1.29    bouyer 		cp->cp_datalen = htobe32(i * sizeof(struct eata_sg));
    887  1.29    bouyer 		cp->cp_ctl0 |= CP_C0_SCATTER;
    888   1.1        ad 	}
    889   1.1        ad 
    890  1.29    bouyer 	return (0);
    891  1.29    bouyer }
    892  1.29    bouyer 
    893  1.29    bouyer /*
    894  1.29    bouyer  * Unmap a transfer.
    895  1.29    bouyer  */
    896  1.29    bouyer static void
    897  1.29    bouyer dpt_ccb_unmap(struct dpt_softc *sc, struct dpt_ccb *ccb)
    898  1.29    bouyer {
    899  1.29    bouyer 
    900  1.29    bouyer 	bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap_xfer, 0,
    901  1.29    bouyer 	    ccb->ccb_dmamap_xfer->dm_mapsize,
    902  1.29    bouyer 	    (ccb->ccb_eata_cp.cp_ctl0 & CP_C0_DATA_IN) != 0 ?
    903  1.29    bouyer 	    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
    904  1.29    bouyer 	bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap_xfer);
    905  1.29    bouyer }
    906  1.29    bouyer 
    907  1.29    bouyer /*
    908  1.29    bouyer  * Adjust the size of each I/O before it passes to the SCSI layer.
    909  1.29    bouyer  */
    910  1.29    bouyer static void
    911  1.29    bouyer dpt_minphys(struct buf *bp)
    912  1.29    bouyer {
    913  1.29    bouyer 
    914  1.29    bouyer 	if (bp->b_bcount > DPT_MAX_XFER)
    915  1.29    bouyer 		bp->b_bcount = DPT_MAX_XFER;
    916  1.29    bouyer 	minphys(bp);
    917  1.29    bouyer }
    918  1.29    bouyer 
    919  1.29    bouyer /*
    920  1.29    bouyer  * Start a SCSI command.
    921  1.29    bouyer  */
    922  1.29    bouyer static void
    923  1.29    bouyer dpt_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req,
    924  1.29    bouyer 		   void *arg)
    925  1.29    bouyer {
    926  1.29    bouyer 	struct dpt_softc *sc;
    927  1.29    bouyer 	struct scsipi_xfer *xs;
    928  1.29    bouyer 	int flags;
    929  1.29    bouyer 	struct scsipi_periph *periph;
    930  1.29    bouyer 	struct dpt_ccb *ccb;
    931  1.29    bouyer 	struct eata_cp *cp;
    932  1.29    bouyer 
    933  1.29    bouyer 	sc = (struct dpt_softc *)chan->chan_adapter->adapt_dev;
    934   1.1        ad 
    935  1.29    bouyer 	switch (req) {
    936  1.29    bouyer 	case ADAPTER_REQ_RUN_XFER:
    937  1.29    bouyer 		xs = arg;
    938  1.29    bouyer 		periph = xs->xs_periph;
    939  1.29    bouyer 		flags = xs->xs_control;
    940   1.1        ad 
    941  1.29    bouyer #ifdef DIAGNOSTIC
    942  1.29    bouyer 		/* Cmds must be no more than 12 bytes for us. */
    943  1.29    bouyer 		if (xs->cmdlen > 12) {
    944  1.29    bouyer 			xs->error = XS_DRIVER_STUFFUP;
    945  1.29    bouyer 			scsipi_done(xs);
    946  1.29    bouyer 			break;
    947   1.1        ad 		}
    948  1.29    bouyer #endif
    949  1.29    bouyer 		/*
    950  1.29    bouyer 		 * XXX We can't reset devices just yet.  Apparently some
    951  1.29    bouyer 		 * older firmware revisions don't even support it.
    952  1.29    bouyer 		 */
    953  1.29    bouyer 		if ((flags & XS_CTL_RESET) != 0) {
    954   1.1        ad 			xs->error = XS_DRIVER_STUFFUP;
    955  1.29    bouyer 			scsipi_done(xs);
    956  1.29    bouyer 			break;
    957   1.1        ad 		}
    958   1.1        ad 
    959  1.29    bouyer 		/*
    960  1.29    bouyer 		 * Get a CCB and fill it.
    961  1.29    bouyer 		 */
    962  1.29    bouyer 		ccb = dpt_ccb_alloc(sc);
    963  1.29    bouyer 		ccb->ccb_xs = xs;
    964  1.29    bouyer 		ccb->ccb_timeout = xs->timeout;
    965  1.29    bouyer 
    966  1.29    bouyer 		cp = &ccb->ccb_eata_cp;
    967  1.29    bouyer 		memcpy(&cp->cp_cdb_cmd, xs->cmd, xs->cmdlen);
    968  1.29    bouyer 		cp->cp_ccbid = ccb->ccb_id;
    969  1.29    bouyer 		cp->cp_senselen = sizeof(ccb->ccb_sense);
    970  1.29    bouyer 		cp->cp_stataddr = htobe32(sc->sc_stppa);
    971  1.29    bouyer 		cp->cp_ctl0 = CP_C0_AUTO_SENSE;
    972  1.44     perry 		cp->cp_ctl1 = 0;
    973  1.29    bouyer 		cp->cp_ctl2 = 0;
    974  1.29    bouyer 		cp->cp_ctl3 = periph->periph_target << CP_C3_ID_SHIFT;
    975  1.29    bouyer 		cp->cp_ctl3 |= chan->chan_channel << CP_C3_CHANNEL_SHIFT;
    976  1.29    bouyer 		cp->cp_ctl4 = periph->periph_lun << CP_C4_LUN_SHIFT;
    977  1.29    bouyer 		cp->cp_ctl4 |= CP_C4_DIS_PRI | CP_C4_IDENTIFY;
    978  1.29    bouyer 
    979  1.29    bouyer 		if ((flags & XS_CTL_DATA_IN) != 0)
    980  1.29    bouyer 			cp->cp_ctl0 |= CP_C0_DATA_IN;
    981  1.29    bouyer 		if ((flags & XS_CTL_DATA_OUT) != 0)
    982  1.29    bouyer 			cp->cp_ctl0 |= CP_C0_DATA_OUT;
    983  1.29    bouyer 		if (sc->sc_hbaid[chan->chan_channel] == periph->periph_target)
    984  1.29    bouyer 			cp->cp_ctl0 |= CP_C0_INTERPRET;
    985  1.29    bouyer 
    986  1.29    bouyer 		/* Synchronous xfers musn't write-back through the cache. */
    987  1.29    bouyer 		if (xs->bp != NULL)
    988  1.29    bouyer 			if ((xs->bp->b_flags & (B_ASYNC | B_READ)) == 0)
    989  1.29    bouyer 				cp->cp_ctl2 |= CP_C2_NO_CACHE;
    990  1.29    bouyer 
    991  1.29    bouyer 		cp->cp_senseaddr =
    992  1.29    bouyer 		    htobe32(sc->sc_dmamap->dm_segs[0].ds_addr +
    993  1.29    bouyer 		    CCB_OFF(sc, ccb) + offsetof(struct dpt_ccb, ccb_sense));
    994   1.1        ad 
    995  1.29    bouyer 		if (xs->datalen != 0) {
    996  1.29    bouyer 			if (dpt_ccb_map(sc, ccb))
    997  1.29    bouyer 				break;
    998   1.9        ad 		} else {
    999  1.29    bouyer 			cp->cp_dataaddr = 0;
   1000  1.29    bouyer 			cp->cp_datalen = 0;
   1001   1.1        ad 		}
   1002   1.1        ad 
   1003  1.29    bouyer 		/* Sync up CCB and status packet. */
   1004  1.29    bouyer 		bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap,
   1005  1.29    bouyer 		    CCB_OFF(sc, ccb), sizeof(struct dpt_ccb),
   1006  1.29    bouyer 		    BUS_DMASYNC_PREWRITE);
   1007  1.29    bouyer 		bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, sc->sc_stpoff,
   1008  1.29    bouyer 		    sizeof(struct eata_sp), BUS_DMASYNC_PREREAD);
   1009   1.1        ad 
   1010  1.44     perry 		/*
   1011  1.29    bouyer 		 * Start the command.
   1012  1.29    bouyer 		 */
   1013  1.29    bouyer 		if ((xs->xs_control & XS_CTL_POLL) != 0)
   1014  1.44     perry 			ccb->ccb_flg |= CCB_PRIVATE;
   1015   1.1        ad 
   1016  1.29    bouyer 		if (dpt_cmd(sc, ccb, CP_DMA_CMD, 0)) {
   1017  1.29    bouyer 			printf("%s: dpt_cmd failed\n", sc->sc_dv.dv_xname);
   1018  1.29    bouyer 			xs->error = XS_DRIVER_STUFFUP;
   1019  1.29    bouyer 			if (xs->datalen != 0)
   1020  1.29    bouyer 				dpt_ccb_unmap(sc, ccb);
   1021  1.29    bouyer 			dpt_ccb_free(sc, ccb);
   1022  1.29    bouyer 			break;
   1023  1.29    bouyer 		}
   1024   1.1        ad 
   1025  1.29    bouyer 		if ((xs->xs_control & XS_CTL_POLL) == 0)
   1026  1.29    bouyer 			break;
   1027   1.1        ad 
   1028  1.29    bouyer 		if (dpt_ccb_poll(sc, ccb)) {
   1029  1.29    bouyer 			dpt_ccb_abort(sc, ccb);
   1030  1.29    bouyer 			/* Wait for abort to complete... */
   1031  1.29    bouyer 			if (dpt_ccb_poll(sc, ccb))
   1032  1.29    bouyer 				dpt_ccb_abort(sc, ccb);
   1033  1.44     perry 		}
   1034   1.1        ad 
   1035  1.29    bouyer 		dpt_ccb_done(sc, ccb);
   1036  1.29    bouyer 		break;
   1037   1.1        ad 
   1038  1.29    bouyer 	case ADAPTER_REQ_GROW_RESOURCES:
   1039  1.29    bouyer 		/*
   1040  1.29    bouyer 		 * Not supported, since we allocate the maximum number of
   1041  1.29    bouyer 		 * CCBs up front.
   1042  1.29    bouyer 		 */
   1043  1.29    bouyer 		break;
   1044   1.1        ad 
   1045  1.29    bouyer 	case ADAPTER_REQ_SET_XFER_MODE:
   1046  1.29    bouyer 		/*
   1047  1.29    bouyer 		 * This will be handled by the HBA itself, and we can't
   1048  1.29    bouyer 		 * modify that (ditto for tagged queueing).
   1049  1.29    bouyer 		 */
   1050  1.29    bouyer 		break;
   1051   1.1        ad 	}
   1052   1.1        ad }
   1053   1.1        ad 
   1054   1.1        ad /*
   1055   1.1        ad  * Get inquiry data from the adapter.
   1056   1.1        ad  */
   1057  1.29    bouyer static void
   1058  1.29    bouyer dpt_hba_inquire(struct dpt_softc *sc, struct eata_inquiry_data **ei)
   1059   1.1        ad {
   1060   1.1        ad 	struct dpt_ccb *ccb;
   1061   1.1        ad 	struct eata_cp *cp;
   1062  1.29    bouyer 
   1063   1.1        ad 	*ei = (struct eata_inquiry_data *)sc->sc_scr;
   1064   1.1        ad 
   1065   1.1        ad 	/* Get a CCB and mark as private */
   1066  1.29    bouyer 	ccb = dpt_ccb_alloc(sc);
   1067   1.1        ad 	ccb->ccb_flg |= CCB_PRIVATE;
   1068   1.1        ad 	ccb->ccb_timeout = 200;
   1069   1.1        ad 
   1070  1.29    bouyer 	/* Put all the arguments into the CCB. */
   1071   1.1        ad 	cp = &ccb->ccb_eata_cp;
   1072   1.1        ad 	cp->cp_ccbid = ccb->ccb_id;
   1073   1.1        ad 	cp->cp_senselen = sizeof(ccb->ccb_sense);
   1074  1.29    bouyer 	cp->cp_senseaddr = 0;
   1075  1.19        ad 	cp->cp_stataddr = htobe32(sc->sc_stppa);
   1076  1.13        ad 	cp->cp_dataaddr = htobe32(sc->sc_scrpa);
   1077  1.13        ad 	cp->cp_datalen = htobe32(sizeof(struct eata_inquiry_data));
   1078  1.19        ad 	cp->cp_ctl0 = CP_C0_DATA_IN | CP_C0_INTERPRET;
   1079  1.19        ad 	cp->cp_ctl1 = 0;
   1080  1.19        ad 	cp->cp_ctl2 = 0;
   1081  1.19        ad 	cp->cp_ctl3 = sc->sc_hbaid[0] << CP_C3_ID_SHIFT;
   1082  1.19        ad 	cp->cp_ctl4 = CP_C4_DIS_PRI | CP_C4_IDENTIFY;
   1083  1.19        ad 
   1084  1.29    bouyer 	/* Put together the SCSI inquiry command. */
   1085  1.29    bouyer 	memset(&cp->cp_cdb_cmd, 0, 12);
   1086  1.19        ad 	cp->cp_cdb_cmd = INQUIRY;
   1087  1.19        ad 	cp->cp_cdb_len = sizeof(struct eata_inquiry_data);
   1088   1.1        ad 
   1089  1.29    bouyer 	/* Sync up CCB, status packet and scratch area. */
   1090  1.44     perry 	bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, CCB_OFF(sc, ccb),
   1091   1.1        ad 	    sizeof(struct dpt_ccb), BUS_DMASYNC_PREWRITE);
   1092  1.44     perry 	bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, sc->sc_stpoff,
   1093   1.1        ad 	    sizeof(struct eata_sp), BUS_DMASYNC_PREREAD);
   1094  1.44     perry 	bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, sc->sc_scroff,
   1095   1.1        ad 	    sizeof(struct eata_inquiry_data), BUS_DMASYNC_PREREAD);
   1096   1.1        ad 
   1097  1.29    bouyer 	/* Start the command and poll on completion. */
   1098  1.29    bouyer 	if (dpt_cmd(sc, ccb, CP_DMA_CMD, 0))
   1099   1.4        ad 		panic("%s: dpt_cmd failed", sc->sc_dv.dv_xname);
   1100   1.1        ad 
   1101  1.29    bouyer 	if (dpt_ccb_poll(sc, ccb))
   1102   1.1        ad 		panic("%s: inquiry timed out", sc->sc_dv.dv_xname);
   1103   1.1        ad 
   1104  1.19        ad 	if (ccb->ccb_hba_status != SP_HBA_NO_ERROR ||
   1105   1.1        ad 	    ccb->ccb_scsi_status != SCSI_OK)
   1106  1.29    bouyer 		panic("%s: inquiry failed (hba:%02x scsi:%02x)",
   1107  1.29    bouyer 		    sc->sc_dv.dv_xname, ccb->ccb_hba_status,
   1108  1.29    bouyer 		    ccb->ccb_scsi_status);
   1109  1.29    bouyer 
   1110  1.29    bouyer 	/* Sync up the DMA map and free CCB, returning. */
   1111  1.44     perry 	bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, sc->sc_scroff,
   1112   1.1        ad 	    sizeof(struct eata_inquiry_data), BUS_DMASYNC_POSTREAD);
   1113  1.29    bouyer 	dpt_ccb_free(sc, ccb);
   1114  1.33        ad }
   1115  1.33        ad 
   1116  1.33        ad int
   1117  1.45  christos dptopen(dev_t dev, int flag, int mode, struct lwp *l)
   1118  1.33        ad {
   1119  1.33        ad 
   1120  1.33        ad 	if (device_lookup(&dpt_cd, minor(dev)) == NULL)
   1121  1.33        ad 		return (ENXIO);
   1122  1.33        ad 
   1123  1.33        ad 	return (0);
   1124  1.33        ad }
   1125  1.33        ad 
   1126  1.33        ad int
   1127  1.45  christos dptioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct lwp *l)
   1128  1.33        ad {
   1129  1.33        ad 	struct dpt_softc *sc;
   1130  1.33        ad 	int rv;
   1131  1.33        ad 
   1132  1.33        ad 	sc = device_lookup(&dpt_cd, minor(dev));
   1133  1.33        ad 
   1134  1.33        ad 	switch (cmd & 0xffff) {
   1135  1.33        ad 	case DPT_SIGNATURE:
   1136  1.33        ad 		memcpy(data, &dpt_sig, min(IOCPARM_LEN(cmd), sizeof(dpt_sig)));
   1137  1.33        ad 		break;
   1138  1.33        ad 
   1139  1.33        ad 	case DPT_CTRLINFO:
   1140  1.33        ad 		dpt_ctlrinfo(sc, (struct dpt_eata_ctlrinfo *)data);
   1141  1.33        ad 		break;
   1142  1.33        ad 
   1143  1.33        ad 	case DPT_SYSINFO:
   1144  1.33        ad 		dpt_sysinfo(sc, (struct dpt_sysinfo *)data);
   1145  1.33        ad 		break;
   1146  1.33        ad 
   1147  1.33        ad 	case DPT_BLINKLED:
   1148  1.33        ad 		/*
   1149  1.33        ad 		 * XXX Don't know how to get this from EATA boards.  I think
   1150  1.33        ad 		 * it involves waiting for a "DPT" sequence from HA_ERROR
   1151  1.33        ad 		 * and then reading one of the HA_ICMD registers.
   1152  1.33        ad 		 */
   1153  1.33        ad 		*(int *)data = 0;
   1154  1.33        ad 		break;
   1155  1.33        ad 
   1156  1.33        ad 	case DPT_EATAUSRCMD:
   1157  1.49  christos 		if (securelevel > 1)
   1158  1.49  christos 			return (EPERM);
   1159  1.49  christos 
   1160  1.37        ad 		if (IOCPARM_LEN(cmd) < sizeof(struct eata_ucp)) {
   1161  1.38    kleink 			DPRINTF(("%s: ucp %lu vs %lu bytes\n",
   1162  1.37        ad 			    sc->sc_dv.dv_xname, IOCPARM_LEN(cmd),
   1163  1.38    kleink 			    (unsigned long int)sizeof(struct eata_ucp)));
   1164  1.37        ad 			return (EINVAL);
   1165  1.37        ad 		}
   1166  1.37        ad 
   1167  1.33        ad 		if (sc->sc_uactive++)
   1168  1.33        ad 			tsleep(&sc->sc_uactive, PRIBIO, "dptslp", 0);
   1169  1.33        ad 
   1170  1.45  christos 		rv = dpt_passthrough(sc, (struct eata_ucp *)data, l);
   1171  1.33        ad 
   1172  1.33        ad 		sc->sc_uactive--;
   1173  1.33        ad 		wakeup_one(&sc->sc_uactive);
   1174  1.33        ad 		return (rv);
   1175  1.33        ad 
   1176  1.33        ad 	default:
   1177  1.33        ad 		DPRINTF(("%s: unknown ioctl %lx\n", sc->sc_dv.dv_xname, cmd));
   1178  1.33        ad 		return (ENOTTY);
   1179  1.33        ad 	}
   1180  1.33        ad 
   1181  1.33        ad 	return (0);
   1182  1.33        ad }
   1183  1.33        ad 
   1184  1.33        ad void
   1185  1.33        ad dpt_ctlrinfo(struct dpt_softc *sc, struct dpt_eata_ctlrinfo *info)
   1186  1.33        ad {
   1187  1.33        ad 
   1188  1.33        ad 	memset(info, 0, sizeof(*info));
   1189  1.33        ad 	info->id = sc->sc_hbaid[0];
   1190  1.33        ad 	info->vect = sc->sc_isairq;
   1191  1.33        ad 	info->base = sc->sc_isaport;
   1192  1.33        ad 	info->qdepth = sc->sc_nccbs;
   1193  1.33        ad 	info->sgsize = DPT_SG_SIZE * sizeof(struct eata_sg);
   1194  1.33        ad 	info->heads = 16;
   1195  1.33        ad 	info->sectors = 63;
   1196  1.33        ad 	info->do_drive32 = 1;
   1197  1.33        ad 	info->primary = 1;
   1198  1.33        ad 	info->cpLength = sizeof(struct eata_cp);
   1199  1.33        ad 	info->spLength = sizeof(struct eata_sp);
   1200  1.33        ad 	info->drqNum = sc->sc_isadrq;
   1201  1.33        ad }
   1202  1.33        ad 
   1203  1.33        ad void
   1204  1.33        ad dpt_sysinfo(struct dpt_softc *sc, struct dpt_sysinfo *info)
   1205  1.33        ad {
   1206  1.33        ad #ifdef i386
   1207  1.33        ad 	int i, j;
   1208  1.33        ad #endif
   1209  1.33        ad 
   1210  1.33        ad 	memset(info, 0, sizeof(*info));
   1211  1.33        ad 
   1212  1.33        ad #ifdef i386
   1213  1.33        ad 	outb (0x70, 0x12);
   1214  1.33        ad 	i = inb(0x71);
   1215  1.33        ad 	j = i >> 4;
   1216  1.33        ad 	if (i == 0x0f) {
   1217  1.33        ad 		outb (0x70, 0x19);
   1218  1.33        ad 		j = inb (0x71);
   1219  1.33        ad 	}
   1220  1.33        ad 	info->drive0CMOS = j;
   1221  1.33        ad 
   1222  1.33        ad 	j = i & 0x0f;
   1223  1.33        ad 	if (i == 0x0f) {
   1224  1.33        ad 		outb (0x70, 0x1a);
   1225  1.33        ad 		j = inb (0x71);
   1226  1.33        ad 	}
   1227  1.33        ad 	info->drive1CMOS = j;
   1228  1.33        ad 	info->processorFamily = dpt_sig.dsProcessorFamily;
   1229  1.33        ad 
   1230  1.33        ad 	/*
   1231  1.33        ad 	 * Get the conventional memory size from CMOS.
   1232  1.33        ad 	 */
   1233  1.33        ad 	outb(0x70, 0x16);
   1234  1.33        ad 	j = inb(0x71);
   1235  1.33        ad 	j <<= 8;
   1236  1.33        ad 	outb(0x70, 0x15);
   1237  1.33        ad 	j |= inb(0x71);
   1238  1.33        ad 	info->conventionalMemSize = j;
   1239  1.33        ad 
   1240  1.33        ad 	/*
   1241  1.33        ad 	 * Get the extended memory size from CMOS.
   1242  1.33        ad 	 */
   1243  1.33        ad 	outb(0x70, 0x31);
   1244  1.33        ad 	j = inb(0x71);
   1245  1.33        ad 	j <<= 8;
   1246  1.33        ad 	outb(0x70, 0x30);
   1247  1.33        ad 	j |= inb(0x71);
   1248  1.33        ad 	info->extendedMemSize = j;
   1249  1.33        ad 
   1250  1.33        ad 	switch (cpu_class) {
   1251  1.33        ad 	case CPUCLASS_386:
   1252  1.33        ad 		info->processorType = PROC_386;
   1253  1.33        ad 		break;
   1254  1.33        ad 	case CPUCLASS_486:
   1255  1.33        ad 		info->processorType = PROC_486;
   1256  1.33        ad 		break;
   1257  1.33        ad 	case CPUCLASS_586:
   1258  1.33        ad 		info->processorType = PROC_PENTIUM;
   1259  1.33        ad 		break;
   1260  1.33        ad 	case CPUCLASS_686:
   1261  1.33        ad 	default:
   1262  1.33        ad 		info->processorType = PROC_SEXIUM;
   1263  1.33        ad 		break;
   1264  1.33        ad 	}
   1265  1.33        ad 
   1266  1.33        ad 	info->flags = SI_CMOS_Valid | SI_BusTypeValid |
   1267  1.33        ad 	    SI_MemorySizeValid | SI_NO_SmartROM;
   1268  1.33        ad #else
   1269  1.33        ad 	info->flags = SI_BusTypeValid | SI_NO_SmartROM;
   1270  1.33        ad #endif
   1271  1.33        ad 
   1272  1.33        ad 	info->busType = sc->sc_bustype;
   1273  1.33        ad }
   1274  1.33        ad 
   1275  1.33        ad int
   1276  1.45  christos dpt_passthrough(struct dpt_softc *sc, struct eata_ucp *ucp, struct lwp *l)
   1277  1.33        ad {
   1278  1.33        ad 	struct dpt_ccb *ccb;
   1279  1.33        ad 	struct eata_sp sp;
   1280  1.33        ad 	struct eata_cp *cp;
   1281  1.33        ad 	struct eata_sg *sg;
   1282  1.42  christos 	bus_dmamap_t xfer = 0; /* XXX: gcc */
   1283  1.33        ad 	bus_dma_segment_t *ds;
   1284  1.42  christos 	int datain = 0, s, rv = 0, i, uslen; /* XXX: gcc */
   1285  1.33        ad 
   1286  1.33        ad 	/*
   1287  1.33        ad 	 * Get a CCB and fill.
   1288  1.33        ad 	 */
   1289  1.33        ad 	ccb = dpt_ccb_alloc(sc);
   1290  1.33        ad 	ccb->ccb_flg |= CCB_PRIVATE | CCB_WAIT;
   1291  1.33        ad 	ccb->ccb_timeout = 0;
   1292  1.33        ad 	ccb->ccb_savesp = &sp;
   1293  1.33        ad 
   1294  1.33        ad 	cp = &ccb->ccb_eata_cp;
   1295  1.34        ad 	memcpy(cp, ucp->ucp_cp, sizeof(ucp->ucp_cp));
   1296  1.34        ad 	uslen = cp->cp_senselen;
   1297  1.33        ad 	cp->cp_ccbid = ccb->ccb_id;
   1298  1.33        ad 	cp->cp_senselen = sizeof(ccb->ccb_sense);
   1299  1.33        ad 	cp->cp_senseaddr = htobe32(sc->sc_dmamap->dm_segs[0].ds_addr +
   1300  1.33        ad 	    CCB_OFF(sc, ccb) + offsetof(struct dpt_ccb, ccb_sense));
   1301  1.33        ad 	cp->cp_stataddr = htobe32(sc->sc_stppa);
   1302  1.33        ad 
   1303  1.33        ad 	/*
   1304  1.33        ad 	 * Map data transfers.
   1305  1.33        ad 	 */
   1306  1.34        ad 	if (ucp->ucp_dataaddr && ucp->ucp_datalen) {
   1307  1.33        ad 		xfer = ccb->ccb_dmamap_xfer;
   1308  1.34        ad 		datain = ((cp->cp_ctl0 & CP_C0_DATA_IN) != 0);
   1309  1.33        ad 
   1310  1.34        ad 		if (ucp->ucp_datalen > DPT_MAX_XFER) {
   1311  1.33        ad 			DPRINTF(("%s: xfer too big\n", sc->sc_dv.dv_xname));
   1312  1.33        ad 			dpt_ccb_free(sc, ccb);
   1313  1.33        ad 			return (EFBIG);
   1314  1.33        ad 		}
   1315  1.33        ad 		rv = bus_dmamap_load(sc->sc_dmat, xfer,
   1316  1.45  christos 		    ucp->ucp_dataaddr, ucp->ucp_datalen, l->l_proc,
   1317  1.33        ad 		    BUS_DMA_WAITOK | BUS_DMA_STREAMING |
   1318  1.33        ad 		    (datain ? BUS_DMA_READ : BUS_DMA_WRITE));
   1319  1.33        ad 		if (rv != 0) {
   1320  1.33        ad 			DPRINTF(("%s: map failed; %d\n", sc->sc_dv.dv_xname,
   1321  1.33        ad 			    rv));
   1322  1.33        ad 			dpt_ccb_free(sc, ccb);
   1323  1.33        ad 			return (rv);
   1324  1.33        ad 		}
   1325  1.33        ad 
   1326  1.33        ad 		bus_dmamap_sync(sc->sc_dmat, xfer, 0, xfer->dm_mapsize,
   1327  1.33        ad 		    (datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE));
   1328  1.33        ad 
   1329  1.33        ad 		sg = ccb->ccb_sg;
   1330  1.33        ad 		ds = xfer->dm_segs;
   1331  1.33        ad 		for (i = 0; i < xfer->dm_nsegs; i++, sg++, ds++) {
   1332  1.33        ad 	 		sg->sg_addr = htobe32(ds->ds_addr);
   1333  1.34        ad 	 		sg->sg_len = htobe32(ds->ds_len);
   1334  1.33        ad  		}
   1335  1.44     perry 		cp->cp_dataaddr = htobe32(CCB_OFF(sc, ccb) +
   1336  1.33        ad 		    sc->sc_dmamap->dm_segs[0].ds_addr +
   1337  1.33        ad 		    offsetof(struct dpt_ccb, ccb_sg));
   1338  1.33        ad 		cp->cp_datalen = htobe32(i * sizeof(struct eata_sg));
   1339  1.33        ad 		cp->cp_ctl0 |= CP_C0_SCATTER;
   1340  1.33        ad 	} else {
   1341  1.33        ad 		cp->cp_dataaddr = 0;
   1342  1.33        ad 		cp->cp_datalen = 0;
   1343  1.33        ad 	}
   1344  1.33        ad 
   1345  1.33        ad 	/*
   1346  1.33        ad 	 * Start the command and sleep on completion.
   1347  1.33        ad 	 */
   1348  1.36   thorpej 	PHOLD(curlwp);	/* XXXJRT curlwp */
   1349  1.44     perry 	bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, CCB_OFF(sc, ccb),
   1350  1.33        ad 	    sizeof(struct dpt_ccb), BUS_DMASYNC_PREWRITE);
   1351  1.33        ad 	s = splbio();
   1352  1.44     perry 	bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, sc->sc_stpoff,
   1353  1.33        ad 	    sizeof(struct eata_sp), BUS_DMASYNC_PREREAD);
   1354  1.33        ad 	if (dpt_cmd(sc, ccb, CP_DMA_CMD, 0))
   1355  1.33        ad 		panic("%s: dpt_cmd failed", sc->sc_dv.dv_xname);
   1356  1.33        ad 	tsleep(ccb, PWAIT, "dptucmd", 0);
   1357  1.33        ad 	splx(s);
   1358  1.36   thorpej 	PRELE(curlwp);	/* XXXJRT curlwp */
   1359  1.33        ad 
   1360  1.33        ad 	/*
   1361  1.33        ad 	 * Sync up the DMA map and copy out results.
   1362  1.33        ad 	 */
   1363  1.44     perry 	bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, CCB_OFF(sc, ccb),
   1364  1.33        ad 	    sizeof(struct dpt_ccb), BUS_DMASYNC_POSTWRITE);
   1365  1.33        ad 
   1366  1.33        ad 	if (cp->cp_datalen != 0) {
   1367  1.33        ad 		bus_dmamap_sync(sc->sc_dmat, xfer, 0, xfer->dm_mapsize,
   1368  1.33        ad 		    (datain ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE));
   1369  1.33        ad 		bus_dmamap_unload(sc->sc_dmat, xfer);
   1370  1.33        ad 	}
   1371  1.33        ad 
   1372  1.34        ad 	if (ucp->ucp_stataddr != NULL) {
   1373  1.34        ad 		rv = copyout(&sp, ucp->ucp_stataddr, sizeof(sp));
   1374  1.51  christos 		if (rv != 0) {
   1375  1.33        ad 			DPRINTF(("%s: sp copyout() failed\n",
   1376  1.33        ad 			    sc->sc_dv.dv_xname));
   1377  1.51  christos 		}
   1378  1.33        ad 	}
   1379  1.34        ad 	if (rv == 0 && ucp->ucp_senseaddr != NULL) {
   1380  1.34        ad 		i = min(uslen, sizeof(ccb->ccb_sense));
   1381  1.34        ad 		rv = copyout(&ccb->ccb_sense, ucp->ucp_senseaddr, i);
   1382  1.51  christos 		if (rv != 0) {
   1383  1.33        ad 			DPRINTF(("%s: sense copyout() failed\n",
   1384  1.33        ad 			    sc->sc_dv.dv_xname));
   1385  1.51  christos 		}
   1386  1.33        ad 	}
   1387  1.33        ad 
   1388  1.37        ad 	ucp->ucp_hstatus = (u_int8_t)ccb->ccb_hba_status;
   1389  1.37        ad 	ucp->ucp_tstatus = (u_int8_t)ccb->ccb_scsi_status;
   1390  1.33        ad 	dpt_ccb_free(sc, ccb);
   1391  1.33        ad 	return (rv);
   1392   1.1        ad }
   1393