1 /* $NetBSD: ata_raid_adaptec.c,v 1.8 2008/03/18 20:46:36 cube Exp $ */
4 * Copyright (c) 2000,2001,2002 Søren Schmidt <sos@FreeBSD.org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer,
12 * without modification, immediately at the beginning of the file.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * Support for parsing Adaptec ATA RAID controller configuration blocks.
34 * Adapted to NetBSD by Allen K. Briggs
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: ata_raid_adaptec.c,v 1.8 2008/03/18 20:46:36 cube Exp $");
40 #include <sys/param.h>
44 #include <sys/device.h>
46 #include <sys/disklabel.h>
47 #include <sys/fcntl.h>
48 #include <sys/malloc.h>
49 #include <sys/vnode.h>
50 #include <sys/kauth.h>
52 #include <miscfs/specfs/specdev.h>
54 #include <dev/ata/atareg.h>
55 #include <dev/ata/atavar.h>
56 #include <dev/ata/wdvar.h>
58 #include <dev/ata/ata_raidreg.h>
59 #include <dev/ata/ata_raidvar.h>
62 #define DPRINTF(x) printf x
64 #define DPRINTF(x) /* nothing */
68 ata_raid_read_config_adaptec(struct wd_softc
*sc
)
70 struct adaptec_raid_conf
*info
;
71 struct atabus_softc
*atabus
;
76 struct ataraid_array_info
*aai
;
77 struct ataraid_disk_info
*adi
;
79 info
= malloc(sizeof(*info
), M_DEVBUF
, M_WAITOK
);
81 bmajor
= devsw_name2blk(device_xname(sc
->sc_dev
), NULL
, 0);
83 /* Get a vnode for the raw partition of this disk. */
84 dev
= MAKEDISKDEV(bmajor
, device_unit(sc
->sc_dev
), RAW_PART
);
85 error
= bdevvp(dev
, &vp
);
89 error
= VOP_OPEN(vp
, FREAD
, NOCRED
);
95 error
= ata_raid_config_block_rw(vp
, ADP_LBA(sc
), info
,
96 sizeof(*info
), B_READ
);
97 VOP_CLOSE(vp
, FREAD
, NOCRED
);
100 aprint_error_dev(sc
->sc_dev
,
101 "error %d reading Adaptec config block\n", error
);
105 info
->magic_0
= be32toh(info
->magic_0
);
106 info
->magic_1
= be32toh(info
->magic_1
);
107 info
->magic_2
= be32toh(info
->magic_2
);
108 info
->magic_3
= be32toh(info
->magic_3
);
109 info
->magic_4
= be32toh(info
->magic_4
);
110 /* Check the signature. */
111 if (info
->magic_0
!= ADP_MAGIC_0
|| info
->magic_3
!= ADP_MAGIC_3
) {
112 DPRINTF(("%s: Adaptec signature check failed\n",
113 device_xname(sc
->sc_dev
)));
119 * Lookup or allocate a new array info structure for
122 aai
= ata_raid_get_array_info(ATA_RAID_TYPE_ADAPTEC
,
123 be32toh(info
->configs
[0].disk_number
));
125 gen
= be32toh(info
->generation
);
127 if (gen
== 0 || gen
> aai
->aai_generation
) {
128 aai
->aai_generation
= gen
;
130 aai
->aai_status
= AAI_S_READY
;
132 switch (info
->configs
[0].type
) {
134 aai
->aai_level
= AAI_L_RAID0
;
135 aai
->aai_interleave
=
136 (be16toh(info
->configs
[0].stripe_sectors
) >> 1);
137 aai
->aai_width
= be16toh(info
->configs
[0].total_disks
);
141 aai
->aai_level
= AAI_L_RAID1
;
142 aai
->aai_interleave
= 0;
143 aai
->aai_width
= be16toh(info
->configs
[0].total_disks
)
148 aprint_error_dev(sc
->sc_dev
,
149 "unknown Adaptec RAID type 0x%02x\n",
150 info
->configs
[0].type
);
155 aai
->aai_type
= ATA_RAID_TYPE_ADAPTEC
;
156 aai
->aai_ndisks
= be16toh(info
->configs
[0].total_disks
);
157 aai
->aai_capacity
= be32toh(info
->configs
[0].sectors
);
158 aai
->aai_heads
= 255;
159 aai
->aai_sectors
= 63;
160 aai
->aai_cylinders
= aai
->aai_capacity
/ (63 * 255);
162 aai
->aai_reserved
= 17;
163 if (info
->configs
[0].name
)
164 strlcpy(aai
->aai_name
, info
->configs
[0].name
,
165 sizeof(aai
->aai_name
));
167 /* XXX - bogus. RAID1 shouldn't really have an interleave */
168 if (aai
->aai_interleave
== 0)
169 aai
->aai_interleave
= aai
->aai_capacity
;
172 atabus
= device_private(device_parent(sc
->sc_dev
));
173 drive
= atabus
->sc_chan
->ch_channel
;
174 if (drive
>= aai
->aai_ndisks
) {
175 aprint_error_dev(sc
->sc_dev
,
176 "drive number %d doesn't make sense within %d-disk "
177 "array\n", drive
, aai
->aai_ndisks
);
182 adi
= &aai
->aai_disks
[drive
];
183 adi
->adi_dev
= sc
->sc_dev
;
184 adi
->adi_status
= ADI_S_ONLINE
| ADI_S_ASSIGNED
;
185 adi
->adi_sectors
= aai
->aai_capacity
;
186 adi
->adi_compsize
= be32toh(info
->configs
[drive
+1].sectors
);
191 free(info
, M_DEVBUF
);