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