2 * Copyright (c) 2000,2001,2002 Søren Schmidt <sos@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer,
10 * without modification, immediately at the beginning of the file.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
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.
28 * $FreeBSD: src/sys/dev/ata/ata-raid.c,v 1.3.2.19 2003/01/30 07:19:59 sos Exp $
29 * $DragonFly: src/sys/dev/disk/ata/ata-raid.c,v 1.25 2006/12/23 00:26:15 swildner Exp $
33 #include <sys/param.h>
34 #include <sys/systm.h>
36 #include <sys/kernel.h>
37 #include <sys/malloc.h>
42 #include <sys/devicestat.h>
47 #include <sys/thread2.h>
53 /* device structures */
54 static d_open_t aropen
;
55 static d_strategy_t arstrategy
;
57 static struct dev_ops ar_ops
= {
58 { "ar", 157, D_DISK
},
63 .d_strategy
= arstrategy
,
67 static void ar_attach_raid(struct ar_softc
*, int);
68 static void ar_done(struct bio
*);
69 static void ar_sync_done(struct bio
*);
70 static void ar_config_changed(struct ar_softc
*, int);
71 static int ar_rebuild(struct ar_softc
*);
72 static int ar_highpoint_read_conf(struct ad_softc
*, struct ar_softc
**);
73 static int ar_highpoint_write_conf(struct ar_softc
*);
74 static int ar_promise_read_conf(struct ad_softc
*, struct ar_softc
**, int);
75 static int ar_promise_write_conf(struct ar_softc
*);
76 static int ar_rw(struct ad_softc
*, u_int32_t
, int, caddr_t
, int);
77 static struct ata_device
*ar_locate_disk(int);
80 static struct ar_softc
**ar_table
= NULL
;
81 static MALLOC_DEFINE(M_AR
, "AR driver", "ATA RAID driver");
84 ata_raiddisk_attach(struct ad_softc
*adp
)
90 for (array
= 0; array
< MAX_ARRAYS
; array
++) {
91 if (!(rdp
= ar_table
[array
]) || !rdp
->flags
)
94 for (disk
= 0; disk
< rdp
->total_disks
; disk
++) {
95 if ((rdp
->disks
[disk
].flags
& AR_DF_ASSIGNED
) &&
96 rdp
->disks
[disk
].device
== adp
->device
) {
97 ata_prtdev(rdp
->disks
[disk
].device
,
98 "inserted into ar%d disk%d as spare\n",
100 rdp
->disks
[disk
].flags
|= (AR_DF_PRESENT
| AR_DF_SPARE
);
101 AD_SOFTC(rdp
->disks
[disk
])->flags
= AD_F_RAID_SUBDISK
;
102 ar_config_changed(rdp
, 1);
110 ar_table
= kmalloc(sizeof(struct ar_soft
*) * MAX_ARRAYS
,
111 M_AR
, M_WAITOK
| M_ZERO
);
114 switch(adp
->device
->channel
->chiptype
) {
115 case 0x4d33105a: case 0x4d38105a: case 0x4d30105a:
116 case 0x0d30105a: case 0x4d68105a: case 0x6268105a:
117 case 0x4d69105a: case 0x5275105a: case 0x6269105a:
119 /* test RAID bit in PCI reg XXX */
120 return (ar_promise_read_conf(adp
, ar_table
, 0));
122 case 0x00041103: case 0x00051103: case 0x00081103:
123 return (ar_highpoint_read_conf(adp
, ar_table
));
126 return (ar_promise_read_conf(adp
, ar_table
, 1));
132 ata_raiddisk_detach(struct ad_softc
*adp
)
134 struct ar_softc
*rdp
;
138 for (array
= 0; array
< MAX_ARRAYS
; array
++) {
139 if (!(rdp
= ar_table
[array
]) || !rdp
->flags
)
141 for (disk
= 0; disk
< rdp
->total_disks
; disk
++) {
142 if (rdp
->disks
[disk
].device
== adp
->device
) {
143 ata_prtdev(rdp
->disks
[disk
].device
,
144 "deleted from ar%d disk%d\n", array
, disk
);
145 rdp
->disks
[disk
].flags
&= ~(AR_DF_PRESENT
| AR_DF_ONLINE
);
146 AD_SOFTC(rdp
->disks
[disk
])->flags
&= ~AD_F_RAID_SUBDISK
;
147 ar_config_changed(rdp
, 1);
159 struct ar_softc
*rdp
;
165 for (array
= 0; array
< MAX_ARRAYS
; array
++) {
166 if (!(rdp
= ar_table
[array
]) || !rdp
->flags
)
168 ar_attach_raid(rdp
, 0);
173 ar_attach_raid(struct ar_softc
*rdp
, int update
)
178 ar_config_changed(rdp
, update
);
179 dev
= disk_create(rdp
->lun
, &rdp
->disk
, 0, &ar_ops
);
181 dev
->si_iosize_max
= 256 * DEV_BSIZE
;
184 kprintf("ar%d: %lluMB <ATA ", rdp
->lun
, (unsigned long long)
185 (rdp
->total_sectors
/ ((1024L * 1024L) / DEV_BSIZE
)));
186 switch (rdp
->flags
& (AR_F_RAID0
| AR_F_RAID1
| AR_F_SPAN
)) {
188 kprintf("RAID0 "); break;
190 kprintf("RAID1 "); break;
192 kprintf("SPAN "); break;
193 case (AR_F_RAID0
| AR_F_RAID1
):
194 kprintf("RAID0+1 "); break;
196 kprintf("unknown 0x%x> ", rdp
->flags
);
199 kprintf("array> [%d/%d/%d] status: ",
200 rdp
->cylinders
, rdp
->heads
, rdp
->sectors
);
201 switch (rdp
->flags
& (AR_F_DEGRADED
| AR_F_READY
)) {
205 case (AR_F_DEGRADED
| AR_F_READY
):
212 kprintf(" subdisks:\n");
213 for (disk
= 0; disk
< rdp
->total_disks
; disk
++) {
214 if (rdp
->disks
[disk
].flags
& AR_DF_PRESENT
) {
215 if (rdp
->disks
[disk
].flags
& AR_DF_ONLINE
)
216 kprintf(" %d READY ", disk
);
217 else if (rdp
->disks
[disk
].flags
& AR_DF_SPARE
)
218 kprintf(" %d SPARE ", disk
);
220 kprintf(" %d FREE ", disk
);
221 ad_print(AD_SOFTC(rdp
->disks
[disk
]));
223 ata_enclosure_print(AD_SOFTC(rdp
->disks
[disk
])->device
);
225 else if (rdp
->disks
[disk
].flags
& AR_DF_ASSIGNED
)
226 kprintf(" %d DOWN\n", disk
);
228 kprintf(" %d INVALID no RAID config info on this disk\n", disk
);
233 ata_raid_create(struct raid_setup
*setup
)
235 struct ata_device
*atadev
;
236 struct ar_softc
*rdp
;
238 int ctlr
= 0, disk_size
= 0, total_disks
= 0;
241 ar_table
= kmalloc(sizeof(struct ar_soft
*) * MAX_ARRAYS
,
242 M_AR
, M_WAITOK
| M_ZERO
);
244 for (array
= 0; array
< MAX_ARRAYS
; array
++) {
245 if (!ar_table
[array
])
248 if (array
>= MAX_ARRAYS
)
251 rdp
= kmalloc(sizeof(struct ar_softc
), M_AR
, M_WAITOK
| M_ZERO
);
253 for (disk
= 0; disk
< setup
->total_disks
; disk
++) {
254 if ((atadev
= ar_locate_disk(setup
->disks
[disk
]))) {
255 rdp
->disks
[disk
].device
= atadev
;
256 if (AD_SOFTC(rdp
->disks
[disk
])->flags
& AD_F_RAID_SUBDISK
) {
257 setup
->disks
[disk
] = -1;
262 switch (rdp
->disks
[disk
].device
->channel
->chiptype
& 0xffff) {
264 ctlr
|= AR_F_HIGHPOINT_RAID
;
265 rdp
->disks
[disk
].disk_sectors
=
266 AD_SOFTC(rdp
->disks
[disk
])->total_secs
;
270 ctlr
|= AR_F_FREEBSD_RAID
;
274 ctlr
|= AR_F_PROMISE_RAID
;
275 rdp
->disks
[disk
].disk_sectors
=
276 PR_LBA(AD_SOFTC(rdp
->disks
[disk
]));
279 if ((rdp
->flags
& (AR_F_PROMISE_RAID
|AR_F_HIGHPOINT_RAID
)) &&
280 (rdp
->flags
& (AR_F_PROMISE_RAID
|AR_F_HIGHPOINT_RAID
)) !=
281 (ctlr
& (AR_F_PROMISE_RAID
|AR_F_HIGHPOINT_RAID
))) {
289 disk_size
= min(rdp
->disks
[disk
].disk_sectors
, disk_size
);
291 disk_size
= rdp
->disks
[disk
].disk_sectors
;
292 rdp
->disks
[disk
].flags
=
293 (AR_DF_PRESENT
| AR_DF_ASSIGNED
| AR_DF_ONLINE
);
298 setup
->disks
[disk
] = -1;
308 switch (setup
->type
) {
310 rdp
->flags
|= AR_F_RAID0
;
313 rdp
->flags
|= AR_F_RAID1
;
314 if (total_disks
!= 2) {
320 rdp
->flags
|= (AR_F_RAID0
| AR_F_RAID1
);
321 if (total_disks
% 2 != 0) {
327 rdp
->flags
|= AR_F_SPAN
;
331 for (disk
= 0; disk
< total_disks
; disk
++)
332 AD_SOFTC(rdp
->disks
[disk
])->flags
= AD_F_RAID_SUBDISK
;
335 if (rdp
->flags
& AR_F_RAID0
) {
338 while (setup
->interleave
>>= 1)
340 if (rdp
->flags
& AR_F_PROMISE_RAID
)
341 rdp
->interleave
= min(max(2, 1 << bit
), 2048);
342 if (rdp
->flags
& AR_F_HIGHPOINT_RAID
)
343 rdp
->interleave
= min(max(32, 1 << bit
), 128);
345 rdp
->total_disks
= total_disks
;
346 rdp
->width
= total_disks
/ ((rdp
->flags
& AR_F_RAID1
) ? 2 : 1);
347 rdp
->total_sectors
= disk_size
* rdp
->width
;
350 rdp
->cylinders
= rdp
->total_sectors
/ (255 * 63);
351 if (rdp
->flags
& AR_F_PROMISE_RAID
) {
355 if (rdp
->flags
& AR_F_HIGHPOINT_RAID
) {
356 rdp
->offset
= HPT_LBA
+ 1;
357 rdp
->reserved
= HPT_LBA
+ 1;
359 rdp
->lock_start
= rdp
->lock_end
= 0xffffffff;
360 rdp
->flags
|= AR_F_READY
;
362 ar_table
[array
] = rdp
;
363 ar_attach_raid(rdp
, 1);
369 ata_raid_delete(int array
)
371 struct ar_softc
*rdp
;
375 kprintf("ar: no memory for ATA raid array\n");
378 if (!(rdp
= ar_table
[array
]))
381 rdp
->flags
&= ~AR_F_READY
;
382 for (disk
= 0; disk
< rdp
->total_disks
; disk
++) {
383 if ((rdp
->disks
[disk
].flags
&AR_DF_PRESENT
) && rdp
->disks
[disk
].device
) {
384 AD_SOFTC(rdp
->disks
[disk
])->flags
&= ~AD_F_RAID_SUBDISK
;
385 ata_enclosure_leds(rdp
->disks
[disk
].device
, ATA_LED_GREEN
);
386 rdp
->disks
[disk
].flags
= 0;
389 if (rdp
->flags
& AR_F_PROMISE_RAID
)
390 ar_promise_write_conf(rdp
);
392 ar_highpoint_write_conf(rdp
);
393 disk_invalidate(&rdp
->disk
);
394 disk_destroy(&rdp
->disk
);
396 ar_table
[array
] = NULL
;
401 ata_raid_status(int array
, struct raid_status
*status
)
403 struct ar_softc
*rdp
;
406 if (!ar_table
|| !(rdp
= ar_table
[array
]))
409 switch (rdp
->flags
& (AR_F_RAID0
| AR_F_RAID1
| AR_F_SPAN
)) {
411 status
->type
= AR_RAID0
;
414 status
->type
= AR_RAID1
;
416 case AR_F_RAID0
| AR_F_RAID1
:
417 status
->type
= AR_RAID0
| AR_RAID1
;
420 status
->type
= AR_SPAN
;
423 status
->total_disks
= rdp
->total_disks
;
424 for (i
= 0; i
< rdp
->total_disks
; i
++ ) {
425 if ((rdp
->disks
[i
].flags
& AR_DF_PRESENT
) && rdp
->disks
[i
].device
)
426 status
->disks
[i
] = AD_SOFTC(rdp
->disks
[i
])->lun
;
428 status
->disks
[i
] = -1;
430 status
->interleave
= rdp
->interleave
;
432 if (rdp
->flags
& AR_F_READY
)
433 status
->status
|= AR_READY
;
434 if (rdp
->flags
& AR_F_DEGRADED
)
435 status
->status
|= AR_DEGRADED
;
436 if (rdp
->flags
& AR_F_REBUILDING
) {
437 status
->status
|= AR_REBUILDING
;
438 status
->progress
= 100*rdp
->lock_start
/(rdp
->total_sectors
/rdp
->width
);
444 ata_raid_rebuild(int array
)
446 struct ar_softc
*rdp
;
448 if (!ar_table
|| !(rdp
= ar_table
[array
]))
450 if (rdp
->flags
& AR_F_REBUILDING
)
452 /* create process here XXX SOS */
453 return ar_rebuild(rdp
);
457 aropen(struct dev_open_args
*ap
)
459 struct ar_softc
*rdp
= ap
->a_head
.a_dev
->si_drv1
;
460 struct disklabel
*dl
;
462 dl
= &rdp
->disk
.d_label
;
463 bzero(dl
, sizeof *dl
);
464 dl
->d_secsize
= DEV_BSIZE
;
465 dl
->d_nsectors
= rdp
->sectors
;
466 dl
->d_ntracks
= rdp
->heads
;
467 dl
->d_ncylinders
= rdp
->cylinders
;
468 dl
->d_secpercyl
= rdp
->sectors
* rdp
->heads
;
469 dl
->d_secperunit
= rdp
->total_sectors
;
474 arstrategy(struct dev_strategy_args
*ap
)
476 cdev_t dev
= ap
->a_head
.a_dev
;
477 struct bio
*bio
= ap
->a_bio
;
478 struct buf
*bp
= bio
->bio_buf
;
479 struct ar_softc
*rdp
= dev
->si_drv1
;
480 int blkno
, count
, chunk
, lba
, lbs
, tmplba
;
483 int drv
= 0, change
= 0;
486 if (!(rdp
->flags
& AR_F_READY
)) {
487 bp
->b_flags
|= B_ERROR
;
493 KKASSERT((bio
->bio_offset
& DEV_BMASK
) == 0);
495 bp
->b_resid
= bp
->b_bcount
;
496 blkno
= (int)(bio
->bio_offset
>> DEV_BSHIFT
);
500 for (count
= howmany(bp
->b_bcount
, DEV_BSIZE
); count
> 0;
501 count
-= chunk
, blkno
+= chunk
, data
+= (chunk
* DEV_BSIZE
)) {
502 struct ar_buf
*buf1
, *buf2
;
504 switch (rdp
->flags
& (AR_F_RAID0
| AR_F_RAID1
| AR_F_SPAN
)) {
507 while (lba
>= AD_SOFTC(rdp
->disks
[drv
])->total_secs
-rdp
->reserved
)
508 lba
-= AD_SOFTC(rdp
->disks
[drv
++])->total_secs
-rdp
->reserved
;
509 chunk
= min(AD_SOFTC(rdp
->disks
[drv
])->total_secs
-rdp
->reserved
-lba
,
514 case AR_F_RAID0
| AR_F_RAID1
:
515 tmplba
= blkno
/ rdp
->interleave
;
516 chunk
= blkno
% rdp
->interleave
;
517 if (tmplba
== rdp
->total_sectors
/ rdp
->interleave
) {
518 lbs
= (rdp
->total_sectors
-(tmplba
*rdp
->interleave
))/rdp
->width
;
520 lba
= ((tmplba
/rdp
->width
)*rdp
->interleave
) + chunk
%lbs
;
521 chunk
= min(count
, lbs
);
524 drv
= tmplba
% rdp
->width
;
525 lba
= ((tmplba
/ rdp
->width
) * rdp
->interleave
) + chunk
;
526 chunk
= min(count
, rdp
->interleave
- chunk
);
537 kprintf("ar%d: unknown array type in arstrategy\n", rdp
->lun
);
538 bp
->b_flags
|= B_ERROR
;
544 buf1
= kmalloc(sizeof(struct ar_buf
), M_AR
, M_INTWAIT
| M_ZERO
);
545 BUF_LOCKINIT(&buf1
->bp
);
546 BUF_LOCK(&buf1
->bp
, LK_EXCLUSIVE
);
547 initbufbio(&buf1
->bp
);
548 buf1
->bp
.b_bio1
.bio_offset
= (off_t
)lba
<< DEV_BSHIFT
;
549 if ((buf1
->drive
= drv
) > 0)
550 buf1
->bp
.b_bio1
.bio_offset
+= (off_t
)rdp
->offset
<< DEV_BSHIFT
;
551 buf1
->bp
.b_bio1
.bio_caller_info1
.ptr
= (void *)rdp
;
552 buf1
->bp
.b_bcount
= chunk
* DEV_BSIZE
;
553 buf1
->bp
.b_data
= data
;
554 buf1
->bp
.b_flags
= bp
->b_flags
| B_PAGING
;
555 buf1
->bp
.b_cmd
= bp
->b_cmd
;
556 buf1
->bp
.b_bio1
.bio_done
= ar_done
;
558 buf1_blkno
= (int)(buf1
->bp
.b_bio1
.bio_offset
>> DEV_BSHIFT
);
560 switch (rdp
->flags
& (AR_F_RAID0
| AR_F_RAID1
| AR_F_SPAN
)) {
563 if ((rdp
->disks
[buf1
->drive
].flags
&
564 (AR_DF_PRESENT
|AR_DF_ONLINE
))==(AR_DF_PRESENT
|AR_DF_ONLINE
) &&
565 !AD_SOFTC(rdp
->disks
[buf1
->drive
])->dev
) {
566 rdp
->disks
[buf1
->drive
].flags
&= ~AR_DF_ONLINE
;
567 ar_config_changed(rdp
, 1);
569 bp
->b_flags
|= B_ERROR
;
574 dev_dstrategy(AD_SOFTC(rdp
->disks
[buf1
->drive
])->dev
,
579 case AR_F_RAID0
| AR_F_RAID1
:
580 if ((rdp
->flags
& AR_F_REBUILDING
) && bp
->b_cmd
!= BUF_CMD_READ
) {
581 if ((orig_blkno
>= rdp
->lock_start
&&
582 orig_blkno
< rdp
->lock_end
) ||
583 ((orig_blkno
+ chunk
) > rdp
->lock_start
&&
584 (orig_blkno
+ chunk
) <= rdp
->lock_end
)) {
585 tsleep(rdp
, 0, "arwait", 0);
588 if ((rdp
->disks
[buf1
->drive
].flags
&
589 (AR_DF_PRESENT
|AR_DF_ONLINE
))==(AR_DF_PRESENT
|AR_DF_ONLINE
) &&
590 !AD_SOFTC(rdp
->disks
[buf1
->drive
])->dev
) {
591 rdp
->disks
[buf1
->drive
].flags
&= ~AR_DF_ONLINE
;
594 if ((rdp
->disks
[buf1
->drive
+ rdp
->width
].flags
&
595 (AR_DF_PRESENT
|AR_DF_ONLINE
))==(AR_DF_PRESENT
|AR_DF_ONLINE
) &&
596 !AD_SOFTC(rdp
->disks
[buf1
->drive
+ rdp
->width
])->dev
) {
597 rdp
->disks
[buf1
->drive
+ rdp
->width
].flags
&= ~AR_DF_ONLINE
;
601 ar_config_changed(rdp
, 1);
603 if (!(rdp
->flags
& AR_F_READY
)) {
605 bp
->b_flags
|= B_ERROR
;
610 if (bp
->b_cmd
== BUF_CMD_READ
) {
612 (rdp
->disks
[buf1
->drive
].last_lba
- AR_PROXIMITY
) ||
614 (rdp
->disks
[buf1
->drive
].last_lba
+ AR_PROXIMITY
) ||
615 !(rdp
->disks
[buf1
->drive
].flags
& AR_DF_ONLINE
)) &&
616 (rdp
->disks
[buf1
->drive
+rdp
->width
].flags
& AR_DF_ONLINE
))
617 buf1
->drive
= buf1
->drive
+ rdp
->width
;
619 if ((rdp
->disks
[buf1
->drive
+rdp
->width
].flags
& AR_DF_ONLINE
) ||
620 ((rdp
->flags
& AR_F_REBUILDING
) &&
621 (rdp
->disks
[buf1
->drive
+rdp
->width
].flags
& AR_DF_SPARE
) &&
622 buf1_blkno
< rdp
->lock_start
)) {
623 if ((rdp
->disks
[buf1
->drive
].flags
& AR_DF_ONLINE
) ||
624 ((rdp
->flags
& AR_F_REBUILDING
) &&
625 (rdp
->disks
[buf1
->drive
].flags
& AR_DF_SPARE
) &&
626 buf1_blkno
< rdp
->lock_start
)) {
627 buf2
= kmalloc(sizeof(struct ar_buf
), M_AR
, M_INTWAIT
);
628 bcopy(buf1
, buf2
, sizeof(struct ar_buf
));
629 BUF_LOCKINIT(&buf2
->bp
);
630 BUF_LOCK(&buf2
->bp
, LK_EXCLUSIVE
);
631 initbufbio(&buf2
->bp
);
632 buf2
->bp
.b_bio1
.bio_offset
= buf1
->bp
.b_bio1
.bio_offset
;
635 buf2
->drive
= buf1
->drive
+ rdp
->width
;
636 dev_dstrategy(AD_SOFTC(rdp
->disks
[buf2
->drive
])->dev
,
638 rdp
->disks
[buf2
->drive
].last_lba
= buf1_blkno
+ chunk
;
641 buf1
->drive
= buf1
->drive
+ rdp
->width
;
644 dev_dstrategy(AD_SOFTC(rdp
->disks
[buf1
->drive
])->dev
,
646 rdp
->disks
[buf1
->drive
].last_lba
= buf1_blkno
+ chunk
;
650 kprintf("ar%d: unknown array type in arstrategy\n", rdp
->lun
);
657 ar_done(struct bio
*bio
)
659 struct ar_softc
*rdp
= (struct ar_softc
*)bio
->bio_caller_info1
.ptr
;
660 struct ar_buf
*buf
= (struct ar_buf
*)bio
->bio_buf
;
662 switch (rdp
->flags
& (AR_F_RAID0
| AR_F_RAID1
| AR_F_SPAN
)) {
665 if (buf
->bp
.b_flags
& B_ERROR
) {
666 rdp
->disks
[buf
->drive
].flags
&= ~AR_DF_ONLINE
;
667 ar_config_changed(rdp
, 1);
668 buf
->org
->bio_buf
->b_flags
|= B_ERROR
;
669 buf
->org
->bio_buf
->b_error
= EIO
;
673 buf
->org
->bio_buf
->b_resid
-= buf
->bp
.b_bcount
;
674 if (buf
->org
->bio_buf
->b_resid
== 0)
680 case AR_F_RAID0
| AR_F_RAID1
:
681 if (buf
->bp
.b_flags
& B_ERROR
) {
682 rdp
->disks
[buf
->drive
].flags
&= ~AR_DF_ONLINE
;
683 ar_config_changed(rdp
, 1);
684 if (rdp
->flags
& AR_F_READY
) {
685 if (buf
->bp
.b_cmd
== BUF_CMD_READ
) {
686 if (buf
->drive
< rdp
->width
)
687 buf
->drive
= buf
->drive
+ rdp
->width
;
689 buf
->drive
= buf
->drive
- rdp
->width
;
690 buf
->bp
.b_flags
= buf
->org
->bio_buf
->b_flags
| B_PAGING
;
692 dev_dstrategy(AD_SOFTC(rdp
->disks
[buf
->drive
])->dev
,
697 if (buf
->flags
& AB_F_DONE
) {
698 buf
->org
->bio_buf
->b_resid
-= buf
->bp
.b_bcount
;
699 if (buf
->org
->bio_buf
->b_resid
== 0)
703 buf
->mirror
->flags
|= AB_F_DONE
;
707 buf
->org
->bio_buf
->b_flags
|= B_ERROR
;
708 buf
->org
->bio_buf
->b_error
= EIO
;
713 if (buf
->bp
.b_cmd
!= BUF_CMD_READ
) {
714 if (buf
->mirror
&& !(buf
->flags
& AB_F_DONE
)){
715 buf
->mirror
->flags
|= AB_F_DONE
;
719 buf
->org
->bio_buf
->b_resid
-= buf
->bp
.b_bcount
;
720 if (buf
->org
->bio_buf
->b_resid
== 0)
726 kprintf("ar%d: unknown array type in ar_done\n", rdp
->lun
);
732 ar_sync_done(struct bio
*bio
)
734 bio
->bio_buf
->b_cmd
= BUF_CMD_DONE
;
739 ar_config_changed(struct ar_softc
*rdp
, int writeback
)
744 rdp
->flags
|= AR_F_READY
;
745 rdp
->flags
&= ~AR_F_DEGRADED
;
747 for (disk
= 0; disk
< rdp
->total_disks
; disk
++)
748 if (!(rdp
->disks
[disk
].flags
& AR_DF_PRESENT
))
749 rdp
->disks
[disk
].flags
&= ~AR_DF_ONLINE
;
751 for (disk
= 0; disk
< rdp
->total_disks
; disk
++) {
752 switch (rdp
->flags
& (AR_F_RAID0
| AR_F_RAID1
| AR_F_SPAN
)) {
755 if (!(rdp
->disks
[disk
].flags
& AR_DF_ONLINE
)) {
756 rdp
->flags
&= ~AR_F_READY
;
757 kprintf("ar%d: ERROR - array broken\n", rdp
->lun
);
762 case AR_F_RAID0
| AR_F_RAID1
:
763 if (disk
< rdp
->width
) {
764 if (!(rdp
->disks
[disk
].flags
& AR_DF_ONLINE
) &&
765 !(rdp
->disks
[disk
+ rdp
->width
].flags
& AR_DF_ONLINE
)) {
766 rdp
->flags
&= ~AR_F_READY
;
767 kprintf("ar%d: ERROR - array broken\n", rdp
->lun
);
769 else if (((rdp
->disks
[disk
].flags
& AR_DF_ONLINE
) &&
771 [disk
+ rdp
->width
].flags
& AR_DF_ONLINE
))||
772 (!(rdp
->disks
[disk
].flags
& AR_DF_ONLINE
) &&
774 [disk
+ rdp
->width
].flags
& AR_DF_ONLINE
))) {
775 rdp
->flags
|= AR_F_DEGRADED
;
776 if (!(flags
& AR_F_DEGRADED
))
777 kprintf("ar%d: WARNING - mirror lost\n", rdp
->lun
);
782 if ((rdp
->disks
[disk
].flags
&AR_DF_PRESENT
) && rdp
->disks
[disk
].device
) {
783 if (rdp
->disks
[disk
].flags
& AR_DF_ONLINE
)
784 ata_enclosure_leds(rdp
->disks
[disk
].device
, ATA_LED_GREEN
);
786 ata_enclosure_leds(rdp
->disks
[disk
].device
, ATA_LED_RED
);
790 if (rdp
->flags
& AR_F_PROMISE_RAID
)
791 ar_promise_write_conf(rdp
);
792 if (rdp
->flags
& AR_F_HIGHPOINT_RAID
)
793 ar_highpoint_write_conf(rdp
);
798 ar_rebuild(struct ar_softc
*rdp
)
800 int disk
, count
= 0, error
= 0;
803 if ((rdp
->flags
& (AR_F_READY
|AR_F_DEGRADED
)) != (AR_F_READY
|AR_F_DEGRADED
))
806 for (disk
= 0; disk
< rdp
->total_disks
; disk
++) {
807 if (((rdp
->disks
[disk
].flags
&(AR_DF_PRESENT
|AR_DF_ONLINE
|AR_DF_SPARE
))==
808 (AR_DF_PRESENT
| AR_DF_SPARE
)) && rdp
->disks
[disk
].device
) {
809 if (AD_SOFTC(rdp
->disks
[disk
])->total_secs
<
810 rdp
->disks
[disk
].disk_sectors
) {
811 ata_prtdev(rdp
->disks
[disk
].device
,
812 "disk capacity too small for this RAID config\n");
814 rdp
->disks
[disk
].flags
&= ~AR_DF_SPARE
;
815 AD_SOFTC(rdp
->disks
[disk
])->flags
&= ~AD_F_RAID_SUBDISK
;
819 ata_enclosure_leds(rdp
->disks
[disk
].device
, ATA_LED_ORANGE
);
826 /* setup start conditions */
829 rdp
->lock_end
= rdp
->lock_start
+ 256;
830 rdp
->flags
|= AR_F_REBUILDING
;
832 buffer
= kmalloc(256 * DEV_BSIZE
, M_AR
, M_WAITOK
| M_ZERO
);
834 /* now go copy entire disk(s) */
835 while (rdp
->lock_end
< (rdp
->total_sectors
/ rdp
->width
)) {
836 int size
= min(256, (rdp
->total_sectors
/ rdp
->width
) - rdp
->lock_end
);
838 for (disk
= 0; disk
< rdp
->width
; disk
++) {
839 struct ad_softc
*adp
;
841 if (((rdp
->disks
[disk
].flags
& AR_DF_ONLINE
) &&
842 (rdp
->disks
[disk
+ rdp
->width
].flags
& AR_DF_ONLINE
)) ||
843 ((rdp
->disks
[disk
].flags
& AR_DF_ONLINE
) &&
844 !(rdp
->disks
[disk
+ rdp
->width
].flags
& AR_DF_SPARE
)) ||
845 ((rdp
->disks
[disk
+ rdp
->width
].flags
& AR_DF_ONLINE
) &&
846 !(rdp
->disks
[disk
].flags
& AR_DF_SPARE
)))
849 if (rdp
->disks
[disk
].flags
& AR_DF_ONLINE
)
850 adp
= AD_SOFTC(rdp
->disks
[disk
]);
852 adp
= AD_SOFTC(rdp
->disks
[disk
+ rdp
->width
]);
853 if ((error
= ar_rw(adp
, rdp
->lock_start
,
854 size
* DEV_BSIZE
, buffer
, AR_READ
| AR_WAIT
)))
857 if (rdp
->disks
[disk
].flags
& AR_DF_ONLINE
)
858 adp
= AD_SOFTC(rdp
->disks
[disk
+ rdp
->width
]);
860 adp
= AD_SOFTC(rdp
->disks
[disk
]);
861 if ((error
= ar_rw(adp
, rdp
->lock_start
,
862 size
* DEV_BSIZE
, buffer
, AR_WRITE
| AR_WAIT
)))
871 rdp
->lock_start
= rdp
->lock_end
;
872 rdp
->lock_end
= rdp
->lock_start
+ size
;
877 for (disk
= 0; disk
< rdp
->total_disks
; disk
++) {
878 if ((rdp
->disks
[disk
].flags
&(AR_DF_PRESENT
|AR_DF_ONLINE
|AR_DF_SPARE
))==
879 (AR_DF_PRESENT
| AR_DF_SPARE
)) {
880 rdp
->disks
[disk
].flags
&= ~AR_DF_SPARE
;
881 rdp
->disks
[disk
].flags
|= (AR_DF_ASSIGNED
| AR_DF_ONLINE
);
885 rdp
->lock_start
= 0xffffffff;
886 rdp
->lock_end
= 0xffffffff;
887 rdp
->flags
&= ~AR_F_REBUILDING
;
889 ar_config_changed(rdp
, 1);
894 ar_highpoint_read_conf(struct ad_softc
*adp
, struct ar_softc
**raidp
)
896 struct highpoint_raid_conf
*info
;
897 struct ar_softc
*raid
= NULL
;
898 int array
, disk_number
= 0, retval
= 0;
900 info
= kmalloc(sizeof(struct highpoint_raid_conf
), M_AR
, M_INTWAIT
|M_ZERO
);
902 if (ar_rw(adp
, HPT_LBA
, sizeof(struct highpoint_raid_conf
),
903 (caddr_t
)info
, AR_READ
| AR_WAIT
)) {
905 kprintf("ar: HighPoint read conf failed\n");
909 /* check if this is a HighPoint RAID struct */
910 if (info
->magic
!= HPT_MAGIC_OK
&& info
->magic
!= HPT_MAGIC_BAD
) {
912 kprintf("ar: HighPoint check1 failed\n");
916 /* is this disk defined, or an old leftover/spare ? */
917 if (!info
->magic_0
) {
919 kprintf("ar: HighPoint check2 failed\n");
923 /* now convert HighPoint config info into our generic form */
924 for (array
= 0; array
< MAX_ARRAYS
; array
++) {
926 raidp
[array
] = kmalloc(sizeof(struct ar_softc
), M_AR
,
930 if (raid
->flags
& AR_F_PROMISE_RAID
)
933 switch (info
->type
) {
935 if ((info
->order
& (HPT_O_RAID0
|HPT_O_OK
))==(HPT_O_RAID0
|HPT_O_OK
))
936 goto highpoint_raid1
;
937 if (info
->order
& (HPT_O_RAID0
| HPT_O_RAID1
))
938 goto highpoint_raid01
;
939 if (raid
->magic_0
&& raid
->magic_0
!= info
->magic_0
)
941 raid
->magic_0
= info
->magic_0
;
942 raid
->flags
|= AR_F_RAID0
;
943 raid
->interleave
= 1 << info
->stripe_shift
;
944 disk_number
= info
->disk_number
;
945 if (!(info
->order
& HPT_O_OK
))
946 info
->magic
= 0; /* mark bad */
951 if (raid
->magic_0
&& raid
->magic_0
!= info
->magic_0
)
953 raid
->magic_0
= info
->magic_0
;
954 raid
->flags
|= AR_F_RAID1
;
955 disk_number
= (info
->disk_number
> 0);
958 case HPT_T_RAID01_RAID0
:
960 if (info
->order
& HPT_O_RAID0
) {
961 if ((raid
->magic_0
&& raid
->magic_0
!= info
->magic_0
) ||
962 (raid
->magic_1
&& raid
->magic_1
!= info
->magic_1
))
964 raid
->magic_0
= info
->magic_0
;
965 raid
->magic_1
= info
->magic_1
;
966 raid
->flags
|= (AR_F_RAID0
| AR_F_RAID1
);
967 raid
->interleave
= 1 << info
->stripe_shift
;
968 disk_number
= info
->disk_number
;
971 if (raid
->magic_1
&& raid
->magic_1
!= info
->magic_1
)
973 raid
->magic_1
= info
->magic_1
;
974 raid
->flags
|= (AR_F_RAID0
| AR_F_RAID1
);
975 raid
->interleave
= 1 << info
->stripe_shift
;
976 disk_number
= info
->disk_number
+ info
->array_width
;
977 if (!(info
->order
& HPT_O_RAID1
))
978 info
->magic
= 0; /* mark bad */
983 if (raid
->magic_0
&& raid
->magic_0
!= info
->magic_0
)
985 raid
->magic_0
= info
->magic_0
;
986 raid
->flags
|= AR_F_SPAN
;
987 disk_number
= info
->disk_number
;
991 kprintf("ar%d: HighPoint unknown RAID type 0x%02x\n",
996 raid
->flags
|= AR_F_HIGHPOINT_RAID
;
997 raid
->disks
[disk_number
].device
= adp
->device
;
998 raid
->disks
[disk_number
].flags
= (AR_DF_PRESENT
| AR_DF_ASSIGNED
);
1000 if (info
->magic
== HPT_MAGIC_OK
) {
1001 raid
->disks
[disk_number
].flags
|= AR_DF_ONLINE
;
1002 raid
->flags
|= AR_F_READY
;
1003 raid
->width
= info
->array_width
;
1006 raid
->cylinders
= info
->total_sectors
/ (63 * 255);
1007 raid
->total_sectors
= info
->total_sectors
;
1008 raid
->offset
= HPT_LBA
+ 1;
1009 raid
->reserved
= HPT_LBA
+ 1;
1010 raid
->lock_start
= raid
->lock_end
= info
->rebuild_lba
;
1011 raid
->disks
[disk_number
].disk_sectors
=
1012 info
->total_sectors
/ info
->array_width
;
1015 raid
->disks
[disk_number
].flags
&= ~ AR_DF_ONLINE
;
1017 if ((raid
->flags
& AR_F_RAID0
) && (raid
->total_disks
< raid
->width
))
1018 raid
->total_disks
= raid
->width
;
1019 if (disk_number
>= raid
->total_disks
)
1020 raid
->total_disks
= disk_number
+ 1;
1030 ar_highpoint_write_conf(struct ar_softc
*rdp
)
1032 struct highpoint_raid_conf
*config
;
1033 struct timeval timestamp
;
1036 microtime(×tamp
);
1037 rdp
->magic_0
= timestamp
.tv_sec
+ 2;
1038 rdp
->magic_1
= timestamp
.tv_sec
;
1040 for (disk
= 0; disk
< rdp
->total_disks
; disk
++) {
1041 config
= kmalloc(sizeof(struct highpoint_raid_conf
),
1042 M_AR
, M_INTWAIT
| M_ZERO
);
1043 if ((rdp
->disks
[disk
].flags
& (AR_DF_PRESENT
| AR_DF_ONLINE
)) ==
1044 (AR_DF_PRESENT
| AR_DF_ONLINE
))
1045 config
->magic
= HPT_MAGIC_OK
;
1046 if (rdp
->disks
[disk
].flags
& AR_DF_ASSIGNED
) {
1047 config
->magic_0
= rdp
->magic_0
;
1048 strcpy(config
->name_1
, "FreeBSD");
1050 config
->disk_number
= disk
;
1052 switch (rdp
->flags
& (AR_F_RAID0
| AR_F_RAID1
| AR_F_SPAN
)) {
1054 config
->type
= HPT_T_RAID0
;
1055 strcpy(config
->name_2
, "RAID 0");
1056 if (rdp
->disks
[disk
].flags
& AR_DF_ONLINE
)
1057 config
->order
= HPT_O_OK
;
1061 config
->type
= HPT_T_RAID0
; /* bogus but old HPT BIOS need it */
1062 strcpy(config
->name_2
, "RAID 1");
1063 config
->disk_number
= (disk
< rdp
->width
) ? disk
: disk
+ 5;
1064 config
->order
= HPT_O_RAID0
| HPT_O_OK
;
1067 case AR_F_RAID0
| AR_F_RAID1
:
1068 config
->type
= HPT_T_RAID01_RAID0
;
1069 strcpy(config
->name_2
, "RAID 0+1");
1070 if (rdp
->disks
[disk
].flags
& AR_DF_ONLINE
) {
1071 if (disk
< rdp
->width
) {
1072 config
->order
= (HPT_O_RAID0
| HPT_O_RAID1
);
1073 config
->magic_0
= rdp
->magic_0
- 1;
1076 config
->order
= HPT_O_RAID1
;
1077 config
->disk_number
-= rdp
->width
;
1081 config
->magic_0
= rdp
->magic_0
- 1;
1082 config
->magic_1
= rdp
->magic_1
;
1086 config
->type
= HPT_T_SPAN
;
1087 strcpy(config
->name_2
, "SPAN");
1091 config
->array_width
= rdp
->width
;
1092 config
->stripe_shift
= (rdp
->width
> 1) ? (ffs(rdp
->interleave
)-1) : 0;
1093 config
->total_sectors
= rdp
->total_sectors
;
1094 config
->rebuild_lba
= rdp
->lock_start
;
1096 if ((rdp
->disks
[disk
].device
&& rdp
->disks
[disk
].device
->driver
) &&
1097 !(rdp
->disks
[disk
].device
->flags
& ATA_D_DETACHING
)) {
1099 if (ar_rw(AD_SOFTC(rdp
->disks
[disk
]), HPT_LBA
,
1100 sizeof(struct highpoint_raid_conf
),
1101 (caddr_t
)config
, AR_WRITE
)) {
1102 kprintf("ar%d: Highpoint write conf failed\n", rdp
->lun
);
1111 ar_promise_read_conf(struct ad_softc
*adp
, struct ar_softc
**raidp
, int local
)
1113 struct promise_raid_conf
*info
;
1114 struct ar_softc
*raid
;
1115 u_int32_t magic
, cksum
, *ckptr
;
1116 int array
, count
, disk
, disksum
= 0, retval
= 0;
1118 info
= kmalloc(sizeof(struct promise_raid_conf
), M_AR
, M_INTWAIT
| M_ZERO
);
1120 if (ar_rw(adp
, PR_LBA(adp
), sizeof(struct promise_raid_conf
),
1121 (caddr_t
)info
, AR_READ
| AR_WAIT
)) {
1123 kprintf("ar: %s read conf failed\n", local
? "FreeBSD" : "Promise");
1127 /* check if this is a Promise RAID struct (or our local one) */
1129 if (strncmp(info
->promise_id
, ATA_MAGIC
, sizeof(ATA_MAGIC
))) {
1131 kprintf("ar: FreeBSD check1 failed\n");
1136 if (strncmp(info
->promise_id
, PR_MAGIC
, sizeof(PR_MAGIC
))) {
1138 kprintf("ar: Promise check1 failed\n");
1143 /* check if the checksum is OK */
1144 for (cksum
= 0, ckptr
= (int32_t *)info
, count
= 0; count
< 511; count
++)
1146 if (cksum
!= *ckptr
) {
1148 kprintf("ar: %s check2 failed\n", local
? "FreeBSD" : "Promise");
1152 /* now convert Promise config info into our generic form */
1153 if (info
->raid
.integrity
!= PR_I_VALID
) {
1155 kprintf("ar: %s check3 failed\n", local
? "FreeBSD" : "Promise");
1159 for (array
= 0; array
< MAX_ARRAYS
; array
++) {
1160 if (!raidp
[array
]) {
1161 raidp
[array
] = kmalloc(sizeof(struct ar_softc
), M_AR
,
1162 M_INTWAIT
| M_ZERO
);
1164 raid
= raidp
[array
];
1165 if (raid
->flags
& AR_F_HIGHPOINT_RAID
)
1168 magic
= (adp
->device
->channel
->chiptype
>> 16) |
1169 (info
->raid
.array_number
<< 16);
1171 if ((raid
->flags
& AR_F_PROMISE_RAID
) && magic
!= raid
->magic_0
)
1174 /* update our knowledge about the array config based on generation */
1175 if (!info
->raid
.generation
|| info
->raid
.generation
> raid
->generation
){
1176 raid
->generation
= info
->raid
.generation
;
1177 raid
->flags
= AR_F_PROMISE_RAID
;
1179 raid
->flags
|= AR_F_FREEBSD_RAID
;
1180 raid
->magic_0
= magic
;
1182 if ((info
->raid
.status
&
1183 (PR_S_VALID
| PR_S_ONLINE
| PR_S_INITED
| PR_S_READY
)) ==
1184 (PR_S_VALID
| PR_S_ONLINE
| PR_S_INITED
| PR_S_READY
)) {
1185 raid
->flags
|= AR_F_READY
;
1186 if (info
->raid
.status
& PR_S_DEGRADED
)
1187 raid
->flags
|= AR_F_DEGRADED
;
1190 raid
->flags
&= ~AR_F_READY
;
1192 switch (info
->raid
.type
) {
1194 raid
->flags
|= AR_F_RAID0
;
1198 raid
->flags
|= AR_F_RAID1
;
1199 if (info
->raid
.array_width
> 1)
1200 raid
->flags
|= AR_F_RAID0
;
1204 raid
->flags
|= AR_F_SPAN
;
1208 kprintf("ar%d: %s unknown RAID type 0x%02x\n",
1209 array
, local
? "FreeBSD" : "Promise", info
->raid
.type
);
1212 raid
->interleave
= 1 << info
->raid
.stripe_shift
;
1213 raid
->width
= info
->raid
.array_width
;
1214 raid
->total_disks
= info
->raid
.total_disks
;
1215 raid
->heads
= info
->raid
.heads
+ 1;
1216 raid
->sectors
= info
->raid
.sectors
;
1217 raid
->cylinders
= info
->raid
.cylinders
+ 1;
1218 raid
->total_sectors
= info
->raid
.total_sectors
;
1220 raid
->reserved
= 63;
1221 raid
->lock_start
= raid
->lock_end
= info
->raid
.rebuild_lba
;
1223 /* convert disk flags to our internal types */
1224 for (disk
= 0; disk
< info
->raid
.total_disks
; disk
++) {
1225 raid
->disks
[disk
].flags
= 0;
1226 disksum
+= info
->raid
.disk
[disk
].flags
;
1227 if (info
->raid
.disk
[disk
].flags
& PR_F_ONLINE
)
1228 raid
->disks
[disk
].flags
|= AR_DF_ONLINE
;
1229 if (info
->raid
.disk
[disk
].flags
& PR_F_ASSIGNED
)
1230 raid
->disks
[disk
].flags
|= AR_DF_ASSIGNED
;
1231 if (info
->raid
.disk
[disk
].flags
& PR_F_SPARE
) {
1232 raid
->disks
[disk
].flags
&= ~AR_DF_ONLINE
;
1233 raid
->disks
[disk
].flags
|= AR_DF_SPARE
;
1235 if (info
->raid
.disk
[disk
].flags
& (PR_F_REDIR
| PR_F_DOWN
))
1236 raid
->disks
[disk
].flags
&= ~AR_DF_ONLINE
;
1239 kfree(raidp
[array
], M_AR
);
1240 raidp
[array
] = NULL
;
1244 if (raid
->disks
[info
->raid
.disk_number
].flags
&& adp
->device
) {
1245 raid
->disks
[info
->raid
.disk_number
].device
= adp
->device
;
1246 raid
->disks
[info
->raid
.disk_number
].flags
|= AR_DF_PRESENT
;
1247 raid
->disks
[info
->raid
.disk_number
].disk_sectors
=
1248 info
->raid
.total_sectors
/ info
->raid
.array_width
;
1249 /*info->raid.disk_sectors;*/
1260 ar_promise_write_conf(struct ar_softc
*rdp
)
1262 struct promise_raid_conf
*config
;
1263 struct timeval timestamp
;
1265 int count
, disk
, drive
;
1266 int local
= rdp
->flags
& AR_F_FREEBSD_RAID
;
1269 microtime(×tamp
);
1271 for (disk
= 0; disk
< rdp
->total_disks
; disk
++) {
1272 config
= kmalloc(sizeof(struct promise_raid_conf
), M_AR
, M_INTWAIT
);
1273 for (count
= 0; count
< sizeof(struct promise_raid_conf
); count
++)
1274 *(((u_int8_t
*)config
) + count
) = 255 - (count
% 256);
1277 bcopy(ATA_MAGIC
, config
->promise_id
, sizeof(ATA_MAGIC
));
1279 bcopy(PR_MAGIC
, config
->promise_id
, sizeof(PR_MAGIC
));
1280 config
->dummy_0
= 0x00020000;
1281 config
->magic_0
= PR_MAGIC0(rdp
->disks
[disk
]) | timestamp
.tv_sec
;
1282 config
->magic_1
= timestamp
.tv_sec
>> 16;
1283 config
->magic_2
= timestamp
.tv_sec
;
1284 config
->raid
.integrity
= PR_I_VALID
;
1286 config
->raid
.disk_number
= disk
;
1287 if ((rdp
->disks
[disk
].flags
&AR_DF_PRESENT
) && rdp
->disks
[disk
].device
) {
1288 config
->raid
.channel
= rdp
->disks
[disk
].device
->channel
->unit
;
1289 config
->raid
.device
= (rdp
->disks
[disk
].device
->unit
!= 0);
1290 if (AD_SOFTC(rdp
->disks
[disk
])->dev
)
1291 config
->raid
.disk_sectors
= PR_LBA(AD_SOFTC(rdp
->disks
[disk
]));
1292 /*config->raid.disk_offset*/
1294 config
->raid
.magic_0
= config
->magic_0
;
1295 config
->raid
.rebuild_lba
= rdp
->lock_start
;
1296 config
->raid
.generation
= rdp
->generation
;
1298 if (rdp
->flags
& AR_F_READY
) {
1299 config
->raid
.flags
= (PR_F_VALID
| PR_F_ASSIGNED
| PR_F_ONLINE
);
1300 config
->raid
.status
=
1301 (PR_S_VALID
| PR_S_ONLINE
| PR_S_INITED
| PR_S_READY
);
1302 if (rdp
->flags
& AR_F_DEGRADED
)
1303 config
->raid
.status
|= PR_S_DEGRADED
;
1305 config
->raid
.status
|= PR_S_FUNCTIONAL
;
1308 config
->raid
.status
= 0;
1309 config
->raid
.flags
= PR_F_DOWN
;
1312 switch (rdp
->flags
& (AR_F_RAID0
| AR_F_RAID1
| AR_F_SPAN
)) {
1314 config
->raid
.type
= PR_T_RAID0
;
1317 config
->raid
.type
= PR_T_RAID1
;
1319 case AR_F_RAID0
| AR_F_RAID1
:
1320 config
->raid
.type
= PR_T_RAID1
;
1323 config
->raid
.type
= PR_T_SPAN
;
1327 config
->raid
.total_disks
= rdp
->total_disks
;
1328 config
->raid
.stripe_shift
= ffs(rdp
->interleave
) - 1;
1329 config
->raid
.array_width
= rdp
->width
;
1330 config
->raid
.array_number
= rdp
->lun
;
1331 config
->raid
.total_sectors
= rdp
->total_sectors
;
1332 config
->raid
.cylinders
= rdp
->cylinders
- 1;
1333 config
->raid
.heads
= rdp
->heads
- 1;
1334 config
->raid
.sectors
= rdp
->sectors
;
1335 config
->raid
.magic_1
= (u_int64_t
)config
->magic_2
<<16 | config
->magic_1
;
1337 bzero(&config
->raid
.disk
, 8 * 12);
1338 for (drive
= 0; drive
< rdp
->total_disks
; drive
++) {
1339 config
->raid
.disk
[drive
].flags
= 0;
1340 if (rdp
->disks
[drive
].flags
& AR_DF_PRESENT
)
1341 config
->raid
.disk
[drive
].flags
|= PR_F_VALID
;
1342 if (rdp
->disks
[drive
].flags
& AR_DF_ASSIGNED
)
1343 config
->raid
.disk
[drive
].flags
|= PR_F_ASSIGNED
;
1344 if (rdp
->disks
[drive
].flags
& AR_DF_ONLINE
)
1345 config
->raid
.disk
[drive
].flags
|= PR_F_ONLINE
;
1347 if (rdp
->disks
[drive
].flags
& AR_DF_PRESENT
)
1348 config
->raid
.disk
[drive
].flags
= (PR_F_REDIR
| PR_F_DOWN
);
1349 if (rdp
->disks
[drive
].flags
& AR_DF_SPARE
)
1350 config
->raid
.disk
[drive
].flags
|= PR_F_SPARE
;
1351 config
->raid
.disk
[drive
].dummy_0
= 0x0;
1352 if (rdp
->disks
[drive
].device
) {
1353 config
->raid
.disk
[drive
].channel
=
1354 rdp
->disks
[drive
].device
->channel
->unit
;
1355 config
->raid
.disk
[drive
].device
=
1356 (rdp
->disks
[drive
].device
->unit
!= 0);
1358 config
->raid
.disk
[drive
].magic_0
=
1359 PR_MAGIC0(rdp
->disks
[drive
]) | timestamp
.tv_sec
;
1362 config
->checksum
= 0;
1363 for (ckptr
= (int32_t *)config
, count
= 0; count
< 511; count
++)
1364 config
->checksum
+= *ckptr
++;
1365 if (rdp
->disks
[disk
].device
&& rdp
->disks
[disk
].device
->driver
&&
1366 !(rdp
->disks
[disk
].device
->flags
& ATA_D_DETACHING
)) {
1367 if (ar_rw(AD_SOFTC(rdp
->disks
[disk
]),
1368 PR_LBA(AD_SOFTC(rdp
->disks
[disk
])),
1369 sizeof(struct promise_raid_conf
),
1370 (caddr_t
)config
, AR_WRITE
)) {
1371 kprintf("ar%d: %s write conf failed\n",
1372 rdp
->lun
, local
? "FreeBSD" : "Promise");
1381 ar_rw_done(struct bio
*bio
)
1383 struct buf
*bp
= bio
->bio_buf
;
1385 kfree(bp
->b_data
, M_AR
);
1390 ar_rw(struct ad_softc
*adp
, u_int32_t lba
, int count
, caddr_t data
, int flags
)
1393 int retry
= 0, error
= 0;
1395 bp
= kmalloc(sizeof(struct buf
), M_AR
, M_INTWAIT
|M_ZERO
);
1397 BUF_LOCK(bp
, LK_EXCLUSIVE
);
1400 bp
->b_bio1
.bio_offset
= (off_t
)lba
<< DEV_BSHIFT
;
1401 bp
->b_bcount
= count
;
1402 if (flags
& AR_WAIT
)
1403 bp
->b_bio1
.bio_done
= ar_sync_done
;
1405 bp
->b_bio1
.bio_done
= ar_rw_done
;
1406 if (flags
& AR_READ
)
1407 bp
->b_cmd
= BUF_CMD_READ
;
1408 if (flags
& AR_WRITE
)
1409 bp
->b_cmd
= BUF_CMD_WRITE
;
1410 KKASSERT(bp
->b_cmd
!= BUF_CMD_DONE
);
1412 dev_dstrategy(adp
->dev
, &bp
->b_bio1
);
1414 if (flags
& AR_WAIT
) {
1415 while ((retry
++ < (15*hz
/10)) && (error
= !(bp
->b_cmd
== BUF_CMD_DONE
)))
1416 error
= tsleep(&bp
->b_bio1
, 0, "arrw", 10);
1417 if (!error
&& (bp
->b_flags
& B_ERROR
))
1418 error
= bp
->b_error
;
1424 static struct ata_device
*
1425 ar_locate_disk(int diskno
)
1427 struct ata_channel
*ch
;
1430 for (ctlr
= 0; ctlr
< devclass_get_maxunit(ata_devclass
); ctlr
++) {
1431 if (!(ch
= devclass_get_softc(ata_devclass
, ctlr
)))
1433 if (ch
->devices
& ATA_ATA_MASTER
)
1434 if (ch
->device
[MASTER
].driver
&&
1435 ((struct ad_softc
*)(ch
->device
[MASTER
].driver
))->lun
== diskno
)
1436 return &ch
->device
[MASTER
];
1437 if (ch
->devices
& ATA_ATA_SLAVE
)
1438 if (ch
->device
[SLAVE
].driver
&&
1439 ((struct ad_softc
*)(ch
->device
[SLAVE
].driver
))->lun
== diskno
)
1440 return &ch
->device
[SLAVE
];