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.26 2007/05/15 00:01:03 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>
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_config_changed(struct ar_softc
*, int);
70 static int ar_rebuild(struct ar_softc
*);
71 static int ar_highpoint_read_conf(struct ad_softc
*, struct ar_softc
**);
72 static int ar_highpoint_write_conf(struct ar_softc
*);
73 static int ar_promise_read_conf(struct ad_softc
*, struct ar_softc
**, int);
74 static int ar_promise_write_conf(struct ar_softc
*);
75 static int ar_rw(struct ad_softc
*, u_int32_t
, int, caddr_t
, int);
76 static struct ata_device
*ar_locate_disk(int);
79 static struct ar_softc
**ar_table
= NULL
;
80 static MALLOC_DEFINE(M_AR
, "AR driver", "ATA RAID driver");
83 ata_raiddisk_attach(struct ad_softc
*adp
)
89 for (array
= 0; array
< MAX_ARRAYS
; array
++) {
90 if (!(rdp
= ar_table
[array
]) || !rdp
->flags
)
93 for (disk
= 0; disk
< rdp
->total_disks
; disk
++) {
94 if ((rdp
->disks
[disk
].flags
& AR_DF_ASSIGNED
) &&
95 rdp
->disks
[disk
].device
== adp
->device
) {
96 ata_prtdev(rdp
->disks
[disk
].device
,
97 "inserted into ar%d disk%d as spare\n",
99 rdp
->disks
[disk
].flags
|= (AR_DF_PRESENT
| AR_DF_SPARE
);
100 AD_SOFTC(rdp
->disks
[disk
])->flags
= AD_F_RAID_SUBDISK
;
101 ar_config_changed(rdp
, 1);
109 ar_table
= kmalloc(sizeof(struct ar_soft
*) * MAX_ARRAYS
,
110 M_AR
, M_WAITOK
| M_ZERO
);
113 switch(adp
->device
->channel
->chiptype
) {
114 case 0x4d33105a: case 0x4d38105a: case 0x4d30105a:
115 case 0x0d30105a: case 0x4d68105a: case 0x6268105a:
116 case 0x4d69105a: case 0x5275105a: case 0x6269105a:
118 /* test RAID bit in PCI reg XXX */
119 return (ar_promise_read_conf(adp
, ar_table
, 0));
121 case 0x00041103: case 0x00051103: case 0x00081103:
122 return (ar_highpoint_read_conf(adp
, ar_table
));
125 return (ar_promise_read_conf(adp
, ar_table
, 1));
131 ata_raiddisk_detach(struct ad_softc
*adp
)
133 struct ar_softc
*rdp
;
137 for (array
= 0; array
< MAX_ARRAYS
; array
++) {
138 if (!(rdp
= ar_table
[array
]) || !rdp
->flags
)
140 for (disk
= 0; disk
< rdp
->total_disks
; disk
++) {
141 if (rdp
->disks
[disk
].device
== adp
->device
) {
142 ata_prtdev(rdp
->disks
[disk
].device
,
143 "deleted from ar%d disk%d\n", array
, disk
);
144 rdp
->disks
[disk
].flags
&= ~(AR_DF_PRESENT
| AR_DF_ONLINE
);
145 AD_SOFTC(rdp
->disks
[disk
])->flags
&= ~AD_F_RAID_SUBDISK
;
146 ar_config_changed(rdp
, 1);
158 struct ar_softc
*rdp
;
164 for (array
= 0; array
< MAX_ARRAYS
; array
++) {
165 if (!(rdp
= ar_table
[array
]) || !rdp
->flags
)
167 ar_attach_raid(rdp
, 0);
172 ar_attach_raid(struct ar_softc
*rdp
, int update
)
174 struct disk_info info
;
178 ar_config_changed(rdp
, update
);
179 dev
= disk_create(rdp
->lun
, &rdp
->disk
, &ar_ops
);
181 dev
->si_iosize_max
= 256 * DEV_BSIZE
;
185 * Set disk info, as it appears that all needed data is available already.
186 * Setting the disk info will also cause the probing to start.
188 bzero(&info
, sizeof(info
));
189 info
.d_media_blksize
= DEV_BSIZE
; /* mandatory */
190 info
.d_media_blocks
= rdp
->total_sectors
;
192 info
.d_secpertrack
= rdp
->sectors
; /* optional */
193 info
.d_nheads
= rdp
->heads
;
194 info
.d_ncylinders
= rdp
->cylinders
;
195 info
.d_secpercyl
= rdp
->sectors
* rdp
->heads
;
197 kprintf("ar%d: %lluMB <ATA ", rdp
->lun
, (unsigned long long)
198 (rdp
->total_sectors
/ ((1024L * 1024L) / DEV_BSIZE
)));
199 switch (rdp
->flags
& (AR_F_RAID0
| AR_F_RAID1
| AR_F_SPAN
)) {
201 kprintf("RAID0 "); break;
203 kprintf("RAID1 "); break;
205 kprintf("SPAN "); break;
206 case (AR_F_RAID0
| AR_F_RAID1
):
207 kprintf("RAID0+1 "); break;
209 kprintf("unknown 0x%x> ", rdp
->flags
);
212 kprintf("array> [%d/%d/%d] status: ",
213 rdp
->cylinders
, rdp
->heads
, rdp
->sectors
);
214 switch (rdp
->flags
& (AR_F_DEGRADED
| AR_F_READY
)) {
218 case (AR_F_DEGRADED
| AR_F_READY
):
225 kprintf(" subdisks:\n");
226 for (disk
= 0; disk
< rdp
->total_disks
; disk
++) {
227 if (rdp
->disks
[disk
].flags
& AR_DF_PRESENT
) {
228 if (rdp
->disks
[disk
].flags
& AR_DF_ONLINE
)
229 kprintf(" %d READY ", disk
);
230 else if (rdp
->disks
[disk
].flags
& AR_DF_SPARE
)
231 kprintf(" %d SPARE ", disk
);
233 kprintf(" %d FREE ", disk
);
234 ad_print(AD_SOFTC(rdp
->disks
[disk
]));
236 ata_enclosure_print(AD_SOFTC(rdp
->disks
[disk
])->device
);
238 else if (rdp
->disks
[disk
].flags
& AR_DF_ASSIGNED
)
239 kprintf(" %d DOWN\n", disk
);
241 kprintf(" %d INVALID no RAID config info on this disk\n", disk
);
243 disk_setdiskinfo(&rdp
->disk
, &info
);
247 ata_raid_create(struct raid_setup
*setup
)
249 struct ata_device
*atadev
;
250 struct ar_softc
*rdp
;
252 int ctlr
= 0, disk_size
= 0, total_disks
= 0;
255 ar_table
= kmalloc(sizeof(struct ar_soft
*) * MAX_ARRAYS
,
256 M_AR
, M_WAITOK
| M_ZERO
);
258 for (array
= 0; array
< MAX_ARRAYS
; array
++) {
259 if (!ar_table
[array
])
262 if (array
>= MAX_ARRAYS
)
265 rdp
= kmalloc(sizeof(struct ar_softc
), M_AR
, M_WAITOK
| M_ZERO
);
267 for (disk
= 0; disk
< setup
->total_disks
; disk
++) {
268 if ((atadev
= ar_locate_disk(setup
->disks
[disk
]))) {
269 rdp
->disks
[disk
].device
= atadev
;
270 if (AD_SOFTC(rdp
->disks
[disk
])->flags
& AD_F_RAID_SUBDISK
) {
271 setup
->disks
[disk
] = -1;
276 switch (rdp
->disks
[disk
].device
->channel
->chiptype
& 0xffff) {
278 ctlr
|= AR_F_HIGHPOINT_RAID
;
279 rdp
->disks
[disk
].disk_sectors
=
280 AD_SOFTC(rdp
->disks
[disk
])->total_secs
;
284 ctlr
|= AR_F_FREEBSD_RAID
;
288 ctlr
|= AR_F_PROMISE_RAID
;
289 rdp
->disks
[disk
].disk_sectors
=
290 PR_LBA(AD_SOFTC(rdp
->disks
[disk
]));
293 if ((rdp
->flags
& (AR_F_PROMISE_RAID
|AR_F_HIGHPOINT_RAID
)) &&
294 (rdp
->flags
& (AR_F_PROMISE_RAID
|AR_F_HIGHPOINT_RAID
)) !=
295 (ctlr
& (AR_F_PROMISE_RAID
|AR_F_HIGHPOINT_RAID
))) {
303 disk_size
= min(rdp
->disks
[disk
].disk_sectors
, disk_size
);
305 disk_size
= rdp
->disks
[disk
].disk_sectors
;
306 rdp
->disks
[disk
].flags
=
307 (AR_DF_PRESENT
| AR_DF_ASSIGNED
| AR_DF_ONLINE
);
312 setup
->disks
[disk
] = -1;
322 switch (setup
->type
) {
324 rdp
->flags
|= AR_F_RAID0
;
327 rdp
->flags
|= AR_F_RAID1
;
328 if (total_disks
!= 2) {
334 rdp
->flags
|= (AR_F_RAID0
| AR_F_RAID1
);
335 if (total_disks
% 2 != 0) {
341 rdp
->flags
|= AR_F_SPAN
;
345 for (disk
= 0; disk
< total_disks
; disk
++)
346 AD_SOFTC(rdp
->disks
[disk
])->flags
= AD_F_RAID_SUBDISK
;
349 if (rdp
->flags
& AR_F_RAID0
) {
352 while (setup
->interleave
>>= 1)
354 if (rdp
->flags
& AR_F_PROMISE_RAID
)
355 rdp
->interleave
= min(max(2, 1 << bit
), 2048);
356 if (rdp
->flags
& AR_F_HIGHPOINT_RAID
)
357 rdp
->interleave
= min(max(32, 1 << bit
), 128);
359 rdp
->total_disks
= total_disks
;
360 rdp
->width
= total_disks
/ ((rdp
->flags
& AR_F_RAID1
) ? 2 : 1);
361 rdp
->total_sectors
= disk_size
* rdp
->width
;
364 rdp
->cylinders
= rdp
->total_sectors
/ (255 * 63);
365 if (rdp
->flags
& AR_F_PROMISE_RAID
) {
369 if (rdp
->flags
& AR_F_HIGHPOINT_RAID
) {
370 rdp
->offset
= HPT_LBA
+ 1;
371 rdp
->reserved
= HPT_LBA
+ 1;
373 rdp
->lock_start
= rdp
->lock_end
= 0xffffffff;
374 rdp
->flags
|= AR_F_READY
;
376 ar_table
[array
] = rdp
;
377 ar_attach_raid(rdp
, 1);
383 ata_raid_delete(int array
)
385 struct ar_softc
*rdp
;
389 kprintf("ar: no memory for ATA raid array\n");
392 if (!(rdp
= ar_table
[array
]))
395 rdp
->flags
&= ~AR_F_READY
;
396 for (disk
= 0; disk
< rdp
->total_disks
; disk
++) {
397 if ((rdp
->disks
[disk
].flags
&AR_DF_PRESENT
) && rdp
->disks
[disk
].device
) {
398 AD_SOFTC(rdp
->disks
[disk
])->flags
&= ~AD_F_RAID_SUBDISK
;
399 ata_enclosure_leds(rdp
->disks
[disk
].device
, ATA_LED_GREEN
);
400 rdp
->disks
[disk
].flags
= 0;
403 if (rdp
->flags
& AR_F_PROMISE_RAID
)
404 ar_promise_write_conf(rdp
);
406 ar_highpoint_write_conf(rdp
);
407 disk_invalidate(&rdp
->disk
);
408 disk_destroy(&rdp
->disk
);
410 ar_table
[array
] = NULL
;
415 ata_raid_status(int array
, struct raid_status
*status
)
417 struct ar_softc
*rdp
;
420 if (!ar_table
|| !(rdp
= ar_table
[array
]))
423 switch (rdp
->flags
& (AR_F_RAID0
| AR_F_RAID1
| AR_F_SPAN
)) {
425 status
->type
= AR_RAID0
;
428 status
->type
= AR_RAID1
;
430 case AR_F_RAID0
| AR_F_RAID1
:
431 status
->type
= AR_RAID0
| AR_RAID1
;
434 status
->type
= AR_SPAN
;
437 status
->total_disks
= rdp
->total_disks
;
438 for (i
= 0; i
< rdp
->total_disks
; i
++ ) {
439 if ((rdp
->disks
[i
].flags
& AR_DF_PRESENT
) && rdp
->disks
[i
].device
)
440 status
->disks
[i
] = AD_SOFTC(rdp
->disks
[i
])->lun
;
442 status
->disks
[i
] = -1;
444 status
->interleave
= rdp
->interleave
;
446 if (rdp
->flags
& AR_F_READY
)
447 status
->status
|= AR_READY
;
448 if (rdp
->flags
& AR_F_DEGRADED
)
449 status
->status
|= AR_DEGRADED
;
450 if (rdp
->flags
& AR_F_REBUILDING
) {
451 status
->status
|= AR_REBUILDING
;
452 status
->progress
= 100*rdp
->lock_start
/(rdp
->total_sectors
/rdp
->width
);
458 ata_raid_rebuild(int array
)
460 struct ar_softc
*rdp
;
462 if (!ar_table
|| !(rdp
= ar_table
[array
]))
464 if (rdp
->flags
& AR_F_REBUILDING
)
466 /* create process here XXX SOS */
467 return ar_rebuild(rdp
);
471 aropen(struct dev_open_args
*ap
)
474 struct ar_softc
*rdp
= ap
->a_head
.a_dev
->si_drv1
;
475 struct disk_info info
;
477 bzero(&info
, sizeof(info
));
478 info
.d_media_blksize
= DEV_BSIZE
; /* mandatory */
479 info
.d_media_blocks
= rdp
->total_sectors
;
481 info
.d_secpertrack
= rdp
->sectors
; /* optional */
482 info
.d_nheads
= rdp
->heads
;
483 info
.d_ncylinders
= rdp
->cylinders
;
484 info
.d_secpercyl
= rdp
->sectors
* rdp
->heads
;
485 disk_setdiskinfo(&rdp
->disk
, &info
);
491 arstrategy(struct dev_strategy_args
*ap
)
493 cdev_t dev
= ap
->a_head
.a_dev
;
494 struct bio
*bio
= ap
->a_bio
;
495 struct buf
*bp
= bio
->bio_buf
;
496 struct ar_softc
*rdp
= dev
->si_drv1
;
497 int blkno
, count
, chunk
, lba
, lbs
, tmplba
;
500 int drv
= 0, change
= 0;
503 if (!(rdp
->flags
& AR_F_READY
)) {
504 bp
->b_flags
|= B_ERROR
;
510 KKASSERT((bio
->bio_offset
& DEV_BMASK
) == 0);
512 bp
->b_resid
= bp
->b_bcount
;
513 blkno
= (int)(bio
->bio_offset
>> DEV_BSHIFT
);
517 for (count
= howmany(bp
->b_bcount
, DEV_BSIZE
); count
> 0;
518 count
-= chunk
, blkno
+= chunk
, data
+= (chunk
* DEV_BSIZE
)) {
519 struct ar_buf
*buf1
, *buf2
;
521 switch (rdp
->flags
& (AR_F_RAID0
| AR_F_RAID1
| AR_F_SPAN
)) {
524 while (lba
>= AD_SOFTC(rdp
->disks
[drv
])->total_secs
-rdp
->reserved
)
525 lba
-= AD_SOFTC(rdp
->disks
[drv
++])->total_secs
-rdp
->reserved
;
526 chunk
= min(AD_SOFTC(rdp
->disks
[drv
])->total_secs
-rdp
->reserved
-lba
,
531 case AR_F_RAID0
| AR_F_RAID1
:
532 tmplba
= blkno
/ rdp
->interleave
;
533 chunk
= blkno
% rdp
->interleave
;
534 if (tmplba
== rdp
->total_sectors
/ rdp
->interleave
) {
535 lbs
= (rdp
->total_sectors
-(tmplba
*rdp
->interleave
))/rdp
->width
;
537 lba
= ((tmplba
/rdp
->width
)*rdp
->interleave
) + chunk
%lbs
;
538 chunk
= min(count
, lbs
);
541 drv
= tmplba
% rdp
->width
;
542 lba
= ((tmplba
/ rdp
->width
) * rdp
->interleave
) + chunk
;
543 chunk
= min(count
, rdp
->interleave
- chunk
);
554 kprintf("ar%d: unknown array type in arstrategy\n", rdp
->lun
);
555 bp
->b_flags
|= B_ERROR
;
561 buf1
= kmalloc(sizeof(struct ar_buf
), M_AR
, M_INTWAIT
| M_ZERO
);
562 BUF_LOCKINIT(&buf1
->bp
);
563 BUF_LOCK(&buf1
->bp
, LK_EXCLUSIVE
);
564 initbufbio(&buf1
->bp
);
565 buf1
->bp
.b_bio1
.bio_offset
= (off_t
)lba
<< DEV_BSHIFT
;
566 if ((buf1
->drive
= drv
) > 0)
567 buf1
->bp
.b_bio1
.bio_offset
+= (off_t
)rdp
->offset
<< DEV_BSHIFT
;
568 buf1
->bp
.b_bio1
.bio_caller_info1
.ptr
= (void *)rdp
;
569 buf1
->bp
.b_bcount
= chunk
* DEV_BSIZE
;
570 buf1
->bp
.b_data
= data
;
571 buf1
->bp
.b_flags
= bp
->b_flags
| B_PAGING
;
572 buf1
->bp
.b_cmd
= bp
->b_cmd
;
573 buf1
->bp
.b_bio1
.bio_done
= ar_done
;
575 buf1_blkno
= (int)(buf1
->bp
.b_bio1
.bio_offset
>> DEV_BSHIFT
);
577 switch (rdp
->flags
& (AR_F_RAID0
| AR_F_RAID1
| AR_F_SPAN
)) {
580 if ((rdp
->disks
[buf1
->drive
].flags
&
581 (AR_DF_PRESENT
|AR_DF_ONLINE
))==(AR_DF_PRESENT
|AR_DF_ONLINE
) &&
582 !AD_SOFTC(rdp
->disks
[buf1
->drive
])->dev
) {
583 rdp
->disks
[buf1
->drive
].flags
&= ~AR_DF_ONLINE
;
584 ar_config_changed(rdp
, 1);
586 bp
->b_flags
|= B_ERROR
;
591 dev_dstrategy(AD_SOFTC(rdp
->disks
[buf1
->drive
])->dev
,
596 case AR_F_RAID0
| AR_F_RAID1
:
597 if ((rdp
->flags
& AR_F_REBUILDING
) && bp
->b_cmd
!= BUF_CMD_READ
) {
598 if ((orig_blkno
>= rdp
->lock_start
&&
599 orig_blkno
< rdp
->lock_end
) ||
600 ((orig_blkno
+ chunk
) > rdp
->lock_start
&&
601 (orig_blkno
+ chunk
) <= rdp
->lock_end
)) {
602 tsleep(rdp
, 0, "arwait", 0);
605 if ((rdp
->disks
[buf1
->drive
].flags
&
606 (AR_DF_PRESENT
|AR_DF_ONLINE
))==(AR_DF_PRESENT
|AR_DF_ONLINE
) &&
607 !AD_SOFTC(rdp
->disks
[buf1
->drive
])->dev
) {
608 rdp
->disks
[buf1
->drive
].flags
&= ~AR_DF_ONLINE
;
611 if ((rdp
->disks
[buf1
->drive
+ rdp
->width
].flags
&
612 (AR_DF_PRESENT
|AR_DF_ONLINE
))==(AR_DF_PRESENT
|AR_DF_ONLINE
) &&
613 !AD_SOFTC(rdp
->disks
[buf1
->drive
+ rdp
->width
])->dev
) {
614 rdp
->disks
[buf1
->drive
+ rdp
->width
].flags
&= ~AR_DF_ONLINE
;
618 ar_config_changed(rdp
, 1);
620 if (!(rdp
->flags
& AR_F_READY
)) {
622 bp
->b_flags
|= B_ERROR
;
627 if (bp
->b_cmd
== BUF_CMD_READ
) {
629 (rdp
->disks
[buf1
->drive
].last_lba
- AR_PROXIMITY
) ||
631 (rdp
->disks
[buf1
->drive
].last_lba
+ AR_PROXIMITY
) ||
632 !(rdp
->disks
[buf1
->drive
].flags
& AR_DF_ONLINE
)) &&
633 (rdp
->disks
[buf1
->drive
+rdp
->width
].flags
& AR_DF_ONLINE
))
634 buf1
->drive
= buf1
->drive
+ rdp
->width
;
636 if ((rdp
->disks
[buf1
->drive
+rdp
->width
].flags
& AR_DF_ONLINE
) ||
637 ((rdp
->flags
& AR_F_REBUILDING
) &&
638 (rdp
->disks
[buf1
->drive
+rdp
->width
].flags
& AR_DF_SPARE
) &&
639 buf1_blkno
< rdp
->lock_start
)) {
640 if ((rdp
->disks
[buf1
->drive
].flags
& AR_DF_ONLINE
) ||
641 ((rdp
->flags
& AR_F_REBUILDING
) &&
642 (rdp
->disks
[buf1
->drive
].flags
& AR_DF_SPARE
) &&
643 buf1_blkno
< rdp
->lock_start
)) {
644 buf2
= kmalloc(sizeof(struct ar_buf
), M_AR
, M_INTWAIT
);
645 bcopy(buf1
, buf2
, sizeof(struct ar_buf
));
646 BUF_LOCKINIT(&buf2
->bp
);
647 BUF_LOCK(&buf2
->bp
, LK_EXCLUSIVE
);
648 initbufbio(&buf2
->bp
);
649 buf2
->bp
.b_bio1
.bio_offset
= buf1
->bp
.b_bio1
.bio_offset
;
652 buf2
->drive
= buf1
->drive
+ rdp
->width
;
653 dev_dstrategy(AD_SOFTC(rdp
->disks
[buf2
->drive
])->dev
,
655 rdp
->disks
[buf2
->drive
].last_lba
= buf1_blkno
+ chunk
;
658 buf1
->drive
= buf1
->drive
+ rdp
->width
;
661 dev_dstrategy(AD_SOFTC(rdp
->disks
[buf1
->drive
])->dev
,
663 rdp
->disks
[buf1
->drive
].last_lba
= buf1_blkno
+ chunk
;
667 kprintf("ar%d: unknown array type in arstrategy\n", rdp
->lun
);
674 ar_done(struct bio
*bio
)
676 struct ar_softc
*rdp
= (struct ar_softc
*)bio
->bio_caller_info1
.ptr
;
677 struct ar_buf
*buf
= (struct ar_buf
*)bio
->bio_buf
;
679 switch (rdp
->flags
& (AR_F_RAID0
| AR_F_RAID1
| AR_F_SPAN
)) {
682 if (buf
->bp
.b_flags
& B_ERROR
) {
683 rdp
->disks
[buf
->drive
].flags
&= ~AR_DF_ONLINE
;
684 ar_config_changed(rdp
, 1);
685 buf
->org
->bio_buf
->b_flags
|= B_ERROR
;
686 buf
->org
->bio_buf
->b_error
= EIO
;
690 buf
->org
->bio_buf
->b_resid
-= buf
->bp
.b_bcount
;
691 if (buf
->org
->bio_buf
->b_resid
== 0)
697 case AR_F_RAID0
| AR_F_RAID1
:
698 if (buf
->bp
.b_flags
& B_ERROR
) {
699 rdp
->disks
[buf
->drive
].flags
&= ~AR_DF_ONLINE
;
700 ar_config_changed(rdp
, 1);
701 if (rdp
->flags
& AR_F_READY
) {
702 if (buf
->bp
.b_cmd
== BUF_CMD_READ
) {
703 if (buf
->drive
< rdp
->width
)
704 buf
->drive
= buf
->drive
+ rdp
->width
;
706 buf
->drive
= buf
->drive
- rdp
->width
;
707 buf
->bp
.b_flags
= buf
->org
->bio_buf
->b_flags
| B_PAGING
;
709 dev_dstrategy(AD_SOFTC(rdp
->disks
[buf
->drive
])->dev
,
714 if (buf
->flags
& AB_F_DONE
) {
715 buf
->org
->bio_buf
->b_resid
-= buf
->bp
.b_bcount
;
716 if (buf
->org
->bio_buf
->b_resid
== 0)
720 buf
->mirror
->flags
|= AB_F_DONE
;
724 buf
->org
->bio_buf
->b_flags
|= B_ERROR
;
725 buf
->org
->bio_buf
->b_error
= EIO
;
730 if (buf
->bp
.b_cmd
!= BUF_CMD_READ
) {
731 if (buf
->mirror
&& !(buf
->flags
& AB_F_DONE
)){
732 buf
->mirror
->flags
|= AB_F_DONE
;
736 buf
->org
->bio_buf
->b_resid
-= buf
->bp
.b_bcount
;
737 if (buf
->org
->bio_buf
->b_resid
== 0)
743 kprintf("ar%d: unknown array type in ar_done\n", rdp
->lun
);
749 ar_config_changed(struct ar_softc
*rdp
, int writeback
)
754 rdp
->flags
|= AR_F_READY
;
755 rdp
->flags
&= ~AR_F_DEGRADED
;
757 for (disk
= 0; disk
< rdp
->total_disks
; disk
++)
758 if (!(rdp
->disks
[disk
].flags
& AR_DF_PRESENT
))
759 rdp
->disks
[disk
].flags
&= ~AR_DF_ONLINE
;
761 for (disk
= 0; disk
< rdp
->total_disks
; disk
++) {
762 switch (rdp
->flags
& (AR_F_RAID0
| AR_F_RAID1
| AR_F_SPAN
)) {
765 if (!(rdp
->disks
[disk
].flags
& AR_DF_ONLINE
)) {
766 rdp
->flags
&= ~AR_F_READY
;
767 kprintf("ar%d: ERROR - array broken\n", rdp
->lun
);
772 case AR_F_RAID0
| AR_F_RAID1
:
773 if (disk
< rdp
->width
) {
774 if (!(rdp
->disks
[disk
].flags
& AR_DF_ONLINE
) &&
775 !(rdp
->disks
[disk
+ rdp
->width
].flags
& AR_DF_ONLINE
)) {
776 rdp
->flags
&= ~AR_F_READY
;
777 kprintf("ar%d: ERROR - array broken\n", rdp
->lun
);
779 else if (((rdp
->disks
[disk
].flags
& AR_DF_ONLINE
) &&
781 [disk
+ rdp
->width
].flags
& AR_DF_ONLINE
))||
782 (!(rdp
->disks
[disk
].flags
& AR_DF_ONLINE
) &&
784 [disk
+ rdp
->width
].flags
& AR_DF_ONLINE
))) {
785 rdp
->flags
|= AR_F_DEGRADED
;
786 if (!(flags
& AR_F_DEGRADED
))
787 kprintf("ar%d: WARNING - mirror lost\n", rdp
->lun
);
792 if ((rdp
->disks
[disk
].flags
&AR_DF_PRESENT
) && rdp
->disks
[disk
].device
) {
793 if (rdp
->disks
[disk
].flags
& AR_DF_ONLINE
)
794 ata_enclosure_leds(rdp
->disks
[disk
].device
, ATA_LED_GREEN
);
796 ata_enclosure_leds(rdp
->disks
[disk
].device
, ATA_LED_RED
);
800 if (rdp
->flags
& AR_F_PROMISE_RAID
)
801 ar_promise_write_conf(rdp
);
802 if (rdp
->flags
& AR_F_HIGHPOINT_RAID
)
803 ar_highpoint_write_conf(rdp
);
808 ar_rebuild(struct ar_softc
*rdp
)
810 int disk
, count
= 0, error
= 0;
813 if ((rdp
->flags
& (AR_F_READY
|AR_F_DEGRADED
)) != (AR_F_READY
|AR_F_DEGRADED
))
816 for (disk
= 0; disk
< rdp
->total_disks
; disk
++) {
817 if (((rdp
->disks
[disk
].flags
&(AR_DF_PRESENT
|AR_DF_ONLINE
|AR_DF_SPARE
))==
818 (AR_DF_PRESENT
| AR_DF_SPARE
)) && rdp
->disks
[disk
].device
) {
819 if (AD_SOFTC(rdp
->disks
[disk
])->total_secs
<
820 rdp
->disks
[disk
].disk_sectors
) {
821 ata_prtdev(rdp
->disks
[disk
].device
,
822 "disk capacity too small for this RAID config\n");
824 rdp
->disks
[disk
].flags
&= ~AR_DF_SPARE
;
825 AD_SOFTC(rdp
->disks
[disk
])->flags
&= ~AD_F_RAID_SUBDISK
;
829 ata_enclosure_leds(rdp
->disks
[disk
].device
, ATA_LED_ORANGE
);
836 /* setup start conditions */
839 rdp
->lock_end
= rdp
->lock_start
+ 256;
840 rdp
->flags
|= AR_F_REBUILDING
;
842 buffer
= kmalloc(256 * DEV_BSIZE
, M_AR
, M_WAITOK
| M_ZERO
);
844 /* now go copy entire disk(s) */
845 while (rdp
->lock_end
< (rdp
->total_sectors
/ rdp
->width
)) {
846 int size
= min(256, (rdp
->total_sectors
/ rdp
->width
) - rdp
->lock_end
);
848 for (disk
= 0; disk
< rdp
->width
; disk
++) {
849 struct ad_softc
*adp
;
851 if (((rdp
->disks
[disk
].flags
& AR_DF_ONLINE
) &&
852 (rdp
->disks
[disk
+ rdp
->width
].flags
& AR_DF_ONLINE
)) ||
853 ((rdp
->disks
[disk
].flags
& AR_DF_ONLINE
) &&
854 !(rdp
->disks
[disk
+ rdp
->width
].flags
& AR_DF_SPARE
)) ||
855 ((rdp
->disks
[disk
+ rdp
->width
].flags
& AR_DF_ONLINE
) &&
856 !(rdp
->disks
[disk
].flags
& AR_DF_SPARE
)))
859 if (rdp
->disks
[disk
].flags
& AR_DF_ONLINE
)
860 adp
= AD_SOFTC(rdp
->disks
[disk
]);
862 adp
= AD_SOFTC(rdp
->disks
[disk
+ rdp
->width
]);
863 if ((error
= ar_rw(adp
, rdp
->lock_start
,
864 size
* DEV_BSIZE
, buffer
, AR_READ
| AR_WAIT
)))
867 if (rdp
->disks
[disk
].flags
& AR_DF_ONLINE
)
868 adp
= AD_SOFTC(rdp
->disks
[disk
+ rdp
->width
]);
870 adp
= AD_SOFTC(rdp
->disks
[disk
]);
871 if ((error
= ar_rw(adp
, rdp
->lock_start
,
872 size
* DEV_BSIZE
, buffer
, AR_WRITE
| AR_WAIT
)))
881 rdp
->lock_start
= rdp
->lock_end
;
882 rdp
->lock_end
= rdp
->lock_start
+ size
;
887 for (disk
= 0; disk
< rdp
->total_disks
; disk
++) {
888 if ((rdp
->disks
[disk
].flags
&(AR_DF_PRESENT
|AR_DF_ONLINE
|AR_DF_SPARE
))==
889 (AR_DF_PRESENT
| AR_DF_SPARE
)) {
890 rdp
->disks
[disk
].flags
&= ~AR_DF_SPARE
;
891 rdp
->disks
[disk
].flags
|= (AR_DF_ASSIGNED
| AR_DF_ONLINE
);
895 rdp
->lock_start
= 0xffffffff;
896 rdp
->lock_end
= 0xffffffff;
897 rdp
->flags
&= ~AR_F_REBUILDING
;
899 ar_config_changed(rdp
, 1);
904 ar_highpoint_read_conf(struct ad_softc
*adp
, struct ar_softc
**raidp
)
906 struct highpoint_raid_conf
*info
;
907 struct ar_softc
*raid
= NULL
;
908 int array
, disk_number
= 0, retval
= 0;
910 info
= kmalloc(sizeof(struct highpoint_raid_conf
), M_AR
, M_INTWAIT
|M_ZERO
);
912 if (ar_rw(adp
, HPT_LBA
, sizeof(struct highpoint_raid_conf
),
913 (caddr_t
)info
, AR_READ
| AR_WAIT
)) {
915 kprintf("ar: HighPoint read conf failed\n");
919 /* check if this is a HighPoint RAID struct */
920 if (info
->magic
!= HPT_MAGIC_OK
&& info
->magic
!= HPT_MAGIC_BAD
) {
922 kprintf("ar: HighPoint check1 failed\n");
926 /* is this disk defined, or an old leftover/spare ? */
927 if (!info
->magic_0
) {
929 kprintf("ar: HighPoint check2 failed\n");
933 /* now convert HighPoint config info into our generic form */
934 for (array
= 0; array
< MAX_ARRAYS
; array
++) {
936 raidp
[array
] = kmalloc(sizeof(struct ar_softc
), M_AR
,
940 if (raid
->flags
& AR_F_PROMISE_RAID
)
943 switch (info
->type
) {
945 if ((info
->order
& (HPT_O_RAID0
|HPT_O_OK
))==(HPT_O_RAID0
|HPT_O_OK
))
946 goto highpoint_raid1
;
947 if (info
->order
& (HPT_O_RAID0
| HPT_O_RAID1
))
948 goto highpoint_raid01
;
949 if (raid
->magic_0
&& raid
->magic_0
!= info
->magic_0
)
951 raid
->magic_0
= info
->magic_0
;
952 raid
->flags
|= AR_F_RAID0
;
953 raid
->interleave
= 1 << info
->stripe_shift
;
954 disk_number
= info
->disk_number
;
955 if (!(info
->order
& HPT_O_OK
))
956 info
->magic
= 0; /* mark bad */
961 if (raid
->magic_0
&& raid
->magic_0
!= info
->magic_0
)
963 raid
->magic_0
= info
->magic_0
;
964 raid
->flags
|= AR_F_RAID1
;
965 disk_number
= (info
->disk_number
> 0);
968 case HPT_T_RAID01_RAID0
:
970 if (info
->order
& HPT_O_RAID0
) {
971 if ((raid
->magic_0
&& raid
->magic_0
!= info
->magic_0
) ||
972 (raid
->magic_1
&& raid
->magic_1
!= info
->magic_1
))
974 raid
->magic_0
= info
->magic_0
;
975 raid
->magic_1
= info
->magic_1
;
976 raid
->flags
|= (AR_F_RAID0
| AR_F_RAID1
);
977 raid
->interleave
= 1 << info
->stripe_shift
;
978 disk_number
= info
->disk_number
;
981 if (raid
->magic_1
&& raid
->magic_1
!= info
->magic_1
)
983 raid
->magic_1
= info
->magic_1
;
984 raid
->flags
|= (AR_F_RAID0
| AR_F_RAID1
);
985 raid
->interleave
= 1 << info
->stripe_shift
;
986 disk_number
= info
->disk_number
+ info
->array_width
;
987 if (!(info
->order
& HPT_O_RAID1
))
988 info
->magic
= 0; /* mark bad */
993 if (raid
->magic_0
&& raid
->magic_0
!= info
->magic_0
)
995 raid
->magic_0
= info
->magic_0
;
996 raid
->flags
|= AR_F_SPAN
;
997 disk_number
= info
->disk_number
;
1001 kprintf("ar%d: HighPoint unknown RAID type 0x%02x\n",
1006 raid
->flags
|= AR_F_HIGHPOINT_RAID
;
1007 raid
->disks
[disk_number
].device
= adp
->device
;
1008 raid
->disks
[disk_number
].flags
= (AR_DF_PRESENT
| AR_DF_ASSIGNED
);
1010 if (info
->magic
== HPT_MAGIC_OK
) {
1011 raid
->disks
[disk_number
].flags
|= AR_DF_ONLINE
;
1012 raid
->flags
|= AR_F_READY
;
1013 raid
->width
= info
->array_width
;
1016 raid
->cylinders
= info
->total_sectors
/ (63 * 255);
1017 raid
->total_sectors
= info
->total_sectors
;
1018 raid
->offset
= HPT_LBA
+ 1;
1019 raid
->reserved
= HPT_LBA
+ 1;
1020 raid
->lock_start
= raid
->lock_end
= info
->rebuild_lba
;
1021 raid
->disks
[disk_number
].disk_sectors
=
1022 info
->total_sectors
/ info
->array_width
;
1025 raid
->disks
[disk_number
].flags
&= ~ AR_DF_ONLINE
;
1027 if ((raid
->flags
& AR_F_RAID0
) && (raid
->total_disks
< raid
->width
))
1028 raid
->total_disks
= raid
->width
;
1029 if (disk_number
>= raid
->total_disks
)
1030 raid
->total_disks
= disk_number
+ 1;
1040 ar_highpoint_write_conf(struct ar_softc
*rdp
)
1042 struct highpoint_raid_conf
*config
;
1043 struct timeval timestamp
;
1046 microtime(×tamp
);
1047 rdp
->magic_0
= timestamp
.tv_sec
+ 2;
1048 rdp
->magic_1
= timestamp
.tv_sec
;
1050 for (disk
= 0; disk
< rdp
->total_disks
; disk
++) {
1051 config
= kmalloc(sizeof(struct highpoint_raid_conf
),
1052 M_AR
, M_INTWAIT
| M_ZERO
);
1053 if ((rdp
->disks
[disk
].flags
& (AR_DF_PRESENT
| AR_DF_ONLINE
)) ==
1054 (AR_DF_PRESENT
| AR_DF_ONLINE
))
1055 config
->magic
= HPT_MAGIC_OK
;
1056 if (rdp
->disks
[disk
].flags
& AR_DF_ASSIGNED
) {
1057 config
->magic_0
= rdp
->magic_0
;
1058 strcpy(config
->name_1
, "FreeBSD");
1060 config
->disk_number
= disk
;
1062 switch (rdp
->flags
& (AR_F_RAID0
| AR_F_RAID1
| AR_F_SPAN
)) {
1064 config
->type
= HPT_T_RAID0
;
1065 strcpy(config
->name_2
, "RAID 0");
1066 if (rdp
->disks
[disk
].flags
& AR_DF_ONLINE
)
1067 config
->order
= HPT_O_OK
;
1071 config
->type
= HPT_T_RAID0
; /* bogus but old HPT BIOS need it */
1072 strcpy(config
->name_2
, "RAID 1");
1073 config
->disk_number
= (disk
< rdp
->width
) ? disk
: disk
+ 5;
1074 config
->order
= HPT_O_RAID0
| HPT_O_OK
;
1077 case AR_F_RAID0
| AR_F_RAID1
:
1078 config
->type
= HPT_T_RAID01_RAID0
;
1079 strcpy(config
->name_2
, "RAID 0+1");
1080 if (rdp
->disks
[disk
].flags
& AR_DF_ONLINE
) {
1081 if (disk
< rdp
->width
) {
1082 config
->order
= (HPT_O_RAID0
| HPT_O_RAID1
);
1083 config
->magic_0
= rdp
->magic_0
- 1;
1086 config
->order
= HPT_O_RAID1
;
1087 config
->disk_number
-= rdp
->width
;
1091 config
->magic_0
= rdp
->magic_0
- 1;
1092 config
->magic_1
= rdp
->magic_1
;
1096 config
->type
= HPT_T_SPAN
;
1097 strcpy(config
->name_2
, "SPAN");
1101 config
->array_width
= rdp
->width
;
1102 config
->stripe_shift
= (rdp
->width
> 1) ? (ffs(rdp
->interleave
)-1) : 0;
1103 config
->total_sectors
= rdp
->total_sectors
;
1104 config
->rebuild_lba
= rdp
->lock_start
;
1106 if ((rdp
->disks
[disk
].device
&& rdp
->disks
[disk
].device
->driver
) &&
1107 !(rdp
->disks
[disk
].device
->flags
& ATA_D_DETACHING
)) {
1109 if (ar_rw(AD_SOFTC(rdp
->disks
[disk
]), HPT_LBA
,
1110 sizeof(struct highpoint_raid_conf
),
1111 (caddr_t
)config
, AR_WRITE
)) {
1112 kprintf("ar%d: Highpoint write conf failed\n", rdp
->lun
);
1121 ar_promise_read_conf(struct ad_softc
*adp
, struct ar_softc
**raidp
, int local
)
1123 struct promise_raid_conf
*info
;
1124 struct ar_softc
*raid
;
1125 u_int32_t magic
, cksum
, *ckptr
;
1126 int array
, count
, disk
, disksum
= 0, retval
= 0;
1128 info
= kmalloc(sizeof(struct promise_raid_conf
), M_AR
, M_INTWAIT
| M_ZERO
);
1130 if (ar_rw(adp
, PR_LBA(adp
), sizeof(struct promise_raid_conf
),
1131 (caddr_t
)info
, AR_READ
| AR_WAIT
)) {
1133 kprintf("ar: %s read conf failed\n", local
? "FreeBSD" : "Promise");
1137 /* check if this is a Promise RAID struct (or our local one) */
1139 if (strncmp(info
->promise_id
, ATA_MAGIC
, sizeof(ATA_MAGIC
))) {
1141 kprintf("ar: FreeBSD check1 failed\n");
1146 if (strncmp(info
->promise_id
, PR_MAGIC
, sizeof(PR_MAGIC
))) {
1148 kprintf("ar: Promise check1 failed\n");
1153 /* check if the checksum is OK */
1154 for (cksum
= 0, ckptr
= (int32_t *)info
, count
= 0; count
< 511; count
++)
1156 if (cksum
!= *ckptr
) {
1158 kprintf("ar: %s check2 failed\n", local
? "FreeBSD" : "Promise");
1162 /* now convert Promise config info into our generic form */
1163 if (info
->raid
.integrity
!= PR_I_VALID
) {
1165 kprintf("ar: %s check3 failed\n", local
? "FreeBSD" : "Promise");
1169 for (array
= 0; array
< MAX_ARRAYS
; array
++) {
1170 if (!raidp
[array
]) {
1171 raidp
[array
] = kmalloc(sizeof(struct ar_softc
), M_AR
,
1172 M_INTWAIT
| M_ZERO
);
1174 raid
= raidp
[array
];
1175 if (raid
->flags
& AR_F_HIGHPOINT_RAID
)
1178 magic
= (adp
->device
->channel
->chiptype
>> 16) |
1179 (info
->raid
.array_number
<< 16);
1181 if ((raid
->flags
& AR_F_PROMISE_RAID
) && magic
!= raid
->magic_0
)
1184 /* update our knowledge about the array config based on generation */
1185 if (!info
->raid
.generation
|| info
->raid
.generation
> raid
->generation
){
1186 raid
->generation
= info
->raid
.generation
;
1187 raid
->flags
= AR_F_PROMISE_RAID
;
1189 raid
->flags
|= AR_F_FREEBSD_RAID
;
1190 raid
->magic_0
= magic
;
1192 if ((info
->raid
.status
&
1193 (PR_S_VALID
| PR_S_ONLINE
| PR_S_INITED
| PR_S_READY
)) ==
1194 (PR_S_VALID
| PR_S_ONLINE
| PR_S_INITED
| PR_S_READY
)) {
1195 raid
->flags
|= AR_F_READY
;
1196 if (info
->raid
.status
& PR_S_DEGRADED
)
1197 raid
->flags
|= AR_F_DEGRADED
;
1200 raid
->flags
&= ~AR_F_READY
;
1202 switch (info
->raid
.type
) {
1204 raid
->flags
|= AR_F_RAID0
;
1208 raid
->flags
|= AR_F_RAID1
;
1209 if (info
->raid
.array_width
> 1)
1210 raid
->flags
|= AR_F_RAID0
;
1214 raid
->flags
|= AR_F_SPAN
;
1218 kprintf("ar%d: %s unknown RAID type 0x%02x\n",
1219 array
, local
? "FreeBSD" : "Promise", info
->raid
.type
);
1222 raid
->interleave
= 1 << info
->raid
.stripe_shift
;
1223 raid
->width
= info
->raid
.array_width
;
1224 raid
->total_disks
= info
->raid
.total_disks
;
1225 raid
->heads
= info
->raid
.heads
+ 1;
1226 raid
->sectors
= info
->raid
.sectors
;
1227 raid
->cylinders
= info
->raid
.cylinders
+ 1;
1228 raid
->total_sectors
= info
->raid
.total_sectors
;
1230 raid
->reserved
= 63;
1231 raid
->lock_start
= raid
->lock_end
= info
->raid
.rebuild_lba
;
1233 /* convert disk flags to our internal types */
1234 for (disk
= 0; disk
< info
->raid
.total_disks
; disk
++) {
1235 raid
->disks
[disk
].flags
= 0;
1236 disksum
+= info
->raid
.disk
[disk
].flags
;
1237 if (info
->raid
.disk
[disk
].flags
& PR_F_ONLINE
)
1238 raid
->disks
[disk
].flags
|= AR_DF_ONLINE
;
1239 if (info
->raid
.disk
[disk
].flags
& PR_F_ASSIGNED
)
1240 raid
->disks
[disk
].flags
|= AR_DF_ASSIGNED
;
1241 if (info
->raid
.disk
[disk
].flags
& PR_F_SPARE
) {
1242 raid
->disks
[disk
].flags
&= ~AR_DF_ONLINE
;
1243 raid
->disks
[disk
].flags
|= AR_DF_SPARE
;
1245 if (info
->raid
.disk
[disk
].flags
& (PR_F_REDIR
| PR_F_DOWN
))
1246 raid
->disks
[disk
].flags
&= ~AR_DF_ONLINE
;
1249 kfree(raidp
[array
], M_AR
);
1250 raidp
[array
] = NULL
;
1254 if (raid
->disks
[info
->raid
.disk_number
].flags
&& adp
->device
) {
1255 raid
->disks
[info
->raid
.disk_number
].device
= adp
->device
;
1256 raid
->disks
[info
->raid
.disk_number
].flags
|= AR_DF_PRESENT
;
1257 raid
->disks
[info
->raid
.disk_number
].disk_sectors
=
1258 info
->raid
.total_sectors
/ info
->raid
.array_width
;
1259 /*info->raid.disk_sectors;*/
1270 ar_promise_write_conf(struct ar_softc
*rdp
)
1272 struct promise_raid_conf
*config
;
1273 struct timeval timestamp
;
1275 int count
, disk
, drive
;
1276 int local
= rdp
->flags
& AR_F_FREEBSD_RAID
;
1279 microtime(×tamp
);
1281 for (disk
= 0; disk
< rdp
->total_disks
; disk
++) {
1282 config
= kmalloc(sizeof(struct promise_raid_conf
), M_AR
, M_INTWAIT
);
1283 for (count
= 0; count
< sizeof(struct promise_raid_conf
); count
++)
1284 *(((u_int8_t
*)config
) + count
) = 255 - (count
% 256);
1287 bcopy(ATA_MAGIC
, config
->promise_id
, sizeof(ATA_MAGIC
));
1289 bcopy(PR_MAGIC
, config
->promise_id
, sizeof(PR_MAGIC
));
1290 config
->dummy_0
= 0x00020000;
1291 config
->magic_0
= PR_MAGIC0(rdp
->disks
[disk
]) | timestamp
.tv_sec
;
1292 config
->magic_1
= timestamp
.tv_sec
>> 16;
1293 config
->magic_2
= timestamp
.tv_sec
;
1294 config
->raid
.integrity
= PR_I_VALID
;
1296 config
->raid
.disk_number
= disk
;
1297 if ((rdp
->disks
[disk
].flags
&AR_DF_PRESENT
) && rdp
->disks
[disk
].device
) {
1298 config
->raid
.channel
= rdp
->disks
[disk
].device
->channel
->unit
;
1299 config
->raid
.device
= (rdp
->disks
[disk
].device
->unit
!= 0);
1300 if (AD_SOFTC(rdp
->disks
[disk
])->dev
)
1301 config
->raid
.disk_sectors
= PR_LBA(AD_SOFTC(rdp
->disks
[disk
]));
1302 /*config->raid.disk_offset*/
1304 config
->raid
.magic_0
= config
->magic_0
;
1305 config
->raid
.rebuild_lba
= rdp
->lock_start
;
1306 config
->raid
.generation
= rdp
->generation
;
1308 if (rdp
->flags
& AR_F_READY
) {
1309 config
->raid
.flags
= (PR_F_VALID
| PR_F_ASSIGNED
| PR_F_ONLINE
);
1310 config
->raid
.status
=
1311 (PR_S_VALID
| PR_S_ONLINE
| PR_S_INITED
| PR_S_READY
);
1312 if (rdp
->flags
& AR_F_DEGRADED
)
1313 config
->raid
.status
|= PR_S_DEGRADED
;
1315 config
->raid
.status
|= PR_S_FUNCTIONAL
;
1318 config
->raid
.status
= 0;
1319 config
->raid
.flags
= PR_F_DOWN
;
1322 switch (rdp
->flags
& (AR_F_RAID0
| AR_F_RAID1
| AR_F_SPAN
)) {
1324 config
->raid
.type
= PR_T_RAID0
;
1327 config
->raid
.type
= PR_T_RAID1
;
1329 case AR_F_RAID0
| AR_F_RAID1
:
1330 config
->raid
.type
= PR_T_RAID1
;
1333 config
->raid
.type
= PR_T_SPAN
;
1337 config
->raid
.total_disks
= rdp
->total_disks
;
1338 config
->raid
.stripe_shift
= ffs(rdp
->interleave
) - 1;
1339 config
->raid
.array_width
= rdp
->width
;
1340 config
->raid
.array_number
= rdp
->lun
;
1341 config
->raid
.total_sectors
= rdp
->total_sectors
;
1342 config
->raid
.cylinders
= rdp
->cylinders
- 1;
1343 config
->raid
.heads
= rdp
->heads
- 1;
1344 config
->raid
.sectors
= rdp
->sectors
;
1345 config
->raid
.magic_1
= (u_int64_t
)config
->magic_2
<<16 | config
->magic_1
;
1347 bzero(&config
->raid
.disk
, 8 * 12);
1348 for (drive
= 0; drive
< rdp
->total_disks
; drive
++) {
1349 config
->raid
.disk
[drive
].flags
= 0;
1350 if (rdp
->disks
[drive
].flags
& AR_DF_PRESENT
)
1351 config
->raid
.disk
[drive
].flags
|= PR_F_VALID
;
1352 if (rdp
->disks
[drive
].flags
& AR_DF_ASSIGNED
)
1353 config
->raid
.disk
[drive
].flags
|= PR_F_ASSIGNED
;
1354 if (rdp
->disks
[drive
].flags
& AR_DF_ONLINE
)
1355 config
->raid
.disk
[drive
].flags
|= PR_F_ONLINE
;
1357 if (rdp
->disks
[drive
].flags
& AR_DF_PRESENT
)
1358 config
->raid
.disk
[drive
].flags
= (PR_F_REDIR
| PR_F_DOWN
);
1359 if (rdp
->disks
[drive
].flags
& AR_DF_SPARE
)
1360 config
->raid
.disk
[drive
].flags
|= PR_F_SPARE
;
1361 config
->raid
.disk
[drive
].dummy_0
= 0x0;
1362 if (rdp
->disks
[drive
].device
) {
1363 config
->raid
.disk
[drive
].channel
=
1364 rdp
->disks
[drive
].device
->channel
->unit
;
1365 config
->raid
.disk
[drive
].device
=
1366 (rdp
->disks
[drive
].device
->unit
!= 0);
1368 config
->raid
.disk
[drive
].magic_0
=
1369 PR_MAGIC0(rdp
->disks
[drive
]) | timestamp
.tv_sec
;
1372 config
->checksum
= 0;
1373 for (ckptr
= (int32_t *)config
, count
= 0; count
< 511; count
++)
1374 config
->checksum
+= *ckptr
++;
1375 if (rdp
->disks
[disk
].device
&& rdp
->disks
[disk
].device
->driver
&&
1376 !(rdp
->disks
[disk
].device
->flags
& ATA_D_DETACHING
)) {
1377 if (ar_rw(AD_SOFTC(rdp
->disks
[disk
]),
1378 PR_LBA(AD_SOFTC(rdp
->disks
[disk
])),
1379 sizeof(struct promise_raid_conf
),
1380 (caddr_t
)config
, AR_WRITE
)) {
1381 kprintf("ar%d: %s write conf failed\n",
1382 rdp
->lun
, local
? "FreeBSD" : "Promise");
1391 ar_rw_done(struct bio
*bio
)
1393 struct buf
*bp
= bio
->bio_buf
;
1395 kfree(bp
->b_data
, M_AR
);
1400 ar_rw(struct ad_softc
*adp
, u_int32_t lba
, int count
, caddr_t data
, int flags
)
1403 int retry
= 0, error
= 0;
1405 bp
= kmalloc(sizeof(struct buf
), M_AR
, M_INTWAIT
|M_ZERO
);
1407 BUF_LOCK(bp
, LK_EXCLUSIVE
);
1410 bp
->b_bio1
.bio_offset
= (off_t
)lba
<< DEV_BSHIFT
;
1411 bp
->b_bcount
= count
;
1412 if (flags
& AR_WAIT
) {
1413 bp
->b_bio1
.bio_flags
|= BIO_SYNC
;
1414 bp
->b_bio1
.bio_done
= biodone_sync
;
1416 bp
->b_bio1
.bio_done
= ar_rw_done
;
1418 if (flags
& AR_READ
)
1419 bp
->b_cmd
= BUF_CMD_READ
;
1420 if (flags
& AR_WRITE
)
1421 bp
->b_cmd
= BUF_CMD_WRITE
;
1422 KKASSERT(bp
->b_cmd
!= BUF_CMD_DONE
);
1424 dev_dstrategy(adp
->dev
, &bp
->b_bio1
);
1426 if (flags
& AR_WAIT
) {
1427 while (retry
++ < (15*hz
/10))
1428 error
= biowait_timeout(&bp
->b_bio1
, "arrw", 10);
1429 if (!error
&& (bp
->b_flags
& B_ERROR
))
1430 error
= bp
->b_error
;
1431 if (error
== EWOULDBLOCK
)
1432 bp
->b_bio1
.bio_done
= ar_rw_done
;
1439 static struct ata_device
*
1440 ar_locate_disk(int diskno
)
1442 struct ata_channel
*ch
;
1445 for (ctlr
= 0; ctlr
< devclass_get_maxunit(ata_devclass
); ctlr
++) {
1446 if (!(ch
= devclass_get_softc(ata_devclass
, ctlr
)))
1448 if (ch
->devices
& ATA_ATA_MASTER
)
1449 if (ch
->device
[MASTER
].driver
&&
1450 ((struct ad_softc
*)(ch
->device
[MASTER
].driver
))->lun
== diskno
)
1451 return &ch
->device
[MASTER
];
1452 if (ch
->devices
& ATA_ATA_SLAVE
)
1453 if (ch
->device
[SLAVE
].driver
&&
1454 ((struct ad_softc
*)(ch
->device
[SLAVE
].driver
))->lun
== diskno
)
1455 return &ch
->device
[SLAVE
];