1 /* $NetBSD: ata_raid.c,v 1.32 2008/09/11 11:08:50 tron Exp $ */
4 * Copyright (c) 2003 Wasabi Systems, Inc.
7 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by
20 * Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 * or promote products derived from this software without specific prior
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
39 * Support for autoconfiguration of RAID sets on ATA RAID controllers.
42 #include <sys/cdefs.h>
43 __KERNEL_RCSID(0, "$NetBSD: ata_raid.c,v 1.32 2008/09/11 11:08:50 tron Exp $");
45 #include <sys/param.h>
49 #include <sys/device.h>
51 #include <sys/disklabel.h>
52 #include <sys/fcntl.h>
53 #include <sys/malloc.h>
54 #include <sys/vnode.h>
57 #include <miscfs/specfs/specdev.h>
59 #include <dev/ata/atareg.h>
60 #include <dev/ata/atavar.h>
61 #include <dev/ata/wdvar.h>
63 #include <dev/ata/ata_raidreg.h>
64 #include <dev/ata/ata_raidvar.h>
69 #define DPRINTF(x) printf x
71 #define DPRINTF(x) /* nothing */
74 void ataraidattach(int);
76 static int ataraid_match(device_t
, cfdata_t
, void *);
77 static void ataraid_attach(device_t
, device_t
, void *);
78 static int ataraid_print(void *, const char *);
80 static int ata_raid_finalize(device_t
);
82 ataraid_array_info_list_t ataraid_array_info_list
=
83 TAILQ_HEAD_INITIALIZER(ataraid_array_info_list
);
84 u_int ataraid_array_info_count
;
86 CFATTACH_DECL_NEW(ataraid
, 0,
87 ataraid_match
, ataraid_attach
, NULL
, NULL
);
92 * Pseudo-device attach routine.
95 ataraidattach(int count
)
99 * Register a finalizer which will be used to actually configure
100 * the logical disks configured by ataraid.
102 if (config_finalize_register(NULL
, ata_raid_finalize
) != 0)
103 printf("WARNING: unable to register ATA RAID finalizer\n");
107 * ata_raid_type_name:
109 * Return the type of ATA RAID.
112 ata_raid_type_name(u_int type
)
114 static const char *ata_raid_type_names
[] = {
123 if (type
< __arraycount(ata_raid_type_names
))
124 return (ata_raid_type_names
[type
]);
132 * Autoconfiguration finalizer for ATA RAID.
135 ata_raid_finalize(device_t self
)
137 static struct cfdata ataraid_cfdata
= {
138 .cf_name
= "ataraid",
139 .cf_atname
= "ataraid",
141 .cf_fstate
= FSTATE_STAR
,
143 extern struct cfdriver ataraid_cd
;
144 static int done_once
;
148 * Since we only handle real hardware, we only need to be
155 if (TAILQ_EMPTY(&ataraid_array_info_list
))
158 error
= config_cfattach_attach(ataraid_cd
.cd_name
, &ataraid_ca
);
160 printf("%s: unable to register cfattach, error = %d\n",
161 ataraid_cd
.cd_name
, error
);
162 (void) config_cfdriver_detach(&ataraid_cd
);
166 if (config_attach_pseudo(&ataraid_cfdata
) == NULL
)
167 printf("%s: unable to attach an instance\n",
177 * Autoconfiguration glue: match routine.
180 ataraid_match(device_t parent
, cfdata_t cf
,
184 /* pseudo-device; always present */
191 * Autoconfiguration glue: attach routine. We attach the children.
194 ataraid_attach(device_t parent
, device_t self
,
197 struct ataraid_array_info
*aai
;
198 int locs
[ATARAIDCF_NLOCS
];
201 * We're a pseudo-device, so we get to announce our own
204 aprint_normal_dev(self
, "found %u RAID volume%s\n",
205 ataraid_array_info_count
,
206 ataraid_array_info_count
== 1 ? "" : "s");
208 TAILQ_FOREACH(aai
, &ataraid_array_info_list
, aai_list
) {
209 locs
[ATARAIDCF_VENDTYPE
] = aai
->aai_type
;
210 locs
[ATARAIDCF_UNIT
] = aai
->aai_arrayno
;
212 config_found_sm_loc(self
, "ataraid", locs
, aai
,
213 ataraid_print
, config_stdsubmatch
);
220 * Autoconfiguration glue: print routine.
223 ataraid_print(void *aux
, const char *pnp
)
225 struct ataraid_array_info
*aai
= aux
;
228 aprint_normal("block device at %s", pnp
);
229 aprint_normal(" vendtype %d unit %d", aai
->aai_type
, aai
->aai_arrayno
);
234 * ata_raid_check_component:
236 * Check the component for a RAID configuration structure.
237 * Called via autoconfiguration callback.
240 ata_raid_check_component(device_t self
)
242 struct wd_softc
*sc
= device_private(self
);
244 if (ata_raid_read_config_adaptec(sc
) == 0)
246 if (ata_raid_read_config_promise(sc
) == 0)
248 if (ata_raid_read_config_via(sc
) == 0)
250 if (ata_raid_read_config_nvidia(sc
) == 0)
252 if (ata_raid_read_config_jmicron(sc
) == 0)
254 if (ata_raid_read_config_intel(sc
) == 0)
258 struct ataraid_array_info
*
259 ata_raid_get_array_info(u_int type
, u_int arrayno
)
261 struct ataraid_array_info
*aai
, *laai
;
263 TAILQ_FOREACH(aai
, &ataraid_array_info_list
, aai_list
) {
264 if (aai
->aai_type
== type
&&
265 aai
->aai_arrayno
== arrayno
)
269 /* Need to allocate a new one. */
270 aai
= malloc(sizeof(*aai
), M_DEVBUF
, M_WAITOK
| M_ZERO
);
271 aai
->aai_type
= type
;
272 aai
->aai_arrayno
= arrayno
;
274 ataraid_array_info_count
++;
276 if (TAILQ_EMPTY(&ataraid_array_info_list
)) {
277 TAILQ_INSERT_TAIL(&ataraid_array_info_list
, aai
, aai_list
);
281 /* Sort it into the list: type first, then array number. */
282 TAILQ_FOREACH(laai
, &ataraid_array_info_list
, aai_list
) {
283 if (aai
->aai_type
< laai
->aai_type
) {
284 TAILQ_INSERT_BEFORE(laai
, aai
, aai_list
);
287 if (aai
->aai_type
== laai
->aai_type
&&
288 aai
->aai_arrayno
< laai
->aai_arrayno
) {
289 TAILQ_INSERT_BEFORE(laai
, aai
, aai_list
);
293 TAILQ_INSERT_TAIL(&ataraid_array_info_list
, aai
, aai_list
);
300 ata_raid_config_block_rw(struct vnode
*vp
, daddr_t blkno
, void *tbuf
,
301 size_t size
, int bflags
)
306 bp
= getiobuf(vp
, false);
308 bp
->b_bcount
= bp
->b_resid
= size
;
309 bp
->b_flags
= bflags
;
310 bp
->b_proc
= curproc
;
312 SET(bp
->b_cflags
, BC_BUSY
); /* mark buffer busy */
314 VOP_STRATEGY(vp
, bp
);