diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c index f7422612f65..cddcbee7210 100644 --- a/sys/dev/ata/ata-all.c +++ b/sys/dev/ata/ata-all.c @@ -170,8 +170,10 @@ ata_attach(device_t dev) return ENXIO; } if ((error = bus_setup_intr(dev, ch->r_irq, INTR_TYPE_BIO | INTR_ENTROPY, - ata_intr, ch, &ch->ih))) + ata_intr, ch, &ch->ih))) { + ata_printf(ch, -1, "unable to setup interrupt\n"); return error; + } /* * do not attach devices if we are in early boot, this is done later @@ -203,7 +205,6 @@ ata_attach(device_t dev) if (ch->devices & ATA_ATAPI_SLAVE) atapi_attach(&ch->device[SLAVE]); #endif - /* we should probe & attach RAID's here as well SOS XXX */ } return 0; } @@ -223,12 +224,6 @@ ata_detach(device_t dev) tsleep((caddr_t)&s, PRIBIO, "atarel", hz/4); splx(s); - /* disable interrupts on devices */ - ATA_OUTB(ch->r_io, ATA_DRIVE, ATA_D_IBM | ATA_MASTER); - ATA_OUTB(ch->r_altio, ATA_ALTSTAT, ATA_A_IDS | ATA_A_4BIT); - ATA_OUTB(ch->r_io, ATA_DRIVE, ATA_D_IBM | ATA_SLAVE); - ATA_OUTB(ch->r_altio, ATA_ALTSTAT, ATA_A_IDS | ATA_A_4BIT); - #ifdef DEV_ATADISK if (ch->devices & ATA_ATA_MASTER && ch->device[MASTER].driver) ad_detach(&ch->device[MASTER], 1); @@ -282,52 +277,46 @@ ataioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td) struct ata_cmd *iocmd = (struct ata_cmd *)addr; struct ata_device *atadev; struct ata_channel *ch; - device_t device; - int error; + device_t device = devclass_get_device(ata_devclass, iocmd->channel); + caddr_t buf; + int error, s; if (cmd != IOCATA) return ENOTTY; - if (iocmd->device < -1 || iocmd->device > SLAVE || iocmd->channel < 0 || - iocmd->channel >= devclass_get_maxunit(ata_devclass)) + if (iocmd->channel < -1 || iocmd->device < -1 || iocmd->device > SLAVE) return ENXIO; - if (!(device = devclass_get_device(ata_devclass, iocmd->channel))) - return ENODEV; - switch (iocmd->cmd) { - case ATAATTACH: { + case ATAATTACH: /* should enable channel HW on controller that can SOS XXX */ error = ata_probe(device); if (!error) error = ata_attach(device); return error; - } - case ATADETACH: { + case ATADETACH: error = ata_detach(device); /* should disable channel HW on controller that can SOS XXX */ return error; - } - case ATAREINIT: { - int s; + case ATAREINIT: + if (!device || !(ch = device_get_softc(device))) + return ENXIO; - if (!(ch = device_get_softc(device))) - return ENODEV; - - /* make sure channel is not busy */ s = splbio(); while (!atomic_cmpset_int(&ch->active, ATA_IDLE, ATA_ACTIVE)) tsleep((caddr_t)&s, PRIBIO, "atarin", hz/4); error = ata_reinit(ch); splx(s); return error; - } + + case ATAREBUILD: + return ata_raid_rebuild(iocmd->channel); case ATAGMODE: - if (!(ch = device_get_softc(device))) - return ENODEV; + if (!device || !(ch = device_get_softc(device))) + return ENXIO; if ((iocmd->device == MASTER || iocmd->device == -1) && ch->device[MASTER].driver) @@ -343,8 +332,8 @@ ataioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td) return 0; case ATASMODE: - if (!(ch = device_get_softc(device))) - return ENODEV; + if (!device || !(ch = device_get_softc(device))) + return ENXIO; if ((iocmd->device == MASTER || iocmd->device == -1) && iocmd->u.mode.mode[MASTER] >= 0 && ch->device[MASTER].param) { @@ -361,12 +350,11 @@ ataioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td) } else iocmd->u.mode.mode[SLAVE] = -1; - return 0; case ATAGPARM: - if (!(ch = device_get_softc(device))) - return ENODEV; + if (!device || !(ch = device_get_softc(device))) + return ENXIO; iocmd->u.param.type[MASTER] = ch->devices & (ATA_ATA_MASTER | ATA_ATAPI_MASTER); @@ -384,17 +372,13 @@ ataioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td) if (ch->device[SLAVE].param) bcopy(ch->device[SLAVE].param, &iocmd->u.param.params[SLAVE], sizeof(struct ata_params)); - return 0; #if defined(DEV_ATAPICD) || defined(DEV_ATAPIFD) || defined(DEV_ATAPIST) - case ATAPICMD: { - caddr_t buf; - - ch = device_get_softc(device); - if (!ch) - return ENODEV; + case ATAPICMD: + if (!device || !(ch = device_get_softc(device))) + return ENXIO; if (!(atadev = &ch->device[iocmd->device]) || !(ch->devices & (iocmd->device == MASTER ? @@ -425,8 +409,8 @@ ataioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td) free(buf, M_ATA); return error; - } #endif + default: } return ENOTTY; } @@ -827,11 +811,13 @@ ata_reinit(struct ata_channel *ch) atapi_detach(&ch->device[SLAVE]); #endif if (misdev & ATA_ATA_MASTER || misdev & ATA_ATAPI_MASTER) { - free(ch->device[MASTER].param, M_ATA); + if (ch->device[MASTER].param) + free(ch->device[MASTER].param, M_ATA); ch->device[MASTER].param = NULL; } if (misdev & ATA_ATA_SLAVE || misdev & ATA_ATAPI_SLAVE) { - free(ch->device[SLAVE].param, M_ATA); + if (ch->device[SLAVE].param) + free(ch->device[SLAVE].param, M_ATA); ch->device[SLAVE].param = NULL; } } diff --git a/sys/dev/ata/ata-disk.c b/sys/dev/ata/ata-disk.c index e1c4ef62fda..88e5bae3775 100644 --- a/sys/dev/ata/ata-disk.c +++ b/sys/dev/ata/ata-disk.c @@ -210,10 +210,10 @@ ad_attach(struct ata_device *atadev) atadev->flags = 0; /* if this disk belongs to an ATA RAID dont print the probe */ - if (!ata_raid_probe(adp)) + if (ata_raiddisk_attach(adp)) adp->flags |= AD_F_RAID_SUBDISK; else - ad_print(adp, ""); + ad_print(adp); } void @@ -244,6 +244,8 @@ ad_detach(struct ata_device *atadev, int flush) /* get rid of flush XXX SOS */ if (ata_command(atadev, ATA_C_FLUSHCACHE, 0, 0, 0, ATA_WAIT_READY)) ata_prtdev(atadev, "flushing cache on detach failed\n"); } + if (adp->flags & AD_F_RAID_SUBDISK) + ata_raiddisk_detach(adp); ata_free_name(atadev); ata_free_lun(&adp_lun_map, adp->lun); atadev->driver = NULL; @@ -426,7 +428,7 @@ ad_transfer(struct ad_request *request) request->timeout_handle = timeout((timeout_t*)ad_timeout, request, 10 * hz); - /* setup transfer parameters !! 65536 for 48bit SOS XXX */ + /* setup transfer parameters */ count = howmany(request->bytecount, DEV_BSIZE); max_count = adp->device->param->support.address48 ? 65536 : 256; if (count > max_count) { @@ -900,9 +902,8 @@ ad_reinit(struct ata_device *atadev) } void -ad_print(struct ad_softc *adp, char *prepend) +ad_print(struct ad_softc *adp) { - if (prepend) printf("%s", prepend); if (bootverbose) { ata_prtdev(adp->device, "<%.40s/%.8s> ATA-%d disk at ata%d-%s\n", adp->device->param->model, adp->device->param->revision, @@ -910,7 +911,6 @@ ad_print(struct ad_softc *adp, char *prepend) device_get_unit(adp->device->channel->dev), (adp->device->unit == ATA_MASTER) ? "master" : "slave"); - if (prepend) printf("%s", prepend); ata_prtdev(adp->device, "%lluMB (%llu sectors), %llu C, %u H, %u S, %u B\n", (unsigned long long)(adp->total_secs / @@ -920,13 +920,11 @@ ad_print(struct ad_softc *adp, char *prepend) (adp->heads * adp->sectors)), adp->heads, adp->sectors, DEV_BSIZE); - if (prepend) printf("%s", prepend); ata_prtdev(adp->device, "%d secs/int, %d depth queue, %s%s\n", adp->transfersize / DEV_BSIZE, adp->num_tags + 1, (adp->flags & AD_F_TAG_ENABLED) ? "tagged " : "", ata_mode2str(adp->device->mode)); - if (prepend) printf("%s", prepend); ata_prtdev(adp->device, "piomode=%d dmamode=%d udmamode=%d cblid=%d\n", ata_pmode(adp->device->param), ata_wmode(adp->device->param), ata_umode(adp->device->param), diff --git a/sys/dev/ata/ata-disk.h b/sys/dev/ata/ata-disk.h index 0c175b9d150..ad5e37d4769 100644 --- a/sys/dev/ata/ata-disk.h +++ b/sys/dev/ata/ata-disk.h @@ -83,4 +83,4 @@ void ad_start(struct ata_device *); int ad_transfer(struct ad_request *); int ad_interrupt(struct ad_request *); int ad_service(struct ad_softc *, int); -void ad_print(struct ad_softc *, char *); +void ad_print(struct ad_softc *); diff --git a/sys/dev/ata/ata-dma.c b/sys/dev/ata/ata-dma.c index 8db7a7be45f..3f2abc51584 100644 --- a/sys/dev/ata/ata-dma.c +++ b/sys/dev/ata/ata-dma.c @@ -1225,11 +1225,11 @@ hpt_timing(struct ata_channel *ch, int devno, int mode) case ATA_PIO2: timing = 0x0a81f454; break; case ATA_PIO3: timing = 0x0a81f443; break; case ATA_PIO4: timing = 0x0a81f442; break; - case ATA_WDMA2: timing = 0x22808242; break; - case ATA_UDMA2: timing = 0x120c8242; break; - case ATA_UDMA4: timing = 0x12ac8242; break; - case ATA_UDMA5: timing = 0x12848242; break; - case ATA_UDMA6: timing = 0x12808242; break; + case ATA_WDMA2: timing = 0x22808242; break; + case ATA_UDMA2: timing = 0x120c8242; break; + case ATA_UDMA4: timing = 0x12ac8242; break; + case ATA_UDMA5: timing = 0x12848242; break; + case ATA_UDMA6: timing = 0x12808242; break; default: timing = 0x0d029d5e; } pci_write_config(parent, 0x40 + (devno << 2) , timing, 4); diff --git a/sys/dev/ata/ata-pci.c b/sys/dev/ata/ata-pci.c index 00fcb07b0a8..60bd1c9ed8f 100644 --- a/sys/dev/ata/ata-pci.c +++ b/sys/dev/ata/ata-pci.c @@ -291,7 +291,7 @@ ata_pci_match(device_t dev) return NULL; case 0x000116ca: - return "Cenatek Rocket Drive controller"; + return "Cenatek Rocket Drive controller"; /* unsupported but known chipsets, generic DMA only */ case 0x10001042: @@ -696,7 +696,7 @@ ata_pci_release_resource(device_t dev, device_t child, int type, int rid, /* primary and secondary channels share interrupt, keep track */ if (--controller->irqcnt) return 0; - controller->irq = 0; + controller->irq = NULL; return BUS_RELEASE_RESOURCE(device_get_parent(dev), dev, SYS_RES_IRQ, rid, r); } diff --git a/sys/dev/ata/ata-raid.c b/sys/dev/ata/ata-raid.c index 2c4022e0983..7a0f63fedea 100644 --- a/sys/dev/ata/ata-raid.c +++ b/sys/dev/ata/ata-raid.c @@ -70,53 +70,112 @@ static struct cdevsw ardisk_cdevsw; /* prototypes */ static void ar_done(struct bio *); static void ar_config_changed(struct ar_softc *, int); +static int ar_rebuild(struct ar_softc *); static int ar_highpoint_read_conf(struct ad_softc *, struct ar_softc **); static int ar_highpoint_write_conf(struct ar_softc *); static int ar_promise_read_conf(struct ad_softc *, struct ar_softc **); static int ar_promise_write_conf(struct ar_softc *); -static int ar_read(struct ad_softc *, u_int32_t, int, u_int8_t *); -static int ar_write(struct ad_softc *, u_int32_t, int, u_int8_t *); +static int ar_rw(struct ad_softc *, u_int32_t, int, caddr_t, int); /* misc defines */ #define AD_STRATEGY(x) si_disk->d_devsw->d_strategy(x) #define AD_SOFTC(x) ((struct ad_softc *)(x.device->driver)) +#define AR_READ 0x01 +#define AR_WRITE 0x02 +#define AR_WAIT 0x04 /* internal vars */ static struct ar_softc **ar_table = NULL; static MALLOC_DEFINE(M_AR, "AR driver", "ATA RAID driver"); int -ata_raid_probe(struct ad_softc *adp) { +ata_raiddisk_attach(struct ad_softc *adp) +{ + struct ar_softc *rdp; + int array, disk; + + switch(adp->device->channel->chiptype) { + default: + return 0; + + case 0x4d33105a: case 0x4d38105a: case 0x4d30105a: + case 0x0d30105a: case 0x4d68105a: case 0x6268105a: + case 0x00041103: case 0x00051103: case 0x00081103: + } + if (ar_table) { + for (array = 0; array < MAX_ARRAYS; array++) { + if (!(rdp = ar_table[array]) || !rdp->flags) + continue; + + for (disk = 0; disk < rdp->total_disks; disk++) { + if (rdp->disks[disk].device == adp->device) { + ata_prtdev(rdp->disks[disk].device, + "inserted into ar%d disk%d as spare\n", + array, disk); + rdp->disks[disk].flags = (AR_DF_PRESENT | AR_DF_SPARE); + ar_config_changed(rdp, 1); + return 1; + } + } + } + } + if (!ar_table) ar_table = malloc(sizeof(struct ar_soft *) * MAX_ARRAYS, M_AR, M_NOWAIT | M_ZERO); if (!ar_table) { ata_prtdev(adp->device, "no memory for ATA raid array\n"); - return 1; + return 0; } switch(adp->device->channel->chiptype) { - case 0x4d33105a: - case 0x4d38105a: - case 0x4d30105a: - case 0x0d30105a: - case 0x4d68105a: - case 0x6268105a: + case 0x4d33105a: case 0x4d38105a: case 0x4d30105a: + case 0x0d30105a: case 0x4d68105a: case 0x6268105a: /* test RAID bit in PCI reg XXX */ return (ar_promise_read_conf(adp, ar_table)); - case 0x00041103: - case 0x00051103: - case 0x00081103: + case 0x00041103: case 0x00051103: case 0x00081103: return (ar_highpoint_read_conf(adp, ar_table)); } - return 1; + return 0; +} + +int +ata_raiddisk_detach(struct ad_softc *adp) +{ + struct ar_softc *rdp; + int array, disk; + + switch(adp->device->channel->chiptype) { + default: + return 0; + + case 0x4d33105a: case 0x4d38105a: case 0x4d30105a: + case 0x0d30105a: case 0x4d68105a: case 0x6268105a: + case 0x00041103: case 0x00051103: case 0x00081103: + } + if (ar_table) { + for (array = 0; array < MAX_ARRAYS; array++) { + if (!(rdp = ar_table[array]) || !rdp->flags) + continue; + for (disk = 0; disk < rdp->total_disks; disk++) { + if (rdp->disks[disk].device == adp->device) { + ata_prtdev(rdp->disks[disk].device, + "deleted from ar%d disk%d\n", array, disk); + rdp->disks[disk].flags &= ~(AR_DF_PRESENT | AR_DF_ONLINE); + ar_config_changed(rdp, 1); + return 1; + } + } + } + } + return 0; } void ata_raid_attach() { - struct ar_softc *raid; + struct ar_softc *rdp; dev_t dev; int array, disk; @@ -124,51 +183,19 @@ ata_raid_attach() return; for (array = 0; array < MAX_ARRAYS; array++) { - if (!(raid = ar_table[array]) || !raid->flags) + if (!(rdp = ar_table[array]) || !rdp->flags) continue; - for (disk = 0; disk < raid->total_disks; disk++) { - switch (raid->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) { - case AR_F_SPAN: - case AR_F_RAID0: - if (!(raid->disks[disk].flags & AR_DF_ONLINE)) - raid->flags &= ~AR_F_READY; - break; - - case AR_F_RAID1: - case AR_F_RAID0 | AR_F_RAID1: - if (disk < raid->width) { - if (!(raid->disks[disk].flags & AR_DF_ONLINE) && - !(raid->disks[disk+raid->width].flags&AR_DF_ONLINE)) - raid->flags &= ~AR_F_READY; - else if (((raid->disks[disk].flags & AR_DF_ONLINE) && - !(raid->disks - [disk + raid->width].flags & AR_DF_ONLINE))|| - (!(raid->disks[disk].flags & AR_DF_ONLINE) && - (raid->disks - [disk + raid->width].flags & AR_DF_ONLINE))) - raid->flags |= AR_F_DEGRADED; - } - break; - } - if (raid->disks[disk].device) { - if (raid->disks[disk].flags & AR_DF_ONLINE) - ata_drawerleds(raid->disks[disk].device, ATA_LED_GREEN); - else - ata_drawerleds(raid->disks[disk].device, ATA_LED_RED); - } - } - - dev = disk_create(raid->lun, &raid->disk, 0, &ar_cdevsw,&ardisk_cdevsw); - dev->si_drv1 = raid; + ar_config_changed(rdp, 0); + dev = disk_create(rdp->lun, &rdp->disk, 0, &ar_cdevsw,&ardisk_cdevsw); + dev->si_drv1 = rdp; dev->si_iosize_max = 256 * DEV_BSIZE; - raid->dev = dev; + rdp->dev = dev; printf("ar%d: %lluMB lun, - (unsigned long long)(raid->total_sectors / - ((1024L * 1024L) / DEV_BSIZE))); - switch (raid->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) { + rdp->lun, (unsigned long long) + rdp->total_sectors / ((1024L * 1024L) / DEV_BSIZE)); + switch (rdp->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) { case AR_F_RAID0: printf("RAID0 "); break; case AR_F_RAID1: @@ -178,12 +205,12 @@ ata_raid_attach() case (AR_F_RAID0 | AR_F_RAID1): printf("RAID0+1 "); break; default: - printf("unknown 0x%x> ", raid->flags); + printf("unknown 0x%x> ", rdp->flags); return; } printf("array> [%d/%d/%d] status: ", - raid->cylinders, raid->heads, raid->sectors); - switch (raid->flags & (AR_F_DEGRADED | AR_F_READY)) { + rdp->cylinders, rdp->heads, rdp->sectors); + switch (rdp->flags & (AR_F_DEGRADED | AR_F_READY)) { case AR_F_READY: printf("READY"); break; @@ -195,23 +222,33 @@ ata_raid_attach() break; } printf(" subdisks:\n"); - for (disk = 0; disk < raid->total_disks; disk++) { - if (raid->disks[disk].flags & AR_DF_ONLINE) + for (disk = 0; disk < rdp->total_disks; disk++) { + if (rdp->disks[disk].flags & AR_DF_ONLINE) printf(" %d READY ", disk); - else if (raid->disks[disk].flags & AR_DF_ASSIGNED) + else if (rdp->disks[disk].flags & AR_DF_ASSIGNED) printf(" %d DOWN ", disk); - else if (raid->disks[disk].flags & AR_DF_SPARE) + else if (rdp->disks[disk].flags & AR_DF_SPARE) printf(" %d SPARE ", disk); - else if (raid->disks[disk].flags & AR_DF_PRESENT) + else if (rdp->disks[disk].flags & AR_DF_PRESENT) printf(" %d FREE ", disk); else printf(" %d INVALID no RAID config info on this disk\n", disk); - if (raid->disks[disk].flags & AR_DF_PRESENT) - ad_print(AD_SOFTC(raid->disks[disk]), ""); + if (rdp->disks[disk].flags & AR_DF_PRESENT) + ad_print(AD_SOFTC(rdp->disks[disk])); } } } +int +ata_raid_rebuild(int array) +{ + struct ar_softc *rdp; + + if (!ar_table || !(rdp = ar_table[array])) + return ENXIO; + return ar_rebuild(rdp); +} + static int aropen(dev_t dev, int flags, int fmt, struct thread *td) { @@ -233,7 +270,8 @@ static void arstrategy(struct bio *bp) { struct ar_softc *rdp = bp->bio_dev->si_drv1; - int lba, count, chunk; + int blkno, count, chunk, lba, lbs, tmplba; + int drv = 0, change = 0; caddr_t data; if (!(rdp->flags & AR_F_READY)) { @@ -243,50 +281,41 @@ arstrategy(struct bio *bp) return; } bp->bio_resid = bp->bio_bcount; - lba = bp->bio_pblkno; + blkno = bp->bio_pblkno; data = bp->bio_data; for (count = howmany(bp->bio_bcount, DEV_BSIZE); count > 0; - count -= chunk, lba += chunk, data += (chunk * DEV_BSIZE)) { + count -= chunk, blkno += chunk, data += (chunk * DEV_BSIZE)) { struct ar_buf *buf1, *buf2; - int plba; - buf1 = malloc(sizeof(struct ar_buf), M_AR, M_NOWAIT | M_ZERO); switch (rdp->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) { case AR_F_SPAN: - plba = lba; - while (plba >= - AD_SOFTC(rdp->disks[buf1->drive])->total_secs-rdp->reserved) - plba -= (AD_SOFTC(rdp->disks[buf1->drive++])->total_secs - - rdp->reserved); - buf1->bp.bio_pblkno = plba; - chunk = min(AD_SOFTC(rdp->disks[buf1->drive])->total_secs - - rdp->reserved - plba, count); + lba = blkno; + while (lba >= AD_SOFTC(rdp->disks[drv])->total_secs-rdp->reserved) + lba -= AD_SOFTC(rdp->disks[drv++])->total_secs-rdp->reserved; + chunk = min(AD_SOFTC(rdp->disks[drv])->total_secs-rdp->reserved-lba, + count); break; case AR_F_RAID0: case AR_F_RAID0 | AR_F_RAID1: - plba = lba / rdp->interleave; - chunk = lba % rdp->interleave; - if (plba == rdp->total_sectors / rdp->interleave) { - int lastblksize = - (rdp->total_sectors-(plba*rdp->interleave))/rdp->width; - - buf1->drive = chunk / lastblksize; - buf1->bp.bio_pblkno = - ((plba / rdp->width) * rdp->interleave) + chunk%lastblksize; - chunk = min(count, lastblksize); + tmplba = blkno / rdp->interleave; + chunk = blkno % rdp->interleave; + if (tmplba == rdp->total_sectors / rdp->interleave) { + lbs = (rdp->total_sectors-(tmplba*rdp->interleave))/rdp->width; + drv = chunk / lbs; + lba = ((tmplba/rdp->width)*rdp->interleave) + chunk%lbs; + chunk = min(count, lbs); } else { - buf1->drive = plba % rdp->width; - buf1->bp.bio_pblkno = - ((plba / rdp->width) * rdp->interleave) + chunk; + drv = tmplba % rdp->width; + lba = ((tmplba / rdp->width) * rdp->interleave) + chunk; chunk = min(count, rdp->interleave - chunk); } break; case AR_F_RAID1: - buf1->bp.bio_pblkno = lba; - buf1->drive = 0; + drv = 0; + lba = blkno; chunk = count; break; @@ -298,7 +327,9 @@ arstrategy(struct bio *bp) return; } - if (buf1->drive > 0) + buf1 = malloc(sizeof(struct ar_buf), M_AR, M_NOWAIT | M_ZERO); + buf1->bp.bio_pblkno = lba; + if ((buf1->drive = drv) > 0) buf1->bp.bio_pblkno += rdp->offset; buf1->bp.bio_caller1 = (void *)rdp; buf1->bp.bio_bcount = chunk * DEV_BSIZE; @@ -311,11 +342,11 @@ arstrategy(struct bio *bp) switch (rdp->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) { case AR_F_SPAN: case AR_F_RAID0: - if (!AD_SOFTC(rdp->disks[buf1->drive])->dev->si_disk) { + if (rdp->disks[buf1->drive].flags & AR_DF_ONLINE && + !AD_SOFTC(rdp->disks[buf1->drive])->dev->si_disk) { rdp->disks[buf1->drive].flags &= ~AR_DF_ONLINE; - rdp->flags &= ~AR_F_READY; - printf("ar%d: ERROR broken array in strategy\n", rdp->lun); - ar_config_changed(rdp, buf1->drive); + ar_config_changed(rdp, 1); + free(buf1, M_AR); bp->bio_flags |= BIO_ERROR; bp->bio_error = EIO; biodone(bp); @@ -328,37 +359,30 @@ arstrategy(struct bio *bp) case AR_F_RAID1: case AR_F_RAID0 | AR_F_RAID1: if (rdp->flags & AR_F_REBUILDING) { - if ((bp->bio_pblkno >= rdp->lock_start && - bp->bio_pblkno < rdp->lock_end) || - ((bp->bio_pblkno + chunk) >= rdp->lock_start && - (bp->bio_pblkno + chunk) < rdp->lock_end)) { + int start = rdp->lock_start / rdp->width; + int end = rdp->lock_end / rdp->width; + + if ((bp->bio_pblkno >= end && bp->bio_pblkno < end) || + ((bp->bio_pblkno + chunk) >= start && + (bp->bio_pblkno + chunk) < end)) { tsleep(rdp, PRIBIO, "arwait", 0); } } if (rdp->disks[buf1->drive].flags & AR_DF_ONLINE && !AD_SOFTC(rdp->disks[buf1->drive])->dev->si_disk) { rdp->disks[buf1->drive].flags &= ~AR_DF_ONLINE; - if (rdp->disks[buf1->drive + rdp->width].flags & AR_DF_ONLINE) { - rdp->flags |= AR_F_DEGRADED; - printf("ar%d: WARNING mirror lost in strategy\n", rdp->lun); - } - else - rdp->flags &= ~AR_F_READY; - ar_config_changed(rdp, buf1->drive); + change = 1; } if (rdp->disks[buf1->drive + rdp->width].flags & AR_DF_ONLINE && !AD_SOFTC(rdp->disks[buf1->drive + rdp->width])->dev->si_disk) { rdp->disks[buf1->drive + rdp->width].flags &= ~AR_DF_ONLINE; - if (rdp->disks[buf1->drive].flags & AR_DF_ONLINE) { - rdp->flags |= AR_F_DEGRADED; - printf("ar%d: WARNING mirror lost in strategy\n", rdp->lun); - } - else - rdp->flags &= ~AR_F_READY; - ar_config_changed(rdp, buf1->drive); + change = 1; } + if (change) + ar_config_changed(rdp, 1); + if (!(rdp->flags & AR_F_READY)) { - printf("ar%d: ERROR broken array in strategy\n", rdp->lun); + free(buf1, M_AR); bp->bio_flags |= BIO_ERROR; bp->bio_error = EIO; biodone(bp); @@ -376,7 +400,7 @@ arstrategy(struct bio *bp) AD_SOFTC(rdp->disks[buf2->drive])->dev; buf2->bp.bio_dev->AD_STRATEGY((struct bio *)buf2); rdp->disks[buf2->drive].last_lba = - buf1->bp.bio_pblkno + chunk; + buf2->bp.bio_pblkno + chunk; } else buf1->drive = buf1->drive + rdp->width; @@ -395,6 +419,7 @@ arstrategy(struct bio *bp) buf1->bp.bio_dev->AD_STRATEGY((struct bio *)buf1); rdp->disks[buf1->drive].last_lba = buf1->bp.bio_pblkno + chunk; break; + default: printf("ar%d: unknown array type in arstrategy\n", rdp->lun); } @@ -406,16 +431,13 @@ ar_done(struct bio *bp) { struct ar_softc *rdp = (struct ar_softc *)bp->bio_caller1; struct ar_buf *buf = (struct ar_buf *)bp; - int s = splbio(); switch (rdp->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) { case AR_F_SPAN: case AR_F_RAID0: - if (bp->bio_flags & BIO_ERROR) { + if (buf->bp.bio_flags & BIO_ERROR) { rdp->disks[buf->drive].flags &= ~AR_DF_ONLINE; - rdp->flags &= ~AR_F_READY; - printf("ar%d: ERROR broken array in done\n", rdp->lun); - ar_config_changed(rdp, buf->drive); + ar_config_changed(rdp, 1); buf->org->bio_flags |= BIO_ERROR; buf->org->bio_error = EIO; biodone(buf->org); @@ -429,24 +451,11 @@ ar_done(struct bio *bp) case AR_F_RAID1: case AR_F_RAID0 | AR_F_RAID1: - if (bp->bio_flags & BIO_ERROR) { + if (buf->bp.bio_flags & BIO_ERROR) { rdp->disks[buf->drive].flags &= ~AR_DF_ONLINE; - if ((rdp->flags & AR_F_DEGRADED) && - !((buf->drive < rdp->width) ? - (rdp->disks[buf->drive + rdp->width].flags & AR_DF_ONLINE) : - (rdp->disks[buf->drive - rdp->width].flags & AR_DF_ONLINE))) { - rdp->flags &= ~AR_F_READY; - printf("ar%d: ERROR broken array in done\n", rdp->lun); - ar_config_changed(rdp, buf->drive); - buf->org->bio_flags |= BIO_ERROR; - buf->org->bio_error = EIO; - biodone(buf->org); - } - else { - rdp->flags |= AR_F_DEGRADED; - printf("ar%d: WARNING mirror lost in done\n", rdp->lun); - ar_config_changed(rdp, buf->drive); - if (bp->bio_cmd == BIO_READ) { + ar_config_changed(rdp, 1); + if (rdp->flags & AR_F_READY) { + if (buf->bp.bio_cmd == BIO_READ) { if (buf->drive < rdp->width) buf->drive = buf->drive + rdp->width; else @@ -455,28 +464,32 @@ ar_done(struct bio *bp) buf->bp.bio_flags = buf->org->bio_flags; buf->bp.bio_error = 0; buf->bp.bio_dev->AD_STRATEGY((struct bio *)buf); - splx(s); return; } - if (bp->bio_cmd == BIO_WRITE) { - if (!(buf->flags & AB_F_DONE)) - buf->mirror->flags |= AB_F_DONE; - else { - buf->org->bio_resid -= bp->bio_bcount; + if (buf->bp.bio_cmd == BIO_WRITE) { + if (buf->flags & AB_F_DONE) { + buf->org->bio_resid -= buf->bp.bio_bcount; if (buf->org->bio_resid == 0) biodone(buf->org); } + else + buf->mirror->flags |= AB_F_DONE; } } + else { + buf->org->bio_flags |= BIO_ERROR; + buf->org->bio_error = EIO; + biodone(buf->org); + } } else { - if (bp->bio_cmd == BIO_WRITE) { - if (!(buf->flags & AB_F_DONE) && !(rdp->flags & AR_F_DEGRADED)){ + if (buf->bp.bio_cmd == BIO_WRITE) { + if (buf->mirror && !(buf->flags & AB_F_DONE)){ buf->mirror->flags |= AB_F_DONE; break; } } - buf->org->bio_resid -= bp->bio_bcount; + buf->org->bio_resid -= buf->bp.bio_bcount; if (buf->org->bio_resid == 0) biodone(buf->org); } @@ -486,18 +499,137 @@ ar_done(struct bio *bp) printf("ar%d: unknown array type in ar_done\n", rdp->lun); } free(buf, M_AR); - splx(s); } static void -ar_config_changed(struct ar_softc *rdp, int disk) +ar_config_changed(struct ar_softc *rdp, int writeback) { - if (rdp->flags & AR_F_PROMISE_RAID) - ar_promise_write_conf(rdp); - if (rdp->flags & AR_F_HIGHPOINT_RAID) - ar_highpoint_write_conf(rdp); - if (rdp->disks[disk].device && !(rdp->disks[disk].flags & AR_DF_ONLINE)) - ata_drawerleds(rdp->disks[disk].device, ATA_LED_RED); + int disk, flags; + + flags = rdp->flags; + rdp->flags |= AR_F_READY; + rdp->flags &= ~AR_F_DEGRADED; + + for (disk = 0; disk < rdp->total_disks; disk++) { + switch (rdp->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) { + case AR_F_SPAN: + case AR_F_RAID0: + if (!(rdp->disks[disk].flags & AR_DF_ONLINE)) { + rdp->flags &= ~AR_F_READY; + printf("ar%d: ERROR - array broken\n", rdp->lun); + } + break; + + case AR_F_RAID1: + case AR_F_RAID0 | AR_F_RAID1: + if (disk < rdp->width) { + if (!(rdp->disks[disk].flags & AR_DF_ONLINE) && + !(rdp->disks[disk + rdp->width].flags & AR_DF_ONLINE)) { + rdp->flags &= ~AR_F_READY; + printf("ar%d: ERROR - array broken\n", rdp->lun); + } + else if (((rdp->disks[disk].flags & AR_DF_ONLINE) && + !(rdp->disks + [disk + rdp->width].flags & AR_DF_ONLINE))|| + (!(rdp->disks[disk].flags & AR_DF_ONLINE) && + (rdp->disks + [disk + rdp->width].flags & AR_DF_ONLINE))) { + rdp->flags |= AR_F_DEGRADED; + if (!(flags & AR_F_DEGRADED)) + printf("ar%d: WARNING - mirror lost\n", rdp->lun); + } + } + break; + } + if ((rdp->disks[disk].flags & AR_DF_PRESENT) && + rdp->disks[disk].device) { + if (rdp->disks[disk].flags & AR_DF_ONLINE) + ata_drawerleds(rdp->disks[disk].device, ATA_LED_GREEN); + else + ata_drawerleds(rdp->disks[disk].device, ATA_LED_RED); + } + } + if (writeback) { + if (rdp->flags & AR_F_PROMISE_RAID) + ar_promise_write_conf(rdp); + if (rdp->flags & AR_F_HIGHPOINT_RAID) + ar_highpoint_write_conf(rdp); + } +} + +static int +ar_rebuild(struct ar_softc *rdp) +{ + caddr_t buffer; + int count = 0; + int disk; + + if ((rdp->flags & (AR_F_READY|AR_F_DEGRADED)) != (AR_F_READY|AR_F_DEGRADED)) + return EEXIST; + + for (disk = 0; disk < rdp->total_disks; disk++) { + if (((rdp->disks[disk].flags&(AR_DF_PRESENT|AR_DF_ONLINE|AR_DF_SPARE))== + (AR_DF_PRESENT | AR_DF_SPARE)) && rdp->disks[disk].device) { + if (AD_SOFTC(rdp->disks[disk])->total_secs < + rdp->disks[disk].disk_sectors) { + ata_prtdev(rdp->disks[disk].device, + "disk capacity too small for this RAID config\n"); + rdp->disks[disk].flags &= ~AR_DF_SPARE; + continue; + } + ata_drawerleds(rdp->disks[disk].device, ATA_LED_ORANGE); + count++; + } + } + if (!count) + return ENODEV; + + /* setup start conditions */ + rdp->lock_start = 0; + rdp->lock_end = rdp->lock_start + 256; + rdp->flags |= AR_F_REBUILDING; + buffer = malloc(256 * DEV_BSIZE, M_AR, M_NOWAIT | M_ZERO); + + /* now go copy entire disk(s) */ + while (rdp->lock_start < rdp->total_sectors) { + for (disk = 0; disk < rdp->width; disk++) { + if (((rdp->disks[disk].flags & AR_DF_ONLINE) && + (rdp->disks[disk + rdp->width].flags & AR_DF_ONLINE)) || + ((rdp->disks[disk].flags & AR_DF_ONLINE) && + !(rdp->disks[disk + rdp->width].flags & AR_DF_SPARE)) || + ((rdp->disks[disk + rdp->width].flags & AR_DF_ONLINE) && + !(rdp->disks[disk].flags & AR_DF_SPARE))) + continue; + if (rdp->disks[disk].flags & AR_DF_ONLINE) + ar_rw(AD_SOFTC(rdp->disks[disk]), rdp->lock_start, + 256 * DEV_BSIZE, buffer, AR_READ | AR_WAIT); + else + ar_rw(AD_SOFTC(rdp->disks[disk + rdp->width]), rdp->lock_start, + 256 * DEV_BSIZE, buffer, AR_READ | AR_WAIT); + + if (rdp->disks[disk].flags & AR_DF_ONLINE) + ar_rw(AD_SOFTC(rdp->disks[disk + rdp->width]), rdp->lock_start, + 256 * DEV_BSIZE, buffer, AR_WRITE | AR_WAIT); + else + ar_rw(AD_SOFTC(rdp->disks[disk]), rdp->lock_start, + 256 * DEV_BSIZE, buffer, AR_WRITE | AR_WAIT); + } + rdp->lock_start = rdp->lock_end; + rdp->lock_end = + rdp->lock_start + min(256, rdp->total_sectors - rdp->lock_end); + wakeup(rdp); + } + free(buffer, M_AR); + for (disk = 0; disk < rdp->total_disks; disk++) { + if ((rdp->disks[disk].flags&(AR_DF_PRESENT|AR_DF_ONLINE|AR_DF_SPARE))== + (AR_DF_PRESENT | AR_DF_SPARE)) { + rdp->disks[disk].flags &= ~AR_DF_SPARE; + rdp->disks[disk].flags |= (AR_DF_ASSIGNED | AR_DF_ONLINE); + } + } + rdp->flags &= ~AR_F_REBUILDING; + ar_config_changed(rdp, 1); + return 0; } static int @@ -505,14 +637,14 @@ ar_highpoint_read_conf(struct ad_softc *adp, struct ar_softc **raidp) { struct highpoint_raid_conf *info; struct ar_softc *raid = NULL; - int array, disk_number = 0, error = 1; + int array, disk_number = 0, retval = 0; if (!(info = (struct highpoint_raid_conf *) malloc(sizeof(struct highpoint_raid_conf), M_AR, M_NOWAIT | M_ZERO))) - return error; + return retval; - if (ar_read(adp, HPT_LBA, sizeof(struct highpoint_raid_conf), - (u_int8_t *)info)) { + if (ar_rw(adp, HPT_LBA, sizeof(struct highpoint_raid_conf), + (caddr_t)info, AR_READ | AR_WAIT)) { if (bootverbose) printf("ar: HighPoint read conf failed\n"); goto highpoint_out; @@ -546,7 +678,6 @@ ar_highpoint_read_conf(struct ad_softc *adp, struct ar_softc **raidp) raid = raidp[array]; if (raid->flags & AR_F_PROMISE_RAID) continue; - raid->flags |= AR_F_HIGHPOINT_RAID; switch (info->type) { case HPT_T_RAID0: @@ -627,6 +758,7 @@ ar_highpoint_read_conf(struct ad_softc *adp, struct ar_softc **raidp) goto highpoint_out; } + raid->flags |= AR_F_HIGHPOINT_RAID; raid->disks[disk_number].device = adp->device; raid->disks[disk_number].flags = (AR_DF_PRESENT | AR_DF_ASSIGNED); if (info->magic == HPT_MAGIC_OK) { @@ -640,6 +772,8 @@ ar_highpoint_read_conf(struct ad_softc *adp, struct ar_softc **raidp) raid->total_sectors = info->total_sectors - (HPT_LBA * raid->width); raid->offset = 10; raid->reserved = 10; + raid->disks[disk_number].disk_sectors = + info->total_sectors / info->array_width; } else raid->disks[disk_number].flags &= ~ AR_DF_ONLINE; @@ -648,12 +782,12 @@ ar_highpoint_read_conf(struct ad_softc *adp, struct ar_softc **raidp) raid->total_disks = raid->width; if (disk_number >= raid->total_disks) raid->total_disks = disk_number + 1; - error = 0; + retval = 1; break; } highpoint_out: free(info, M_AR); - return error; + return retval; } static int @@ -663,16 +797,17 @@ ar_highpoint_write_conf(struct ar_softc *rdp) struct timeval timestamp; int disk; - if (!(config = (struct highpoint_raid_conf *) - malloc(sizeof(struct highpoint_raid_conf), M_AR, M_NOWAIT))) - return -1; - microtime(×tamp); rdp->magic_0 = timestamp.tv_sec + 1; rdp->magic_1 = timestamp.tv_sec; for (disk = 0; disk < rdp->total_disks; disk++) { - bzero(config, sizeof(struct highpoint_raid_conf)); + if (!(config = (struct highpoint_raid_conf *) + malloc(sizeof(struct highpoint_raid_conf), + M_AR, M_NOWAIT | M_ZERO))) { + printf("ar%d: Highpoint write conf failed\n", rdp->lun); + return -1; + } if ((rdp->disks[disk].flags & (AR_DF_PRESENT | AR_DF_ONLINE)) == (AR_DF_PRESENT | AR_DF_ONLINE)) config->magic = HPT_MAGIC_OK; @@ -732,11 +867,12 @@ ar_highpoint_write_conf(struct ar_softc *rdp) config->stripe_shift = (rdp->width > 1) ? (ffs(rdp->interleave)-1) : 0; config->total_sectors = rdp->total_sectors; - if (rdp->disks[disk].device && rdp->disks[disk].device->driver && + if ((rdp->disks[disk].flags & AR_DF_PRESENT) && + rdp->disks[disk].device && rdp->disks[disk].device->driver && !(rdp->disks[disk].device->flags & ATA_D_DETACHING)) { - if (ar_write(AD_SOFTC(rdp->disks[disk]), HPT_LBA, - sizeof(struct highpoint_raid_conf), - (u_int8_t *)config)) { + if (ar_rw(AD_SOFTC(rdp->disks[disk]), HPT_LBA, + sizeof(struct highpoint_raid_conf), + (caddr_t)config, AR_WRITE)) { if (bootverbose) printf("ar%d: Highpoint write conf failed\n", rdp->lun); return -1; @@ -752,14 +888,14 @@ ar_promise_read_conf(struct ad_softc *adp, struct ar_softc **raidp) struct promise_raid_conf *info; struct ar_softc *raid; u_int32_t magic, cksum, *ckptr; - int array, count, disk, error = 1; + int array, count, disk, retval = 0; if (!(info = (struct promise_raid_conf *) malloc(sizeof(struct promise_raid_conf), M_AR, M_NOWAIT | M_ZERO))) - return error; + return retval; - if (ar_read(adp, PR_LBA(adp), sizeof(struct promise_raid_conf), - (u_int8_t *)info)) { + if (ar_rw(adp, PR_LBA(adp), sizeof(struct promise_raid_conf), + (caddr_t)info, AR_READ | AR_WAIT)) { if (bootverbose) printf("ar: Promise read conf failed\n"); goto promise_out; @@ -872,13 +1008,15 @@ ar_promise_read_conf(struct ad_softc *adp, struct ar_softc **raidp) if (raid->disks[info->raid.disk_number].flags && adp->device) { raid->disks[info->raid.disk_number].device = adp->device; raid->disks[info->raid.disk_number].flags |= AR_DF_PRESENT; - error = 0; + raid->disks[info->raid.disk_number].disk_sectors = + info->raid.disk_sectors; + retval = 1; } break; } promise_out: free(info, M_AR); - return error; + return retval; } static int @@ -889,17 +1027,18 @@ ar_promise_write_conf(struct ar_softc *rdp) u_int32_t *ckptr; int count, disk, drive; - if (!(config = (struct promise_raid_conf *) - malloc(sizeof(struct promise_raid_conf), M_AR, M_NOWAIT))) - return -1; - - for (count = 0; count < sizeof(struct promise_raid_conf); count++) - *(((u_int8_t *)config) + count) = 255 - (count % 256); - rdp->generation++; microtime(×tamp); for (disk = 0; disk < rdp->total_disks; disk++) { + if (!(config = (struct promise_raid_conf *) + malloc(sizeof(struct promise_raid_conf), M_AR, M_NOWAIT))) { + printf("ar%d: Promise write conf failed\n", rdp->lun); + return -1; + } + for (count = 0; count < sizeof(struct promise_raid_conf); count++) + *(((u_int8_t *)config) + count) = 255 - (count % 256); + bcopy(PR_MAGIC, config->promise_id, sizeof(PR_MAGIC)); config->dummy_0 = 0x00020000; config->magic_0 = PR_MAGIC0(rdp->disks[disk]) | timestamp.tv_sec; @@ -918,7 +1057,7 @@ ar_promise_write_conf(struct ar_softc *rdp) else config->raid.flags |= PR_F_DOWN; config->raid.disk_number = disk; - if (rdp->disks[disk].device) { + if (rdp->disks[disk].flags & AR_DF_PRESENT && rdp->disks[disk].device) { config->raid.channel = rdp->disks[disk].device->channel->unit; config->raid.device = (rdp->disks[disk].device->unit != 0); if (AD_SOFTC(rdp->disks[disk])->dev->si_disk) @@ -992,12 +1131,13 @@ ar_promise_write_conf(struct ar_softc *rdp) config->checksum = 0; for (ckptr = (int32_t *)config, count = 0; count < 511; count++) config->checksum += *ckptr++; - - if (rdp->disks[disk].device && rdp->disks[disk].device->driver && + if ((rdp->disks[disk].flags & AR_DF_PRESENT) && + rdp->disks[disk].device && rdp->disks[disk].device->driver && !(rdp->disks[disk].device->flags & ATA_D_DETACHING)) { - if (ar_write(AD_SOFTC(rdp->disks[disk]), - PR_LBA(AD_SOFTC(rdp->disks[disk])), - sizeof(struct promise_raid_conf), (u_int8_t *)config)){ + if (ar_rw(AD_SOFTC(rdp->disks[disk]), + PR_LBA(AD_SOFTC(rdp->disks[disk])), + sizeof(struct promise_raid_conf), + (caddr_t)config, AR_WRITE)) { if (bootverbose) printf("ar%d: Promise write conf failed\n", rdp->lun); return -1; @@ -1007,44 +1147,39 @@ ar_promise_write_conf(struct ar_softc *rdp) return 0; } -static int -ar_read(struct ad_softc *adp, u_int32_t lba, int count, u_int8_t *data) +static void +ar_rw_done(struct bio *bp) { - if (ata_command(adp->device, count > DEV_BSIZE ? ATA_C_READ_MUL:ATA_C_READ, - lba, count / DEV_BSIZE, 0, ATA_IMMEDIATE)) { - ata_prtdev(adp->device, "RAID read config failed\n"); - return 1; - } - if (ata_wait(adp->device, ATA_S_READY | ATA_S_DSC | ATA_S_DRQ)){ - ata_prtdev(adp->device, "RAID read config timeout\n"); - return 1; - } - ATA_INSW(adp->device->channel->r_io, ATA_DATA, (int16_t *)data, - count/sizeof(int16_t)); - if (ata_wait(adp->device, ATA_S_READY | ATA_S_DSC) < 0) { - ata_prtdev(adp->device, "timeout waiting for final ready\n"); - return 1; - } - return 0; + free(bp->bio_data, M_AR); + free(bp, M_AR); } static int -ar_write(struct ad_softc *adp, u_int32_t lba, int count, u_int8_t *data) +ar_rw(struct ad_softc *adp, u_int32_t lba, int count, caddr_t data, int flags) { - if (ata_command(adp->device,count > DEV_BSIZE ? ATA_C_WRITE_MUL:ATA_C_WRITE, - lba, count / DEV_BSIZE, 0, ATA_IMMEDIATE)) { - ata_prtdev(adp->device, "RAID write config failed\n"); - return 1; - } - if (ata_wait(adp->device, ATA_S_READY | ATA_S_DSC | ATA_S_DRQ)){ - ata_prtdev(adp->device, "RAID write config timeout\n"); - return 1; - } - ATA_OUTSW(adp->device->channel->r_io, ATA_DATA, (int16_t *)data, - count/sizeof(int16_t)); - if (ata_wait(adp->device, ATA_S_READY | ATA_S_DSC) < 0) { - ata_prtdev(adp->device, "timeout waiting for final ready\n"); + struct bio *bp; + int s; + + if (!(bp = (struct bio *)malloc(sizeof(struct bio), M_AR, M_NOWAIT|M_ZERO))) return 1; + bp->bio_dev = adp->dev; + bp->bio_data = data; + bp->bio_pblkno = lba; + bp->bio_bcount = count; + if (flags & AR_READ) + bp->bio_cmd = BIO_READ; + if (flags & AR_WRITE) + bp->bio_cmd = BIO_WRITE; + if (flags & AR_WAIT) + bp->bio_done = (void *)wakeup; + else + bp->bio_done = ar_rw_done; + s = splbio(); + bp->bio_dev->AD_STRATEGY(bp); + splx(s); + if (flags & AR_WAIT) { + tsleep(bp, PRIBIO, "arrw", 0); + free(bp, M_AR); } return 0; } diff --git a/sys/dev/ata/ata-raid.h b/sys/dev/ata/ata-raid.h index 40617018f5f..fc48e22aa9b 100644 --- a/sys/dev/ata/ata-raid.h +++ b/sys/dev/ata/ata-raid.h @@ -30,6 +30,7 @@ struct ar_disk { struct ata_device *device; + u_int64_t disk_sectors; /* sectors on this disk */ off_t last_lba; /* last lba used */ int flags; #define AR_DF_PRESENT 0x00000001 @@ -208,6 +209,9 @@ struct promise_raid_conf { u_int32_t checksum; } __attribute__((packed)); -int ata_raid_probe(struct ad_softc *); +int ata_raiddisk_probe(struct ad_softc *); +int ata_raiddisk_attach(struct ad_softc *); +int ata_raiddisk_detach(struct ad_softc *); void ata_raid_attach(void); +int ata_raid_rebuild(int);