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