1 /* $NetBSD: mly.c,v 1.42 2009/05/12 08:23:01 cegger Exp $ */
4 * Copyright (c) 2001 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Andrew Doran, Thor Lancelot Simon, and Eric Haszlakiewicz.
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) 2000, 2001 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: mly.c,v 1.8 2001/07/14 00:12:22 msmith Exp
62 * Driver for the Mylex AcceleRAID and eXtremeRAID family with v6 firmware.
66 * o Make mly->mly_btl a hash, then MLY_BTL_RESCAN becomes a SIMPLEQ.
67 * o Handle FC and multiple LUNs.
69 * o Fix transfer speed fudge.
72 #include <sys/cdefs.h>
73 __KERNEL_RCSID(0, "$NetBSD: mly.c,v 1.42 2009/05/12 08:23:01 cegger Exp $");
75 #include <sys/param.h>
76 #include <sys/systm.h>
77 #include <sys/device.h>
78 #include <sys/kernel.h>
79 #include <sys/queue.h>
81 #include <sys/endian.h>
83 #include <sys/malloc.h>
84 #include <sys/ioctl.h>
85 #include <sys/scsiio.h>
86 #include <sys/kthread.h>
87 #include <sys/kauth.h>
89 #include <uvm/uvm_extern.h>
93 #include <dev/scsipi/scsi_all.h>
94 #include <dev/scsipi/scsipi_all.h>
95 #include <dev/scsipi/scsiconf.h>
97 #include <dev/pci/pcireg.h>
98 #include <dev/pci/pcivar.h>
99 #include <dev/pci/pcidevs.h>
101 #include <dev/pci/mlyreg.h>
102 #include <dev/pci/mlyio.h>
103 #include <dev/pci/mlyvar.h>
104 #include <dev/pci/mly_tables.h>
106 static void mly_attach(device_t
, device_t
, void *);
107 static int mly_match(device_t
, cfdata_t
, void *);
108 static const struct mly_ident
*mly_find_ident(struct pci_attach_args
*);
109 static int mly_fwhandshake(struct mly_softc
*);
110 static int mly_flush(struct mly_softc
*);
111 static int mly_intr(void *);
112 static void mly_shutdown(void *);
114 static int mly_alloc_ccbs(struct mly_softc
*);
115 static void mly_check_event(struct mly_softc
*);
116 static void mly_complete_event(struct mly_softc
*, struct mly_ccb
*);
117 static void mly_complete_rescan(struct mly_softc
*, struct mly_ccb
*);
118 static int mly_dmamem_alloc(struct mly_softc
*, int, bus_dmamap_t
*,
119 void **, bus_addr_t
*, bus_dma_segment_t
*);
120 static void mly_dmamem_free(struct mly_softc
*, int, bus_dmamap_t
,
121 void *, bus_dma_segment_t
*);
122 static int mly_enable_mmbox(struct mly_softc
*);
123 static void mly_fetch_event(struct mly_softc
*);
124 static int mly_get_controllerinfo(struct mly_softc
*);
125 static int mly_get_eventstatus(struct mly_softc
*);
126 static int mly_ioctl(struct mly_softc
*, struct mly_cmd_ioctl
*,
127 void **, size_t, void *, size_t *);
128 static void mly_padstr(char *, const char *, int);
129 static void mly_process_event(struct mly_softc
*, struct mly_event
*);
130 static void mly_release_ccbs(struct mly_softc
*);
131 static int mly_scan_btl(struct mly_softc
*, int, int);
132 static void mly_scan_channel(struct mly_softc
*, int);
133 static void mly_thread(void *);
135 static int mly_ccb_alloc(struct mly_softc
*, struct mly_ccb
**);
136 static void mly_ccb_complete(struct mly_softc
*, struct mly_ccb
*);
137 static void mly_ccb_enqueue(struct mly_softc
*, struct mly_ccb
*);
138 static void mly_ccb_free(struct mly_softc
*, struct mly_ccb
*);
139 static int mly_ccb_map(struct mly_softc
*, struct mly_ccb
*);
140 static int mly_ccb_poll(struct mly_softc
*, struct mly_ccb
*, int);
141 static int mly_ccb_submit(struct mly_softc
*, struct mly_ccb
*);
142 static void mly_ccb_unmap(struct mly_softc
*, struct mly_ccb
*);
143 static int mly_ccb_wait(struct mly_softc
*, struct mly_ccb
*, int);
145 static void mly_get_xfer_mode(struct mly_softc
*, int,
146 struct scsipi_xfer_mode
*);
147 static void mly_scsipi_complete(struct mly_softc
*, struct mly_ccb
*);
148 static int mly_scsipi_ioctl(struct scsipi_channel
*, u_long
, void *,
150 static void mly_scsipi_minphys(struct buf
*);
151 static void mly_scsipi_request(struct scsipi_channel
*,
152 scsipi_adapter_req_t
, void *);
154 static int mly_user_command(struct mly_softc
*, struct mly_user_command
*);
155 static int mly_user_health(struct mly_softc
*, struct mly_user_health
*);
157 extern struct cfdriver mly_cd
;
159 CFATTACH_DECL(mly
, sizeof(struct mly_softc
),
160 mly_match
, mly_attach
, NULL
, NULL
);
162 dev_type_open(mlyopen
);
163 dev_type_close(mlyclose
);
164 dev_type_ioctl(mlyioctl
);
166 const struct cdevsw mly_cdevsw
= {
167 mlyopen
, mlyclose
, noread
, nowrite
, mlyioctl
,
168 nostop
, notty
, nopoll
, nommap
, nokqfilter
, D_OTHER
,
171 static struct mly_ident
{
178 } const mly_ident
[] = {
181 PCI_PRODUCT_MYLEX_EXTREMERAID
,
189 PCI_PRODUCT_MYLEX_EXTREMERAID
,
197 PCI_PRODUCT_MYLEX_ACCELERAID
,
205 PCI_PRODUCT_MYLEX_ACCELERAID
,
213 PCI_PRODUCT_MYLEX_ACCELERAID
,
221 static void *mly_sdh
;
224 * Try to find a `mly_ident' entry corresponding to this board.
226 static const struct mly_ident
*
227 mly_find_ident(struct pci_attach_args
*pa
)
229 const struct mly_ident
*mpi
, *maxmpi
;
233 maxmpi
= mpi
+ sizeof(mly_ident
) / sizeof(mly_ident
[0]);
235 if (PCI_CLASS(pa
->pa_class
) == PCI_CLASS_I2O
)
238 for (; mpi
< maxmpi
; mpi
++) {
239 if (PCI_VENDOR(pa
->pa_id
) != mpi
->vendor
||
240 PCI_PRODUCT(pa
->pa_id
) != mpi
->product
)
243 if (mpi
->subvendor
== 0x0000)
246 reg
= pci_conf_read(pa
->pa_pc
, pa
->pa_tag
, PCI_SUBSYS_ID_REG
);
248 if (PCI_VENDOR(reg
) == mpi
->subvendor
&&
249 PCI_PRODUCT(reg
) == mpi
->subproduct
)
257 * Match a supported board.
260 mly_match(device_t parent
, cfdata_t cfdata
, void *aux
)
263 return (mly_find_ident(aux
) != NULL
);
267 * Attach a supported board.
270 mly_attach(device_t parent
, device_t self
, void *aux
)
272 struct pci_attach_args
*pa
;
273 struct mly_softc
*mly
;
274 struct mly_ioctl_getcontrollerinfo
*mi
;
275 const struct mly_ident
*ident
;
276 pci_chipset_tag_t pc
;
277 pci_intr_handle_t ih
;
278 bus_space_handle_t memh
, ioh
;
279 bus_space_tag_t memt
, iot
;
282 int ior
, memr
, i
, rv
, state
;
283 struct scsipi_adapter
*adapt
;
284 struct scsipi_channel
*chan
;
286 mly
= device_private(self
);
289 ident
= mly_find_ident(pa
);
292 mly
->mly_dmat
= pa
->pa_dmat
;
293 mly
->mly_hwif
= ident
->hwif
;
295 printf(": Mylex %s\n", ident
->desc
);
298 * Map the PCI register window.
303 for (i
= 0x10; i
<= 0x14; i
+= 4) {
304 reg
= pci_conf_read(pa
->pa_pc
, pa
->pa_tag
, i
);
306 if (PCI_MAPREG_TYPE(reg
) == PCI_MAPREG_TYPE_IO
) {
307 if (ior
== -1 && PCI_MAPREG_IO_SIZE(reg
) != 0)
310 if (memr
== -1 && PCI_MAPREG_MEM_SIZE(reg
) != 0)
316 if (pci_mapreg_map(pa
, memr
, PCI_MAPREG_TYPE_MEM
, 0,
317 &memt
, &memh
, NULL
, NULL
))
320 if (pci_mapreg_map(pa
, ior
, PCI_MAPREG_TYPE_IO
, 0,
321 &iot
, &ioh
, NULL
, NULL
))
327 } else if (ior
!= -1) {
331 aprint_error_dev(self
, "can't map i/o or memory space\n");
338 reg
= pci_conf_read(pa
->pa_pc
, pa
->pa_tag
, PCI_COMMAND_STATUS_REG
);
339 pci_conf_write(pa
->pa_pc
, pa
->pa_tag
, PCI_COMMAND_STATUS_REG
,
340 reg
| PCI_COMMAND_MASTER_ENABLE
);
343 * Map and establish the interrupt.
345 if (pci_intr_map(pa
, &ih
)) {
346 aprint_error_dev(self
, "can't map interrupt\n");
349 intrstr
= pci_intr_string(pc
, ih
);
350 mly
->mly_ih
= pci_intr_establish(pc
, ih
, IPL_BIO
, mly_intr
, mly
);
351 if (mly
->mly_ih
== NULL
) {
352 aprint_error_dev(self
, "can't establish interrupt");
354 aprint_error(" at %s", intrstr
);
360 aprint_normal_dev(&mly
->mly_dv
, "interrupting at %s\n",
364 * Take care of interface-specific tasks.
366 switch (mly
->mly_hwif
) {
367 case MLY_HWIF_I960RX
:
368 mly
->mly_doorbell_true
= 0x00;
369 mly
->mly_cmd_mailbox
= MLY_I960RX_COMMAND_MAILBOX
;
370 mly
->mly_status_mailbox
= MLY_I960RX_STATUS_MAILBOX
;
371 mly
->mly_idbr
= MLY_I960RX_IDBR
;
372 mly
->mly_odbr
= MLY_I960RX_ODBR
;
373 mly
->mly_error_status
= MLY_I960RX_ERROR_STATUS
;
374 mly
->mly_interrupt_status
= MLY_I960RX_INTERRUPT_STATUS
;
375 mly
->mly_interrupt_mask
= MLY_I960RX_INTERRUPT_MASK
;
378 case MLY_HWIF_STRONGARM
:
379 mly
->mly_doorbell_true
= 0xff;
380 mly
->mly_cmd_mailbox
= MLY_STRONGARM_COMMAND_MAILBOX
;
381 mly
->mly_status_mailbox
= MLY_STRONGARM_STATUS_MAILBOX
;
382 mly
->mly_idbr
= MLY_STRONGARM_IDBR
;
383 mly
->mly_odbr
= MLY_STRONGARM_ODBR
;
384 mly
->mly_error_status
= MLY_STRONGARM_ERROR_STATUS
;
385 mly
->mly_interrupt_status
= MLY_STRONGARM_INTERRUPT_STATUS
;
386 mly
->mly_interrupt_mask
= MLY_STRONGARM_INTERRUPT_MASK
;
391 * Allocate and map the scatter/gather lists.
393 rv
= mly_dmamem_alloc(mly
, MLY_SGL_SIZE
* MLY_MAX_CCBS
,
394 &mly
->mly_sg_dmamap
, (void **)&mly
->mly_sg
,
395 &mly
->mly_sg_busaddr
, &mly
->mly_sg_seg
);
397 printf("%s: unable to allocate S/G maps\n",
398 device_xname(&mly
->mly_dv
));
404 * Allocate and map the memory mailbox.
406 rv
= mly_dmamem_alloc(mly
, sizeof(struct mly_mmbox
),
407 &mly
->mly_mmbox_dmamap
, (void **)&mly
->mly_mmbox
,
408 &mly
->mly_mmbox_busaddr
, &mly
->mly_mmbox_seg
);
410 aprint_error_dev(&mly
->mly_dv
, "unable to allocate mailboxes\n");
416 * Initialise per-controller queues.
418 SLIST_INIT(&mly
->mly_ccb_free
);
419 SIMPLEQ_INIT(&mly
->mly_ccb_queue
);
422 * Disable interrupts before we start talking to the controller.
424 mly_outb(mly
, mly
->mly_interrupt_mask
, MLY_INTERRUPT_MASK_DISABLE
);
427 * Wait for the controller to come ready, handshaking with the
428 * firmware if required. This is typically only necessary on
429 * platforms where the controller BIOS does not run.
431 if (mly_fwhandshake(mly
)) {
432 aprint_error_dev(&mly
->mly_dv
, "unable to bring controller online\n");
437 * Allocate initial command buffers, obtain controller feature
438 * information, and then reallocate command buffers, since we'll
439 * know how many we want.
441 if (mly_alloc_ccbs(mly
)) {
442 aprint_error_dev(&mly
->mly_dv
, "unable to allocate CCBs\n");
446 if (mly_get_controllerinfo(mly
)) {
447 aprint_error_dev(&mly
->mly_dv
, "unable to retrieve controller info\n");
450 mly_release_ccbs(mly
);
451 if (mly_alloc_ccbs(mly
)) {
452 aprint_error_dev(&mly
->mly_dv
, "unable to allocate CCBs\n");
458 * Get the current event counter for health purposes, populate the
459 * initial health status buffer.
461 if (mly_get_eventstatus(mly
)) {
462 aprint_error_dev(&mly
->mly_dv
, "unable to retrieve event status\n");
467 * Enable memory-mailbox mode.
469 if (mly_enable_mmbox(mly
)) {
470 aprint_error_dev(&mly
->mly_dv
, "unable to enable memory mailbox\n");
475 * Print a little information about the controller.
477 mi
= mly
->mly_controllerinfo
;
479 printf("%s: %d physical channel%s, firmware %d.%02d-%d-%02d "
480 "(%02d%02d%02d%02d), %dMB RAM\n", device_xname(&mly
->mly_dv
),
481 mi
->physical_channels_present
,
482 (mi
->physical_channels_present
) > 1 ? "s" : "",
483 mi
->fw_major
, mi
->fw_minor
, mi
->fw_turn
, mi
->fw_build
,
484 mi
->fw_century
, mi
->fw_year
, mi
->fw_month
, mi
->fw_day
,
485 le16toh(mi
->memory_size
));
488 * Register our `shutdownhook'.
491 shutdownhook_establish(mly_shutdown
, NULL
);
494 * Clear any previous BTL information. For each bus that scsipi
495 * wants to scan, we'll receive the SCBUSIOLLSCAN ioctl and retrieve
496 * all BTL info at that point.
498 memset(&mly
->mly_btl
, 0, sizeof(mly
->mly_btl
));
500 mly
->mly_nchans
= mly
->mly_controllerinfo
->physical_channels_present
+
501 mly
->mly_controllerinfo
->virtual_channels_present
;
506 adapt
= &mly
->mly_adapt
;
507 memset(adapt
, 0, sizeof(*adapt
));
508 adapt
->adapt_dev
= &mly
->mly_dv
;
509 adapt
->adapt_nchannels
= mly
->mly_nchans
;
510 adapt
->adapt_openings
= mly
->mly_ncmds
- MLY_CCBS_RESV
;
511 adapt
->adapt_max_periph
= mly
->mly_ncmds
- MLY_CCBS_RESV
;
512 adapt
->adapt_request
= mly_scsipi_request
;
513 adapt
->adapt_minphys
= mly_scsipi_minphys
;
514 adapt
->adapt_ioctl
= mly_scsipi_ioctl
;
516 for (i
= 0; i
< mly
->mly_nchans
; i
++) {
517 chan
= &mly
->mly_chans
[i
];
518 memset(chan
, 0, sizeof(*chan
));
519 chan
->chan_adapter
= adapt
;
520 chan
->chan_bustype
= &scsi_bustype
;
521 chan
->chan_channel
= i
;
522 chan
->chan_ntargets
= MLY_MAX_TARGETS
;
523 chan
->chan_nluns
= MLY_MAX_LUNS
;
524 chan
->chan_id
= mly
->mly_controllerparam
->initiator_id
;
525 chan
->chan_flags
= SCSIPI_CHAN_NOSETTLE
;
526 config_found(&mly
->mly_dv
, chan
, scsiprint
);
530 * Now enable interrupts...
532 mly_outb(mly
, mly
->mly_interrupt_mask
, MLY_INTERRUPT_MASK_ENABLE
);
535 * Finally, create our monitoring thread.
537 mly
->mly_state
|= MLY_STATE_INITOK
;
538 rv
= kthread_create(PRI_NONE
, 0, NULL
, mly_thread
, mly
,
539 &mly
->mly_thread
, "%s", device_xname(&mly
->mly_dv
));
541 aprint_error_dev(&mly
->mly_dv
, "unable to create thread (%d)\n",
547 mly_release_ccbs(mly
);
549 mly_dmamem_free(mly
, sizeof(struct mly_mmbox
),
550 mly
->mly_mmbox_dmamap
, (void *)mly
->mly_mmbox
,
551 &mly
->mly_mmbox_seg
);
553 mly_dmamem_free(mly
, MLY_SGL_SIZE
* MLY_MAX_CCBS
,
554 mly
->mly_sg_dmamap
, (void *)mly
->mly_sg
,
559 * Scan all possible devices on the specified channel.
562 mly_scan_channel(struct mly_softc
*mly
, int bus
)
566 for (target
= 0; target
< MLY_MAX_TARGETS
; target
++) {
568 if (!mly_scan_btl(mly
, bus
, target
)) {
569 tsleep(&mly
->mly_btl
[bus
][target
], PRIBIO
, "mlyscan",
577 * Shut down all configured `mly' devices.
580 mly_shutdown(void *cookie
)
582 struct mly_softc
*mly
;
585 for (i
= 0; i
< mly_cd
.cd_ndevs
; i
++) {
586 if ((mly
= device_lookup_private(&mly_cd
, i
)) == NULL
)
590 aprint_error_dev(&mly
->mly_dv
, "unable to flush cache\n");
595 * Fill in the mly_controllerinfo and mly_controllerparam fields in the
599 mly_get_controllerinfo(struct mly_softc
*mly
)
601 struct mly_cmd_ioctl mci
;
605 * Build the getcontrollerinfo ioctl and send it.
607 memset(&mci
, 0, sizeof(mci
));
608 mci
.sub_ioctl
= MDACIOCTL_GETCONTROLLERINFO
;
609 rv
= mly_ioctl(mly
, &mci
, (void **)&mly
->mly_controllerinfo
,
610 sizeof(*mly
->mly_controllerinfo
), NULL
, NULL
);
615 * Build the getcontrollerparameter ioctl and send it.
617 memset(&mci
, 0, sizeof(mci
));
618 mci
.sub_ioctl
= MDACIOCTL_GETCONTROLLERPARAMETER
;
619 rv
= mly_ioctl(mly
, &mci
, (void **)&mly
->mly_controllerparam
,
620 sizeof(*mly
->mly_controllerparam
), NULL
, NULL
);
626 * Rescan a device, possibly as a consequence of getting an event which
627 * suggests that it may have changed. Must be called with interrupts
631 mly_scan_btl(struct mly_softc
*mly
, int bus
, int target
)
634 struct mly_cmd_ioctl
*mci
;
637 if (target
== mly
->mly_controllerparam
->initiator_id
) {
638 mly
->mly_btl
[bus
][target
].mb_flags
= MLY_BTL_PROTECTED
;
642 /* Don't re-scan if a scan is already in progress. */
643 if ((mly
->mly_btl
[bus
][target
].mb_flags
& MLY_BTL_SCANNING
) != 0)
647 if ((rv
= mly_ccb_alloc(mly
, &mc
)) != 0)
650 /* Set up the data buffer. */
651 mc
->mc_data
= malloc(sizeof(union mly_devinfo
),
652 M_DEVBUF
, M_NOWAIT
|M_ZERO
);
654 mc
->mc_flags
|= MLY_CCB_DATAIN
;
655 mc
->mc_complete
= mly_complete_rescan
;
660 mci
= (struct mly_cmd_ioctl
*)&mc
->mc_packet
->ioctl
;
661 mci
->opcode
= MDACMD_IOCTL
;
662 mci
->timeout
= 30 | MLY_TIMEOUT_SECONDS
;
663 memset(&mci
->param
, 0, sizeof(mci
->param
));
665 if (MLY_BUS_IS_VIRTUAL(mly
, bus
)) {
666 mc
->mc_length
= sizeof(struct mly_ioctl_getlogdevinfovalid
);
667 mci
->data_size
= htole32(mc
->mc_length
);
668 mci
->sub_ioctl
= MDACIOCTL_GETLOGDEVINFOVALID
;
669 _lto3l(MLY_LOGADDR(0, MLY_LOGDEV_ID(mly
, bus
, target
)),
672 mc
->mc_length
= sizeof(struct mly_ioctl_getphysdevinfovalid
);
673 mci
->data_size
= htole32(mc
->mc_length
);
674 mci
->sub_ioctl
= MDACIOCTL_GETPHYSDEVINFOVALID
;
675 _lto3l(MLY_PHYADDR(0, bus
, target
, 0), mci
->addr
);
679 * Dispatch the command.
681 if ((rv
= mly_ccb_map(mly
, mc
)) != 0) {
682 free(mc
->mc_data
, M_DEVBUF
);
683 mly_ccb_free(mly
, mc
);
687 mly
->mly_btl
[bus
][target
].mb_flags
|= MLY_BTL_SCANNING
;
688 mly_ccb_enqueue(mly
, mc
);
693 * Handle the completion of a rescan operation.
696 mly_complete_rescan(struct mly_softc
*mly
, struct mly_ccb
*mc
)
698 struct mly_ioctl_getlogdevinfovalid
*ldi
;
699 struct mly_ioctl_getphysdevinfovalid
*pdi
;
700 struct mly_cmd_ioctl
*mci
;
701 struct mly_btl btl
, *btlp
;
702 struct scsipi_xfer_mode xm
;
703 int bus
, target
, rescan
;
706 mly_ccb_unmap(mly
, mc
);
709 * Recover the bus and target from the command. We need these even
710 * in the case where we don't have a useful response.
712 mci
= (struct mly_cmd_ioctl
*)&mc
->mc_packet
->ioctl
;
713 tmp
= _3ltol(mci
->addr
);
716 if (mci
->sub_ioctl
== MDACIOCTL_GETLOGDEVINFOVALID
) {
717 bus
= MLY_LOGDEV_BUS(mly
, MLY_LOGADDR_DEV(tmp
));
718 target
= MLY_LOGDEV_TARGET(mly
, MLY_LOGADDR_DEV(tmp
));
720 bus
= MLY_PHYADDR_CHANNEL(tmp
);
721 target
= MLY_PHYADDR_TARGET(tmp
);
724 btlp
= &mly
->mly_btl
[bus
][target
];
726 /* The default result is 'no device'. */
727 memset(&btl
, 0, sizeof(btl
));
728 btl
.mb_flags
= MLY_BTL_PROTECTED
;
730 /* If the rescan completed OK, we have possibly-new BTL data. */
731 if (mc
->mc_status
!= 0)
734 if (mc
->mc_length
== sizeof(*ldi
)) {
735 ldi
= (struct mly_ioctl_getlogdevinfovalid
*)mc
->mc_data
;
736 tmp
= le32toh(ldi
->logical_device_number
);
738 if (MLY_LOGDEV_BUS(mly
, tmp
) != bus
||
739 MLY_LOGDEV_TARGET(mly
, tmp
) != target
) {
741 printf("%s: WARNING: BTL rescan (logical) for %d:%d "
742 "returned data for %d:%d instead\n",
743 device_xname(&mly
->mly_dv
), bus
, target
,
744 MLY_LOGDEV_BUS(mly
, tmp
),
745 MLY_LOGDEV_TARGET(mly
, tmp
));
750 btl
.mb_flags
= MLY_BTL_LOGICAL
| MLY_BTL_TQING
;
751 btl
.mb_type
= ldi
->raid_level
;
752 btl
.mb_state
= ldi
->state
;
753 } else if (mc
->mc_length
== sizeof(*pdi
)) {
754 pdi
= (struct mly_ioctl_getphysdevinfovalid
*)mc
->mc_data
;
756 if (pdi
->channel
!= bus
|| pdi
->target
!= target
) {
758 printf("%s: WARNING: BTL rescan (physical) for %d:%d "
759 " returned data for %d:%d instead\n",
760 device_xname(&mly
->mly_dv
),
761 bus
, target
, pdi
->channel
, pdi
->target
);
766 btl
.mb_flags
= MLY_BTL_PHYSICAL
;
767 btl
.mb_type
= MLY_DEVICE_TYPE_PHYSICAL
;
768 btl
.mb_state
= pdi
->state
;
769 btl
.mb_speed
= pdi
->speed
;
770 btl
.mb_width
= pdi
->width
;
772 if (pdi
->state
!= MLY_DEVICE_STATE_UNCONFIGURED
)
773 btl
.mb_flags
|= MLY_BTL_PROTECTED
;
774 if (pdi
->command_tags
!= 0)
775 btl
.mb_flags
|= MLY_BTL_TQING
;
777 printf("%s: BTL rescan result invalid\n", device_xname(&mly
->mly_dv
));
781 /* Decide whether we need to rescan the device. */
782 if (btl
.mb_flags
!= btlp
->mb_flags
||
783 btl
.mb_speed
!= btlp
->mb_speed
||
784 btl
.mb_width
!= btlp
->mb_width
)
790 if (rescan
&& (btl
.mb_flags
& MLY_BTL_PROTECTED
) == 0) {
791 xm
.xm_target
= target
;
792 mly_get_xfer_mode(mly
, bus
, &xm
);
793 /* XXX SCSI mid-layer rescan goes here. */
796 /* Wake anybody waiting on the device to be rescanned. */
799 free(mc
->mc_data
, M_DEVBUF
);
800 mly_ccb_free(mly
, mc
);
804 * Get the current health status and set the 'next event' counter to suit.
807 mly_get_eventstatus(struct mly_softc
*mly
)
809 struct mly_cmd_ioctl mci
;
810 struct mly_health_status
*mh
;
813 /* Build the gethealthstatus ioctl and send it. */
814 memset(&mci
, 0, sizeof(mci
));
816 mci
.sub_ioctl
= MDACIOCTL_GETHEALTHSTATUS
;
818 rv
= mly_ioctl(mly
, &mci
, (void *)&mh
, sizeof(*mh
), NULL
, NULL
);
822 /* Get the event counter. */
823 mly
->mly_event_change
= le32toh(mh
->change_counter
);
824 mly
->mly_event_waiting
= le32toh(mh
->next_event
);
825 mly
->mly_event_counter
= le32toh(mh
->next_event
);
827 /* Save the health status into the memory mailbox */
828 memcpy(&mly
->mly_mmbox
->mmm_health
.status
, mh
, sizeof(*mh
));
830 bus_dmamap_sync(mly
->mly_dmat
, mly
->mly_mmbox_dmamap
,
831 offsetof(struct mly_mmbox
, mmm_health
),
832 sizeof(mly
->mly_mmbox
->mmm_health
),
833 BUS_DMASYNC_PREWRITE
| BUS_DMASYNC_PREREAD
);
840 * Enable memory mailbox mode.
843 mly_enable_mmbox(struct mly_softc
*mly
)
845 struct mly_cmd_ioctl mci
;
850 /* Build the ioctl and send it. */
851 memset(&mci
, 0, sizeof(mci
));
852 mci
.sub_ioctl
= MDACIOCTL_SETMEMORYMAILBOX
;
854 /* Set buffer addresses. */
855 tmp
= mly
->mly_mmbox_busaddr
+ offsetof(struct mly_mmbox
, mmm_command
);
856 mci
.param
.setmemorymailbox
.command_mailbox_physaddr
= htole64(tmp
);
858 tmp
= mly
->mly_mmbox_busaddr
+ offsetof(struct mly_mmbox
, mmm_status
);
859 mci
.param
.setmemorymailbox
.status_mailbox_physaddr
= htole64(tmp
);
861 tmp
= mly
->mly_mmbox_busaddr
+ offsetof(struct mly_mmbox
, mmm_health
);
862 mci
.param
.setmemorymailbox
.health_buffer_physaddr
= htole64(tmp
);
864 /* Set buffer sizes - abuse of data_size field is revolting. */
865 sp
= (u_int8_t
*)&mci
.data_size
;
866 sp
[0] = (sizeof(union mly_cmd_packet
) * MLY_MMBOX_COMMANDS
) >> 10;
867 sp
[1] = (sizeof(union mly_status_packet
) * MLY_MMBOX_STATUS
) >> 10;
868 mci
.param
.setmemorymailbox
.health_buffer_size
=
869 sizeof(union mly_health_region
) >> 10;
871 rv
= mly_ioctl(mly
, &mci
, NULL
, 0, NULL
, NULL
);
875 mly
->mly_state
|= MLY_STATE_MMBOX_ACTIVE
;
880 * Flush all pending I/O from the controller.
883 mly_flush(struct mly_softc
*mly
)
885 struct mly_cmd_ioctl mci
;
887 /* Build the ioctl */
888 memset(&mci
, 0, sizeof(mci
));
889 mci
.sub_ioctl
= MDACIOCTL_FLUSHDEVICEDATA
;
890 mci
.param
.deviceoperation
.operation_device
=
891 MLY_OPDEVICE_PHYSICAL_CONTROLLER
;
893 /* Pass it off to the controller */
894 return (mly_ioctl(mly
, &mci
, NULL
, 0, NULL
, NULL
));
898 * Perform an ioctl command.
900 * If (data) is not NULL, the command requires data transfer to the
901 * controller. If (*data) is NULL the command requires data transfer from
902 * the controller, and we will allocate a buffer for it.
905 mly_ioctl(struct mly_softc
*mly
, struct mly_cmd_ioctl
*ioctl
, void **data
,
906 size_t datasize
, void *sense_buffer
,
907 size_t *sense_length
)
910 struct mly_cmd_ioctl
*mci
;
915 if ((rv
= mly_ccb_alloc(mly
, &mc
)) != 0)
919 * Copy the ioctl structure, but save some important fields and then
922 mci
= &mc
->mc_packet
->ioctl
;
923 ioctl
->sense_buffer_address
= htole64(mci
->sense_buffer_address
);
924 ioctl
->maximum_sense_size
= mci
->maximum_sense_size
;
926 mci
->opcode
= MDACMD_IOCTL
;
927 mci
->timeout
= 30 | MLY_TIMEOUT_SECONDS
;
929 /* Handle the data buffer. */
932 /* Allocate data buffer */
933 mc
->mc_data
= malloc(datasize
, M_DEVBUF
, M_NOWAIT
);
934 mc
->mc_flags
|= MLY_CCB_DATAIN
;
937 mc
->mc_flags
|= MLY_CCB_DATAOUT
;
939 mc
->mc_length
= datasize
;
940 mc
->mc_packet
->generic
.data_size
= htole32(datasize
);
943 /* Run the command. */
945 if ((rv
= mly_ccb_map(mly
, mc
)) != 0)
947 rv
= mly_ccb_poll(mly
, mc
, 30000);
949 mly_ccb_unmap(mly
, mc
);
953 /* Clean up and return any data. */
954 status
= mc
->mc_status
;
957 printf("mly_ioctl: command status %d\n", status
);
959 if (mc
->mc_sense
> 0 && sense_buffer
!= NULL
) {
960 memcpy(sense_buffer
, mc
->mc_packet
, mc
->mc_sense
);
961 *sense_length
= mc
->mc_sense
;
965 /* Should we return a data pointer? */
966 if (data
!= NULL
&& *data
== NULL
)
969 /* Command completed OK. */
970 rv
= (status
!= 0 ? EIO
: 0);
974 /* Do we need to free a data buffer we allocated? */
975 if (rv
!= 0 && mc
->mc_data
!= NULL
&&
976 (data
== NULL
|| *data
== NULL
))
977 free(mc
->mc_data
, M_DEVBUF
);
978 mly_ccb_free(mly
, mc
);
985 * Check for event(s) outstanding in the controller.
988 mly_check_event(struct mly_softc
*mly
)
991 bus_dmamap_sync(mly
->mly_dmat
, mly
->mly_mmbox_dmamap
,
992 offsetof(struct mly_mmbox
, mmm_health
),
993 sizeof(mly
->mly_mmbox
->mmm_health
),
994 BUS_DMASYNC_POSTWRITE
| BUS_DMASYNC_POSTREAD
);
997 * The controller may have updated the health status information, so
998 * check for it here. Note that the counters are all in host
999 * memory, so this check is very cheap. Also note that we depend on
1000 * checking on completion
1002 if (le32toh(mly
->mly_mmbox
->mmm_health
.status
.change_counter
) !=
1003 mly
->mly_event_change
) {
1004 mly
->mly_event_change
=
1005 le32toh(mly
->mly_mmbox
->mmm_health
.status
.change_counter
);
1006 mly
->mly_event_waiting
=
1007 le32toh(mly
->mly_mmbox
->mmm_health
.status
.next_event
);
1009 /* Wake up anyone that might be interested in this. */
1010 wakeup(&mly
->mly_event_change
);
1013 bus_dmamap_sync(mly
->mly_dmat
, mly
->mly_mmbox_dmamap
,
1014 offsetof(struct mly_mmbox
, mmm_health
),
1015 sizeof(mly
->mly_mmbox
->mmm_health
),
1016 BUS_DMASYNC_PREWRITE
| BUS_DMASYNC_PREREAD
);
1018 if (mly
->mly_event_counter
!= mly
->mly_event_waiting
)
1019 mly_fetch_event(mly
);
1023 * Fetch one event from the controller. If we fail due to resource
1024 * starvation, we'll be retried the next time a command completes.
1027 mly_fetch_event(struct mly_softc
*mly
)
1030 struct mly_cmd_ioctl
*mci
;
1034 /* Get a command. */
1035 if (mly_ccb_alloc(mly
, &mc
))
1038 /* Set up the data buffer. */
1039 mc
->mc_data
= malloc(sizeof(struct mly_event
), M_DEVBUF
,
1042 mc
->mc_length
= sizeof(struct mly_event
);
1043 mc
->mc_flags
|= MLY_CCB_DATAIN
;
1044 mc
->mc_complete
= mly_complete_event
;
1047 * Get an event number to fetch. It's possible that we've raced
1048 * with another context for the last event, in which case there will
1049 * be no more events.
1052 if (mly
->mly_event_counter
== mly
->mly_event_waiting
) {
1054 free(mc
->mc_data
, M_DEVBUF
);
1055 mly_ccb_free(mly
, mc
);
1058 event
= mly
->mly_event_counter
++;
1064 * At this point we are committed to sending this request, as it
1065 * will be the only one constructed for this particular event
1068 mci
= (struct mly_cmd_ioctl
*)&mc
->mc_packet
->ioctl
;
1069 mci
->opcode
= MDACMD_IOCTL
;
1070 mci
->data_size
= htole32(sizeof(struct mly_event
));
1071 _lto3l(MLY_PHYADDR(0, 0, (event
>> 16) & 0xff, (event
>> 24) & 0xff),
1073 mci
->timeout
= 30 | MLY_TIMEOUT_SECONDS
;
1074 mci
->sub_ioctl
= MDACIOCTL_GETEVENT
;
1075 mci
->param
.getevent
.sequence_number_low
= htole16(event
& 0xffff);
1078 * Submit the command.
1080 if (mly_ccb_map(mly
, mc
) != 0)
1082 mly_ccb_enqueue(mly
, mc
);
1086 printf("%s: couldn't fetch event %u\n", device_xname(&mly
->mly_dv
), event
);
1087 free(mc
->mc_data
, M_DEVBUF
);
1088 mly_ccb_free(mly
, mc
);
1092 * Handle the completion of an event poll.
1095 mly_complete_event(struct mly_softc
*mly
, struct mly_ccb
*mc
)
1097 struct mly_event
*me
;
1099 me
= (struct mly_event
*)mc
->mc_data
;
1100 mly_ccb_unmap(mly
, mc
);
1101 mly_ccb_free(mly
, mc
);
1103 /* If the event was successfully fetched, process it. */
1104 if (mc
->mc_status
== SCSI_OK
)
1105 mly_process_event(mly
, me
);
1107 aprint_error_dev(&mly
->mly_dv
, "unable to fetch event; status = 0x%x\n",
1112 /* Check for another event. */
1113 mly_check_event(mly
);
1117 * Process a controller event. Called with interrupts blocked (i.e., at
1121 mly_process_event(struct mly_softc
*mly
, struct mly_event
*me
)
1123 struct scsi_sense_data
*ssd
;
1124 int bus
, target
, event
, class, action
;
1125 const char *fp
, *tp
;
1127 ssd
= (struct scsi_sense_data
*)&me
->sense
[0];
1130 * Errors can be reported using vendor-unique sense data. In this
1131 * case, the event code will be 0x1c (Request sense data present),
1132 * the sense key will be 0x09 (vendor specific), the MSB of the ASC
1133 * will be set, and the actual event code will be a 16-bit value
1134 * comprised of the ASCQ (low byte) and low seven bits of the ASC
1135 * (low seven bits of the high byte).
1137 if (le32toh(me
->code
) == 0x1c &&
1138 SSD_SENSE_KEY(ssd
->flags
) == SKEY_VENDOR_SPECIFIC
&&
1139 (ssd
->asc
& 0x80) != 0) {
1140 event
= ((int)(ssd
->asc
& ~0x80) << 8) +
1143 event
= le32toh(me
->code
);
1145 /* Look up event, get codes. */
1146 fp
= mly_describe_code(mly_table_event
, event
);
1151 if (isupper(class) && bootverbose
)
1152 class = tolower(class);
1155 /* Get action code, text string. */
1160 * Print some information about the event.
1162 * This code uses a table derived from the corresponding portion of
1163 * the Linux driver, and thus the parser is very similar.
1168 * Error on physical drive.
1170 printf("%s: physical device %d:%d %s\n", device_xname(&mly
->mly_dv
),
1171 me
->channel
, me
->target
, tp
);
1173 mly
->mly_btl
[me
->channel
][me
->target
].mb_flags
|=
1180 * Error on logical unit, or message about logical unit.
1182 bus
= MLY_LOGDEV_BUS(mly
, me
->lun
);
1183 target
= MLY_LOGDEV_TARGET(mly
, me
->lun
);
1184 printf("%s: logical device %d:%d %s\n", device_xname(&mly
->mly_dv
),
1187 mly
->mly_btl
[bus
][target
].mb_flags
|= MLY_BTL_RESCAN
;
1192 * Report of sense data.
1194 if ((SSD_SENSE_KEY(ssd
->flags
) == SKEY_NO_SENSE
||
1195 SSD_SENSE_KEY(ssd
->flags
) == SKEY_NOT_READY
) &&
1197 (ssd
->ascq
== 0x01 ||
1198 ssd
->ascq
== 0x02)) {
1199 /* Ignore NO_SENSE or NOT_READY in one case */
1204 * XXX Should translate this if SCSIVERBOSE.
1206 printf("%s: physical device %d:%d %s\n", device_xname(&mly
->mly_dv
),
1207 me
->channel
, me
->target
, tp
);
1208 printf("%s: sense key %d asc %02x ascq %02x\n",
1209 device_xname(&mly
->mly_dv
), SSD_SENSE_KEY(ssd
->flags
),
1210 ssd
->asc
, ssd
->ascq
);
1211 printf("%s: info %x%x%x%x csi %x%x%x%x\n",
1212 device_xname(&mly
->mly_dv
), ssd
->info
[0], ssd
->info
[1],
1213 ssd
->info
[2], ssd
->info
[3], ssd
->csi
[0],
1214 ssd
->csi
[1], ssd
->csi
[2],
1217 mly
->mly_btl
[me
->channel
][me
->target
].mb_flags
|=
1222 printf("%s: ", device_xname(&mly
->mly_dv
));
1223 printf(tp
, me
->target
, me
->lun
);
1227 printf("%s: controller %s\n", device_xname(&mly
->mly_dv
), tp
);
1231 printf("%s: %s - %d\n", device_xname(&mly
->mly_dv
), tp
, event
);
1235 /* Probably a 'noisy' event being ignored. */
1241 * Perform periodic activities.
1244 mly_thread(void *cookie
)
1246 struct mly_softc
*mly
;
1247 struct mly_btl
*btl
;
1248 int s
, bus
, target
, done
;
1250 mly
= (struct mly_softc
*)cookie
;
1253 /* Check for new events. */
1254 mly_check_event(mly
);
1256 /* Re-scan up to 1 device. */
1259 for (bus
= 0; bus
< mly
->mly_nchans
&& !done
; bus
++) {
1260 for (target
= 0; target
< MLY_MAX_TARGETS
; target
++) {
1261 /* Perform device rescan? */
1262 btl
= &mly
->mly_btl
[bus
][target
];
1263 if ((btl
->mb_flags
& MLY_BTL_RESCAN
) != 0) {
1264 btl
->mb_flags
^= MLY_BTL_RESCAN
;
1265 mly_scan_btl(mly
, bus
, target
);
1273 /* Sleep for N seconds. */
1274 tsleep(mly_thread
, PWAIT
, "mlyzzz",
1275 hz
* MLY_PERIODIC_INTERVAL
);
1280 * Submit a command to the controller and poll on completion. Return
1281 * non-zero on timeout.
1284 mly_ccb_poll(struct mly_softc
*mly
, struct mly_ccb
*mc
, int timo
)
1288 if ((rv
= mly_ccb_submit(mly
, mc
)) != 0)
1291 for (timo
*= 10; timo
!= 0; timo
--) {
1292 if ((mc
->mc_flags
& MLY_CCB_COMPLETE
) != 0)
1302 * Submit a command to the controller and sleep on completion. Return
1303 * non-zero on timeout.
1306 mly_ccb_wait(struct mly_softc
*mly
, struct mly_ccb
*mc
, int timo
)
1310 mly_ccb_enqueue(mly
, mc
);
1313 if ((mc
->mc_flags
& MLY_CCB_COMPLETE
) != 0) {
1317 rv
= tsleep(mc
, PRIBIO
, "mlywccb", timo
* hz
/ 1000);
1324 * If a CCB is specified, enqueue it. Pull CCBs off the software queue in
1325 * the order that they were enqueued and try to submit their command blocks
1326 * to the controller for execution.
1329 mly_ccb_enqueue(struct mly_softc
*mly
, struct mly_ccb
*mc
)
1336 SIMPLEQ_INSERT_TAIL(&mly
->mly_ccb_queue
, mc
, mc_link
.simpleq
);
1338 while ((mc
= SIMPLEQ_FIRST(&mly
->mly_ccb_queue
)) != NULL
) {
1339 if (mly_ccb_submit(mly
, mc
))
1341 SIMPLEQ_REMOVE_HEAD(&mly
->mly_ccb_queue
, mc_link
.simpleq
);
1348 * Deliver a command to the controller.
1351 mly_ccb_submit(struct mly_softc
*mly
, struct mly_ccb
*mc
)
1353 union mly_cmd_packet
*pkt
;
1356 mc
->mc_packet
->generic
.command_id
= htole16(mc
->mc_slot
);
1358 bus_dmamap_sync(mly
->mly_dmat
, mly
->mly_pkt_dmamap
,
1359 mc
->mc_packetphys
- mly
->mly_pkt_busaddr
,
1360 sizeof(union mly_cmd_packet
),
1361 BUS_DMASYNC_PREREAD
| BUS_DMASYNC_PREWRITE
);
1366 * Do we have to use the hardware mailbox?
1368 if ((mly
->mly_state
& MLY_STATE_MMBOX_ACTIVE
) == 0) {
1370 * Check to see if the controller is ready for us.
1372 if (mly_idbr_true(mly
, MLY_HM_CMDSENT
)) {
1378 * It's ready, send the command.
1380 mly_outl(mly
, mly
->mly_cmd_mailbox
,
1381 (u_int64_t
)mc
->mc_packetphys
& 0xffffffff);
1382 mly_outl(mly
, mly
->mly_cmd_mailbox
+ 4,
1383 (u_int64_t
)mc
->mc_packetphys
>> 32);
1384 mly_outb(mly
, mly
->mly_idbr
, MLY_HM_CMDSENT
);
1386 pkt
= &mly
->mly_mmbox
->mmm_command
[mly
->mly_mmbox_cmd_idx
];
1387 off
= (char *)pkt
- (char *)mly
->mly_mmbox
;
1389 bus_dmamap_sync(mly
->mly_dmat
, mly
->mly_mmbox_dmamap
,
1390 off
, sizeof(mly
->mly_mmbox
->mmm_command
[0]),
1391 BUS_DMASYNC_POSTWRITE
| BUS_DMASYNC_POSTREAD
);
1393 /* Check to see if the next index is free yet. */
1394 if (pkt
->mmbox
.flag
!= 0) {
1399 /* Copy in new command */
1400 memcpy(pkt
->mmbox
.data
, mc
->mc_packet
->mmbox
.data
,
1401 sizeof(pkt
->mmbox
.data
));
1403 /* Copy flag last. */
1404 pkt
->mmbox
.flag
= mc
->mc_packet
->mmbox
.flag
;
1406 bus_dmamap_sync(mly
->mly_dmat
, mly
->mly_mmbox_dmamap
,
1407 off
, sizeof(mly
->mly_mmbox
->mmm_command
[0]),
1408 BUS_DMASYNC_PREWRITE
| BUS_DMASYNC_PREREAD
);
1410 /* Signal controller and update index. */
1411 mly_outb(mly
, mly
->mly_idbr
, MLY_AM_CMDSENT
);
1412 mly
->mly_mmbox_cmd_idx
=
1413 (mly
->mly_mmbox_cmd_idx
+ 1) % MLY_MMBOX_COMMANDS
;
1421 * Pick up completed commands from the controller and handle accordingly.
1424 mly_intr(void *cookie
)
1427 union mly_status_packet
*sp
;
1430 struct mly_softc
*mly
;
1436 * Pick up hardware-mailbox commands.
1438 if (mly_odbr_true(mly
, MLY_HM_STSREADY
)) {
1439 slot
= mly_inw(mly
, mly
->mly_status_mailbox
);
1441 if (slot
< MLY_SLOT_MAX
) {
1442 mc
= mly
->mly_ccbs
+ (slot
- MLY_SLOT_START
);
1444 mly_inb(mly
, mly
->mly_status_mailbox
+ 2);
1446 mly_inb(mly
, mly
->mly_status_mailbox
+ 3);
1448 mly_inl(mly
, mly
->mly_status_mailbox
+ 4);
1450 mly_ccb_complete(mly
, mc
);
1452 /* Slot 0xffff may mean "extremely bogus command". */
1453 printf("%s: got HM completion for illegal slot %u\n",
1454 device_xname(&mly
->mly_dv
), slot
);
1457 /* Unconditionally acknowledge status. */
1458 mly_outb(mly
, mly
->mly_odbr
, MLY_HM_STSREADY
);
1459 mly_outb(mly
, mly
->mly_idbr
, MLY_HM_STSACK
);
1464 * Pick up memory-mailbox commands.
1466 if (mly_odbr_true(mly
, MLY_AM_STSREADY
)) {
1468 sp
= &mly
->mly_mmbox
->mmm_status
[mly
->mly_mmbox_sts_idx
];
1469 off
= (char *)sp
- (char *)mly
->mly_mmbox
;
1471 bus_dmamap_sync(mly
->mly_dmat
, mly
->mly_mmbox_dmamap
,
1472 off
, sizeof(mly
->mly_mmbox
->mmm_command
[0]),
1473 BUS_DMASYNC_POSTWRITE
| BUS_DMASYNC_POSTREAD
);
1475 /* Check for more status. */
1476 if (sp
->mmbox
.flag
== 0)
1479 /* Get slot number. */
1480 slot
= le16toh(sp
->status
.command_id
);
1481 if (slot
< MLY_SLOT_MAX
) {
1482 mc
= mly
->mly_ccbs
+ (slot
- MLY_SLOT_START
);
1483 mc
->mc_status
= sp
->status
.status
;
1484 mc
->mc_sense
= sp
->status
.sense_length
;
1485 mc
->mc_resid
= le32toh(sp
->status
.residue
);
1486 mly_ccb_complete(mly
, mc
);
1489 * Slot 0xffff may mean "extremely bogus
1492 printf("%s: got AM completion for illegal "
1493 "slot %u at %d\n", device_xname(&mly
->mly_dv
),
1494 slot
, mly
->mly_mmbox_sts_idx
);
1497 /* Clear and move to next index. */
1499 mly
->mly_mmbox_sts_idx
=
1500 (mly
->mly_mmbox_sts_idx
+ 1) % MLY_MMBOX_STATUS
;
1503 /* Acknowledge that we have collected status value(s). */
1504 mly_outb(mly
, mly
->mly_odbr
, MLY_AM_STSREADY
);
1511 if (forus
&& ! SIMPLEQ_EMPTY(&mly
->mly_ccb_queue
))
1512 mly_ccb_enqueue(mly
, NULL
);
1518 * Process completed commands
1521 mly_ccb_complete(struct mly_softc
*mly
, struct mly_ccb
*mc
)
1523 void (*complete
)(struct mly_softc
*, struct mly_ccb
*);
1525 bus_dmamap_sync(mly
->mly_dmat
, mly
->mly_pkt_dmamap
,
1526 mc
->mc_packetphys
- mly
->mly_pkt_busaddr
,
1527 sizeof(union mly_cmd_packet
),
1528 BUS_DMASYNC_POSTREAD
| BUS_DMASYNC_POSTWRITE
);
1530 complete
= mc
->mc_complete
;
1531 mc
->mc_flags
|= MLY_CCB_COMPLETE
;
1534 * Call completion handler or wake up sleeping consumer.
1536 if (complete
!= NULL
)
1537 (*complete
)(mly
, mc
);
1543 * Allocate a command.
1546 mly_ccb_alloc(struct mly_softc
*mly
, struct mly_ccb
**mcp
)
1552 mc
= SLIST_FIRST(&mly
->mly_ccb_free
);
1554 SLIST_REMOVE_HEAD(&mly
->mly_ccb_free
, mc_link
.slist
);
1558 return (mc
== NULL
? EAGAIN
: 0);
1562 * Release a command back to the freelist.
1565 mly_ccb_free(struct mly_softc
*mly
, struct mly_ccb
*mc
)
1570 * Fill in parts of the command that may cause confusion if a
1571 * consumer doesn't when we are later allocated.
1575 mc
->mc_complete
= NULL
;
1576 mc
->mc_private
= NULL
;
1577 mc
->mc_packet
->generic
.command_control
= 0;
1580 * By default, we set up to overwrite the command packet with sense
1583 mc
->mc_packet
->generic
.sense_buffer_address
=
1584 htole64(mc
->mc_packetphys
);
1585 mc
->mc_packet
->generic
.maximum_sense_size
=
1586 sizeof(union mly_cmd_packet
);
1589 SLIST_INSERT_HEAD(&mly
->mly_ccb_free
, mc
, mc_link
.slist
);
1594 * Allocate and initialize command and packet structures.
1596 * If the controller supports fewer than MLY_MAX_CCBS commands, limit our
1597 * allocation to that number. If we don't yet know how many commands the
1598 * controller supports, allocate a very small set (suitable for initialization
1602 mly_alloc_ccbs(struct mly_softc
*mly
)
1607 if (mly
->mly_controllerinfo
== NULL
)
1608 mly
->mly_ncmds
= MLY_CCBS_RESV
;
1610 i
= le16toh(mly
->mly_controllerinfo
->maximum_parallel_commands
);
1611 mly
->mly_ncmds
= min(MLY_MAX_CCBS
, i
);
1615 * Allocate enough space for all the command packets in one chunk
1616 * and map them permanently into controller-visible space.
1618 rv
= mly_dmamem_alloc(mly
,
1619 mly
->mly_ncmds
* sizeof(union mly_cmd_packet
),
1620 &mly
->mly_pkt_dmamap
, (void **)&mly
->mly_pkt
,
1621 &mly
->mly_pkt_busaddr
, &mly
->mly_pkt_seg
);
1625 mly
->mly_ccbs
= malloc(sizeof(struct mly_ccb
) * mly
->mly_ncmds
,
1626 M_DEVBUF
, M_NOWAIT
|M_ZERO
);
1628 for (i
= 0; i
< mly
->mly_ncmds
; i
++) {
1629 mc
= mly
->mly_ccbs
+ i
;
1630 mc
->mc_slot
= MLY_SLOT_START
+ i
;
1631 mc
->mc_packet
= mly
->mly_pkt
+ i
;
1632 mc
->mc_packetphys
= mly
->mly_pkt_busaddr
+
1633 (i
* sizeof(union mly_cmd_packet
));
1635 rv
= bus_dmamap_create(mly
->mly_dmat
, MLY_MAX_XFER
,
1636 MLY_MAX_SEGS
, MLY_MAX_XFER
, 0,
1637 BUS_DMA_NOWAIT
| BUS_DMA_ALLOCNOW
,
1640 mly_release_ccbs(mly
);
1644 mly_ccb_free(mly
, mc
);
1651 * Free all the storage held by commands.
1653 * Must be called with all commands on the free list.
1656 mly_release_ccbs(struct mly_softc
*mly
)
1660 /* Throw away command buffer DMA maps. */
1661 while (mly_ccb_alloc(mly
, &mc
) == 0)
1662 bus_dmamap_destroy(mly
->mly_dmat
, mc
->mc_datamap
);
1664 /* Release CCB storage. */
1665 free(mly
->mly_ccbs
, M_DEVBUF
);
1667 /* Release the packet storage. */
1668 mly_dmamem_free(mly
, mly
->mly_ncmds
* sizeof(union mly_cmd_packet
),
1669 mly
->mly_pkt_dmamap
, (void *)mly
->mly_pkt
, &mly
->mly_pkt_seg
);
1673 * Map a command into controller-visible space.
1676 mly_ccb_map(struct mly_softc
*mly
, struct mly_ccb
*mc
)
1678 struct mly_cmd_generic
*gen
;
1679 struct mly_sg_entry
*sg
;
1680 bus_dma_segment_t
*ds
;
1684 /* Don't map more than once. */
1685 if ((mc
->mc_flags
& MLY_CCB_MAPPED
) != 0)
1686 panic("mly_ccb_map: already mapped");
1687 mc
->mc_flags
|= MLY_CCB_MAPPED
;
1689 /* Does the command have a data buffer? */
1690 if (mc
->mc_data
== NULL
)
1691 panic("mly_ccb_map: no data buffer");
1694 rv
= bus_dmamap_load(mly
->mly_dmat
, mc
->mc_datamap
, mc
->mc_data
,
1695 mc
->mc_length
, NULL
, BUS_DMA_NOWAIT
| BUS_DMA_STREAMING
|
1696 ((mc
->mc_flags
& MLY_CCB_DATAIN
) != 0 ?
1697 BUS_DMA_READ
: BUS_DMA_WRITE
));
1701 gen
= &mc
->mc_packet
->generic
;
1704 * Can we use the transfer structure directly?
1706 if ((nseg
= mc
->mc_datamap
->dm_nsegs
) <= 2) {
1708 sg
= &gen
->transfer
.direct
.sg
[0];
1710 mc
->mc_sgoff
= (mc
->mc_slot
- MLY_SLOT_START
) *
1712 sg
= mly
->mly_sg
+ mc
->mc_sgoff
;
1713 gen
->command_control
|= MLY_CMDCTL_EXTENDED_SG_TABLE
;
1714 gen
->transfer
.indirect
.entries
[0] = htole16(nseg
);
1715 gen
->transfer
.indirect
.table_physaddr
[0] =
1716 htole64(mly
->mly_sg_busaddr
+
1717 (mc
->mc_sgoff
* sizeof(struct mly_sg_entry
)));
1721 * Fill the S/G table.
1723 for (ds
= mc
->mc_datamap
->dm_segs
; nseg
!= 0; nseg
--, sg
++, ds
++) {
1724 sg
->physaddr
= htole64(ds
->ds_addr
);
1725 sg
->length
= htole64(ds
->ds_len
);
1729 * Sync up the data map.
1731 if ((mc
->mc_flags
& MLY_CCB_DATAIN
) != 0)
1732 flg
= BUS_DMASYNC_PREREAD
;
1733 else /* if ((mc->mc_flags & MLY_CCB_DATAOUT) != 0) */ {
1734 gen
->command_control
|= MLY_CMDCTL_DATA_DIRECTION
;
1735 flg
= BUS_DMASYNC_PREWRITE
;
1738 bus_dmamap_sync(mly
->mly_dmat
, mc
->mc_datamap
, 0, mc
->mc_length
, flg
);
1741 * Sync up the chained S/G table, if we're using one.
1743 if (mc
->mc_sgoff
== -1)
1746 bus_dmamap_sync(mly
->mly_dmat
, mly
->mly_sg_dmamap
, mc
->mc_sgoff
,
1747 MLY_SGL_SIZE
, BUS_DMASYNC_PREWRITE
);
1753 * Unmap a command from controller-visible space.
1756 mly_ccb_unmap(struct mly_softc
*mly
, struct mly_ccb
*mc
)
1761 if ((mc
->mc_flags
& MLY_CCB_MAPPED
) == 0)
1762 panic("mly_ccb_unmap: not mapped");
1763 mc
->mc_flags
&= ~MLY_CCB_MAPPED
;
1766 if ((mc
->mc_flags
& MLY_CCB_DATAIN
) != 0)
1767 flg
= BUS_DMASYNC_POSTREAD
;
1768 else /* if ((mc->mc_flags & MLY_CCB_DATAOUT) != 0) */
1769 flg
= BUS_DMASYNC_POSTWRITE
;
1771 bus_dmamap_sync(mly
->mly_dmat
, mc
->mc_datamap
, 0, mc
->mc_length
, flg
);
1772 bus_dmamap_unload(mly
->mly_dmat
, mc
->mc_datamap
);
1774 if (mc
->mc_sgoff
== -1)
1777 bus_dmamap_sync(mly
->mly_dmat
, mly
->mly_sg_dmamap
, mc
->mc_sgoff
,
1778 MLY_SGL_SIZE
, BUS_DMASYNC_POSTWRITE
);
1782 * Adjust the size of each I/O before it passes to the SCSI layer.
1785 mly_scsipi_minphys(struct buf
*bp
)
1788 if (bp
->b_bcount
> MLY_MAX_XFER
)
1789 bp
->b_bcount
= MLY_MAX_XFER
;
1794 * Start a SCSI command.
1797 mly_scsipi_request(struct scsipi_channel
*chan
, scsipi_adapter_req_t req
,
1801 struct mly_cmd_scsi_small
*ss
;
1802 struct scsipi_xfer
*xs
;
1803 struct scsipi_periph
*periph
;
1804 struct mly_softc
*mly
;
1805 struct mly_btl
*btl
;
1808 mly
= device_private(chan
->chan_adapter
->adapt_dev
);
1811 case ADAPTER_REQ_RUN_XFER
:
1813 periph
= xs
->xs_periph
;
1814 btl
= &mly
->mly_btl
[chan
->chan_channel
][periph
->periph_target
];
1816 tmp
= btl
->mb_flags
;
1820 * Check for I/O attempt to a protected or non-existant
1823 if ((tmp
& MLY_BTL_PROTECTED
) != 0) {
1824 xs
->error
= XS_SELTIMEOUT
;
1830 /* XXX Increase if/when we support large SCSI commands. */
1831 if (xs
->cmdlen
> MLY_CMD_SCSI_SMALL_CDB
) {
1832 printf("%s: cmd too large\n", device_xname(&mly
->mly_dv
));
1833 xs
->error
= XS_DRIVER_STUFFUP
;
1839 if (mly_ccb_alloc(mly
, &mc
)) {
1840 xs
->error
= XS_RESOURCE_SHORTAGE
;
1845 /* Build the command. */
1846 mc
->mc_data
= xs
->data
;
1847 mc
->mc_length
= xs
->datalen
;
1848 mc
->mc_complete
= mly_scsipi_complete
;
1849 mc
->mc_private
= xs
;
1851 /* Build the packet for the controller. */
1852 ss
= &mc
->mc_packet
->scsi_small
;
1853 ss
->opcode
= MDACMD_SCSI
;
1856 * XXX FreeBSD does this, but it doesn't fix anything,
1857 * XXX and appears potentially harmful.
1859 ss
->command_control
|= MLY_CMDCTL_DISABLE_DISCONNECT
;
1862 ss
->data_size
= htole32(xs
->datalen
);
1863 _lto3l(MLY_PHYADDR(0, chan
->chan_channel
,
1864 periph
->periph_target
, periph
->periph_lun
), ss
->addr
);
1866 if (xs
->timeout
< 60 * 1000)
1867 ss
->timeout
= xs
->timeout
/ 1000 |
1868 MLY_TIMEOUT_SECONDS
;
1869 else if (xs
->timeout
< 60 * 60 * 1000)
1870 ss
->timeout
= xs
->timeout
/ (60 * 1000) |
1871 MLY_TIMEOUT_MINUTES
;
1873 ss
->timeout
= xs
->timeout
/ (60 * 60 * 1000) |
1876 ss
->maximum_sense_size
= sizeof(xs
->sense
);
1877 ss
->cdb_length
= xs
->cmdlen
;
1878 memcpy(ss
->cdb
, xs
->cmd
, xs
->cmdlen
);
1880 if (mc
->mc_length
!= 0) {
1881 if ((xs
->xs_control
& XS_CTL_DATA_OUT
) != 0)
1882 mc
->mc_flags
|= MLY_CCB_DATAOUT
;
1883 else /* if ((xs->xs_control & XS_CTL_DATA_IN) != 0) */
1884 mc
->mc_flags
|= MLY_CCB_DATAIN
;
1886 if (mly_ccb_map(mly
, mc
) != 0) {
1887 xs
->error
= XS_DRIVER_STUFFUP
;
1888 mly_ccb_free(mly
, mc
);
1895 * Give the command to the controller.
1897 if ((xs
->xs_control
& XS_CTL_POLL
) != 0) {
1898 if (mly_ccb_poll(mly
, mc
, xs
->timeout
+ 5000)) {
1899 xs
->error
= XS_REQUEUE
;
1900 if (mc
->mc_length
!= 0)
1901 mly_ccb_unmap(mly
, mc
);
1902 mly_ccb_free(mly
, mc
);
1906 mly_ccb_enqueue(mly
, mc
);
1910 case ADAPTER_REQ_GROW_RESOURCES
:
1916 case ADAPTER_REQ_SET_XFER_MODE
:
1918 * We can't change the transfer mode, but at least let
1919 * scsipi know what the adapter has negotiated.
1921 mly_get_xfer_mode(mly
, chan
->chan_channel
, arg
);
1927 * Handle completion of a SCSI command.
1930 mly_scsipi_complete(struct mly_softc
*mly
, struct mly_ccb
*mc
)
1932 struct scsipi_xfer
*xs
;
1933 struct scsipi_channel
*chan
;
1934 struct scsipi_inquiry_data
*inq
;
1935 struct mly_btl
*btl
;
1939 xs
= mc
->mc_private
;
1940 xs
->status
= mc
->mc_status
;
1943 * XXX The `resid' value as returned by the controller appears to be
1944 * bogus, so we always set it to zero. Is it perhaps the transfer
1947 xs
->resid
= 0; /* mc->mc_resid; */
1949 if (mc
->mc_length
!= 0)
1950 mly_ccb_unmap(mly
, mc
);
1952 switch (mc
->mc_status
) {
1955 * In order to report logical device type and status, we
1956 * overwrite the result of the INQUIRY command to logical
1959 if (xs
->cmd
->opcode
== INQUIRY
) {
1960 chan
= xs
->xs_periph
->periph_channel
;
1961 target
= xs
->xs_periph
->periph_target
;
1962 btl
= &mly
->mly_btl
[chan
->chan_channel
][target
];
1965 if ((btl
->mb_flags
& MLY_BTL_LOGICAL
) != 0) {
1966 inq
= (struct scsipi_inquiry_data
*)xs
->data
;
1967 mly_padstr(inq
->vendor
, "MYLEX", 8);
1968 p
= mly_describe_code(mly_table_device_type
,
1970 mly_padstr(inq
->product
, p
, 16);
1971 p
= mly_describe_code(mly_table_device_state
,
1973 mly_padstr(inq
->revision
, p
, 4);
1978 xs
->error
= XS_NOERROR
;
1983 if (sl
> sizeof(xs
->sense
.scsi_sense
))
1984 sl
= sizeof(xs
->sense
.scsi_sense
);
1985 memcpy(&xs
->sense
.scsi_sense
, mc
->mc_packet
, sl
);
1986 xs
->error
= XS_SENSE
;
1990 case SCSI_QUEUE_FULL
:
1991 xs
->error
= XS_BUSY
;
1995 printf("%s: unknown SCSI status 0x%x\n",
1996 device_xname(&mly
->mly_dv
), xs
->status
);
1997 xs
->error
= XS_DRIVER_STUFFUP
;
2001 mly_ccb_free(mly
, mc
);
2006 * Notify scsipi about a target's transfer mode.
2009 mly_get_xfer_mode(struct mly_softc
*mly
, int bus
, struct scsipi_xfer_mode
*xm
)
2011 struct mly_btl
*btl
;
2014 btl
= &mly
->mly_btl
[bus
][xm
->xm_target
];
2019 if ((btl
->mb_flags
& MLY_BTL_PHYSICAL
) != 0) {
2020 if (btl
->mb_speed
== 0) {
2024 xm
->xm_period
= 12; /* XXX */
2025 xm
->xm_offset
= 8; /* XXX */
2026 xm
->xm_mode
|= PERIPH_CAP_SYNC
; /* XXX */
2029 switch (btl
->mb_width
) {
2031 xm
->xm_mode
= PERIPH_CAP_WIDE32
;
2034 xm
->xm_mode
= PERIPH_CAP_WIDE16
;
2040 } else /* ((btl->mb_flags & MLY_BTL_LOGICAL) != 0) */ {
2041 xm
->xm_mode
= PERIPH_CAP_WIDE16
| PERIPH_CAP_SYNC
;
2046 if ((btl
->mb_flags
& MLY_BTL_TQING
) != 0)
2047 xm
->xm_mode
|= PERIPH_CAP_TQING
;
2051 scsipi_async_event(&mly
->mly_chans
[bus
], ASYNC_EVENT_XFER_MODE
, xm
);
2055 * ioctl hook; used here only to initiate low-level rescans.
2058 mly_scsipi_ioctl(struct scsipi_channel
*chan
, u_long cmd
, void *data
,
2059 int flag
, struct proc
*p
)
2061 struct mly_softc
*mly
;
2064 mly
= device_private(chan
->chan_adapter
->adapt_dev
);
2068 mly_scan_channel(mly
, chan
->chan_channel
);
2080 * Handshake with the firmware while the card is being initialized.
2083 mly_fwhandshake(struct mly_softc
*mly
)
2085 u_int8_t error
, param0
, param1
;
2090 /* Set HM_STSACK and let the firmware initialize. */
2091 mly_outb(mly
, mly
->mly_idbr
, MLY_HM_STSACK
);
2092 DELAY(1000); /* too short? */
2094 /* If HM_STSACK is still true, the controller is initializing. */
2095 if (!mly_idbr_true(mly
, MLY_HM_STSACK
))
2098 printf("%s: controller initialization started\n",
2099 device_xname(&mly
->mly_dv
));
2102 * Spin waiting for initialization to finish, or for a message to be
2105 while (mly_idbr_true(mly
, MLY_HM_STSACK
)) {
2106 /* Check for a message */
2107 if (!mly_error_valid(mly
))
2110 error
= mly_inb(mly
, mly
->mly_error_status
) & ~MLY_MSG_EMPTY
;
2111 param0
= mly_inb(mly
, mly
->mly_cmd_mailbox
);
2112 param1
= mly_inb(mly
, mly
->mly_cmd_mailbox
+ 1);
2115 case MLY_MSG_SPINUP
:
2117 printf("%s: drive spinup in progress\n",
2118 device_xname(&mly
->mly_dv
));
2123 case MLY_MSG_RACE_RECOVERY_FAIL
:
2124 printf("%s: mirror race recovery failed - \n",
2125 device_xname(&mly
->mly_dv
));
2126 printf("%s: one or more drives offline\n",
2127 device_xname(&mly
->mly_dv
));
2130 case MLY_MSG_RACE_IN_PROGRESS
:
2131 printf("%s: mirror race recovery in progress\n",
2132 device_xname(&mly
->mly_dv
));
2135 case MLY_MSG_RACE_ON_CRITICAL
:
2136 printf("%s: mirror race recovery on critical drive\n",
2137 device_xname(&mly
->mly_dv
));
2140 case MLY_MSG_PARITY_ERROR
:
2141 printf("%s: FATAL MEMORY PARITY ERROR\n",
2142 device_xname(&mly
->mly_dv
));
2146 printf("%s: unknown initialization code 0x%x\n",
2147 device_xname(&mly
->mly_dv
), error
);
2156 * Space-fill a character string
2159 mly_padstr(char *dst
, const char *src
, int len
)
2171 * Allocate DMA safe memory.
2174 mly_dmamem_alloc(struct mly_softc
*mly
, int size
, bus_dmamap_t
*dmamap
,
2175 void **kva
, bus_addr_t
*paddr
, bus_dma_segment_t
*seg
)
2177 int rseg
, rv
, state
;
2181 if ((rv
= bus_dmamem_alloc(mly
->mly_dmat
, size
, PAGE_SIZE
, 0,
2182 seg
, 1, &rseg
, BUS_DMA_NOWAIT
)) != 0) {
2183 aprint_error_dev(&mly
->mly_dv
, "dmamem_alloc = %d\n", rv
);
2189 if ((rv
= bus_dmamem_map(mly
->mly_dmat
, seg
, 1, size
, kva
,
2190 BUS_DMA_NOWAIT
| BUS_DMA_COHERENT
)) != 0) {
2191 aprint_error_dev(&mly
->mly_dv
, "dmamem_map = %d\n", rv
);
2197 if ((rv
= bus_dmamap_create(mly
->mly_dmat
, size
, size
, 1, 0,
2198 BUS_DMA_NOWAIT
, dmamap
)) != 0) {
2199 aprint_error_dev(&mly
->mly_dv
, "dmamap_create = %d\n", rv
);
2205 if ((rv
= bus_dmamap_load(mly
->mly_dmat
, *dmamap
, *kva
, size
,
2206 NULL
, BUS_DMA_NOWAIT
)) != 0) {
2207 aprint_error_dev(&mly
->mly_dv
, "dmamap_load = %d\n", rv
);
2211 *paddr
= (*dmamap
)->dm_segs
[0].ds_addr
;
2212 memset(*kva
, 0, size
);
2217 bus_dmamap_destroy(mly
->mly_dmat
, *dmamap
);
2219 bus_dmamem_unmap(mly
->mly_dmat
, *kva
, size
);
2221 bus_dmamem_free(mly
->mly_dmat
, seg
, 1);
2227 * Free DMA safe memory.
2230 mly_dmamem_free(struct mly_softc
*mly
, int size
, bus_dmamap_t dmamap
,
2231 void *kva
, bus_dma_segment_t
*seg
)
2234 bus_dmamap_unload(mly
->mly_dmat
, dmamap
);
2235 bus_dmamap_destroy(mly
->mly_dmat
, dmamap
);
2236 bus_dmamem_unmap(mly
->mly_dmat
, kva
, size
);
2237 bus_dmamem_free(mly
->mly_dmat
, seg
, 1);
2242 * Accept an open operation on the control device.
2245 mlyopen(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
2247 struct mly_softc
*mly
;
2249 if ((mly
= device_lookup_private(&mly_cd
, minor(dev
))) == NULL
)
2251 if ((mly
->mly_state
& MLY_STATE_INITOK
) == 0)
2253 if ((mly
->mly_state
& MLY_STATE_OPEN
) != 0)
2256 mly
->mly_state
|= MLY_STATE_OPEN
;
2261 * Accept the last close on the control device.
2264 mlyclose(dev_t dev
, int flag
, int mode
,
2267 struct mly_softc
*mly
;
2269 mly
= device_lookup_private(&mly_cd
, minor(dev
));
2270 mly
->mly_state
&= ~MLY_STATE_OPEN
;
2275 * Handle control operations.
2278 mlyioctl(dev_t dev
, u_long cmd
, void *data
, int flag
,
2281 struct mly_softc
*mly
;
2284 mly
= device_lookup_private(&mly_cd
, minor(dev
));
2288 rv
= kauth_authorize_device_passthru(l
->l_cred
, dev
,
2289 KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_ALL
, data
);
2293 rv
= mly_user_command(mly
, (void *)data
);
2296 rv
= mly_user_health(mly
, (void *)data
);
2307 * Execute a command passed in from userspace.
2309 * The control structure contains the actual command for the controller, as
2310 * well as the user-space data pointer and data size, and an optional sense
2311 * buffer size/pointer. On completion, the data size is adjusted to the
2312 * command residual, and the sense buffer size to the size of the returned
2316 mly_user_command(struct mly_softc
*mly
, struct mly_user_command
*uc
)
2321 if ((rv
= mly_ccb_alloc(mly
, &mc
)) != 0)
2328 * Handle data size/direction.
2330 if ((mc
->mc_length
= abs(uc
->DataTransferLength
)) != 0) {
2331 if (mc
->mc_length
> MAXPHYS
) {
2336 mc
->mc_data
= malloc(mc
->mc_length
, M_DEVBUF
, M_WAITOK
);
2337 if (mc
->mc_data
== NULL
) {
2342 if (uc
->DataTransferLength
> 0) {
2343 mc
->mc_flags
|= MLY_CCB_DATAIN
;
2344 memset(mc
->mc_data
, 0, mc
->mc_length
);
2347 if (uc
->DataTransferLength
< 0) {
2348 mc
->mc_flags
|= MLY_CCB_DATAOUT
;
2349 rv
= copyin(uc
->DataTransferBuffer
, mc
->mc_data
,
2355 if ((rv
= mly_ccb_map(mly
, mc
)) != 0)
2360 /* Copy in the command and execute it. */
2361 memcpy(mc
->mc_packet
, &uc
->CommandMailbox
, sizeof(uc
->CommandMailbox
));
2363 if ((rv
= mly_ccb_wait(mly
, mc
, 60000)) != 0)
2366 /* Return the data to userspace. */
2367 if (uc
->DataTransferLength
> 0) {
2368 rv
= copyout(mc
->mc_data
, uc
->DataTransferBuffer
,
2374 /* Return the sense buffer to userspace. */
2375 if (uc
->RequestSenseLength
> 0 && mc
->mc_sense
> 0) {
2376 rv
= copyout(mc
->mc_packet
, uc
->RequestSenseBuffer
,
2377 min(uc
->RequestSenseLength
, mc
->mc_sense
));
2382 /* Return command results to userspace (caller will copy out). */
2383 uc
->DataTransferLength
= mc
->mc_resid
;
2384 uc
->RequestSenseLength
= min(uc
->RequestSenseLength
, mc
->mc_sense
);
2385 uc
->CommandStatus
= mc
->mc_status
;
2390 mly_ccb_unmap(mly
, mc
);
2391 if (mc
->mc_data
!= NULL
)
2392 free(mc
->mc_data
, M_DEVBUF
);
2393 mly_ccb_free(mly
, mc
);
2399 * Return health status to userspace. If the health change index in the
2400 * user structure does not match that currently exported by the controller,
2401 * we return the current status immediately. Otherwise, we block until
2402 * either interrupted or new status is delivered.
2405 mly_user_health(struct mly_softc
*mly
, struct mly_user_health
*uh
)
2407 struct mly_health_status mh
;
2410 /* Fetch the current health status from userspace. */
2411 rv
= copyin(uh
->HealthStatusBuffer
, &mh
, sizeof(mh
));
2415 /* spin waiting for a status update */
2417 if (mly
->mly_event_change
== mh
.change_counter
)
2418 rv
= tsleep(&mly
->mly_event_change
, PRIBIO
| PCATCH
,
2424 * Copy the controller's health status buffer out (there is
2425 * a race here if it changes again).
2427 rv
= copyout(&mly
->mly_mmbox
->mmm_health
.status
,
2428 uh
->HealthStatusBuffer
, sizeof(uh
->HealthStatusBuffer
));