1 /* $NetBSD: ld_amr.c,v 1.18 2009/05/06 10:34:32 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 * AMI RAID controller front-end for ld(4) driver.
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: ld_amr.c,v 1.18 2009/05/06 10:34:32 cegger Exp $");
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/kernel.h>
44 #include <sys/device.h>
47 #include <sys/endian.h>
54 #include <uvm/uvm_extern.h>
58 #include <dev/ldvar.h>
60 #include <dev/pci/pcireg.h>
61 #include <dev/pci/pcivar.h>
62 #include <dev/pci/amrreg.h>
63 #include <dev/pci/amrvar.h>
66 struct ld_softc sc_ld
;
70 static int ld_amr_dobio(struct ld_amr_softc
*, void *, int, int, int,
72 static int ld_amr_dump(struct ld_softc
*, void *, int, int);
73 static void ld_amr_handler(struct amr_ccb
*);
74 static int ld_amr_start(struct ld_softc
*, struct buf
*);
77 ld_amr_match(device_t parent
, cfdata_t match
, void *aux
)
84 ld_amr_attach(device_t parent
, device_t self
, void *aux
)
86 struct amr_attach_args
*amra
= aux
;
87 struct ld_amr_softc
*sc
= device_private(self
);
88 struct ld_softc
*ld
= &sc
->sc_ld
;
89 struct amr_softc
*amr
= device_private(parent
);
95 sc
->sc_hwunit
= amra
->amra_unit
;
96 ld
->sc_maxxfer
= amr_max_xfer
;
97 ld
->sc_maxqueuecnt
= (amr
->amr_maxqueuecnt
- AMR_NCCB_RESV
)
99 ld
->sc_secperunit
= amr
->amr_drive
[sc
->sc_hwunit
].al_size
;
100 ld
->sc_secsize
= AMR_SECTOR_SIZE
;
101 ld
->sc_start
= ld_amr_start
;
102 ld
->sc_dump
= ld_amr_dump
;
104 if (ld
->sc_maxqueuecnt
> AMR_MAX_CMDS_PU
)
105 ld
->sc_maxqueuecnt
= AMR_MAX_CMDS_PU
;
108 * Print status information and attach to the ld driver proper.
110 statestr
= amr_drive_state(amr
->amr_drive
[sc
->sc_hwunit
].al_state
,
113 ld
->sc_flags
= LDF_ENABLED
;
114 aprint_normal(": RAID %d, %s\n",
115 amr
->amr_drive
[sc
->sc_hwunit
].al_properties
& AMR_DRV_RAID_MASK
,
121 CFATTACH_DECL_NEW(ld_amr
, sizeof(struct ld_amr_softc
),
122 ld_amr_match
, ld_amr_attach
, NULL
, NULL
);
125 ld_amr_dobio(struct ld_amr_softc
*sc
, void *data
, int datasize
,
126 int blkno
, int dowrite
, struct buf
*bp
)
129 struct amr_softc
*amr
;
130 struct amr_mailbox_cmd
*mb
;
133 amr
= device_private(device_parent(sc
->sc_ld
.sc_dv
));
135 if ((rv
= amr_ccb_alloc(amr
, &ac
)) != 0)
139 mb
->mb_command
= (dowrite
? AMR_CMD_LWRITE
: AMR_CMD_LREAD
);
140 mb
->mb_drive
= sc
->sc_hwunit
;
141 mb
->mb_blkcount
= htole16(datasize
/ AMR_SECTOR_SIZE
);
142 mb
->mb_lba
= htole32(blkno
);
144 rv
= amr_ccb_map(amr
, ac
, data
, datasize
,
145 (dowrite
? AC_XFER_OUT
: AC_XFER_IN
));
147 amr_ccb_free(amr
, ac
);
153 * Polled commands must not sit on the software queue. Wait
154 * up to 30 seconds for the command to complete.
157 rv
= amr_ccb_poll(amr
, ac
, 30000);
159 amr_ccb_unmap(amr
, ac
);
160 amr_ccb_free(amr
, ac
);
162 ac
->ac_handler
= ld_amr_handler
;
164 ac
->ac_dv
= sc
->sc_ld
.sc_dv
;
165 amr_ccb_enqueue(amr
, ac
);
173 ld_amr_start(struct ld_softc
*ld
, struct buf
*bp
)
176 return (ld_amr_dobio((struct ld_amr_softc
*)ld
, bp
->b_data
,
177 bp
->b_bcount
, bp
->b_rawblkno
, (bp
->b_flags
& B_READ
) == 0, bp
));
181 ld_amr_handler(struct amr_ccb
*ac
)
184 struct ld_amr_softc
*sc
;
185 struct amr_softc
*amr
;
188 sc
= device_private(ac
->ac_dv
);
189 amr
= device_private(device_parent(sc
->sc_ld
.sc_dv
));
191 if (ac
->ac_status
!= AMR_STATUS_SUCCESS
) {
192 printf("%s: cmd status 0x%02x\n", device_xname(sc
->sc_ld
.sc_dv
),
196 bp
->b_resid
= bp
->b_bcount
;
200 amr_ccb_unmap(amr
, ac
);
201 amr_ccb_free(amr
, ac
);
202 lddone(&sc
->sc_ld
, bp
);
206 ld_amr_dump(struct ld_softc
*ld
, void *data
, int blkno
, int blkcnt
)
208 struct ld_amr_softc
*sc
;
210 sc
= (struct ld_amr_softc
*)ld
;
212 return (ld_amr_dobio(sc
, data
, blkcnt
* ld
->sc_secsize
, blkno
, 1,