1 /* $NetBSD: ata_raid_promise.c,v 1.10 2008/02/02 16:15:02 mjf 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 Promise ATA RAID controller configuration blocks.
34 * Adapted to NetBSD by Jason R. Thorpe of Wasabi Systems, Inc.
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: ata_raid_promise.c,v 1.10 2008/02/02 16:15:02 mjf 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_promise(struct wd_softc
*sc
)
70 struct promise_raid_conf
*info
;
72 int bmajor
, error
, count
;
75 uint32_t cksum
, *ckptr
;
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
, PR_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 Promise config block\n", error
);
105 /* Check the signature. */
106 if (strncmp(info
->promise_id
, PR_MAGIC
, sizeof(PR_MAGIC
)) != 0) {
107 DPRINTF(("%s: Promise signature check failed\n",
108 device_xname(sc
->sc_dev
)));
113 /* Verify the checksum. */
114 for (cksum
= 0, ckptr
= (uint32_t *) info
, count
= 0; count
< 511;
117 if (cksum
!= *ckptr
) {
118 DPRINTF(("%s: Promise checksum failed\n",
119 device_xname(sc
->sc_dev
)));
124 if (info
->raid
.integrity
!= PR_I_VALID
) {
125 DPRINTF(("%s: Promise config block marked invalid\n",
126 device_xname(sc
->sc_dev
)));
132 * Lookup or allocate a new array info structure for
135 aai
= ata_raid_get_array_info(ATA_RAID_TYPE_PROMISE
,
136 info
->raid
.array_number
);
138 if (info
->raid
.generation
== 0 ||
139 info
->raid
.generation
> aai
->aai_generation
) {
140 aai
->aai_generation
= info
->raid
.generation
;
141 /* aai_type and aai_arrayno filled in already */
142 if ((info
->raid
.status
&
143 (PR_S_VALID
| PR_S_ONLINE
| PR_S_INITED
| PR_S_READY
)) ==
144 (PR_S_VALID
| PR_S_ONLINE
| PR_S_INITED
| PR_S_READY
)) {
145 aai
->aai_status
|= AAI_S_READY
;
146 if (info
->raid
.status
& PR_S_DEGRADED
)
147 aai
->aai_status
|= AAI_S_DEGRADED
;
149 aai
->aai_status
&= ~AAI_S_READY
;
151 switch (info
->raid
.type
) {
153 aai
->aai_level
= AAI_L_RAID0
;
157 aai
->aai_level
= AAI_L_RAID1
;
158 if (info
->raid
.array_width
> 1)
159 aai
->aai_level
|= AAI_L_RAID0
;
163 aai
->aai_level
= AAI_L_SPAN
;
167 aprint_error_dev(sc
->sc_dev
,
168 "unknown Promise RAID type 0x%02x\n",
174 aai
->aai_interleave
= 1U << info
->raid
.stripe_shift
;
175 aai
->aai_width
= info
->raid
.array_width
;
176 aai
->aai_ndisks
= info
->raid
.total_disks
;
177 aai
->aai_heads
= info
->raid
.heads
+ 1;
178 aai
->aai_sectors
= info
->raid
.sectors
;
179 aai
->aai_cylinders
= info
->raid
.cylinders
+ 1;
180 aai
->aai_capacity
= info
->raid
.total_sectors
;
182 aai
->aai_reserved
= 63;
184 for (disk
= 0; disk
< aai
->aai_ndisks
; disk
++) {
185 adi
= &aai
->aai_disks
[disk
];
187 if (info
->raid
.disk
[disk
].flags
& PR_F_ONLINE
)
188 adi
->adi_status
|= ADI_S_ONLINE
;
189 if (info
->raid
.disk
[disk
].flags
& PR_F_ASSIGNED
)
190 adi
->adi_status
|= ADI_S_ASSIGNED
;
191 if (info
->raid
.disk
[disk
].flags
& PR_F_SPARE
) {
192 adi
->adi_status
&= ~ADI_S_ONLINE
;
193 adi
->adi_status
|= ADI_S_SPARE
;
195 if (info
->raid
.disk
[disk
].flags
&
196 (PR_F_REDIR
| PR_F_DOWN
))
197 adi
->adi_status
&= ~ADI_S_ONLINE
;
200 adi
= &aai
->aai_disks
[info
->raid
.disk_number
];
201 if (adi
->adi_status
) {
202 adi
->adi_dev
= sc
->sc_dev
;
203 adi
->adi_sectors
= info
->raid
.disk_sectors
;
204 adi
->adi_compsize
= sc
->sc_capacity
- aai
->aai_reserved
;
210 free(info
, M_DEVBUF
);