1/*	$NetBSD: twe.c,v 1.95 2011/06/30 20:09:40 wiz Exp $	*/
2
3/*-
4 * Copyright (c) 2000, 2001, 2002, 2003, 2004 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; and by Jason R. Thorpe of Wasabi Systems, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32/*-
33 * Copyright (c) 2000 Michael Smith
34 * Copyright (c) 2000 BSDi
35 * All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 *    notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 *    notice, this list of conditions and the following disclaimer in the
44 *    documentation and/or other materials provided with the distribution.
45 *
46 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 * SUCH DAMAGE.
57 *
58 * from FreeBSD: twe.c,v 1.1 2000/05/24 23:35:23 msmith Exp
59 */
60
61/*
62 * Driver for the 3ware Escalade family of RAID controllers.
63 */
64
65#include <sys/cdefs.h>
66__KERNEL_RCSID(0, "$NetBSD: twe.c,v 1.95 2011/06/30 20:09:40 wiz Exp $");
67
68#include <sys/param.h>
69#include <sys/systm.h>
70#include <sys/kernel.h>
71#include <sys/device.h>
72#include <sys/queue.h>
73#include <sys/proc.h>
74#include <sys/buf.h>
75#include <sys/endian.h>
76#include <sys/malloc.h>
77#include <sys/conf.h>
78#include <sys/disk.h>
79#include <sys/sysctl.h>
80#include <sys/syslog.h>
81#include <sys/kauth.h>
82
83#include <sys/bswap.h>
84#include <sys/bus.h>
85
86#include <dev/pci/pcireg.h>
87#include <dev/pci/pcivar.h>
88#include <dev/pci/pcidevs.h>
89#include <dev/pci/twereg.h>
90#include <dev/pci/twevar.h>
91#include <dev/pci/tweio.h>
92
93#include "locators.h"
94
95#define	PCI_CBIO	0x10
96
97static int	twe_aen_get(struct twe_softc *, uint16_t *);
98static void	twe_aen_handler(struct twe_ccb *, int);
99static void	twe_aen_enqueue(struct twe_softc *sc, uint16_t, int);
100static uint16_t	twe_aen_dequeue(struct twe_softc *);
101
102static void	twe_attach(device_t, device_t, void *);
103static int	twe_init_connection(struct twe_softc *);
104static int	twe_intr(void *);
105static int	twe_match(device_t, cfdata_t, void *);
106static int	twe_param_set(struct twe_softc *, int, int, size_t, void *);
107static void	twe_poll(struct twe_softc *);
108static int	twe_print(void *, const char *);
109static int	twe_reset(struct twe_softc *);
110static int	twe_status_check(struct twe_softc *, u_int);
111static int	twe_status_wait(struct twe_softc *, u_int, int);
112static void	twe_describe_controller(struct twe_softc *);
113static void twe_clear_pci_abort(struct twe_softc *sc);
114static void twe_clear_pci_parity_error(struct twe_softc *sc);
115
116static int	twe_add_unit(struct twe_softc *, int);
117static int	twe_del_unit(struct twe_softc *, int);
118static int	twe_init_connection(struct twe_softc *);
119
120static inline u_int32_t	twe_inl(struct twe_softc *, int);
121static inline void twe_outl(struct twe_softc *, int, u_int32_t);
122
123extern struct	cfdriver twe_cd;
124
125CFATTACH_DECL(twe, sizeof(struct twe_softc),
126    twe_match, twe_attach, NULL, NULL);
127
128/* FreeBSD driver revision for sysctl expected by the 3ware cli */
129const char twever[] = "1.50.01.002";
130
131/*
132 * Tables to convert numeric codes to strings.
133 */
134const struct twe_code_table twe_table_status[] = {
135	{ 0x00,	"successful completion" },
136
137	/* info */
138	{ 0x42,	"command in progress" },
139	{ 0x6c,	"retrying interface CRC error from UDMA command" },
140
141	/* warning */
142	{ 0x81,	"redundant/inconsequential request ignored" },
143	{ 0x8e,	"failed to write zeroes to LBA 0" },
144	{ 0x8f,	"failed to profile TwinStor zones" },
145
146	/* fatal */
147	{ 0xc1,	"aborted due to system command or reconfiguration" },
148	{ 0xc4,	"aborted" },
149	{ 0xc5,	"access error" },
150	{ 0xc6,	"access violation" },
151	{ 0xc7,	"device failure" },	/* high byte may be port # */
152	{ 0xc8,	"controller error" },
153	{ 0xc9,	"timed out" },
154	{ 0xcb,	"invalid unit number" },
155	{ 0xcf,	"unit not available" },
156	{ 0xd2,	"undefined opcode" },
157	{ 0xdb,	"request incompatible with unit" },
158	{ 0xdc,	"invalid request" },
159	{ 0xff,	"firmware error, reset requested" },
160
161	{ 0,	NULL }
162};
163
164const struct twe_code_table twe_table_unitstate[] = {
165	{ TWE_PARAM_UNITSTATUS_Normal,		"Normal" },
166	{ TWE_PARAM_UNITSTATUS_Initialising,	"Initializing" },
167	{ TWE_PARAM_UNITSTATUS_Degraded,	"Degraded" },
168	{ TWE_PARAM_UNITSTATUS_Rebuilding,	"Rebuilding" },
169	{ TWE_PARAM_UNITSTATUS_Verifying,	"Verifying" },
170	{ TWE_PARAM_UNITSTATUS_Corrupt,		"Corrupt" },
171	{ TWE_PARAM_UNITSTATUS_Missing,		"Missing" },
172
173	{ 0,					NULL }
174};
175
176const struct twe_code_table twe_table_unittype[] = {
177	/* array descriptor configuration */
178	{ TWE_AD_CONFIG_RAID0,			"RAID0" },
179	{ TWE_AD_CONFIG_RAID1,			"RAID1" },
180	{ TWE_AD_CONFIG_TwinStor,		"TwinStor" },
181	{ TWE_AD_CONFIG_RAID5,			"RAID5" },
182	{ TWE_AD_CONFIG_RAID10,			"RAID10" },
183	{ TWE_UD_CONFIG_JBOD,			"JBOD" },
184
185	{ 0,					NULL }
186};
187
188const struct twe_code_table twe_table_stripedepth[] = {
189	{ TWE_AD_STRIPE_4k,			"4K" },
190	{ TWE_AD_STRIPE_8k,			"8K" },
191	{ TWE_AD_STRIPE_16k,			"16K" },
192	{ TWE_AD_STRIPE_32k,			"32K" },
193	{ TWE_AD_STRIPE_64k,			"64K" },
194	{ TWE_AD_STRIPE_128k,			"128K" },
195	{ TWE_AD_STRIPE_256k,			"256K" },
196	{ TWE_AD_STRIPE_512k,			"512K" },
197	{ TWE_AD_STRIPE_1024k,			"1024K" },
198
199	{ 0,					NULL }
200};
201
202/*
203 * Asynchronous event notification messages are qualified:
204 *	a - not unit/port specific
205 *	u - unit specific
206 *	p - port specific
207 *
208 * They are further qualified with a severity:
209 *	E - LOG_EMERG
210 *	a - LOG_ALERT
211 *	c - LOG_CRIT
212 *	e - LOG_ERR
213 *	w - LOG_WARNING
214 *	n - LOG_NOTICE
215 *	i - LOG_INFO
216 *	d - LOG_DEBUG
217 *	blank - just use printf
218 */
219const struct twe_code_table twe_table_aen[] = {
220	{ 0x00,	"a  queue empty" },
221	{ 0x01,	"a  soft reset" },
222	{ 0x02,	"uc degraded mode" },
223	{ 0x03,	"aa controller error" },
224	{ 0x04,	"uE rebuild fail" },
225	{ 0x05,	"un rebuild done" },
226	{ 0x06,	"ue incomplete unit" },
227	{ 0x07,	"un initialization done" },
228	{ 0x08,	"uw unclean shutdown detected" },
229	{ 0x09,	"pe drive timeout" },
230	{ 0x0a,	"pc drive error" },
231	{ 0x0b,	"un rebuild started" },
232	{ 0x0c,	"un initialization started" },
233	{ 0x0d,	"ui logical unit deleted" },
234	{ 0x0f,	"pc SMART threshold exceeded" },
235	{ 0x15,	"a  table undefined" },	/* XXX: Not in FreeBSD's table */
236	{ 0x21,	"pe ATA UDMA downgrade" },
237	{ 0x22,	"pi ATA UDMA upgrade" },
238	{ 0x23,	"pw sector repair occurred" },
239	{ 0x24,	"aa SBUF integrity check failure" },
240	{ 0x25,	"pa lost cached write" },
241	{ 0x26,	"pa drive ECC error detected" },
242	{ 0x27,	"pe DCB checksum error" },
243	{ 0x28,	"pn DCB unsupported version" },
244	{ 0x29,	"ui verify started" },
245	{ 0x2a,	"ua verify failed" },
246	{ 0x2b,	"ui verify complete" },
247	{ 0x2c,	"pw overwrote bad sector during rebuild" },
248	{ 0x2d,	"pa encountered bad sector during rebuild" },
249	{ 0x2e,	"pe replacement drive too small" },
250	{ 0x2f,	"ue array not previously initialized" },
251	{ 0x30,	"p  drive not supported" },
252	{ 0xff,	"a  aen queue full" },
253
254	{ 0,	NULL },
255};
256
257const char *
258twe_describe_code(const struct twe_code_table *table, uint32_t code)
259{
260
261	for (; table->string != NULL; table++) {
262		if (table->code == code)
263			return (table->string);
264	}
265	return (NULL);
266}
267
268static inline u_int32_t
269twe_inl(struct twe_softc *sc, int off)
270{
271
272	bus_space_barrier(sc->sc_iot, sc->sc_ioh, off, 4,
273	    BUS_SPACE_BARRIER_WRITE | BUS_SPACE_BARRIER_READ);
274	return (bus_space_read_4(sc->sc_iot, sc->sc_ioh, off));
275}
276
277static inline void
278twe_outl(struct twe_softc *sc, int off, u_int32_t val)
279{
280
281	bus_space_write_4(sc->sc_iot, sc->sc_ioh, off, val);
282	bus_space_barrier(sc->sc_iot, sc->sc_ioh, off, 4,
283	    BUS_SPACE_BARRIER_WRITE);
284}
285
286/*
287 * Match a supported board.
288 */
289static int
290twe_match(device_t parent, cfdata_t cfdata, void *aux)
291{
292	struct pci_attach_args *pa;
293
294	pa = aux;
295
296	return (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_3WARE &&
297	    (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_3WARE_ESCALADE ||
298	    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_3WARE_ESCALADE_ASIC));
299}
300
301/*
302 * Attach a supported board.
303 *
304 * XXX This doesn't fail gracefully.
305 */
306static void
307twe_attach(device_t parent, device_t self, void *aux)
308{
309	struct pci_attach_args *pa;
310	struct twe_softc *sc;
311	pci_chipset_tag_t pc;
312	pci_intr_handle_t ih;
313	pcireg_t csr;
314	const char *intrstr;
315	int s, size, i, rv, rseg;
316	size_t max_segs, max_xfer;
317	bus_dma_segment_t seg;
318	const struct sysctlnode *node;
319	struct twe_cmd *tc;
320	struct twe_ccb *ccb;
321
322	sc = device_private(self);
323	pa = aux;
324	pc = pa->pa_pc;
325	sc->sc_dmat = pa->pa_dmat;
326	SIMPLEQ_INIT(&sc->sc_ccb_queue);
327	SLIST_INIT(&sc->sc_ccb_freelist);
328
329	aprint_naive(": RAID controller\n");
330	aprint_normal(": 3ware Escalade\n");
331
332
333	if (pci_mapreg_map(pa, PCI_CBIO, PCI_MAPREG_TYPE_IO, 0,
334	    &sc->sc_iot, &sc->sc_ioh, NULL, NULL)) {
335		aprint_error_dev(&sc->sc_dv, "can't map i/o space\n");
336		return;
337	}
338
339	/* Enable the device. */
340	csr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
341	pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
342	    csr | PCI_COMMAND_MASTER_ENABLE);
343
344	/* Map and establish the interrupt. */
345	if (pci_intr_map(pa, &ih)) {
346		aprint_error_dev(&sc->sc_dv, "can't map interrupt\n");
347		return;
348	}
349
350	intrstr = pci_intr_string(pc, ih);
351	sc->sc_ih = pci_intr_establish(pc, ih, IPL_BIO, twe_intr, sc);
352	if (sc->sc_ih == NULL) {
353		aprint_error_dev(&sc->sc_dv, "can't establish interrupt%s%s\n",
354			(intrstr) ? " at " : "",
355			(intrstr) ? intrstr : "");
356		return;
357	}
358
359	if (intrstr != NULL)
360		aprint_normal_dev(&sc->sc_dv, "interrupting at %s\n",
361			intrstr);
362
363	/*
364	 * Allocate and initialise the command blocks and CCBs.
365	 */
366	size = sizeof(struct twe_cmd) * TWE_MAX_QUEUECNT;
367
368	if ((rv = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &seg, 1,
369	    &rseg, BUS_DMA_NOWAIT)) != 0) {
370		aprint_error_dev(&sc->sc_dv, "unable to allocate commands, rv = %d\n", rv);
371		return;
372	}
373
374	if ((rv = bus_dmamem_map(sc->sc_dmat, &seg, rseg, size,
375	    (void **)&sc->sc_cmds,
376	    BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) {
377		aprint_error_dev(&sc->sc_dv, "unable to map commands, rv = %d\n", rv);
378		return;
379	}
380
381	if ((rv = bus_dmamap_create(sc->sc_dmat, size, size, 1, 0,
382	    BUS_DMA_NOWAIT, &sc->sc_dmamap)) != 0) {
383		aprint_error_dev(&sc->sc_dv, "unable to create command DMA map, rv = %d\n", rv);
384		return;
385	}
386
387	if ((rv = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap, sc->sc_cmds,
388	    size, NULL, BUS_DMA_NOWAIT)) != 0) {
389		aprint_error_dev(&sc->sc_dv, "unable to load command DMA map, rv = %d\n", rv);
390		return;
391	}
392
393	ccb = malloc(sizeof(*ccb) * TWE_MAX_QUEUECNT, M_DEVBUF, M_NOWAIT);
394	if (ccb == NULL) {
395		aprint_error_dev(&sc->sc_dv, "unable to allocate memory for ccbs\n");
396		return;
397	}
398
399	sc->sc_cmds_paddr = sc->sc_dmamap->dm_segs[0].ds_addr;
400	memset(sc->sc_cmds, 0, size);
401
402	sc->sc_ccbs = ccb;
403	tc = (struct twe_cmd *)sc->sc_cmds;
404	max_segs = twe_get_maxsegs();
405	max_xfer = twe_get_maxxfer(max_segs);
406
407	for (i = 0; i < TWE_MAX_QUEUECNT; i++, tc++, ccb++) {
408		ccb->ccb_cmd = tc;
409		ccb->ccb_cmdid = i;
410		ccb->ccb_flags = 0;
411		rv = bus_dmamap_create(sc->sc_dmat, max_xfer,
412		    max_segs, PAGE_SIZE, 0,
413		    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
414		    &ccb->ccb_dmamap_xfer);
415		if (rv != 0) {
416			aprint_error_dev(&sc->sc_dv, "can't create dmamap, rv = %d\n", rv);
417			return;
418		}
419
420		/* Save the first CCB for AEN retrieval. */
421		if (i != 0)
422			SLIST_INSERT_HEAD(&sc->sc_ccb_freelist, ccb,
423			    ccb_chain.slist);
424	}
425
426	/* Wait for the controller to become ready. */
427	if (twe_status_wait(sc, TWE_STS_MICROCONTROLLER_READY, 6)) {
428		aprint_error_dev(&sc->sc_dv, "microcontroller not ready\n");
429		return;
430	}
431
432	twe_outl(sc, TWE_REG_CTL, TWE_CTL_DISABLE_INTRS);
433
434	/* Reset the controller. */
435	s = splbio();
436	rv = twe_reset(sc);
437	splx(s);
438	if (rv) {
439		aprint_error_dev(&sc->sc_dv, "reset failed\n");
440		return;
441	}
442
443	/* Initialise connection with controller. */
444	twe_init_connection(sc);
445
446	twe_describe_controller(sc);
447
448	/* Find and attach RAID array units. */
449	sc->sc_nunits = 0;
450	for (i = 0; i < TWE_MAX_UNITS; i++)
451		(void) twe_add_unit(sc, i);
452
453	/* ...and finally, enable interrupts. */
454	twe_outl(sc, TWE_REG_CTL, TWE_CTL_CLEAR_ATTN_INTR |
455	    TWE_CTL_UNMASK_RESP_INTR |
456	    TWE_CTL_ENABLE_INTRS);
457
458	/* sysctl set-up for 3ware cli */
459	if (sysctl_createv(NULL, 0, NULL, NULL,
460				CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw",
461				NULL, NULL, 0, NULL, 0,
462				CTL_HW, CTL_EOL) != 0) {
463		aprint_error_dev(&sc->sc_dv, "could not create %s sysctl node\n",
464			"hw");
465		return;
466	}
467	if (sysctl_createv(NULL, 0, NULL, &node,
468				0, CTLTYPE_NODE, device_xname(&sc->sc_dv),
469				SYSCTL_DESCR("twe driver information"),
470				NULL, 0, NULL, 0,
471				CTL_HW, CTL_CREATE, CTL_EOL) != 0) {
472		aprint_error_dev(&sc->sc_dv, "could not create %s.%s sysctl node\n",
473			"hw", device_xname(&sc->sc_dv));
474		return;
475	}
476	if ((i = sysctl_createv(NULL, 0, NULL, NULL,
477				0, CTLTYPE_STRING, "driver_version",
478				SYSCTL_DESCR("twe0 driver version"),
479				NULL, 0, __UNCONST(&twever), 0,
480				CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL))
481				!= 0) {
482		aprint_error_dev(&sc->sc_dv, "could not create %s.%s.driver_version sysctl\n",
483			"hw", device_xname(&sc->sc_dv));
484		return;
485	}
486}
487
488void
489twe_register_callbacks(struct twe_softc *sc, int unit,
490    const struct twe_callbacks *tcb)
491{
492
493	sc->sc_units[unit].td_callbacks = tcb;
494}
495
496static void
497twe_recompute_openings(struct twe_softc *sc)
498{
499	struct twe_drive *td;
500	int unit, openings;
501
502	if (sc->sc_nunits != 0)
503		openings = (TWE_MAX_QUEUECNT - 1) / sc->sc_nunits;
504	else
505		openings = 0;
506	if (openings == sc->sc_openings)
507		return;
508	sc->sc_openings = openings;
509
510#ifdef TWE_DEBUG
511	printf("%s: %d array%s, %d openings per array\n",
512	    device_xname(&sc->sc_dv), sc->sc_nunits,
513	    sc->sc_nunits == 1 ? "" : "s", sc->sc_openings);
514#endif
515
516	for (unit = 0; unit < TWE_MAX_UNITS; unit++) {
517		td = &sc->sc_units[unit];
518		if (td->td_dev != NULL)
519			(*td->td_callbacks->tcb_openings)(td->td_dev,
520			    sc->sc_openings);
521	}
522}
523
524static int
525twe_add_unit(struct twe_softc *sc, int unit)
526{
527	struct twe_param *dtp, *atp;
528	struct twe_array_descriptor *ad;
529	struct twe_drive *td;
530	struct twe_attach_args twea;
531	uint32_t newsize;
532	int rv;
533	uint16_t dsize;
534	uint8_t newtype, newstripe;
535	int locs[TWECF_NLOCS];
536
537	if (unit < 0 || unit >= TWE_MAX_UNITS)
538		return (EINVAL);
539
540	/* Find attached units. */
541	rv = twe_param_get(sc, TWE_PARAM_UNITSUMMARY,
542	    TWE_PARAM_UNITSUMMARY_Status, TWE_MAX_UNITS, NULL, &dtp);
543	if (rv != 0) {
544		aprint_error_dev(&sc->sc_dv, "error %d fetching unit summary\n",
545		    rv);
546		return (rv);
547	}
548
549	/* For each detected unit, collect size and store in an array. */
550	td = &sc->sc_units[unit];
551
552	/* Unit present? */
553	if ((dtp->tp_data[unit] & TWE_PARAM_UNITSTATUS_Online) == 0) {
554		/*
555		 * XXX Should we check to see if a device has been
556		 * XXX attached at this index and detach it if it
557		 * XXX has?  ("rescan" semantics)
558		 */
559		rv = 0;
560		goto out;
561   	}
562
563	rv = twe_param_get_2(sc, TWE_PARAM_UNITINFO + unit,
564	    TWE_PARAM_UNITINFO_DescriptorSize, &dsize);
565	if (rv != 0) {
566		aprint_error_dev(&sc->sc_dv, "error %d fetching descriptor size "
567		    "for unit %d\n", rv, unit);
568		goto out;
569	}
570
571	rv = twe_param_get(sc, TWE_PARAM_UNITINFO + unit,
572	    TWE_PARAM_UNITINFO_Descriptor, dsize - 3, NULL, &atp);
573	if (rv != 0) {
574		aprint_error_dev(&sc->sc_dv, "error %d fetching array descriptor "
575		    "for unit %d\n", rv, unit);
576		goto out;
577	}
578
579	ad = (struct twe_array_descriptor *)atp->tp_data;
580	newtype = ad->configuration;
581	newstripe = ad->stripe_size;
582	free(atp, M_DEVBUF);
583
584	rv = twe_param_get_4(sc, TWE_PARAM_UNITINFO + unit,
585	    TWE_PARAM_UNITINFO_Capacity, &newsize);
586	if (rv != 0) {
587		aprint_error_dev(&sc->sc_dv,
588		    "error %d fetching capacity for unit %d\n",
589		    rv, unit);
590		goto out;
591	}
592
593	/*
594	 * Have a device, so we need to attach it.  If there is currently
595	 * something sitting at the slot, and the parameters are different,
596	 * then we detach the old device before attaching the new one.
597	 */
598	if (td->td_dev != NULL &&
599	    td->td_size == newsize &&
600	    td->td_type == newtype &&
601	    td->td_stripe == newstripe) {
602		/* Same as the old device; just keep using it. */
603		rv = 0;
604		goto out;
605	} else if (td->td_dev != NULL) {
606		/* Detach the old device first. */
607		(void) config_detach(td->td_dev, DETACH_FORCE);
608		td->td_dev = NULL;
609	} else if (td->td_size == 0)
610		sc->sc_nunits++;
611
612	/*
613	 * Committed to the new array unit; assign its parameters and
614	 * recompute the number of available command openings.
615	 */
616	td->td_size = newsize;
617	td->td_type = newtype;
618	td->td_stripe = newstripe;
619	twe_recompute_openings(sc);
620
621	twea.twea_unit = unit;
622
623	locs[TWECF_UNIT] = unit;
624
625	td->td_dev = config_found_sm_loc(&sc->sc_dv, "twe", locs, &twea,
626					 twe_print, config_stdsubmatch);
627
628	rv = 0;
629 out:
630	free(dtp, M_DEVBUF);
631	return (rv);
632}
633
634static int
635twe_del_unit(struct twe_softc *sc, int unit)
636{
637	struct twe_drive *td;
638
639	if (unit < 0 || unit >= TWE_MAX_UNITS)
640		return (EINVAL);
641
642	td = &sc->sc_units[unit];
643	if (td->td_size != 0)
644		sc->sc_nunits--;
645	td->td_size = 0;
646	td->td_type = 0;
647	td->td_stripe = 0;
648	if (td->td_dev != NULL) {
649		(void) config_detach(td->td_dev, DETACH_FORCE);
650		td->td_dev = NULL;
651	}
652	twe_recompute_openings(sc);
653	return (0);
654}
655
656/*
657 * Reset the controller.
658 * MUST BE CALLED AT splbio()!
659 */
660static int
661twe_reset(struct twe_softc *sc)
662{
663	uint16_t aen;
664	u_int status;
665	volatile u_int32_t junk;
666	int got, rv;
667
668	/* Issue a soft reset. */
669	twe_outl(sc, TWE_REG_CTL, TWE_CTL_ISSUE_SOFT_RESET |
670	    TWE_CTL_CLEAR_HOST_INTR |
671	    TWE_CTL_CLEAR_ATTN_INTR |
672	    TWE_CTL_MASK_CMD_INTR |
673	    TWE_CTL_MASK_RESP_INTR |
674	    TWE_CTL_CLEAR_ERROR_STS |
675	    TWE_CTL_DISABLE_INTRS);
676
677	/* Wait for attention... */
678	if (twe_status_wait(sc, TWE_STS_ATTN_INTR, 30)) {
679		aprint_error_dev(&sc->sc_dv, "timeout waiting for attention interrupt\n");
680		return (-1);
681	}
682
683	/* ...and ACK it. */
684	twe_outl(sc, TWE_REG_CTL, TWE_CTL_CLEAR_ATTN_INTR);
685
686	/*
687	 * Pull AENs out of the controller; look for a soft reset AEN.
688	 * Open code this, since we want to detect reset even if the
689	 * queue for management tools is full.
690	 *
691	 * Note that since:
692	 *	- interrupts are blocked
693	 *	- we have reset the controller
694	 *	- acknowledged the pending ATTENTION
695	 * that there is no way a pending asynchronous AEN fetch would
696	 * finish, so clear the flag.
697	 */
698	sc->sc_flags &= ~TWEF_AEN;
699	for (got = 0;;) {
700		rv = twe_aen_get(sc, &aen);
701		if (rv != 0)
702			printf("%s: error %d while draining event queue\n",
703			    device_xname(&sc->sc_dv), rv);
704		if (TWE_AEN_CODE(aen) == TWE_AEN_QUEUE_EMPTY)
705			break;
706		if (TWE_AEN_CODE(aen) == TWE_AEN_SOFT_RESET)
707			got = 1;
708		twe_aen_enqueue(sc, aen, 1);
709	}
710
711	if (!got) {
712		printf("%s: reset not reported\n", device_xname(&sc->sc_dv));
713		return (-1);
714	}
715
716	/* Check controller status. */
717	status = twe_inl(sc, TWE_REG_STS);
718	if (twe_status_check(sc, status)) {
719		printf("%s: controller errors detected\n",
720		    device_xname(&sc->sc_dv));
721		return (-1);
722	}
723
724	/* Drain the response queue. */
725	for (;;) {
726		status = twe_inl(sc, TWE_REG_STS);
727		if (twe_status_check(sc, status) != 0) {
728			aprint_error_dev(&sc->sc_dv, "can't drain response queue\n");
729			return (-1);
730		}
731		if ((status & TWE_STS_RESP_QUEUE_EMPTY) != 0)
732			break;
733		junk = twe_inl(sc, TWE_REG_RESP_QUEUE);
734	}
735
736	return (0);
737}
738
739/*
740 * Print autoconfiguration message for a sub-device.
741 */
742static int
743twe_print(void *aux, const char *pnp)
744{
745	struct twe_attach_args *twea;
746
747	twea = aux;
748
749	if (pnp != NULL)
750		aprint_normal("block device at %s", pnp);
751	aprint_normal(" unit %d", twea->twea_unit);
752	return (UNCONF);
753}
754
755/*
756 * Interrupt service routine.
757 */
758static int
759twe_intr(void *arg)
760{
761	struct twe_softc *sc;
762	u_int status;
763	int caught, rv;
764
765	sc = arg;
766	caught = 0;
767	status = twe_inl(sc, TWE_REG_STS);
768	twe_status_check(sc, status);
769
770	/* Host interrupts - purpose unknown. */
771	if ((status & TWE_STS_HOST_INTR) != 0) {
772#ifdef DEBUG
773		printf("%s: host interrupt\n", device_xname(&sc->sc_dv));
774#endif
775		twe_outl(sc, TWE_REG_CTL, TWE_CTL_CLEAR_HOST_INTR);
776		caught = 1;
777	}
778
779	/*
780	 * Attention interrupts, signalled when a controller or child device
781	 * state change has occurred.
782	 */
783	if ((status & TWE_STS_ATTN_INTR) != 0) {
784		rv = twe_aen_get(sc, NULL);
785		if (rv != 0)
786			aprint_error_dev(&sc->sc_dv, "unable to retrieve AEN (%d)\n", rv);
787		else
788			twe_outl(sc, TWE_REG_CTL, TWE_CTL_CLEAR_ATTN_INTR);
789		caught = 1;
790	}
791
792	/*
793	 * Command interrupts, signalled when the controller can accept more
794	 * commands.  We don't use this; instead, we try to submit commands
795	 * when we receive them, and when other commands have completed.
796	 * Mask it so we don't get another one.
797	 */
798	if ((status & TWE_STS_CMD_INTR) != 0) {
799#ifdef DEBUG
800		printf("%s: command interrupt\n", device_xname(&sc->sc_dv));
801#endif
802		twe_outl(sc, TWE_REG_CTL, TWE_CTL_MASK_CMD_INTR);
803		caught = 1;
804	}
805
806	if ((status & TWE_STS_RESP_INTR) != 0) {
807		twe_poll(sc);
808		caught = 1;
809	}
810
811	return (caught);
812}
813
814/*
815 * Fetch an AEN.  Even though this is really like parameter
816 * retrieval, we handle this specially, because we issue this
817 * AEN retrieval command from interrupt context, and thus
818 * reserve a CCB for it to avoid resource shortage.
819 *
820 * XXX There are still potential resource shortages we could
821 * XXX encounter.  Consider pre-allocating all AEN-related
822 * XXX resources.
823 *
824 * MUST BE CALLED AT splbio()!
825 */
826static int
827twe_aen_get(struct twe_softc *sc, uint16_t *aenp)
828{
829	struct twe_ccb *ccb;
830	struct twe_cmd *tc;
831	struct twe_param *tp;
832	int rv;
833
834	/*
835	 * If we're already retrieving an AEN, just wait; another
836	 * retrieval will be chained after the current one completes.
837	 */
838	if (sc->sc_flags & TWEF_AEN) {
839		/*
840		 * It is a fatal software programming error to attempt
841		 * to fetch an AEN synchronously when an AEN fetch is
842		 * already pending.
843		 */
844		KASSERT(aenp == NULL);
845		return (0);
846	}
847
848	tp = malloc(TWE_SECTOR_SIZE, M_DEVBUF, M_NOWAIT);
849	if (tp == NULL)
850		return (ENOMEM);
851
852	ccb = twe_ccb_alloc(sc,
853	    TWE_CCB_AEN | TWE_CCB_DATA_IN | TWE_CCB_DATA_OUT);
854	KASSERT(ccb != NULL);
855
856	ccb->ccb_data = tp;
857	ccb->ccb_datasize = TWE_SECTOR_SIZE;
858	ccb->ccb_tx.tx_handler = (aenp == NULL) ? twe_aen_handler : NULL;
859	ccb->ccb_tx.tx_context = tp;
860	ccb->ccb_tx.tx_dv = &sc->sc_dv;
861
862	tc = ccb->ccb_cmd;
863	tc->tc_size = 2;
864	tc->tc_opcode = TWE_OP_GET_PARAM | (tc->tc_size << 5);
865	tc->tc_unit = 0;
866	tc->tc_count = htole16(1);
867
868	/* Fill in the outbound parameter data. */
869	tp->tp_table_id = htole16(TWE_PARAM_AEN);
870	tp->tp_param_id = TWE_PARAM_AEN_UnitCode;
871	tp->tp_param_size = 2;
872
873	/* Map the transfer. */
874	if ((rv = twe_ccb_map(sc, ccb)) != 0) {
875		twe_ccb_free(sc, ccb);
876		goto done;
877	}
878
879	/* Enqueue the command and wait. */
880	if (aenp != NULL) {
881		rv = twe_ccb_poll(sc, ccb, 5);
882		twe_ccb_unmap(sc, ccb);
883		twe_ccb_free(sc, ccb);
884		if (rv == 0)
885			*aenp = le16toh(*(uint16_t *)tp->tp_data);
886		free(tp, M_DEVBUF);
887	} else {
888		sc->sc_flags |= TWEF_AEN;
889		twe_ccb_enqueue(sc, ccb);
890		rv = 0;
891	}
892
893 done:
894	return (rv);
895}
896
897/*
898 * Handle an AEN returned by the controller.
899 * MUST BE CALLED AT splbio()!
900 */
901static void
902twe_aen_handler(struct twe_ccb *ccb, int error)
903{
904	struct twe_softc *sc;
905	struct twe_param *tp;
906	uint16_t aen;
907	int rv;
908
909	sc = device_private(ccb->ccb_tx.tx_dv);
910	tp = ccb->ccb_tx.tx_context;
911	twe_ccb_unmap(sc, ccb);
912
913	sc->sc_flags &= ~TWEF_AEN;
914
915	if (error) {
916		aprint_error_dev(&sc->sc_dv, "error retrieving AEN\n");
917		aen = TWE_AEN_QUEUE_EMPTY;
918	} else
919		aen = le16toh(*(u_int16_t *)tp->tp_data);
920	free(tp, M_DEVBUF);
921	twe_ccb_free(sc, ccb);
922
923	if (TWE_AEN_CODE(aen) == TWE_AEN_QUEUE_EMPTY) {
924		twe_outl(sc, TWE_REG_CTL, TWE_CTL_CLEAR_ATTN_INTR);
925		return;
926	}
927
928	twe_aen_enqueue(sc, aen, 0);
929
930	/*
931	 * Chain another retrieval in case interrupts have been
932	 * coalesced.
933	 */
934	rv = twe_aen_get(sc, NULL);
935	if (rv != 0)
936		aprint_error_dev(&sc->sc_dv, "unable to retrieve AEN (%d)\n", rv);
937}
938
939static void
940twe_aen_enqueue(struct twe_softc *sc, uint16_t aen, int quiet)
941{
942	const char *str, *msg;
943	int s, next, nextnext, level;
944
945	/*
946	 * First report the AEN on the console.  Maybe.
947	 */
948	if (! quiet) {
949		str = twe_describe_code(twe_table_aen, TWE_AEN_CODE(aen));
950		if (str == NULL) {
951			aprint_error_dev(&sc->sc_dv, "unknown AEN 0x%04x\n", aen);
952		} else {
953			msg = str + 3;
954			switch (str[1]) {
955			case 'E':	level = LOG_EMERG; break;
956			case 'a':	level = LOG_ALERT; break;
957			case 'c':	level = LOG_CRIT; break;
958			case 'e':	level = LOG_ERR; break;
959			case 'w':	level = LOG_WARNING; break;
960			case 'n':	level = LOG_NOTICE; break;
961			case 'i':	level = LOG_INFO; break;
962			case 'd':	level = LOG_DEBUG; break;
963			default:
964				/* Don't use syslog. */
965				level = -1;
966			}
967
968			if (level < 0) {
969				switch (str[0]) {
970				case 'u':
971				case 'p':
972					printf("%s: %s %d: %s\n",
973					    device_xname(&sc->sc_dv),
974					    str[0] == 'u' ? "unit" : "port",
975					    TWE_AEN_UNIT(aen), msg);
976					break;
977
978				default:
979					printf("%s: %s\n",
980					    device_xname(&sc->sc_dv), msg);
981				}
982			} else {
983				switch (str[0]) {
984				case 'u':
985				case 'p':
986					log(level, "%s: %s %d: %s\n",
987					    device_xname(&sc->sc_dv),
988					    str[0] == 'u' ? "unit" : "port",
989					    TWE_AEN_UNIT(aen), msg);
990					break;
991
992				default:
993					log(level, "%s: %s\n",
994					    device_xname(&sc->sc_dv), msg);
995				}
996			}
997		}
998	}
999
1000	/* Now enqueue the AEN for mangement tools. */
1001	s = splbio();
1002
1003	next = (sc->sc_aen_head + 1) % TWE_AEN_Q_LENGTH;
1004	nextnext = (sc->sc_aen_head + 2) % TWE_AEN_Q_LENGTH;
1005
1006	/*
1007	 * If this is the last free slot, then queue up a "queue
1008	 * full" message.
1009	 */
1010	if (nextnext == sc->sc_aen_tail)
1011		aen = TWE_AEN_QUEUE_FULL;
1012
1013	if (next != sc->sc_aen_tail) {
1014		sc->sc_aen_queue[sc->sc_aen_head] = aen;
1015		sc->sc_aen_head = next;
1016	}
1017
1018	if (sc->sc_flags & TWEF_AENQ_WAIT) {
1019		sc->sc_flags &= ~TWEF_AENQ_WAIT;
1020		wakeup(&sc->sc_aen_queue);
1021	}
1022
1023	splx(s);
1024}
1025
1026/* NOTE: Must be called at splbio(). */
1027static uint16_t
1028twe_aen_dequeue(struct twe_softc *sc)
1029{
1030	uint16_t aen;
1031
1032	if (sc->sc_aen_tail == sc->sc_aen_head)
1033		aen = TWE_AEN_QUEUE_EMPTY;
1034	else {
1035		aen = sc->sc_aen_queue[sc->sc_aen_tail];
1036		sc->sc_aen_tail = (sc->sc_aen_tail + 1) % TWE_AEN_Q_LENGTH;
1037	}
1038
1039	return (aen);
1040}
1041
1042/*
1043 * These are short-hand functions that execute TWE_OP_GET_PARAM to
1044 * fetch 1, 2, and 4 byte parameter values, respectively.
1045 */
1046int
1047twe_param_get_1(struct twe_softc *sc, int table_id, int param_id,
1048    uint8_t *valp)
1049{
1050	struct twe_param *tp;
1051	int rv;
1052
1053	rv = twe_param_get(sc, table_id, param_id, 1, NULL, &tp);
1054	if (rv != 0)
1055		return (rv);
1056	*valp = *(uint8_t *)tp->tp_data;
1057	free(tp, M_DEVBUF);
1058	return (0);
1059}
1060
1061int
1062twe_param_get_2(struct twe_softc *sc, int table_id, int param_id,
1063    uint16_t *valp)
1064{
1065	struct twe_param *tp;
1066	int rv;
1067
1068	rv = twe_param_get(sc, table_id, param_id, 2, NULL, &tp);
1069	if (rv != 0)
1070		return (rv);
1071	*valp = le16toh(*(uint16_t *)tp->tp_data);
1072	free(tp, M_DEVBUF);
1073	return (0);
1074}
1075
1076int
1077twe_param_get_4(struct twe_softc *sc, int table_id, int param_id,
1078    uint32_t *valp)
1079{
1080	struct twe_param *tp;
1081	int rv;
1082
1083	rv = twe_param_get(sc, table_id, param_id, 4, NULL, &tp);
1084	if (rv != 0)
1085		return (rv);
1086	*valp = le32toh(*(uint32_t *)tp->tp_data);
1087	free(tp, M_DEVBUF);
1088	return (0);
1089}
1090
1091/*
1092 * Execute a TWE_OP_GET_PARAM command.  If a callback function is provided,
1093 * it will be called with generated context when the command has completed.
1094 * If no callback is provided, the command will be executed synchronously
1095 * and a pointer to a buffer containing the data returned.
1096 *
1097 * The caller or callback is responsible for freeing the buffer.
1098 *
1099 * NOTE: We assume we can sleep here to wait for a CCB to become available.
1100 */
1101int
1102twe_param_get(struct twe_softc *sc, int table_id, int param_id, size_t size,
1103	      void (*func)(struct twe_ccb *, int), struct twe_param **pbuf)
1104{
1105	struct twe_ccb *ccb;
1106	struct twe_cmd *tc;
1107	struct twe_param *tp;
1108	int rv, s;
1109
1110	tp = malloc(TWE_SECTOR_SIZE, M_DEVBUF, M_NOWAIT);
1111	if (tp == NULL)
1112		return ENOMEM;
1113
1114	ccb = twe_ccb_alloc_wait(sc, TWE_CCB_DATA_IN | TWE_CCB_DATA_OUT);
1115	KASSERT(ccb != NULL);
1116
1117	ccb->ccb_data = tp;
1118	ccb->ccb_datasize = TWE_SECTOR_SIZE;
1119	ccb->ccb_tx.tx_handler = func;
1120	ccb->ccb_tx.tx_context = tp;
1121	ccb->ccb_tx.tx_dv = &sc->sc_dv;
1122
1123	tc = ccb->ccb_cmd;
1124	tc->tc_size = 2;
1125	tc->tc_opcode = TWE_OP_GET_PARAM | (tc->tc_size << 5);
1126	tc->tc_unit = 0;
1127	tc->tc_count = htole16(1);
1128
1129	/* Fill in the outbound parameter data. */
1130	tp->tp_table_id = htole16(table_id);
1131	tp->tp_param_id = param_id;
1132	tp->tp_param_size = size;
1133
1134	/* Map the transfer. */
1135	if ((rv = twe_ccb_map(sc, ccb)) != 0) {
1136		twe_ccb_free(sc, ccb);
1137		goto done;
1138	}
1139
1140	/* Submit the command and either wait or let the callback handle it. */
1141	if (func == NULL) {
1142		s = splbio();
1143		rv = twe_ccb_poll(sc, ccb, 5);
1144		twe_ccb_unmap(sc, ccb);
1145		twe_ccb_free(sc, ccb);
1146		splx(s);
1147	} else {
1148#ifdef DEBUG
1149		if (pbuf != NULL)
1150			panic("both func and pbuf defined");
1151#endif
1152		twe_ccb_enqueue(sc, ccb);
1153		return 0;
1154	}
1155
1156done:
1157	if (pbuf == NULL || rv != 0)
1158		free(tp, M_DEVBUF);
1159	else if (pbuf != NULL && rv == 0)
1160		*pbuf = tp;
1161	return rv;
1162}
1163
1164/*
1165 * Execute a TWE_OP_SET_PARAM command.
1166 *
1167 * NOTE: We assume we can sleep here to wait for a CCB to become available.
1168 */
1169static int
1170twe_param_set(struct twe_softc *sc, int table_id, int param_id, size_t size,
1171	      void *sbuf)
1172{
1173	struct twe_ccb *ccb;
1174	struct twe_cmd *tc;
1175	struct twe_param *tp;
1176	int rv, s;
1177
1178	tp = malloc(TWE_SECTOR_SIZE, M_DEVBUF, M_NOWAIT);
1179	if (tp == NULL)
1180		return ENOMEM;
1181
1182	ccb = twe_ccb_alloc_wait(sc, TWE_CCB_DATA_IN | TWE_CCB_DATA_OUT);
1183	KASSERT(ccb != NULL);
1184
1185	ccb->ccb_data = tp;
1186	ccb->ccb_datasize = TWE_SECTOR_SIZE;
1187	ccb->ccb_tx.tx_handler = 0;
1188	ccb->ccb_tx.tx_context = tp;
1189	ccb->ccb_tx.tx_dv = &sc->sc_dv;
1190
1191	tc = ccb->ccb_cmd;
1192	tc->tc_size = 2;
1193	tc->tc_opcode = TWE_OP_SET_PARAM | (tc->tc_size << 5);
1194	tc->tc_unit = 0;
1195	tc->tc_count = htole16(1);
1196
1197	/* Fill in the outbound parameter data. */
1198	tp->tp_table_id = htole16(table_id);
1199	tp->tp_param_id = param_id;
1200	tp->tp_param_size = size;
1201	memcpy(tp->tp_data, sbuf, size);
1202
1203	/* Map the transfer. */
1204	if ((rv = twe_ccb_map(sc, ccb)) != 0) {
1205		twe_ccb_free(sc, ccb);
1206		goto done;
1207	}
1208
1209	/* Submit the command and wait. */
1210	s = splbio();
1211	rv = twe_ccb_poll(sc, ccb, 5);
1212	twe_ccb_unmap(sc, ccb);
1213	twe_ccb_free(sc, ccb);
1214	splx(s);
1215done:
1216	free(tp, M_DEVBUF);
1217	return (rv);
1218}
1219
1220/*
1221 * Execute a TWE_OP_INIT_CONNECTION command.  Return non-zero on error.
1222 * Must be called with interrupts blocked.
1223 */
1224static int
1225twe_init_connection(struct twe_softc *sc)
1226{
1227	struct twe_ccb *ccb;
1228	struct twe_cmd *tc;
1229	int rv;
1230
1231	if ((ccb = twe_ccb_alloc(sc, 0)) == NULL)
1232		return (EAGAIN);
1233
1234	/* Build the command. */
1235	tc = ccb->ccb_cmd;
1236	tc->tc_size = 3;
1237	tc->tc_opcode = TWE_OP_INIT_CONNECTION;
1238	tc->tc_unit = 0;
1239	tc->tc_count = htole16(TWE_MAX_CMDS);
1240	tc->tc_args.init_connection.response_queue_pointer = 0;
1241
1242	/* Submit the command for immediate execution. */
1243	rv = twe_ccb_poll(sc, ccb, 5);
1244	twe_ccb_free(sc, ccb);
1245	return (rv);
1246}
1247
1248/*
1249 * Poll the controller for completed commands.  Must be called with
1250 * interrupts blocked.
1251 */
1252static void
1253twe_poll(struct twe_softc *sc)
1254{
1255	struct twe_ccb *ccb;
1256	int found;
1257	u_int status, cmdid;
1258
1259	found = 0;
1260
1261	for (;;) {
1262		status = twe_inl(sc, TWE_REG_STS);
1263		twe_status_check(sc, status);
1264
1265		if ((status & TWE_STS_RESP_QUEUE_EMPTY))
1266			break;
1267
1268		found = 1;
1269		cmdid = twe_inl(sc, TWE_REG_RESP_QUEUE);
1270		cmdid = (cmdid & TWE_RESP_MASK) >> TWE_RESP_SHIFT;
1271		if (cmdid >= TWE_MAX_QUEUECNT) {
1272			aprint_error_dev(&sc->sc_dv, "bad cmdid %d\n", cmdid);
1273			continue;
1274		}
1275
1276		ccb = sc->sc_ccbs + cmdid;
1277		if ((ccb->ccb_flags & TWE_CCB_ACTIVE) == 0) {
1278			printf("%s: CCB for cmdid %d not active\n",
1279			    device_xname(&sc->sc_dv), cmdid);
1280			continue;
1281		}
1282		ccb->ccb_flags ^= TWE_CCB_COMPLETE | TWE_CCB_ACTIVE;
1283
1284		bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap,
1285		    (char *)ccb->ccb_cmd - (char *)sc->sc_cmds,
1286		    sizeof(struct twe_cmd),
1287		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1288
1289		/* Pass notification to upper layers. */
1290		if (ccb->ccb_tx.tx_handler != NULL)
1291			(*ccb->ccb_tx.tx_handler)(ccb,
1292			    ccb->ccb_cmd->tc_status != 0 ? EIO : 0);
1293	}
1294
1295	/* If any commands have completed, run the software queue. */
1296	if (found)
1297		twe_ccb_enqueue(sc, NULL);
1298}
1299
1300/*
1301 * Wait for `status' to be set in the controller status register.  Return
1302 * zero if found, non-zero if the operation timed out.
1303 */
1304static int
1305twe_status_wait(struct twe_softc *sc, u_int32_t status, int timo)
1306{
1307
1308	for (timo *= 10; timo != 0; timo--) {
1309		if ((twe_inl(sc, TWE_REG_STS) & status) == status)
1310			break;
1311		delay(100000);
1312	}
1313
1314	return (timo == 0);
1315}
1316
1317/*
1318 * Clear a PCI parity error.
1319 */
1320static void
1321twe_clear_pci_parity_error(struct twe_softc *sc)
1322{
1323	bus_space_write_4(sc->sc_iot, sc->sc_ioh, 0x0, TWE_CTL_CLEAR_PARITY_ERROR);
1324
1325	//FreeBSD: pci_write_config(sc->twe_dev, PCIR_STATUS, TWE_PCI_CLEAR_PARITY_ERROR, 2);
1326}
1327
1328
1329/*
1330 * Clear a PCI abort.
1331 */
1332static void
1333twe_clear_pci_abort(struct twe_softc *sc)
1334{
1335	bus_space_write_4(sc->sc_iot, sc->sc_ioh, 0x0, TWE_CTL_CLEAR_PCI_ABORT);
1336
1337	//FreeBSD: pci_write_config(sc->twe_dev, PCIR_STATUS, TWE_PCI_CLEAR_PCI_ABORT, 2);
1338}
1339
1340/*
1341 * Complain if the status bits aren't what we expect.
1342 */
1343static int
1344twe_status_check(struct twe_softc *sc, u_int status)
1345{
1346	int rv;
1347
1348	rv = 0;
1349
1350	if ((status & TWE_STS_EXPECTED_BITS) != TWE_STS_EXPECTED_BITS) {
1351		aprint_error_dev(&sc->sc_dv, "missing status bits: 0x%08x\n",
1352		    status & ~TWE_STS_EXPECTED_BITS);
1353		rv = -1;
1354	}
1355
1356	if ((status & TWE_STS_UNEXPECTED_BITS) != 0) {
1357		aprint_error_dev(&sc->sc_dv, "unexpected status bits: 0x%08x\n",
1358		    status & TWE_STS_UNEXPECTED_BITS);
1359		rv = -1;
1360		if (status & TWE_STS_PCI_PARITY_ERROR) {
1361			aprint_error_dev(&sc->sc_dv, "PCI parity error: Reseat card, move card "
1362			       "or buggy device present.\n");
1363			twe_clear_pci_parity_error(sc);
1364		}
1365		if (status & TWE_STS_PCI_ABORT) {
1366			aprint_error_dev(&sc->sc_dv, "PCI abort, clearing.\n");
1367			twe_clear_pci_abort(sc);
1368		}
1369	}
1370
1371	return (rv);
1372}
1373
1374/*
1375 * Allocate and initialise a CCB.
1376 */
1377static inline void
1378twe_ccb_init(struct twe_softc *sc, struct twe_ccb *ccb, int flags)
1379{
1380	struct twe_cmd *tc;
1381
1382	ccb->ccb_tx.tx_handler = NULL;
1383	ccb->ccb_flags = flags;
1384	tc = ccb->ccb_cmd;
1385	tc->tc_status = 0;
1386	tc->tc_flags = 0;
1387	tc->tc_cmdid = ccb->ccb_cmdid;
1388}
1389
1390struct twe_ccb *
1391twe_ccb_alloc(struct twe_softc *sc, int flags)
1392{
1393	struct twe_ccb *ccb;
1394	int s;
1395
1396	s = splbio();
1397	if (__predict_false((flags & TWE_CCB_AEN) != 0)) {
1398		/* Use the reserved CCB. */
1399		ccb = sc->sc_ccbs;
1400	} else {
1401		/* Allocate a CCB and command block. */
1402		if (__predict_false((ccb =
1403				SLIST_FIRST(&sc->sc_ccb_freelist)) == NULL)) {
1404			splx(s);
1405			return (NULL);
1406		}
1407		SLIST_REMOVE_HEAD(&sc->sc_ccb_freelist, ccb_chain.slist);
1408	}
1409#ifdef DIAGNOSTIC
1410	if ((long)(ccb - sc->sc_ccbs) == 0 && (flags & TWE_CCB_AEN) == 0)
1411		panic("twe_ccb_alloc: got reserved CCB for non-AEN");
1412	if ((ccb->ccb_flags & TWE_CCB_ALLOCED) != 0)
1413		panic("twe_ccb_alloc: CCB %ld already allocated",
1414		    (long)(ccb - sc->sc_ccbs));
1415	flags |= TWE_CCB_ALLOCED;
1416#endif
1417	splx(s);
1418
1419	twe_ccb_init(sc, ccb, flags);
1420	return (ccb);
1421}
1422
1423struct twe_ccb *
1424twe_ccb_alloc_wait(struct twe_softc *sc, int flags)
1425{
1426	struct twe_ccb *ccb;
1427	int s;
1428
1429	KASSERT((flags & TWE_CCB_AEN) == 0);
1430
1431	s = splbio();
1432	while (__predict_false((ccb =
1433				SLIST_FIRST(&sc->sc_ccb_freelist)) == NULL)) {
1434		sc->sc_flags |= TWEF_WAIT_CCB;
1435		(void) tsleep(&sc->sc_ccb_freelist, PRIBIO, "tweccb", 0);
1436	}
1437	SLIST_REMOVE_HEAD(&sc->sc_ccb_freelist, ccb_chain.slist);
1438#ifdef DIAGNOSTIC
1439	if ((ccb->ccb_flags & TWE_CCB_ALLOCED) != 0)
1440		panic("twe_ccb_alloc_wait: CCB %ld already allocated",
1441		    (long)(ccb - sc->sc_ccbs));
1442	flags |= TWE_CCB_ALLOCED;
1443#endif
1444	splx(s);
1445
1446	twe_ccb_init(sc, ccb, flags);
1447	return (ccb);
1448}
1449
1450/*
1451 * Free a CCB.
1452 */
1453void
1454twe_ccb_free(struct twe_softc *sc, struct twe_ccb *ccb)
1455{
1456	int s;
1457
1458	s = splbio();
1459	if ((ccb->ccb_flags & TWE_CCB_AEN) == 0) {
1460		SLIST_INSERT_HEAD(&sc->sc_ccb_freelist, ccb, ccb_chain.slist);
1461		if (__predict_false((sc->sc_flags & TWEF_WAIT_CCB) != 0)) {
1462			sc->sc_flags &= ~TWEF_WAIT_CCB;
1463			wakeup(&sc->sc_ccb_freelist);
1464		}
1465	}
1466	ccb->ccb_flags = 0;
1467	splx(s);
1468}
1469
1470/*
1471 * Map the specified CCB's command block and data buffer (if any) into
1472 * controller visible space.  Perform DMA synchronisation.
1473 */
1474int
1475twe_ccb_map(struct twe_softc *sc, struct twe_ccb *ccb)
1476{
1477	struct twe_cmd *tc;
1478	int flags, nsegs, i, s, rv, rc;
1479	void *data;
1480
1481	/*
1482	 * The data as a whole must be 512-byte aligned.
1483	 */
1484	if (((u_long)ccb->ccb_data & (TWE_ALIGNMENT - 1)) != 0) {
1485		s = splvm();
1486		/* XXX */
1487		rc = uvm_km_kmem_alloc(kmem_va_arena,
1488		    ccb->ccb_datasize, (VM_NOSLEEP | VM_INSTANTFIT),
1489		    (vmem_addr_t *)&ccb->ccb_abuf);
1490		splx(s);
1491		data = (void *)ccb->ccb_abuf;
1492		if ((ccb->ccb_flags & TWE_CCB_DATA_OUT) != 0)
1493			memcpy(data, ccb->ccb_data, ccb->ccb_datasize);
1494	} else {
1495		ccb->ccb_abuf = (vaddr_t)0;
1496		data = ccb->ccb_data;
1497	}
1498
1499	/*
1500	 * Map the data buffer into bus space and build the S/G list.
1501	 */
1502	rv = bus_dmamap_load(sc->sc_dmat, ccb->ccb_dmamap_xfer, data,
1503	    ccb->ccb_datasize, NULL, BUS_DMA_NOWAIT | BUS_DMA_STREAMING |
1504	    ((ccb->ccb_flags & TWE_CCB_DATA_IN) ?
1505	    BUS_DMA_READ : BUS_DMA_WRITE));
1506	if (rv != 0) {
1507		if (ccb->ccb_abuf != (vaddr_t)0) {
1508			s = splvm();
1509			/* XXX */
1510			uvm_km_kmem_free(kmem_va_arena, ccb->ccb_abuf,
1511			    ccb->ccb_datasize);
1512			splx(s);
1513		}
1514		return (rv);
1515	}
1516
1517	nsegs = ccb->ccb_dmamap_xfer->dm_nsegs;
1518	tc = ccb->ccb_cmd;
1519	tc->tc_size += 2 * nsegs;
1520
1521	/* The location of the S/G list is dependent upon command type. */
1522	switch (tc->tc_opcode >> 5) {
1523	case 2:
1524		for (i = 0; i < nsegs; i++) {
1525			tc->tc_args.param.sgl[i].tsg_address =
1526			    htole32(ccb->ccb_dmamap_xfer->dm_segs[i].ds_addr);
1527			tc->tc_args.param.sgl[i].tsg_length =
1528			    htole32(ccb->ccb_dmamap_xfer->dm_segs[i].ds_len);
1529		}
1530		/* XXX Needed? */
1531		for (; i < TWE_SG_SIZE; i++) {
1532			tc->tc_args.param.sgl[i].tsg_address = 0;
1533			tc->tc_args.param.sgl[i].tsg_length = 0;
1534		}
1535		break;
1536	case 3:
1537		for (i = 0; i < nsegs; i++) {
1538			tc->tc_args.io.sgl[i].tsg_address =
1539			    htole32(ccb->ccb_dmamap_xfer->dm_segs[i].ds_addr);
1540			tc->tc_args.io.sgl[i].tsg_length =
1541			    htole32(ccb->ccb_dmamap_xfer->dm_segs[i].ds_len);
1542		}
1543		/* XXX Needed? */
1544		for (; i < TWE_SG_SIZE; i++) {
1545			tc->tc_args.io.sgl[i].tsg_address = 0;
1546			tc->tc_args.io.sgl[i].tsg_length = 0;
1547		}
1548		break;
1549	default:
1550		/*
1551		 * In all likelihood, this is a command passed from
1552		 * management tools in userspace where no S/G list is
1553		 * necessary because no data is being passed.
1554		 */
1555		break;
1556	}
1557
1558	if ((ccb->ccb_flags & TWE_CCB_DATA_IN) != 0)
1559		flags = BUS_DMASYNC_PREREAD;
1560	else
1561		flags = 0;
1562	if ((ccb->ccb_flags & TWE_CCB_DATA_OUT) != 0)
1563		flags |= BUS_DMASYNC_PREWRITE;
1564
1565	bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap_xfer, 0,
1566	    ccb->ccb_datasize, flags);
1567	return (0);
1568}
1569
1570/*
1571 * Unmap the specified CCB's command block and data buffer (if any) and
1572 * perform DMA synchronisation.
1573 */
1574void
1575twe_ccb_unmap(struct twe_softc *sc, struct twe_ccb *ccb)
1576{
1577	int flags, s;
1578
1579	if ((ccb->ccb_flags & TWE_CCB_DATA_IN) != 0)
1580		flags = BUS_DMASYNC_POSTREAD;
1581	else
1582		flags = 0;
1583	if ((ccb->ccb_flags & TWE_CCB_DATA_OUT) != 0)
1584		flags |= BUS_DMASYNC_POSTWRITE;
1585
1586	bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap_xfer, 0,
1587	    ccb->ccb_datasize, flags);
1588	bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap_xfer);
1589
1590	if (ccb->ccb_abuf != (vaddr_t)0) {
1591		if ((ccb->ccb_flags & TWE_CCB_DATA_IN) != 0)
1592			memcpy(ccb->ccb_data, (void *)ccb->ccb_abuf,
1593			    ccb->ccb_datasize);
1594		s = splvm();
1595		/* XXX */
1596		uvm_km_kmem_free(kmem_va_arena, ccb->ccb_abuf,
1597		    ccb->ccb_datasize);
1598		splx(s);
1599	}
1600}
1601
1602/*
1603 * Submit a command to the controller and poll on completion.  Return
1604 * non-zero on timeout (but don't check status, as some command types don't
1605 * return status).  Must be called with interrupts blocked.
1606 */
1607int
1608twe_ccb_poll(struct twe_softc *sc, struct twe_ccb *ccb, int timo)
1609{
1610	int rv;
1611
1612	if ((rv = twe_ccb_submit(sc, ccb)) != 0)
1613		return (rv);
1614
1615	for (timo *= 1000; timo != 0; timo--) {
1616		twe_poll(sc);
1617		if ((ccb->ccb_flags & TWE_CCB_COMPLETE) != 0)
1618			break;
1619		DELAY(100);
1620	}
1621
1622	return (timo == 0);
1623}
1624
1625/*
1626 * If a CCB is specified, enqueue it.  Pull CCBs off the software queue in
1627 * the order that they were enqueued and try to submit their command blocks
1628 * to the controller for execution.
1629 */
1630void
1631twe_ccb_enqueue(struct twe_softc *sc, struct twe_ccb *ccb)
1632{
1633	int s;
1634
1635	s = splbio();
1636
1637	if (ccb != NULL)
1638		SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_queue, ccb, ccb_chain.simpleq);
1639
1640	while ((ccb = SIMPLEQ_FIRST(&sc->sc_ccb_queue)) != NULL) {
1641		if (twe_ccb_submit(sc, ccb))
1642			break;
1643		SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_queue, ccb_chain.simpleq);
1644	}
1645
1646	splx(s);
1647}
1648
1649/*
1650 * Submit the command block associated with the specified CCB to the
1651 * controller for execution.  Must be called with interrupts blocked.
1652 */
1653int
1654twe_ccb_submit(struct twe_softc *sc, struct twe_ccb *ccb)
1655{
1656	bus_addr_t pa;
1657	int rv;
1658	u_int status;
1659
1660	/* Check to see if we can post a command. */
1661	status = twe_inl(sc, TWE_REG_STS);
1662	twe_status_check(sc, status);
1663
1664	if ((status & TWE_STS_CMD_QUEUE_FULL) == 0) {
1665		bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap,
1666		    (char *)ccb->ccb_cmd - (char *)sc->sc_cmds,
1667		    sizeof(struct twe_cmd),
1668		    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
1669#ifdef DIAGNOSTIC
1670		if ((ccb->ccb_flags & TWE_CCB_ALLOCED) == 0)
1671			panic("%s: CCB %ld not ALLOCED\n",
1672			    device_xname(&sc->sc_dv), (long)(ccb - sc->sc_ccbs));
1673#endif
1674		ccb->ccb_flags |= TWE_CCB_ACTIVE;
1675		pa = sc->sc_cmds_paddr +
1676		    ccb->ccb_cmdid * sizeof(struct twe_cmd);
1677		twe_outl(sc, TWE_REG_CMD_QUEUE, (u_int32_t)pa);
1678		rv = 0;
1679	} else
1680		rv = EBUSY;
1681
1682	return (rv);
1683}
1684
1685
1686/*
1687 * Accept an open operation on the control device.
1688 */
1689static int
1690tweopen(dev_t dev, int flag, int mode, struct lwp *l)
1691{
1692	struct twe_softc *twe;
1693
1694	if ((twe = device_lookup_private(&twe_cd, minor(dev))) == NULL)
1695		return (ENXIO);
1696	if ((twe->sc_flags & TWEF_OPEN) != 0)
1697		return (EBUSY);
1698
1699	twe->sc_flags |= TWEF_OPEN;
1700	return (0);
1701}
1702
1703/*
1704 * Accept the last close on the control device.
1705 */
1706static int
1707tweclose(dev_t dev, int flag, int mode,
1708    struct lwp *l)
1709{
1710	struct twe_softc *twe;
1711
1712	twe = device_lookup_private(&twe_cd, minor(dev));
1713	twe->sc_flags &= ~TWEF_OPEN;
1714	return (0);
1715}
1716
1717void
1718twe_ccb_wait_handler(struct twe_ccb *ccb, int error)
1719{
1720
1721	/* Just wake up the sleeper. */
1722	wakeup(ccb);
1723}
1724
1725/*
1726 * Handle control operations.
1727 */
1728static int
1729tweioctl(dev_t dev, u_long cmd, void *data, int flag,
1730    struct lwp *l)
1731{
1732	struct twe_softc *twe;
1733	struct twe_ccb *ccb;
1734	struct twe_param *param;
1735	struct twe_usercommand *tu;
1736	struct twe_paramcommand *tp;
1737	struct twe_drivecommand *td;
1738	void *pdata = NULL;
1739	int s, error = 0;
1740	u_int8_t cmdid;
1741
1742	twe = device_lookup_private(&twe_cd, minor(dev));
1743	tu = (struct twe_usercommand *)data;
1744	tp = (struct twe_paramcommand *)data;
1745	td = (struct twe_drivecommand *)data;
1746
1747	/* This is intended to be compatible with the FreeBSD interface. */
1748	switch (cmd) {
1749	case TWEIO_COMMAND:
1750		error = kauth_authorize_device_passthru(l->l_cred, dev,
1751		    KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_ALL, data);
1752		if (error)
1753			return (error);
1754
1755		/* XXX mutex */
1756		if (tu->tu_size > 0) {
1757			/*
1758			 * XXX Handle > TWE_SECTOR_SIZE?  Let's see if
1759			 * it's really necessary, first.
1760			 */
1761			if (tu->tu_size > TWE_SECTOR_SIZE) {
1762#ifdef TWE_DEBUG
1763				printf("%s: TWEIO_COMMAND: tu_size = %zu\n",
1764				    device_xname(&twe->sc_dv), tu->tu_size);
1765#endif
1766				return EINVAL;
1767			}
1768			pdata = malloc(TWE_SECTOR_SIZE, M_DEVBUF, M_WAITOK);
1769			error = copyin(tu->tu_data, pdata, tu->tu_size);
1770			if (error != 0)
1771				goto done;
1772			ccb = twe_ccb_alloc_wait(twe,
1773			    TWE_CCB_DATA_IN | TWE_CCB_DATA_OUT);
1774			KASSERT(ccb != NULL);
1775			ccb->ccb_data = pdata;
1776			ccb->ccb_datasize = TWE_SECTOR_SIZE;
1777		} else {
1778			ccb = twe_ccb_alloc_wait(twe, 0);
1779			KASSERT(ccb != NULL);
1780		}
1781
1782		ccb->ccb_tx.tx_handler = twe_ccb_wait_handler;
1783		ccb->ccb_tx.tx_context = NULL;
1784		ccb->ccb_tx.tx_dv = &twe->sc_dv;
1785
1786		cmdid = ccb->ccb_cmdid;
1787		memcpy(ccb->ccb_cmd, &tu->tu_cmd, sizeof(struct twe_cmd));
1788		ccb->ccb_cmd->tc_cmdid = cmdid;
1789
1790		/* Map the transfer. */
1791		if ((error = twe_ccb_map(twe, ccb)) != 0) {
1792			twe_ccb_free(twe, ccb);
1793			goto done;
1794		}
1795
1796		/* Submit the command and wait up to 1 minute. */
1797		error = 0;
1798		twe_ccb_enqueue(twe, ccb);
1799		s = splbio();
1800		while ((ccb->ccb_flags & TWE_CCB_COMPLETE) == 0)
1801			if ((error = tsleep(ccb, PRIBIO, "tweioctl",
1802					    60 * hz)) != 0)
1803				break;
1804		splx(s);
1805
1806		/* Copy the command back to the ioctl argument. */
1807		memcpy(&tu->tu_cmd, ccb->ccb_cmd, sizeof(struct twe_cmd));
1808#ifdef TWE_DEBUG
1809		printf("%s: TWEIO_COMMAND: tc_opcode = 0x%02x, "
1810		    "tc_status = 0x%02x\n", device_xname(&twe->sc_dv),
1811		    tu->tu_cmd.tc_opcode, tu->tu_cmd.tc_status);
1812#endif
1813
1814		s = splbio();
1815		twe_ccb_free(twe, ccb);
1816		splx(s);
1817
1818		if (tu->tu_size > 0)
1819			error = copyout(pdata, tu->tu_data, tu->tu_size);
1820		goto done;
1821
1822	case TWEIO_STATS:
1823		return (ENOENT);
1824
1825	case TWEIO_AEN_POLL:
1826		s = splbio();
1827		*(u_int *)data = twe_aen_dequeue(twe);
1828		splx(s);
1829		return (0);
1830
1831	case TWEIO_AEN_WAIT:
1832		s = splbio();
1833		while ((*(u_int *)data =
1834		    twe_aen_dequeue(twe)) == TWE_AEN_QUEUE_EMPTY) {
1835			twe->sc_flags |= TWEF_AENQ_WAIT;
1836			error = tsleep(&twe->sc_aen_queue, PRIBIO | PCATCH,
1837			    "tweaen", 0);
1838			if (error == EINTR) {
1839				splx(s);
1840				return (error);
1841			}
1842		}
1843		splx(s);
1844		return (0);
1845
1846	case TWEIO_GET_PARAM:
1847		error = twe_param_get(twe, tp->tp_table_id, tp->tp_param_id,
1848		    tp->tp_size, 0, &param);
1849		if (error != 0)
1850			return (error);
1851		if (param->tp_param_size > tp->tp_size) {
1852			error = EFAULT;
1853			goto done;
1854		}
1855		error = copyout(param->tp_data, tp->tp_data,
1856		    param->tp_param_size);
1857		free(param, M_DEVBUF);
1858		goto done;
1859
1860	case TWEIO_SET_PARAM:
1861		pdata = malloc(tp->tp_size, M_DEVBUF, M_WAITOK);
1862		if ((error = copyin(tp->tp_data, pdata, tp->tp_size)) != 0)
1863			goto done;
1864		error = twe_param_set(twe, tp->tp_table_id, tp->tp_param_id,
1865		    tp->tp_size, pdata);
1866		goto done;
1867
1868	case TWEIO_RESET:
1869		s = splbio();
1870		twe_reset(twe);
1871		splx(s);
1872		return (0);
1873
1874	case TWEIO_ADD_UNIT:
1875		/* XXX mutex */
1876		return (twe_add_unit(twe, td->td_unit));
1877
1878	case TWEIO_DEL_UNIT:
1879		/* XXX mutex */
1880		return (twe_del_unit(twe, td->td_unit));
1881
1882	default:
1883		return EINVAL;
1884	}
1885done:
1886	if (pdata)
1887		free(pdata, M_DEVBUF);
1888	return error;
1889}
1890
1891const struct cdevsw twe_cdevsw = {
1892	tweopen, tweclose, noread, nowrite, tweioctl,
1893	    nostop, notty, nopoll, nommap, nokqfilter, D_OTHER,
1894};
1895
1896/*
1897 * Print some information about the controller
1898 */
1899static void
1900twe_describe_controller(struct twe_softc *sc)
1901{
1902	struct twe_param *p[6];
1903	int i, rv = 0;
1904	uint32_t dsize;
1905	uint8_t ports;
1906
1907	ports = 0;
1908
1909	/* get the port count */
1910	rv |= twe_param_get_1(sc, TWE_PARAM_CONTROLLER,
1911		TWE_PARAM_CONTROLLER_PortCount, &ports);
1912
1913	/* get version strings */
1914	rv |= twe_param_get(sc, TWE_PARAM_VERSION, TWE_PARAM_VERSION_Mon,
1915		16, NULL, &p[0]);
1916	rv |= twe_param_get(sc, TWE_PARAM_VERSION, TWE_PARAM_VERSION_FW,
1917		16, NULL, &p[1]);
1918	rv |= twe_param_get(sc, TWE_PARAM_VERSION, TWE_PARAM_VERSION_BIOS,
1919		16, NULL, &p[2]);
1920	rv |= twe_param_get(sc, TWE_PARAM_VERSION, TWE_PARAM_VERSION_PCB,
1921		8, NULL, &p[3]);
1922	rv |= twe_param_get(sc, TWE_PARAM_VERSION, TWE_PARAM_VERSION_ATA,
1923		8, NULL, &p[4]);
1924	rv |= twe_param_get(sc, TWE_PARAM_VERSION, TWE_PARAM_VERSION_PCI,
1925		8, NULL, &p[5]);
1926
1927	if (rv) {
1928		/* some error occurred */
1929		aprint_error_dev(&sc->sc_dv, "failed to fetch version information\n");
1930		return;
1931	}
1932
1933	aprint_normal_dev(&sc->sc_dv, "%d ports, Firmware %.16s, BIOS %.16s\n",
1934		ports, p[1]->tp_data, p[2]->tp_data);
1935
1936	aprint_verbose_dev(&sc->sc_dv, "Monitor %.16s, PCB %.8s, Achip %.8s, Pchip %.8s\n",
1937		p[0]->tp_data, p[3]->tp_data,
1938		p[4]->tp_data, p[5]->tp_data);
1939
1940	free(p[0], M_DEVBUF);
1941	free(p[1], M_DEVBUF);
1942	free(p[2], M_DEVBUF);
1943	free(p[3], M_DEVBUF);
1944	free(p[4], M_DEVBUF);
1945	free(p[5], M_DEVBUF);
1946
1947	rv = twe_param_get(sc, TWE_PARAM_DRIVESUMMARY,
1948	    TWE_PARAM_DRIVESUMMARY_Status, 16, NULL, &p[0]);
1949	if (rv) {
1950		aprint_error_dev(&sc->sc_dv, "failed to get drive status summary\n");
1951		return;
1952	}
1953	for (i = 0; i < ports; i++) {
1954		if (p[0]->tp_data[i] != TWE_PARAM_DRIVESTATUS_Present)
1955			continue;
1956		rv = twe_param_get_4(sc, TWE_PARAM_DRIVEINFO + i,
1957		    TWE_PARAM_DRIVEINFO_Size, &dsize);
1958		if (rv) {
1959			aprint_error_dev(&sc->sc_dv,
1960			    "unable to get drive size for port %d\n", i);
1961			continue;
1962		}
1963		rv = twe_param_get(sc, TWE_PARAM_DRIVEINFO + i,
1964		    TWE_PARAM_DRIVEINFO_Model, 40, NULL, &p[1]);
1965		if (rv) {
1966			aprint_error_dev(&sc->sc_dv,
1967			    "unable to get drive model for port %d\n", i);
1968			continue;
1969		}
1970		aprint_verbose_dev(&sc->sc_dv, "port %d: %.40s %d MB\n",
1971		    i, p[1]->tp_data, dsize / 2048);
1972		free(p[1], M_DEVBUF);
1973	}
1974	free(p[0], M_DEVBUF);
1975}
1976