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