4 * Copyright (c) 2000 - 2008 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.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 * Support for parsing nVIDIA MediaShield RAID controller configuration blocks.
32 * Adapted to NetBSD by Tatoku Ogaito (tacha@NetBSD.org)
35 #include <sys/cdefs.h>
36 __KERNEL_RCSID(0, "$NetBSD$");
38 #include <sys/param.h>
42 #include <sys/device.h>
44 #include <sys/disklabel.h>
45 #include <sys/fcntl.h>
46 #include <sys/malloc.h>
47 #include <sys/vnode.h>
48 #include <sys/kauth.h>
50 #include <miscfs/specfs/specdev.h>
52 #include <dev/ata/atareg.h>
53 #include <dev/ata/atavar.h>
54 #include <dev/ata/wdvar.h>
56 #include <dev/ata/ata_raidreg.h>
57 #include <dev/ata/ata_raidvar.h>
60 #define DPRINTF(x) printf x
62 #define DPRINTF(x) /* nothing */
67 ata_raid_nvidia_type(int type
)
69 static char buffer
[16];
72 case NV_T_SPAN
: return "SPAN";
73 case NV_T_RAID0
: return "RAID0";
74 case NV_T_RAID1
: return "RAID1";
75 case NV_T_RAID3
: return "RAID3";
76 case NV_T_RAID5
: return "RAID5";
77 case NV_T_RAID01
: return "RAID0+1";
79 sprintf(buffer
, "UNKNOWN 0x%02x", type
);
85 ata_raid_nvidia_print_info(struct nvidia_raid_conf
*info
)
87 printf("******** ATA nVidia MediaShield Metadata ********\n");
88 printf("nvidia_id <%.8s>\n", info
->nvidia_id
);
89 printf("config_size %d\n", info
->config_size
);
90 printf("checksum 0x%08x\n", info
->checksum
);
91 printf("version 0x%04x\n", info
->version
);
92 printf("disk_number %d\n", info
->disk_number
);
93 printf("dummy_0 0x%02x\n", info
->dummy_0
);
94 printf("total_sectors %d\n", info
->total_sectors
);
95 printf("sectors_size %d\n", info
->sector_size
);
96 printf("serial %.16s\n", info
->serial
);
97 printf("revision %.4s\n", info
->revision
);
98 printf("dummy_1 0x%08x\n", info
->dummy_1
);
99 printf("magic_0 0x%08x\n", info
->magic_0
);
100 printf("magic_1 0x%016jx\n", info
->magic_1
);
101 printf("magic_2 0x%016jx\n", info
->magic_2
);
102 printf("flags 0x%02x\n", info
->flags
);
103 printf("array_width %d\n", info
->array_width
);
104 printf("total_disks %d\n", info
->total_disks
);
105 printf("dummy_2 0x%02x\n", info
->dummy_2
);
106 printf("type %s\n", ata_raid_nvidia_type(info
->type
));
107 printf("dummy_3 0x%04x\n", info
->dummy_3
);
108 printf("stripe_sectors %d\n", info
->stripe_sectors
);
109 printf("stripe_bytes %d\n", info
->stripe_bytes
);
110 printf("stripe_shift %d\n", info
->stripe_shift
);
111 printf("stripe_mask 0x%08x\n", info
->stripe_mask
);
112 printf("stripe_sizesectors %d\n", info
->stripe_sizesectors
);
113 printf("stripe_sizebytes %d\n", info
->stripe_sizebytes
);
114 printf("rebuild_lba %d\n", info
->rebuild_lba
);
115 printf("dummy_4 0x%08x\n", info
->dummy_4
);
116 printf("dummy_5 0x%08x\n", info
->dummy_5
);
117 printf("status 0x%08x\n", info
->status
);
118 printf("=================================================\n");
123 ata_raid_read_config_nvidia(struct wd_softc
*sc
)
125 struct nvidia_raid_conf
*info
;
127 int bmajor
, error
, count
;
129 uint32_t cksum
, *ckptr
;
130 struct ataraid_array_info
*aai
;
131 struct ataraid_disk_info
*adi
;
132 static struct _arrayno
{
135 struct _arrayno
*next
;
136 } arrayno
= { 0, 0, NULL
}, *anptr
;
138 info
= malloc(sizeof(*info
), M_DEVBUF
, M_WAITOK
);
140 bmajor
= devsw_name2blk(device_xname(sc
->sc_dev
), NULL
, 0);
142 /* Get a vnode for the raw partition of this disk. */
143 dev
= MAKEDISKDEV(bmajor
, device_unit(sc
->sc_dev
), RAW_PART
);
144 error
= bdevvp(dev
, &vp
);
148 error
= VOP_OPEN(vp
, FREAD
, NOCRED
);
154 error
= ata_raid_config_block_rw(vp
, NVIDIA_LBA(sc
), info
,
155 sizeof(*info
), B_READ
);
156 VOP_CLOSE(vp
, FREAD
, NOCRED
);
159 aprint_error_dev(sc
->sc_dev
,
160 "error %d reading nVidia MediaShield config block\n", error
);
164 #ifdef ATA_RAID_DEBUG
165 ata_raid_nvidia_print_info(info
);
168 /* Check the signature. */
169 if (strncmp(info
->nvidia_id
, NV_MAGIC
, strlen(NV_MAGIC
)) != 0) {
170 DPRINTF(("%s: nVidia signature check failed\n",
171 device_xname(sc
->sc_dev
)));
176 /* check if the checksum is OK */
177 for (cksum
= 0, ckptr
= (uint32_t *)info
, count
= 0; count
< info
->config_size
;
181 DPRINTF(("%s: nVidia checksum failed (0x%02x)\n",
182 device_xname(sc
->sc_dev
), cksum
));
188 * Lookup or allocate a new array info structure for
189 * this array. Since nVidia raid information does not
190 * provides array# directory, we must count the number.
191 * The available traces are magic_1 and magic_2.
193 for (anptr
= &arrayno
, count
= 0; anptr
->next
; anptr
= anptr
->next
, count
++) {
194 if (anptr
->magic1
== info
->magic_1
&&
195 anptr
->magic2
== info
->magic_2
)
198 if (anptr
->next
== NULL
) {
200 anptr
->magic1
= info
->magic_1
;
201 anptr
->magic2
= info
->magic_2
;
202 anptr
->next
= malloc(sizeof(arrayno
), M_DEVBUF
, M_WAITOK
);
204 aai
= ata_raid_get_array_info(ATA_RAID_TYPE_NVIDIA
, count
);
206 aai
->aai_status
= AAI_S_READY
;
207 if (info
->status
& NV_S_DEGRADED
)
208 aai
->aai_status
|= AAI_S_DEGRADED
;
210 switch (info
->type
) {
212 aai
->aai_level
= AAI_L_RAID0
;
216 aai
->aai_level
= AAI_L_RAID1
;
220 aai
->aai_level
= AAI_L_RAID5
;
224 aai
->aai_level
= AAI_L_RAID0
| AAI_L_RAID1
;
228 aai
->aai_level
= AAI_L_SPAN
;
232 aprint_error_dev(sc
->sc_dev
,
233 "unknown nVidia type 0x%02x\n", info
->type
);
238 aai
->aai_type
= ATA_RAID_TYPE_NVIDIA
;
239 aai
->aai_interleave
= info
->stripe_sectors
;
240 aai
->aai_width
= info
->array_width
;
242 aai
->aai_ndisks
= info
->total_disks
;
243 aai
->aai_capacity
= info
->total_sectors
;
244 aai
->aai_heads
= 255;
245 aai
->aai_sectors
= 63;
246 aai
->aai_cylinders
= aai
->aai_capacity
/ (aai
->aai_heads
* aai
->aai_sectors
);
248 aai
->aai_reserved
= 2;
250 adi
= &aai
->aai_disks
[info
->disk_number
];
251 adi
->adi_dev
= sc
->sc_dev
;
252 adi
->adi_status
= ADI_S_ONLINE
| ADI_S_ASSIGNED
;
253 adi
->adi_sectors
= aai
->aai_capacity
;
254 adi
->adi_compsize
= aai
->aai_capacity
/ info
->array_width
;
259 free(info
, M_DEVBUF
);