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.12 2004/07/20 17:55:33 dillon 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>
44 #include <machine/bus.h>
52 /* device structures */
53 static d_open_t aropen;
54 static d_strategy_t arstrategy;
56 static struct cdevsw ar_cdevsw = {
64 /* close */ nullclose,
66 /* write */ physwrite,
70 /* strategy */ arstrategy,
76 static void ar_attach_raid(struct ar_softc *, int);
77 static void ar_done(struct buf *);
78 static void ar_config_changed(struct ar_softc *, int);
79 static int ar_rebuild(struct ar_softc *);
80 static int ar_highpoint_read_conf(struct ad_softc *, struct ar_softc **);
81 static int ar_highpoint_write_conf(struct ar_softc *);
82 static int ar_promise_read_conf(struct ad_softc *, struct ar_softc **, int);
83 static int ar_promise_write_conf(struct ar_softc *);
84 static int ar_rw(struct ad_softc *, u_int32_t, int, caddr_t, int);
85 static struct ata_device *ar_locate_disk(int);
88 static struct ar_softc **ar_table = NULL;
89 static MALLOC_DEFINE(M_AR, "AR driver", "ATA RAID driver");
92 ata_raiddisk_attach(struct ad_softc *adp)
98 for (array = 0; array < MAX_ARRAYS; array++) {
99 if (!(rdp = ar_table[array]) || !rdp->flags)
102 for (disk = 0; disk < rdp->total_disks; disk++) {
103 if ((rdp->disks[disk].flags & AR_DF_ASSIGNED) &&
104 rdp->disks[disk].device == adp->device) {
105 ata_prtdev(rdp->disks[disk].device,
106 "inserted into ar%d disk%d as spare\n",
108 rdp->disks[disk].flags |= (AR_DF_PRESENT | AR_DF_SPARE);
109 AD_SOFTC(rdp->disks[disk])->flags = AD_F_RAID_SUBDISK;
110 ar_config_changed(rdp, 1);
118 ar_table = malloc(sizeof(struct ar_soft *) * MAX_ARRAYS,
119 M_AR, M_WAITOK | M_ZERO);
122 switch(adp->device->channel->chiptype) {
123 case 0x4d33105a: case 0x4d38105a: case 0x4d30105a:
124 case 0x0d30105a: case 0x4d68105a: case 0x6268105a:
125 case 0x4d69105a: case 0x5275105a: case 0x6269105a:
127 /* test RAID bit in PCI reg XXX */
128 return (ar_promise_read_conf(adp, ar_table, 0));
130 case 0x00041103: case 0x00051103: case 0x00081103:
131 return (ar_highpoint_read_conf(adp, ar_table));
134 return (ar_promise_read_conf(adp, ar_table, 1));
140 ata_raiddisk_detach(struct ad_softc *adp)
142 struct ar_softc *rdp;
146 for (array = 0; array < MAX_ARRAYS; array++) {
147 if (!(rdp = ar_table[array]) || !rdp->flags)
149 for (disk = 0; disk < rdp->total_disks; disk++) {
150 if (rdp->disks[disk].device == adp->device) {
151 ata_prtdev(rdp->disks[disk].device,
152 "deleted from ar%d disk%d\n", array, disk);
153 rdp->disks[disk].flags &= ~(AR_DF_PRESENT | AR_DF_ONLINE);
154 AD_SOFTC(rdp->disks[disk])->flags &= ~AD_F_RAID_SUBDISK;
155 ar_config_changed(rdp, 1);
167 struct ar_softc *rdp;
173 for (array = 0; array < MAX_ARRAYS; array++) {
174 if (!(rdp = ar_table[array]) || !rdp->flags)
176 ar_attach_raid(rdp, 0);
181 ar_attach_raid(struct ar_softc *rdp, int update)
186 ar_config_changed(rdp, update);
187 dev = disk_create(rdp->lun, &rdp->disk, 0, &ar_cdevsw);
189 dev->si_iosize_max = 256 * DEV_BSIZE;
192 printf("ar%d: %lluMB <ATA ", rdp->lun, (unsigned long long)
193 (rdp->total_sectors / ((1024L * 1024L) / DEV_BSIZE)));
194 switch (rdp->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) {
196 printf("RAID0 "); break;
198 printf("RAID1 "); break;
200 printf("SPAN "); break;
201 case (AR_F_RAID0 | AR_F_RAID1):
202 printf("RAID0+1 "); break;
204 printf("unknown 0x%x> ", rdp->flags);
207 printf("array> [%d/%d/%d] status: ",
208 rdp->cylinders, rdp->heads, rdp->sectors);
209 switch (rdp->flags & (AR_F_DEGRADED | AR_F_READY)) {
213 case (AR_F_DEGRADED | AR_F_READY):
220 printf(" subdisks:\n");
221 for (disk = 0; disk < rdp->total_disks; disk++) {
222 if (rdp->disks[disk].flags & AR_DF_PRESENT) {
223 if (rdp->disks[disk].flags & AR_DF_ONLINE)
224 printf(" %d READY ", disk);
225 else if (rdp->disks[disk].flags & AR_DF_SPARE)
226 printf(" %d SPARE ", disk);
228 printf(" %d FREE ", disk);
229 ad_print(AD_SOFTC(rdp->disks[disk]));
231 ata_enclosure_print(AD_SOFTC(rdp->disks[disk])->device);
233 else if (rdp->disks[disk].flags & AR_DF_ASSIGNED)
234 printf(" %d DOWN\n", disk);
236 printf(" %d INVALID no RAID config info on this disk\n", disk);
241 ata_raid_create(struct raid_setup *setup)
243 struct ata_device *atadev;
244 struct ar_softc *rdp;
246 int ctlr = 0, disk_size = 0, total_disks = 0;
249 ar_table = malloc(sizeof(struct ar_soft *) * MAX_ARRAYS,
250 M_AR, M_WAITOK | M_ZERO);
252 for (array = 0; array < MAX_ARRAYS; array++) {
253 if (!ar_table[array])
256 if (array >= MAX_ARRAYS)
259 rdp = malloc(sizeof(struct ar_softc), M_AR, M_WAITOK | M_ZERO);
261 for (disk = 0; disk < setup->total_disks; disk++) {
262 if ((atadev = ar_locate_disk(setup->disks[disk]))) {
263 rdp->disks[disk].device = atadev;
264 if (AD_SOFTC(rdp->disks[disk])->flags & AD_F_RAID_SUBDISK) {
265 setup->disks[disk] = -1;
270 switch (rdp->disks[disk].device->channel->chiptype & 0xffff) {
272 ctlr |= AR_F_HIGHPOINT_RAID;
273 rdp->disks[disk].disk_sectors =
274 AD_SOFTC(rdp->disks[disk])->total_secs;
278 ctlr |= AR_F_FREEBSD_RAID;
282 ctlr |= AR_F_PROMISE_RAID;
283 rdp->disks[disk].disk_sectors =
284 PR_LBA(AD_SOFTC(rdp->disks[disk]));
287 if ((rdp->flags & (AR_F_PROMISE_RAID|AR_F_HIGHPOINT_RAID)) &&
288 (rdp->flags & (AR_F_PROMISE_RAID|AR_F_HIGHPOINT_RAID)) !=
289 (ctlr & (AR_F_PROMISE_RAID|AR_F_HIGHPOINT_RAID))) {
297 disk_size = min(rdp->disks[disk].disk_sectors, disk_size);
299 disk_size = rdp->disks[disk].disk_sectors;
300 rdp->disks[disk].flags =
301 (AR_DF_PRESENT | AR_DF_ASSIGNED | AR_DF_ONLINE);
306 setup->disks[disk] = -1;
316 switch (setup->type) {
318 rdp->flags |= AR_F_RAID0;
321 rdp->flags |= AR_F_RAID1;
322 if (total_disks != 2) {
328 rdp->flags |= (AR_F_RAID0 | AR_F_RAID1);
329 if (total_disks % 2 != 0) {
335 rdp->flags |= AR_F_SPAN;
339 for (disk = 0; disk < total_disks; disk++)
340 AD_SOFTC(rdp->disks[disk])->flags = AD_F_RAID_SUBDISK;
343 if (rdp->flags & AR_F_RAID0) {
346 while (setup->interleave >>= 1)
348 if (rdp->flags & AR_F_PROMISE_RAID)
349 rdp->interleave = min(max(2, 1 << bit), 2048);
350 if (rdp->flags & AR_F_HIGHPOINT_RAID)
351 rdp->interleave = min(max(32, 1 << bit), 128);
353 rdp->total_disks = total_disks;
354 rdp->width = total_disks / ((rdp->flags & AR_F_RAID1) ? 2 : 1);
355 rdp->total_sectors = disk_size * rdp->width;
358 rdp->cylinders = rdp->total_sectors / (255 * 63);
359 if (rdp->flags & AR_F_PROMISE_RAID) {
363 if (rdp->flags & AR_F_HIGHPOINT_RAID) {
364 rdp->offset = HPT_LBA + 1;
365 rdp->reserved = HPT_LBA + 1;
367 rdp->lock_start = rdp->lock_end = 0xffffffff;
368 rdp->flags |= AR_F_READY;
370 ar_table[array] = rdp;
371 ar_attach_raid(rdp, 1);
377 ata_raid_delete(int array)
379 struct ar_softc *rdp;
383 printf("ar: no memory for ATA raid array\n");
386 if (!(rdp = ar_table[array]))
389 rdp->flags &= ~AR_F_READY;
390 for (disk = 0; disk < rdp->total_disks; disk++) {
391 if ((rdp->disks[disk].flags&AR_DF_PRESENT) && rdp->disks[disk].device) {
392 AD_SOFTC(rdp->disks[disk])->flags &= ~AD_F_RAID_SUBDISK;
393 ata_enclosure_leds(rdp->disks[disk].device, ATA_LED_GREEN);
394 rdp->disks[disk].flags = 0;
397 if (rdp->flags & AR_F_PROMISE_RAID)
398 ar_promise_write_conf(rdp);
400 ar_highpoint_write_conf(rdp);
401 disk_invalidate(&rdp->disk);
402 disk_destroy(&rdp->disk);
404 ar_table[array] = NULL;
409 ata_raid_status(int array, struct raid_status *status)
411 struct ar_softc *rdp;
414 if (!ar_table || !(rdp = ar_table[array]))
417 switch (rdp->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) {
419 status->type = AR_RAID0;
422 status->type = AR_RAID1;
424 case AR_F_RAID0 | AR_F_RAID1:
425 status->type = AR_RAID0 | AR_RAID1;
428 status->type = AR_SPAN;
431 status->total_disks = rdp->total_disks;
432 for (i = 0; i < rdp->total_disks; i++ ) {
433 if ((rdp->disks[i].flags & AR_DF_PRESENT) && rdp->disks[i].device)
434 status->disks[i] = AD_SOFTC(rdp->disks[i])->lun;
436 status->disks[i] = -1;
438 status->interleave = rdp->interleave;
440 if (rdp->flags & AR_F_READY)
441 status->status |= AR_READY;
442 if (rdp->flags & AR_F_DEGRADED)
443 status->status |= AR_DEGRADED;
444 if (rdp->flags & AR_F_REBUILDING) {
445 status->status |= AR_REBUILDING;
446 status->progress = 100*rdp->lock_start/(rdp->total_sectors/rdp->width);
452 ata_raid_rebuild(int array)
454 struct ar_softc *rdp;
456 if (!ar_table || !(rdp = ar_table[array]))
458 if (rdp->flags & AR_F_REBUILDING)
460 /* create process here XXX SOS */
461 return ar_rebuild(rdp);
465 aropen(dev_t dev, int flags, int fmt, struct thread *td)
467 struct ar_softc *rdp = dev->si_drv1;
468 struct disklabel *dl;
470 dl = &rdp->disk.d_label;
471 bzero(dl, sizeof *dl);
472 dl->d_secsize = DEV_BSIZE;
473 dl->d_nsectors = rdp->sectors;
474 dl->d_ntracks = rdp->heads;
475 dl->d_ncylinders = rdp->cylinders;
476 dl->d_secpercyl = rdp->sectors * rdp->heads;
477 dl->d_secperunit = rdp->total_sectors;
482 arstrategy(struct buf *bp)
484 struct ar_softc *rdp = bp->b_dev->si_drv1;
485 int blkno, count, chunk, lba, lbs, tmplba;
486 int drv = 0, change = 0;
489 if (!(rdp->flags & AR_F_READY)) {
490 bp->b_flags |= B_ERROR;
496 bp->b_resid = bp->b_bcount;
497 blkno = bp->b_pblkno;
499 for (count = howmany(bp->b_bcount, DEV_BSIZE); count > 0;
500 count -= chunk, blkno += chunk, data += (chunk * DEV_BSIZE)) {
501 struct ar_buf *buf1, *buf2;
503 switch (rdp->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) {
506 while (lba >= AD_SOFTC(rdp->disks[drv])->total_secs-rdp->reserved)
507 lba -= AD_SOFTC(rdp->disks[drv++])->total_secs-rdp->reserved;
508 chunk = min(AD_SOFTC(rdp->disks[drv])->total_secs-rdp->reserved-lba,
513 case AR_F_RAID0 | AR_F_RAID1:
514 tmplba = blkno / rdp->interleave;
515 chunk = blkno % rdp->interleave;
516 if (tmplba == rdp->total_sectors / rdp->interleave) {
517 lbs = (rdp->total_sectors-(tmplba*rdp->interleave))/rdp->width;
519 lba = ((tmplba/rdp->width)*rdp->interleave) + chunk%lbs;
520 chunk = min(count, lbs);
523 drv = tmplba % rdp->width;
524 lba = ((tmplba / rdp->width) * rdp->interleave) + chunk;
525 chunk = min(count, rdp->interleave - chunk);
536 printf("ar%d: unknown array type in arstrategy\n", rdp->lun);
537 bp->b_flags |= B_ERROR;
543 buf1 = malloc(sizeof(struct ar_buf), M_AR, M_INTWAIT | M_ZERO);
544 BUF_LOCKINIT(&buf1->bp);
545 BUF_LOCK(&buf1->bp, LK_EXCLUSIVE);
546 buf1->bp.b_pblkno = lba;
547 if ((buf1->drive = drv) > 0)
548 buf1->bp.b_pblkno += rdp->offset;
549 buf1->bp.b_caller1 = (void *)rdp;
550 buf1->bp.b_bcount = chunk * DEV_BSIZE;
551 buf1->bp.b_data = data;
552 buf1->bp.b_flags = bp->b_flags | B_CALL;
553 buf1->bp.b_iodone = ar_done;
556 switch (rdp->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) {
559 if ((rdp->disks[buf1->drive].flags &
560 (AR_DF_PRESENT|AR_DF_ONLINE))==(AR_DF_PRESENT|AR_DF_ONLINE) &&
561 !AD_SOFTC(rdp->disks[buf1->drive])->dev) {
562 rdp->disks[buf1->drive].flags &= ~AR_DF_ONLINE;
563 ar_config_changed(rdp, 1);
565 bp->b_flags |= B_ERROR;
570 buf1->bp.b_dev = AD_SOFTC(rdp->disks[buf1->drive])->dev;
571 AR_STRATEGY((struct buf *)buf1);
575 case AR_F_RAID0 | AR_F_RAID1:
576 if ((rdp->flags & AR_F_REBUILDING) && !(bp->b_flags & B_READ)) {
577 if ((bp->b_pblkno >= rdp->lock_start &&
578 bp->b_pblkno < rdp->lock_end) ||
579 ((bp->b_pblkno + chunk) > rdp->lock_start &&
580 (bp->b_pblkno + chunk) <= rdp->lock_end)) {
581 tsleep(rdp, 0, "arwait", 0);
584 if ((rdp->disks[buf1->drive].flags &
585 (AR_DF_PRESENT|AR_DF_ONLINE))==(AR_DF_PRESENT|AR_DF_ONLINE) &&
586 !AD_SOFTC(rdp->disks[buf1->drive])->dev) {
587 rdp->disks[buf1->drive].flags &= ~AR_DF_ONLINE;
590 if ((rdp->disks[buf1->drive + rdp->width].flags &
591 (AR_DF_PRESENT|AR_DF_ONLINE))==(AR_DF_PRESENT|AR_DF_ONLINE) &&
592 !AD_SOFTC(rdp->disks[buf1->drive + rdp->width])->dev) {
593 rdp->disks[buf1->drive + rdp->width].flags &= ~AR_DF_ONLINE;
597 ar_config_changed(rdp, 1);
599 if (!(rdp->flags & AR_F_READY)) {
601 bp->b_flags |= B_ERROR;
606 if (bp->b_flags & B_READ) {
607 if ((buf1->bp.b_pblkno <
608 (rdp->disks[buf1->drive].last_lba - AR_PROXIMITY) ||
610 (rdp->disks[buf1->drive].last_lba + AR_PROXIMITY) ||
611 !(rdp->disks[buf1->drive].flags & AR_DF_ONLINE)) &&
612 (rdp->disks[buf1->drive+rdp->width].flags & AR_DF_ONLINE))
613 buf1->drive = buf1->drive + rdp->width;
616 if ((rdp->disks[buf1->drive+rdp->width].flags & AR_DF_ONLINE) ||
617 ((rdp->flags & AR_F_REBUILDING) &&
618 (rdp->disks[buf1->drive+rdp->width].flags & AR_DF_SPARE) &&
619 buf1->bp.b_pblkno < rdp->lock_start)) {
620 if ((rdp->disks[buf1->drive].flags & AR_DF_ONLINE) ||
621 ((rdp->flags & AR_F_REBUILDING) &&
622 (rdp->disks[buf1->drive].flags & AR_DF_SPARE) &&
623 buf1->bp.b_pblkno < rdp->lock_start)) {
624 buf2 = malloc(sizeof(struct ar_buf), M_AR, M_INTWAIT);
625 bcopy(buf1, buf2, sizeof(struct ar_buf));
626 BUF_LOCKINIT(&buf2->bp);
627 BUF_LOCK(&buf2->bp, LK_EXCLUSIVE);
630 buf2->drive = buf1->drive + rdp->width;
631 buf2->bp.b_dev = AD_SOFTC(rdp->disks[buf2->drive])->dev;
632 AR_STRATEGY((struct buf *)buf2);
633 rdp->disks[buf2->drive].last_lba =
634 buf2->bp.b_pblkno + chunk;
637 buf1->drive = buf1->drive + rdp->width;
640 buf1->bp.b_dev = AD_SOFTC(rdp->disks[buf1->drive])->dev;
641 AR_STRATEGY((struct buf *)buf1);
642 rdp->disks[buf1->drive].last_lba = buf1->bp.b_pblkno + chunk;
646 printf("ar%d: unknown array type in arstrategy\n", rdp->lun);
652 ar_done(struct buf *bp)
654 struct ar_softc *rdp = (struct ar_softc *)bp->b_caller1;
655 struct ar_buf *buf = (struct ar_buf *)bp;
657 switch (rdp->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) {
660 if (buf->bp.b_flags & B_ERROR) {
661 rdp->disks[buf->drive].flags &= ~AR_DF_ONLINE;
662 ar_config_changed(rdp, 1);
663 buf->org->b_flags |= B_ERROR;
664 buf->org->b_error = EIO;
668 buf->org->b_resid -= buf->bp.b_bcount;
669 if (buf->org->b_resid == 0)
675 case AR_F_RAID0 | AR_F_RAID1:
676 if (buf->bp.b_flags & B_ERROR) {
677 rdp->disks[buf->drive].flags &= ~AR_DF_ONLINE;
678 ar_config_changed(rdp, 1);
679 if (rdp->flags & AR_F_READY) {
680 if (buf->bp.b_flags & B_READ) {
681 if (buf->drive < rdp->width)
682 buf->drive = buf->drive + rdp->width;
684 buf->drive = buf->drive - rdp->width;
685 buf->bp.b_dev = AD_SOFTC(rdp->disks[buf->drive])->dev;
686 buf->bp.b_flags = buf->org->b_flags | B_CALL;
688 AR_STRATEGY((struct buf *)buf);
692 if (buf->flags & AB_F_DONE) {
693 buf->org->b_resid -= buf->bp.b_bcount;
694 if (buf->org->b_resid == 0)
698 buf->mirror->flags |= AB_F_DONE;
702 buf->org->b_flags |= B_ERROR;
703 buf->org->b_error = EIO;
708 if (!(buf->bp.b_flags & B_READ)) {
709 if (buf->mirror && !(buf->flags & AB_F_DONE)){
710 buf->mirror->flags |= AB_F_DONE;
714 buf->org->b_resid -= buf->bp.b_bcount;
715 if (buf->org->b_resid == 0)
721 printf("ar%d: unknown array type in ar_done\n", rdp->lun);
727 ar_config_changed(struct ar_softc *rdp, int writeback)
732 rdp->flags |= AR_F_READY;
733 rdp->flags &= ~AR_F_DEGRADED;
735 for (disk = 0; disk < rdp->total_disks; disk++)
736 if (!(rdp->disks[disk].flags & AR_DF_PRESENT))
737 rdp->disks[disk].flags &= ~AR_DF_ONLINE;
739 for (disk = 0; disk < rdp->total_disks; disk++) {
740 switch (rdp->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) {
743 if (!(rdp->disks[disk].flags & AR_DF_ONLINE)) {
744 rdp->flags &= ~AR_F_READY;
745 printf("ar%d: ERROR - array broken\n", rdp->lun);
750 case AR_F_RAID0 | AR_F_RAID1:
751 if (disk < rdp->width) {
752 if (!(rdp->disks[disk].flags & AR_DF_ONLINE) &&
753 !(rdp->disks[disk + rdp->width].flags & AR_DF_ONLINE)) {
754 rdp->flags &= ~AR_F_READY;
755 printf("ar%d: ERROR - array broken\n", rdp->lun);
757 else if (((rdp->disks[disk].flags & AR_DF_ONLINE) &&
759 [disk + rdp->width].flags & AR_DF_ONLINE))||
760 (!(rdp->disks[disk].flags & AR_DF_ONLINE) &&
762 [disk + rdp->width].flags & AR_DF_ONLINE))) {
763 rdp->flags |= AR_F_DEGRADED;
764 if (!(flags & AR_F_DEGRADED))
765 printf("ar%d: WARNING - mirror lost\n", rdp->lun);
770 if ((rdp->disks[disk].flags&AR_DF_PRESENT) && rdp->disks[disk].device) {
771 if (rdp->disks[disk].flags & AR_DF_ONLINE)
772 ata_enclosure_leds(rdp->disks[disk].device, ATA_LED_GREEN);
774 ata_enclosure_leds(rdp->disks[disk].device, ATA_LED_RED);
778 if (rdp->flags & AR_F_PROMISE_RAID)
779 ar_promise_write_conf(rdp);
780 if (rdp->flags & AR_F_HIGHPOINT_RAID)
781 ar_highpoint_write_conf(rdp);
786 ar_rebuild(struct ar_softc *rdp)
788 int disk, s, count = 0, error = 0;
791 if ((rdp->flags & (AR_F_READY|AR_F_DEGRADED)) != (AR_F_READY|AR_F_DEGRADED))
794 for (disk = 0; disk < rdp->total_disks; disk++) {
795 if (((rdp->disks[disk].flags&(AR_DF_PRESENT|AR_DF_ONLINE|AR_DF_SPARE))==
796 (AR_DF_PRESENT | AR_DF_SPARE)) && rdp->disks[disk].device) {
797 if (AD_SOFTC(rdp->disks[disk])->total_secs <
798 rdp->disks[disk].disk_sectors) {
799 ata_prtdev(rdp->disks[disk].device,
800 "disk capacity too small for this RAID config\n");
802 rdp->disks[disk].flags &= ~AR_DF_SPARE;
803 AD_SOFTC(rdp->disks[disk])->flags &= ~AD_F_RAID_SUBDISK;
807 ata_enclosure_leds(rdp->disks[disk].device, ATA_LED_ORANGE);
814 /* setup start conditions */
817 rdp->lock_end = rdp->lock_start + 256;
818 rdp->flags |= AR_F_REBUILDING;
820 buffer = malloc(256 * DEV_BSIZE, M_AR, M_WAITOK | M_ZERO);
822 /* now go copy entire disk(s) */
823 while (rdp->lock_end < (rdp->total_sectors / rdp->width)) {
824 int size = min(256, (rdp->total_sectors / rdp->width) - rdp->lock_end);
826 for (disk = 0; disk < rdp->width; disk++) {
827 struct ad_softc *adp;
829 if (((rdp->disks[disk].flags & AR_DF_ONLINE) &&
830 (rdp->disks[disk + rdp->width].flags & AR_DF_ONLINE)) ||
831 ((rdp->disks[disk].flags & AR_DF_ONLINE) &&
832 !(rdp->disks[disk + rdp->width].flags & AR_DF_SPARE)) ||
833 ((rdp->disks[disk + rdp->width].flags & AR_DF_ONLINE) &&
834 !(rdp->disks[disk].flags & AR_DF_SPARE)))
837 if (rdp->disks[disk].flags & AR_DF_ONLINE)
838 adp = AD_SOFTC(rdp->disks[disk]);
840 adp = AD_SOFTC(rdp->disks[disk + rdp->width]);
841 if ((error = ar_rw(adp, rdp->lock_start,
842 size * DEV_BSIZE, buffer, AR_READ | AR_WAIT)))
845 if (rdp->disks[disk].flags & AR_DF_ONLINE)
846 adp = AD_SOFTC(rdp->disks[disk + rdp->width]);
848 adp = AD_SOFTC(rdp->disks[disk]);
849 if ((error = ar_rw(adp, rdp->lock_start,
850 size * DEV_BSIZE, buffer, AR_WRITE | AR_WAIT)))
859 rdp->lock_start = rdp->lock_end;
860 rdp->lock_end = rdp->lock_start + size;
865 for (disk = 0; disk < rdp->total_disks; disk++) {
866 if ((rdp->disks[disk].flags&(AR_DF_PRESENT|AR_DF_ONLINE|AR_DF_SPARE))==
867 (AR_DF_PRESENT | AR_DF_SPARE)) {
868 rdp->disks[disk].flags &= ~AR_DF_SPARE;
869 rdp->disks[disk].flags |= (AR_DF_ASSIGNED | AR_DF_ONLINE);
873 rdp->lock_start = 0xffffffff;
874 rdp->lock_end = 0xffffffff;
875 rdp->flags &= ~AR_F_REBUILDING;
877 ar_config_changed(rdp, 1);
882 ar_highpoint_read_conf(struct ad_softc *adp, struct ar_softc **raidp)
884 struct highpoint_raid_conf *info;
885 struct ar_softc *raid = NULL;
886 int array, disk_number = 0, retval = 0;
888 info = malloc(sizeof(struct highpoint_raid_conf), M_AR, M_INTWAIT|M_ZERO);
890 if (ar_rw(adp, HPT_LBA, sizeof(struct highpoint_raid_conf),
891 (caddr_t)info, AR_READ | AR_WAIT)) {
893 printf("ar: HighPoint read conf failed\n");
897 /* check if this is a HighPoint RAID struct */
898 if (info->magic != HPT_MAGIC_OK && info->magic != HPT_MAGIC_BAD) {
900 printf("ar: HighPoint check1 failed\n");
904 /* is this disk defined, or an old leftover/spare ? */
905 if (!info->magic_0) {
907 printf("ar: HighPoint check2 failed\n");
911 /* now convert HighPoint config info into our generic form */
912 for (array = 0; array < MAX_ARRAYS; array++) {
914 raidp[array] = malloc(sizeof(struct ar_softc), M_AR,
918 if (raid->flags & AR_F_PROMISE_RAID)
921 switch (info->type) {
923 if ((info->order & (HPT_O_RAID0|HPT_O_OK))==(HPT_O_RAID0|HPT_O_OK))
924 goto highpoint_raid1;
925 if (info->order & (HPT_O_RAID0 | HPT_O_RAID1))
926 goto highpoint_raid01;
927 if (raid->magic_0 && raid->magic_0 != info->magic_0)
929 raid->magic_0 = info->magic_0;
930 raid->flags |= AR_F_RAID0;
931 raid->interleave = 1 << info->stripe_shift;
932 disk_number = info->disk_number;
933 if (!(info->order & HPT_O_OK))
934 info->magic = 0; /* mark bad */
939 if (raid->magic_0 && raid->magic_0 != info->magic_0)
941 raid->magic_0 = info->magic_0;
942 raid->flags |= AR_F_RAID1;
943 disk_number = (info->disk_number > 0);
946 case HPT_T_RAID01_RAID0:
948 if (info->order & HPT_O_RAID0) {
949 if ((raid->magic_0 && raid->magic_0 != info->magic_0) ||
950 (raid->magic_1 && raid->magic_1 != info->magic_1))
952 raid->magic_0 = info->magic_0;
953 raid->magic_1 = info->magic_1;
954 raid->flags |= (AR_F_RAID0 | AR_F_RAID1);
955 raid->interleave = 1 << info->stripe_shift;
956 disk_number = info->disk_number;
959 if (raid->magic_1 && raid->magic_1 != info->magic_1)
961 raid->magic_1 = info->magic_1;
962 raid->flags |= (AR_F_RAID0 | AR_F_RAID1);
963 raid->interleave = 1 << info->stripe_shift;
964 disk_number = info->disk_number + info->array_width;
965 if (!(info->order & HPT_O_RAID1))
966 info->magic = 0; /* mark bad */
971 if (raid->magic_0 && raid->magic_0 != info->magic_0)
973 raid->magic_0 = info->magic_0;
974 raid->flags |= AR_F_SPAN;
975 disk_number = info->disk_number;
979 printf("ar%d: HighPoint unknown RAID type 0x%02x\n",
984 raid->flags |= AR_F_HIGHPOINT_RAID;
985 raid->disks[disk_number].device = adp->device;
986 raid->disks[disk_number].flags = (AR_DF_PRESENT | AR_DF_ASSIGNED);
988 if (info->magic == HPT_MAGIC_OK) {
989 raid->disks[disk_number].flags |= AR_DF_ONLINE;
990 raid->flags |= AR_F_READY;
991 raid->width = info->array_width;
994 raid->cylinders = info->total_sectors / (63 * 255);
995 raid->total_sectors = info->total_sectors;
996 raid->offset = HPT_LBA + 1;
997 raid->reserved = HPT_LBA + 1;
998 raid->lock_start = raid->lock_end = info->rebuild_lba;
999 raid->disks[disk_number].disk_sectors =
1000 info->total_sectors / info->array_width;
1003 raid->disks[disk_number].flags &= ~ AR_DF_ONLINE;
1005 if ((raid->flags & AR_F_RAID0) && (raid->total_disks < raid->width))
1006 raid->total_disks = raid->width;
1007 if (disk_number >= raid->total_disks)
1008 raid->total_disks = disk_number + 1;
1018 ar_highpoint_write_conf(struct ar_softc *rdp)
1020 struct highpoint_raid_conf *config;
1021 struct timeval timestamp;
1024 microtime(×tamp);
1025 rdp->magic_0 = timestamp.tv_sec + 2;
1026 rdp->magic_1 = timestamp.tv_sec;
1028 for (disk = 0; disk < rdp->total_disks; disk++) {
1029 config = malloc(sizeof(struct highpoint_raid_conf),
1030 M_AR, M_INTWAIT | M_ZERO);
1031 if ((rdp->disks[disk].flags & (AR_DF_PRESENT | AR_DF_ONLINE)) ==
1032 (AR_DF_PRESENT | AR_DF_ONLINE))
1033 config->magic = HPT_MAGIC_OK;
1034 if (rdp->disks[disk].flags & AR_DF_ASSIGNED) {
1035 config->magic_0 = rdp->magic_0;
1036 strcpy(config->name_1, "FreeBSD");
1038 config->disk_number = disk;
1040 switch (rdp->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) {
1042 config->type = HPT_T_RAID0;
1043 strcpy(config->name_2, "RAID 0");
1044 if (rdp->disks[disk].flags & AR_DF_ONLINE)
1045 config->order = HPT_O_OK;
1049 config->type = HPT_T_RAID0; /* bogus but old HPT BIOS need it */
1050 strcpy(config->name_2, "RAID 1");
1051 config->disk_number = (disk < rdp->width) ? disk : disk + 5;
1052 config->order = HPT_O_RAID0 | HPT_O_OK;
1055 case AR_F_RAID0 | AR_F_RAID1:
1056 config->type = HPT_T_RAID01_RAID0;
1057 strcpy(config->name_2, "RAID 0+1");
1058 if (rdp->disks[disk].flags & AR_DF_ONLINE) {
1059 if (disk < rdp->width) {
1060 config->order = (HPT_O_RAID0 | HPT_O_RAID1);
1061 config->magic_0 = rdp->magic_0 - 1;
1064 config->order = HPT_O_RAID1;
1065 config->disk_number -= rdp->width;
1069 config->magic_0 = rdp->magic_0 - 1;
1070 config->magic_1 = rdp->magic_1;
1074 config->type = HPT_T_SPAN;
1075 strcpy(config->name_2, "SPAN");
1079 config->array_width = rdp->width;
1080 config->stripe_shift = (rdp->width > 1) ? (ffs(rdp->interleave)-1) : 0;
1081 config->total_sectors = rdp->total_sectors;
1082 config->rebuild_lba = rdp->lock_start;
1084 if ((rdp->disks[disk].device && rdp->disks[disk].device->driver) &&
1085 !(rdp->disks[disk].device->flags & ATA_D_DETACHING)) {
1087 if (ar_rw(AD_SOFTC(rdp->disks[disk]), HPT_LBA,
1088 sizeof(struct highpoint_raid_conf),
1089 (caddr_t)config, AR_WRITE)) {
1090 printf("ar%d: Highpoint write conf failed\n", rdp->lun);
1099 ar_promise_read_conf(struct ad_softc *adp, struct ar_softc **raidp, int local)
1101 struct promise_raid_conf *info;
1102 struct ar_softc *raid;
1103 u_int32_t magic, cksum, *ckptr;
1104 int array, count, disk, disksum = 0, retval = 0;
1106 info = malloc(sizeof(struct promise_raid_conf), M_AR, M_INTWAIT | M_ZERO);
1108 if (ar_rw(adp, PR_LBA(adp), sizeof(struct promise_raid_conf),
1109 (caddr_t)info, AR_READ | AR_WAIT)) {
1111 printf("ar: %s read conf failed\n", local ? "FreeBSD" : "Promise");
1115 /* check if this is a Promise RAID struct (or our local one) */
1117 if (strncmp(info->promise_id, ATA_MAGIC, sizeof(ATA_MAGIC))) {
1119 printf("ar: FreeBSD check1 failed\n");
1124 if (strncmp(info->promise_id, PR_MAGIC, sizeof(PR_MAGIC))) {
1126 printf("ar: Promise check1 failed\n");
1131 /* check if the checksum is OK */
1132 for (cksum = 0, ckptr = (int32_t *)info, count = 0; count < 511; count++)
1134 if (cksum != *ckptr) {
1136 printf("ar: %s check2 failed\n", local ? "FreeBSD" : "Promise");
1140 /* now convert Promise config info into our generic form */
1141 if (info->raid.integrity != PR_I_VALID) {
1143 printf("ar: %s check3 failed\n", local ? "FreeBSD" : "Promise");
1147 for (array = 0; array < MAX_ARRAYS; array++) {
1148 if (!raidp[array]) {
1149 raidp[array] = malloc(sizeof(struct ar_softc), M_AR,
1150 M_INTWAIT | M_ZERO);
1152 raid = raidp[array];
1153 if (raid->flags & AR_F_HIGHPOINT_RAID)
1156 magic = (adp->device->channel->chiptype >> 16) |
1157 (info->raid.array_number << 16);
1159 if ((raid->flags & AR_F_PROMISE_RAID) && magic != raid->magic_0)
1162 /* update our knowledge about the array config based on generation */
1163 if (!info->raid.generation || info->raid.generation > raid->generation){
1164 raid->generation = info->raid.generation;
1165 raid->flags = AR_F_PROMISE_RAID;
1167 raid->flags |= AR_F_FREEBSD_RAID;
1168 raid->magic_0 = magic;
1170 if ((info->raid.status &
1171 (PR_S_VALID | PR_S_ONLINE | PR_S_INITED | PR_S_READY)) ==
1172 (PR_S_VALID | PR_S_ONLINE | PR_S_INITED | PR_S_READY)) {
1173 raid->flags |= AR_F_READY;
1174 if (info->raid.status & PR_S_DEGRADED)
1175 raid->flags |= AR_F_DEGRADED;
1178 raid->flags &= ~AR_F_READY;
1180 switch (info->raid.type) {
1182 raid->flags |= AR_F_RAID0;
1186 raid->flags |= AR_F_RAID1;
1187 if (info->raid.array_width > 1)
1188 raid->flags |= AR_F_RAID0;
1192 raid->flags |= AR_F_SPAN;
1196 printf("ar%d: %s unknown RAID type 0x%02x\n",
1197 array, local ? "FreeBSD" : "Promise", info->raid.type);
1200 raid->interleave = 1 << info->raid.stripe_shift;
1201 raid->width = info->raid.array_width;
1202 raid->total_disks = info->raid.total_disks;
1203 raid->heads = info->raid.heads + 1;
1204 raid->sectors = info->raid.sectors;
1205 raid->cylinders = info->raid.cylinders + 1;
1206 raid->total_sectors = info->raid.total_sectors;
1208 raid->reserved = 63;
1209 raid->lock_start = raid->lock_end = info->raid.rebuild_lba;
1211 /* convert disk flags to our internal types */
1212 for (disk = 0; disk < info->raid.total_disks; disk++) {
1213 raid->disks[disk].flags = 0;
1214 disksum += info->raid.disk[disk].flags;
1215 if (info->raid.disk[disk].flags & PR_F_ONLINE)
1216 raid->disks[disk].flags |= AR_DF_ONLINE;
1217 if (info->raid.disk[disk].flags & PR_F_ASSIGNED)
1218 raid->disks[disk].flags |= AR_DF_ASSIGNED;
1219 if (info->raid.disk[disk].flags & PR_F_SPARE) {
1220 raid->disks[disk].flags &= ~AR_DF_ONLINE;
1221 raid->disks[disk].flags |= AR_DF_SPARE;
1223 if (info->raid.disk[disk].flags & (PR_F_REDIR | PR_F_DOWN))
1224 raid->disks[disk].flags &= ~AR_DF_ONLINE;
1227 free(raidp[array], M_AR);
1228 raidp[array] = NULL;
1232 if (raid->disks[info->raid.disk_number].flags && adp->device) {
1233 raid->disks[info->raid.disk_number].device = adp->device;
1234 raid->disks[info->raid.disk_number].flags |= AR_DF_PRESENT;
1235 raid->disks[info->raid.disk_number].disk_sectors =
1236 info->raid.total_sectors / info->raid.array_width;
1237 /*info->raid.disk_sectors;*/
1248 ar_promise_write_conf(struct ar_softc *rdp)
1250 struct promise_raid_conf *config;
1251 struct timeval timestamp;
1253 int count, disk, drive;
1254 int local = rdp->flags & AR_F_FREEBSD_RAID;
1257 microtime(×tamp);
1259 for (disk = 0; disk < rdp->total_disks; disk++) {
1260 config = malloc(sizeof(struct promise_raid_conf), M_AR, M_INTWAIT);
1261 for (count = 0; count < sizeof(struct promise_raid_conf); count++)
1262 *(((u_int8_t *)config) + count) = 255 - (count % 256);
1265 bcopy(ATA_MAGIC, config->promise_id, sizeof(ATA_MAGIC));
1267 bcopy(PR_MAGIC, config->promise_id, sizeof(PR_MAGIC));
1268 config->dummy_0 = 0x00020000;
1269 config->magic_0 = PR_MAGIC0(rdp->disks[disk]) | timestamp.tv_sec;
1270 config->magic_1 = timestamp.tv_sec >> 16;
1271 config->magic_2 = timestamp.tv_sec;
1272 config->raid.integrity = PR_I_VALID;
1274 config->raid.disk_number = disk;
1275 if ((rdp->disks[disk].flags&AR_DF_PRESENT) && rdp->disks[disk].device) {
1276 config->raid.channel = rdp->disks[disk].device->channel->unit;
1277 config->raid.device = (rdp->disks[disk].device->unit != 0);
1278 if (AD_SOFTC(rdp->disks[disk])->dev)
1279 config->raid.disk_sectors = PR_LBA(AD_SOFTC(rdp->disks[disk]));
1280 /*config->raid.disk_offset*/
1282 config->raid.magic_0 = config->magic_0;
1283 config->raid.rebuild_lba = rdp->lock_start;
1284 config->raid.generation = rdp->generation;
1286 if (rdp->flags & AR_F_READY) {
1287 config->raid.flags = (PR_F_VALID | PR_F_ASSIGNED | PR_F_ONLINE);
1288 config->raid.status =
1289 (PR_S_VALID | PR_S_ONLINE | PR_S_INITED | PR_S_READY);
1290 if (rdp->flags & AR_F_DEGRADED)
1291 config->raid.status |= PR_S_DEGRADED;
1293 config->raid.status |= PR_S_FUNCTIONAL;
1296 config->raid.status = 0;
1297 config->raid.flags = PR_F_DOWN;
1300 switch (rdp->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) {
1302 config->raid.type = PR_T_RAID0;
1305 config->raid.type = PR_T_RAID1;
1307 case AR_F_RAID0 | AR_F_RAID1:
1308 config->raid.type = PR_T_RAID1;
1311 config->raid.type = PR_T_SPAN;
1315 config->raid.total_disks = rdp->total_disks;
1316 config->raid.stripe_shift = ffs(rdp->interleave) - 1;
1317 config->raid.array_width = rdp->width;
1318 config->raid.array_number = rdp->lun;
1319 config->raid.total_sectors = rdp->total_sectors;
1320 config->raid.cylinders = rdp->cylinders - 1;
1321 config->raid.heads = rdp->heads - 1;
1322 config->raid.sectors = rdp->sectors;
1323 config->raid.magic_1 = (u_int64_t)config->magic_2<<16 | config->magic_1;
1325 bzero(&config->raid.disk, 8 * 12);
1326 for (drive = 0; drive < rdp->total_disks; drive++) {
1327 config->raid.disk[drive].flags = 0;
1328 if (rdp->disks[drive].flags & AR_DF_PRESENT)
1329 config->raid.disk[drive].flags |= PR_F_VALID;
1330 if (rdp->disks[drive].flags & AR_DF_ASSIGNED)
1331 config->raid.disk[drive].flags |= PR_F_ASSIGNED;
1332 if (rdp->disks[drive].flags & AR_DF_ONLINE)
1333 config->raid.disk[drive].flags |= PR_F_ONLINE;
1335 if (rdp->disks[drive].flags & AR_DF_PRESENT)
1336 config->raid.disk[drive].flags = (PR_F_REDIR | PR_F_DOWN);
1337 if (rdp->disks[drive].flags & AR_DF_SPARE)
1338 config->raid.disk[drive].flags |= PR_F_SPARE;
1339 config->raid.disk[drive].dummy_0 = 0x0;
1340 if (rdp->disks[drive].device) {
1341 config->raid.disk[drive].channel =
1342 rdp->disks[drive].device->channel->unit;
1343 config->raid.disk[drive].device =
1344 (rdp->disks[drive].device->unit != 0);
1346 config->raid.disk[drive].magic_0 =
1347 PR_MAGIC0(rdp->disks[drive]) | timestamp.tv_sec;
1350 config->checksum = 0;
1351 for (ckptr = (int32_t *)config, count = 0; count < 511; count++)
1352 config->checksum += *ckptr++;
1353 if (rdp->disks[disk].device && rdp->disks[disk].device->driver &&
1354 !(rdp->disks[disk].device->flags & ATA_D_DETACHING)) {
1355 if (ar_rw(AD_SOFTC(rdp->disks[disk]),
1356 PR_LBA(AD_SOFTC(rdp->disks[disk])),
1357 sizeof(struct promise_raid_conf),
1358 (caddr_t)config, AR_WRITE)) {
1359 printf("ar%d: %s write conf failed\n",
1360 rdp->lun, local ? "FreeBSD" : "Promise");
1369 ar_rw_done(struct buf *bp)
1371 free(bp->b_data, M_AR);
1376 ar_rw(struct ad_softc *adp, u_int32_t lba, int count, caddr_t data, int flags)
1379 int retry = 0, error = 0;
1381 bp = malloc(sizeof(struct buf), M_AR, M_INTWAIT|M_ZERO);
1383 BUF_LOCK(bp, LK_EXCLUSIVE);
1384 bp->b_dev = adp->dev;
1387 bp->b_bcount = count;
1388 if (flags & AR_WAIT)
1389 bp->b_iodone = (void *)wakeup;
1391 bp->b_iodone = ar_rw_done;
1392 bp->b_flags = B_CALL;
1393 if (flags & AR_READ)
1394 bp->b_flags |= B_READ;
1395 if (flags & AR_WRITE)
1396 bp->b_flags |= B_WRITE;
1398 AR_STRATEGY((struct buf *)bp);
1400 if (flags & AR_WAIT) {
1401 while ((retry++ < (15*hz/10)) && (error = !(bp->b_flags & B_DONE)))
1402 error = tsleep(bp, 0, "arrw", 10);
1403 if (!error && (bp->b_flags & B_ERROR))
1404 error = bp->b_error;
1410 static struct ata_device *
1411 ar_locate_disk(int diskno)
1413 struct ata_channel *ch;
1416 for (ctlr = 0; ctlr < devclass_get_maxunit(ata_devclass); ctlr++) {
1417 if (!(ch = devclass_get_softc(ata_devclass, ctlr)))
1419 if (ch->devices & ATA_ATA_MASTER)
1420 if (ch->device[MASTER].driver &&
1421 ((struct ad_softc *)(ch->device[MASTER].driver))->lun == diskno)
1422 return &ch->device[MASTER];
1423 if (ch->devices & ATA_ATA_SLAVE)
1424 if (ch->device[SLAVE].driver &&
1425 ((struct ad_softc *)(ch->device[SLAVE].driver))->lun == diskno)
1426 return &ch->device[SLAVE];