1 /* $NetBSD: amr.c,v 1.52 2009/05/12 08:22:59 cegger Exp $ */
4 * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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.
33 * Copyright (c) 1999,2000 Michael Smith
34 * Copyright (c) 2000 BSDi
35 * All rights reserved.
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
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.
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
58 * from FreeBSD: amr_pci.c,v 1.5 2000/08/30 07:52:40 msmith Exp
59 * from FreeBSD: amr.c,v 1.16 2000/08/30 07:52:40 msmith Exp
63 * Driver for AMI RAID controllers.
66 #include <sys/cdefs.h>
67 __KERNEL_RCSID(0, "$NetBSD: amr.c,v 1.52 2009/05/12 08:22:59 cegger Exp $");
69 #include <sys/param.h>
70 #include <sys/systm.h>
71 #include <sys/kernel.h>
72 #include <sys/device.h>
73 #include <sys/queue.h>
76 #include <sys/malloc.h>
78 #include <sys/kthread.h>
79 #include <sys/kauth.h>
81 #include <uvm/uvm_extern.h>
83 #include <machine/endian.h>
86 #include <dev/pci/pcidevs.h>
87 #include <dev/pci/pcivar.h>
88 #include <dev/pci/amrreg.h>
89 #include <dev/pci/amrvar.h>
90 #include <dev/pci/amrio.h>
94 static void amr_attach(device_t
, device_t
, void *);
95 static void amr_ccb_dump(struct amr_softc
*, struct amr_ccb
*);
96 static void *amr_enquire(struct amr_softc
*, u_int8_t
, u_int8_t
, u_int8_t
,
98 static int amr_init(struct amr_softc
*, const char *,
99 struct pci_attach_args
*pa
);
100 static int amr_intr(void *);
101 static int amr_match(device_t
, cfdata_t
, void *);
102 static int amr_print(void *, const char *);
103 static void amr_shutdown(void *);
104 static void amr_teardown(struct amr_softc
*);
105 static void amr_thread(void *);
107 static int amr_quartz_get_work(struct amr_softc
*,
108 struct amr_mailbox_resp
*);
109 static int amr_quartz_submit(struct amr_softc
*, struct amr_ccb
*);
110 static int amr_std_get_work(struct amr_softc
*, struct amr_mailbox_resp
*);
111 static int amr_std_submit(struct amr_softc
*, struct amr_ccb
*);
113 static dev_type_open(amropen
);
114 static dev_type_close(amrclose
);
115 static dev_type_ioctl(amrioctl
);
117 CFATTACH_DECL(amr
, sizeof(struct amr_softc
),
118 amr_match
, amr_attach
, NULL
, NULL
);
120 const struct cdevsw amr_cdevsw
= {
121 amropen
, amrclose
, noread
, nowrite
, amrioctl
,
122 nostop
, notty
, nopoll
, nommap
, nokqfilter
, D_OTHER
125 extern struct cfdriver amr_cd
;
127 #define AT_QUARTZ 0x01 /* `Quartz' chipset */
128 #define AT_SIG 0x02 /* Check for signature */
130 static struct amr_pci_type
{
134 } const amr_pci_type
[] = {
135 { PCI_VENDOR_AMI
, PCI_PRODUCT_AMI_MEGARAID
, 0 },
136 { PCI_VENDOR_AMI
, PCI_PRODUCT_AMI_MEGARAID2
, 0 },
137 { PCI_VENDOR_AMI
, PCI_PRODUCT_AMI_MEGARAID3
, AT_QUARTZ
},
138 { PCI_VENDOR_SYMBIOS
, PCI_PRODUCT_AMI_MEGARAID3
, AT_QUARTZ
},
139 { PCI_VENDOR_INTEL
, PCI_PRODUCT_AMI_MEGARAID3
, AT_QUARTZ
| AT_SIG
},
140 { PCI_VENDOR_INTEL
, PCI_PRODUCT_SYMBIOS_MEGARAID_320X
, AT_QUARTZ
},
141 { PCI_VENDOR_INTEL
, PCI_PRODUCT_SYMBIOS_MEGARAID_320E
, AT_QUARTZ
},
142 { PCI_VENDOR_SYMBIOS
, PCI_PRODUCT_SYMBIOS_MEGARAID_300X
, AT_QUARTZ
},
143 { PCI_VENDOR_DELL
, PCI_PRODUCT_DELL_PERC_4DI
, AT_QUARTZ
},
144 { PCI_VENDOR_DELL
, PCI_PRODUCT_DELL_PERC_4DI_2
, AT_QUARTZ
},
145 { PCI_VENDOR_DELL
, PCI_PRODUCT_DELL_PERC_4ESI
, AT_QUARTZ
},
146 { PCI_VENDOR_SYMBIOS
, PCI_PRODUCT_SYMBIOS_PERC_4SC
, AT_QUARTZ
},
147 { PCI_VENDOR_SYMBIOS
, PCI_PRODUCT_SYMBIOS_MEGARAID_320X
, AT_QUARTZ
},
148 { PCI_VENDOR_SYMBIOS
, PCI_PRODUCT_SYMBIOS_MEGARAID_320E
, AT_QUARTZ
},
149 { PCI_VENDOR_SYMBIOS
, PCI_PRODUCT_SYMBIOS_MEGARAID_300X
, AT_QUARTZ
},
152 static struct amr_typestr
{
155 } const amr_typestr
[] = {
156 { "Series 431", AMR_SIG_431
},
157 { "Series 438", AMR_SIG_438
},
158 { "Series 466", AMR_SIG_466
},
159 { "Series 467", AMR_SIG_467
},
160 { "Series 490", AMR_SIG_490
},
161 { "Series 762", AMR_SIG_762
},
162 { "HP NetRAID (T5)", AMR_SIG_T5
},
163 { "HP NetRAID (T7)", AMR_SIG_T7
},
167 const char *ds_descr
;
169 } const amr_dstate
[] = {
179 static void *amr_sdh
;
181 static int amr_max_segs
;
184 static inline u_int8_t
185 amr_inb(struct amr_softc
*amr
, int off
)
188 bus_space_barrier(amr
->amr_iot
, amr
->amr_ioh
, off
, 1,
189 BUS_SPACE_BARRIER_WRITE
| BUS_SPACE_BARRIER_READ
);
190 return (bus_space_read_1(amr
->amr_iot
, amr
->amr_ioh
, off
));
193 static inline u_int32_t
194 amr_inl(struct amr_softc
*amr
, int off
)
197 bus_space_barrier(amr
->amr_iot
, amr
->amr_ioh
, off
, 4,
198 BUS_SPACE_BARRIER_WRITE
| BUS_SPACE_BARRIER_READ
);
199 return (bus_space_read_4(amr
->amr_iot
, amr
->amr_ioh
, off
));
203 amr_outb(struct amr_softc
*amr
, int off
, u_int8_t val
)
206 bus_space_write_1(amr
->amr_iot
, amr
->amr_ioh
, off
, val
);
207 bus_space_barrier(amr
->amr_iot
, amr
->amr_ioh
, off
, 1,
208 BUS_SPACE_BARRIER_WRITE
);
212 amr_outl(struct amr_softc
*amr
, int off
, u_int32_t val
)
215 bus_space_write_4(amr
->amr_iot
, amr
->amr_ioh
, off
, val
);
216 bus_space_barrier(amr
->amr_iot
, amr
->amr_ioh
, off
, 4,
217 BUS_SPACE_BARRIER_WRITE
);
221 * Match a supported device.
224 amr_match(device_t parent
, cfdata_t match
, void *aux
)
226 struct pci_attach_args
*pa
;
230 pa
= (struct pci_attach_args
*)aux
;
233 * Don't match the device if it's operating in I2O mode. In this
234 * case it should be handled by the `iop' driver.
236 if (PCI_CLASS(pa
->pa_class
) == PCI_CLASS_I2O
)
239 for (i
= 0; i
< sizeof(amr_pci_type
) / sizeof(amr_pci_type
[0]); i
++)
240 if (PCI_VENDOR(pa
->pa_id
) == amr_pci_type
[i
].apt_vendor
&&
241 PCI_PRODUCT(pa
->pa_id
) == amr_pci_type
[i
].apt_product
)
244 if (i
== sizeof(amr_pci_type
) / sizeof(amr_pci_type
[0]))
247 if ((amr_pci_type
[i
].apt_flags
& AT_SIG
) == 0)
250 s
= pci_conf_read(pa
->pa_pc
, pa
->pa_tag
, AMR_QUARTZ_SIG_REG
) & 0xffff;
251 return (s
== AMR_QUARTZ_SIG0
|| s
== AMR_QUARTZ_SIG1
);
255 * Attach a supported device.
258 amr_attach(device_t parent
, device_t self
, void *aux
)
260 struct pci_attach_args
*pa
;
261 struct amr_attach_args amra
;
262 const struct amr_pci_type
*apt
;
263 struct amr_softc
*amr
;
264 pci_chipset_tag_t pc
;
265 pci_intr_handle_t ih
;
268 int rseg
, i
, j
, size
, rv
, memreg
, ioreg
;
270 int locs
[AMRCF_NLOCS
];
272 aprint_naive(": RAID controller\n");
274 amr
= device_private(self
);
275 pa
= (struct pci_attach_args
*)aux
;
278 for (i
= 0; i
< sizeof(amr_pci_type
) / sizeof(amr_pci_type
[0]); i
++)
279 if (PCI_VENDOR(pa
->pa_id
) == amr_pci_type
[i
].apt_vendor
&&
280 PCI_PRODUCT(pa
->pa_id
) == amr_pci_type
[i
].apt_product
)
282 apt
= amr_pci_type
+ i
;
285 for (i
= 0x10; i
<= 0x14; i
+= 4) {
286 reg
= pci_conf_read(pc
, pa
->pa_tag
, i
);
287 switch (PCI_MAPREG_TYPE(reg
)) {
288 case PCI_MAPREG_TYPE_MEM
:
289 if (PCI_MAPREG_MEM_SIZE(reg
) != 0)
292 case PCI_MAPREG_TYPE_IO
:
293 if (PCI_MAPREG_IO_SIZE(reg
) != 0)
300 if (memreg
&& pci_mapreg_map(pa
, memreg
, PCI_MAPREG_TYPE_MEM
, 0,
301 &amr
->amr_iot
, &amr
->amr_ioh
, NULL
, &amr
->amr_ios
) == 0)
303 else if (ioreg
&& pci_mapreg_map(pa
, ioreg
, PCI_MAPREG_TYPE_IO
, 0,
304 &amr
->amr_iot
, &amr
->amr_ioh
, NULL
, &amr
->amr_ios
) == 0)
307 aprint_error("can't map control registers\n");
312 amr
->amr_flags
|= AMRF_PCI_REGS
;
313 amr
->amr_dmat
= pa
->pa_dmat
;
314 amr
->amr_pc
= pa
->pa_pc
;
316 /* Enable the device. */
317 reg
= pci_conf_read(pa
->pa_pc
, pa
->pa_tag
, PCI_COMMAND_STATUS_REG
);
318 pci_conf_write(pa
->pa_pc
, pa
->pa_tag
, PCI_COMMAND_STATUS_REG
,
319 reg
| PCI_COMMAND_MASTER_ENABLE
);
321 /* Map and establish the interrupt. */
322 if (pci_intr_map(pa
, &ih
)) {
323 aprint_error("can't map interrupt\n");
327 intrstr
= pci_intr_string(pc
, ih
);
328 amr
->amr_ih
= pci_intr_establish(pc
, ih
, IPL_BIO
, amr_intr
, amr
);
329 if (amr
->amr_ih
== NULL
) {
330 aprint_error("can't establish interrupt");
332 aprint_error(" at %s", intrstr
);
337 amr
->amr_flags
|= AMRF_PCI_INTR
;
340 * Allocate space for the mailbox and S/G lists. Some controllers
341 * don't like S/G lists to be located below 0x2000, so we allocate
342 * enough slop to enable us to compensate.
344 * The standard mailbox structure needs to be aligned on a 16-byte
345 * boundary. The 64-bit mailbox has one extra field, 4 bytes in
346 * size, which precedes the standard mailbox.
348 size
= AMR_SGL_SIZE
* AMR_MAX_CMDS
+ 0x2000;
349 amr
->amr_dmasize
= size
;
351 if ((rv
= bus_dmamem_alloc(amr
->amr_dmat
, size
, PAGE_SIZE
, 0,
352 &amr
->amr_dmaseg
, 1, &rseg
, BUS_DMA_NOWAIT
)) != 0) {
353 aprint_error_dev(&amr
->amr_dv
, "unable to allocate buffer, rv = %d\n",
358 amr
->amr_flags
|= AMRF_DMA_ALLOC
;
360 if ((rv
= bus_dmamem_map(amr
->amr_dmat
, &amr
->amr_dmaseg
, rseg
, size
,
361 (void **)&amr
->amr_mbox
,
362 BUS_DMA_NOWAIT
| BUS_DMA_COHERENT
)) != 0) {
363 aprint_error_dev(&amr
->amr_dv
, "unable to map buffer, rv = %d\n",
368 amr
->amr_flags
|= AMRF_DMA_MAP
;
370 if ((rv
= bus_dmamap_create(amr
->amr_dmat
, size
, 1, size
, 0,
371 BUS_DMA_NOWAIT
, &amr
->amr_dmamap
)) != 0) {
372 aprint_error_dev(&amr
->amr_dv
, "unable to create buffer DMA map, rv = %d\n",
377 amr
->amr_flags
|= AMRF_DMA_CREATE
;
379 if ((rv
= bus_dmamap_load(amr
->amr_dmat
, amr
->amr_dmamap
,
380 amr
->amr_mbox
, size
, NULL
, BUS_DMA_NOWAIT
)) != 0) {
381 aprint_error_dev(&amr
->amr_dv
, "unable to load buffer DMA map, rv = %d\n",
386 amr
->amr_flags
|= AMRF_DMA_LOAD
;
388 memset(amr
->amr_mbox
, 0, size
);
390 amr
->amr_mbox_paddr
= amr
->amr_dmamap
->dm_segs
[0].ds_addr
;
391 amr
->amr_sgls_paddr
= (amr
->amr_mbox_paddr
+ 0x1fff) & ~0x1fff;
392 amr
->amr_sgls
= (struct amr_sgentry
*)((char *)amr
->amr_mbox
+
393 amr
->amr_sgls_paddr
- amr
->amr_dmamap
->dm_segs
[0].ds_addr
);
396 * Allocate and initalise the command control blocks.
398 ac
= malloc(sizeof(*ac
) * AMR_MAX_CMDS
, M_DEVBUF
, M_NOWAIT
| M_ZERO
);
400 SLIST_INIT(&amr
->amr_ccb_freelist
);
401 TAILQ_INIT(&amr
->amr_ccb_active
);
402 amr
->amr_flags
|= AMRF_CCBS
;
404 if (amr_max_xfer
== 0) {
405 amr_max_xfer
= min(((AMR_MAX_SEGS
- 1) * PAGE_SIZE
), MAXPHYS
);
406 amr_max_segs
= (amr_max_xfer
+ (PAGE_SIZE
* 2) - 1) / PAGE_SIZE
;
409 for (i
= 0; i
< AMR_MAX_CMDS
; i
++, ac
++) {
410 rv
= bus_dmamap_create(amr
->amr_dmat
, amr_max_xfer
,
411 amr_max_segs
, amr_max_xfer
, 0,
412 BUS_DMA_NOWAIT
| BUS_DMA_ALLOCNOW
, &ac
->ac_xfer_map
);
417 amr_ccb_free(amr
, ac
);
419 if (i
!= AMR_MAX_CMDS
) {
420 aprint_error_dev(&amr
->amr_dv
, "memory exhausted\n");
426 * Take care of model-specific tasks.
428 if ((apt
->apt_flags
& AT_QUARTZ
) != 0) {
429 amr
->amr_submit
= amr_quartz_submit
;
430 amr
->amr_get_work
= amr_quartz_get_work
;
432 amr
->amr_submit
= amr_std_submit
;
433 amr
->amr_get_work
= amr_std_get_work
;
435 /* Notify the controller of the mailbox location. */
436 amr_outl(amr
, AMR_SREG_MBOX
, (u_int32_t
)amr
->amr_mbox_paddr
+ 16);
437 amr_outb(amr
, AMR_SREG_MBOX_ENABLE
, AMR_SMBOX_ENABLE_ADDR
);
439 /* Clear outstanding interrupts and enable interrupts. */
440 amr_outb(amr
, AMR_SREG_CMD
, AMR_SCMD_ACKINTR
);
441 amr_outb(amr
, AMR_SREG_TOGL
,
442 amr_inb(amr
, AMR_SREG_TOGL
) | AMR_STOGL_ENABLE
);
446 * Retrieve parameters, and tell the world about us.
448 amr
->amr_enqbuf
= malloc(AMR_ENQUIRY_BUFSIZE
, M_DEVBUF
, M_NOWAIT
);
449 amr
->amr_flags
|= AMRF_ENQBUF
;
450 amr
->amr_maxqueuecnt
= i
;
451 aprint_normal(": AMI RAID ");
452 if (amr_init(amr
, intrstr
, pa
) != 0) {
458 * Cap the maximum number of outstanding commands. AMI's Linux
459 * driver doesn't trust the controller's reported value, and lockups
460 * have been seen when we do.
462 amr
->amr_maxqueuecnt
= min(amr
->amr_maxqueuecnt
, AMR_MAX_CMDS
);
463 if (amr
->amr_maxqueuecnt
> i
)
464 amr
->amr_maxqueuecnt
= i
;
466 /* Set our `shutdownhook' before we start any device activity. */
468 amr_sdh
= shutdownhook_establish(amr_shutdown
, NULL
);
470 /* Attach sub-devices. */
471 for (j
= 0; j
< amr
->amr_numdrives
; j
++) {
472 if (amr
->amr_drive
[j
].al_size
== 0)
476 locs
[AMRCF_UNIT
] = j
;
478 amr
->amr_drive
[j
].al_dv
= config_found_sm_loc(&amr
->amr_dv
,
479 "amr", locs
, &amra
, amr_print
, config_stdsubmatch
);
482 SIMPLEQ_INIT(&amr
->amr_ccb_queue
);
484 /* XXX This doesn't work for newer boards yet. */
485 if ((apt
->apt_flags
& AT_QUARTZ
) == 0) {
486 rv
= kthread_create(PRI_NONE
, 0, NULL
, amr_thread
, amr
,
487 &amr
->amr_thread
, "%s", device_xname(&amr
->amr_dv
));
489 aprint_error_dev(&amr
->amr_dv
, "unable to create thread (%d)",
492 amr
->amr_flags
|= AMRF_THREAD
;
500 amr_teardown(struct amr_softc
*amr
)
507 if ((fl
& AMRF_THREAD
) != 0) {
508 amr
->amr_flags
|= AMRF_THREAD_EXIT
;
510 while ((amr
->amr_flags
& AMRF_THREAD_EXIT
) != 0)
511 tsleep(&amr
->amr_flags
, PWAIT
, "amrexit", 0);
513 if ((fl
& AMRF_CCBS
) != 0) {
514 SLIST_FOREACH(ac
, &amr
->amr_ccb_freelist
, ac_chain
.slist
) {
515 bus_dmamap_destroy(amr
->amr_dmat
, ac
->ac_xfer_map
);
517 free(amr
->amr_ccbs
, M_DEVBUF
);
519 if ((fl
& AMRF_ENQBUF
) != 0)
520 free(amr
->amr_enqbuf
, M_DEVBUF
);
521 if ((fl
& AMRF_DMA_LOAD
) != 0)
522 bus_dmamap_unload(amr
->amr_dmat
, amr
->amr_dmamap
);
523 if ((fl
& AMRF_DMA_MAP
) != 0)
524 bus_dmamem_unmap(amr
->amr_dmat
, (void *)amr
->amr_mbox
,
526 if ((fl
& AMRF_DMA_ALLOC
) != 0)
527 bus_dmamem_free(amr
->amr_dmat
, &amr
->amr_dmaseg
, 1);
528 if ((fl
& AMRF_DMA_CREATE
) != 0)
529 bus_dmamap_destroy(amr
->amr_dmat
, amr
->amr_dmamap
);
530 if ((fl
& AMRF_PCI_INTR
) != 0)
531 pci_intr_disestablish(amr
->amr_pc
, amr
->amr_ih
);
532 if ((fl
& AMRF_PCI_REGS
) != 0)
533 bus_space_unmap(amr
->amr_iot
, amr
->amr_ioh
, amr
->amr_ios
);
537 * Print autoconfiguration message for a sub-device.
540 amr_print(void *aux
, const char *pnp
)
542 struct amr_attach_args
*amra
;
544 amra
= (struct amr_attach_args
*)aux
;
547 aprint_normal("block device at %s", pnp
);
548 aprint_normal(" unit %d", amra
->amra_unit
);
553 * Retrieve operational parameters and describe the controller.
556 amr_init(struct amr_softc
*amr
, const char *intrstr
,
557 struct pci_attach_args
*pa
)
559 struct amr_adapter_info
*aa
;
560 struct amr_prodinfo
*ap
;
561 struct amr_enquiry
*ae
;
562 struct amr_enquiry3
*aex
;
568 * Try to get 40LD product info, which tells us what the card is
571 ap
= amr_enquire(amr
, AMR_CMD_CONFIG
, AMR_CONFIG_PRODUCT_INFO
, 0,
574 aprint_normal("<%.80s>\n", ap
->ap_product
);
576 aprint_normal_dev(&amr
->amr_dv
, "interrupting at %s\n",
578 aprint_normal_dev(&amr
->amr_dv
, "firmware %.16s, BIOS %.16s, %dMB RAM\n",
579 ap
->ap_firmware
, ap
->ap_bios
,
580 le16toh(ap
->ap_memsize
));
582 amr
->amr_maxqueuecnt
= ap
->ap_maxio
;
585 * Fetch and record state of logical drives.
587 aex
= amr_enquire(amr
, AMR_CMD_CONFIG
, AMR_CONFIG_ENQ3
,
588 AMR_CONFIG_ENQ3_SOLICITED_FULL
, amr
->amr_enqbuf
);
590 aprint_error_dev(&amr
->amr_dv
, "ENQUIRY3 failed\n");
594 if (aex
->ae_numldrives
> __arraycount(aex
->ae_drivestate
)) {
595 aprint_error_dev(&amr
->amr_dv
, "Inquiry returned more drives (%d)"
596 " than the array can handle (%zu)\n",
598 __arraycount(aex
->ae_drivestate
));
599 aex
->ae_numldrives
= __arraycount(aex
->ae_drivestate
);
601 if (aex
->ae_numldrives
> AMR_MAX_UNITS
) {
602 aprint_error_dev(&amr
->amr_dv
,
603 "adjust AMR_MAX_UNITS to %d (currently %d)"
606 amr
->amr_numdrives
= AMR_MAX_UNITS
;
608 amr
->amr_numdrives
= aex
->ae_numldrives
;
610 for (i
= 0; i
< amr
->amr_numdrives
; i
++) {
611 amr
->amr_drive
[i
].al_size
=
612 le32toh(aex
->ae_drivesize
[i
]);
613 amr
->amr_drive
[i
].al_state
= aex
->ae_drivestate
[i
];
614 amr
->amr_drive
[i
].al_properties
= aex
->ae_driveprop
[i
];
621 * Try 8LD extended ENQUIRY to get the controller signature. Once
622 * found, search for a product description.
624 ae
= amr_enquire(amr
, AMR_CMD_EXT_ENQUIRY2
, 0, 0, amr
->amr_enqbuf
);
627 sig
= le32toh(ae
->ae_signature
);
629 while (i
< sizeof(amr_typestr
) / sizeof(amr_typestr
[0])) {
630 if (amr_typestr
[i
].at_sig
== sig
)
634 if (i
== sizeof(amr_typestr
) / sizeof(amr_typestr
[0])) {
635 snprintf(sbuf
, sizeof(sbuf
),
636 "unknown ENQUIRY2 sig (0x%08x)", sig
);
639 prodstr
= amr_typestr
[i
].at_str
;
641 ae
= amr_enquire(amr
, AMR_CMD_ENQUIRY
, 0, 0, amr
->amr_enqbuf
);
643 aprint_error_dev(&amr
->amr_dv
, "unsupported controller\n");
647 switch (PCI_PRODUCT(pa
->pa_id
)) {
648 case PCI_PRODUCT_AMI_MEGARAID
:
649 prodstr
= "Series 428";
651 case PCI_PRODUCT_AMI_MEGARAID2
:
652 prodstr
= "Series 434";
655 snprintf(sbuf
, sizeof(sbuf
), "unknown PCI dev (0x%04x)",
656 PCI_PRODUCT(pa
->pa_id
));
663 * HP NetRaid controllers have a special encoding of the firmware
664 * and BIOS versions. The AMI version seems to have it as strings
665 * whereas the HP version does it with a leading uppercase character
666 * and two binary numbers.
668 aa
= &ae
->ae_adapter
;
670 if (aa
->aa_firmware
[2] >= 'A' && aa
->aa_firmware
[2] <= 'Z' &&
671 aa
->aa_firmware
[1] < ' ' && aa
->aa_firmware
[0] < ' ' &&
672 aa
->aa_bios
[2] >= 'A' && aa
->aa_bios
[2] <= 'Z' &&
673 aa
->aa_bios
[1] < ' ' && aa
->aa_bios
[0] < ' ') {
674 if (le32toh(ae
->ae_signature
) == AMR_SIG_438
) {
675 /* The AMI 438 is a NetRaid 3si in HP-land. */
676 prodstr
= "HP NetRaid 3si";
682 aprint_normal("<%s>\n", prodstr
);
684 aprint_normal_dev(&amr
->amr_dv
, "interrupting at %s\n",
688 aprint_normal_dev(&amr
->amr_dv
, "firmware <%c.%02d.%02d>, BIOS <%c.%02d.%02d>"
689 ", %dMB RAM\n", aa
->aa_firmware
[2],
690 aa
->aa_firmware
[1], aa
->aa_firmware
[0], aa
->aa_bios
[2],
691 aa
->aa_bios
[1], aa
->aa_bios
[0], aa
->aa_memorysize
);
693 aprint_normal_dev(&amr
->amr_dv
, "firmware <%.4s>, BIOS <%.4s>, %dMB RAM\n",
694 aa
->aa_firmware
, aa
->aa_bios
,
697 amr
->amr_maxqueuecnt
= aa
->aa_maxio
;
700 * Record state of logical drives.
702 if (ae
->ae_ldrv
.al_numdrives
> __arraycount(ae
->ae_ldrv
.al_size
)) {
703 aprint_error_dev(&amr
->amr_dv
, "Inquiry returned more drives (%d)"
704 " than the array can handle (%zu)\n",
705 ae
->ae_ldrv
.al_numdrives
,
706 __arraycount(ae
->ae_ldrv
.al_size
));
707 ae
->ae_ldrv
.al_numdrives
= __arraycount(ae
->ae_ldrv
.al_size
);
709 if (ae
->ae_ldrv
.al_numdrives
> AMR_MAX_UNITS
) {
710 aprint_error_dev(&amr
->amr_dv
, "adjust AMR_MAX_UNITS to %d (currently %d)\n",
711 ae
->ae_ldrv
.al_numdrives
,
713 amr
->amr_numdrives
= AMR_MAX_UNITS
;
715 amr
->amr_numdrives
= ae
->ae_ldrv
.al_numdrives
;
717 for (i
= 0; i
< amr
->amr_numdrives
; i
++) {
718 amr
->amr_drive
[i
].al_size
= le32toh(ae
->ae_ldrv
.al_size
[i
]);
719 amr
->amr_drive
[i
].al_state
= ae
->ae_ldrv
.al_state
[i
];
720 amr
->amr_drive
[i
].al_properties
= ae
->ae_ldrv
.al_properties
[i
];
727 * Flush the internal cache on each configured controller. Called at
731 amr_shutdown(void *cookie
)
733 extern struct cfdriver amr_cd
;
734 struct amr_softc
*amr
;
738 for (i
= 0; i
< amr_cd
.cd_ndevs
; i
++) {
739 if ((amr
= device_lookup_private(&amr_cd
, i
)) == NULL
)
742 if ((rv
= amr_ccb_alloc(amr
, &ac
)) == 0) {
743 ac
->ac_cmd
.mb_command
= AMR_CMD_FLUSH
;
745 rv
= amr_ccb_poll(amr
, ac
, 30000);
747 amr_ccb_free(amr
, ac
);
750 aprint_error_dev(&amr
->amr_dv
, "unable to flush cache (%d)\n", rv
);
755 * Interrupt service routine.
758 amr_intr(void *cookie
)
760 struct amr_softc
*amr
;
762 struct amr_mailbox_resp mbox
;
768 while ((*amr
->amr_get_work
)(amr
, &mbox
) == 0) {
769 /* Iterate over completed commands in this result. */
770 for (i
= 0; i
< mbox
.mb_nstatus
; i
++) {
771 idx
= mbox
.mb_completed
[i
] - 1;
772 ac
= amr
->amr_ccbs
+ idx
;
774 if (idx
>= amr
->amr_maxqueuecnt
) {
775 printf("%s: bad status (bogus ID: %u=%u)\n",
776 device_xname(&amr
->amr_dv
), i
, idx
);
780 if ((ac
->ac_flags
& AC_ACTIVE
) == 0) {
781 printf("%s: bad status (not active; 0x04%x)\n",
782 device_xname(&amr
->amr_dv
), ac
->ac_flags
);
786 ac
->ac_status
= mbox
.mb_status
;
787 ac
->ac_flags
= (ac
->ac_flags
& ~AC_ACTIVE
) |
789 TAILQ_REMOVE(&amr
->amr_ccb_active
, ac
, ac_chain
.tailq
);
791 if ((ac
->ac_flags
& AC_MOAN
) != 0)
792 printf("%s: ccb %d completed\n",
793 device_xname(&amr
->amr_dv
), ac
->ac_ident
);
795 /* Pass notification to upper layers. */
796 if (ac
->ac_handler
!= NULL
)
797 (*ac
->ac_handler
)(ac
);
805 amr_ccb_enqueue(amr
, NULL
);
814 amr_thread(void *cookie
)
816 struct amr_softc
*amr
;
818 struct amr_logdrive
*al
;
819 struct amr_enquiry
*ae
;
823 ae
= amr
->amr_enqbuf
;
826 tsleep(amr_thread
, PWAIT
, "amrwdog", AMR_WDOG_TICKS
);
828 if ((amr
->amr_flags
& AMRF_THREAD_EXIT
) != 0) {
829 amr
->amr_flags
^= AMRF_THREAD_EXIT
;
830 wakeup(&amr
->amr_flags
);
836 ac
= TAILQ_FIRST(&amr
->amr_ccb_active
);
838 if (ac
->ac_start_time
+ AMR_TIMEOUT
> time_uptime
)
840 if ((ac
->ac_flags
& AC_MOAN
) == 0) {
841 printf("%s: ccb %d timed out; mailbox:\n",
842 device_xname(&amr
->amr_dv
), ac
->ac_ident
);
843 amr_ccb_dump(amr
, ac
);
844 ac
->ac_flags
|= AC_MOAN
;
846 ac
= TAILQ_NEXT(ac
, ac_chain
.tailq
);
850 if ((rv
= amr_ccb_alloc(amr
, &ac
)) != 0) {
851 printf("%s: ccb_alloc failed (%d)\n",
852 device_xname(&amr
->amr_dv
), rv
);
856 ac
->ac_cmd
.mb_command
= AMR_CMD_ENQUIRY
;
858 rv
= amr_ccb_map(amr
, ac
, amr
->amr_enqbuf
,
859 AMR_ENQUIRY_BUFSIZE
, AC_XFER_IN
);
861 aprint_error_dev(&amr
->amr_dv
, "ccb_map failed (%d)\n",
863 amr_ccb_free(amr
, ac
);
867 rv
= amr_ccb_wait(amr
, ac
);
868 amr_ccb_unmap(amr
, ac
);
870 aprint_error_dev(&amr
->amr_dv
, "enquiry failed (st=%d)\n",
874 amr_ccb_free(amr
, ac
);
877 for (i
= 0; i
< __arraycount(ae
->ae_ldrv
.al_state
); i
++, al
++) {
878 if (al
->al_dv
== NULL
)
880 if (al
->al_state
== ae
->ae_ldrv
.al_state
[i
])
883 printf("%s: state changed: %s -> %s\n",
884 device_xname(al
->al_dv
),
885 amr_drive_state(al
->al_state
, NULL
),
886 amr_drive_state(ae
->ae_ldrv
.al_state
[i
], NULL
));
888 al
->al_state
= ae
->ae_ldrv
.al_state
[i
];
894 * Return a text description of a logical drive's current state.
897 amr_drive_state(int state
, int *happy
)
901 state
= AMR_DRV_CURSTATE(state
);
902 if (state
>= sizeof(amr_dstate
) / sizeof(amr_dstate
[0])) {
905 str
= "status unknown";
908 *happy
= amr_dstate
[state
].ds_happy
;
909 str
= amr_dstate
[state
].ds_descr
;
916 * Run a generic enquiry-style command.
919 amr_enquire(struct amr_softc
*amr
, u_int8_t cmd
, u_int8_t cmdsub
,
920 u_int8_t cmdqual
, void *sbuf
)
926 if (amr_ccb_alloc(amr
, &ac
) != 0)
929 /* Build the command proper. */
930 mb
= (u_int8_t
*)&ac
->ac_cmd
;
935 rv
= amr_ccb_map(amr
, ac
, sbuf
, AMR_ENQUIRY_BUFSIZE
, AC_XFER_IN
);
937 rv
= amr_ccb_poll(amr
, ac
, 2000);
938 amr_ccb_unmap(amr
, ac
);
940 amr_ccb_free(amr
, ac
);
942 return (rv
? NULL
: sbuf
);
946 * Allocate and initialise a CCB.
949 amr_ccb_alloc(struct amr_softc
*amr
, struct amr_ccb
**acp
)
954 if ((*acp
= SLIST_FIRST(&amr
->amr_ccb_freelist
)) == NULL
) {
958 SLIST_REMOVE_HEAD(&amr
->amr_ccb_freelist
, ac_chain
.slist
);
968 amr_ccb_free(struct amr_softc
*amr
, struct amr_ccb
*ac
)
972 memset(&ac
->ac_cmd
, 0, sizeof(ac
->ac_cmd
));
973 ac
->ac_cmd
.mb_ident
= ac
->ac_ident
+ 1;
974 ac
->ac_cmd
.mb_busy
= 1;
975 ac
->ac_handler
= NULL
;
979 SLIST_INSERT_HEAD(&amr
->amr_ccb_freelist
, ac
, ac_chain
.slist
);
984 * If a CCB is specified, enqueue it. Pull CCBs off the software queue in
985 * the order that they were enqueued and try to submit their command blocks
986 * to the controller for execution.
989 amr_ccb_enqueue(struct amr_softc
*amr
, struct amr_ccb
*ac
)
996 SIMPLEQ_INSERT_TAIL(&amr
->amr_ccb_queue
, ac
, ac_chain
.simpleq
);
998 while ((ac
= SIMPLEQ_FIRST(&amr
->amr_ccb_queue
)) != NULL
) {
999 if ((*amr
->amr_submit
)(amr
, ac
) != 0)
1001 SIMPLEQ_REMOVE_HEAD(&amr
->amr_ccb_queue
, ac_chain
.simpleq
);
1002 TAILQ_INSERT_TAIL(&amr
->amr_ccb_active
, ac
, ac_chain
.tailq
);
1009 * Map the specified CCB's data buffer onto the bus, and fill the
1010 * scatter-gather list.
1013 amr_ccb_map(struct amr_softc
*amr
, struct amr_ccb
*ac
, void *data
, int size
,
1016 struct amr_sgentry
*sge
;
1017 struct amr_mailbox_cmd
*mb
;
1018 int nsegs
, i
, rv
, sgloff
;
1022 xfer
= ac
->ac_xfer_map
;
1024 rv
= bus_dmamap_load(amr
->amr_dmat
, xfer
, data
, size
, NULL
,
1030 ac
->ac_xfer_size
= size
;
1031 ac
->ac_flags
|= (tflag
& (AC_XFER_OUT
| AC_XFER_IN
));
1032 sgloff
= AMR_SGL_SIZE
* ac
->ac_ident
;
1034 if (tflag
& AC_XFER_OUT
)
1035 dmaflag
|= BUS_DMASYNC_PREWRITE
;
1036 if (tflag
& AC_XFER_IN
)
1037 dmaflag
|= BUS_DMASYNC_PREREAD
;
1039 /* We don't need to use a scatter/gather list for just 1 segment. */
1040 nsegs
= xfer
->dm_nsegs
;
1043 mb
->mb_physaddr
= htole32(xfer
->dm_segs
[0].ds_addr
);
1044 ac
->ac_flags
|= AC_NOSGL
;
1046 mb
->mb_nsgelem
= nsegs
;
1047 mb
->mb_physaddr
= htole32(amr
->amr_sgls_paddr
+ sgloff
);
1049 sge
= (struct amr_sgentry
*)((char *)amr
->amr_sgls
+ sgloff
);
1050 for (i
= 0; i
< nsegs
; i
++, sge
++) {
1051 sge
->sge_addr
= htole32(xfer
->dm_segs
[i
].ds_addr
);
1052 sge
->sge_count
= htole32(xfer
->dm_segs
[i
].ds_len
);
1056 bus_dmamap_sync(amr
->amr_dmat
, xfer
, 0, ac
->ac_xfer_size
, dmaflag
);
1058 if ((ac
->ac_flags
& AC_NOSGL
) == 0)
1059 bus_dmamap_sync(amr
->amr_dmat
, amr
->amr_dmamap
, sgloff
,
1060 AMR_SGL_SIZE
, BUS_DMASYNC_PREWRITE
);
1066 * Unmap the specified CCB's data buffer.
1069 amr_ccb_unmap(struct amr_softc
*amr
, struct amr_ccb
*ac
)
1073 if (ac
->ac_flags
& AC_XFER_IN
)
1074 dmaflag
|= BUS_DMASYNC_POSTREAD
;
1075 if (ac
->ac_flags
& AC_XFER_OUT
)
1076 dmaflag
|= BUS_DMASYNC_POSTWRITE
;
1078 if ((ac
->ac_flags
& AC_NOSGL
) == 0)
1079 bus_dmamap_sync(amr
->amr_dmat
, amr
->amr_dmamap
,
1080 AMR_SGL_SIZE
* ac
->ac_ident
, AMR_SGL_SIZE
,
1081 BUS_DMASYNC_POSTWRITE
);
1082 bus_dmamap_sync(amr
->amr_dmat
, ac
->ac_xfer_map
, 0, ac
->ac_xfer_size
,
1084 bus_dmamap_unload(amr
->amr_dmat
, ac
->ac_xfer_map
);
1088 * Submit a command to the controller and poll on completion. Return
1089 * non-zero on timeout or error. Must be called with interrupts blocked.
1092 amr_ccb_poll(struct amr_softc
*amr
, struct amr_ccb
*ac
, int timo
)
1096 if ((rv
= (*amr
->amr_submit
)(amr
, ac
)) != 0)
1098 TAILQ_INSERT_TAIL(&amr
->amr_ccb_active
, ac
, ac_chain
.tailq
);
1100 for (timo
*= 10; timo
!= 0; timo
--) {
1102 if ((ac
->ac_flags
& AC_COMPLETE
) != 0)
1107 return (timo
== 0 || ac
->ac_status
!= 0 ? EIO
: 0);
1111 * Submit a command to the controller and sleep on completion. Return
1112 * non-zero on error.
1115 amr_ccb_wait(struct amr_softc
*amr
, struct amr_ccb
*ac
)
1120 amr_ccb_enqueue(amr
, ac
);
1121 tsleep(ac
, PRIBIO
, "amrcmd", 0);
1124 return (ac
->ac_status
!= 0 ? EIO
: 0);
1129 * Wait for the mailbox to become available.
1132 amr_mbox_wait(struct amr_softc
*amr
)
1136 for (timo
= 10000; timo
!= 0; timo
--) {
1137 bus_dmamap_sync(amr
->amr_dmat
, amr
->amr_dmamap
, 0,
1138 sizeof(struct amr_mailbox
), BUS_DMASYNC_POSTREAD
);
1139 if (amr
->amr_mbox
->mb_cmd
.mb_busy
== 0)
1145 printf("%s: controller wedged\n", device_xname(&amr
->amr_dv
));
1147 return (timo
!= 0 ? 0 : EAGAIN
);
1152 * Tell the controller that the mailbox contains a valid command. Must be
1153 * called with interrupts blocked.
1156 amr_quartz_submit(struct amr_softc
*amr
, struct amr_ccb
*ac
)
1160 amr
->amr_mbox
->mb_poll
= 0;
1161 amr
->amr_mbox
->mb_ack
= 0;
1162 bus_dmamap_sync(amr
->amr_dmat
, amr
->amr_dmamap
, 0,
1163 sizeof(struct amr_mailbox
), BUS_DMASYNC_PREWRITE
);
1164 bus_dmamap_sync(amr
->amr_dmat
, amr
->amr_dmamap
, 0,
1165 sizeof(struct amr_mailbox
), BUS_DMASYNC_POSTREAD
);
1166 if (amr
->amr_mbox
->mb_cmd
.mb_busy
!= 0)
1169 v
= amr_inl(amr
, AMR_QREG_IDB
);
1170 if ((v
& AMR_QIDB_SUBMIT
) != 0) {
1171 amr
->amr_mbox
->mb_cmd
.mb_busy
= 0;
1172 bus_dmamap_sync(amr
->amr_dmat
, amr
->amr_dmamap
, 0,
1173 sizeof(struct amr_mailbox
), BUS_DMASYNC_PREWRITE
);
1174 bus_dmamap_sync(amr
->amr_dmat
, amr
->amr_dmamap
, 0,
1175 sizeof(struct amr_mailbox
), BUS_DMASYNC_PREREAD
);
1179 amr
->amr_mbox
->mb_segment
= 0;
1180 memcpy(&amr
->amr_mbox
->mb_cmd
, &ac
->ac_cmd
, sizeof(ac
->ac_cmd
));
1181 bus_dmamap_sync(amr
->amr_dmat
, amr
->amr_dmamap
, 0,
1182 sizeof(struct amr_mailbox
), BUS_DMASYNC_PREWRITE
);
1184 ac
->ac_start_time
= time_uptime
;
1185 ac
->ac_flags
|= AC_ACTIVE
;
1186 amr_outl(amr
, AMR_QREG_IDB
,
1187 (amr
->amr_mbox_paddr
+ 16) | AMR_QIDB_SUBMIT
);
1192 amr_std_submit(struct amr_softc
*amr
, struct amr_ccb
*ac
)
1195 amr
->amr_mbox
->mb_poll
= 0;
1196 amr
->amr_mbox
->mb_ack
= 0;
1197 bus_dmamap_sync(amr
->amr_dmat
, amr
->amr_dmamap
, 0,
1198 sizeof(struct amr_mailbox
), BUS_DMASYNC_PREWRITE
);
1199 bus_dmamap_sync(amr
->amr_dmat
, amr
->amr_dmamap
, 0,
1200 sizeof(struct amr_mailbox
), BUS_DMASYNC_POSTREAD
);
1201 if (amr
->amr_mbox
->mb_cmd
.mb_busy
!= 0)
1204 if ((amr_inb(amr
, AMR_SREG_MBOX_BUSY
) & AMR_SMBOX_BUSY_FLAG
) != 0) {
1205 amr
->amr_mbox
->mb_cmd
.mb_busy
= 0;
1206 bus_dmamap_sync(amr
->amr_dmat
, amr
->amr_dmamap
, 0,
1207 sizeof(struct amr_mailbox
), BUS_DMASYNC_PREWRITE
);
1208 bus_dmamap_sync(amr
->amr_dmat
, amr
->amr_dmamap
, 0,
1209 sizeof(struct amr_mailbox
), BUS_DMASYNC_PREREAD
);
1213 amr
->amr_mbox
->mb_segment
= 0;
1214 memcpy(&amr
->amr_mbox
->mb_cmd
, &ac
->ac_cmd
, sizeof(ac
->ac_cmd
));
1215 bus_dmamap_sync(amr
->amr_dmat
, amr
->amr_dmamap
, 0,
1216 sizeof(struct amr_mailbox
), BUS_DMASYNC_PREWRITE
);
1218 ac
->ac_start_time
= time_uptime
;
1219 ac
->ac_flags
|= AC_ACTIVE
;
1220 amr_outb(amr
, AMR_SREG_CMD
, AMR_SCMD_POST
);
1225 * Claim any work that the controller has completed; acknowledge completion,
1226 * save details of the completion in (mbsave). Must be called with
1227 * interrupts blocked.
1230 amr_quartz_get_work(struct amr_softc
*amr
, struct amr_mailbox_resp
*mbsave
)
1233 /* Work waiting for us? */
1234 if (amr_inl(amr
, AMR_QREG_ODB
) != AMR_QODB_READY
)
1237 bus_dmamap_sync(amr
->amr_dmat
, amr
->amr_dmamap
, 0,
1238 sizeof(struct amr_mailbox
), BUS_DMASYNC_POSTREAD
);
1240 /* Save the mailbox, which contains a list of completed commands. */
1241 memcpy(mbsave
, &amr
->amr_mbox
->mb_resp
, sizeof(*mbsave
));
1243 bus_dmamap_sync(amr
->amr_dmat
, amr
->amr_dmamap
, 0,
1244 sizeof(struct amr_mailbox
), BUS_DMASYNC_PREREAD
);
1246 /* Ack the interrupt and mailbox transfer. */
1247 amr_outl(amr
, AMR_QREG_ODB
, AMR_QODB_READY
);
1248 amr_outl(amr
, AMR_QREG_IDB
, (amr
->amr_mbox_paddr
+16) | AMR_QIDB_ACK
);
1251 * This waits for the controller to notice that we've taken the
1252 * command from it. It's very inefficient, and we shouldn't do it,
1253 * but if we remove this code, we stop completing commands under
1256 * Peter J says we shouldn't do this. The documentation says we
1257 * should. Who is right?
1259 while ((amr_inl(amr
, AMR_QREG_IDB
) & AMR_QIDB_ACK
) != 0)
1266 amr_std_get_work(struct amr_softc
*amr
, struct amr_mailbox_resp
*mbsave
)
1270 /* Check for valid interrupt status. */
1271 if (((istat
= amr_inb(amr
, AMR_SREG_INTR
)) & AMR_SINTR_VALID
) == 0)
1274 /* Ack the interrupt. */
1275 amr_outb(amr
, AMR_SREG_INTR
, istat
);
1277 bus_dmamap_sync(amr
->amr_dmat
, amr
->amr_dmamap
, 0,
1278 sizeof(struct amr_mailbox
), BUS_DMASYNC_POSTREAD
);
1280 /* Save mailbox, which contains a list of completed commands. */
1281 memcpy(mbsave
, &amr
->amr_mbox
->mb_resp
, sizeof(*mbsave
));
1283 bus_dmamap_sync(amr
->amr_dmat
, amr
->amr_dmamap
, 0,
1284 sizeof(struct amr_mailbox
), BUS_DMASYNC_PREREAD
);
1286 /* Ack mailbox transfer. */
1287 amr_outb(amr
, AMR_SREG_CMD
, AMR_SCMD_ACKINTR
);
1293 amr_ccb_dump(struct amr_softc
*amr
, struct amr_ccb
*ac
)
1297 printf("%s: ", device_xname(&amr
->amr_dv
));
1298 for (i
= 0; i
< 4; i
++)
1299 printf("%08x ", ((u_int32_t
*)&ac
->ac_cmd
)[i
]);
1304 amropen(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
1306 struct amr_softc
*amr
;
1308 if ((amr
= device_lookup_private(&amr_cd
, minor(dev
))) == NULL
)
1310 if ((amr
->amr_flags
& AMRF_OPEN
) != 0)
1313 amr
->amr_flags
|= AMRF_OPEN
;
1318 amrclose(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
1320 struct amr_softc
*amr
;
1322 amr
= device_lookup_private(&amr_cd
, minor(dev
));
1323 amr
->amr_flags
&= ~AMRF_OPEN
;
1328 amrioctl(dev_t dev
, u_long cmd
, void *data
, int flag
,
1331 struct amr_softc
*amr
;
1332 struct amr_user_ioctl
*au
;
1334 struct amr_mailbox_ioctl
*mbi
;
1335 unsigned long au_length
;
1338 void *dp
= NULL
, *au_buffer
;
1340 amr
= device_lookup_private(&amr_cd
, minor(dev
));
1342 /* This should be compatible with the FreeBSD interface */
1345 case AMR_IO_VERSION
:
1346 *(int *)data
= AMR_IO_VERSION_NUMBER
;
1348 case AMR_IO_COMMAND
:
1349 error
= kauth_authorize_device_passthru(l
->l_cred
, dev
,
1350 KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_ALL
, data
);
1354 au
= (struct amr_user_ioctl
*)data
;
1355 au_cmd
= au
->au_cmd
;
1356 au_buffer
= au
->au_buffer
;
1357 au_length
= au
->au_length
;
1363 if (au_cmd
[0] == AMR_CMD_PASS
) {
1368 if (au_length
<= 0 || au_length
> MAXPHYS
|| au_cmd
[0] == 0x06)
1372 * allocate kernel memory for data, doing I/O directly to user
1373 * buffer isn't that easy.
1375 dp
= malloc(au_length
, M_DEVBUF
, M_WAITOK
|M_ZERO
);
1378 if ((error
= copyin(au_buffer
, dp
, au_length
)) != 0)
1381 /* direct command to controller */
1382 while (amr_ccb_alloc(amr
, &ac
) != 0) {
1383 error
= tsleep(NULL
, PRIBIO
| PCATCH
, "armmbx", hz
);
1388 mbi
= (struct amr_mailbox_ioctl
*)&ac
->ac_cmd
;
1389 mbi
->mb_command
= au_cmd
[0];
1390 mbi
->mb_channel
= au_cmd
[1];
1391 mbi
->mb_param
= au_cmd
[2];
1392 mbi
->mb_pad
[0] = au_cmd
[3];
1393 mbi
->mb_drive
= au_cmd
[4];
1394 error
= amr_ccb_map(amr
, ac
, dp
, (int)au_length
,
1395 AC_XFER_IN
| AC_XFER_OUT
);
1397 error
= amr_ccb_wait(amr
, ac
);
1398 amr_ccb_unmap(amr
, ac
);
1400 error
= copyout(dp
, au_buffer
, au_length
);
1403 amr_ccb_free(amr
, ac
);