summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sbin/atacontrol/atacontrol.c48
-rw-r--r--sys/conf/files1
-rw-r--r--sys/conf/kmod.mk5
-rw-r--r--sys/conf/options6
-rw-r--r--sys/dev/ata/ata-all.c1085
-rw-r--r--sys/dev/ata/ata-all.h575
-rw-r--r--sys/dev/ata/ata-card.c37
-rw-r--r--sys/dev/ata/ata-cbus.c88
-rw-r--r--sys/dev/ata/ata-chipset.c1308
-rw-r--r--sys/dev/ata/ata-commands.h195
-rw-r--r--sys/dev/ata/ata-disk.c469
-rw-r--r--sys/dev/ata/ata-disk.h34
-rw-r--r--sys/dev/ata/ata-dma.c115
-rw-r--r--sys/dev/ata/ata-isa.c35
-rw-r--r--sys/dev/ata/ata-lowlevel.c533
-rw-r--r--sys/dev/ata/ata-pci.c157
-rw-r--r--sys/dev/ata/ata-pci.h598
-rw-r--r--sys/dev/ata/ata-queue.c350
-rw-r--r--sys/dev/ata/ata-raid.c4435
-rw-r--r--sys/dev/ata/ata-raid.h817
-rw-r--r--sys/dev/ata/atapi-cd.c1306
-rw-r--r--sys/dev/ata/atapi-cd.h466
-rw-r--r--sys/dev/ata/atapi-fd.c498
-rw-r--r--sys/dev/ata/atapi-fd.h72
-rw-r--r--sys/dev/ata/atapi-tape.c630
-rw-r--r--sys/dev/ata/atapi-tape.h198
-rw-r--r--sys/modules/Makefile1
-rw-r--r--sys/modules/ata/Makefile13
-rw-r--r--sys/modules/ata/Makefile.inc3
-rw-r--r--sys/modules/ata/ata/Makefile10
-rw-r--r--sys/modules/ata/atacam/Makefile9
-rw-r--r--sys/modules/ata/atacard/Makefile9
-rw-r--r--sys/modules/ata/atacbus/Makefile9
-rw-r--r--sys/modules/ata/atadisk/Makefile9
-rw-r--r--sys/modules/ata/ataisa/Makefile9
-rw-r--r--sys/modules/ata/atapci/Makefile9
-rw-r--r--sys/modules/ata/atapicd/Makefile9
-rw-r--r--sys/modules/ata/atapifd/Makefile9
-rw-r--r--sys/modules/ata/atapist/Makefile9
-rw-r--r--sys/modules/ata/ataraid/Makefile9
-rw-r--r--sys/sys/ata.h27
41 files changed, 8313 insertions, 5892 deletions
diff --git a/sbin/atacontrol/atacontrol.c b/sbin/atacontrol/atacontrol.c
index 4332299..4f1973a 100644
--- a/sbin/atacontrol/atacontrol.c
+++ b/sbin/atacontrol/atacontrol.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2000 - 2004 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 2000 - 2005 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -373,17 +373,21 @@ main(int argc, char **argv)
iocmd.cmd = ATARAIDCREATE;
if (argc > 2) {
- if (!strcmp(argv[2], "RAID0") ||
- !strcmp(argv[2], "stripe"))
- iocmd.u.raid_setup.type = 1;
- if (!strcmp(argv[2], "RAID1") ||
- !strcmp(argv[2],"mirror"))
- iocmd.u.raid_setup.type = 2;
- if (!strcmp(argv[2], "RAID0+1"))
- iocmd.u.raid_setup.type = 3;
- if (!strcmp(argv[2], "SPAN") ||
- !strcmp(argv[2], "JBOD"))
- iocmd.u.raid_setup.type = 4;
+ if (!strcasecmp(argv[2], "RAID0") ||
+ !strcasecmp(argv[2], "stripe"))
+ iocmd.u.raid_setup.type = AR_RAID0;
+ if (!strcasecmp(argv[2], "RAID1") ||
+ !strcasecmp(argv[2],"mirror"))
+ iocmd.u.raid_setup.type = AR_RAID1;
+ if (!strcasecmp(argv[2], "RAID0+1") ||
+ !strcasecmp(argv[2],"RAID10"))
+ iocmd.u.raid_setup.type = AR_RAID01;
+ if (!strcasecmp(argv[2], "RAID5"))
+ iocmd.u.raid_setup.type = AR_RAID5;
+ if (!strcasecmp(argv[2], "SPAN"))
+ iocmd.u.raid_setup.type = AR_SPAN;
+ if (!strcasecmp(argv[2], "JBOD"))
+ iocmd.u.raid_setup.type = AR_JBOD;
}
if (!iocmd.u.raid_setup.type) {
fprintf(stderr, "atacontrol: Invalid RAID type\n");
@@ -393,7 +397,9 @@ main(int argc, char **argv)
exit(EX_USAGE);
}
- if (iocmd.u.raid_setup.type & 1) {
+ if (iocmd.u.raid_setup.type == AR_RAID0 ||
+ iocmd.u.raid_setup.type == AR_RAID01 ||
+ iocmd.u.raid_setup.type == AR_RAID5) {
if (argc < 4 ||
!sscanf(argv[3], "%d",
&iocmd.u.raid_setup.interleave) == 1) {
@@ -451,6 +457,14 @@ main(int argc, char **argv)
iocmd.cmd = ATARAIDREBUILD;
if (ioctl(fd, IOCATA, &iocmd) < 0)
warn("ioctl(ATARAIDREBUILD)");
+ else {
+ char buffer[128];
+ sprintf(buffer, "/usr/bin/nice -n 20 /bin/dd "
+ "if=/dev/ar%d of=/dev/null bs=1m &",
+ iocmd.channel);
+ if (system(buffer))
+ warn("background dd");
+ }
}
else if (!strcmp(argv[1], "status") && argc == 3) {
int i;
@@ -467,10 +481,16 @@ main(int argc, char **argv)
case AR_RAID1:
printf("RAID1");
break;
- case AR_RAID0 | AR_RAID1:
+ case AR_RAID01:
printf("RAID0+1 stripesize=%d",
iocmd.u.raid_status.interleave);
break;
+ case AR_RAID5:
+ printf("RAID5 stripesize=%d",
+ iocmd.u.raid_status.interleave);
+ break;
+ case AR_JBOD:
+ printf("JBOD");
case AR_SPAN:
printf("SPAN");
break;
diff --git a/sys/conf/files b/sys/conf/files
index c734acc..73fd93a 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -387,6 +387,7 @@ dev/an/if_an_isa.c optional an isa
dev/an/if_an_pccard.c optional an pccard
dev/an/if_an_pci.c optional an pci
dev/asr/asr.c optional asr pci
+dev/ata/ata_if.m optional ata
dev/ata/ata-all.c optional ata
dev/ata/ata-card.c optional ata pccard
dev/ata/ata-cbus.c optional ata pc98
diff --git a/sys/conf/kmod.mk b/sys/conf/kmod.mk
index c753254..07d0c38 100644
--- a/sys/conf/kmod.mk
+++ b/sys/conf/kmod.mk
@@ -298,8 +298,9 @@ ${_src}:
.endfor
.endif
-MFILES?= dev/acpica/acpi_if.m dev/eisa/eisa_if.m dev/iicbus/iicbb_if.m \
- dev/iicbus/iicbus_if.m dev/mii/miibus_if.m dev/ofw/ofw_bus_if.m \
+MFILES?= dev/acpica/acpi_if.m dev/ata/ata_if.m dev/eisa/eisa_if.m \
+ dev/iicbus/iicbb_if.m dev/iicbus/iicbus_if.m \
+ dev/mii/miibus_if.m dev/ofw/ofw_bus_if.m \
dev/pccard/card_if.m dev/pccard/power_if.m dev/pci/pci_if.m \
dev/pci/pcib_if.m dev/ppbus/ppbus_if.m dev/smbus/smbus_if.m \
dev/sound/pcm/ac97_if.m dev/sound/pcm/channel_if.m \
diff --git a/sys/conf/options b/sys/conf/options
index 25608bc..eb0174f 100644
--- a/sys/conf/options
+++ b/sys/conf/options
@@ -303,12 +303,6 @@ ISP_FW_CRASH_DUMP opt_isp.h
# Options used in the 'ata' ATA/ATAPI driver
ATA_STATIC_ID opt_ata.h
ATA_NOPCI opt_ata.h
-DEV_ATADISK opt_ata.h
-DEV_ATAPICD opt_ata.h
-DEV_ATAPIST opt_ata.h
-DEV_ATAPIFD opt_ata.h
-DEV_ATAPICAM opt_ata.h
-DEV_ATARAID opt_ata.h
# Net stuff.
ACCEPT_FILTER_DATA
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c
index ca38b5b..45786e3 100644
--- a/sys/dev/ata/ata-all.c
+++ b/sys/dev/ata/ata-all.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2004 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2005 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/ata.h>
#include <sys/kernel.h>
+#include <sys/module.h>
#include <sys/endian.h>
#include <sys/ctype.h>
#include <sys/conf.h>
@@ -51,33 +52,27 @@ __FBSDID("$FreeBSD$");
#ifdef __alpha__
#include <machine/md_var.h>
#endif
-#include <geom/geom_disk.h>
#include <dev/ata/ata-all.h>
-#include <dev/ata/ata-disk.h>
-#include <dev/ata/ata-raid.h>
+#include <dev/ata/ata-commands.h>
+#include <ata_if.h>
-/* device structures */
-static d_ioctl_t ata_ioctl;
+/* device structure */
+static d_ioctl_t ata_ioctl;
static struct cdevsw ata_cdevsw = {
- .d_version = D_VERSION,
- .d_flags = D_NEEDGIANT,
- .d_ioctl = ata_ioctl,
- .d_name = "ata",
+ .d_version = D_VERSION,
+ .d_flags = D_NEEDGIANT, /* we need this as newbus isn't safe */
+ .d_ioctl = ata_ioctl,
+ .d_name = "ata",
};
/* prototypes */
-static void ata_shutdown(void *, int);
static void ata_interrupt(void *);
-static int ata_getparam(struct ata_device *, u_int8_t);
-static void ata_identify_devices(struct ata_channel *);
static void ata_boot_attach(void);
-static void bswap(int8_t *, int);
-static void btrim(int8_t *, int);
-static void bpack(int8_t *, int8_t *, int);
-static void ata_init(void);
+device_t ata_add_child(driver_t *driver, device_t parent, struct ata_device *atadev, const char *name, int unit);
/* global vars */
MALLOC_DEFINE(M_ATA, "ATA generic", "ATA driver generic layer");
+int (*ata_ioctl_func)(struct ata_cmd *iocmd) = NULL;
devclass_t ata_devclass;
uma_zone_t ata_zone;
int ata_wc = 1;
@@ -86,19 +81,18 @@ int ata_wc = 1;
static struct intr_config_hook *ata_delayed_attach = NULL;
static int ata_dma = 1;
static int atapi_dma = 1;
-static int ata_resuming = 0;
/* sysctl vars */
SYSCTL_NODE(_hw, OID_AUTO, ata, CTLFLAG_RD, 0, "ATA driver parameters");
TUNABLE_INT("hw.ata.ata_dma", &ata_dma);
SYSCTL_INT(_hw_ata, OID_AUTO, ata_dma, CTLFLAG_RDTUN, &ata_dma, 0,
"ATA disk DMA mode control");
-TUNABLE_INT("hw.ata.wc", &ata_wc);
-SYSCTL_INT(_hw_ata, OID_AUTO, wc, CTLFLAG_RDTUN, &ata_wc, 0,
- "ATA disk write caching");
TUNABLE_INT("hw.ata.atapi_dma", &atapi_dma);
SYSCTL_INT(_hw_ata, OID_AUTO, atapi_dma, CTLFLAG_RDTUN, &atapi_dma, 0,
"ATAPI device DMA mode control");
+TUNABLE_INT("hw.ata.wc", &ata_wc);
+SYSCTL_INT(_hw_ata, OID_AUTO, wc, CTLFLAG_RDTUN, &ata_wc, 0,
+ "ATA disk write caching");
/*
* newbus device interface related functions
@@ -106,231 +100,147 @@ SYSCTL_INT(_hw_ata, OID_AUTO, atapi_dma, CTLFLAG_RDTUN, &atapi_dma, 0,
int
ata_probe(device_t dev)
{
- struct ata_channel *ch;
-
- if (!dev || !(ch = device_get_softc(dev)))
- return ENXIO;
-
- if (ch->r_irq)
- return EEXIST;
-
return 0;
}
int
ata_attach(device_t dev)
{
- struct ata_channel *ch;
+ struct ata_channel *ch = device_get_softc(dev);
int error, rid;
- if (!dev || !(ch = device_get_softc(dev)))
- return ENXIO;
+ /* check that we have a virgin channel to attach */
+ if (ch->r_irq)
+ return EEXIST;
/* initialize the softc basics */
- ch->device[MASTER].channel = ch;
- ch->device[MASTER].unit = ATA_MASTER;
- ch->device[MASTER].mode = ATA_PIO;
- ch->device[SLAVE].channel = ch;
- ch->device[SLAVE].unit = ATA_SLAVE;
- ch->device[SLAVE].mode = ATA_PIO;
ch->dev = dev;
ch->state = ATA_IDLE;
bzero(&ch->state_mtx, sizeof(struct mtx));
mtx_init(&ch->state_mtx, "ATA state lock", NULL, MTX_DEF);
+ bzero(&ch->queue_mtx, sizeof(struct mtx));
+ mtx_init(&ch->queue_mtx, "ATA queue lock", NULL, MTX_DEF);
+ TAILQ_INIT(&ch->ata_queue);
/* initialise device(s) on this channel */
- while (ch->locking(ch, ATA_LF_LOCK) != ch->unit)
+ while (ATA_LOCKING(device_get_parent(dev), dev, ATA_LF_LOCK) != ch->unit)
tsleep(&error, PRIBIO, "ataatch", 1);
ch->hw.reset(ch);
- ch->locking(ch, ATA_LF_UNLOCK);
+ ATA_LOCKING(device_get_parent(dev), dev, ATA_LF_UNLOCK);
+ /* setup interrupt delivery */
rid = ATA_IRQ_RID;
ch->r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
RF_SHAREABLE | RF_ACTIVE);
if (!ch->r_irq) {
- ata_printf(ch, -1, "unable to allocate interrupt\n");
+ device_printf(dev, "unable to allocate interrupt\n");
return ENXIO;
}
if ((error = bus_setup_intr(dev, ch->r_irq, ATA_INTR_FLAGS,
ata_interrupt, ch, &ch->ih))) {
- ata_printf(ch, -1, "unable to setup interrupt\n");
+ device_printf(dev, "unable to setup interrupt\n");
return error;
}
- /* initialize queue and associated lock */
- bzero(&ch->queue_mtx, sizeof(struct mtx));
- mtx_init(&ch->queue_mtx, "ATA queue lock", NULL, MTX_DEF);
- TAILQ_INIT(&ch->ata_queue);
-
/* do not attach devices if we are in early boot */
if (ata_delayed_attach)
return 0;
- ata_identify_devices(ch);
-
- if (ch->device[MASTER].attach)
- ch->device[MASTER].attach(&ch->device[MASTER]);
- if (ch->device[SLAVE].attach)
- ch->device[SLAVE].attach(&ch->device[SLAVE]);
-#ifdef DEV_ATAPICAM
- atapi_cam_attach_bus(ch);
-#endif
+ /* probe and attach devices on this channel */
+ bus_generic_probe(dev);
+ bus_generic_attach(dev);
return 0;
}
int
ata_detach(device_t dev)
{
- struct ata_channel *ch;
+ struct ata_channel *ch = device_get_softc(dev);
+ device_t *children;
+ int nchildren, i;
- if (!dev || !(ch = device_get_softc(dev)) || !ch->r_irq)
+ /* check that we have a vaild channel to detach */
+ if (!ch->r_irq)
return ENXIO;
- /* mark devices on this channel as detaching */
- ch->device[MASTER].flags |= ATA_D_DETACHING;
- ch->device[SLAVE].flags |= ATA_D_DETACHING;
+ /* detach & delete all children */
+ if (!device_get_children(dev, &children, &nchildren)) {
+ for (i = 0; i < nchildren; i++)
+ if (children[i])
+ device_delete_child(dev, children[i]);
+ free(children, M_TEMP);
+ }
- /* fail outstanding requests on this channel */
+ /* fail outstanding requests on this channel (SOS shouldn't be any XXX ) */
ata_fail_requests(ch, NULL);
- /* unlock the channel */
- mtx_lock(&ch->state_mtx);
- ch->state = ATA_IDLE;
- mtx_unlock(&ch->state_mtx);
- ch->locking(ch, ATA_LF_UNLOCK);
-
- /* detach devices on this channel */
- if (ch->device[MASTER].detach)
- ch->device[MASTER].detach(&ch->device[MASTER]);
- if (ch->device[SLAVE].detach)
- ch->device[SLAVE].detach(&ch->device[SLAVE]);
-#ifdef DEV_ATAPICAM
- atapi_cam_detach_bus(ch);
-#endif
-
- /* flush cache and powerdown device */
- if (ch->device[MASTER].param) {
- if (ch->device[MASTER].param->support.command2 & ATA_SUPPORT_FLUSHCACHE)
- ata_controlcmd(&ch->device[MASTER], ATA_FLUSHCACHE, 0, 0, 0);
- ata_controlcmd(&ch->device[MASTER], ATA_SLEEP, 0, 0, 0);
- free(ch->device[MASTER].param, M_ATA);
- ch->device[MASTER].param = NULL;
- }
- if (ch->device[SLAVE].param) {
- if (ch->device[SLAVE].param->support.command2 & ATA_SUPPORT_FLUSHCACHE)
- ata_controlcmd(&ch->device[SLAVE], ATA_FLUSHCACHE, 0, 0, 0);
- ata_controlcmd(&ch->device[SLAVE], ATA_SLEEP, 0, 0, 0);
- free(ch->device[SLAVE].param, M_ATA);
- ch->device[SLAVE].param = NULL;
- }
- ch->device[MASTER].mode = ATA_PIO;
- ch->device[SLAVE].mode = ATA_PIO;
- ch->devices = 0;
-
+ /* release resources */
bus_teardown_intr(dev, ch->r_irq, ch->ih);
bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, ch->r_irq);
ch->r_irq = NULL;
+ mtx_destroy(&ch->state_mtx);
mtx_destroy(&ch->queue_mtx);
return 0;
}
int
-ata_reinit(struct ata_channel *ch)
+ata_reinit(device_t dev)
{
- int devices, misdev, newdev;
+ struct ata_channel *ch = device_get_softc(dev);
+ device_t *children;
+ int nchildren, i;
- if (!ch->r_irq)
+ if (!ch || !ch->r_irq)
return ENXIO;
if (bootverbose)
- ata_printf(ch, -1, "reiniting channel ..\n");
+ device_printf(dev, "reiniting channel ..\n");
- /* poll for locking of this channel */
- while (ch->locking(ch, ATA_LF_LOCK) != ch->unit)
- tsleep(&devices, PRIBIO, "atarint", 1);
+ /* poll for locking the channel */
+ while (ATA_LOCKING(device_get_parent(dev), dev, ATA_LF_LOCK) != ch->unit)
+ tsleep(&dev, PRIBIO, "atarini", 1);
- ata_catch_inflight(ch);
-
- /* grap the channel lock no matter what */
+ /* grap the channel lock */
mtx_lock(&ch->state_mtx);
- ch->state = ATA_ACTIVE;
+ ch->state = ATA_STALL_QUEUE;
mtx_unlock(&ch->state_mtx);
- if (ch->flags & ATA_IMMEDIATE_MODE)
- return EIO;
- else
- ch->flags |= ATA_IMMEDIATE_MODE;
-
- devices = ch->devices;
-
+ /* reset the channel and devices */
ch->hw.reset(ch);
- if (bootverbose)
- ata_printf(ch, -1, "resetting done ..\n");
-
- /* detach what left the channel during reset */
- if ((misdev = devices & ~ch->devices)) {
- if ((misdev & (ATA_ATA_MASTER | ATA_ATAPI_MASTER)) &&
- ch->device[MASTER].detach) {
- ata_fail_requests(ch, &ch->device[MASTER]);
- ch->device[MASTER].detach(&ch->device[MASTER]);
- free(ch->device[MASTER].param, M_ATA);
- ch->device[MASTER].param = NULL;
- }
- if ((misdev & (ATA_ATA_SLAVE | ATA_ATAPI_SLAVE)) &&
- ch->device[SLAVE].detach) {
- ata_fail_requests(ch, &ch->device[SLAVE]);
- ch->device[SLAVE].detach(&ch->device[SLAVE]);
- free(ch->device[SLAVE].param, M_ATA);
- ch->device[SLAVE].param = NULL;
+ /* reinit the children and delete any that fails */
+ if (!device_get_children(dev, &children, &nchildren)) {
+ mtx_lock(&Giant); /* newbus suckage it needs Giant */
+ for (i = 0; i < nchildren; i++) {
+ if (children[i] && device_is_attached(children[i]))
+ if (ATA_REINIT(children[i])) {
+ if (ch->running->dev == children[i]) {
+ device_printf(ch->running->dev,
+ "FAILURE - device detached\n");
+ ch->running->dev = NULL;
+ ch->running = NULL;
+ }
+ device_delete_child(dev, children[i]);
+ }
}
+ free(children, M_TEMP);
+ mtx_unlock(&Giant); /* newbus suckage dealt with, release Giant */
}
- /* identify what is present on the channel now */
- ata_identify_devices(ch);
-
- /* detach what left the channel during identify */
- if ((misdev = devices & ~ch->devices)) {
- if ((misdev & (ATA_ATA_MASTER | ATA_ATAPI_MASTER)) &&
- ch->device[MASTER].detach) {
- ata_fail_requests(ch, &ch->device[MASTER]);
- ch->device[MASTER].detach(&ch->device[MASTER]);
- free(ch->device[MASTER].param, M_ATA);
- ch->device[MASTER].param = NULL;
- }
- if ((misdev & (ATA_ATA_SLAVE | ATA_ATAPI_SLAVE)) &&
- ch->device[SLAVE].detach) {
- ata_fail_requests(ch, &ch->device[SLAVE]);
- ch->device[SLAVE].detach(&ch->device[SLAVE]);
- free(ch->device[SLAVE].param, M_ATA);
- ch->device[SLAVE].param = NULL;
- }
- }
+ /* catch running request if any */
+ ata_catch_inflight(ch);
- ch->flags &= ~ATA_IMMEDIATE_MODE;
+ /* we're done release the channel for new work */
mtx_lock(&ch->state_mtx);
ch->state = ATA_IDLE;
mtx_unlock(&ch->state_mtx);
- ch->locking(ch, ATA_LF_UNLOCK);
-
- /* attach new devices */
- if ((newdev = ~devices & ch->devices)) {
- if ((newdev & (ATA_ATA_MASTER | ATA_ATAPI_MASTER)) &&
- ch->device[MASTER].attach)
- ch->device[MASTER].attach(&ch->device[MASTER]);
- if ((newdev & (ATA_ATA_SLAVE | ATA_ATAPI_SLAVE)) &&
- ch->device[SLAVE].attach)
- ch->device[SLAVE].attach(&ch->device[SLAVE]);
- }
-
-#ifdef DEV_ATAPICAM
- atapi_cam_reinit_bus(ch);
-#endif
+ ATA_LOCKING(device_get_parent(dev), dev, ATA_LF_UNLOCK);
if (bootverbose)
- ata_printf(ch, -1, "device config done ..\n");
+ device_printf(dev, "reinit done ..\n");
- ata_start(ch);
+ /* kick off requests on the queue */
+ ata_start(dev);
return 0;
}
@@ -342,6 +252,7 @@ ata_suspend(device_t dev)
if (!dev || !(ch = device_get_softc(dev)))
return ENXIO;
+ /* wait for the channel to be IDLE before when enter suspend mode */
while (1) {
mtx_lock(&ch->state_mtx);
if (ch->state == ATA_IDLE) {
@@ -352,7 +263,7 @@ ata_suspend(device_t dev)
mtx_unlock(&ch->state_mtx);
tsleep(ch, PRIBIO, "atasusp", hz/10);
}
- ch->locking(ch, ATA_LF_UNLOCK);
+ ATA_LOCKING(device_get_parent(dev), dev, ATA_LF_UNLOCK);
return 0;
}
@@ -365,30 +276,12 @@ ata_resume(device_t dev)
if (!dev || !(ch = device_get_softc(dev)))
return ENXIO;
- ata_resuming = 1;
- error = ata_reinit(ch);
- ata_start(ch);
- ata_resuming = 0;
- return error;
-}
-
-static void
-ata_shutdown(void *arg, int howto)
-{
- struct ata_channel *ch;
- int ctlr;
+ /* reinit the devices, we dont know what mode/state they have */
+ error = ata_reinit(dev);
- /* flush cache on all devices */
- for (ctlr = 0; ctlr < devclass_get_maxunit(ata_devclass); ctlr++) {
- if (!(ch = devclass_get_softc(ata_devclass, ctlr)))
- continue;
- if (ch->device[MASTER].param &&
- ch->device[MASTER].param->support.command2 & ATA_SUPPORT_FLUSHCACHE)
- ata_controlcmd(&ch->device[MASTER], ATA_FLUSHCACHE, 0, 0, 0);
- if (ch->device[SLAVE].param &&
- ch->device[SLAVE].param->support.command2 & ATA_SUPPORT_FLUSHCACHE)
- ata_controlcmd(&ch->device[SLAVE], ATA_FLUSHCACHE, 0, 0, 0);
- }
+ /* kick off requests on the queue */
+ ata_start(dev);
+ return error;
}
static void
@@ -400,7 +293,7 @@ ata_interrupt(void *data)
mtx_lock(&ch->state_mtx);
do {
/* do we have a running request */
- if (!(request = ch->running))
+ if (ch->state & ATA_TIMEOUT || !(request = ch->running))
break;
ATA_DEBUG_RQ(request, "interrupt");
@@ -413,30 +306,30 @@ ata_interrupt(void *data)
}
/* check for the right state */
- if (ch->state == ATA_ACTIVE) {
+ if (ch->state == ATA_ACTIVE || ch->state == ATA_STALL_QUEUE) {
request->flags |= ATA_R_INTR_SEEN;
- ch->state = ATA_INTERRUPT;
}
else {
- ata_prtdev(request->device,
- "interrupt state=%d unexpected\n", ch->state);
+ device_printf(request->dev,
+ "interrupt state=%d unexpected\n", ch->state);
break;
}
+ /*
+ * we have the HW locks, so start the tranaction for this request
+ * if it finishes immediately we dont need to wait for interrupt
+ */
if (ch->hw.end_transaction(request) == ATA_OP_FINISHED) {
ch->running = NULL;
- if (ch->flags & ATA_IMMEDIATE_MODE)
- ch->state = ATA_ACTIVE;
- else
+ if (ch->state == ATA_ACTIVE)
ch->state = ATA_IDLE;
mtx_unlock(&ch->state_mtx);
- ch->locking(ch, ATA_LF_UNLOCK);
+ ATA_LOCKING(device_get_parent(ch->dev), ch->dev, ATA_LF_UNLOCK);
ata_finish(request);
return;
}
else {
request->flags &= ~ATA_R_INTR_SEEN;
- ch->state = ATA_ACTIVE;
}
} while (0);
mtx_unlock(&ch->state_mtx);
@@ -450,537 +343,350 @@ ata_ioctl(struct cdev *dev, u_long cmd, caddr_t addr,
int32_t flag, struct thread *td)
{
struct ata_cmd *iocmd = (struct ata_cmd *)addr;
- device_t device = devclass_get_device(ata_devclass, iocmd->channel);
- struct ata_channel *ch;
- struct ata_device *atadev;
+ device_t *children, device = NULL;
struct ata_request *request;
caddr_t buf;
+ int nchildren, i;
int error = ENOTTY;
if (cmd != IOCATA)
- return error;
-
- DROP_GIANT();
- switch (iocmd->cmd) {
- case ATAGMAXCHANNEL:
+ return ENOTSUP;
+ if (iocmd->cmd == ATAGMAXCHANNEL) {
iocmd->u.maxchan = devclass_get_maxunit(ata_devclass);
- error = 0;
- break;
+ return 0;
+ }
+ if (iocmd->channel < 0 ||
+ iocmd->channel >= devclass_get_maxunit(ata_devclass)) {
+ return ENXIO;
+ }
+ if (!(device = devclass_get_device(ata_devclass, iocmd->channel)))
+ return ENXIO;
+ switch (iocmd->cmd) {
case ATAGPARM:
- if (!device || !(ch = device_get_softc(device))) {
- error = ENXIO;
- break;
+ if (!device_get_children(device, &children, &nchildren)) {
+ struct ata_channel *ch;
+
+ if (!(ch = device_get_softc(device)))
+ return ENXIO;
+ iocmd->u.param.type[0] =
+ ch->devices & (ATA_ATA_MASTER | ATA_ATAPI_MASTER);
+ iocmd->u.param.type[1] =
+ ch->devices & (ATA_ATA_SLAVE | ATA_ATAPI_SLAVE);
+ for (i = 0; i < nchildren; i++) {
+ if (children[i] && device_is_attached(children[i])) {
+ struct ata_device *atadev = device_get_softc(children[i]);
+
+ if (atadev->unit == ATA_MASTER) {
+ strcpy(iocmd->u.param.name[0],
+ device_get_nameunit(children[i]));
+ bcopy(&atadev->param, &iocmd->u.param.params[0],
+ sizeof(struct ata_params));
+ }
+ if (atadev->unit == ATA_SLAVE) {
+ strcpy(iocmd->u.param.name[1],
+ device_get_nameunit(children[i]));
+ bcopy(&atadev->param, &iocmd->u.param.params[1],
+ sizeof(struct ata_params));
+ }
+ }
+ }
+ free(children, M_TEMP);
+ error = 0;
}
- iocmd->u.param.type[MASTER] =
- ch->devices & (ATA_ATA_MASTER | ATA_ATAPI_MASTER);
- iocmd->u.param.type[SLAVE] =
- ch->devices & (ATA_ATA_SLAVE | ATA_ATAPI_SLAVE);
- if (ch->device[MASTER].name)
- strcpy(iocmd->u.param.name[MASTER], ch->device[MASTER].name);
- if (ch->device[SLAVE].name)
- strcpy(iocmd->u.param.name[SLAVE], ch->device[SLAVE].name);
- if (ch->device[MASTER].param)
- bcopy(ch->device[MASTER].param, &iocmd->u.param.params[MASTER],
- sizeof(struct ata_params));
- if (ch->device[SLAVE].param)
- bcopy(ch->device[SLAVE].param, &iocmd->u.param.params[SLAVE],
- sizeof(struct ata_params));
- error = 0;
+ else
+ error = ENXIO;
break;
case ATAGMODE:
- if (!device || !(ch = device_get_softc(device))) {
- error = ENXIO;
- break;
+ if (!device_get_children(device, &children, &nchildren)) {
+ for (i = 0; i < nchildren; i++) {
+ if (children[i] && device_is_attached(children[i])) {
+ struct ata_device *atadev = device_get_softc(children[i]);
+
+ atadev = device_get_softc(children[i]);
+ if (atadev->unit == ATA_MASTER)
+ iocmd->u.mode.mode[0] = atadev->mode;
+ if (atadev->unit == ATA_SLAVE)
+ iocmd->u.mode.mode[1] = atadev->mode;
+ }
+ free(children, M_TEMP);
+ }
+ error = 0;
}
- iocmd->u.mode.mode[MASTER] = ch->device[MASTER].mode;
- iocmd->u.mode.mode[SLAVE] = ch->device[SLAVE].mode;
- error = 0;
+ else
+ error = ENXIO;
break;
case ATASMODE:
- if (!device || !(ch = device_get_softc(device))) {
- error = ENXIO;
- break;
+ if (!device_get_children(device, &children, &nchildren)) {
+ for (i = 0; i < nchildren; i++) {
+ if (children[i] && device_is_attached(children[i])) {
+ struct ata_device *atadev = device_get_softc(children[i]);
+
+ if (atadev->unit == ATA_MASTER) {
+ atadev->mode = iocmd->u.mode.mode[0];
+ ATA_SETMODE(device_get_parent(device), children[i]);
+ iocmd->u.mode.mode[0] = atadev->mode;
+ }
+ if (atadev->unit == ATA_SLAVE) {
+ atadev->mode = iocmd->u.mode.mode[1];
+ ATA_SETMODE(device_get_parent(device), children[i]);
+ iocmd->u.mode.mode[1] = atadev->mode;
+ }
+ }
+ }
+ free(children, M_TEMP);
+ error = 0;
}
- if (iocmd->u.mode.mode[MASTER] >= 0 && ch->device[MASTER].param)
- ch->device[MASTER].setmode(&ch->device[MASTER],
- iocmd->u.mode.mode[MASTER]);
- iocmd->u.mode.mode[MASTER] = ch->device[MASTER].mode;
- if (iocmd->u.mode.mode[SLAVE] >= 0 && ch->device[SLAVE].param)
- ch->device[SLAVE].setmode(&ch->device[SLAVE],
- iocmd->u.mode.mode[SLAVE]);
- iocmd->u.mode.mode[SLAVE] = ch->device[SLAVE].mode;
- error = 0;
+ else
+ error = ENXIO;
break;
case ATAREQUEST:
- if (!device || !(ch = device_get_softc(device))) {
- error = ENXIO;
- break;
- }
- if (!(atadev = &ch->device[iocmd->device])) {
- error = ENODEV;
- break;
- }
- if (!(buf = malloc(iocmd->u.request.count, M_ATA, M_NOWAIT))) {
- error = ENOMEM;
- break;
- }
- if (!(request = ata_alloc_request())) {
- error = ENOMEM;
- free(buf, M_ATA);
- break;
- }
- if (iocmd->u.request.flags & ATA_CMD_WRITE) {
- error = copyin(iocmd->u.request.data, buf, iocmd->u.request.count);
- if (error) {
- free(buf, M_ATA);
- ata_free_request(request);
- break;
+ if (!device_get_children(device, &children, &nchildren)) {
+ for (i = 0; i < nchildren; i++) {
+ if (children[i] && device_is_attached(children[i])) {
+ struct ata_device *atadev = device_get_softc(children[i]);
+
+ if (ATA_DEV(atadev->unit) == iocmd->device) {
+ if (!(buf = malloc(iocmd->u.request.count,
+ M_ATA, M_NOWAIT))) {
+ error = ENOMEM;
+ break;
+ }
+ if (!(request = ata_alloc_request())) {
+ error = ENOMEM;
+ free(buf, M_ATA);
+ break;
+ }
+ if (iocmd->u.request.flags & ATA_CMD_WRITE) {
+ error = copyin(iocmd->u.request.data, buf,
+ iocmd->u.request.count);
+ if (error) {
+ free(buf, M_ATA);
+ ata_free_request(request);
+ break;
+ }
+ }
+ request->dev = atadev->dev;
+ if (iocmd->u.request.flags & ATA_CMD_ATAPI) {
+ request->flags = ATA_R_ATAPI;
+ bcopy(iocmd->u.request.u.atapi.ccb,
+ request->u.atapi.ccb, 16);
+ }
+ else {
+ request->u.ata.command =
+ iocmd->u.request.u.ata.command;
+ request->u.ata.feature =
+ iocmd->u.request.u.ata.feature;
+ request->u.ata.lba = iocmd->u.request.u.ata.lba;
+ request->u.ata.count = iocmd->u.request.u.ata.count;
+ }
+ request->timeout = iocmd->u.request.timeout;
+ request->data = buf;
+ request->bytecount = iocmd->u.request.count;
+ request->transfersize = request->bytecount;
+ if (iocmd->u.request.flags & ATA_CMD_CONTROL)
+ request->flags |= ATA_R_CONTROL;
+ if (iocmd->u.request.flags & ATA_CMD_READ)
+ request->flags |= ATA_R_READ;
+ if (iocmd->u.request.flags & ATA_CMD_WRITE)
+ request->flags |= ATA_R_WRITE;
+ ata_queue_request(request);
+ if (!(request->flags & ATA_R_ATAPI)) {
+ iocmd->u.request.u.ata.command =
+ request->u.ata.command;
+ iocmd->u.request.u.ata.feature =
+ request->u.ata.feature;
+ iocmd->u.request.u.ata.lba = request->u.ata.lba;
+ iocmd->u.request.u.ata.count = request->u.ata.count;
+ }
+ iocmd->u.request.error = request->result;
+ if (iocmd->u.request.flags & ATA_CMD_READ)
+ error = copyout(buf, iocmd->u.request.data,
+ iocmd->u.request.count);
+ else
+ error = 0;
+ free(buf, M_ATA);
+ ata_free_request(request);
+ break;
+ }
+ }
}
+ free(children, M_TEMP);
}
-
- request->device = atadev;
-
- if (iocmd->u.request.flags & ATA_CMD_ATAPI) {
- request->flags = ATA_R_ATAPI;
- bcopy(iocmd->u.request.u.atapi.ccb, request->u.atapi.ccb, 16);
- }
- else {
- request->u.ata.command = iocmd->u.request.u.ata.command;
- request->u.ata.feature = iocmd->u.request.u.ata.feature;
- request->u.ata.lba = iocmd->u.request.u.ata.lba;
- request->u.ata.count = iocmd->u.request.u.ata.count;
- }
-
- request->timeout = iocmd->u.request.timeout;
- request->data = buf;
- request->bytecount = iocmd->u.request.count;
- request->transfersize = request->bytecount;
-
- if (iocmd->u.request.flags & ATA_CMD_CONTROL)
- request->flags |= ATA_R_CONTROL;
- if (iocmd->u.request.flags & ATA_CMD_READ)
- request->flags |= ATA_R_READ;
- if (iocmd->u.request.flags & ATA_CMD_WRITE)
- request->flags |= ATA_R_WRITE;
-
- ata_queue_request(request);
-
- iocmd->u.request.u.ata.command = request->u.ata.command;
- iocmd->u.request.u.ata.feature = request->u.ata.feature;
- iocmd->u.request.u.ata.lba = request->u.ata.lba;
- iocmd->u.request.u.ata.count = request->u.ata.count;
- if (request->result)
- iocmd->u.request.error = request->result;
- else {
- if (iocmd->u.request.flags & ATA_CMD_READ)
- error = copyout(buf,
- iocmd->u.request.data, iocmd->u.request.count);
- else
- error = 0;
- }
- free(buf, M_ATA);
- ata_free_request(request);
+ else
+ error = ENXIO;
break;
case ATAREINIT:
- if (!device || !(ch = device_get_softc(device))) {
- error = ENXIO;
- break;
- }
- error = ata_reinit(ch);
- ata_start(ch);
+ error = ata_reinit(device);
+ ata_start(device);
break;
case ATAATTACH:
- if (!device) {
- error = ENXIO;
- break;
- }
/* SOS should enable channel HW on controller XXX */
- error = ata_probe(device);
- if (!error)
- error = ata_attach(device);
+ error = ata_attach(device);
break;
case ATADETACH:
- if (!device) {
- error = ENXIO;
- break;
- }
error = ata_detach(device);
/* SOS should disable channel HW on controller XXX */
break;
-
-#ifdef DEV_ATARAID
- case ATARAIDCREATE:
- error = ata_raid_create(&iocmd->u.raid_setup);
- break;
-
- case ATARAIDDELETE:
- error = ata_raid_delete(iocmd->channel);
- break;
-
- case ATARAIDSTATUS:
- error = ata_raid_status(iocmd->channel, &iocmd->u.raid_status);
- break;
-
- case ATARAIDADDSPARE:
- error = ata_raid_addspare(iocmd->channel, iocmd->u.raid_spare.disk);
- break;
-
- case ATARAIDREBUILD:
- error = ata_raid_rebuild(iocmd->channel);
- break;
-#endif
- }
- PICKUP_GIANT();
- return error;
-}
-
-/*
- * device probe functions
- */
-static int
-ata_getparam(struct ata_device *atadev, u_int8_t command)
-{
- struct ata_request *request;
- int error = ENOMEM;
-
- if (!atadev->param)
- atadev->param = malloc(sizeof(struct ata_params), M_ATA, M_NOWAIT);
- if (atadev->param) {
- request = ata_alloc_request();
- if (request) {
- int retries = 2;
- while (retries-- > 0) {
- request->device = atadev;
- request->timeout = 5;
- request->retries = 0;
- request->u.ata.command = command;
- request->flags = (ATA_R_READ | ATA_R_IMMEDIATE);
- request->data = (caddr_t)atadev->param;
- request->bytecount = sizeof(struct ata_params);
- request->donecount = 0;
- request->transfersize = DEV_BSIZE;
- ata_queue_request(request);
- if (!(error = request->result))
- break;
- }
- ata_free_request(request);
- }
- if (!error && (isprint(atadev->param->model[0]) ||
- isprint(atadev->param->model[1]))) {
- struct ata_params *atacap = atadev->param;
-#if BYTE_ORDER == BIG_ENDIAN
- int16_t *ptr;
-
- for (ptr = (int16_t *)atacap;
- ptr < (int16_t *)atacap + sizeof(struct ata_params)/2; ptr++) {
- *ptr = bswap16(*ptr);
- }
-#endif
- if (!(!strncmp(atacap->model, "FX", 2) ||
- !strncmp(atacap->model, "NEC", 3) ||
- !strncmp(atacap->model, "Pioneer", 7) ||
- !strncmp(atacap->model, "SHARP", 5))) {
- bswap(atacap->model, sizeof(atacap->model));
- bswap(atacap->revision, sizeof(atacap->revision));
- bswap(atacap->serial, sizeof(atacap->serial));
- }
- btrim(atacap->model, sizeof(atacap->model));
- bpack(atacap->model, atacap->model, sizeof(atacap->model));
- btrim(atacap->revision, sizeof(atacap->revision));
- bpack(atacap->revision, atacap->revision, sizeof(atacap->revision));
- btrim(atacap->serial, sizeof(atacap->serial));
- bpack(atacap->serial, atacap->serial, sizeof(atacap->serial));
- if (bootverbose)
- ata_prtdev(atadev,
- "pio=0x%02x wdma=0x%02x udma=0x%02x cable=%spin\n",
- ata_pmode(atacap), ata_wmode(atacap),
- ata_umode(atacap),
- (atacap->hwres & ATA_CABLE_ID) ? "80":"40");
- }
- else {
- if (!error)
- error = ENXIO;
- if (atadev->param) {
- free(atadev->param, M_ATA);
- atadev->param = NULL;
- }
- }
+ default:
+ if (ata_ioctl_func)
+ error = ata_ioctl_func(iocmd);
}
return error;
}
static void
-ata_identify_devices(struct ata_channel *ch)
-{
- if (ch->devices & ATA_ATA_SLAVE) {
- if (ata_getparam(&ch->device[SLAVE], ATA_ATA_IDENTIFY))
- ch->devices &= ~ATA_ATA_SLAVE;
-#ifdef DEV_ATADISK
- else
- ch->device[SLAVE].attach = ad_attach;
-#endif
- }
- if (ch->devices & ATA_ATAPI_SLAVE) {
- if (ata_getparam(&ch->device[SLAVE], ATA_ATAPI_IDENTIFY))
- ch->devices &= ~ATA_ATAPI_SLAVE;
- else {
- ata_controlcmd(&ch->device[SLAVE], ATA_ATAPI_RESET, 0, 0, 0);
- switch (ch->device[SLAVE].param->config & ATA_ATAPI_TYPE_MASK) {
-#ifdef DEV_ATAPICD
- case ATA_ATAPI_TYPE_CDROM:
- ch->device[SLAVE].attach = acd_attach;
- break;
-#endif
-#ifdef DEV_ATAPIFD
- case ATA_ATAPI_TYPE_DIRECT:
- ch->device[SLAVE].attach = afd_attach;
- break;
-#endif
-#ifdef DEV_ATAPIST
- case ATA_ATAPI_TYPE_TAPE:
- ch->device[SLAVE].attach = ast_attach;
- break;
-#endif
- }
- }
- }
- if (ch->devices & ATA_ATA_MASTER) {
- if (ata_getparam(&ch->device[MASTER], ATA_ATA_IDENTIFY))
- ch->devices &= ~ATA_ATA_MASTER;
-#ifdef DEV_ATADISK
- else
- ch->device[MASTER].attach = ad_attach;
-#endif
- }
- if (ch->devices & ATA_ATAPI_MASTER) {
- if (ata_getparam(&ch->device[MASTER], ATA_ATAPI_IDENTIFY))
- ch->devices &= ~ATA_ATAPI_MASTER;
- else {
- ata_controlcmd(&ch->device[MASTER], ATA_ATAPI_RESET, 0, 0, 0);
- switch (ch->device[MASTER].param->config & ATA_ATAPI_TYPE_MASK) {
-#ifdef DEV_ATAPICD
- case ATA_ATAPI_TYPE_CDROM:
- ch->device[MASTER].attach = acd_attach;
- break;
-#endif
-#ifdef DEV_ATAPIFD
- case ATA_ATAPI_TYPE_DIRECT:
- ch->device[MASTER].attach = afd_attach;
- break;
-#endif
-#ifdef DEV_ATAPIST
- case ATA_ATAPI_TYPE_TAPE:
- ch->device[MASTER].attach = ast_attach;
- break;
-#endif
- }
- }
- }
-
- /* setup basic transfer mode by setting PIO mode and DMA if supported */
- if (ch->device[MASTER].param) {
- ch->device[MASTER].setmode(&ch->device[MASTER], ATA_PIO_MAX);
- if ((((ch->devices & ATA_ATAPI_MASTER) && atapi_dma &&
- (ch->device[MASTER].param->config&ATA_DRQ_MASK) != ATA_DRQ_INTR &&
- ata_umode(ch->device[MASTER].param) >= ATA_UDMA2) ||
- ((ch->devices & ATA_ATA_MASTER) && ata_dma)) && ch->dma)
- ch->device[MASTER].setmode(&ch->device[MASTER], ATA_DMA_MAX);
-
- }
- if (ch->device[SLAVE].param) {
- ch->device[SLAVE].setmode(&ch->device[SLAVE], ATA_PIO_MAX);
- if ((((ch->devices & ATA_ATAPI_SLAVE) && atapi_dma &&
- (ch->device[SLAVE].param->config&ATA_DRQ_MASK) != ATA_DRQ_INTR &&
- ata_umode(ch->device[SLAVE].param) >= ATA_UDMA2) ||
- ((ch->devices & ATA_ATA_SLAVE) && ata_dma)) && ch->dma)
- ch->device[SLAVE].setmode(&ch->device[SLAVE], ATA_DMA_MAX);
- }
-}
-
-static void
ata_boot_attach(void)
{
struct ata_channel *ch;
int ctlr;
+ /* release the hook that got us here, only needed during boot */
if (ata_delayed_attach) {
config_intrhook_disestablish(ata_delayed_attach);
free(ata_delayed_attach, M_TEMP);
ata_delayed_attach = NULL;
}
- /*
- * run through all ata devices and look for real ATA & ATAPI devices
- * using the hints we found in the early probe, this avoids some of
- * the delays probing of non-exsistent devices can cause.
- */
- for (ctlr=0; ctlr<devclass_get_maxunit(ata_devclass); ctlr++) {
- if (!(ch = devclass_get_softc(ata_devclass, ctlr)))
- continue;
- ata_identify_devices(ch);
- if (ch->device[MASTER].attach)
- ch->device[MASTER].attach(&ch->device[MASTER]);
- if (ch->device[SLAVE].attach)
- ch->device[SLAVE].attach(&ch->device[SLAVE]);
-#ifdef DEV_ATAPICAM
- atapi_cam_attach_bus(ch);
-#endif
+ /* kick of probe and attach on all channels */
+ for (ctlr = 0; ctlr < devclass_get_maxunit(ata_devclass); ctlr++) {
+ if ((ch = devclass_get_softc(ata_devclass, ctlr))) {
+ bus_generic_probe(ch->dev);
+ bus_generic_attach(ch->dev);
+ }
}
-#ifdef DEV_ATARAID
- ata_raid_attach();
-#endif
}
/*
* misc support functions
*/
-void
-ata_udelay(int interval)
-{
- if (interval < (1000000/hz) || ata_delayed_attach || ata_resuming)
- DELAY(interval);
- else
- tsleep(&interval, PRIBIO, "ataslp", interval/(1000000/hz));
-}
-
-static void
-bswap(int8_t *buf, int len)
-{
- u_int16_t *ptr = (u_int16_t*)(buf + len);
-
- while (--ptr >= (u_int16_t*)buf)
- *ptr = ntohs(*ptr);
-}
-
-static void
-btrim(int8_t *buf, int len)
-{
- int8_t *ptr;
-
- for (ptr = buf; ptr < buf+len; ++ptr)
- if (!*ptr || *ptr == '_')
- *ptr = ' ';
- for (ptr = buf + len - 1; ptr >= buf && *ptr == ' '; --ptr)
- *ptr = 0;
-}
-
-static void
-bpack(int8_t *src, int8_t *dst, int len)
+device_t
+ata_add_child(driver_t *driver, device_t parent, struct ata_device *atadev,
+ const char *name, int unit)
{
- int i, j, blank;
-
- for (i = j = blank = 0 ; i < len; i++) {
- if (blank && src[i] == ' ') continue;
- if (blank && src[i] != ' ') {
- dst[j++] = src[i];
- blank = 0;
- continue;
+ struct ata_channel *ch = device_get_softc(parent);
+ device_t child;
+
+ if ((child = device_add_child(parent, name, unit))) {
+ char buffer[64];
+
+ device_set_driver(child, driver);
+ device_set_softc(child, atadev);
+ sprintf(buffer, "%.40s/%.8s",
+ atadev->param.model, atadev->param.revision);
+ device_set_desc_copy(child, buffer);
+ device_quiet(child);
+ atadev->dev = child;
+ atadev->max_iosize = DEV_BSIZE;
+ atadev->mode = ATA_PIO_MAX;
+ if ((atadev->param.config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12) {
+ if (atapi_dma && ch->dma &&
+ (atadev->param.config & ATA_DRQ_MASK) != ATA_DRQ_INTR &&
+ ata_umode(&atadev->param) >= ATA_UDMA2)
+ atadev->mode = ATA_DMA_MAX;
}
- if (src[i] == ' ') {
- blank = 1;
- if (i == 0)
- continue;
+ else {
+ if (ata_dma && ch->dma)
+ atadev->mode = ATA_DMA_MAX;
}
- dst[j++] = src[i];
}
- if (j < len)
- dst[j] = 0x00;
+ return child;
}
-int
-ata_printf(struct ata_channel *ch, int device, const char * fmt, ...)
+void
+ata_identify(driver_t *driver, device_t parent, int type, const char *name)
{
- va_list ap;
- int ret;
+ struct ata_channel *ch = device_get_softc(parent);
+ struct ata_device *master, *slave;
+ int master_res = EIO, slave_res = EIO, master_unit = -1, slave_unit = -1;
- if (device == -1)
- ret = printf("ata%d: ", device_get_unit(ch->dev));
- else {
- if (ch->device[ATA_DEV(device)].name)
- ret = printf("%s: ", ch->device[ATA_DEV(device)].name);
- else
- ret = printf("ata%d-%s: ", device_get_unit(ch->dev),
- (device == ATA_MASTER) ? "master" : "slave");
+ if (!(master = malloc(sizeof(struct ata_device),
+ M_ATA, M_NOWAIT | M_ZERO))) {
+ device_printf(parent, "out of memory\n");
+ return;
}
- va_start(ap, fmt);
- ret += vprintf(fmt, ap);
- va_end(ap);
- return ret;
-}
-
-int
-ata_prtdev(struct ata_device *atadev, const char * fmt, ...)
-{
- va_list ap;
- int ret;
-
- if (atadev->name)
- ret = printf("%s: ", atadev->name);
- else
- ret = printf("ata%d-%s: ", device_get_unit(atadev->channel->dev),
- (atadev->unit == ATA_MASTER) ? "master" : "slave");
- va_start(ap, fmt);
- ret += vprintf(fmt, ap);
- va_end(ap);
- return ret;
-}
-
-void
-ata_set_name(struct ata_device *atadev, char *name, int lun)
-{
- atadev->name = malloc(strlen(name) + 4, M_ATA, M_NOWAIT);
- if (atadev->name)
- sprintf(atadev->name, "%s%d", name, lun);
-}
+ master->unit = ATA_MASTER;
+ if (!(slave = malloc(sizeof(struct ata_device),
+ M_ATA, M_NOWAIT | M_ZERO))) {
+ free(master, M_ATA);
+ device_printf(parent, "out of memory\n");
+ return;
+ }
+ slave->unit = ATA_SLAVE;
-void
-ata_free_name(struct ata_device *atadev)
-{
- if (atadev->name)
- free(atadev->name, M_ATA);
- atadev->name = NULL;
-}
+ /* wait for the channel to be IDLE then grab it before touching HW */
+ while (ATA_LOCKING(device_get_parent(parent),parent,ATA_LF_LOCK)!=ch->unit)
+ tsleep(ch, PRIBIO, "ataidnt2", 1);
+ while (1) {
+ mtx_lock(&ch->state_mtx);
+ if (ch->state == ATA_IDLE) {
+ ch->state = ATA_ACTIVE;
+ mtx_unlock(&ch->state_mtx);
+ break;
+ }
+ mtx_unlock(&ch->state_mtx);
+ tsleep(ch, PRIBIO, "ataidnt1", 1);
+ }
-int
-ata_get_lun(u_int32_t *map)
-{
- int lun = ffs(~*map) - 1;
+ if (type < 0) {
+ if (ch->devices & ATA_ATA_SLAVE)
+ slave_res = ata_getparam(parent, slave, ATA_ATA_IDENTIFY);
+ if (ch->devices & ATA_ATA_MASTER)
+ master_res = ata_getparam(parent, master, ATA_ATA_IDENTIFY);
+#ifdef ATA_STATIC_ID
+ master_unit = (device_get_unit(parent) << 1);
+ slave_unit = (device_get_unit(parent) << 1) + 1;
+#endif
+ }
+ else {
+ if (ch->devices & ATA_ATAPI_SLAVE)
+ slave_res = ata_getparam(parent, slave, ATA_ATAPI_IDENTIFY);
+ if (ch->devices & ATA_ATAPI_MASTER)
+ master_res = ata_getparam(parent, master, ATA_ATAPI_IDENTIFY);
+ }
- *map |= (1 << lun);
- return lun;
-}
+ if (master_res ||
+ !(type < 0 || (master->param.config & ATA_ATAPI_TYPE_MASK) == type) ||
+ !ata_add_child(driver, parent, master, name, master_unit))
+ free(master, M_ATA);
+
+ if (slave_res ||
+ !(type < 0 || (slave->param.config & ATA_ATAPI_TYPE_MASK) == type) ||
+ !ata_add_child(driver, parent, slave, name, slave_unit))
+ free(slave, M_ATA);
-int
-ata_test_lun(u_int32_t *map, int lun)
-{
- return (*map & (1 << lun));
+ mtx_lock(&ch->state_mtx);
+ ch->state = ATA_IDLE;
+ mtx_unlock(&ch->state_mtx);
+ ATA_LOCKING(device_get_parent(parent), parent, ATA_LF_UNLOCK);
}
void
-ata_free_lun(u_int32_t *map, int lun)
+ata_udelay(int interval)
{
- *map &= ~(1 << lun);
+ /* for now just use DELAY, the timer/sleep subsytems are not there yet */
+ if (1 || interval < (1000000/hz) || ata_delayed_attach)
+ DELAY(interval);
+ else
+ tsleep(&interval, PRIBIO, "ataslp", interval/(1000000/hz));
}
char *
ata_mode2str(int mode)
{
switch (mode) {
- case ATA_PIO: return "BIOSPIO";
case ATA_PIO0: return "PIO0";
case ATA_PIO1: return "PIO1";
case ATA_PIO2: return "PIO2";
case ATA_PIO3: return "PIO3";
case ATA_PIO4: return "PIO4";
- case ATA_DMA: return "BIOSDMA";
case ATA_WDMA0: return "WDMA0";
case ATA_WDMA1: return "WDMA1";
case ATA_WDMA2: return "WDMA2";
@@ -992,7 +698,11 @@ ata_mode2str(int mode)
case ATA_UDMA5: return "UDMA100";
case ATA_UDMA6: return "UDMA133";
case ATA_SA150: return "SATA150";
- default: return "???";
+ default:
+ if (mode & ATA_DMA_MASK)
+ return "BIOSDMA";
+ else
+ return "BIOSPIO";
}
}
@@ -1060,44 +770,67 @@ ata_limit_mode(struct ata_device *atadev, int mode, int maxmode)
if (maxmode && mode > maxmode)
mode = maxmode;
- if (mode >= ATA_UDMA0 && ata_umode(atadev->param) > 0)
- return min(mode, ata_umode(atadev->param));
+ if (mode >= ATA_UDMA0 && ata_umode(&atadev->param) > 0)
+ return min(mode, ata_umode(&atadev->param));
- if (mode >= ATA_WDMA0 && ata_wmode(atadev->param) > 0)
- return min(mode, ata_wmode(atadev->param));
+ if (mode >= ATA_WDMA0 && ata_wmode(&atadev->param) > 0)
+ return min(mode, ata_wmode(&atadev->param));
- if (mode > ata_pmode(atadev->param))
- return min(mode, ata_pmode(atadev->param));
+ if (mode > ata_pmode(&atadev->param))
+ return min(mode, ata_pmode(&atadev->param));
return mode;
}
-static void
-ata_init(void)
+/*
+ * module handeling
+ */
+static int
+ata_module_event_handler(module_t mod, int what, void *arg)
{
- /* register controlling device */
- make_dev(&ata_cdevsw, 0, UID_ROOT, GID_OPERATOR, 0600, "ata");
-
- /* register boot attach to be run when interrupts are enabled */
- if (!(ata_delayed_attach = (struct intr_config_hook *)
- malloc(sizeof(struct intr_config_hook),
- M_TEMP, M_NOWAIT | M_ZERO))) {
- printf("ata: malloc of delayed attach hook failed\n");
- return;
- }
- ata_delayed_attach->ich_func = (void*)ata_boot_attach;
- if (config_intrhook_establish(ata_delayed_attach) != 0) {
- printf("ata: config_intrhook_establish failed\n");
- free(ata_delayed_attach, M_TEMP);
+ static struct cdev *atacdev;
+
+ switch (what) {
+ case MOD_LOAD:
+ /* register controlling device */
+ atacdev = make_dev(&ata_cdevsw, 0, UID_ROOT, GID_OPERATOR, 0600, "ata");
+
+ if (cold) {
+ /* register boot attach to be run when interrupts are enabled */
+ if (!(ata_delayed_attach = (struct intr_config_hook *)
+ malloc(sizeof(struct intr_config_hook),
+ M_TEMP, M_NOWAIT | M_ZERO))) {
+ printf("ata: malloc of delayed attach hook failed\n");
+ return EIO;
+ }
+ ata_delayed_attach->ich_func = (void*)ata_boot_attach;
+ if (config_intrhook_establish(ata_delayed_attach) != 0) {
+ printf("ata: config_intrhook_establish failed\n");
+ free(ata_delayed_attach, M_TEMP);
+ }
+ }
+ return 0;
+
+ case MOD_UNLOAD:
+ /* deregister controlling device */
+ destroy_dev(atacdev);
+ return 0;
+
+ default:
+ return EOPNOTSUPP;
}
+}
- /* register handler to flush write caches on shutdown */
- if ((EVENTHANDLER_REGISTER(shutdown_post_sync, ata_shutdown,
- NULL, SHUTDOWN_PRI_DEFAULT)) == NULL)
- printf("ata: shutdown event registration failed!\n");
+static moduledata_t ata_moduledata = { "ata", ata_module_event_handler, NULL };
+DECLARE_MODULE(ata, ata_moduledata, SI_SUB_CONFIGURE, SI_ORDER_SECOND);
+MODULE_VERSION(ata, 1);
+static void
+ata_init(void)
+{
/* init our UMA zone for ATA requests */
ata_zone = uma_zcreate("ata_request", sizeof(struct ata_request),
NULL, NULL, NULL, NULL, 0, 0);
}
+
SYSINIT(atadev, SI_SUB_DRIVERS, SI_ORDER_SECOND, ata_init, NULL)
diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h
index 6a9d099..72608e3 100644
--- a/sys/dev/ata/ata-all.h
+++ b/sys/dev/ata/ata-all.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2004 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2005 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,220 +29,235 @@
*/
/* ATA register defines */
-#define ATA_DATA 0x00 /* data register */
-
-#define ATA_ERROR 0x01 /* (R) error register */
-#define ATA_E_ILI 0x01 /* illegal length */
-#define ATA_E_NM 0x02 /* no media */
-#define ATA_E_ABORT 0x04 /* command aborted */
-#define ATA_E_MCR 0x08 /* media change request */
-#define ATA_E_IDNF 0x10 /* ID not found */
-#define ATA_E_MC 0x20 /* media changed */
-#define ATA_E_UNC 0x40 /* uncorrectable data */
-#define ATA_E_ICRC 0x80 /* UDMA crc error */
-#define ATA_E_MASK 0x0f /* error mask */
-#define ATA_SK_MASK 0xf0 /* sense key mask */
-#define ATA_SK_NO_SENSE 0x00 /* no specific sense key info */
-#define ATA_SK_RECOVERED_ERROR 0x10 /* command OK, data recovered */
-#define ATA_SK_NOT_READY 0x20 /* no access to drive */
-#define ATA_SK_MEDIUM_ERROR 0x30 /* non-recovered data error */
-#define ATA_SK_HARDWARE_ERROR 0x40 /* non-recoverable HW failure */
-#define ATA_SK_ILLEGAL_REQUEST 0x50 /* invalid command param(s) */
-#define ATA_SK_UNIT_ATTENTION 0x60 /* media changed */
-#define ATA_SK_DATA_PROTECT 0x70 /* write protect */
-#define ATA_SK_BLANK_CHECK 0x80 /* blank check */
-#define ATA_SK_VENDOR_SPECIFIC 0x90 /* vendor specific skey */
-#define ATA_SK_COPY_ABORTED 0xa0 /* copy aborted */
-#define ATA_SK_ABORTED_COMMAND 0xb0 /* command aborted, try again */
-#define ATA_SK_EQUAL 0xc0 /* equal */
-#define ATA_SK_VOLUME_OVERFLOW 0xd0 /* volume overflow */
-#define ATA_SK_MISCOMPARE 0xe0 /* data dont match the medium */
-#define ATA_SK_RESERVED 0xf0
-
-#define ATA_FEATURE 0x01 /* (W) feature register */
-#define ATA_F_DMA 0x01 /* enable DMA */
-#define ATA_F_OVL 0x02 /* enable overlap */
-
-#define ATA_COUNT 0x02 /* (W) sector count */
-#define ATA_IREASON 0x02 /* (R) interrupt reason */
-#define ATA_I_CMD 0x01 /* cmd (1) | data (0) */
-#define ATA_I_IN 0x02 /* read (1) | write (0) */
-#define ATA_I_RELEASE 0x04 /* released bus (1) */
-#define ATA_I_TAGMASK 0xf8 /* tag mask */
-
-#define ATA_SECTOR 0x03 /* sector # */
-#define ATA_CYL_LSB 0x04 /* cylinder# LSB */
-#define ATA_CYL_MSB 0x05 /* cylinder# MSB */
-#define ATA_DRIVE 0x06 /* Sector/Drive/Head register */
-#define ATA_D_LBA 0x40 /* use LBA addressing */
-#define ATA_D_IBM 0xa0 /* 512 byte sectors, ECC */
-
-#define ATA_CMD 0x07 /* command register */
-
-#define ATA_STATUS 0x07 /* status register */
-#define ATA_S_ERROR 0x01 /* error */
-#define ATA_S_INDEX 0x02 /* index */
-#define ATA_S_CORR 0x04 /* data corrected */
-#define ATA_S_DRQ 0x08 /* data request */
-#define ATA_S_DSC 0x10 /* drive seek completed */
-#define ATA_S_SERVICE 0x10 /* drive needs service */
-#define ATA_S_DWF 0x20 /* drive write fault */
-#define ATA_S_DMA 0x20 /* DMA ready */
-#define ATA_S_READY 0x40 /* drive ready */
-#define ATA_S_BUSY 0x80 /* busy */
-
-#define ATA_ALTSTAT 0x08 /* alternate status register */
-#define ATA_ALTOFFSET 0x206 /* alternate registers offset */
-#define ATA_PCCARD_ALTOFFSET 0x0e /* do for PCCARD devices */
-#define ATA_PC98_ALTOFFSET 0x10c /* do for PC98 devices */
-#define ATA_A_IDS 0x02 /* disable interrupts */
-#define ATA_A_RESET 0x04 /* RESET controller */
-#define ATA_A_4BIT 0x08 /* 4 head bits */
+#define ATA_DATA 0x00 /* data register */
+
+#define ATA_ERROR 0x01 /* (R) error register */
+#define ATA_E_ILI 0x01 /* illegal length */
+#define ATA_E_NM 0x02 /* no media */
+#define ATA_E_ABORT 0x04 /* command aborted */
+#define ATA_E_MCR 0x08 /* media change request */
+#define ATA_E_IDNF 0x10 /* ID not found */
+#define ATA_E_MC 0x20 /* media changed */
+#define ATA_E_UNC 0x40 /* uncorrectable data */
+#define ATA_E_ICRC 0x80 /* UDMA crc error */
+#define ATA_E_MASK 0x0f /* error mask */
+#define ATA_SK_MASK 0xf0 /* sense key mask */
+#define ATA_SK_NO_SENSE 0x00 /* no specific sense key info */
+#define ATA_SK_RECOVERED_ERROR 0x10 /* command OK, data recovered */
+#define ATA_SK_NOT_READY 0x20 /* no access to drive */
+#define ATA_SK_MEDIUM_ERROR 0x30 /* non-recovered data error */
+#define ATA_SK_HARDWARE_ERROR 0x40 /* non-recoverable HW failure */
+#define ATA_SK_ILLEGAL_REQUEST 0x50 /* invalid command param(s) */
+#define ATA_SK_UNIT_ATTENTION 0x60 /* media changed */
+#define ATA_SK_DATA_PROTECT 0x70 /* write protect */
+#define ATA_SK_BLANK_CHECK 0x80 /* blank check */
+#define ATA_SK_VENDOR_SPECIFIC 0x90 /* vendor specific skey */
+#define ATA_SK_COPY_ABORTED 0xa0 /* copy aborted */
+#define ATA_SK_ABORTED_COMMAND 0xb0 /* command aborted, try again */
+#define ATA_SK_EQUAL 0xc0 /* equal */
+#define ATA_SK_VOLUME_OVERFLOW 0xd0 /* volume overflow */
+#define ATA_SK_MISCOMPARE 0xe0 /* data dont match the medium */
+#define ATA_SK_RESERVED 0xf0
+
+#define ATA_FEATURE 0x01 /* (W) feature register */
+#define ATA_F_DMA 0x01 /* enable DMA */
+#define ATA_F_OVL 0x02 /* enable overlap */
+
+#define ATA_COUNT 0x02 /* (W) sector count */
+#define ATA_IREASON 0x02 /* (R) interrupt reason */
+#define ATA_I_CMD 0x01 /* cmd (1) | data (0) */
+#define ATA_I_IN 0x02 /* read (1) | write (0) */
+#define ATA_I_RELEASE 0x04 /* released bus (1) */
+#define ATA_I_TAGMASK 0xf8 /* tag mask */
+
+#define ATA_SECTOR 0x03 /* sector # */
+#define ATA_CYL_LSB 0x04 /* cylinder# LSB */
+#define ATA_CYL_MSB 0x05 /* cylinder# MSB */
+#define ATA_DRIVE 0x06 /* Sector/Drive/Head register */
+#define ATA_D_LBA 0x40 /* use LBA addressing */
+#define ATA_D_IBM 0xa0 /* 512 byte sectors, ECC */
+
+#define ATA_CMD 0x07 /* command register */
+
+#define ATA_STATUS 0x07 /* status register */
+#define ATA_S_ERROR 0x01 /* error */
+#define ATA_S_INDEX 0x02 /* index */
+#define ATA_S_CORR 0x04 /* data corrected */
+#define ATA_S_DRQ 0x08 /* data request */
+#define ATA_S_DSC 0x10 /* drive seek completed */
+#define ATA_S_SERVICE 0x10 /* drive needs service */
+#define ATA_S_DWF 0x20 /* drive write fault */
+#define ATA_S_DMA 0x20 /* DMA ready */
+#define ATA_S_READY 0x40 /* drive ready */
+#define ATA_S_BUSY 0x80 /* busy */
+
+#define ATA_ALTSTAT 0x08 /* alternate status register */
+#define ATA_ALTOFFSET 0x206 /* alternate registers offset */
+#define ATA_PCCARD_ALTOFFSET 0x0e /* do for PCCARD devices */
+#define ATA_PC98_ALTOFFSET 0x10c /* do for PC98 devices */
+#define ATA_A_IDS 0x02 /* disable interrupts */
+#define ATA_A_RESET 0x04 /* RESET controller */
+#define ATA_A_4BIT 0x08 /* 4 head bits */
+#define ATA_A_HOB 0x80 /* High Order Byte enable */
/* ATAPI misc defines */
-#define ATAPI_MAGIC_LSB 0x14
-#define ATAPI_MAGIC_MSB 0xeb
-#define ATAPI_P_READ (ATA_S_DRQ | ATA_I_IN)
-#define ATAPI_P_WRITE (ATA_S_DRQ)
-#define ATAPI_P_CMDOUT (ATA_S_DRQ | ATA_I_CMD)
-#define ATAPI_P_DONEDRQ (ATA_S_DRQ | ATA_I_CMD | ATA_I_IN)
-#define ATAPI_P_DONE (ATA_I_CMD | ATA_I_IN)
-#define ATAPI_P_ABORT 0
+#define ATAPI_MAGIC_LSB 0x14
+#define ATAPI_MAGIC_MSB 0xeb
+#define ATAPI_P_READ (ATA_S_DRQ | ATA_I_IN)
+#define ATAPI_P_WRITE (ATA_S_DRQ)
+#define ATAPI_P_CMDOUT (ATA_S_DRQ | ATA_I_CMD)
+#define ATAPI_P_DONEDRQ (ATA_S_DRQ | ATA_I_CMD | ATA_I_IN)
+#define ATAPI_P_DONE (ATA_I_CMD | ATA_I_IN)
+#define ATAPI_P_ABORT 0
/* misc defines */
-#define ATA_PRIMARY 0x1f0
-#define ATA_SECONDARY 0x170
-#define ATA_PC98_BANK 0x432
-#define ATA_IOSIZE 0x08
-#define ATA_PC98_IOSIZE 0x10
-#define ATA_ALTIOSIZE 0x01
-#define ATA_BMIOSIZE 0x08
-#define ATA_PC98_BANKIOSIZE 0x01
-#define ATA_IOADDR_RID 0
-#define ATA_ALTADDR_RID 1
-#define ATA_BMADDR_RID 0x20
-#define ATA_PC98_ALTADDR_RID 8
-#define ATA_PC98_BANKADDR_RID 9
-
-#define ATA_IRQ_RID 0
-#define ATA_DEV(device) ((device == ATA_MASTER) ? 0 : 1)
+#define ATA_PRIMARY 0x1f0
+#define ATA_SECONDARY 0x170
+#define ATA_PC98_BANK 0x432
+#define ATA_IOSIZE 0x08
+#define ATA_PC98_IOSIZE 0x10
+#define ATA_ALTIOSIZE 0x01
+#define ATA_BMIOSIZE 0x08
+#define ATA_PC98_BANKIOSIZE 0x01
+#define ATA_IOADDR_RID 0
+#define ATA_ALTADDR_RID 1
+#define ATA_BMADDR_RID 0x20
+#define ATA_PC98_ALTADDR_RID 8
+#define ATA_PC98_BANKADDR_RID 9
+
+#define ATA_IRQ_RID 0
+#define ATA_DEV(device) ((device == ATA_MASTER) ? 0 : 1)
/* busmaster DMA related defines */
-#define ATA_DMA_ENTRIES 256
-#define ATA_DMA_EOT 0x80000000
+#define ATA_DMA_ENTRIES 256
+#define ATA_DMA_EOT 0x80000000
-#define ATA_BMCMD_PORT 0x09
-#define ATA_BMCMD_START_STOP 0x01
-#define ATA_BMCMD_WRITE_READ 0x08
+#define ATA_BMCMD_PORT 0x09
+#define ATA_BMCMD_START_STOP 0x01
+#define ATA_BMCMD_WRITE_READ 0x08
-#define ATA_BMDEVSPEC_0 0x0a
-#define ATA_BMSTAT_PORT 0x0b
-#define ATA_BMSTAT_ACTIVE 0x01
-#define ATA_BMSTAT_ERROR 0x02
-#define ATA_BMSTAT_INTERRUPT 0x04
-#define ATA_BMSTAT_MASK 0x07
-#define ATA_BMSTAT_DMA_MASTER 0x20
-#define ATA_BMSTAT_DMA_SLAVE 0x40
-#define ATA_BMSTAT_DMA_SIMPLEX 0x80
+#define ATA_BMDEVSPEC_0 0x0a
+#define ATA_BMSTAT_PORT 0x0b
+#define ATA_BMSTAT_ACTIVE 0x01
+#define ATA_BMSTAT_ERROR 0x02
+#define ATA_BMSTAT_INTERRUPT 0x04
+#define ATA_BMSTAT_MASK 0x07
+#define ATA_BMSTAT_DMA_MASTER 0x20
+#define ATA_BMSTAT_DMA_SLAVE 0x40
+#define ATA_BMSTAT_DMA_SIMPLEX 0x80
-#define ATA_BMDEVSPEC_1 0x0c
-#define ATA_BMDTP_PORT 0x0d
+#define ATA_BMDEVSPEC_1 0x0c
+#define ATA_BMDTP_PORT 0x0d
-#define ATA_IDX_ADDR 0x0e
-#define ATA_IDX_DATA 0x0f
-#define ATA_MAX_RES 0x10
+#define ATA_IDX_ADDR 0x0e
+#define ATA_IDX_DATA 0x0f
+#define ATA_MAX_RES 0x10
-#define ATA_INTR_FLAGS (INTR_MPSAFE|INTR_TYPE_BIO|INTR_ENTROPY)
-#define ATA_OP_CONTINUES 0
-#define ATA_OP_FINISHED 1
+#define ATA_INTR_FLAGS (INTR_MPSAFE|INTR_TYPE_BIO|INTR_ENTROPY)
+#define ATA_OP_CONTINUES 0
+#define ATA_OP_FINISHED 1
-#define ATA_MAX_28BIT_LBA 268435455
+#define ATA_MAX_28BIT_LBA 268435455
/* ATAPI request sense structure */
struct atapi_sense {
- u_int8_t error_code :7; /* current or deferred errors */
- u_int8_t valid :1; /* follows ATAPI spec */
- u_int8_t segment; /* Segment number */
- u_int8_t sense_key :4; /* sense key */
- u_int8_t reserved2_4 :1; /* reserved */
- u_int8_t ili :1; /* incorrect length indicator */
- u_int8_t eom :1; /* end of medium */
- u_int8_t filemark :1; /* filemark */
- u_int32_t cmd_info __packed; /* cmd information */
- u_int8_t sense_length; /* additional sense len (n-7) */
- u_int32_t cmd_specific_info __packed; /* additional cmd spec info */
- u_int8_t asc; /* additional sense code */
- u_int8_t ascq; /* additional sense code qual */
- u_int8_t replaceable_unit_code; /* replaceable unit code */
- u_int8_t sk_specific :7; /* sense key specific */
- u_int8_t sksv :1; /* sense key specific info OK */
- u_int8_t sk_specific1; /* sense key specific */
- u_int8_t sk_specific2; /* sense key specific */
+ u_int8_t error_code :7; /* current or deferred errors */
+ u_int8_t valid :1; /* follows ATAPI spec */
+ u_int8_t segment; /* Segment number */
+ u_int8_t sense_key :4; /* sense key */
+ u_int8_t reserved2_4 :1; /* reserved */
+ u_int8_t ili :1; /* incorrect length indicator */
+ u_int8_t eom :1; /* end of medium */
+ u_int8_t filemark :1; /* filemark */
+ u_int32_t cmd_info __packed; /* cmd information */
+ u_int8_t sense_length; /* additional sense len (n-7) */
+ u_int32_t cmd_specific_info __packed; /* additional cmd spec info */
+ u_int8_t asc; /* additional sense code */
+ u_int8_t ascq; /* additional sense code qual */
+ u_int8_t replaceable_unit_code; /* replaceable unit code */
+ u_int8_t sk_specific :7; /* sense key specific */
+ u_int8_t sksv :1; /* sense key specific info OK */
+ u_int8_t sk_specific1; /* sense key specific */
+ u_int8_t sk_specific2; /* sense key specific */
};
-struct ata_request {
- struct ata_device *device; /* ptr to device softc */
- void *driver; /* driver specific */
+/* structure used for composite atomic operations */
+struct ata_composite {
+ struct mtx lock; /* control lock */
+ u_int32_t rd_needed; /* needed read subdisks */
+ u_int32_t rd_done; /* done read subdisks */
+ u_int32_t wr_needed; /* needed write subdisks */
+ u_int32_t wr_depend; /* write depends on subdisks */
+ u_int32_t wr_done; /* done write subdisks */
+ struct ata_request *request[32]; /* size must match maps above */
+ caddr_t data_1;
+ caddr_t data_2;
+};
+/* structure used to queue an ATA/ATAPI request */
+struct ata_request {
+ device_t dev; /* device handle */
union {
struct {
- u_int8_t command; /* command reg */
- u_int8_t feature; /* feature reg */
- u_int16_t count; /* count reg */
- u_int64_t lba; /* lba reg */
+ u_int8_t command; /* command reg */
+ u_int8_t feature; /* feature reg */
+ u_int16_t count; /* count reg */
+ u_int64_t lba; /* lba reg */
} ata;
struct {
- u_int8_t ccb[16]; /* ATAPI command block */
- struct atapi_sense sense_data; /* ATAPI request sense data */
- u_int8_t sense_key; /* ATAPI request sense key */
- u_int8_t sense_cmd; /* ATAPI saved command */
+ u_int8_t ccb[16]; /* ATAPI command block */
+ struct atapi_sense sense_data; /* ATAPI request sense data */
+ u_int8_t sense_key; /* ATAPI request sense key */
+ u_int8_t sense_cmd; /* ATAPI saved command */
} atapi;
} u;
-
- u_int8_t status; /* ATA status */
- u_int8_t error; /* ATA error */
- u_int8_t dmastat; /* DMA status */
-
- u_int32_t bytecount; /* bytes to transfer */
- u_int32_t transfersize; /* bytes pr transfer */
- u_int32_t donecount; /* bytes transferred */
- caddr_t data; /* pointer to data buf */
- int flags;
-#define ATA_R_CONTROL 0x0001
-#define ATA_R_READ 0x0002
-#define ATA_R_WRITE 0x0004
-#define ATA_R_DMA 0x0008
-
-#define ATA_R_ATAPI 0x0010
-#define ATA_R_QUIET 0x0020
-#define ATA_R_INTR_SEEN 0x0040
-#define ATA_R_TIMEOUT 0x0080
-
-#define ATA_R_ORDERED 0x0100
-#define ATA_R_IMMEDIATE 0x0200
-#define ATA_R_REQUEUE 0x0400
-
-#define ATA_R_DEBUG 0x1000
-
- void (*callback)(struct ata_request *request);
- struct sema done; /* request done sema */
- int retries; /* retry count */
- int timeout; /* timeout for this cmd */
- struct callout callout; /* callout management */
- int result; /* result error code */
- struct task task; /* task management */
- struct bio *bio; /* bio for this request */
- TAILQ_ENTRY(ata_request) sequence; /* sequence management */
- TAILQ_ENTRY(ata_request) chain; /* list management */
+ u_int32_t bytecount; /* bytes to transfer */
+ u_int32_t transfersize; /* bytes pr transfer */
+ caddr_t data; /* pointer to data buf */
+ int flags;
+#define ATA_R_CONTROL 0x00000001
+#define ATA_R_READ 0x00000002
+#define ATA_R_WRITE 0x00000004
+#define ATA_R_DMA 0x00000008
+
+#define ATA_R_ATAPI 0x00000010
+#define ATA_R_QUIET 0x00000020
+#define ATA_R_INTR_SEEN 0x00000040
+#define ATA_R_TIMEOUT 0x00000080
+
+#define ATA_R_ORDERED 0x00000100
+#define ATA_R_AT_HEAD 0x00000200
+#define ATA_R_REQUEUE 0x00000400
+#define ATA_R_THREAD 0x00000800
+#define ATA_R_DIRECT 0x00001000
+
+#define ATA_R_DEBUG 0x10000000
+
+ u_int8_t status; /* ATA status */
+ u_int8_t error; /* ATA error */
+ u_int8_t dmastat; /* DMA status */
+ u_int32_t donecount; /* bytes transferred */
+ int result; /* result error code */
+ void (*callback)(struct ata_request *request);
+ struct sema done; /* request done sema */
+ int retries; /* retry count */
+ int timeout; /* timeout for this cmd */
+ struct callout callout; /* callout management */
+ struct task task; /* task management */
+ struct bio *bio; /* bio for this request */
+ int this; /* this request ID */
+ struct ata_composite *composite; /* for composite atomic ops */
+ void *driver; /* driver specific */
+ TAILQ_ENTRY(ata_request) chain; /* list management */
};
/* define this for debugging request processing */
-#if 0
+#if 1
#define ATA_DEBUG_RQ(request, string) \
{ \
if (request->flags & ATA_R_DEBUG) \
- ata_prtdev(request->device, "req=%p %s " string "\n", \
- request, ata_cmd2str(request)); \
+ device_printf(request->dev, "req=%p %s " string "\n", \
+ request, ata_cmd2str(request)); \
}
#else
#define ATA_DEBUG_RQ(request, string)
@@ -251,27 +266,19 @@ struct ata_request {
/* structure describing an ATA/ATAPI device */
struct ata_device {
- struct ata_channel *channel;
- int unit; /* unit number */
-#define ATA_MASTER 0x00
-#define ATA_SLAVE 0x10
-
- char *name; /* device name */
- struct ata_params *param; /* ata param structure */
- void *softc; /* ptr to softc for device */
- void (*attach)(struct ata_device *atadev);
- void (*detach)(struct ata_device *atadev);
- void (*config)(struct ata_device *atadev);
- void (*start)(struct ata_device *atadev);
- int flags;
-#define ATA_D_USE_CHS 0x0001
-#define ATA_D_DETACHING 0x0002
-#define ATA_D_MEDIA_CHANGED 0x0004
-#define ATA_D_ENC_PRESENT 0x0008
-
- int cmd; /* last cmd executed */
- int mode; /* transfermode */
- void (*setmode)(struct ata_device *atadev, int mode);
+ device_t dev; /* device handle */
+ int unit; /* physical unit */
+#define ATA_MASTER 0x00
+#define ATA_SLAVE 0x10
+
+ struct ata_params param; /* ata param structure */
+ int mode; /* current transfermode */
+ u_int32_t max_iosize; /* max IO size */
+ int cmd; /* last cmd executed */
+ int flags;
+#define ATA_D_USE_CHS 0x0001
+#define ATA_D_MEDIA_CHANGED 0x0002
+#define ATA_D_ENC_PRESENT 0x0004
};
/* structure for holding DMA Physical Region Descriptors (PRD) entries */
@@ -286,28 +293,29 @@ struct ata_dmasetprd_args {
int error;
};
+struct ata_channel {};
/* structure holding DMA related information */
struct ata_dma {
- bus_dma_tag_t dmatag; /* parent DMA tag */
- bus_dma_tag_t cdmatag; /* control DMA tag */
- bus_dmamap_t cdmamap; /* control DMA map */
- bus_dma_tag_t ddmatag; /* data DMA tag */
- bus_dmamap_t ddmamap; /* data DMA map */
- void *dmatab; /* DMA transfer table */
- bus_addr_t mdmatab; /* bus address of dmatab */
- bus_dma_tag_t wdmatag; /* workspace DMA tag */
- bus_dmamap_t wdmamap; /* workspace DMA map */
- u_int8_t *workspace; /* workspace */
- bus_addr_t wdmatab; /* bus address of dmatab */
-
- u_int32_t alignment; /* DMA engine alignment */
- u_int32_t boundary; /* DMA engine boundary */
- u_int32_t max_iosize; /* DMA engine max IO size */
- u_int32_t cur_iosize; /* DMA engine current IO size */
- int flags;
-#define ATA_DMA_READ 0x01 /* transaction is a read */
-#define ATA_DMA_LOADED 0x02 /* DMA tables etc loaded */
-#define ATA_DMA_ACTIVE 0x04 /* DMA transfer in progress */
+ bus_dma_tag_t dmatag; /* parent DMA tag */
+ bus_dma_tag_t sg_tag; /* SG list DMA tag */
+ bus_dmamap_t sg_map; /* SG list DMA map */
+ void *sg; /* DMA transfer table */
+ bus_addr_t sg_bus; /* bus address of dmatab */
+ bus_dma_tag_t data_tag; /* data DMA tag */
+ bus_dmamap_t data_map; /* data DMA map */
+ bus_dma_tag_t work_tag; /* workspace DMA tag */
+ bus_dmamap_t work_map; /* workspace DMA map */
+ u_int8_t *work; /* workspace */
+ bus_addr_t work_bus; /* bus address of dmatab */
+
+ u_int32_t alignment; /* DMA engine alignment */
+ u_int32_t boundary; /* DMA engine boundary */
+ u_int32_t max_iosize; /* DMA engine max IO size */
+ u_int32_t cur_iosize; /* DMA engine current IO size */
+ int flags;
+#define ATA_DMA_READ 0x01 /* transaction is a read */
+#define ATA_DMA_LOADED 0x02 /* DMA tables etc loaded */
+#define ATA_DMA_ACTIVE 0x04 /* DMA transfer in progress */
void (*alloc)(struct ata_channel *ch);
void (*free)(struct ata_channel *ch);
@@ -322,70 +330,59 @@ struct ata_dma {
struct ata_lowlevel {
int (*begin_transaction)(struct ata_request *request);
int (*end_transaction)(struct ata_request *request);
- void (*interrupt)(void *channel);
void (*reset)(struct ata_channel *ch);
int (*command)(struct ata_device *atadev, u_int8_t command, u_int64_t lba, u_int16_t count, u_int16_t feature);
};
/* structure holding resources for an ATA channel */
struct ata_resource {
- struct resource *res;
- int offset;
+ struct resource *res;
+ int offset;
};
/* structure describing an ATA channel */
struct ata_channel {
- struct device *dev; /* device handle */
- int unit; /* channel number */
- struct ata_resource r_io[ATA_MAX_RES];/* I/O resources */
- struct resource *r_irq; /* interrupt of this channel */
- void *ih; /* interrupt handle */
- struct ata_lowlevel hw; /* lowlevel HW functions */
- struct ata_dma *dma; /* DMA data / functions */
- int flags; /* channel flags */
-#define ATA_NO_SLAVE 0x01
-#define ATA_USE_16BIT 0x02
-#define ATA_ATAPI_DMA_RO 0x04
-#define ATA_48BIT_ACTIVE 0x10
-#define ATA_IMMEDIATE_MODE 0x20
-#define ATA_HWGONE 0x40
-
- struct ata_device device[2]; /* devices on this channel */
-#define MASTER 0x00
-#define SLAVE 0x01
-
- int devices; /* what is present */
-#define ATA_ATA_MASTER 0x01
-#define ATA_ATA_SLAVE 0x02
-#define ATA_ATAPI_MASTER 0x04
-#define ATA_ATAPI_SLAVE 0x08
-
- struct mtx state_mtx; /* state lock */
- int state; /* ATA channel state */
-#define ATA_IDLE 0x0000
-#define ATA_ACTIVE 0x0001
-#define ATA_INTERRUPT 0x0002
-#define ATA_TIMEOUT 0x0004
-
- void (*reset)(struct ata_channel *);
- int (*locking)(struct ata_channel *, int);
-#define ATA_LF_LOCK 0x0001
-#define ATA_LF_UNLOCK 0x0002
-#define ATA_LF_WHICH 0x0004
-
- struct mtx queue_mtx; /* queue lock */
- TAILQ_HEAD(, ata_request) ata_queue; /* head of ATA queue */
- struct ata_request *running; /* currently running request */
+ device_t dev; /* device handle */
+ int unit; /* physical channel */
+ struct ata_resource r_io[ATA_MAX_RES];/* I/O resources */
+ struct resource *r_irq; /* interrupt of this channel */
+ void *ih; /* interrupt handle */
+ struct ata_lowlevel hw; /* lowlevel HW functions */
+ struct ata_dma *dma; /* DMA data / functions */
+ int flags; /* channel flags */
+#define ATA_NO_SLAVE 0x01
+#define ATA_USE_16BIT 0x02
+#define ATA_ATAPI_DMA_RO 0x04
+#define ATA_48BIT_ACTIVE 0x08
+
+ int devices; /* what is present */
+#define ATA_ATA_MASTER 0x01
+#define ATA_ATA_SLAVE 0x02
+#define ATA_ATAPI_MASTER 0x04
+#define ATA_ATAPI_SLAVE 0x08
+
+ struct mtx state_mtx; /* state lock */
+ int state; /* ATA channel state */
+#define ATA_IDLE 0x0000
+#define ATA_ACTIVE 0x0001
+#define ATA_STALL_QUEUE 0x0002
+#define ATA_TIMEOUT 0x0004
+
+ struct mtx queue_mtx; /* queue lock */
+ TAILQ_HEAD(, ata_request) ata_queue; /* head of ATA queue */
+ struct ata_request *freezepoint; /* composite freezepoint */
+ struct ata_request *running; /* currently running request */
};
/* disk bay/enclosure related */
-#define ATA_LED_OFF 0x00
-#define ATA_LED_RED 0x01
-#define ATA_LED_GREEN 0x02
-#define ATA_LED_ORANGE 0x03
-#define ATA_LED_MASK 0x03
+#define ATA_LED_OFF 0x00
+#define ATA_LED_RED 0x01
+#define ATA_LED_GREEN 0x02
+#define ATA_LED_ORANGE 0x03
+#define ATA_LED_MASK 0x03
/* externs */
+extern int (*ata_ioctl_func)(struct ata_cmd *iocmd);
extern devclass_t ata_devclass;
extern int ata_wc;
@@ -394,16 +391,11 @@ extern int ata_wc;
int ata_probe(device_t dev);
int ata_attach(device_t dev);
int ata_detach(device_t dev);
+int ata_reinit(device_t dev);
int ata_suspend(device_t dev);
int ata_resume(device_t dev);
+void ata_identify(driver_t *driver, device_t parent, int type, const char *name);
void ata_udelay(int interval);
-int ata_printf(struct ata_channel *ch, int device, const char *fmt, ...) __printflike(3, 4);
-int ata_prtdev(struct ata_device *atadev, const char *fmt, ...) __printflike(2, 3);
-void ata_set_name(struct ata_device *atadev, char *name, int lun);
-void ata_free_name(struct ata_device *atadev);
-int ata_get_lun(u_int32_t *map);
-int ata_test_lun(u_int32_t *map, int lun);
-void ata_free_lun(u_int32_t *map, int lun);
char *ata_mode2str(int mode);
int ata_pmode(struct ata_params *ap);
int ata_wmode(struct ata_params *ap);
@@ -411,33 +403,28 @@ int ata_umode(struct ata_params *ap);
int ata_limit_mode(struct ata_device *atadev, int mode, int maxmode);
/* ata-queue.c: */
-int ata_reinit(struct ata_channel *ch);
-void ata_start(struct ata_channel *ch);
int ata_controlcmd(struct ata_device *atadev, u_int8_t command, u_int16_t feature, u_int64_t lba, u_int16_t count);
int ata_atapicmd(struct ata_device *atadev, u_int8_t *ccb, caddr_t data, int count, int flags, int timeout);
void ata_queue_request(struct ata_request *request);
+void ata_start(device_t dev);
void ata_finish(struct ata_request *request);
void ata_catch_inflight(struct ata_channel *ch);
-void ata_fail_requests(struct ata_channel *ch, struct ata_device *device);
+void ata_fail_requests(struct ata_channel *ch, device_t dev);
char *ata_cmd2str(struct ata_request *request);
/* ata-lowlevel.c: */
void ata_generic_hw(struct ata_channel *ch);
int ata_generic_command(struct ata_device *atadev, u_int8_t command, u_int64_t lba, u_int16_t count, u_int16_t feature);
-
-/* subdrivers */
-void ad_attach(struct ata_device *atadev);
-void acd_attach(struct ata_device *atadev);
-void afd_attach(struct ata_device *atadev);
-void ast_attach(struct ata_device *atadev);
-void atapi_cam_attach_bus(struct ata_channel *ch);
-void atapi_cam_detach_bus(struct ata_channel *ch);
-void atapi_cam_reinit_bus(struct ata_channel *ch);
+int ata_getparam(device_t parent, struct ata_device *atadev, u_int8_t command);
/* macros for alloc/free of ata_requests */
extern uma_zone_t ata_zone;
#define ata_alloc_request() uma_zalloc(ata_zone, M_NOWAIT | M_ZERO)
#define ata_free_request(request) uma_zfree(ata_zone, request)
+MALLOC_DECLARE(M_ATA);
+
+/* misc newbus defines */
+#define GRANDPARENT(dev) device_get_parent(device_get_parent(dev))
/* macros to hide busspace uglyness */
#define ATA_INB(res, offset) \
diff --git a/sys/dev/ata/ata-card.c b/sys/dev/ata/ata-card.c
index 0a6c8c6..a8aa985 100644
--- a/sys/dev/ata/ata-card.c
+++ b/sys/dev/ata/ata-card.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2004 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2005 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -61,8 +61,6 @@ static const struct pccard_product ata_pccard_products[] = {
{NULL}
};
-MALLOC_DECLARE(M_ATA);
-
static int
ata_pccard_match(device_t dev)
{
@@ -89,18 +87,6 @@ ata_pccard_match(device_t dev)
}
static int
-ata_pccard_locknoop(struct ata_channel *ch, int type)
-{
- return ch->unit;
-}
-
-static void
-ata_pccard_setmode(struct ata_device *atadev, int mode)
-{
- atadev->mode = ata_limit_mode(atadev, mode, ATA_PIO_MAX);
-}
-
-static int
ata_pccard_probe(device_t dev)
{
struct ata_channel *ch = device_get_softc(dev);
@@ -145,8 +131,6 @@ ata_pccard_probe(device_t dev)
/* initialize softc for this channel */
ch->unit = 0;
ch->flags |= (ATA_USE_16BIT | ATA_NO_SLAVE);
- ch->locking = ata_pccard_locknoop;
- ch->device[MASTER].setmode = ata_pccard_setmode;
ata_generic_hw(ch);
return ata_probe(dev);
}
@@ -157,8 +141,6 @@ ata_pccard_detach(device_t dev)
struct ata_channel *ch = device_get_softc(dev);
int i;
- free(ch->device[MASTER].param, M_ATA);
- ch->device[MASTER].param = NULL;
ata_detach(dev);
if (ch->r_io[ATA_ALTSTAT].res != ch->r_io[ATA_DATA].res)
bus_release_resource(dev, SYS_RES_IOPORT, ATA_ALTADDR_RID,
@@ -172,14 +154,14 @@ ata_pccard_detach(device_t dev)
static device_method_t ata_pccard_methods[] = {
/* device interface */
- DEVMETHOD(device_probe, pccard_compat_probe),
- DEVMETHOD(device_attach, pccard_compat_attach),
- DEVMETHOD(device_detach, ata_pccard_detach),
-
- /* Card interface */
- DEVMETHOD(card_compat_match, ata_pccard_match),
- DEVMETHOD(card_compat_probe, ata_pccard_probe),
- DEVMETHOD(card_compat_attach, ata_attach),
+ DEVMETHOD(device_probe, pccard_compat_probe),
+ DEVMETHOD(device_attach, pccard_compat_attach),
+ DEVMETHOD(device_detach, ata_pccard_detach),
+
+ /* card interface */
+ DEVMETHOD(card_compat_match, ata_pccard_match),
+ DEVMETHOD(card_compat_probe, ata_pccard_probe),
+ DEVMETHOD(card_compat_attach, ata_attach),
{ 0, 0 }
};
@@ -190,3 +172,4 @@ static driver_t ata_pccard_driver = {
};
DRIVER_MODULE(ata, pccard, ata_pccard_driver, ata_devclass, 0, 0);
+MODULE_DEPEND(ata, ata, 1, 1, 1);
diff --git a/sys/dev/ata/ata-cbus.c b/sys/dev/ata/ata-cbus.c
index 5c39261..46b009c 100644
--- a/sys/dev/ata/ata-cbus.c
+++ b/sys/dev/ata/ata-cbus.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2002 - 2004 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 2002 - 2005 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <sys/rman.h>
#include <isa/isavar.h>
#include <dev/ata/ata-all.h>
+#include <ata_if.h>
/* local vars */
struct ata_cbus_controller {
@@ -54,11 +55,10 @@ struct ata_cbus_controller {
struct resource *bankio;
struct resource *irq;
void *ih;
- void (*setmode)(struct ata_device *, int);
- int (*locking)(struct ata_channel *, int);
struct mtx bank_mtx;
- int current_bank;
+ int locked_bank;
int restart_bank;
+ int hardware_bank;
struct {
void (*function)(void *);
void *argument;
@@ -67,8 +67,7 @@ struct ata_cbus_controller {
/* local prototypes */
static void ata_cbus_intr(void *);
-static int ata_cbus_banking(struct ata_channel *, int);
-static void ata_cbus_setmode(struct ata_device *, int);
+static int ata_cbus_banking(device_t parent, device_t dev, int flags);
static int
ata_cbus_probe(device_t dev)
@@ -162,10 +161,9 @@ ata_cbus_attach(device_t dev)
}
mtx_init(&ctlr->bank_mtx, "ATA cbus bank lock", NULL, MTX_DEF);
- ctlr->current_bank = -1;
+ ctlr->hardware_bank = -1;
+ ctlr->locked_bank = -1;
ctlr->restart_bank = -1;
- ctlr->locking = ata_cbus_banking;
- ctlr->setmode = ata_cbus_setmode;;
if (!device_add_child(dev, "ata", 0))
return ENOMEM;
@@ -229,41 +227,44 @@ ata_cbus_intr(void *data)
int unit;
for (unit = 0; unit < 2; unit++) {
- if (!(ch = ctlr->interrupt[unit].argument))
- continue;
- if (ch->locking(ch, ATA_LF_WHICH) == unit)
+ if (!(ch = ctlr->interrupt[unit].argument))
+ continue;
+ if (ata_cbus_banking(device_get_parent(ch->dev), ch->dev,
+ ATA_LF_WHICH) == unit)
ctlr->interrupt[unit].function(ch);
}
}
static int
-ata_cbus_banking(struct ata_channel *ch, int flags)
+ata_cbus_banking(device_t parent, device_t dev, int flags)
{
- struct ata_cbus_controller *ctlr =
- device_get_softc(device_get_parent(ch->dev));
+ struct ata_cbus_controller *ctlr = device_get_softc(parent);
+ struct ata_channel *ch = device_get_softc(dev);
int res;
mtx_lock(&ctlr->bank_mtx);
switch (flags) {
case ATA_LF_LOCK:
- if (ctlr->current_bank == -1)
- ctlr->current_bank = ch->unit;
- if (ctlr->current_bank == ch->unit)
+ if (ctlr->locked_bank == -1)
+ ctlr->locked_bank = ch->unit;
+ if (ctlr->locked_bank == ch->unit) {
+ ctlr->hardware_bank = ch->unit;
ATA_OUTB(ctlr->bankio, 0, ch->unit);
+ }
else
ctlr->restart_bank = ch->unit;
break;
case ATA_LF_UNLOCK:
- if (ctlr->current_bank == ch->unit) {
- ctlr->current_bank = -1;
+ if (ctlr->locked_bank == ch->unit) {
+ ctlr->locked_bank = -1;
if (ctlr->restart_bank != -1) {
- if (ctlr->interrupt[ctlr->restart_bank].argument) {
- mtx_unlock(&ctlr->bank_mtx);
- ata_start(ctlr->interrupt[ctlr->restart_bank].argument);
- mtx_lock(&ctlr->bank_mtx);
+ if ((ch = ctlr->interrupt[ctlr->restart_bank].argument)) {
+ ctlr->restart_bank = -1;
+ mtx_unlock(&ctlr->bank_mtx);
+ ata_start(ch->dev);
+ return -1;
}
- ctlr->restart_bank = -1;
}
}
break;
@@ -271,26 +272,24 @@ ata_cbus_banking(struct ata_channel *ch, int flags)
case ATA_LF_WHICH:
break;
}
- res = ctlr->current_bank;
+ res = ctlr->locked_bank;
mtx_unlock(&ctlr->bank_mtx);
return res;
}
-static void
-ata_cbus_setmode(struct ata_device *atadev, int mode)
-{
- atadev->mode = ata_limit_mode(atadev, mode, ATA_PIO_MAX);
-}
-
static device_method_t ata_cbus_methods[] = {
- /* device_interface */
- DEVMETHOD(device_probe, ata_cbus_probe),
- DEVMETHOD(device_attach, ata_cbus_attach),
+ /* device interface */
+ DEVMETHOD(device_probe, ata_cbus_probe),
+ DEVMETHOD(device_attach, ata_cbus_attach),
+// DEVMETHOD(device_detach, ata_cbus_detach),
/* bus methods */
- DEVMETHOD(bus_alloc_resource, ata_cbus_alloc_resource),
- DEVMETHOD(bus_setup_intr, ata_cbus_setup_intr),
- DEVMETHOD(bus_print_child, ata_cbus_print_child),
+ DEVMETHOD(bus_alloc_resource, ata_cbus_alloc_resource),
+ DEVMETHOD(bus_setup_intr, ata_cbus_setup_intr),
+ DEVMETHOD(bus_print_child, ata_cbus_print_child),
+
+ /* ATA methods */
+ DEVMETHOD(ata_locking, ata_cbus_banking),
{ 0, 0 }
};
@@ -330,19 +329,17 @@ ata_cbussub_probe(device_t dev)
/* initialize softc for this channel */
ch->flags |= ATA_USE_16BIT;
- ch->locking = ctlr->locking;
- ch->device[MASTER].setmode = ctlr->setmode;
- ch->device[SLAVE].setmode = ctlr->setmode;
ata_generic_hw(ch);
return ata_probe(dev);
}
static device_method_t ata_cbussub_methods[] = {
/* device interface */
- DEVMETHOD(device_probe, ata_cbussub_probe),
- DEVMETHOD(device_attach, ata_attach),
- DEVMETHOD(device_detach, ata_detach),
- DEVMETHOD(device_resume, ata_resume),
+ DEVMETHOD(device_probe, ata_cbussub_probe),
+ DEVMETHOD(device_attach, ata_attach),
+ DEVMETHOD(device_detach, ata_detach),
+ DEVMETHOD(device_suspend, ata_suspend),
+ DEVMETHOD(device_resume, ata_resume),
{ 0, 0 }
};
@@ -353,3 +350,4 @@ static driver_t ata_cbussub_driver = {
};
DRIVER_MODULE(ata, atacbus, ata_cbussub_driver, ata_devclass, 0, 0);
+MODULE_DEPEND(ata, ata, 1, 1, 1);
diff --git a/sys/dev/ata/ata-chipset.c b/sys/dev/ata/ata-chipset.c
index 1e1735f..b87c1b3 100644
--- a/sys/dev/ata/ata-chipset.c
+++ b/sys/dev/ata/ata-chipset.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2004 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2005 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -50,14 +50,7 @@ __FBSDID("$FreeBSD$");
#include <dev/pci/pcireg.h>
#include <dev/ata/ata-all.h>
#include <dev/ata/ata-pci.h>
-
-/* misc defines */
-#define GRANDPARENT(dev) device_get_parent(device_get_parent(dev))
-#define ATAPI_DEVICE(atadev) \
- ((atadev->unit == ATA_MASTER && \
- atadev->channel->devices & ATA_ATAPI_MASTER) ||\
- (atadev->unit == ATA_SLAVE && \
- atadev->channel->devices & ATA_ATAPI_SLAVE))
+#include <ata_if.h>
/* local prototypes */
static int ata_generic_chipinit(device_t);
@@ -120,12 +113,29 @@ static int ata_sis_chipinit(device_t);
static void ata_sis_setmode(struct ata_device *, int);
static int ata_check_80pin(struct ata_device *, int);
static struct ata_chip_id *ata_find_chip(device_t, struct ata_chip_id *, int);
-static struct ata_chip_id *ata_match_chip(device_t, struct ata_chip_id *);
static int ata_setup_interrupt(device_t);
static int ata_serialize(struct ata_channel *, int);
static int ata_mode2idx(int);
-/* generic or unknown ATA chipset init code */
+
+static void
+ata_print_cable(device_t dev, u_int8_t *who)
+{
+ device_printf(dev,
+ "DMA limited to UDMA33, %s found non-ATA66 cable\n", who);
+}
+
+static int
+ata_atapi(struct ata_device *atadev)
+{
+ struct ata_channel *ch = device_get_softc(device_get_parent(atadev->dev));
+
+ return ((atadev->unit == ATA_MASTER && ch->devices & ATA_ATAPI_MASTER) ||
+ (atadev->unit == ATA_SLAVE && ch->devices & ATA_ATAPI_SLAVE));
+}
+
+
+/* generic or unknown ATA chipset support functions */
int
ata_generic_ident(device_t dev)
{
@@ -180,6 +190,8 @@ ata_generic_setmode(struct ata_device *atadev, int mode)
atadev->mode = mode;
}
+
+/* SATA support functions */
static void
ata_sata_setmode(struct ata_device *atadev, int mode)
{
@@ -189,9 +201,9 @@ ata_sata_setmode(struct ata_device *atadev, int mode)
* this works around the problems some devices has with the
* Marvell 88SX8030 SATA->PATA converters and UDMA6/ATA133.
*/
- if (atadev->param->satacapabilities != 0x0000 &&
- atadev->param->satacapabilities != 0xffff) {
- if (!ata_controlcmd(atadev, ATA_SETFEATURES, ATA_SF_SETXFER, 0,
+ if (atadev->param.satacapabilities != 0x0000 &&
+ atadev->param.satacapabilities != 0xffff) {
+ if (!ata_controlcmd(atadev, ATA_SETFEATURES, ATA_SF_SETXFER, 0,
ata_limit_mode(atadev, mode, ATA_UDMA6)))
atadev->mode = ATA_SA150;
}
@@ -202,6 +214,33 @@ ata_sata_setmode(struct ata_device *atadev, int mode)
}
}
+static void
+ata_sata_connect(void *context, int dummy)
+{
+ struct ata_connect_task *tp = (struct ata_connect_task *)context;
+ device_t *children;
+ int nchildren, i;
+
+ mtx_lock(&Giant); /* newbus suckage it needs Giant */
+ if (tp->action == ATA_C_ATTACH) {
+ bus_generic_probe(tp->dev);
+ bus_generic_attach(tp->dev);
+ device_printf(tp->dev, "CONNECTED\n");
+ }
+ if (tp->action == ATA_C_DETACH) {
+ if (!device_get_children(tp->dev, &children, &nchildren)) {
+ for (i = 0; i < nchildren; i++)
+ if (children[i])
+ device_delete_child(tp->dev, children[i]);
+ free(children, M_TEMP);
+ }
+ device_printf(tp->dev, "DISCONNECTED\n");
+ }
+ mtx_unlock(&Giant); /* suckage code dealt with, release Giant */
+ free(tp, M_ATA);
+}
+
+
/*
* Acard chipset support functions
*/
@@ -265,7 +304,9 @@ ata_acard_intr(void *data)
for (unit = 0; unit < 2; unit++) {
if (!(ch = ctlr->interrupt[unit].argument))
continue;
- if (ctlr->chip->cfg1 == ATPOLD && ch->locking(ch, ATA_LF_WHICH) != unit)
+ if (ctlr->chip->cfg1 == ATPOLD &&
+ ATA_LOCKING(device_get_parent(ch->dev),
+ ch->dev, ATA_LF_WHICH) != unit)
continue;
if (ch->dma && (ch->dma->flags & ATA_DMA_ACTIVE)) {
int bmstat = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
@@ -286,30 +327,31 @@ ata_acard_intr(void *data)
static void
ata_acard_850_setmode(struct ata_device *atadev, int mode)
{
- device_t parent = device_get_parent(atadev->channel->dev);
- struct ata_pci_controller *ctlr = device_get_softc(parent);
- int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit);
+ device_t gparent = GRANDPARENT(atadev->dev);
+ struct ata_pci_controller *ctlr = device_get_softc(gparent);
+ struct ata_channel *ch = device_get_softc(device_get_parent(atadev->dev));
+ int devno = (ch->unit << 1) + ATA_DEV(atadev->unit);
int error;
mode = ata_limit_mode(atadev, mode,
- ATAPI_DEVICE(atadev)?ATA_PIO_MAX:ctlr->chip->max_dma);
+ ata_atapi(atadev) ? ATA_PIO_MAX:ctlr->chip->max_dma);
/* XXX missing WDMA0+1 + PIO modes */
if (mode >= ATA_WDMA2) {
error = ata_controlcmd(atadev, ATA_SETFEATURES, ATA_SF_SETXFER, 0,mode);
if (bootverbose)
- ata_prtdev(atadev, "%ssetting %s on %s chip\n",
- (error) ? "FAILURE " : "",
- ata_mode2str(mode), ctlr->chip->text);
+ device_printf(atadev->dev, "%ssetting %s on %s chip\n",
+ (error) ? "FAILURE " : "",
+ ata_mode2str(mode), ctlr->chip->text);
if (!error) {
- u_int8_t reg54 = pci_read_config(parent, 0x54, 1);
+ u_int8_t reg54 = pci_read_config(gparent, 0x54, 1);
reg54 &= ~(0x03 << (devno << 1));
if (mode >= ATA_UDMA0)
reg54 |= (((mode & ATA_MODE_MASK) + 1) << (devno << 1));
- pci_write_config(parent, 0x54, reg54, 1);
- pci_write_config(parent, 0x4a, 0xa6, 1);
- pci_write_config(parent, 0x40 + (devno << 1), 0x0301, 2);
+ pci_write_config(gparent, 0x54, reg54, 1);
+ pci_write_config(gparent, 0x4a, 0xa6, 1);
+ pci_write_config(gparent, 0x40 + (devno << 1), 0x0301, 2);
atadev->mode = mode;
return;
}
@@ -320,14 +362,15 @@ ata_acard_850_setmode(struct ata_device *atadev, int mode)
static void
ata_acard_86X_setmode(struct ata_device *atadev, int mode)
{
- device_t parent = device_get_parent(atadev->channel->dev);
- struct ata_pci_controller *ctlr = device_get_softc(parent);
- int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit);
+ device_t gparent = GRANDPARENT(atadev->dev);
+ struct ata_pci_controller *ctlr = device_get_softc(gparent);
+ struct ata_channel *ch = device_get_softc(device_get_parent(atadev->dev));
+ int devno = (ch->unit << 1) + ATA_DEV(atadev->unit);
int error;
mode = ata_limit_mode(atadev, mode,
- ATAPI_DEVICE(atadev)?ATA_PIO_MAX:ctlr->chip->max_dma);
+ ata_atapi(atadev) ? ATA_PIO_MAX:ctlr->chip->max_dma);
mode = ata_check_80pin(atadev, mode);
@@ -335,18 +378,18 @@ ata_acard_86X_setmode(struct ata_device *atadev, int mode)
if (mode >= ATA_WDMA2) {
error = ata_controlcmd(atadev, ATA_SETFEATURES, ATA_SF_SETXFER, 0,mode);
if (bootverbose)
- ata_prtdev(atadev, "%ssetting %s on %s chip\n",
- (error) ? "FAILURE " : "",
- ata_mode2str(mode), ctlr->chip->text);
+ device_printf(atadev->dev, "%ssetting %s on %s chip\n",
+ (error) ? "FAILURE " : "",
+ ata_mode2str(mode), ctlr->chip->text);
if (!error) {
- u_int16_t reg44 = pci_read_config(parent, 0x44, 2);
+ u_int16_t reg44 = pci_read_config(gparent, 0x44, 2);
reg44 &= ~(0x000f << (devno << 2));
if (mode >= ATA_UDMA0)
reg44 |= (((mode & ATA_MODE_MASK) + 1) << (devno << 2));
- pci_write_config(parent, 0x44, reg44, 2);
- pci_write_config(parent, 0x4a, 0xa6, 1);
- pci_write_config(parent, 0x40 + devno, 0x31, 1);
+ pci_write_config(gparent, 0x44, reg44, 2);
+ pci_write_config(gparent, 0x4a, 0xa6, 1);
+ pci_write_config(gparent, 0x40 + devno, 0x31, 1);
atadev->mode = mode;
return;
}
@@ -389,11 +432,16 @@ ata_ali_chipinit(device_t dev)
return ENXIO;
/* deactivate the ATAPI FIFO and enable ATAPI UDMA */
- pci_write_config(dev, 0x53, pci_read_config(dev, 0x53, 1) | 0x03, 1);
+ if (ctlr->chip->cfg2 & ALINEW)
+ pci_write_config(dev, 0x53, pci_read_config(dev, 0x53, 1) | 0x01, 1);
+ else
+ pci_write_config(dev, 0x53,
+ (pci_read_config(dev, 0x53, 1) & ~0x02) | 0x03, 1);
/* enable cable detection and UDMA support on newer chips */
if (ctlr->chip->cfg2 & ALINEW)
pci_write_config(dev, 0x4b, pci_read_config(dev, 0x4b, 1) | 0x09, 1);
+
ctlr->setmode = ata_ali_setmode;
return 0;
}
@@ -401,18 +449,18 @@ ata_ali_chipinit(device_t dev)
static void
ata_ali_setmode(struct ata_device *atadev, int mode)
{
- device_t parent = device_get_parent(atadev->channel->dev);
- struct ata_pci_controller *ctlr = device_get_softc(parent);
- int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit);
+ device_t gparent = GRANDPARENT(atadev->dev);
+ struct ata_pci_controller *ctlr = device_get_softc(gparent);
+ struct ata_channel *ch = device_get_softc(device_get_parent(atadev->dev));
+ int devno = (ch->unit << 1) + ATA_DEV(atadev->unit);
int error;
mode = ata_limit_mode(atadev, mode, ctlr->chip->max_dma);
if (ctlr->chip->cfg2 & ALINEW) {
if (mode > ATA_UDMA2 &&
- pci_read_config(parent, 0x4a, 1) & (1 << atadev->channel->unit)) {
- ata_prtdev(atadev,
- "DMA limited to UDMA33, non-ATA66 cable or device\n");
+ pci_read_config(gparent, 0x4a, 1) & (1 << ch->unit)) {
+ ata_print_cable(atadev->dev, "controller");
mode = ATA_UDMA2;
}
}
@@ -421,11 +469,11 @@ ata_ali_setmode(struct ata_device *atadev, int mode)
if (ctlr->chip->cfg2 & ALIOLD) {
/* doesn't support ATAPI DMA on write */
- atadev->channel->flags |= ATA_ATAPI_DMA_RO;
- if (atadev->channel->devices & ATA_ATAPI_MASTER &&
- atadev->channel->devices & ATA_ATAPI_SLAVE) {
+ ch->flags |= ATA_ATAPI_DMA_RO;
+ if (ch->devices & ATA_ATAPI_MASTER && ch->devices & ATA_ATAPI_SLAVE) {
/* doesn't support ATAPI DMA on two ATAPI devices */
- ata_prtdev(atadev, "two atapi devices on this channel, no DMA\n");
+ device_printf(atadev->dev,
+ "two atapi devices on this channel, no DMA\n");
mode = ata_limit_mode(atadev, mode, ATA_PIO_MAX);
}
}
@@ -433,18 +481,18 @@ ata_ali_setmode(struct ata_device *atadev, int mode)
error = ata_controlcmd(atadev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode);
if (bootverbose)
- ata_prtdev(atadev, "%ssetting %s on %s chip\n",
+ device_printf(atadev->dev, "%ssetting %s on %s chip\n",
(error) ? "FAILURE " : "",
ata_mode2str(mode), ctlr->chip->text);
if (!error) {
if (mode >= ATA_UDMA0) {
u_int8_t udma[] = {0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x0f};
- u_int32_t word54 = pci_read_config(parent, 0x54, 4);
+ u_int32_t word54 = pci_read_config(gparent, 0x54, 4);
word54 &= ~(0x000f000f << (devno << 2));
word54 |= (((udma[mode&ATA_MODE_MASK]<<16)|0x05)<<(devno<<2));
- pci_write_config(parent, 0x54, word54, 4);
- pci_write_config(parent, 0x58 + (atadev->channel->unit << 2),
+ pci_write_config(gparent, 0x54, word54, 4);
+ pci_write_config(gparent, 0x58 + (ch->unit << 2),
0x00310001, 4);
}
else {
@@ -452,9 +500,9 @@ ata_ali_setmode(struct ata_device *atadev, int mode)
{ 0x006d0003, 0x00580002, 0x00440001, 0x00330001,
0x00310001, 0x00440001, 0x00330001, 0x00310001};
- pci_write_config(parent, 0x54, pci_read_config(parent, 0x54, 4) &
- ~(0x0008000f << (devno << 2)), 4);
- pci_write_config(parent, 0x58 + (atadev->channel->unit << 2),
+ pci_write_config(gparent, 0x54, pci_read_config(gparent, 0x54, 4) &
+ ~(0x0008000f << (devno << 2)), 4);
+ pci_write_config(gparent, 0x58 + (ch->unit << 2),
piotimings[ata_mode2idx(mode)], 4);
}
atadev->mode = mode;
@@ -462,7 +510,7 @@ ata_ali_setmode(struct ata_device *atadev, int mode)
}
/*
- * American Micro Devices (AMD) support functions
+ * American Micro Devices (AMD) chipset support functions
*/
int
ata_amd_ident(device_t dev)
@@ -470,10 +518,10 @@ ata_amd_ident(device_t dev)
struct ata_pci_controller *ctlr = device_get_softc(dev);
struct ata_chip_id *idx;
static struct ata_chip_id ids[] =
- {{ ATA_AMD756, 0x00, AMDNVIDIA, 0x00, ATA_UDMA4, "AMD 756" },
+ {{ ATA_AMD756, 0x00, AMDNVIDIA, 0x00, ATA_UDMA4, "AMD 756" },
{ ATA_AMD766, 0x00, AMDNVIDIA, AMDCABLE|AMDBUG, ATA_UDMA5, "AMD 766" },
- { ATA_AMD768, 0x00, AMDNVIDIA, AMDCABLE, ATA_UDMA5, "AMD 768" },
- { ATA_AMD8111, 0x00, AMDNVIDIA, AMDCABLE, ATA_UDMA6, "AMD 8111" },
+ { ATA_AMD768, 0x00, AMDNVIDIA, AMDCABLE, ATA_UDMA5, "AMD 768" },
+ { ATA_AMD8111, 0x00, AMDNVIDIA, AMDCABLE, ATA_UDMA6, "AMD 8111" },
{ 0, 0, 0, 0, 0, 0}};
char buffer[64];
@@ -539,24 +587,24 @@ ata_cyrix_chipinit(device_t dev)
static void
ata_cyrix_setmode(struct ata_device *atadev, int mode)
{
- struct ata_channel *ch = atadev->channel;
- int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit);
+ struct ata_channel *ch = device_get_softc(device_get_parent(atadev->dev));
+ int devno = (ch->unit << 1) + ATA_DEV(atadev->unit);
u_int32_t piotiming[] =
{ 0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010 };
u_int32_t dmatiming[] = { 0x00077771, 0x00012121, 0x00002020 };
u_int32_t udmatiming[] = { 0x00921250, 0x00911140, 0x00911030 };
int error;
- atadev->channel->dma->alignment = 16;
- atadev->channel->dma->max_iosize = 126 * DEV_BSIZE;
+ ch->dma->alignment = 16;
+ ch->dma->max_iosize = 126 * DEV_BSIZE;
mode = ata_limit_mode(atadev, mode, ATA_UDMA2);
error = ata_controlcmd(atadev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode);
if (bootverbose)
- ata_prtdev(atadev, "%ssetting %s on Cyrix chip\n",
- (error) ? "FAILURE " : "", ata_mode2str(mode));
+ device_printf(atadev->dev, "%ssetting %s on Cyrix chip\n",
+ (error) ? "FAILURE " : "", ata_mode2str(mode));
if (!error) {
if (mode >= ATA_UDMA0) {
ATA_OUTL(ch->r_io[ATA_BMCMD_PORT].res,
@@ -614,7 +662,8 @@ ata_cypress_chipinit(device_t dev)
static void
ata_cypress_setmode(struct ata_device *atadev, int mode)
{
- device_t parent = device_get_parent(atadev->channel->dev);
+ device_t gparent = GRANDPARENT(atadev->dev);
+ struct ata_channel *ch = device_get_softc(device_get_parent(atadev->dev));
int error;
mode = ata_limit_mode(atadev, mode, ATA_WDMA2);
@@ -623,10 +672,10 @@ ata_cypress_setmode(struct ata_device *atadev, int mode)
if (mode == ATA_WDMA2) {
error = ata_controlcmd(atadev, ATA_SETFEATURES, ATA_SF_SETXFER, 0,mode);
if (bootverbose)
- ata_prtdev(atadev, "%ssetting WDMA2 on Cypress chip\n",
- error ? "FAILURE " : "");
+ device_printf(atadev->dev, "%ssetting WDMA2 on Cypress chip\n",
+ error ? "FAILURE " : "");
if (!error) {
- pci_write_config(parent, atadev->channel->unit?0x4e:0x4c,0x2020,2);
+ pci_write_config(gparent, ch->unit ? 0x4e : 0x4c, 0x2020, 2);
atadev->mode = mode;
return;
}
@@ -643,14 +692,15 @@ ata_highpoint_ident(device_t dev)
struct ata_pci_controller *ctlr = device_get_softc(dev);
struct ata_chip_id *idx;
static struct ata_chip_id ids[] =
- {{ ATA_HPT366, 0x05, HPT372, 0x00, ATA_UDMA6, "HighPoint HPT372" },
- { ATA_HPT366, 0x03, HPT370, 0x00, ATA_UDMA5, "HighPoint HPT370" },
- { ATA_HPT366, 0x02, HPT366, 0x00, ATA_UDMA4, "HighPoint HPT368" },
+ {{ ATA_HPT374, 0x07, HPT374, 0x00, ATA_UDMA6, "HighPoint HPT374" },
+ { ATA_HPT372, 0x02, HPT372, 0x00, ATA_UDMA6, "HighPoint HPT372N" },
+ { ATA_HPT372, 0x01, HPT372, 0x00, ATA_UDMA6, "HighPoint HPT372" },
+ { ATA_HPT371, 0x01, HPT372, 0x00, ATA_UDMA6, "HighPoint HPT371" },
+ { ATA_HPT366, 0x05, HPT372, 0x00, ATA_UDMA6, "HighPoint HPT372" },
+ { ATA_HPT366, 0x03, HPT370, 0x00, ATA_UDMA5, "HighPoint HPT370" },
+ { ATA_HPT366, 0x02, HPT366, 0x00, ATA_UDMA4, "HighPoint HPT368" },
{ ATA_HPT366, 0x00, HPT366, HPTOLD, ATA_UDMA4, "HighPoint HPT366" },
- { ATA_HPT372, 0x01, HPT372, 0x00, ATA_UDMA6, "HighPoint HPT372" },
- { ATA_HPT302, 0x01, HPT372, 0x00, ATA_UDMA6, "HighPoint HPT302" },
- { ATA_HPT371, 0x01, HPT372, 0x00, ATA_UDMA6, "HighPoint HPT371" },
- { ATA_HPT374, 0x07, HPT374, 0x00, ATA_UDMA6, "HighPoint HPT374" },
+ { ATA_HPT302, 0x01, HPT372, 0x00, ATA_UDMA6, "HighPoint HPT302" },
{ 0, 0, 0, 0, 0, 0}};
char buffer[64];
@@ -738,43 +788,50 @@ ata_highpoint_intr(void *data)
static void
ata_highpoint_setmode(struct ata_device *atadev, int mode)
{
- device_t parent = device_get_parent(atadev->channel->dev);
- struct ata_pci_controller *ctlr = device_get_softc(parent);
- int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit);
+ device_t gparent = GRANDPARENT(atadev->dev);
+ struct ata_pci_controller *ctlr = device_get_softc(gparent);
+ struct ata_channel *ch = device_get_softc(device_get_parent(atadev->dev));
+ int devno = (ch->unit << 1) + ATA_DEV(atadev->unit);
int error;
u_int32_t timings33[][4] = {
- /* HPT366 HPT370 HPT372 HPT374 mode */
- { 0x40d0a7aa, 0x06914e57, 0x0d029d5e, 0x0ac1f48a }, /* PIO 0 */
- { 0x40d0a7a3, 0x06914e43, 0x0d029d26, 0x0ac1f465 }, /* PIO 1 */
- { 0x40d0a753, 0x06514e33, 0x0c829ca6, 0x0a81f454 }, /* PIO 2 */
- { 0x40c8a742, 0x06514e22, 0x0c829c84, 0x0a81f443 }, /* PIO 3 */
- { 0x40c8a731, 0x06514e21, 0x0c829c62, 0x0a81f442 }, /* PIO 4 */
- { 0x20c8a797, 0x26514e97, 0x2c82922e, 0x228082ea }, /* MWDMA 0 */
- { 0x20c8a732, 0x26514e33, 0x2c829266, 0x22808254 }, /* MWDMA 1 */
- { 0x20c8a731, 0x26514e21, 0x2c829262, 0x22808242 }, /* MWDMA 2 */
- { 0x10c8a731, 0x16514e31, 0x1c82dc62, 0x121882ea }, /* UDMA 0 */
- { 0x10cba731, 0x164d4e31, 0x1c9adc62, 0x12148254 }, /* UDMA 1 */
- { 0x10caa731, 0x16494e31, 0x1c91dc62, 0x120c8242 }, /* UDMA 2 */
- { 0x10cfa731, 0x166d4e31, 0x1c8edc62, 0x128c8242 }, /* UDMA 3 */
- { 0x10c9a731, 0x16454e31, 0x1c8ddc62, 0x12ac8242 }, /* UDMA 4 */
- { 0, 0x16454e31, 0x1c6ddc62, 0x12848242 }, /* UDMA 5 */
- { 0, 0, 0x1c81dc62, 0x12448242 } /* UDMA 6 */
+ /* HPT366 HPT370 HPT372 HPT374 mode */
+ { 0x40d0a7aa, 0x06914e57, 0x0d029d5e, 0x0ac1f48a }, /* PIO 0 */
+ { 0x40d0a7a3, 0x06914e43, 0x0d029d26, 0x0ac1f465 }, /* PIO 1 */
+ { 0x40d0a753, 0x06514e33, 0x0c829ca6, 0x0a81f454 }, /* PIO 2 */
+ { 0x40c8a742, 0x06514e22, 0x0c829c84, 0x0a81f443 }, /* PIO 3 */
+ { 0x40c8a731, 0x06514e21, 0x0c829c62, 0x0a81f442 }, /* PIO 4 */
+ { 0x20c8a797, 0x26514e97, 0x2c82922e, 0x228082ea }, /* MWDMA 0 */
+ { 0x20c8a732, 0x26514e33, 0x2c829266, 0x22808254 }, /* MWDMA 1 */
+ { 0x20c8a731, 0x26514e21, 0x2c829262, 0x22808242 }, /* MWDMA 2 */
+ { 0x10c8a731, 0x16514e31, 0x1c829c62, 0x121882ea }, /* UDMA 0 */
+ { 0x10cba731, 0x164d4e31, 0x1c9a9c62, 0x12148254 }, /* UDMA 1 */
+ { 0x10caa731, 0x16494e31, 0x1c929c62, 0x120c8242 }, /* UDMA 2 */
+ { 0x10cfa731, 0x166d4e31, 0x1c8e9c62, 0x128c8242 }, /* UDMA 3 */
+ { 0x10c9a731, 0x16454e31, 0x1c8a9c62, 0x12ac8242 }, /* UDMA 4 */
+ { 0, 0x16454e31, 0x1c8a9c62, 0x12848242 }, /* UDMA 5 */
+ { 0, 0, 0x1c869c62, 0x12808242 } /* UDMA 6 */
};
mode = ata_limit_mode(atadev, mode, ctlr->chip->max_dma);
- if (ctlr->chip->cfg1 == HPT366 && ATAPI_DEVICE(atadev))
+ if (ctlr->chip->cfg1 == HPT366 && ata_atapi(atadev))
mode = ata_limit_mode(atadev, mode, ATA_PIO_MAX);
mode = ata_highpoint_check_80pin(atadev, mode);
- error = ata_controlcmd(atadev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode);
+ /*
+ * most if not all HPT chips cant really handle that the device is
+ * running at ATA_UDMA6/ATA133 speed, so we cheat at set the device to
+ * a max of ATA_UDMA5/ATA100 to guard against suboptimal performance
+ */
+ error = ata_controlcmd(atadev, ATA_SETFEATURES, ATA_SF_SETXFER, 0,
+ ata_limit_mode(atadev, mode, ATA_UDMA5));
if (bootverbose)
- ata_prtdev(atadev, "%ssetting %s on HighPoint chip\n",
- (error) ? "FAILURE " : "", ata_mode2str(mode));
+ device_printf(atadev->dev, "%ssetting %s on HighPoint chip\n",
+ (error) ? "FAILURE " : "", ata_mode2str(mode));
if (!error)
- pci_write_config(parent, 0x40 + (devno << 2),
+ pci_write_config(gparent, 0x40 + (devno << 2),
timings33[ata_mode2idx(mode)][ctlr->chip->cfg1], 4);
atadev->mode = mode;
}
@@ -782,25 +839,26 @@ ata_highpoint_setmode(struct ata_device *atadev, int mode)
static int
ata_highpoint_check_80pin(struct ata_device *atadev, int mode)
{
- device_t parent = device_get_parent(atadev->channel->dev);
- struct ata_pci_controller *ctlr = device_get_softc(parent);
+ device_t gparent = GRANDPARENT(atadev->dev);
+ struct ata_pci_controller *ctlr = device_get_softc(gparent);
+ struct ata_channel *ch = device_get_softc(device_get_parent(atadev->dev));
u_int8_t reg, val, res;
- if (ctlr->chip->cfg1 == HPT374 && pci_get_function(parent) == 1) {
- reg = atadev->channel->unit ? 0x57 : 0x53;
- val = pci_read_config(parent, reg, 1);
- pci_write_config(parent, reg, val | 0x80, 1);
+ if (ctlr->chip->cfg1 == HPT374 && pci_get_function(gparent) == 1) {
+ reg = ch->unit ? 0x57 : 0x53;
+ val = pci_read_config(gparent, reg, 1);
+ pci_write_config(gparent, reg, val | 0x80, 1);
}
else {
reg = 0x5b;
- val = pci_read_config(parent, reg, 1);
- pci_write_config(parent, reg, val & 0xfe, 1);
+ val = pci_read_config(gparent, reg, 1);
+ pci_write_config(gparent, reg, val & 0xfe, 1);
}
- res = pci_read_config(parent, 0x5a, 1) & (atadev->channel->unit ? 0x1:0x2);
- pci_write_config(parent, reg, val, 1);
+ res = pci_read_config(gparent, 0x5a, 1) & (ch->unit ? 0x1:0x2);
+ pci_write_config(gparent, reg, val, 1);
if (mode > ATA_UDMA2 && res) {
- ata_prtdev(atadev,"DMA limited to UDMA33, non-ATA66 cable or device\n");
+ ata_print_cable(atadev->dev, "controller");
mode = ATA_UDMA2;
}
return mode;
@@ -920,7 +978,7 @@ ata_intel_reset(struct ata_channel *ch)
{
device_t parent = device_get_parent(ch->dev);
struct ata_pci_controller *ctlr = device_get_softc(parent);
- int mask, timeout = 100;
+ int mask, timeout;
/* ICH6 has 4 SATA ports as master/slave on 2 channels so deal with pairs */
if (ctlr->chip->chipid == ATA_I82801FB_S1 ||
@@ -931,33 +989,37 @@ ata_intel_reset(struct ata_channel *ch)
/* ICH5 in compat mode has SATA ports as master/slave on 1 channel */
if (pci_read_config(parent, 0x90, 1) & 0x04)
mask = 0x0003;
- else
+ else {
mask = (0x0001 << ch->unit);
+ /* XXX SOS should be in intel_allocate when we grow it */
+ ch->flags |= ATA_NO_SLAVE;
+ }
}
pci_write_config(parent, 0x92, pci_read_config(parent, 0x92, 2) & ~mask, 2);
DELAY(10);
pci_write_config(parent, 0x92, pci_read_config(parent, 0x92, 2) | mask, 2);
- while (timeout--) {
+ /* wait up to 1 sec for "connect well" */
+ for (timeout = 0; timeout < 100 ; timeout++) {
+ if (((pci_read_config(parent, 0x92, 2) & (mask << 4)) == (mask << 4)) &&
+ (ATA_IDX_INB(ch, ATA_STATUS) != 0xff))
+ break;
ata_udelay(10000);
- if ((pci_read_config(parent, 0x92, 2) & (mask << 4)) == (mask << 4)) {
- ata_udelay(10000);
- return;
- }
}
}
static void
ata_intel_new_setmode(struct ata_device *atadev, int mode)
{
- device_t parent = device_get_parent(atadev->channel->dev);
- struct ata_pci_controller *ctlr = device_get_softc(parent);
- int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit);
- u_int32_t reg40 = pci_read_config(parent, 0x40, 4);
- u_int8_t reg44 = pci_read_config(parent, 0x44, 1);
- u_int8_t reg48 = pci_read_config(parent, 0x48, 1);
- u_int16_t reg4a = pci_read_config(parent, 0x4a, 2);
- u_int16_t reg54 = pci_read_config(parent, 0x54, 2);
+ device_t gparent = GRANDPARENT(atadev->dev);
+ struct ata_pci_controller *ctlr = device_get_softc(gparent);
+ struct ata_channel *ch = device_get_softc(device_get_parent(atadev->dev));
+ int devno = (ch->unit << 1) + ATA_DEV(atadev->unit);
+ u_int32_t reg40 = pci_read_config(gparent, 0x40, 4);
+ u_int8_t reg44 = pci_read_config(gparent, 0x44, 1);
+ u_int8_t reg48 = pci_read_config(gparent, 0x48, 1);
+ u_int16_t reg4a = pci_read_config(gparent, 0x4a, 2);
+ u_int16_t reg54 = pci_read_config(gparent, 0x54, 2);
u_int32_t mask40 = 0, new40 = 0;
u_int8_t mask44 = 0, new44 = 0;
int error;
@@ -967,38 +1029,38 @@ ata_intel_new_setmode(struct ata_device *atadev, int mode)
mode = ata_limit_mode(atadev, mode, ctlr->chip->max_dma);
if ( mode > ATA_UDMA2 && !(reg54 & (0x10 << devno))) {
- ata_prtdev(atadev,"DMA limited to UDMA33, non-ATA66 cable or device\n");
+ ata_print_cable(atadev->dev, "controller");
mode = ATA_UDMA2;
}
error = ata_controlcmd(atadev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode);
if (bootverbose)
- ata_prtdev(atadev, "%ssetting %s on %s chip\n",
- (error) ? "FAILURE " : "",
- ata_mode2str(mode), ctlr->chip->text);
+ device_printf(atadev->dev, "%ssetting %s on %s chip\n",
+ (error) ? "FAILURE " : "",
+ ata_mode2str(mode), ctlr->chip->text);
if (error)
return;
if (mode >= ATA_UDMA0) {
- pci_write_config(parent, 0x48, reg48 | (0x0001 << devno), 2);
- pci_write_config(parent, 0x4a, (reg4a & ~(0x3 << (devno<<2))) |
+ pci_write_config(gparent, 0x48, reg48 | (0x0001 << devno), 2);
+ pci_write_config(gparent, 0x4a, (reg4a & ~(0x3 << (devno<<2))) |
(0x01 + !(mode & 0x01)), 2);
}
else {
- pci_write_config(parent, 0x48, reg48 & ~(0x0001 << devno), 2);
- pci_write_config(parent, 0x4a, (reg4a & ~(0x3 << (devno << 2))), 2);
+ pci_write_config(gparent, 0x48, reg48 & ~(0x0001 << devno), 2);
+ pci_write_config(gparent, 0x4a, (reg4a & ~(0x3 << (devno << 2))), 2);
}
reg54 |= 0x0400;
if (mode >= ATA_UDMA2)
- pci_write_config(parent, 0x54, reg54 | (0x1 << devno), 2);
+ pci_write_config(gparent, 0x54, reg54 | (0x1 << devno), 2);
else
- pci_write_config(parent, 0x54, reg54 & ~(0x1 << devno), 2);
+ pci_write_config(gparent, 0x54, reg54 & ~(0x1 << devno), 2);
if (mode >= ATA_UDMA5)
- pci_write_config(parent, 0x54, reg54 | (0x1000 << devno), 2);
+ pci_write_config(gparent, 0x54, reg54 | (0x1000 << devno), 2);
else
- pci_write_config(parent, 0x54, reg54 & ~(0x1000 << devno), 2);
+ pci_write_config(gparent, 0x54, reg54 & ~(0x1000 << devno), 2);
reg40 &= ~0x00ff00ff;
reg40 |= 0x40774077;
@@ -1012,14 +1074,14 @@ ata_intel_new_setmode(struct ata_device *atadev, int mode)
new44 = ((timings[ata_mode2idx(mode)] & 0x30) >> 2) |
(timings[ata_mode2idx(mode)] & 0x03);
}
- if (atadev->channel->unit) {
+ if (ch->unit) {
mask40 <<= 16;
new40 <<= 16;
mask44 <<= 4;
new44 <<= 4;
}
- pci_write_config(parent, 0x40, (reg40 & ~mask40) | new40, 4);
- pci_write_config(parent, 0x44, (reg44 & ~mask44) | new44, 1);
+ pci_write_config(gparent, 0x40, (reg40 & ~mask40) | new40, 4);
+ pci_write_config(gparent, 0x44, (reg44 & ~mask44) | new44, 1);
atadev->mode = mode;
}
@@ -1062,8 +1124,8 @@ ata_ite_chipinit(device_t dev)
static void
ata_ite_setmode(struct ata_device *atadev, int mode)
{
- device_t parent = device_get_parent(atadev->channel->dev);
- struct ata_channel *ch = atadev->channel;
+ device_t gparent = GRANDPARENT(atadev->dev);
+ struct ata_channel *ch = device_get_softc(device_get_parent(atadev->dev));
int devno = (ch->unit << 1) + ATA_DEV(atadev->unit);
int error;
@@ -1071,9 +1133,9 @@ ata_ite_setmode(struct ata_device *atadev, int mode)
mode = ata_limit_mode(atadev, mode, ATA_UDMA6);
/* check the CBLID bits for 80 conductor cable detection */
- if (mode > ATA_UDMA2 && (pci_read_config(parent, 0x40, 2) &
+ if (mode > ATA_UDMA2 && (pci_read_config(gparent, 0x40, 2) &
(ch->unit ? (1<<3) : (1<<2)))) {
- ata_prtdev(atadev,"DMA limited to UDMA33, non-ATA66 cable or device\n");
+ ata_print_cable(atadev->dev, "controller");
mode = ATA_UDMA2;
}
@@ -1081,8 +1143,8 @@ ata_ite_setmode(struct ata_device *atadev, int mode)
error = ata_controlcmd(atadev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode);
if (bootverbose)
- ata_prtdev(atadev, "%s setting %s on ITE8212F chip\n",
- (error) ? "failed" : "success", ata_mode2str(mode));
+ device_printf(atadev->dev, "%s setting %s on ITE8212F chip\n",
+ (error) ? "failed" : "success", ata_mode2str(mode));
/* if the device accepted the mode change, setup the HW accordingly */
if (!error) {
@@ -1091,12 +1153,12 @@ ata_ite_setmode(struct ata_device *atadev, int mode)
{ 0x44, 0x42, 0x31, 0x21, 0x11, 0xa2, 0x91 };
/* enable UDMA mode */
- pci_write_config(parent, 0x50,
- pci_read_config(parent, 0x50, 1) &
+ pci_write_config(gparent, 0x50,
+ pci_read_config(gparent, 0x50, 1) &
~(1 << (devno + 3)), 1);
/* set UDMA timing */
- pci_write_config(parent,
+ pci_write_config(gparent,
0x56 + (ch->unit << 2) + ATA_DEV(atadev->unit),
udmatiming[mode & ATA_MODE_MASK], 1);
}
@@ -1105,19 +1167,20 @@ ata_ite_setmode(struct ata_device *atadev, int mode)
{ 0xaa, 0xa3, 0xa1, 0x33, 0x31, 0x88, 0x32, 0x31 };
/* disable UDMA mode */
- pci_write_config(parent, 0x50,
- pci_read_config(parent, 0x50, 1) |
+ pci_write_config(gparent, 0x50,
+ pci_read_config(gparent, 0x50, 1) |
(1 << (devno + 3)), 1);
/* set active and recover timing (shared between master & slave) */
- if (pci_read_config(parent, 0x54 + (ch->unit << 2), 1) <
+ if (pci_read_config(gparent, 0x54 + (ch->unit << 2), 1) <
chtiming[ata_mode2idx(mode)])
- pci_write_config(parent, 0x54 + (ch->unit << 2),
- chtiming[ata_mode2idx(mode)], 1);
+ pci_write_config(gparent, 0x54 + (ch->unit << 2),
+ chtiming[ata_mode2idx(mode)], 1);
}
atadev->mode = mode;
}
}
+
/*
* National chipset support functions
*/
@@ -1164,41 +1227,42 @@ ata_national_chipinit(device_t dev)
static void
ata_national_setmode(struct ata_device *atadev, int mode)
{
- device_t parent = device_get_parent(atadev->channel->dev);
- int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit);
+ device_t gparent = GRANDPARENT(atadev->dev);
+ struct ata_channel *ch = device_get_softc(device_get_parent(atadev->dev));
+ int devno = (ch->unit << 1) + ATA_DEV(atadev->unit);
u_int32_t piotiming[] =
- { 0x9172d132, 0x21717121, 0x00803020, 0x20102010, 0x00100010,
+ { 0x9172d132, 0x21717121, 0x00803020, 0x20102010, 0x00100010,
0x00803020, 0x20102010, 0x00100010,
0x00100010, 0x00100010, 0x00100010 };
u_int32_t dmatiming[] = { 0x80077771, 0x80012121, 0x80002020 };
u_int32_t udmatiming[] = { 0x80921250, 0x80911140, 0x80911030 };
int error;
- atadev->channel->dma->alignment = 16;
- atadev->channel->dma->max_iosize = 126 * DEV_BSIZE;
+ ch->dma->alignment = 16;
+ ch->dma->max_iosize = 126 * DEV_BSIZE;
mode = ata_limit_mode(atadev, mode, ATA_UDMA2);
error = ata_controlcmd(atadev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode);
if (bootverbose)
- ata_prtdev(atadev, "%s setting %s on National chip\n",
- (error) ? "failed" : "success", ata_mode2str(mode));
+ device_printf(atadev->dev, "%s setting %s on National chip\n",
+ (error) ? "failed" : "success", ata_mode2str(mode));
if (!error) {
if (mode >= ATA_UDMA0) {
- pci_write_config(parent, 0x44 + (devno << 3),
+ pci_write_config(gparent, 0x44 + (devno << 3),
udmatiming[mode & ATA_MODE_MASK], 4);
}
else if (mode >= ATA_WDMA0) {
- pci_write_config(parent, 0x44 + (devno << 3),
+ pci_write_config(gparent, 0x44 + (devno << 3),
dmatiming[mode & ATA_MODE_MASK], 4);
}
else {
- pci_write_config(parent, 0x44 + (devno << 3),
- pci_read_config(parent, 0x44 + (devno << 3), 4) |
+ pci_write_config(gparent, 0x44 + (devno << 3),
+ pci_read_config(gparent, 0x44 + (devno << 3), 4) |
0x80000000, 4);
}
- pci_write_config(parent, 0x40 + (devno << 3),
+ pci_write_config(gparent, 0x40 + (devno << 3),
piotiming[ata_mode2idx(mode)], 4);
atadev->mode = mode;
}
@@ -1218,8 +1282,14 @@ ata_nvidia_ident(device_t dev)
{ ATA_NFORCE2_MCP, 0, AMDNVIDIA, NVIDIA, ATA_UDMA6, "nVidia nForce2 MCP" },
{ ATA_NFORCE3, 0, AMDNVIDIA, NVIDIA, ATA_UDMA6, "nVidia nForce3" },
{ ATA_NFORCE3_PRO, 0, AMDNVIDIA, NVIDIA, ATA_UDMA6, "nVidia nForce3 Pro" },
+ { ATA_NFORCE3_PRO_S1, 0, 0, 0, ATA_SA150, "nVidia nForce3 Pro" },
+ { ATA_NFORCE3_PRO_S2, 0, 0, 0, ATA_SA150, "nVidia nForce3 Pro" },
{ ATA_NFORCE3_MCP, 0, AMDNVIDIA, NVIDIA, ATA_UDMA6, "nVidia nForce3 MCP" },
+ { ATA_NFORCE3_MCP_S1, 0, 0, 0, ATA_SA150, "nVidia nForce3 MCP" },
+ { ATA_NFORCE3_MCP_S2, 0, 0, 0, ATA_SA150, "nVidia nForce3 MCP" },
{ ATA_NFORCE4, 0, AMDNVIDIA, NVIDIA, ATA_UDMA6, "nVidia nForce4" },
+ { ATA_NFORCE4_S1, 0, 0, 0, ATA_SA150, "nVidia nForce4" },
+ { ATA_NFORCE4_S1, 0, 0, 0, ATA_SA150, "nVidia nForce4" },
{ 0, 0, 0, 0, 0, 0}};
char buffer[64];
@@ -1241,38 +1311,52 @@ ata_nvidia_chipinit(device_t dev)
if (ata_setup_interrupt(dev))
return ENXIO;
- /* disable prefetch, postwrite */
- pci_write_config(dev, 0x51, pci_read_config(dev, 0x51, 1) & 0x0f, 1);
-
- ctlr->setmode = ata_via_family_setmode;
+ if (ctlr->chip->max_dma < ATA_SA150) {
+ /* disable prefetch, postwrite */
+ pci_write_config(dev, 0x51, pci_read_config(dev, 0x51, 1) & 0x0f, 1);
+ ctlr->setmode = ata_via_family_setmode;
+ }
+ else {
+ /* we need hotplug and proper reset code as well XXX SOS */
+ ctlr->setmode = ata_sata_setmode;
+ }
return 0;
}
/*
* Promise chipset support functions
*/
-#define ATA_PDC_APKT_OFFSET 0x00000010
-#define ATA_PDC_HPKT_OFFSET 0x00000040
-#define ATA_PDC_ASG_OFFSET 0x00000080
-#define ATA_PDC_LSG_OFFSET 0x000000c0
-#define ATA_PDC_HSG_OFFSET 0x00000100
-#define ATA_PDC_CHN_OFFSET 0x00000400
-#define ATA_PDC_BUF_BASE 0x00400000
-#define ATA_PDC_BUF_OFFSET 0x00100000
-#define ATA_PDC_MAX_HPKT 8
-#define ATA_PDC_WRITE_REG 0x00
-#define ATA_PDC_WRITE_CTL 0x0e
-#define ATA_PDC_WRITE_END 0x08
-#define ATA_PDC_WAIT_NBUSY 0x10
-#define ATA_PDC_WAIT_READY 0x18
-#define ATA_PDC_1B 0x20
-#define ATA_PDC_2B 0x40
+#define ATA_PDC_APKT_OFFSET 0x00000010
+#define ATA_PDC_HPKT_OFFSET 0x00000040
+#define ATA_PDC_ASG_OFFSET 0x00000080
+#define ATA_PDC_LSG_OFFSET 0x000000c0
+#define ATA_PDC_HSG_OFFSET 0x00000100
+#define ATA_PDC_CHN_OFFSET 0x00000400
+#define ATA_PDC_BUF_BASE 0x00400000
+#define ATA_PDC_BUF_OFFSET 0x00100000
+#define ATA_PDC_MAX_HPKT 8
+#define ATA_PDC_WRITE_REG 0x00
+#define ATA_PDC_WRITE_CTL 0x0e
+#define ATA_PDC_WRITE_END 0x08
+#define ATA_PDC_WAIT_NBUSY 0x10
+#define ATA_PDC_WAIT_READY 0x18
+#define ATA_PDC_1B 0x20
+#define ATA_PDC_2B 0x40
+
+struct host_packet {
+u_int32_t addr;
+ TAILQ_ENTRY(host_packet) chain;
+};
struct ata_promise_sx4 {
- struct mtx mtx;
- u_int32_t array[ATA_PDC_MAX_HPKT];
- int head, tail;
- int busy;
+ struct mtx mtx;
+#if 0
+ u_int32_t array[ATA_PDC_MAX_HPKT];
+ int head, tail;
+#else
+ TAILQ_HEAD(, host_packet) queue;
+#endif
+ int busy;
};
int
@@ -1281,18 +1365,18 @@ ata_promise_ident(device_t dev)
struct ata_pci_controller *ctlr = device_get_softc(dev);
struct ata_chip_id *idx;
static struct ata_chip_id ids[] =
- {{ ATA_PDC20246, 0, PROLD, 0x00, ATA_UDMA2, "Promise PDC20246" },
- { ATA_PDC20262, 0, PRNEW, 0x00, ATA_UDMA4, "Promise PDC20262" },
- { ATA_PDC20263, 0, PRNEW, 0x00, ATA_UDMA4, "Promise PDC20263" },
- { ATA_PDC20265, 0, PRNEW, 0x00, ATA_UDMA5, "Promise PDC20265" },
- { ATA_PDC20267, 0, PRNEW, 0x00, ATA_UDMA5, "Promise PDC20267" },
- { ATA_PDC20268, 0, PRTX, PRTX4, ATA_UDMA5, "Promise PDC20268" },
- { ATA_PDC20269, 0, PRTX, 0x00, ATA_UDMA6, "Promise PDC20269" },
- { ATA_PDC20270, 0, PRTX, PRTX4, ATA_UDMA5, "Promise PDC20270" },
- { ATA_PDC20271, 0, PRTX, 0x00, ATA_UDMA6, "Promise PDC20271" },
- { ATA_PDC20275, 0, PRTX, 0x00, ATA_UDMA6, "Promise PDC20275" },
- { ATA_PDC20276, 0, PRTX, PRSX6K, ATA_UDMA6, "Promise PDC20276" },
- { ATA_PDC20277, 0, PRTX, 0x00, ATA_UDMA6, "Promise PDC20277" },
+ {{ ATA_PDC20246, 0, PROLD, 0x00, ATA_UDMA2, "Promise PDC20246" },
+ { ATA_PDC20262, 0, PRNEW, 0x00, ATA_UDMA4, "Promise PDC20262" },
+ { ATA_PDC20263, 0, PRNEW, 0x00, ATA_UDMA4, "Promise PDC20263" },
+ { ATA_PDC20265, 0, PRNEW, 0x00, ATA_UDMA5, "Promise PDC20265" },
+ { ATA_PDC20267, 0, PRNEW, 0x00, ATA_UDMA5, "Promise PDC20267" },
+ { ATA_PDC20268, 0, PRTX, PRTX4, ATA_UDMA5, "Promise PDC20268" },
+ { ATA_PDC20269, 0, PRTX, 0x00, ATA_UDMA6, "Promise PDC20269" },
+ { ATA_PDC20270, 0, PRTX, PRTX4, ATA_UDMA5, "Promise PDC20270" },
+ { ATA_PDC20271, 0, PRTX, 0x00, ATA_UDMA6, "Promise PDC20271" },
+ { ATA_PDC20275, 0, PRTX, 0x00, ATA_UDMA6, "Promise PDC20275" },
+ { ATA_PDC20276, 0, PRTX, PRSX6K, ATA_UDMA6, "Promise PDC20276" },
+ { ATA_PDC20277, 0, PRTX, 0x00, ATA_UDMA6, "Promise PDC20277" },
{ ATA_PDC20318, 0, PRMIO, PRSATA, ATA_SA150, "Promise PDC20318" },
{ ATA_PDC20319, 0, PRMIO, PRSATA, ATA_SA150, "Promise PDC20319" },
{ ATA_PDC20371, 0, PRMIO, PRCMBO, ATA_SA150, "Promise PDC20371" },
@@ -1400,8 +1484,8 @@ ata_promise_chipinit(device_t dev)
break;
case PRMIO:
-// if (ctlr->r_res1)
-// bus_release_resource(dev, ctlr->r_type1, ctlr->r_rid1,ctlr->r_res1);
+// if (ctlr->r_res1)
+// bus_release_resource(dev, ctlr->r_type1, ctlr->r_rid1,ctlr->r_res1);
ctlr->r_type1 = SYS_RES_MEMORY;
ctlr->r_rid1 = PCIR_BAR(4);
if (!(ctlr->r_res1 = bus_alloc_resource_any(dev, ctlr->r_type1,
@@ -1411,43 +1495,25 @@ ata_promise_chipinit(device_t dev)
ctlr->r_type2 = SYS_RES_MEMORY;
ctlr->r_rid2 = PCIR_BAR(3);
if (!(ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2,
- &ctlr->r_rid2, RF_ACTIVE)))
+ &ctlr->r_rid2, RF_ACTIVE))){
+ bus_release_resource(dev, ctlr->r_type1, ctlr->r_rid1,ctlr->r_res1);
return ENXIO;
-
+ }
ctlr->reset = ata_promise_mio_reset;
ctlr->dmainit = ata_promise_mio_dmainit;
ctlr->allocate = ata_promise_mio_allocate;
- switch (ctlr->chip->cfg2) {
- case PRPATA:
- ctlr->channels = ((ATA_INL(ctlr->r_res2, 0x48) & 0x01) > 0) +
- ((ATA_INL(ctlr->r_res2, 0x48) & 0x02) > 0) + 2;
- break;
-
- case PRCMBO:
- ATA_OUTL(ctlr->r_res2, 0x06c, 0x000000ff);
- ctlr->channels = ((ATA_INL(ctlr->r_res2, 0x48) & 0x02) > 0) + 3;
- break;
-
- case PRSATA:
- ATA_OUTL(ctlr->r_res2, 0x06c, 0x000000ff);
- ctlr->channels = 4;
- break;
-
- case PRCMBO2:
- ATA_OUTL(ctlr->r_res2, 0x060, 0x000000ff);
- ctlr->channels = 3;
- break;
-
- case PRSATA2:
- ATA_OUTL(ctlr->r_res2, 0x060, 0x000000ff);
- ctlr->channels = 4;
- break;
-
- case PRSX4X: {
+ if (ctlr->chip->cfg2 == PRSX4X) {
struct ata_promise_sx4 *hpkt;
u_int32_t dimm = ATA_INL(ctlr->r_res2, 0x000c0080);
+ if ((bus_setup_intr(dev, ctlr->r_irq, ATA_INTR_FLAGS,
+ ata_promise_sx4_intr, ctlr, &ctlr->handle))) {
+ device_printf(dev, "unable to setup interrupt\n");
+ /* XXX SOS release resources */
+ return ENXIO;
+ }
+
/* print info about cache memory */
device_printf(dev, "DIMM size %dMB @ 0x%08x%s\n",
(((dimm >> 16) & 0xff)-((dimm >> 24) & 0xff)+1) << 4,
@@ -1455,34 +1521,63 @@ ata_promise_chipinit(device_t dev)
ATA_INL(ctlr->r_res2, 0x000c0088) & (1<<16) ?
" ECC enabled" : "" );
+ /* adjust cache memory parameters */
ATA_OUTL(ctlr->r_res2, 0x000c000c,
(ATA_INL(ctlr->r_res2, 0x000c000c) & 0xffff0000));
- ctlr->driver = malloc(sizeof(struct ata_promise_sx4),
- M_TEMP, M_NOWAIT | M_ZERO);
- hpkt = ctlr->driver;
+ /* setup host packet controls */
+ hpkt = malloc(sizeof(struct ata_promise_sx4),
+ M_TEMP, M_NOWAIT | M_ZERO);
mtx_init(&hpkt->mtx, "ATA promise HPKT lock", NULL, MTX_DEF);
- hpkt->busy = hpkt->head = hpkt->tail = 0;
-
- ctlr->channels = 4;
-
- if ((bus_setup_intr(dev, ctlr->r_irq, ATA_INTR_FLAGS,
- ata_promise_sx4_intr, ctlr, &ctlr->handle))) {
- device_printf(dev, "unable to setup interrupt\n");
- return ENXIO;
- }
+ TAILQ_INIT(&hpkt->queue);
+ hpkt->busy = 0; //hpkt->head = hpkt->tail = 0;
+ device_set_ivars(dev, hpkt);
+ ctlr->channels = 4;
return 0;
- }
}
if ((bus_setup_intr(dev, ctlr->r_irq, ATA_INTR_FLAGS,
ata_promise_mio_intr, ctlr, &ctlr->handle))) {
device_printf(dev, "unable to setup interrupt\n");
+ /* XXX SOS release resources */
return ENXIO;
}
- return 0;
+
+ switch (ctlr->chip->cfg2) {
+ case PRPATA:
+ ctlr->channels = ((ATA_INL(ctlr->r_res2, 0x48) & 0x01) > 0) +
+ ((ATA_INL(ctlr->r_res2, 0x48) & 0x02) > 0) + 2;
+ break;
+
+ case PRCMBO:
+ ATA_OUTL(ctlr->r_res2, 0x06c, 0x000000ff);
+ ctlr->channels = ((ATA_INL(ctlr->r_res2, 0x48) & 0x02) > 0) + 3;
+ break;
+
+ case PRSATA:
+ ATA_OUTL(ctlr->r_res2, 0x06c, 0x000000ff);
+ ctlr->channels = 4;
+ break;
+
+ case PRCMBO2:
+ ATA_OUTL(ctlr->r_res2, 0x060, 0x000000ff);
+ ctlr->channels = 3;
+ break;
+
+ case PRSATA2:
+ ATA_OUTL(ctlr->r_res2, 0x060, 0x000000ff);
+ ctlr->channels = 4;
+ break;
+
+ default:
+ /* XXX SOS release resources */
+ return ENXIO;
+ }
+ default:
+ /* XXX SOS release resources */
+ return ENXIO;
}
- return ENXIO;
+ return 0;
}
static int
@@ -1500,11 +1595,13 @@ ata_promise_mio_allocate(device_t dev, struct ata_channel *ch)
ch->r_io[ATA_ALTSTAT].offset = offset + 0x0238 + (ch->unit << 7);
ch->r_io[ATA_IDX_ADDR].res = ctlr->r_res2;
ch->flags |= ATA_USE_16BIT;
+
if ((ctlr->chip->cfg2 & (PRSATA | PRSATA2)) ||
((ctlr->chip->cfg2 & (PRCMBO | PRCMBO2)) && ch->unit < 2))
ch->flags |= ATA_NO_SLAVE;
+
ata_generic_hw(ch);
- if (ctlr->chip->cfg2 & PRSX4X)
+ if (offset)
ch->hw.command = ata_promise_sx4_command;
else
ch->hw.command = ata_promise_mio_command;
@@ -1516,26 +1613,74 @@ ata_promise_mio_intr(void *data)
{
struct ata_pci_controller *ctlr = data;
struct ata_channel *ch;
- u_int32_t vector = ATA_INL(ctlr->r_res2, 0x00040);
- u_int32_t status = 0;
+ u_int32_t vector = 0, status = 0;
int unit;
- if (ctlr->chip->cfg2 & (PRSATA | PRCMBO)) {
+ switch (ctlr->chip->cfg2) {
+ case PRSATA:
+ case PRCMBO:
+ /* read and acknowledge interrupt(s) */
+ vector = ATA_INL(ctlr->r_res2, 0x040);
+
+ /* read and clear interface status */
status = ATA_INL(ctlr->r_res2, 0x06c);
ATA_OUTL(ctlr->r_res2, 0x06c, status & 0x000000ff);
- }
- if (ctlr->chip->cfg2 & (PRSATA2 | PRCMBO2)) {
+ break;
+
+ case PRSATA2:
+ case PRCMBO2:
+ /* read and acknowledge interrupt(s) */
+ vector = ATA_INL(ctlr->r_res2, 0x040);
ATA_OUTL(ctlr->r_res2, 0x040, vector & 0x0000ffff);
+
+ /* read and clear interface status */
status = ATA_INL(ctlr->r_res2, 0x060);
ATA_OUTL(ctlr->r_res2, 0x060, status & 0x000000ff);
+ break;
}
+
for (unit = 0; unit < ctlr->channels; unit++) {
- if (status & (0x00000011 << unit))
- if ((ch = ctlr->interrupt[unit].argument))
- ata_promise_mio_reset(ch);
- if (vector & (1 << (unit + 1)))
- if ((ch = ctlr->interrupt[unit].argument))
- ctlr->interrupt[unit].function(ch);
+
+ if ((ch = ctlr->interrupt[unit].argument)) {
+
+ /* check for and handle disconnect events */
+ if (status & (0x00000001 << unit)) {
+ struct ata_connect_task *tp = (struct ata_connect_task *)
+ malloc(sizeof(struct ata_connect_task),
+ M_ATA, M_NOWAIT | M_ZERO);
+
+ if (bootverbose)
+ device_printf(ch->dev, "DISCONNECT requested\n");
+ tp->action = ATA_C_DETACH;
+ tp->dev = ch->dev;
+ TASK_INIT(&tp->task, 0, ata_sata_connect, tp);
+ taskqueue_enqueue(taskqueue_thread, &tp->task);
+ }
+
+ /* check for and handle connect events */
+ if (status & (0x00000010 << unit)) {
+ struct ata_connect_task *tp = (struct ata_connect_task *)
+ malloc(sizeof(struct ata_connect_task),
+ M_ATA, M_NOWAIT | M_ZERO);
+
+ if (bootverbose)
+ device_printf(ch->dev, "CONNECT requested\n");
+
+ /* if we dont get "connect well" reset the channel */
+ if (!(status & (0x00000100 << unit)))
+ ctlr->reset(ch);
+
+ tp->action = ATA_C_ATTACH;
+ tp->dev = ch->dev;
+ TASK_INIT(&tp->task, 0, ata_sata_connect, tp);
+ taskqueue_enqueue(taskqueue_thread, &tp->task);
+ }
+
+ /* active interrupt(s) need to call the interrupt handler */
+ if (vector & (1 << (unit + 1)))
+ if ((ch = ctlr->interrupt[unit].argument))
+ ctlr->interrupt[unit].function(ch);
+ }
}
}
@@ -1596,6 +1741,40 @@ ata_promise_mio_dmainit(struct ata_channel *ch)
}
}
+static int
+ata_promise_connect(struct ata_channel *ch)
+{
+ struct ata_pci_controller *ctlr =
+ device_get_softc(device_get_parent(ch->dev));
+ u_int32_t status;
+ int loop, retry;
+
+ if ((ATA_INL(ctlr->r_res2, 0x408 + (ch->unit << 8)) & 0x07) == 0) {
+ status = ATA_INL(ctlr->r_res2, 0x400 + (ch->unit << 8));
+ if ((status & 0x737) == 0x113 || (status & 0x737) == 0x123)
+ return 1;
+ }
+ for (retry = 0; retry < 10; retry++) {
+ for (loop = 0; loop < 10; loop++) {
+ ATA_OUTL(ctlr->r_res2, 0x408 + (ch->unit << 8), 1);
+ ata_udelay(100);
+ if ((ATA_INL(ctlr->r_res2, 0x408 + (ch->unit << 8)) & 0x07) == 1)
+ break;
+ }
+ ata_udelay(1000);
+ for (loop = 0; loop < 10; loop++) {
+ ATA_OUTL(ctlr->r_res2, 0x408 + (ch->unit << 8), 0);
+ ata_udelay(100);
+ if ((ATA_INL(ctlr->r_res2, 0x408 + (ch->unit << 8)) & 0x07) == 0)
+ break;
+ }
+ status = ATA_INL(ctlr->r_res2, 0x400 + (ch->unit << 8));
+ if ((status & 0x737) == 0x113 || (status & 0x737) == 0x123)
+ return 1;
+ }
+ return 0;
+}
+
static void
ata_promise_mio_reset(struct ata_channel *ch)
{
@@ -1604,42 +1783,38 @@ ata_promise_mio_reset(struct ata_channel *ch)
switch (ctlr->chip->cfg2) {
case PRSX4X: {
- struct ata_promise_sx4 *hpktp = ctlr->driver;
+ struct ata_promise_sx4 *hpktp = device_get_ivars(ctlr->dev);
/* softreset channel ATA module */
ATA_OUTL(ctlr->r_res2, 0xc0260 + (ch->unit << 7), ch->unit + 1);
- DELAY(1000);
+ ata_udelay(1000);
ATA_OUTL(ctlr->r_res2, 0xc0260 + (ch->unit << 7),
(ATA_INL(ctlr->r_res2, 0xc0260 + (ch->unit << 7)) &
~0x00003f9f) | (ch->unit + 1));
- /* softreset HOST module */
+ /* softreset HOST module XXX SOS what about other outstandings */
mtx_lock(&hpktp->mtx);
ATA_OUTL(ctlr->r_res2, 0xc012c,
(ATA_INL(ctlr->r_res2, 0xc012c) & ~0x00000f9f) | (1 << 11));
DELAY(10);
ATA_OUTL(ctlr->r_res2, 0xc012c,
(ATA_INL(ctlr->r_res2, 0xc012c) & ~0x00000f9f));
+ hpktp->busy = 0;
mtx_unlock(&hpktp->mtx);
- }
- break;
-
- case PRCMBO:
- case PRCMBO2:
- /* softreset channel ATA module */
- ATA_OUTL(ctlr->r_res2, 0x0260 + (ch->unit << 7), (1 << 11));
- ata_udelay(10000);
- ATA_OUTL(ctlr->r_res2, 0x0260 + (ch->unit << 7),
- (ATA_INL(ctlr->r_res2, 0x0260 + (ch->unit << 7)) &
- ~0x00003f9f) | (ch->unit + 1));
+ }
break;
+ case PRCMBO:
case PRSATA: {
u_int32_t status = 0;
int timeout;
- /* mask plug/unplug intr */
- ATA_OUTL(ctlr->r_res2, 0x06c, (0x00110000 << ch->unit));
+ if ((ctlr->chip->cfg2 == PRSATA) ||
+ ((ctlr->chip->cfg2 == PRCMBO) && (ch->unit < 2))) {
+
+ /* mask plug/unplug intr */
+ ATA_OUTL(ctlr->r_res2, 0x06c, (0x00110000 << ch->unit));
+ }
/* softreset channels ATA module */
ATA_OUTL(ctlr->r_res2, 0x0260 + (ch->unit << 7), (1 << 11));
@@ -1648,32 +1823,42 @@ ata_promise_mio_reset(struct ata_channel *ch)
(ATA_INL(ctlr->r_res2, 0x0260 + (ch->unit << 7)) &
~0x00003f9f) | (ch->unit + 1));
- /* enable PHY XXX SOS */
- /* wait up to 1 sec for "connect well" */
- for (timeout = 0; timeout > 1000000 ; timeout += 100) {
+ if ((ctlr->chip->cfg2 == PRSATA) ||
+ ((ctlr->chip->cfg2 == PRCMBO) && (ch->unit < 2))) {
+
+ /* enable PHY and try to connect */
+ ata_promise_connect(ch);
+
+ /* wait up to 1 sec for "connect well" */
+ for (timeout = 0; timeout < 100 ; timeout++) {
status = ATA_INL(ctlr->r_res2, 0x400 + (ch->unit << 8));
+ if (((status & 0x717) == 0x113) &&
+ (ATA_IDX_INB(ch, ATA_STATUS) != 0xff))
+ break;
+ ata_udelay(10000);
+ }
+ if (timeout >= 100)
+ device_printf(ch->dev, "connect status=%08x\n", status);
- if ((status & 0x313) == 0x112)
- break;
- ata_udelay(10000);
+ /* reset and enable plug/unplug intr */
+ ATA_OUTL(ctlr->r_res2, 0x06c, (0x00000011 << ch->unit));
+ }
}
- if (timeout >= 1000000)
- device_printf(ch->dev, "connect status=%08x\n", status);
-
- /* reset and enable plug/unplug intr */
- ATA_OUTL(ctlr->r_res2, 0x06c, (0x00000011 << ch->unit));
- }
break;
+ case PRCMBO2:
case PRSATA2: {
u_int32_t status = 0;
int timeout;
- /* set portmultiplier port */
- ATA_OUTL(ctlr->r_res2, 0x4e8 + (ch->unit << 8), 0x0f);
+ if ((ctlr->chip->cfg2 == PRSATA2) ||
+ ((ctlr->chip->cfg2 == PRCMBO2) && (ch->unit < 2))) {
+ /* set portmultiplier port */
+ ATA_OUTL(ctlr->r_res2, 0x4e8 + (ch->unit << 8), 0x0f);
- /* mask plug/unplug intr */
- ATA_OUTL(ctlr->r_res2, 0x060, (0x00110000 << ch->unit));
+ /* mask plug/unplug intr */
+ ATA_OUTL(ctlr->r_res2, 0x060, (0x00110000 << ch->unit));
+ }
/* softreset channels ATA module */
ATA_OUTL(ctlr->r_res2, 0x0260 + (ch->unit << 7), (1 << 11));
@@ -1682,28 +1867,34 @@ ata_promise_mio_reset(struct ata_channel *ch)
(ATA_INL(ctlr->r_res2, 0x0260 + (ch->unit << 7)) &
~0x00003f9f) | (ch->unit + 1));
- /* enable PHY XXX SOS */
- /* set PHY mode to "improved" */
- ATA_OUTL(ctlr->r_res2, 0x414 + (ch->unit << 8),
- (ATA_INL(ctlr->r_res2, 0x414 + (ch->unit << 8)) &
- ~0x00000003) | 0x00000001);
+ if ((ctlr->chip->cfg2 == PRSATA2) ||
+ ((ctlr->chip->cfg2 == PRCMBO2) && (ch->unit < 2))) {
- /* wait up to 1 sec for "connect well" */
- for (timeout = 0; timeout > 1000000 ; timeout += 100) {
- status = ATA_INL(ctlr->r_res2, 0x400 + (ch->unit << 8));
+ /* set PHY mode to "improved" */
+ ATA_OUTL(ctlr->r_res2, 0x414 + (ch->unit << 8),
+ (ATA_INL(ctlr->r_res2, 0x414 + (ch->unit << 8)) &
+ ~0x00000003) | 0x00000001);
- if ((status & 0x737) == 0x113 || (status & 0x727) == 0x123)
- break;
- ata_udelay(10000);
- }
- if (timeout >= 1000000)
- device_printf(ch->dev, "connect status=%08x\n", status);
+ /* enable PHY and try to connect */
+ ata_promise_connect(ch);
- /* reset and enable plug/unplug intr */
- ATA_OUTL(ctlr->r_res2, 0x060, (0x00000011 << ch->unit));
+ /* wait up to 1 sec for "connect well" */
+ for (timeout = 0; timeout < 100 ; timeout++) {
+ status = ATA_INL(ctlr->r_res2, 0x400 + (ch->unit << 8));
+ if (((status & 0x737) == 0x113 || (status & 0x737) == 0x123) &&
+ (ATA_IDX_INB(ch, ATA_STATUS) != 0xff))
+ break;
+ ata_udelay(10000);
+ }
+ if (timeout >= 100)
+ device_printf(ch->dev, "connect status=%08x\n", status);
+
+ /* reset and enable plug/unplug intr */
+ ATA_OUTL(ctlr->r_res2, 0x060, (0x00000011 << ch->unit));
- /* set portmultiplier port */
- ATA_OUTL(ctlr->r_res2, 0x4e8 + (ch->unit << 8), 0x00);
+ /* set portmultiplier port */
+ ATA_OUTL(ctlr->r_res2, 0x4e8 + (ch->unit << 8), 0x00);
+ }
}
break;
}
@@ -1713,30 +1904,29 @@ static int
ata_promise_mio_command(struct ata_device *atadev, u_int8_t command,
u_int64_t lba, u_int16_t count, u_int16_t feature)
{
- struct ata_pci_controller *ctlr =
- device_get_softc(device_get_parent(atadev->channel->dev));
- u_int32_t *wordp = (u_int32_t *)atadev->channel->dma->workspace;
+ struct ata_pci_controller *ctlr=device_get_softc(GRANDPARENT(atadev->dev));
+ struct ata_channel *ch = device_get_softc(device_get_parent(atadev->dev));
+ u_int32_t *wordp = (u_int32_t *)ch->dma->work;
- ATA_OUTL(ctlr->r_res2, (atadev->channel->unit + 1) << 2, 0x00000001);
+ ATA_OUTL(ctlr->r_res2, (ch->unit + 1) << 2, 0x00000001);
switch (command) {
default:
return ata_generic_command(atadev, command, lba, count, feature);
case ATA_READ_DMA:
- wordp[0] = htole32(0x04 | ((atadev->channel->unit+1)<<16) | (0x00<<24));
+ wordp[0] = htole32(0x04 | ((ch->unit + 1) << 16) | (0x00 << 24));
break;
case ATA_WRITE_DMA:
- wordp[0] = htole32(0x00 | ((atadev->channel->unit+1)<<16) | (0x00<<24));
+ wordp[0] = htole32(0x00 | ((ch->unit + 1) << 16) | (0x00 << 24));
break;
}
- wordp[1] = htole32(atadev->channel->dma->mdmatab);
+ wordp[1] = htole32(ch->dma->sg_bus);
wordp[2] = 0;
ata_promise_apkt((u_int8_t*)wordp, atadev, command, lba, count, feature);
- ATA_OUTL(ctlr->r_res2, 0x0240 + (atadev->channel->unit << 7),
- atadev->channel->dma->wdmatab);
+ ATA_OUTL(ctlr->r_res2, 0x0240 + (ch->unit << 7), ch->dma->work_bus);
return 0;
}
@@ -1744,10 +1934,10 @@ static int
ata_promise_sx4_command(struct ata_device *atadev, u_int8_t command,
u_int64_t lba, u_int16_t count, u_int16_t feature)
{
- struct ata_channel *ch = atadev->channel;
- struct ata_dma_prdentry *prd = ch->dma->dmatab;
- struct ata_pci_controller *ctlr =
- device_get_softc(device_get_parent(ch->dev));
+ device_t gparent = GRANDPARENT(atadev->dev);
+ struct ata_pci_controller *ctlr = device_get_softc(gparent);
+ struct ata_channel *ch = device_get_softc(device_get_parent(atadev->dev));
+ struct ata_dma_prdentry *prd = ch->dma->sg;
caddr_t window = rman_get_virtual(ctlr->r_res1);
u_int32_t *wordp;
int i, idx, length = 0;
@@ -1844,6 +2034,7 @@ static int
ata_promise_apkt(u_int8_t *bytep, struct ata_device *atadev, u_int8_t command,
u_int64_t lba, u_int16_t count, u_int16_t feature)
{
+ struct ata_channel *ch = device_get_softc(device_get_parent(atadev->dev));
int i = 12;
bytep[i++] = ATA_PDC_1B | ATA_PDC_WRITE_REG | ATA_PDC_WAIT_NBUSY|ATA_DRIVE;
@@ -1851,9 +2042,9 @@ ata_promise_apkt(u_int8_t *bytep, struct ata_device *atadev, u_int8_t command,
bytep[i++] = ATA_PDC_1B | ATA_PDC_WRITE_CTL;
bytep[i++] = ATA_A_4BIT;
- if ((lba >= ATA_MAX_28BIT_LBA || count > 256) && atadev->param &&
- (atadev->param->support.command2 & ATA_SUPPORT_ADDRESS48)) {
- atadev->channel->flags |= ATA_48BIT_ACTIVE;
+ if ((lba >= ATA_MAX_28BIT_LBA || count > 256) &&
+ (atadev->param.support.command2 & ATA_SUPPORT_ADDRESS48)) {
+ ch->flags |= ATA_48BIT_ACTIVE;
if (command == ATA_READ_DMA)
command = ATA_READ_DMA48;
if (command == ATA_WRITE_DMA)
@@ -1877,7 +2068,7 @@ ata_promise_apkt(u_int8_t *bytep, struct ata_device *atadev, u_int8_t command,
bytep[i++] = ATA_D_LBA | atadev->unit;
}
else {
- atadev->channel->flags &= ~ATA_48BIT_ACTIVE;
+ ch->flags &= ~ATA_48BIT_ACTIVE;
bytep[i++] = ATA_PDC_1B | ATA_PDC_WRITE_REG | ATA_FEATURE;
bytep[i++] = feature;
bytep[i++] = ATA_PDC_1B | ATA_PDC_WRITE_REG | ATA_COUNT;
@@ -1900,28 +2091,50 @@ ata_promise_apkt(u_int8_t *bytep, struct ata_device *atadev, u_int8_t command,
static void
ata_promise_queue_hpkt(struct ata_pci_controller *ctlr, u_int32_t hpkt)
{
- struct ata_promise_sx4 *hpktp = ctlr->driver;
+ struct ata_promise_sx4 *hpktp = device_get_ivars(ctlr->dev);
mtx_lock(&hpktp->mtx);
+#if 0
if (hpktp->tail == hpktp->head && !hpktp->busy) {
ATA_OUTL(ctlr->r_res2, 0x000c0100, hpkt);
hpktp->busy = 1;
}
else
hpktp->array[(hpktp->head++) & (ATA_PDC_MAX_HPKT - 1)] = hpkt;
+#else
+ if (hpktp->busy) {
+ struct host_packet *hp =
+ malloc(sizeof(struct host_packet), M_TEMP, M_NOWAIT | M_ZERO);
+ hp->addr = hpkt;
+ TAILQ_INSERT_TAIL(&hpktp->queue, hp, chain);
+ }
+ else {
+ hpktp->busy = 1;
+ ATA_OUTL(ctlr->r_res2, 0x000c0100, hpkt);
+ }
+#endif
mtx_unlock(&hpktp->mtx);
}
static void
ata_promise_next_hpkt(struct ata_pci_controller *ctlr)
{
- struct ata_promise_sx4 *hpktp = ctlr->driver;
+ struct ata_promise_sx4 *hpktp = device_get_ivars(ctlr->dev);
+ struct host_packet *hp;
mtx_lock(&hpktp->mtx);
+#if 0
if (hpktp->tail != hpktp->head) {
ATA_OUTL(ctlr->r_res2, 0x000c0100,
hpktp->array[(hpktp->tail++) & (ATA_PDC_MAX_HPKT - 1)]);
}
+#else
+ if ((hp = TAILQ_FIRST(&hpktp->queue))) {
+ TAILQ_REMOVE(&hpktp->queue, hp, chain);
+ ATA_OUTL(ctlr->r_res2, 0x000c0100, hp->addr);
+ free(hp, M_TEMP);
+ }
+#endif
else
hpktp->busy = 0;
mtx_unlock(&hpktp->mtx);
@@ -1995,7 +2208,7 @@ ata_promise_new_dmastart(struct ata_channel *ch)
}
ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, (ATA_IDX_INB(ch, ATA_BMSTAT_PORT) |
(ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR)));
- ATA_IDX_OUTL(ch, ATA_BMDTP_PORT, ch->dma->mdmatab);
+ ATA_IDX_OUTL(ch, ATA_BMDTP_PORT, ch->dma->sg_bus);
ATA_IDX_OUTB(ch, ATA_BMCMD_PORT,
((ch->dma->flags & ATA_DMA_READ) ? ATA_BMCMD_WRITE_READ : 0) |
ATA_BMCMD_START_STOP);
@@ -2036,26 +2249,27 @@ ata_promise_new_dmainit(struct ata_channel *ch)
static void
ata_promise_setmode(struct ata_device *atadev, int mode)
{
- device_t parent = device_get_parent(atadev->channel->dev);
- struct ata_pci_controller *ctlr = device_get_softc(parent);
- int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit);
+ device_t gparent = GRANDPARENT(atadev->dev);
+ struct ata_pci_controller *ctlr = device_get_softc(gparent);
+ struct ata_channel *ch = device_get_softc(device_get_parent(atadev->dev));
+ int devno = (ch->unit << 1) + ATA_DEV(atadev->unit);
int error;
u_int32_t timings33[][2] = {
- /* PROLD PRNEW mode */
- { 0x004ff329, 0x004fff2f }, /* PIO 0 */
- { 0x004fec25, 0x004ff82a }, /* PIO 1 */
- { 0x004fe823, 0x004ff026 }, /* PIO 2 */
- { 0x004fe622, 0x004fec24 }, /* PIO 3 */
- { 0x004fe421, 0x004fe822 }, /* PIO 4 */
- { 0x004567f3, 0x004acef6 }, /* MWDMA 0 */
- { 0x004467f3, 0x0048cef6 }, /* MWDMA 1 */
- { 0x004367f3, 0x0046cef6 }, /* MWDMA 2 */
- { 0x004367f3, 0x0046cef6 }, /* UDMA 0 */
- { 0x004247f3, 0x00448ef6 }, /* UDMA 1 */
- { 0x004127f3, 0x00436ef6 }, /* UDMA 2 */
- { 0, 0x00424ef6 }, /* UDMA 3 */
- { 0, 0x004127f3 }, /* UDMA 4 */
- { 0, 0x004127f3 } /* UDMA 5 */
+ /* PROLD PRNEW mode */
+ { 0x004ff329, 0x004fff2f }, /* PIO 0 */
+ { 0x004fec25, 0x004ff82a }, /* PIO 1 */
+ { 0x004fe823, 0x004ff026 }, /* PIO 2 */
+ { 0x004fe622, 0x004fec24 }, /* PIO 3 */
+ { 0x004fe421, 0x004fe822 }, /* PIO 4 */
+ { 0x004567f3, 0x004acef6 }, /* MWDMA 0 */
+ { 0x004467f3, 0x0048cef6 }, /* MWDMA 1 */
+ { 0x004367f3, 0x0046cef6 }, /* MWDMA 2 */
+ { 0x004367f3, 0x0046cef6 }, /* UDMA 0 */
+ { 0x004247f3, 0x00448ef6 }, /* UDMA 1 */
+ { 0x004127f3, 0x00436ef6 }, /* UDMA 2 */
+ { 0, 0x00424ef6 }, /* UDMA 3 */
+ { 0, 0x004127f3 }, /* UDMA 4 */
+ { 0, 0x004127f3 } /* UDMA 5 */
};
mode = ata_limit_mode(atadev, mode, ctlr->chip->max_dma);
@@ -2063,22 +2277,20 @@ ata_promise_setmode(struct ata_device *atadev, int mode)
switch (ctlr->chip->cfg1) {
case PROLD:
case PRNEW:
- if (mode > ATA_UDMA2 && (pci_read_config(parent, 0x50, 2) &
- (atadev->channel->unit ? 1 << 11 : 1 << 10))) {
- ata_prtdev(atadev,
- "DMA limited to UDMA33, non-ATA66 cable or device\n");
+ if (mode > ATA_UDMA2 && (pci_read_config(gparent, 0x50, 2) &
+ (ch->unit ? 1 << 11 : 1 << 10))) {
+ ata_print_cable(atadev->dev, "controller");
mode = ATA_UDMA2;
}
- if (ATAPI_DEVICE(atadev) && mode > ATA_PIO_MAX)
+ if (ata_atapi(atadev) && mode > ATA_PIO_MAX)
mode = ata_limit_mode(atadev, mode, ATA_PIO_MAX);
break;
case PRTX:
- ATA_IDX_OUTB(atadev->channel, ATA_BMDEVSPEC_0, 0x0b);
+ ATA_IDX_OUTB(ch, ATA_BMDEVSPEC_0, 0x0b);
if (mode > ATA_UDMA2 &&
- ATA_IDX_INB(atadev->channel, ATA_BMDEVSPEC_1) & 0x04) {
- ata_prtdev(atadev,
- "DMA limited to UDMA33, non-ATA66 cable or device\n");
+ ATA_IDX_INB(ch, ATA_BMDEVSPEC_1) & 0x04) {
+ ata_print_cable(atadev->dev, "controller");
mode = ATA_UDMA2;
}
break;
@@ -2087,9 +2299,8 @@ ata_promise_setmode(struct ata_device *atadev, int mode)
if (mode > ATA_UDMA2 &&
(ATA_INL(ctlr->r_res2,
(ctlr->chip->cfg2 & PRSX4X ? 0x000c0260 : 0x0260) +
- (atadev->channel->unit << 7)) & 0x01000000)) {
- ata_prtdev(atadev,
- "DMA limited to UDMA33, non-ATA66 cable or device\n");
+ (ch->unit << 7)) & 0x01000000)) {
+ ata_print_cable(atadev->dev, "controller");
mode = ATA_UDMA2;
}
break;
@@ -2098,12 +2309,12 @@ ata_promise_setmode(struct ata_device *atadev, int mode)
error = ata_controlcmd(atadev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode);
if (bootverbose)
- ata_prtdev(atadev, "%ssetting %s on %s chip\n",
- (error) ? "FAILURE " : "",
- ata_mode2str(mode), ctlr->chip->text);
+ device_printf(atadev->dev, "%ssetting %s on %s chip\n",
+ (error) ? "FAILURE " : "",
+ ata_mode2str(mode), ctlr->chip->text);
if (!error) {
if (ctlr->chip->cfg1 < PRTX)
- pci_write_config(parent, 0x60 + (devno << 2),
+ pci_write_config(gparent, 0x60 + (devno << 2),
timings33[ctlr->chip->cfg1][ata_mode2idx(mode)],4);
atadev->mode = mode;
}
@@ -2174,9 +2385,10 @@ ata_serverworks_chipinit(device_t dev)
static void
ata_serverworks_setmode(struct ata_device *atadev, int mode)
{
- device_t parent = device_get_parent(atadev->channel->dev);
- struct ata_pci_controller *ctlr = device_get_softc(parent);
- int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit);
+ device_t gparent = GRANDPARENT(atadev->dev);
+ struct ata_pci_controller *ctlr = device_get_softc(gparent);
+ struct ata_channel *ch = device_get_softc(device_get_parent(atadev->dev));
+ int devno = (ch->unit << 1) + ATA_DEV(atadev->unit);
int offset = (devno ^ 0x01) << 3;
int error;
u_int8_t piotimings[] = { 0x5d, 0x47, 0x34, 0x22, 0x20, 0x34, 0x22, 0x20,
@@ -2190,39 +2402,39 @@ ata_serverworks_setmode(struct ata_device *atadev, int mode)
error = ata_controlcmd(atadev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode);
if (bootverbose)
- ata_prtdev(atadev, "%ssetting %s on %s chip\n",
- (error) ? "FAILURE " : "",
- ata_mode2str(mode), ctlr->chip->text);
+ device_printf(atadev->dev, "%ssetting %s on %s chip\n",
+ (error) ? "FAILURE " : "",
+ ata_mode2str(mode), ctlr->chip->text);
if (!error) {
if (mode >= ATA_UDMA0) {
- pci_write_config(parent, 0x56,
- (pci_read_config(parent, 0x56, 2) &
+ pci_write_config(gparent, 0x56,
+ (pci_read_config(gparent, 0x56, 2) &
~(0xf << (devno << 2))) |
((mode & ATA_MODE_MASK) << (devno << 2)), 2);
- pci_write_config(parent, 0x54,
- pci_read_config(parent, 0x54, 1) |
+ pci_write_config(gparent, 0x54,
+ pci_read_config(gparent, 0x54, 1) |
(0x01 << devno), 1);
- pci_write_config(parent, 0x44,
- (pci_read_config(parent, 0x44, 4) &
+ pci_write_config(gparent, 0x44,
+ (pci_read_config(gparent, 0x44, 4) &
~(0xff << offset)) |
(dmatimings[2] << offset), 4);
}
else if (mode >= ATA_WDMA0) {
- pci_write_config(parent, 0x54,
- pci_read_config(parent, 0x54, 1) &
+ pci_write_config(gparent, 0x54,
+ pci_read_config(gparent, 0x54, 1) &
~(0x01 << devno), 1);
- pci_write_config(parent, 0x44,
- (pci_read_config(parent, 0x44, 4) &
+ pci_write_config(gparent, 0x44,
+ (pci_read_config(gparent, 0x44, 4) &
~(0xff << offset)) |
(dmatimings[mode & ATA_MODE_MASK] << offset),4);
}
else
- pci_write_config(parent, 0x54,
- pci_read_config(parent, 0x54, 1) &
+ pci_write_config(gparent, 0x54,
+ pci_read_config(gparent, 0x54, 1) &
~(0x01 << devno), 1);
- pci_write_config(parent, 0x40,
- (pci_read_config(parent, 0x40, 4) &
+ pci_write_config(gparent, 0x40,
+ (pci_read_config(gparent, 0x40, 4) &
~(0xff << offset)) |
(piotimings[ata_mode2idx(mode)] << offset), 4);
atadev->mode = mode;
@@ -2230,7 +2442,7 @@ ata_serverworks_setmode(struct ata_device *atadev, int mode)
}
/*
- * Silicon Image (former CMD) chipset support functions
+ * Silicon Image Inc. (SiI) (former CMD) chipset support functions
*/
int
ata_sii_ident(device_t dev)
@@ -2238,18 +2450,18 @@ ata_sii_ident(device_t dev)
struct ata_pci_controller *ctlr = device_get_softc(dev);
struct ata_chip_id *idx;
static struct ata_chip_id ids[] =
- {{ ATA_SII3114, 0x00, SIIMEMIO, SII4CH, ATA_SA150, "SiI 3114" },
- { ATA_SII3512, 0x02, SIIMEMIO, 0, ATA_SA150, "SiI 3512" },
- { ATA_SII3112, 0x02, SIIMEMIO, 0, ATA_SA150, "SiI 3112" },
- { ATA_SII3112_1, 0x02, SIIMEMIO, 0, ATA_SA150, "SiI 3112" },
- { ATA_SII3512, 0x00, SIIMEMIO, SIIBUG, ATA_SA150, "SiI 3512" },
- { ATA_SII3112, 0x00, SIIMEMIO, SIIBUG, ATA_SA150, "SiI 3112" },
- { ATA_SII3112_1, 0x00, SIIMEMIO, SIIBUG, ATA_SA150, "SiI 3112" },
+ {{ ATA_SII3114, 0x00, SIIMEMIO, SII4CH, ATA_SA150, "SiI 3114" },
+ { ATA_SII3512, 0x02, SIIMEMIO, 0, ATA_SA150, "SiI 3512" },
+ { ATA_SII3112, 0x02, SIIMEMIO, 0, ATA_SA150, "SiI 3112" },
+ { ATA_SII3112_1, 0x02, SIIMEMIO, 0, ATA_SA150, "SiI 3112" },
+ { ATA_SII3512, 0x00, SIIMEMIO, SIIBUG, ATA_SA150, "SiI 3512" },
+ { ATA_SII3112, 0x00, SIIMEMIO, SIIBUG, ATA_SA150, "SiI 3112" },
+ { ATA_SII3112_1, 0x00, SIIMEMIO, SIIBUG, ATA_SA150, "SiI 3112" },
{ ATA_SII0680, 0x00, SIIMEMIO, SIISETCLK, ATA_UDMA6, "SiI 0680" },
- { ATA_CMD649, 0x00, 0, SIIINTR, ATA_UDMA5, "CMD 649" },
- { ATA_CMD648, 0x00, 0, SIIINTR, ATA_UDMA4, "CMD 648" },
- { ATA_CMD646, 0x07, 0, 0, ATA_UDMA2, "CMD 646U2" },
- { ATA_CMD646, 0x00, 0, 0, ATA_WDMA2, "CMD 646" },
+ { ATA_CMD649, 0x00, 0, SIIINTR, ATA_UDMA5, "CMD 649" },
+ { ATA_CMD648, 0x00, 0, SIIINTR, ATA_UDMA4, "CMD 648" },
+ { ATA_CMD646, 0x07, 0, 0, ATA_UDMA2, "CMD 646U2" },
+ { ATA_CMD646, 0x00, 0, 0, ATA_WDMA2, "CMD 646" },
{ 0, 0, 0, 0, 0, 0}};
char buffer[64];
@@ -2297,14 +2509,19 @@ ata_sii_chipinit(device_t dev)
ctlr->chip->text);
}
- /* enable interrupt as BIOS might not */
- pci_write_config(dev, 0x8a, (pci_read_config(dev, 0x8a, 1) & 0x3f), 1);
-
+ /* if we have 4 channels enable the second set */
if (ctlr->chip->cfg2 & SII4CH) {
ATA_OUTL(ctlr->r_res2, 0x0200, 0x00000002);
ctlr->channels = 4;
}
+ /* enable PCI interrupt as BIOS might not */
+ pci_write_config(dev, 0x8a, (pci_read_config(dev, 0x8a, 1) & 0x3f), 1);
+
+ /* dont block interrupts from any channel */
+ pci_write_config(dev, 0x48,
+ (pci_read_config(dev, 0x48, 4) & ~0x03c00000), 4);
+
ctlr->allocate = ata_sii_allocate;
if (ctlr->chip->max_dma >= ATA_SA150) {
ctlr->reset = ata_sii_reset;
@@ -2360,14 +2577,18 @@ ata_sii_allocate(device_t dev, struct ata_channel *ch)
ch->r_io[ATA_BMDEVSPEC_1].offset = 0x100 + (unit01 << 7) + (unit10 << 8);
ch->r_io[ATA_IDX_ADDR].res = ctlr->r_res2;
- if (ctlr->chip->max_dma >= ATA_SA150)
+ if (ctlr->chip->max_dma >= ATA_SA150) {
ch->flags |= ATA_NO_SLAVE;
+ /* enable PHY state change interrupt */
+ ATA_OUTL(ctlr->r_res2, 0x148 + (unit01 << 7) + (unit10 << 8),(1 << 16));
+ }
+
if ((ctlr->chip->cfg2 & SIIBUG) && ch->dma) {
+ /* work around errata in early chips */
ch->dma->boundary = 16 * DEV_BSIZE;
ch->dma->max_iosize = 15 * DEV_BSIZE;
}
-
ata_generic_hw(ch);
return 0;
@@ -2376,10 +2597,37 @@ ata_sii_allocate(device_t dev, struct ata_channel *ch)
static void
ata_sii_reset(struct ata_channel *ch)
{
- ATA_IDX_OUTL(ch, ATA_BMDEVSPEC_1, 0x00000001);
- DELAY(25000);
- ATA_IDX_OUTL(ch, ATA_BMDEVSPEC_1, 0x00000000);
- ata_udelay(1000000);
+ struct ata_pci_controller *ctlr =
+ device_get_softc(device_get_parent(ch->dev));
+ int offset = ((ch->unit & 1) << 7) + ((ch->unit & 2) << 8);
+ u_int32_t status = 0, error;
+ int timeout;
+
+ /* disable PHY state change interrupt */
+ ATA_OUTL(ctlr->r_res2, 0x148 + offset, ~(1 << 16));
+
+ /* flip reset bit */
+ ATA_OUTL(ctlr->r_res2, 0x100 + offset, 0x00000001);
+ ata_udelay(25000);
+ ATA_OUTL(ctlr->r_res2, 0x100 + offset, 0x00000000);
+
+ /* enable PHY and try to connect XXX SOS */
+ /* wait up to 1 sec for "connect well" */
+ for (timeout = 0; timeout < 100 ; timeout++) {
+ status = ATA_INL(ctlr->r_res2, 0x104 + offset);
+ if (((status & 0x717) == 0x113) && ATA_IDX_INB(ch, ATA_STATUS) != 0xff)
+ break;
+ ata_udelay(10000);
+ }
+ if (timeout >= 100)
+ device_printf(ch->dev, "connect status=%08x\n", status);
+
+ /* clear error register */
+ error = ATA_INL(ctlr->r_res2, 0x108 + offset);
+ ATA_OUTL(ctlr->r_res2, 0x108 + offset, error);
+
+ /* enable PHY state change interrupt */
+ ATA_OUTL(ctlr->r_res2, 0x148 + offset, (1 << 16));
}
static void
@@ -2393,6 +2641,39 @@ ata_sii_intr(void *data)
for (unit = 0; unit < ctlr->channels; unit++) {
if (!(ch = ctlr->interrupt[unit].argument))
continue;
+
+ /* check for PHY related interrupts on SATA capable HW */
+ if (ctlr->chip->max_dma >= ATA_SA150) {
+ int offset = ((ch->unit & 1) << 7) + ((ch->unit & 2) << 8);
+ u_int32_t status = ATA_INL(ctlr->r_res2, 0x104 + offset);
+ u_int32_t error = ATA_INL(ctlr->r_res2, 0x108 + offset);
+
+ if (error) {
+ /* clear error bits/interrupt */
+ ATA_OUTL(ctlr->r_res2, 0x108 + offset, error);
+
+ /* if we have a connection "surprise" deal with it */
+ if (error & (1 << 16)) {
+ struct ata_connect_task *tp = (struct ata_connect_task *)
+ malloc(sizeof(struct ata_connect_task),
+ M_ATA, M_NOWAIT | M_ZERO);
+
+ if ((status & 0x717) == 0x113) {
+ device_printf(ch->dev, "CONNECT requested\n");
+ tp->action = ATA_C_ATTACH;
+ }
+ else {
+ device_printf(ch->dev, "DISCONNECT requested\n");
+ tp->action = ATA_C_DETACH;
+ }
+ tp->dev = ch->dev;
+ TASK_INIT(&tp->task, 0, ata_sata_connect, tp);
+ taskqueue_enqueue(taskqueue_thread, &tp->task);
+ }
+ }
+ }
+
+ /* any drive action to take care of ? */
if (ATA_IDX_INB(ch, ATA_BMDEVSPEC_0) & 0x08) {
if (ch->dma && (ch->dma->flags & ATA_DMA_ACTIVE)) {
int bmstat = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
@@ -2404,6 +2685,7 @@ ata_sii_intr(void *data)
}
ctlr->interrupt[unit].function(ch);
}
+
}
}
@@ -2464,21 +2746,21 @@ ata_cmd_old_intr(void *data)
static void
ata_sii_setmode(struct ata_device *atadev, int mode)
{
- device_t parent = device_get_parent(atadev->channel->dev);
- struct ata_pci_controller *ctlr = device_get_softc(parent);
- int rego = (atadev->channel->unit << 4) + (ATA_DEV(atadev->unit) << 1);
- int mreg = atadev->channel->unit ? 0x84 : 0x80;
+ device_t gparent = GRANDPARENT(atadev->dev);
+ struct ata_pci_controller *ctlr = device_get_softc(gparent);
+ struct ata_channel *ch = device_get_softc(device_get_parent(atadev->dev));
+ int rego = (ch->unit << 4) + (ATA_DEV(atadev->unit) << 1);
+ int mreg = ch->unit ? 0x84 : 0x80;
int mask = 0x03 << (ATA_DEV(atadev->unit) << 2);
- int mval = pci_read_config(parent, mreg, 1) & ~mask;
+ int mval = pci_read_config(gparent, mreg, 1) & ~mask;
int error;
mode = ata_limit_mode(atadev, mode, ctlr->chip->max_dma);
if (ctlr->chip->cfg2 & SIISETCLK) {
- if (mode > ATA_UDMA2 && (pci_read_config(parent, 0x79, 1) &
- (atadev->channel->unit ? 0x02 : 0x01))) {
- ata_prtdev(atadev,
- "DMA limited to UDMA33, non-ATA66 cable or device\n");
+ if (mode > ATA_UDMA2 && (pci_read_config(gparent, 0x79, 1) &
+ (ch->unit ? 0x02 : 0x01))) {
+ ata_print_cable(atadev->dev, "controller");
mode = ATA_UDMA2;
}
}
@@ -2488,9 +2770,9 @@ ata_sii_setmode(struct ata_device *atadev, int mode)
error = ata_controlcmd(atadev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode);
if (bootverbose)
- ata_prtdev(atadev, "%ssetting %s on %s chip\n",
- (error) ? "FAILURE " : "",
- ata_mode2str(mode), ctlr->chip->text);
+ device_printf(atadev->dev, "%ssetting %s on %s chip\n",
+ (error) ? "FAILURE " : "",
+ ata_mode2str(mode), ctlr->chip->text);
if (error)
return;
@@ -2498,10 +2780,10 @@ ata_sii_setmode(struct ata_device *atadev, int mode)
u_int8_t udmatimings[] = { 0xf, 0xb, 0x7, 0x5, 0x3, 0x2, 0x1 };
u_int8_t ureg = 0xac + rego;
- pci_write_config(parent, mreg,
+ pci_write_config(gparent, mreg,
mval | (0x03 << (ATA_DEV(atadev->unit) << 2)), 1);
- pci_write_config(parent, ureg,
- (pci_read_config(parent, ureg, 1) & ~0x3f) |
+ pci_write_config(gparent, ureg,
+ (pci_read_config(gparent, ureg, 1) & ~0x3f) |
udmatimings[mode & ATA_MODE_MASK], 1);
}
@@ -2509,18 +2791,18 @@ ata_sii_setmode(struct ata_device *atadev, int mode)
u_int8_t dreg = 0xa8 + rego;
u_int16_t dmatimings[] = { 0x2208, 0x10c2, 0x10c1 };
- pci_write_config(parent, mreg,
+ pci_write_config(gparent, mreg,
mval | (0x02 << (ATA_DEV(atadev->unit) << 2)), 1);
- pci_write_config(parent, dreg, dmatimings[mode & ATA_MODE_MASK], 2);
+ pci_write_config(gparent, dreg, dmatimings[mode & ATA_MODE_MASK], 2);
}
else {
u_int8_t preg = 0xa4 + rego;
u_int16_t piotimings[] = { 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1 };
- pci_write_config(parent, mreg,
+ pci_write_config(gparent, mreg,
mval | (0x01 << (ATA_DEV(atadev->unit) << 2)), 1);
- pci_write_config(parent, preg, piotimings[mode & ATA_MODE_MASK], 2);
+ pci_write_config(gparent, preg, piotimings[mode & ATA_MODE_MASK], 2);
}
atadev->mode = mode;
}
@@ -2528,9 +2810,10 @@ ata_sii_setmode(struct ata_device *atadev, int mode)
static void
ata_cmd_setmode(struct ata_device *atadev, int mode)
{
- device_t parent = device_get_parent(atadev->channel->dev);
- struct ata_pci_controller *ctlr = device_get_softc(parent);
- int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit);
+ device_t gparent = GRANDPARENT(atadev->dev);
+ struct ata_pci_controller *ctlr = device_get_softc(gparent);
+ struct ata_channel *ch = device_get_softc(device_get_parent(atadev->dev));
+ int devno = (ch->unit << 1) + ATA_DEV(atadev->unit);
int error;
mode = ata_limit_mode(atadev, mode, ctlr->chip->max_dma);
@@ -2540,38 +2823,38 @@ ata_cmd_setmode(struct ata_device *atadev, int mode)
error = ata_controlcmd(atadev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode);
if (bootverbose)
- ata_prtdev(atadev, "%ssetting %s on %s chip\n",
- (error) ? "FAILURE " : "",
- ata_mode2str(mode), ctlr->chip->text);
+ device_printf(atadev->dev, "%ssetting %s on %s chip\n",
+ (error) ? "FAILURE " : "",
+ ata_mode2str(mode), ctlr->chip->text);
if (!error) {
int treg = 0x54 + ((devno < 3) ? (devno << 1) : 7);
- int ureg = atadev->channel->unit ? 0x7b : 0x73;
+ int ureg = ch->unit ? 0x7b : 0x73;
- if (mode >= ATA_UDMA0) {
+ if (mode >= ATA_UDMA0) {
int udmatimings[][2] = { { 0x31, 0xc2 }, { 0x21, 0x82 },
{ 0x11, 0x42 }, { 0x25, 0x8a },
{ 0x15, 0x4a }, { 0x05, 0x0a } };
- u_int8_t umode = pci_read_config(parent, ureg, 1);
+ u_int8_t umode = pci_read_config(gparent, ureg, 1);
umode &= ~(atadev->unit == ATA_MASTER ? 0x35 : 0xca);
umode |= udmatimings[mode & ATA_MODE_MASK][ATA_DEV(atadev->unit)];
- pci_write_config(parent, ureg, umode, 1);
+ pci_write_config(gparent, ureg, umode, 1);
}
else if (mode >= ATA_WDMA0) {
int dmatimings[] = { 0x87, 0x32, 0x3f };
- pci_write_config(parent, treg, dmatimings[mode & ATA_MODE_MASK], 1);
- pci_write_config(parent, ureg,
- pci_read_config(parent, ureg, 1) &
+ pci_write_config(gparent, treg, dmatimings[mode & ATA_MODE_MASK], 1);
+ pci_write_config(gparent, ureg,
+ pci_read_config(gparent, ureg, 1) &
~(atadev->unit == ATA_MASTER ? 0x35 : 0xca), 1);
}
else {
int piotimings[] = { 0xa9, 0x57, 0x44, 0x32, 0x3f };
- pci_write_config(parent, treg,
+ pci_write_config(gparent, treg,
piotimings[(mode & ATA_MODE_MASK) - ATA_PIO0], 1);
- pci_write_config(parent, ureg,
- pci_read_config(parent, ureg, 1) &
+ pci_write_config(gparent, ureg,
+ pci_read_config(gparent, ureg, 1) &
~(atadev->unit == ATA_MASTER ? 0x35 : 0xca), 1);
}
atadev->mode = mode;
@@ -2579,7 +2862,7 @@ ata_cmd_setmode(struct ata_device *atadev, int mode)
}
/*
- * SiS chipset support functions
+ * Silicon Integrated Systems Corp. (SiS) chipset support functions
*/
int
ata_sis_ident(device_t dev)
@@ -2587,7 +2870,9 @@ ata_sis_ident(device_t dev)
struct ata_pci_controller *ctlr = device_get_softc(dev);
struct ata_chip_id *idx;
static struct ata_chip_id ids[] =
- {{ ATA_SIS964_S,0x00, SISSATA, 0, ATA_SA150, "SiS 964" }, /* south */
+ {{ ATA_SIS181, 0x00, SISSATA, 0, ATA_SA150, "SiS 181" }, /* south */
+ { ATA_SIS180, 0x00, SISSATA, 0, ATA_SA150, "SiS 180" }, /* south */
+ { ATA_SIS965, 0x00, SIS133NEW, 0, ATA_UDMA6, "SiS 965" }, /* south */
{ ATA_SIS964, 0x00, SIS133NEW, 0, ATA_UDMA6, "SiS 964" }, /* south */
{ ATA_SIS963, 0x00, SIS133NEW, 0, ATA_UDMA6, "SiS 963" }, /* south */
{ ATA_SIS962, 0x00, SIS133NEW, 0, ATA_UDMA6, "SiS 962" }, /* south */
@@ -2697,26 +2982,25 @@ ata_sis_chipinit(device_t dev)
static void
ata_sis_setmode(struct ata_device *atadev, int mode)
{
- device_t parent = device_get_parent(atadev->channel->dev);
- struct ata_pci_controller *ctlr = device_get_softc(parent);
- int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit);
+ device_t gparent = GRANDPARENT(atadev->dev);
+ struct ata_pci_controller *ctlr = device_get_softc(gparent);
+ struct ata_channel *ch = device_get_softc(device_get_parent(atadev->dev));
+ int devno = (ch->unit << 1) + ATA_DEV(atadev->unit);
int error;
mode = ata_limit_mode(atadev, mode, ctlr->chip->max_dma);
if (ctlr->chip->cfg1 == SIS133NEW) {
if (mode > ATA_UDMA2 &&
- pci_read_config(parent, atadev->channel->unit?0x52:0x50,2)&0x8000){
- ata_prtdev(atadev,
- "DMA limited to UDMA33, non-ATA66 cable or device\n");
+ pci_read_config(gparent, ch->unit ? 0x52 : 0x50,2) & 0x8000) {
+ ata_print_cable(atadev->dev, "controller");
mode = ATA_UDMA2;
}
}
else {
if (mode > ATA_UDMA2 &&
- pci_read_config(parent, 0x48, 1)&(atadev->channel->unit?0x20:0x10)){
- ata_prtdev(atadev,
- "DMA limited to UDMA33, non-ATA66 cable or device\n");
+ pci_read_config(gparent, 0x48, 1)&(ch->unit ? 0x20 : 0x10)) {
+ ata_print_cable(atadev->dev, "controller");
mode = ATA_UDMA2;
}
}
@@ -2724,9 +3008,9 @@ ata_sis_setmode(struct ata_device *atadev, int mode)
error = ata_controlcmd(atadev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode);
if (bootverbose)
- ata_prtdev(atadev, "%ssetting %s on %s chip\n",
- (error) ? "FAILURE " : "",
- ata_mode2str(mode), ctlr->chip->text);
+ device_printf(atadev->dev, "%ssetting %s on %s chip\n",
+ (error) ? "FAILURE " : "",
+ ata_mode2str(mode), ctlr->chip->text);
if (!error) {
switch (ctlr->chip->cfg1) {
case SIS133NEW: {
@@ -2736,8 +3020,8 @@ ata_sis_setmode(struct ata_device *atadev, int mode)
0x0509347c, 0x0509325c, 0x0509323c, 0x0509322c, 0x0509321c};
u_int32_t reg;
- reg = (pci_read_config(parent, 0x57, 1)&0x40?0x70:0x40)+(devno<<2);
- pci_write_config(parent, reg, timings[ata_mode2idx(mode)], 4);
+ reg = (pci_read_config(gparent, 0x57, 1)&0x40?0x70:0x40)+(devno<<2);
+ pci_write_config(gparent, reg, timings[ata_mode2idx(mode)], 4);
break;
}
case SIS133OLD: {
@@ -2747,7 +3031,7 @@ ata_sis_setmode(struct ata_device *atadev, int mode)
u_int16_t reg = 0x40 + (devno << 1);
- pci_write_config(parent, reg, timings[ata_mode2idx(mode)], 2);
+ pci_write_config(gparent, reg, timings[ata_mode2idx(mode)], 2);
break;
}
case SIS100NEW: {
@@ -2756,7 +3040,7 @@ ata_sis_setmode(struct ata_device *atadev, int mode)
0x0031, 0x8b31, 0x8731, 0x8531, 0x8431, 0x8231, 0x8131 };
u_int16_t reg = 0x40 + (devno << 1);
- pci_write_config(parent, reg, timings[ata_mode2idx(mode)], 2);
+ pci_write_config(gparent, reg, timings[ata_mode2idx(mode)], 2);
break;
}
case SIS100OLD:
@@ -2767,7 +3051,7 @@ ata_sis_setmode(struct ata_device *atadev, int mode)
0x0301, 0xf301, 0xd301, 0xb301, 0xa301, 0x9301, 0x8301 };
u_int16_t reg = 0x40 + (devno << 1);
- pci_write_config(parent, reg, timings[ata_mode2idx(mode)], 2);
+ pci_write_config(gparent, reg, timings[ata_mode2idx(mode)], 2);
break;
}
}
@@ -2775,7 +3059,7 @@ ata_sis_setmode(struct ata_device *atadev, int mode)
}
}
-/* VIA chipsets */
+/* VIA Technologies Inc. chipset support functions */
int
ata_via_ident(device_t dev)
{
@@ -2797,8 +3081,8 @@ ata_via_ident(device_t dev)
{ ATA_VIA8237, 0x00, VIA133, 0x00, ATA_UDMA6, "VIA 8237" },
{ 0, 0, 0, 0, 0, 0 }};
static struct ata_chip_id new_ids[] =
- {{ ATA_VIA6410, 0x00, 0x00, 0x00, ATA_UDMA6, "VIA 6410" },
- { ATA_VIA6420, 0x00, 0x00, 0x00, ATA_SA150, "VIA 6420" },
+ {{ ATA_VIA6410, 0x00, 0x00, 0x00, ATA_UDMA6, "VIA 6410" },
+ { ATA_VIA6420, 0x00, 0x00, 0x00, ATA_SA150, "VIA 6420" },
{ 0, 0, 0, 0, 0, 0 }};
char buffer[64];
@@ -2835,7 +3119,7 @@ ata_via_chipinit(device_t dev)
/* prepare for ATA-66 on the 82C686a and 82C596b */
if (ctlr->chip->cfg2 & VIACLK)
- pci_write_config(dev, 0x50, 0x030b030b, 4);
+ pci_write_config(dev, 0x50, 0x030b030b, 4);
/* the southbridge might need the data corruption fix */
if (ctlr->chip->cfg2 & VIABUG)
@@ -2892,17 +3176,18 @@ ata_via_southbridge_fixup(device_t dev)
static void
ata_via_family_setmode(struct ata_device *atadev, int mode)
{
- device_t parent = device_get_parent(atadev->channel->dev);
- struct ata_pci_controller *ctlr = device_get_softc(parent);
+ device_t gparent = GRANDPARENT(atadev->dev);
+ struct ata_pci_controller *ctlr = device_get_softc(gparent);
+ struct ata_channel *ch = device_get_softc(device_get_parent(atadev->dev));
u_int8_t timings[] = { 0xa8, 0x65, 0x42, 0x22, 0x20, 0x42, 0x22, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
int modes[][7] = {
- { 0xc2, 0xc1, 0xc0, 0x00, 0x00, 0x00, 0x00 }, /* VIA ATA33 */
- { 0xee, 0xec, 0xea, 0xe9, 0xe8, 0x00, 0x00 }, /* VIA ATA66 */
- { 0xf7, 0xf6, 0xf4, 0xf2, 0xf1, 0xf0, 0x00 }, /* VIA ATA100 */
- { 0xf7, 0xf7, 0xf6, 0xf4, 0xf2, 0xf1, 0xf0 }, /* VIA ATA133 */
- { 0xc2, 0xc1, 0xc0, 0xc4, 0xc5, 0xc6, 0xc7 }}; /* AMD/nVIDIA */
- int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit);
+ { 0xc2, 0xc1, 0xc0, 0x00, 0x00, 0x00, 0x00 }, /* VIA ATA33 */
+ { 0xee, 0xec, 0xea, 0xe9, 0xe8, 0x00, 0x00 }, /* VIA ATA66 */
+ { 0xf7, 0xf6, 0xf4, 0xf2, 0xf1, 0xf0, 0x00 }, /* VIA ATA100 */
+ { 0xf7, 0xf7, 0xf6, 0xf4, 0xf2, 0xf1, 0xf0 }, /* VIA ATA133 */
+ { 0xc2, 0xc1, 0xc0, 0xc4, 0xc5, 0xc6, 0xc7 }}; /* AMD/nVIDIA */
+ int devno = (ch->unit << 1) + ATA_DEV(atadev->unit);
int reg = 0x53 - devno;
int error;
@@ -2910,9 +3195,8 @@ ata_via_family_setmode(struct ata_device *atadev, int mode)
if (ctlr->chip->cfg2 & AMDCABLE) {
if (mode > ATA_UDMA2 &&
- !(pci_read_config(parent, 0x42, 1) & (1 << devno))) {
- ata_prtdev(atadev,
- "DMA limited to UDMA33, non-ATA66 cable or device\n");
+ !(pci_read_config(gparent, 0x42, 1) & (1 << devno))) {
+ ata_print_cable(atadev->dev, "controller");
mode = ATA_UDMA2;
}
}
@@ -2923,25 +3207,37 @@ ata_via_family_setmode(struct ata_device *atadev, int mode)
reg += 0x10;
if (ctlr->chip->cfg1 != VIA133)
- pci_write_config(parent, reg - 0x08, timings[ata_mode2idx(mode)], 1);
+ pci_write_config(gparent, reg - 0x08, timings[ata_mode2idx(mode)], 1);
error = ata_controlcmd(atadev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode);
if (bootverbose)
- ata_prtdev(atadev, "%ssetting %s on %s chip\n",
- (error) ? "FAILURE " : "", ata_mode2str(mode),
- ctlr->chip->text);
+ device_printf(atadev->dev, "%ssetting %s on %s chip\n",
+ (error) ? "FAILURE " : "", ata_mode2str(mode),
+ ctlr->chip->text);
if (!error) {
if (mode >= ATA_UDMA0)
- pci_write_config(parent, reg,
+ pci_write_config(gparent, reg,
modes[ctlr->chip->cfg1][mode & ATA_MODE_MASK], 1);
else
- pci_write_config(parent, reg, 0x8b, 1);
+ pci_write_config(gparent, reg, 0x8b, 1);
atadev->mode = mode;
}
}
/* misc functions */
+struct ata_chip_id *
+ata_match_chip(device_t dev, struct ata_chip_id *index)
+{
+ while (index->chipid != 0) {
+ if (pci_get_devid(dev) == index->chipid &&
+ pci_get_revid(dev) >= index->chiprev)
+ return index;
+ index++;
+ }
+ return NULL;
+}
+
static struct ata_chip_id *
ata_find_chip(device_t dev, struct ata_chip_id *index, int slot)
{
@@ -2967,18 +3263,6 @@ ata_find_chip(device_t dev, struct ata_chip_id *index, int slot)
return NULL;
}
-static struct ata_chip_id *
-ata_match_chip(device_t dev, struct ata_chip_id *index)
-{
- while (index->chipid != 0) {
- if (pci_get_devid(dev) == index->chipid &&
- pci_get_revid(dev) >= index->chiprev)
- return index;
- index++;
- }
- return NULL;
-}
-
static int
ata_setup_interrupt(device_t dev)
{
@@ -3001,9 +3285,9 @@ ata_setup_interrupt(device_t dev)
}
struct ata_serialize {
- struct mtx locked_mtx;
- int locked_ch;
- int restart_ch;
+ struct mtx locked_mtx;
+ int locked_ch;
+ int restart_ch;
};
static int
@@ -3016,16 +3300,16 @@ ata_serialize(struct ata_channel *ch, int flags)
int res;
if (!inited) {
- ctlr->driver = malloc(sizeof(struct ata_serialize),
+ serial = malloc(sizeof(struct ata_serialize),
M_TEMP, M_NOWAIT | M_ZERO);
- serial = ctlr->driver;
mtx_init(&serial->locked_mtx, "ATA serialize lock", NULL, MTX_DEF);
serial->locked_ch = -1;
serial->restart_ch = -1;
+ device_set_ivars(ctlr->dev, serial);
inited = 1;
}
else
- serial = ctlr->driver;
+ serial = device_get_ivars(ctlr->dev);
mtx_lock(&serial->locked_mtx);
switch (flags) {
@@ -3037,17 +3321,17 @@ ata_serialize(struct ata_channel *ch, int flags)
break;
case ATA_LF_UNLOCK:
- if (serial->locked_ch == ch->unit) {
- serial->locked_ch = -1;
- if (serial->restart_ch != -1) {
- if (ctlr->interrupt[serial->restart_ch].argument) {
- mtx_unlock(&serial->locked_mtx);
- ata_start(ctlr->interrupt[serial->restart_ch].argument);
- mtx_lock(&serial->locked_mtx);
- }
- serial->restart_ch = -1;
- }
- }
+ if (serial->locked_ch == ch->unit) {
+ serial->locked_ch = -1;
+ if (serial->restart_ch != -1) {
+ if ((ch = ctlr->interrupt[serial->restart_ch].argument)) {
+ serial->restart_ch = -1;
+ mtx_unlock(&serial->locked_mtx);
+ ata_start(ch->dev);
+ return -1;
+ }
+ }
+ }
break;
case ATA_LF_WHICH:
@@ -3061,8 +3345,8 @@ ata_serialize(struct ata_channel *ch, int flags)
static int
ata_check_80pin(struct ata_device *atadev, int mode)
{
- if (mode > ATA_UDMA2 && !(atadev->param->hwres & ATA_CABLE_ID)) {
- ata_prtdev(atadev,"DMA limited to UDMA33, non-ATA66 cable or device\n");
+ if (mode > ATA_UDMA2 && !(atadev->param.hwres & ATA_CABLE_ID)) {
+ ata_print_cable(atadev->dev, "device");
mode = ATA_UDMA2;
}
return mode;
diff --git a/sys/dev/ata/ata-commands.h b/sys/dev/ata/ata-commands.h
index ea27d68..4a6320b 100644
--- a/sys/dev/ata/ata-commands.h
+++ b/sys/dev/ata/ata-commands.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2004 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2005 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,101 +29,102 @@
*/
/* ATA commands */
-#define ATA_NOP 0x00 /* NOP command */
-#define ATA_NF_FLUSHQUEUE 0x00 /* flush queued cmd's */
-#define ATA_NF_AUTOPOLL 0x01 /* start autopoll function */
-#define ATA_ATAPI_RESET 0x08 /* reset ATAPI device */
-#define ATA_READ 0x20 /* read command */
-#define ATA_READ48 0x24 /* read command */
-#define ATA_READ_DMA48 0x25 /* read w/DMA command */
-#define ATA_READ_DMA_QUEUED48 0x26 /* read w/DMA QUEUED command */
-#define ATA_READ_MUL48 0x29 /* read multi command */
-#define ATA_WRITE 0x30 /* write command */
-#define ATA_WRITE48 0x34 /* write command */
-#define ATA_WRITE_DMA48 0x35 /* write w/DMA command */
-#define ATA_WRITE_DMA_QUEUED48 0x36 /* write w/DMA QUEUED command */
-#define ATA_WRITE_MUL48 0x39 /* write multi command */
-#define ATA_READ_FPDMA_QUEUED 0x60 /* read w/DMA NCQ */
-#define ATA_WRITE_FPDMA_QUEUED 0x61 /* write w/DMA NCQ */
-#define ATA_PACKET_CMD 0xa0 /* packet command */
-#define ATA_ATAPI_IDENTIFY 0xa1 /* get ATAPI params*/
-#define ATA_SERVICE 0xa2 /* service command */
-#define ATA_READ_MUL 0xc4 /* read multi command */
-#define ATA_WRITE_MUL 0xc5 /* write multi command */
-#define ATA_SET_MULTI 0xc6 /* set multi size command */
-#define ATA_READ_DMA_QUEUED 0xc7 /* read w/DMA QUEUED command */
-#define ATA_READ_DMA 0xc8 /* read w/DMA command */
-#define ATA_WRITE_DMA 0xca /* write w/DMA command */
-#define ATA_WRITE_DMA_QUEUED 0xcc /* write w/DMA QUEUED command */
-#define ATA_SLEEP 0xe6 /* sleep command */
-#define ATA_FLUSHCACHE 0xe7 /* flush cache to disk */
-#define ATA_FLUSHCACHE48 0xea /* flush cache to disk */
-#define ATA_ATA_IDENTIFY 0xec /* get ATA params */
-#define ATA_SETFEATURES 0xef /* features command */
-#define ATA_SF_SETXFER 0x03 /* set transfer mode */
-#define ATA_SF_ENAB_WCACHE 0x02 /* enable write cache */
-#define ATA_SF_DIS_WCACHE 0x82 /* disable write cache */
-#define ATA_SF_ENAB_RCACHE 0xaa /* enable readahead cache */
-#define ATA_SF_DIS_RCACHE 0x55 /* disable readahead cache */
-#define ATA_SF_ENAB_RELIRQ 0x5d /* enable release interrupt */
-#define ATA_SF_DIS_RELIRQ 0xdd /* disable release interrupt */
-#define ATA_SF_ENAB_SRVIRQ 0x5e /* enable service interrupt */
-#define ATA_SF_DIS_SRVIRQ 0xde /* disable service interrupt */
+#define ATA_NOP 0x00 /* NOP command */
+#define ATA_NF_FLUSHQUEUE 0x00 /* flush queued cmd's */
+#define ATA_NF_AUTOPOLL 0x01 /* start autopoll function */
+#define ATA_DEVICE_RESET 0x08 /* reset ATAPI device */
+#define ATA_READ 0x20 /* read command */
+#define ATA_READ48 0x24 /* read command */
+#define ATA_READ_DMA48 0x25 /* read w/DMA command */
+#define ATA_READ_DMA_QUEUED48 0x26 /* read w/DMA QUEUED command */
+#define ATA_READ_MUL48 0x29 /* read multi command */
+#define ATA_WRITE 0x30 /* write command */
+#define ATA_WRITE48 0x34 /* write command */
+#define ATA_WRITE_DMA48 0x35 /* write w/DMA command */
+#define ATA_WRITE_DMA_QUEUED48 0x36 /* write w/DMA QUEUED command */
+#define ATA_WRITE_MUL48 0x39 /* write multi command */
+#define ATA_READ_FPDMA_QUEUED 0x60 /* read w/DMA NCQ */
+#define ATA_WRITE_FPDMA_QUEUED 0x61 /* write w/DMA NCQ */
+#define ATA_SEEK 0x70 /* seek */
+#define ATA_PACKET_CMD 0xa0 /* packet command */
+#define ATA_ATAPI_IDENTIFY 0xa1 /* get ATAPI params*/
+#define ATA_SERVICE 0xa2 /* service command */
+#define ATA_READ_MUL 0xc4 /* read multi command */
+#define ATA_WRITE_MUL 0xc5 /* write multi command */
+#define ATA_SET_MULTI 0xc6 /* set multi size command */
+#define ATA_READ_DMA_QUEUED 0xc7 /* read w/DMA QUEUED command */
+#define ATA_READ_DMA 0xc8 /* read w/DMA command */
+#define ATA_WRITE_DMA 0xca /* write w/DMA command */
+#define ATA_WRITE_DMA_QUEUED 0xcc /* write w/DMA QUEUED command */
+#define ATA_SLEEP 0xe6 /* sleep command */
+#define ATA_FLUSHCACHE 0xe7 /* flush cache to disk */
+#define ATA_FLUSHCACHE48 0xea /* flush cache to disk */
+#define ATA_ATA_IDENTIFY 0xec /* get ATA params */
+#define ATA_SETFEATURES 0xef /* features command */
+#define ATA_SF_SETXFER 0x03 /* set transfer mode */
+#define ATA_SF_ENAB_WCACHE 0x02 /* enable write cache */
+#define ATA_SF_DIS_WCACHE 0x82 /* disable write cache */
+#define ATA_SF_ENAB_RCACHE 0xaa /* enable readahead cache */
+#define ATA_SF_DIS_RCACHE 0x55 /* disable readahead cache */
+#define ATA_SF_ENAB_RELIRQ 0x5d /* enable release interrupt */
+#define ATA_SF_DIS_RELIRQ 0xdd /* disable release interrupt */
+#define ATA_SF_ENAB_SRVIRQ 0x5e /* enable service interrupt */
+#define ATA_SF_DIS_SRVIRQ 0xde /* disable service interrupt */
/* ATAPI commands */
-#define ATAPI_TEST_UNIT_READY 0x00 /* check if device is ready */
-#define ATAPI_REZERO 0x01 /* rewind */
-#define ATAPI_REQUEST_SENSE 0x03 /* get sense data */
-#define ATAPI_FORMAT 0x04 /* format unit */
-#define ATAPI_READ 0x08 /* read data */
-#define ATAPI_WRITE 0x0a /* write data */
-#define ATAPI_WEOF 0x10 /* write filemark */
-#define ATAPI_WF_WRITE 0x01
-#define ATAPI_SPACE 0x11 /* space command */
-#define ATAPI_SP_FM 0x01
-#define ATAPI_SP_EOD 0x03
-#define ATAPI_MODE_SELECT 0x15 /* mode select */
-#define ATAPI_ERASE 0x19 /* erase */
-#define ATAPI_MODE_SENSE 0x1a /* mode sense */
-#define ATAPI_START_STOP 0x1b /* start/stop unit */
-#define ATAPI_SS_LOAD 0x01
-#define ATAPI_SS_RETENSION 0x02
-#define ATAPI_SS_EJECT 0x04
-#define ATAPI_PREVENT_ALLOW 0x1e /* media removal */
-#define ATAPI_READ_FORMAT_CAPACITIES 0x23 /* get format capacities */
-#define ATAPI_READ_CAPACITY 0x25 /* get volume capacity */
-#define ATAPI_READ_BIG 0x28 /* read data */
-#define ATAPI_WRITE_BIG 0x2a /* write data */
-#define ATAPI_LOCATE 0x2b /* locate to position */
-#define ATAPI_READ_POSITION 0x34 /* read position */
-#define ATAPI_SYNCHRONIZE_CACHE 0x35 /* flush buf, close channel */
-#define ATAPI_WRITE_BUFFER 0x3b /* write device buffer */
-#define ATAPI_READ_BUFFER 0x3c /* read device buffer */
-#define ATAPI_READ_SUBCHANNEL 0x42 /* get subchannel info */
-#define ATAPI_READ_TOC 0x43 /* get table of contents */
-#define ATAPI_PLAY_10 0x45 /* play by lba */
-#define ATAPI_PLAY_MSF 0x47 /* play by MSF address */
-#define ATAPI_PLAY_TRACK 0x48 /* play by track number */
-#define ATAPI_PAUSE 0x4b /* pause audio operation */
-#define ATAPI_READ_DISK_INFO 0x51 /* get disk info structure */
-#define ATAPI_READ_TRACK_INFO 0x52 /* get track info structure */
-#define ATAPI_RESERVE_TRACK 0x53 /* reserve track */
-#define ATAPI_SEND_OPC_INFO 0x54 /* send OPC structurek */
-#define ATAPI_MODE_SELECT_BIG 0x55 /* set device parameters */
-#define ATAPI_REPAIR_TRACK 0x58 /* repair track */
-#define ATAPI_READ_MASTER_CUE 0x59 /* read master CUE info */
-#define ATAPI_MODE_SENSE_BIG 0x5a /* get device parameters */
-#define ATAPI_CLOSE_TRACK 0x5b /* close track/session */
-#define ATAPI_READ_BUFFER_CAPACITY 0x5c /* get buffer capicity */
-#define ATAPI_SEND_CUE_SHEET 0x5d /* send CUE sheet */
-#define ATAPI_BLANK 0xa1 /* blank the media */
-#define ATAPI_SEND_KEY 0xa3 /* send DVD key structure */
-#define ATAPI_REPORT_KEY 0xa4 /* get DVD key structure */
-#define ATAPI_PLAY_12 0xa5 /* play by lba */
-#define ATAPI_LOAD_UNLOAD 0xa6 /* changer control command */
-#define ATAPI_READ_STRUCTURE 0xad /* get DVD structure */
-#define ATAPI_PLAY_CD 0xb4 /* universal play command */
-#define ATAPI_SET_SPEED 0xbb /* set drive speed */
-#define ATAPI_MECH_STATUS 0xbd /* get changer status */
-#define ATAPI_READ_CD 0xbe /* read data */
-#define ATAPI_POLL_DSC 0xff /* poll DSC status bit */
+#define ATAPI_TEST_UNIT_READY 0x00 /* check if device is ready */
+#define ATAPI_REZERO 0x01 /* rewind */
+#define ATAPI_REQUEST_SENSE 0x03 /* get sense data */
+#define ATAPI_FORMAT 0x04 /* format unit */
+#define ATAPI_READ 0x08 /* read data */
+#define ATAPI_WRITE 0x0a /* write data */
+#define ATAPI_WEOF 0x10 /* write filemark */
+#define ATAPI_WF_WRITE 0x01
+#define ATAPI_SPACE 0x11 /* space command */
+#define ATAPI_SP_FM 0x01
+#define ATAPI_SP_EOD 0x03
+#define ATAPI_MODE_SELECT 0x15 /* mode select */
+#define ATAPI_ERASE 0x19 /* erase */
+#define ATAPI_MODE_SENSE 0x1a /* mode sense */
+#define ATAPI_START_STOP 0x1b /* start/stop unit */
+#define ATAPI_SS_LOAD 0x01
+#define ATAPI_SS_RETENSION 0x02
+#define ATAPI_SS_EJECT 0x04
+#define ATAPI_PREVENT_ALLOW 0x1e /* media removal */
+#define ATAPI_READ_FORMAT_CAPACITIES 0x23 /* get format capacities */
+#define ATAPI_READ_CAPACITY 0x25 /* get volume capacity */
+#define ATAPI_READ_BIG 0x28 /* read data */
+#define ATAPI_WRITE_BIG 0x2a /* write data */
+#define ATAPI_LOCATE 0x2b /* locate to position */
+#define ATAPI_READ_POSITION 0x34 /* read position */
+#define ATAPI_SYNCHRONIZE_CACHE 0x35 /* flush buf, close channel */
+#define ATAPI_WRITE_BUFFER 0x3b /* write device buffer */
+#define ATAPI_READ_BUFFER 0x3c /* read device buffer */
+#define ATAPI_READ_SUBCHANNEL 0x42 /* get subchannel info */
+#define ATAPI_READ_TOC 0x43 /* get table of contents */
+#define ATAPI_PLAY_10 0x45 /* play by lba */
+#define ATAPI_PLAY_MSF 0x47 /* play by MSF address */
+#define ATAPI_PLAY_TRACK 0x48 /* play by track number */
+#define ATAPI_PAUSE 0x4b /* pause audio operation */
+#define ATAPI_READ_DISK_INFO 0x51 /* get disk info structure */
+#define ATAPI_READ_TRACK_INFO 0x52 /* get track info structure */
+#define ATAPI_RESERVE_TRACK 0x53 /* reserve track */
+#define ATAPI_SEND_OPC_INFO 0x54 /* send OPC structurek */
+#define ATAPI_MODE_SELECT_BIG 0x55 /* set device parameters */
+#define ATAPI_REPAIR_TRACK 0x58 /* repair track */
+#define ATAPI_READ_MASTER_CUE 0x59 /* read master CUE info */
+#define ATAPI_MODE_SENSE_BIG 0x5a /* get device parameters */
+#define ATAPI_CLOSE_TRACK 0x5b /* close track/session */
+#define ATAPI_READ_BUFFER_CAPACITY 0x5c /* get buffer capicity */
+#define ATAPI_SEND_CUE_SHEET 0x5d /* send CUE sheet */
+#define ATAPI_BLANK 0xa1 /* blank the media */
+#define ATAPI_SEND_KEY 0xa3 /* send DVD key structure */
+#define ATAPI_REPORT_KEY 0xa4 /* get DVD key structure */
+#define ATAPI_PLAY_12 0xa5 /* play by lba */
+#define ATAPI_LOAD_UNLOAD 0xa6 /* changer control command */
+#define ATAPI_READ_STRUCTURE 0xad /* get DVD structure */
+#define ATAPI_PLAY_CD 0xb4 /* universal play command */
+#define ATAPI_SET_SPEED 0xbb /* set drive speed */
+#define ATAPI_MECH_STATUS 0xbd /* get changer status */
+#define ATAPI_READ_CD 0xbe /* read data */
+#define ATAPI_POLL_DSC 0xff /* poll DSC status bit */
diff --git a/sys/dev/ata/ata-disk.c b/sys/dev/ata/ata-disk.c
index 2a338c6..9183645 100644
--- a/sys/dev/ata/ata-disk.c
+++ b/sys/dev/ata/ata-disk.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2004 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2005 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/ata.h>
#include <sys/kernel.h>
+#include <sys/module.h>
#include <sys/malloc.h>
#include <sys/bio.h>
#include <sys/bus.h>
@@ -52,287 +53,225 @@ __FBSDID("$FreeBSD$");
#include <dev/ata/ata-pci.h>
#include <dev/ata/ata-disk.h>
#include <dev/ata/ata-raid.h>
+#include <ata_if.h>
/* prototypes */
-static void ad_detach(struct ata_device *);
-static void ad_config(struct ata_device *);
-static void ad_start(struct ata_device *);
+static void ad_init(device_t);
static void ad_done(struct ata_request *);
-static disk_open_t adopen;
-static disk_strategy_t adstrategy;
-static dumper_t addump;
-void ad_print(struct ad_softc *);
+static void ad_describe(device_t dev);
static int ad_version(u_int16_t);
+static disk_strategy_t ad_strategy;
+static dumper_t ad_dump;
-/* internal vars */
+/* local vars */
static MALLOC_DEFINE(M_AD, "AD driver", "ATA disk driver");
-static u_int32_t adp_lun_map = 0;
-void
-ad_attach(struct ata_device *atadev)
+static void
+ad_identify(driver_t *driver, device_t parent)
{
+ ata_identify(driver, parent, -1, "ad");
+}
+
+static int
+ad_probe(device_t dev)
+{
+ return 0;
+}
+
+static int
+ad_attach(device_t dev)
+{
+ struct ata_channel *ch = device_get_softc(device_get_parent(dev));
+ struct ata_device *atadev = device_get_softc(dev);
struct ad_softc *adp;
u_int32_t lbasize;
u_int64_t lbasize48;
+ /* check that we have a virgin disk to attach */
+ if (device_get_ivars(dev))
+ return EEXIST;
+
if (!(adp = malloc(sizeof(struct ad_softc), M_AD, M_NOWAIT | M_ZERO))) {
- ata_prtdev(atadev, "FAILURE - could not allocate driver storage\n");
- atadev->attach = NULL;
- return;
+ device_printf(dev, "out of memory\n");
+ device_set_softc(dev, NULL);
+ free(atadev, M_ATA);
+ return ENOMEM;
}
- atadev->softc = adp;
- adp->device = atadev;
-
-#ifdef ATA_STATIC_ID
- adp->lun = (device_get_unit(atadev->channel->dev)<<1)+ATA_DEV(atadev->unit);
-#else
- adp->lun = ata_get_lun(&adp_lun_map);
-#endif
- ata_set_name(atadev, "ad", adp->lun);
- adp->heads = atadev->param->heads;
- adp->sectors = atadev->param->sectors;
- adp->total_secs = atadev->param->cylinders * adp->heads * adp->sectors;
-#ifdef PC98
- /*
- * During the BOOT process, the PC-98 BIOS sets fake geometry of
- * xxxx/8/17 of the disk using 'INITIALIZE DEVICE PARAMETER (91h)'
- * command. After this command, all access to the drive must be done
- * via the new, fake geometry, rather than the old, native format.
- * With ATA/ATAPI-6 or later, these parameters are obsolete, but
- * PC-98s are still using them.
- *
- * This only really matters when we're talking to disks using CHS
- * mode, not LBA mode. The CHS mode disks are still relatively
- * common in these machines, so that case must be addressed.
- *
- * (ITF sets new CHS geometry to initialized disks.)
- *
- * obsolete54[0]: current cylinder
- * obsolete54[1]: current heads
- * obsolete54[2]: current sectors
- * obsolete54[3-4]: current capacities(multiplied above 3 values)
- */
- /* Get CHS geometry from set by Initialize Device Parameters command. */
- if ((atadev->param->atavalid & ATA_FLAG_54_58) ||
- (atadev->param->obsolete54[0] != 0 &&
- atadev->param->obsolete54[1] != 0 &&
- atadev->param->obsolete54[2] != 0)) {
- adp->heads = atadev->param->obsolete54[1];
- adp->sectors = atadev->param->obsolete54[2];
- adp->total_secs = *(u_int32_t*)&(atadev->param->obsolete54[3]);
- }
-#endif
-
- mtx_init(&adp->queue_mtx, "ATA disk bioqueue lock", NULL, MTX_DEF);
- bioq_init(&adp->queue);
+ device_set_ivars(dev, adp);
- lbasize = (u_int32_t)atadev->param->lba_size_1 |
- ((u_int32_t)atadev->param->lba_size_2 << 16);
+ if (atadev->param.atavalid & ATA_FLAG_54_58) {
+ adp->heads = atadev->param.current_heads;
+ adp->sectors = atadev->param.current_sectors;
+ adp->total_secs = (u_int32_t)atadev->param.current_size_1 |
+ ((u_int32_t)atadev->param.current_size_2 << 16);
+ }
+ else {
+ adp->heads = atadev->param.heads;
+ adp->sectors = atadev->param.sectors;
+ adp->total_secs = atadev->param.cylinders * adp->heads * adp->sectors;
+ }
+ lbasize = (u_int32_t)atadev->param.lba_size_1 |
+ ((u_int32_t)atadev->param.lba_size_2 << 16);
/* does this device need oldstyle CHS addressing */
- if (!ad_version(atadev->param->version_major) || !lbasize)
+ if (!ad_version(atadev->param.version_major) || !lbasize)
atadev->flags |= ATA_D_USE_CHS;
/* use the 28bit LBA size if valid or bigger than the CHS mapping */
- if (atadev->param->cylinders == 16383 || adp->total_secs < lbasize)
+ if (atadev->param.cylinders == 16383 || adp->total_secs < lbasize)
adp->total_secs = lbasize;
- lbasize48 = ((u_int64_t)atadev->param->lba_size48_1) |
- ((u_int64_t)atadev->param->lba_size48_2 << 16) |
- ((u_int64_t)atadev->param->lba_size48_3 << 32) |
- ((u_int64_t)atadev->param->lba_size48_4 << 48);
-
/* use the 48bit LBA size if valid */
- if ((atadev->param->support.command2 & ATA_SUPPORT_ADDRESS48) &&
+ lbasize48 = ((u_int64_t)atadev->param.lba_size48_1) |
+ ((u_int64_t)atadev->param.lba_size48_2 << 16) |
+ ((u_int64_t)atadev->param.lba_size48_3 << 32) |
+ ((u_int64_t)atadev->param.lba_size48_4 << 48);
+ if ((atadev->param.support.command2 & ATA_SUPPORT_ADDRESS48) &&
lbasize48 > ATA_MAX_28BIT_LBA)
adp->total_secs = lbasize48;
- /* setup the function ptrs */
- atadev->detach = ad_detach;
- atadev->config = ad_config;
- atadev->start = ad_start;
+ /* init device parameters */
+ ad_init(dev);
- /* config device features */
- ad_config(atadev);
+ /* announce we are here */
+ ad_describe(dev);
- /* lets create the disk device */
+ /* create the disk device */
adp->disk = disk_alloc();
- adp->disk->d_open = adopen;
- adp->disk->d_strategy = adstrategy;
- adp->disk->d_dump = addump;
+ adp->disk->d_strategy = ad_strategy;
+ adp->disk->d_dump = ad_dump;
adp->disk->d_name = "ad";
- adp->disk->d_drv1 = adp;
- if (atadev->channel->dma)
- adp->disk->d_maxsize = atadev->channel->dma->max_iosize;
+ adp->disk->d_drv1 = dev;
+ if (ch->dma)
+ adp->disk->d_maxsize = ch->dma->max_iosize;
else
adp->disk->d_maxsize = DFLTPHYS;
adp->disk->d_sectorsize = DEV_BSIZE;
adp->disk->d_mediasize = DEV_BSIZE * (off_t)adp->total_secs;
adp->disk->d_fwsectors = adp->sectors;
adp->disk->d_fwheads = adp->heads;
- adp->disk->d_unit = adp->lun;
+ adp->disk->d_unit = device_get_unit(dev);
disk_create(adp->disk, DISK_VERSION);
-
- /* announce we are here */
- ad_print(adp);
-
-#ifdef DEV_ATARAID
- ata_raiddisk_attach(adp);
-#endif
+ device_add_child(dev, "subdisk", device_get_unit(dev));
+ bus_generic_attach(dev);
+ return 0;
}
-static void
-ad_detach(struct ata_device *atadev)
+static int
+ad_detach(device_t dev)
{
- struct ad_softc *adp = atadev->softc;
+ struct ata_channel *ch = device_get_softc(device_get_parent(dev));
+ struct ata_device *atadev = device_get_softc(dev);
+ struct ad_softc *adp = device_get_ivars(dev);
+ device_t *children;
+ int nchildren, i;
+
+ /* check that we have a valid disk to detach */
+ if (!device_get_ivars(dev))
+ return ENXIO;
+
+ /* detach & delete all children */
+ if (!device_get_children(dev, &children, &nchildren)) {
+ for (i = 0; i < nchildren; i++)
+ if (children[i])
+ device_delete_child(dev, children[i]);
+ free(children, M_TEMP);
+ }
-#ifdef DEV_ATARAID
- if (adp->flags & AD_F_RAID_SUBDISK)
- ata_raiddisk_detach(adp);
-#endif
+ /* detroy disk from the system so we dont get any further requests */
disk_destroy(adp->disk);
- ata_prtdev(atadev, "WARNING - removed from configuration\n");
- mtx_lock(&adp->queue_mtx);
- bioq_flush(&adp->queue, NULL, ENXIO);
- mtx_unlock(&adp->queue_mtx);
- mtx_destroy(&adp->queue_mtx);
- ata_free_name(atadev);
- ata_free_lun(&adp_lun_map, adp->lun);
- atadev->attach = NULL;
- atadev->detach = NULL;
- atadev->start = NULL;
- atadev->softc = NULL;
- atadev->flags = 0;
+
+ /* fail requests on the queue and any thats "in flight" for this device */
+ ata_fail_requests(ch, dev);
+
+ /* dont leave anything behind */
+ device_set_ivars(dev, NULL);
free(adp, M_AD);
+ device_set_softc(dev, NULL);
+ free(atadev, M_ATA);
+ return 0;
}
static void
-ad_config(struct ata_device *atadev)
+ad_shutdown(device_t dev)
{
- struct ad_softc *adp = atadev->softc;
-
- /* enable read caching */
- ata_controlcmd(atadev, ATA_SETFEATURES, ATA_SF_ENAB_RCACHE, 0, 0);
-
- /* enable write caching if enabled */
- if (ata_wc)
- ata_controlcmd(atadev, ATA_SETFEATURES, ATA_SF_ENAB_WCACHE, 0, 0);
- else
- ata_controlcmd(atadev, ATA_SETFEATURES, ATA_SF_DIS_WCACHE, 0, 0);
-
- /* use multiple sectors/interrupt if device supports it */
- adp->max_iosize = DEV_BSIZE;
- if (ad_version(atadev->param->version_major)) {
- int secsperint = max(1, min(atadev->param->sectors_intr, 16));
+ struct ata_device *atadev = device_get_softc(dev);
- if (!ata_controlcmd(atadev, ATA_SET_MULTI, 0, 0, secsperint))
- adp->max_iosize = secsperint * DEV_BSIZE;
- }
+ if (atadev->param.support.command2 & ATA_SUPPORT_FLUSHCACHE)
+ ata_controlcmd(atadev, ATA_FLUSHCACHE, 0, 0, 0);
}
static int
-adopen(struct disk *dp)
+ad_reinit(device_t dev)
{
- struct ad_softc *adp = dp->d_drv1;
+ struct ata_channel *ch = device_get_softc(device_get_parent(dev));
+ struct ata_device *atadev = device_get_softc(dev);
- if (adp == NULL || adp->device->flags & ATA_D_DETACHING)
- return ENXIO;
+ /* if detach pending flag set, return error */
+
+ if (((atadev->unit == ATA_MASTER) && !(ch->devices & ATA_ATA_MASTER)) ||
+ ((atadev->unit == ATA_SLAVE) && !(ch->devices & ATA_ATA_SLAVE))) {
+ return 1;
+ }
+ ad_init(dev);
return 0;
}
static void
-adstrategy(struct bio *bp)
-{
- struct ad_softc *adp = bp->bio_disk->d_drv1;
-
- mtx_lock(&adp->queue_mtx);
- bioq_disksort(&adp->queue, bp);
- mtx_unlock(&adp->queue_mtx);
- ata_start(adp->device->channel);
-}
-
-static void
-ad_start(struct ata_device *atadev)
+ad_strategy(struct bio *bp)
{
- struct ad_softc *adp = atadev->softc;
- struct bio *bp;
+ device_t dev = bp->bio_disk->d_drv1;
+ struct ata_device *atadev = device_get_softc(dev);
struct ata_request *request;
- /* remove request from drive queue */
- mtx_lock(&adp->queue_mtx);
- bp = bioq_first(&adp->queue);
- if (!bp) {
- mtx_unlock(&adp->queue_mtx);
- return;
- }
- bioq_remove(&adp->queue, bp);
- mtx_unlock(&adp->queue_mtx);
- if (adp->device->flags & ATA_D_DETACHING) {
- biofinish(bp, NULL, ENXIO);
- return;
- }
-
if (!(request = ata_alloc_request())) {
- ata_prtdev(atadev, "FAILURE - out of memory in start\n");
+ device_printf(dev, "FAILURE - out of memory in start\n");
biofinish(bp, NULL, ENOMEM);
return;
}
/* setup request */
- request->device = atadev;
+ request->dev = dev;
request->bio = bp;
request->callback = ad_done;
request->timeout = 5;
request->retries = 2;
request->data = bp->bio_data;
request->bytecount = bp->bio_bcount;
-
- /* convert LBA contents if this is an old non-LBA device */
- if (atadev->flags & ATA_D_USE_CHS) {
- int sector = (bp->bio_pblkno % adp->sectors) + 1;
- int cylinder = bp->bio_pblkno / (adp->sectors * adp->heads);
- int head = (bp->bio_pblkno %
- (adp->sectors * adp->heads)) / adp->sectors;
-
- request->u.ata.lba =
- (sector & 0xff) | (cylinder & 0xffff) << 8 | (head & 0xf) << 24;
- }
- else
- request->u.ata.lba = bp->bio_pblkno;
-
+ request->u.ata.lba = bp->bio_pblkno;
request->u.ata.count = request->bytecount / DEV_BSIZE;
- request->transfersize = min(bp->bio_bcount, adp->max_iosize);
+ request->transfersize = min(bp->bio_bcount, atadev->max_iosize);
switch (bp->bio_cmd) {
case BIO_READ:
- request->flags |= ATA_R_READ;
+ request->flags = ATA_R_READ;
if (atadev->mode >= ATA_DMA) {
request->u.ata.command = ATA_READ_DMA;
request->flags |= ATA_R_DMA;
}
- else if (adp->max_iosize > DEV_BSIZE)
+ else if (atadev->max_iosize > DEV_BSIZE)
request->u.ata.command = ATA_READ_MUL;
else
request->u.ata.command = ATA_READ;
-
break;
case BIO_WRITE:
- request->flags |= ATA_R_WRITE;
+ request->flags = ATA_R_WRITE;
if (atadev->mode >= ATA_DMA) {
request->u.ata.command = ATA_WRITE_DMA;
request->flags |= ATA_R_DMA;
}
- else if (adp->max_iosize > DEV_BSIZE)
+ else if (atadev->max_iosize > DEV_BSIZE)
request->u.ata.command = ATA_WRITE_MUL;
else
request->u.ata.command = ATA_WRITE;
break;
default:
- ata_prtdev(atadev, "FAILURE - unknown BIO operation\n");
+ device_printf(dev, "FAILURE - unknown BIO operation\n");
ata_free_request(request);
biofinish(bp, NULL, EIO);
return;
}
+ request->flags |= ATA_R_ORDERED;
ata_queue_request(request);
}
@@ -350,25 +289,28 @@ ad_done(struct ata_request *request)
}
static int
-addump(void *arg, void *virtual, vm_offset_t physical,
+ad_dump(void *arg, void *virtual, vm_offset_t physical,
off_t offset, size_t length)
{
- struct ata_request request;
struct disk *dp = arg;
- struct ad_softc *adp = dp->d_drv1;
+ device_t dev = dp->d_drv1;
+ struct ata_device *atadev = device_get_softc(dev);
+ struct ad_softc *adp = device_get_ivars(dev);
+ struct ata_channel *ch = device_get_softc(device_get_parent(dev));
+ struct ata_request request;
if (!adp)
return ENXIO;
bzero(&request, sizeof(struct ata_request));
- request.device = adp->device;
+ request.dev = dev;
if (length) {
request.data = virtual;
request.bytecount = length;
- request.transfersize = min(length, adp->max_iosize);
+ request.transfersize = min(length, atadev->max_iosize);
request.flags = ATA_R_WRITE;
- if (adp->max_iosize > DEV_BSIZE)
+ if (atadev->max_iosize > DEV_BSIZE)
request.u.ata.command = ATA_WRITE_MUL;
else
request.u.ata.command = ATA_WRITE;
@@ -379,13 +321,10 @@ addump(void *arg, void *virtual, vm_offset_t physical,
request.u.ata.command = ATA_FLUSHCACHE;
request.flags = ATA_R_CONTROL;
}
-
- if (request.device->channel->
- hw.begin_transaction(&request) == ATA_OP_CONTINUES) {
+ if (ch->hw.begin_transaction(&request) == ATA_OP_CONTINUES) {
do {
DELAY(20);
- } while (request.device->channel->
- hw.end_transaction(&request) == ATA_OP_CONTINUES);
+ } while (ch->hw.end_transaction(&request) == ATA_OP_CONTINUES);
ata_finish(&request);
}
if (request.status & ATA_S_ERROR)
@@ -393,43 +332,75 @@ addump(void *arg, void *virtual, vm_offset_t physical,
return 0;
}
+static void
+ad_init(device_t dev)
+{
+ struct ata_device *atadev = device_get_softc(dev);
+
+ ATA_SETMODE(GRANDPARENT(dev), dev);
+
+ /* enable read caching */
+ ata_controlcmd(atadev, ATA_SETFEATURES, ATA_SF_ENAB_RCACHE, 0, 0);
+
+ /* enable write caching if enabled */
+ if (ata_wc)
+ ata_controlcmd(atadev, ATA_SETFEATURES, ATA_SF_ENAB_WCACHE, 0, 0);
+ else
+ ata_controlcmd(atadev, ATA_SETFEATURES, ATA_SF_DIS_WCACHE, 0, 0);
+
+ /* use multiple sectors/interrupt if device supports it */
+ if (ad_version(atadev->param.version_major)) {
+ int secsperint = max(1, min(atadev->param.sectors_intr, 16));
+
+ if (!ata_controlcmd(atadev, ATA_SET_MULTI, 0, 0, secsperint))
+ atadev->max_iosize = secsperint * DEV_BSIZE;
+ }
+ else
+ atadev->max_iosize = DEV_BSIZE;
+}
+
void
-ad_print(struct ad_softc *adp)
+ad_describe(device_t dev)
{
- if (bootverbose) {
- ata_prtdev(adp->device, "<%.40s/%.8s> ATA-%d disk at ata%d-%s\n",
- adp->device->param->model, adp->device->param->revision,
- ad_version(adp->device->param->version_major),
- device_get_unit(adp->device->channel->dev),
- (adp->device->unit == ATA_MASTER) ? "master" : "slave");
-
- ata_prtdev(adp->device,
- "%lluMB (%llu sectors), %llu C, %u H, %u S, %u B\n",
- (unsigned long long)(adp->total_secs /
- ((1024L*1024L)/DEV_BSIZE)),
- (unsigned long long)adp->total_secs,
- (unsigned long long)(adp->total_secs /
- (adp->heads * adp->sectors)),
- adp->heads, adp->sectors, DEV_BSIZE);
-
- ata_prtdev(adp->device, "%d secs/int, %d depth queue, %s%s\n",
- adp->max_iosize / DEV_BSIZE, adp->num_tags + 1,
- (adp->flags & AD_F_TAG_ENABLED) ? "tagged " : "",
- ata_mode2str(adp->device->mode));
+ struct ata_channel *ch = device_get_softc(device_get_parent(dev));
+ struct ata_device *atadev = device_get_softc(dev);
+ struct ad_softc *adp = device_get_ivars(dev);
+ u_int8_t *marker, vendor[64], product[64];
+
+ /* try to seperate the ATA model string into vendor and model parts */
+ if ((marker = index(atadev->param.model, ' ')) ||
+ (marker = index(atadev->param.model, '-'))) {
+ int len = (marker - atadev->param.model);
+
+ strncpy(vendor, atadev->param.model, len);
+ vendor[len++] = 0;
+ strcat(vendor, " ");
+ strncpy(product, atadev->param.model + len, 40 - len);
+ vendor[40 - len] = 0;
}
else {
- ata_prtdev(adp->device,
- "%lluMB <%.40s/%.8s> [%lld/%d/%d] at ata%d-%s %s%s\n",
- (unsigned long long)(adp->total_secs /
- ((1024L * 1024L) / DEV_BSIZE)),
- adp->device->param->model, adp->device->param->revision,
- (unsigned long long)(adp->total_secs /
- (adp->heads * adp->sectors)),
- adp->heads, adp->sectors,
- device_get_unit(adp->device->channel->dev),
- (adp->device->unit == ATA_MASTER) ? "master" : "slave",
- (adp->flags & AD_F_TAG_ENABLED) ? "tagged " : "",
- ata_mode2str(adp->device->mode));
+ if (!strncmp(atadev->param.model, "ST", 2))
+ strcpy(vendor, "Seagate ");
+ else
+ strcpy(vendor, "");
+ strncpy(product, atadev->param.model, 40);
+ }
+
+ device_printf(dev, "%lluMB <%s%s %.8s> at ata%d-%s %s%s\n",
+ (unsigned long long)(adp->total_secs / (1048576 / DEV_BSIZE)),
+ vendor, product, atadev->param.revision,
+ device_get_unit(ch->dev),
+ (atadev->unit == ATA_MASTER) ? "master" : "slave",
+ (adp->flags & AD_F_TAG_ENABLED) ? "tagged " : "",
+ ata_mode2str(atadev->mode));
+ if (bootverbose) {
+ device_printf(dev, "%llu sectors [%lldC/%dH/%dS] "
+ "%d sectors/interrupt %d depth queue\n",
+ (unsigned long long)adp->total_secs,
+ (unsigned long long)(adp->total_secs /
+ (adp->heads * adp->sectors)),
+ adp->heads, adp->sectors, atadev->max_iosize / DEV_BSIZE,
+ adp->num_tags + 1);
}
}
@@ -445,3 +416,45 @@ ad_version(u_int16_t version)
return bit;
return 0;
}
+
+static device_method_t ad_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_identify, ad_identify),
+ DEVMETHOD(device_probe, ad_probe),
+ DEVMETHOD(device_attach, ad_attach),
+ DEVMETHOD(device_detach, ad_detach),
+ DEVMETHOD(device_shutdown, ad_shutdown),
+
+ /* ATA methods */
+ DEVMETHOD(ata_reinit, ad_reinit),
+
+ { 0, 0 }
+};
+
+static driver_t ad_driver = {
+ "ad",
+ ad_methods,
+ sizeof(struct ad_softc)
+};
+
+devclass_t ad_devclass;
+
+static int
+ad_modevent(module_t mod, int what, void *arg)
+{
+ device_t *devs;
+ int ndevs, i;
+
+ if (what == MOD_UNLOAD) {
+ if (!devclass_get_devices(ad_devclass, &devs, &ndevs) && devs) {
+ for (i = 0; i < ndevs; i++)
+ device_delete_child(device_get_parent(devs[i]), devs[i]);
+ free(devs, M_TEMP);
+ }
+ }
+ return 0;
+}
+
+DRIVER_MODULE(ad, ata, ad_driver, ad_devclass, ad_modevent, NULL);
+MODULE_VERSION(ad, 1);
+MODULE_DEPEND(ad, ata, 1, 1, 1);
diff --git a/sys/dev/ata/ata-disk.h b/sys/dev/ata/ata-disk.h
index c24c4ae..cbfc4a65 100644
--- a/sys/dev/ata/ata-disk.h
+++ b/sys/dev/ata/ata-disk.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2004 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2005 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,22 +30,20 @@
/* structure describing an ATA disk */
struct ad_softc {
- struct ata_device *device; /* ptr to device softc */
- int lun; /* logical unit number */
- u_int64_t total_secs; /* total # of sectors (LBA) */
- u_int8_t heads;
- u_int8_t sectors;
- u_int32_t transfersize; /* size of each transfer */
- int num_tags; /* number of tags supported */
- int max_iosize; /* max transfer HW supports */
- int flags; /* drive flags */
-#define AD_F_LABELLING 0x0001
-#define AD_F_CHS_USED 0x0002
-#define AD_F_32B_ENABLED 0x0004
-#define AD_F_TAG_ENABLED 0x0008
-#define AD_F_RAID_SUBDISK 0x0010
+ u_int64_t total_secs; /* total # of sectors (LBA) */
+ u_int8_t heads;
+ u_int8_t sectors;
+ u_int32_t transfersize; /* size of each transfer */
+ int num_tags; /* number of tags supported */
+ int flags; /* drive flags */
+#define AD_F_LABELLING 0x0001
+#define AD_F_CHS_USED 0x0002
+#define AD_F_32B_ENABLED 0x0004
+#define AD_F_TAG_ENABLED 0x0008
+#define AD_F_RAID_SUBDISK 0x0010
- struct mtx queue_mtx; /* bio queue lock */
- struct bio_queue_head queue; /* head of request queue */
- struct disk *disk; /* disklabel/slice stuff */
+ struct disk *disk; /* disklabel/slice stuff */
};
+
+extern devclass_t ad_devclass;
+
diff --git a/sys/dev/ata/ata-dma.c b/sys/dev/ata/ata-dma.c
index 974fb7d..98e35a1 100644
--- a/sys/dev/ata/ata-dma.c
+++ b/sys/dev/ata/ata-dma.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2004 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2005 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -57,8 +57,8 @@ static int ata_dmaunload(struct ata_channel *);
static MALLOC_DEFINE(M_ATADMA, "ATA DMA", "ATA driver DMA");
/* misc defines */
-#define MAXTABSZ PAGE_SIZE
-#define MAXWSPCSZ PAGE_SIZE
+#define MAXTABSZ PAGE_SIZE
+#define MAXWSPCSZ PAGE_SIZE
struct ata_dc_cb_args {
bus_addr_t maddr;
@@ -104,51 +104,51 @@ ata_dmaalloc(struct ata_channel *ch)
if (bus_dma_tag_create(ch->dma->dmatag, PAGE_SIZE, PAGE_SIZE,
BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
NULL, NULL, MAXTABSZ, 1, MAXTABSZ,
- 0, NULL, NULL, &ch->dma->cdmatag))
+ 0, NULL, NULL, &ch->dma->sg_tag))
goto error;
if (bus_dma_tag_create(ch->dma->dmatag,ch->dma->alignment,ch->dma->boundary,
BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
NULL, NULL, 256 * DEV_BSIZE,
ATA_DMA_ENTRIES, ch->dma->max_iosize,
- BUS_DMA_ALLOCNOW, NULL, NULL, &ch->dma->ddmatag))
+ BUS_DMA_ALLOCNOW, NULL, NULL, &ch->dma->data_tag))
goto error;
- if (bus_dmamem_alloc(ch->dma->cdmatag, (void **)&ch->dma->dmatab, 0,
- &ch->dma->cdmamap))
+ if (bus_dmamem_alloc(ch->dma->sg_tag, (void **)&ch->dma->sg, 0,
+ &ch->dma->sg_map))
goto error;
- if (bus_dmamap_load(ch->dma->cdmatag, ch->dma->cdmamap, ch->dma->dmatab,
+ if (bus_dmamap_load(ch->dma->sg_tag, ch->dma->sg_map, ch->dma->sg,
MAXTABSZ, ata_dmasetupc_cb, &ccba, 0) || ccba.error) {
- bus_dmamem_free(ch->dma->cdmatag, ch->dma->dmatab, ch->dma->cdmamap);
+ bus_dmamem_free(ch->dma->sg_tag, ch->dma->sg, ch->dma->sg_map);
goto error;
}
- ch->dma->mdmatab = ccba.maddr;
+ ch->dma->sg_bus = ccba.maddr;
- if (bus_dmamap_create(ch->dma->ddmatag, 0, &ch->dma->ddmamap))
+ if (bus_dmamap_create(ch->dma->data_tag, 0, &ch->dma->data_map))
goto error;
if (bus_dma_tag_create(ch->dma->dmatag, PAGE_SIZE, PAGE_SIZE,
BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
NULL, NULL, MAXWSPCSZ, 1, MAXWSPCSZ,
- 0, NULL, NULL, &ch->dma->wdmatag))
+ 0, NULL, NULL, &ch->dma->work_tag))
goto error;
- if (bus_dmamem_alloc(ch->dma->wdmatag, (void **)&ch->dma->workspace, 0,
- &ch->dma->wdmamap))
+ if (bus_dmamem_alloc(ch->dma->work_tag, (void **)&ch->dma->work, 0,
+ &ch->dma->work_map))
goto error;
- if (bus_dmamap_load(ch->dma->wdmatag, ch->dma->wdmamap, ch->dma->workspace,
+ if (bus_dmamap_load(ch->dma->work_tag, ch->dma->work_map,ch->dma->work,
MAXWSPCSZ, ata_dmasetupc_cb, &ccba, 0) || ccba.error) {
- bus_dmamem_free(ch->dma->wdmatag, ch->dma->workspace, ch->dma->wdmamap);
+ bus_dmamem_free(ch->dma->work_tag,ch->dma->work, ch->dma->work_map);
goto error;
}
- ch->dma->wdmatab = ccba.maddr;
+ ch->dma->work_bus = ccba.maddr;
return;
error:
- ata_printf(ch, -1, "WARNING - DMA allocation failed, disabling DMA\n");
+ device_printf(ch->dev, "WARNING - DMA allocation failed, disabling DMA\n");
ata_dmafree(ch);
free(ch->dma, M_ATADMA);
ch->dma = NULL;
@@ -157,35 +157,35 @@ error:
static void
ata_dmafree(struct ata_channel *ch)
{
- if (ch->dma->wdmatab) {
- bus_dmamap_unload(ch->dma->wdmatag, ch->dma->wdmamap);
- bus_dmamem_free(ch->dma->wdmatag, ch->dma->workspace, ch->dma->wdmamap);
- ch->dma->wdmatab = 0;
- ch->dma->wdmamap = NULL;
- ch->dma->workspace = NULL;
+ if (ch->dma->work_bus) {
+ bus_dmamap_unload(ch->dma->work_tag, ch->dma->work_map);
+ bus_dmamem_free(ch->dma->work_tag, ch->dma->work, ch->dma->work_map);
+ ch->dma->work_bus = 0;
+ ch->dma->work_map = NULL;
+ ch->dma->work = NULL;
}
- if (ch->dma->wdmatag) {
- bus_dma_tag_destroy(ch->dma->wdmatag);
- ch->dma->wdmatag = NULL;
+ if (ch->dma->work_tag) {
+ bus_dma_tag_destroy(ch->dma->work_tag);
+ ch->dma->work_tag = NULL;
}
- if (ch->dma->mdmatab) {
- bus_dmamap_unload(ch->dma->cdmatag, ch->dma->cdmamap);
- bus_dmamem_free(ch->dma->cdmatag, ch->dma->dmatab, ch->dma->cdmamap);
- ch->dma->mdmatab = 0;
- ch->dma->cdmamap = NULL;
- ch->dma->dmatab = NULL;
+ if (ch->dma->sg_bus) {
+ bus_dmamap_unload(ch->dma->sg_tag, ch->dma->sg_map);
+ bus_dmamem_free(ch->dma->sg_tag, ch->dma->sg, ch->dma->sg_map);
+ ch->dma->sg_bus = 0;
+ ch->dma->sg_map = NULL;
+ ch->dma->sg = NULL;
}
- if (ch->dma->ddmamap) {
- bus_dmamap_destroy(ch->dma->ddmatag, ch->dma->ddmamap);
- ch->dma->ddmamap = NULL;
+ if (ch->dma->data_map) {
+ bus_dmamap_destroy(ch->dma->data_tag, ch->dma->data_map);
+ ch->dma->data_map = NULL;
}
- if (ch->dma->cdmatag) {
- bus_dma_tag_destroy(ch->dma->cdmatag);
- ch->dma->cdmatag = NULL;
+ if (ch->dma->sg_tag) {
+ bus_dma_tag_destroy(ch->dma->sg_tag);
+ ch->dma->sg_tag = NULL;
}
- if (ch->dma->ddmatag) {
- bus_dma_tag_destroy(ch->dma->ddmatag);
- ch->dma->ddmatag = NULL;
+ if (ch->dma->data_tag) {
+ bus_dma_tag_destroy(ch->dma->data_tag);
+ ch->dma->data_tag = NULL;
}
if (ch->dma->dmatag) {
bus_dma_tag_destroy(ch->dma->dmatag);
@@ -213,38 +213,41 @@ ata_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error)
static int
ata_dmaload(struct ata_device *atadev, caddr_t data, int32_t count, int dir)
{
- struct ata_channel *ch = atadev->channel;
+ struct ata_channel *ch = device_get_softc(device_get_parent(atadev->dev));
struct ata_dmasetprd_args cba;
if (ch->dma->flags & ATA_DMA_LOADED) {
- ata_prtdev(atadev, "FAILURE - already active DMA on this device\n");
+ device_printf(atadev->dev,
+ "FAILURE - already active DMA on this device\n");
return -1;
}
if (!count) {
- ata_prtdev(atadev, "FAILURE - zero length DMA transfer attempted\n");
+ device_printf(atadev->dev,
+ "FAILURE - zero length DMA transfer attempted\n");
return -1;
}
if (((uintptr_t)data & (ch->dma->alignment - 1)) ||
(count & (ch->dma->alignment - 1))) {
- ata_prtdev(atadev, "FAILURE - non aligned DMA transfer attempted\n");
+ device_printf(atadev->dev,
+ "FAILURE - non aligned DMA transfer attempted\n");
return -1;
}
if (count > ch->dma->max_iosize) {
- ata_prtdev(atadev,
- "FAILURE - oversized DMA transfer attempted %d > %d\n",
- count, ch->dma->max_iosize);
+ device_printf(atadev->dev,
+ "FAILURE - oversized DMA transfer attempted %d > %d\n",
+ count, ch->dma->max_iosize);
return -1;
}
- cba.dmatab = ch->dma->dmatab;
+ cba.dmatab = ch->dma->sg;
- bus_dmamap_sync(ch->dma->cdmatag, ch->dma->cdmamap, BUS_DMASYNC_PREWRITE);
+ bus_dmamap_sync(ch->dma->sg_tag, ch->dma->sg_map, BUS_DMASYNC_PREWRITE);
- if (bus_dmamap_load(ch->dma->ddmatag, ch->dma->ddmamap, data, count,
+ if (bus_dmamap_load(ch->dma->data_tag, ch->dma->data_map, data, count,
ch->dma->setprd, &cba, 0) || cba.error)
return -1;
- bus_dmamap_sync(ch->dma->ddmatag, ch->dma->ddmamap,
+ bus_dmamap_sync(ch->dma->data_tag, ch->dma->data_map,
dir ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
ch->dma->cur_iosize = count;
@@ -255,12 +258,12 @@ ata_dmaload(struct ata_device *atadev, caddr_t data, int32_t count, int dir)
int
ata_dmaunload(struct ata_channel *ch)
{
- bus_dmamap_sync(ch->dma->cdmatag, ch->dma->cdmamap, BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_sync(ch->dma->sg_tag, ch->dma->sg_map, BUS_DMASYNC_POSTWRITE);
- bus_dmamap_sync(ch->dma->ddmatag, ch->dma->ddmamap,
+ bus_dmamap_sync(ch->dma->data_tag, ch->dma->data_map,
(ch->dma->flags & ATA_DMA_READ) != 0 ?
BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
- bus_dmamap_unload(ch->dma->ddmatag, ch->dma->ddmamap);
+ bus_dmamap_unload(ch->dma->data_tag, ch->dma->data_map);
ch->dma->cur_iosize = 0;
ch->dma->flags &= ~ATA_DMA_LOADED;
diff --git a/sys/dev/ata/ata-isa.c b/sys/dev/ata/ata-isa.c
index 4fadd2d..c15a2d3 100644
--- a/sys/dev/ata/ata-isa.c
+++ b/sys/dev/ata/ata-isa.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2004 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2005 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -49,28 +49,16 @@ __FBSDID("$FreeBSD$");
/* local vars */
static struct isa_pnp_id ata_ids[] = {
- {0x0006d041, "Generic ESDI/IDE/ATA controller"}, /* PNP0600 */
- {0x0106d041, "Plus Hardcard II"}, /* PNP0601 */
- {0x0206d041, "Plus Hardcard IIXL/EZ"}, /* PNP0602 */
- {0x0306d041, "Generic ATA"}, /* PNP0603 */
+ {0x0006d041, "Generic ESDI/IDE/ATA controller"}, /* PNP0600 */
+ {0x0106d041, "Plus Hardcard II"}, /* PNP0601 */
+ {0x0206d041, "Plus Hardcard IIXL/EZ"}, /* PNP0602 */
+ {0x0306d041, "Generic ATA"}, /* PNP0603 */
/* PNP0680 */
- {0x8006d041, "Standard bus mastering IDE hard disk controller"},
+ {0x8006d041, "Standard bus mastering IDE hard disk controller"},
{0}
};
static int
-ata_isa_locknoop(struct ata_channel *ch, int type)
-{
- return ch->unit;
-}
-
-static void
-ata_isa_setmode(struct ata_device *atadev, int mode)
-{
- atadev->mode = ata_limit_mode(atadev, mode, ATA_PIO_MAX);
-}
-
-static int
ata_isa_probe(device_t dev)
{
struct ata_channel *ch = device_get_softc(dev);
@@ -115,18 +103,16 @@ ata_isa_probe(device_t dev)
/* initialize softc for this channel */
ch->unit = 0;
ch->flags |= ATA_USE_16BIT;
- ch->locking = ata_isa_locknoop;
- ch->device[MASTER].setmode = ata_isa_setmode;
- ch->device[SLAVE].setmode = ata_isa_setmode;
ata_generic_hw(ch);
return ata_probe(dev);
}
static device_method_t ata_isa_methods[] = {
/* device interface */
- DEVMETHOD(device_probe, ata_isa_probe),
- DEVMETHOD(device_attach, ata_attach),
- DEVMETHOD(device_resume, ata_resume),
+ DEVMETHOD(device_probe, ata_isa_probe),
+ DEVMETHOD(device_attach, ata_attach),
+ DEVMETHOD(device_suspend, ata_suspend),
+ DEVMETHOD(device_resume, ata_resume),
{ 0, 0 }
};
@@ -137,3 +123,4 @@ static driver_t ata_isa_driver = {
};
DRIVER_MODULE(ata, isa, ata_isa_driver, ata_devclass, 0, 0);
+MODULE_DEPEND(ata, ata, 1, 1, 1);
diff --git a/sys/dev/ata/ata-lowlevel.c b/sys/dev/ata/ata-lowlevel.c
index aec3b05..bb9d9e0 100644
--- a/sys/dev/ata/ata-lowlevel.c
+++ b/sys/dev/ata/ata-lowlevel.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2004 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2005 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,9 +32,11 @@ __FBSDID("$FreeBSD$");
#include "opt_ata.h"
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/ata.h>
#include <sys/kernel.h>
+#include <sys/endian.h>
+#include <sys/ata.h>
#include <sys/conf.h>
+#include <sys/ctype.h>
#include <sys/bus.h>
#include <sys/sema.h>
#include <sys/taskqueue.h>
@@ -42,17 +44,108 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <sys/rman.h>
#include <dev/ata/ata-all.h>
+#include <dev/ata/ata-commands.h>
+#include <dev/ata/ata-pci.h>
+#include <ata_if.h>
/* prototypes */
static int ata_begin_transaction(struct ata_request *);
static int ata_end_transaction(struct ata_request *);
static void ata_generic_reset(struct ata_channel *);
-static int ata_wait(struct ata_device *, u_int8_t);
+static int ata_wait(struct ata_channel *ch, struct ata_device *, u_int8_t);
static void ata_pio_read(struct ata_request *, int);
static void ata_pio_write(struct ata_request *, int);
+static void bswap(int8_t *, int);
+static void btrim(int8_t *, int);
+static void bpack(int8_t *, int8_t *, int);
+
+/* get device parameter page from device */
+int
+ata_getparam(device_t parent, struct ata_device *atadev, u_int8_t command)
+{
+ struct ata_channel *ch = device_get_softc(parent);
+ int error = 0, retry = 0;
+
+ do {
+ if (retry++ > 4) {
+ if (bootverbose)
+ printf("ata%d-%s: %s-identify retries exceeded\n", ch->unit,
+ atadev->unit == ATA_MASTER ? "master" : "slave",
+ command == ATA_ATAPI_IDENTIFY ? "ATAPI" : "ATA");
+ error = ENXIO;
+ break;
+ }
+
+ /* select device */
+ ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | atadev->unit);
+
+ /* disable interrupt */
+ ATA_IDX_OUTB(ch, ATA_ALTSTAT, ATA_A_4BIT | ATA_A_IDS);
+
+ /* ready to issue command ? */
+ if ((error = ata_wait(ch, atadev, 0)) < 0) {
+ printf("ata%d-%s: timeout sending %s-identify error=%d\n",
+ device_get_unit(parent),
+ atadev->unit == ATA_MASTER ? "master" : "slave",
+ command == ATA_ATAPI_IDENTIFY ? "ATAPI" : "ATA", error);
+ error = ENXIO;
+ break;
+ }
+
+ /* select device */
+ ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | atadev->unit);
+
+ /* issue command */
+ ATA_IDX_OUTB(ch, ATA_CMD, command);
+
+ } while (ata_wait(ch, atadev, ATA_S_DRQ));
+
+ if (!error) {
+ ATA_IDX_INSW_STRM(ch, ATA_DATA, (void *)&atadev->param,
+ sizeof(struct ata_params)/sizeof(int16_t));
+ ATA_IDX_INB(ch, ATA_STATUS);
+ }
+
+ if (!error && (isprint(atadev->param.model[0]) ||
+ isprint(atadev->param.model[1]))) {
+ struct ata_params *atacap = &atadev->param;
+#if BYTE_ORDER == BIG_ENDIAN
+ int16_t *ptr;
+
+ for (ptr = (int16_t *)atacap;
+ ptr < (int16_t *)atacap + sizeof(struct ata_params)/2; ptr++) {
+ *ptr = bswap16(*ptr);
+ }
+#endif
+ if (!(!strncmp(atacap->model, "FX", 2) ||
+ !strncmp(atacap->model, "NEC", 3) ||
+ !strncmp(atacap->model, "Pioneer", 7) ||
+ !strncmp(atacap->model, "SHARP", 5))) {
+ bswap(atacap->model, sizeof(atacap->model));
+ bswap(atacap->revision, sizeof(atacap->revision));
+ bswap(atacap->serial, sizeof(atacap->serial));
+ }
+ btrim(atacap->model, sizeof(atacap->model));
+ bpack(atacap->model, atacap->model, sizeof(atacap->model));
+ btrim(atacap->revision, sizeof(atacap->revision));
+ bpack(atacap->revision, atacap->revision, sizeof(atacap->revision));
+ btrim(atacap->serial, sizeof(atacap->serial));
+ bpack(atacap->serial, atacap->serial, sizeof(atacap->serial));
+ if (bootverbose)
+ printf("ata%d-%s: pio=%s wdma=%s udma=%s cable=%s wire\n",
+ ch->unit, atadev->unit == ATA_MASTER ? "master":"slave",
+ ata_mode2str(ata_pmode(atacap)),
+ ata_mode2str(ata_wmode(atacap)),
+ ata_mode2str(ata_umode(atacap)),
+ (atacap->hwres & ATA_CABLE_ID) ? "80":"40");
+ }
+ else {
+ if (!error)
+ error = ENXIO;
+ }
-/* local vars */
-static int atadebug = 0;
+ return error;
+}
/*
* low level ATA functions
@@ -70,14 +163,8 @@ ata_generic_hw(struct ata_channel *ch)
static int
ata_begin_transaction(struct ata_request *request)
{
- struct ata_channel *ch = request->device->channel;
-
- /* safetybelt for HW that went away */
- if (!request->device->param || request->device->channel->flags&ATA_HWGONE) {
- request->retries = 0;
- request->result = ENXIO;
- return ATA_OP_FINISHED;
- }
+ struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
+ struct ata_device *atadev = device_get_softc(request->dev);
ATA_DEBUG_RQ(request, "begin transaction");
@@ -96,17 +183,17 @@ ata_begin_transaction(struct ata_request *request)
int write = (request->flags & ATA_R_WRITE);
/* issue command */
- if (ch->hw.command(request->device, request->u.ata.command,
+ if (ch->hw.command(atadev, request->u.ata.command,
request->u.ata.lba, request->u.ata.count,
request->u.ata.feature)) {
- ata_prtdev(request->device, "error issueing %s command\n",
+ device_printf(request->dev, "error issueing %s command\n",
ata_cmd2str(request));
request->result = EIO;
break;
}
/* device reset doesn't interrupt */
- if (request->u.ata.command == ATA_ATAPI_RESET) {
+ if (request->u.ata.command == ATA_DEVICE_RESET) {
int timeout = 1000000;
do {
DELAY(10);
@@ -119,9 +206,9 @@ ata_begin_transaction(struct ata_request *request)
/* if write command output the data */
if (write) {
- if (ata_wait(request->device,
+ if (ata_wait(ch, atadev,
(ATA_S_READY | ATA_S_DSC | ATA_S_DRQ)) < 0) {
- ata_prtdev(request->device,"timeout waiting for write DRQ");
+ device_printf(request->dev,"timeout waiting for write DRQ");
request->result = EIO;
break;
}
@@ -133,18 +220,18 @@ ata_begin_transaction(struct ata_request *request)
/* ATA DMA data transfer commands */
case ATA_R_DMA:
/* check sanity, setup SG list and DMA engine */
- if (ch->dma->load(request->device, request->data, request->bytecount,
+ if (ch->dma->load(atadev, request->data, request->bytecount,
request->flags & ATA_R_READ)) {
- ata_prtdev(request->device, "setting up DMA failed\n");
+ device_printf(request->dev, "setting up DMA failed\n");
request->result = EIO;
break;
}
/* issue command */
- if (ch->hw.command(request->device, request->u.ata.command,
+ if (ch->hw.command(atadev, request->u.ata.command,
request->u.ata.lba, request->u.ata.count,
request->u.ata.feature)) {
- ata_prtdev(request->device, "error issueing %s command\n",
+ device_printf(request->dev, "error issueing %s command\n",
ata_cmd2str(request));
request->result = EIO;
break;
@@ -152,7 +239,7 @@ ata_begin_transaction(struct ata_request *request)
/* start DMA engine */
if (ch->dma->start(ch)) {
- ata_prtdev(request->device, "error starting DMA\n");
+ device_printf(request->dev, "error starting DMA\n");
request->result = EIO;
break;
}
@@ -162,8 +249,7 @@ ata_begin_transaction(struct ata_request *request)
case ATA_R_ATAPI:
/* is this just a POLL DSC command ? */
if (request->u.atapi.ccb[0] == ATAPI_POLL_DSC) {
- ATA_IDX_OUTB(ch, ATA_DRIVE,
- ATA_D_IBM | request->device->unit);
+ ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | atadev->unit);
DELAY(10);
if (!(ATA_IDX_INB(ch, ATA_ALTSTAT)&ATA_S_DSC))
request->result = EBUSY;
@@ -171,15 +257,15 @@ ata_begin_transaction(struct ata_request *request)
}
/* start ATAPI operation */
- if (ch->hw.command(request->device, ATA_PACKET_CMD,
+ if (ch->hw.command(atadev, ATA_PACKET_CMD,
request->transfersize << 8, 0, 0)) {
- ata_prtdev(request->device, "error issuing ATA PACKET command\n");
+ device_printf(request->dev, "error issuing ATA PACKET command\n");
request->result = EIO;
break;
}
/* command interrupt device ? just return and wait for interrupt */
- if ((request->device->param->config & ATA_DRQ_MASK) == ATA_DRQ_INTR)
+ if ((atadev->param.config & ATA_DRQ_MASK) == ATA_DRQ_INTR)
return ATA_OP_CONTINUES;
/* wait for ready to write ATAPI command block */
@@ -195,8 +281,7 @@ ata_begin_transaction(struct ata_request *request)
DELAY(20);
}
if (timeout <= 0) {
- ata_prtdev(request->device,
- "timeout waiting for ATAPI ready\n");
+ device_printf(request->dev,"timeout waiting for ATAPI ready\n");
request->result = EIO;
break;
}
@@ -208,15 +293,14 @@ ata_begin_transaction(struct ata_request *request)
/* output actual command block */
ATA_IDX_OUTSW_STRM(ch, ATA_DATA,
(int16_t *)request->u.atapi.ccb,
- (request->device->param->config & ATA_PROTO_MASK) ==
+ (atadev->param.config & ATA_PROTO_MASK) ==
ATA_PROTO_ATAPI_12 ? 6 : 8);
return ATA_OP_CONTINUES;
case ATA_R_ATAPI|ATA_R_DMA:
/* is this just a POLL DSC command ? */
if (request->u.atapi.ccb[0] == ATAPI_POLL_DSC) {
- ATA_IDX_OUTB(ch, ATA_DRIVE,
- ATA_D_IBM | request->device->unit);
+ ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | atadev->unit);
DELAY(10);
if (!(ATA_IDX_INB(ch, ATA_ALTSTAT)&ATA_S_DSC))
request->result = EBUSY;
@@ -224,18 +308,16 @@ ata_begin_transaction(struct ata_request *request)
}
/* check sanity, setup SG list and DMA engine */
- if (ch->dma->load(request->device,
- request->data,
- request->bytecount,
- request->flags & ATA_R_READ)) {
- ata_prtdev(request->device, "setting up DMA failed\n");
+ if (ch->dma->load(atadev, request->data, request->bytecount,
+ request->flags & ATA_R_READ)) {
+ device_printf(request->dev, "setting up DMA failed\n");
request->result = EIO;
break;
}
/* start ATAPI operation */
- if (ch->hw.command(request->device, ATA_PACKET_CMD, 0, 0, ATA_F_DMA)) {
- ata_prtdev(request->device, "error issuing ATAPI packet command\n");
+ if (ch->hw.command(atadev, ATA_PACKET_CMD, 0, 0, ATA_F_DMA)) {
+ device_printf(request->dev, "error issuing ATAPI packet command\n");
request->result = EIO;
break;
}
@@ -253,7 +335,7 @@ ata_begin_transaction(struct ata_request *request)
DELAY(20);
}
if (timeout <= 0) {
- ata_prtdev(request->device,"timeout waiting for ATAPI ready\n");
+ device_printf(request->dev,"timeout waiting for ATAPI ready\n");
request->result = EIO;
break;
}
@@ -265,7 +347,7 @@ ata_begin_transaction(struct ata_request *request)
/* output actual command block */
ATA_IDX_OUTSW_STRM(ch, ATA_DATA,
(int16_t *)request->u.atapi.ccb,
- (request->device->param->config & ATA_PROTO_MASK) ==
+ (atadev->param.config & ATA_PROTO_MASK) ==
ATA_PROTO_ATAPI_12 ? 6 : 8);
/* start DMA engine */
@@ -285,7 +367,8 @@ ata_begin_transaction(struct ata_request *request)
static int
ata_end_transaction(struct ata_request *request)
{
- struct ata_channel *ch = request->device->channel;
+ struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
+ struct ata_device *atadev = device_get_softc(request->dev);
int length;
ATA_DEBUG_RQ(request, "end transaction");
@@ -297,9 +380,11 @@ ata_end_transaction(struct ata_request *request)
/* ATA PIO data transfer and control commands */
default:
- /* XXX Doesn't handle the non-PIO case. */
+
+ /* on timeouts we have no data or anything so just return */
if (request->flags & ATA_R_TIMEOUT)
- return ATA_OP_FINISHED;
+ //return ATA_OP_FINISHED;
+ break;
/* on control commands read back registers to the request struct */
if (request->flags & ATA_R_CONTROL) {
@@ -307,21 +392,30 @@ ata_end_transaction(struct ata_request *request)
request->u.ata.lba = ATA_IDX_INB(ch, ATA_SECTOR) |
(ATA_IDX_INB(ch, ATA_CYL_LSB) << 8) |
(ATA_IDX_INB(ch, ATA_CYL_MSB) << 16) |
- ((ATA_IDX_INB(ch, ATA_DRIVE) & 0x0f) << 24);
+ ((ATA_IDX_INB(ch, ATA_DRIVE) & 0x0f) << 24);
}
/* if we got an error we are done with the HW */
if (request->status & ATA_S_ERROR) {
request->error = ATA_IDX_INB(ch, ATA_ERROR);
- return ATA_OP_FINISHED;
+ //return ATA_OP_FINISHED;
+ break;
}
/* are we moving data ? */
if (request->flags & (ATA_R_READ | ATA_R_WRITE)) {
/* if read data get it */
- if (request->flags & ATA_R_READ)
+ if (request->flags & ATA_R_READ) {
+ if (ata_wait(ch, atadev,
+ (ATA_S_READY | ATA_S_DSC | ATA_S_DRQ)) < 0) {
+ device_printf(request->dev, "timeout waiting for read DRQ");
+ request->result = EIO;
+ //return ATA_OP_FINISHED;
+ break;
+ }
ata_pio_read(request, request->transfersize);
+ }
/* update how far we've gotten */
request->donecount += request->transfersize;
@@ -334,19 +428,17 @@ ata_end_transaction(struct ata_request *request)
min((request->bytecount - request->donecount),
request->transfersize);
- /* clear interrupt seen flag as we need to wait again */
- request->flags &= ~ATA_R_INTR_SEEN;
-
/* if data write command, output the data */
if (request->flags & ATA_R_WRITE) {
/* if we get an error here we are done with the HW */
- if (ata_wait(request->device,
+ if (ata_wait(ch, atadev,
(ATA_S_READY | ATA_S_DSC | ATA_S_DRQ)) < 0) {
- ata_prtdev(request->device,
- "timeout waiting for write DRQ");
+ device_printf(request->dev,
+ "timeout waiting for write DRQ");
request->status = ATA_IDX_INB(ch, ATA_STATUS);
- return ATA_OP_FINISHED;
+ //return ATA_OP_FINISHED;
+ break;
}
/* output data and return waiting for new interrupt */
@@ -360,7 +452,8 @@ ata_end_transaction(struct ata_request *request)
}
}
/* done with HW */
- return ATA_OP_FINISHED;
+ //return ATA_OP_FINISHED;
+ break;
/* ATA DMA data transfer commands */
case ATA_R_DMA:
@@ -374,19 +467,25 @@ ata_end_transaction(struct ata_request *request)
request->error = ATA_IDX_INB(ch, ATA_ERROR);
else if (request->dmastat & ATA_BMSTAT_ERROR)
request->status |= ATA_S_ERROR;
- else
+ else if (!(request->flags & ATA_R_TIMEOUT))
request->donecount = request->bytecount;
/* release SG list etc */
ch->dma->unload(ch);
/* done with HW */
- return ATA_OP_FINISHED;
+ //return ATA_OP_FINISHED;
+ break;
/* ATAPI PIO commands */
case ATA_R_ATAPI:
length = ATA_IDX_INB(ch, ATA_CYL_LSB)|(ATA_IDX_INB(ch, ATA_CYL_MSB)<<8);
+ /* on timeouts we have no data or anything so just return */
+ if (request->flags & ATA_R_TIMEOUT)
+ //return ATA_OP_FINISHED;
+ break;
+
switch ((ATA_IDX_INB(ch, ATA_IREASON) & (ATA_I_CMD | ATA_I_IN)) |
(request->status & ATA_S_DRQ)) {
@@ -395,12 +494,13 @@ ata_end_transaction(struct ata_request *request)
DELAY(10);
if (!(request->status & ATA_S_DRQ)) {
- ata_prtdev(request->device, "command interrupt without DRQ\n");
+ device_printf(request->dev, "command interrupt without DRQ\n");
request->status = ATA_S_ERROR;
- return ATA_OP_FINISHED;
+ //return ATA_OP_FINISHED;
+ break;
}
ATA_IDX_OUTSW_STRM(ch, ATA_DATA, (int16_t *)request->u.atapi.ccb,
- (request->device->param->config &
+ (atadev->param.config &
ATA_PROTO_MASK)== ATA_PROTO_ATAPI_12 ? 6 : 8);
/* return wait for interrupt */
return ATA_OP_CONTINUES;
@@ -408,10 +508,11 @@ ata_end_transaction(struct ata_request *request)
case ATAPI_P_WRITE:
if (request->flags & ATA_R_READ) {
request->status = ATA_S_ERROR;
- ata_prtdev(request->device,
- "%s trying to write on read buffer\n",
+ device_printf(request->dev,
+ "%s trying to write on read buffer\n",
ata_cmd2str(request));
- return ATA_OP_FINISHED;
+ //return ATA_OP_FINISHED;
+ break;
}
ata_pio_write(request, length);
request->donecount += length;
@@ -425,10 +526,11 @@ ata_end_transaction(struct ata_request *request)
case ATAPI_P_READ:
if (request->flags & ATA_R_WRITE) {
request->status = ATA_S_ERROR;
- ata_prtdev(request->device,
- "%s trying to read on write buffer\n",
+ device_printf(request->dev,
+ "%s trying to read on write buffer\n",
ata_cmd2str(request));
- return ATA_OP_FINISHED;
+ //return ATA_OP_FINISHED;
+ break;
}
ata_pio_read(request, length);
request->donecount += length;
@@ -440,9 +542,9 @@ ata_end_transaction(struct ata_request *request)
return ATA_OP_CONTINUES;
case ATAPI_P_DONEDRQ:
- ata_prtdev(request->device,
- "WARNING - %s DONEDRQ non conformant device\n",
- ata_cmd2str(request));
+ device_printf(request->dev,
+ "WARNING - %s DONEDRQ non conformant device\n",
+ ata_cmd2str(request));
if (request->flags & ATA_R_READ) {
ata_pio_read(request, length);
request->donecount += length;
@@ -459,15 +561,17 @@ ata_end_transaction(struct ata_request *request)
case ATAPI_P_DONE:
if (request->status & (ATA_S_ERROR | ATA_S_DWF))
request->error = ATA_IDX_INB(ch, ATA_ERROR);
- return ATA_OP_FINISHED;
+ //return ATA_OP_FINISHED;
+ break;
default:
- ata_prtdev(request->device, "unknown transfer phase\n");
+ device_printf(request->dev, "unknown transfer phase\n");
request->status = ATA_S_ERROR;
}
/* done with HW */
- return ATA_OP_FINISHED;
+ //return ATA_OP_FINISHED;
+ break;
/* ATAPI DMA commands */
case ATA_R_ATAPI|ATA_R_DMA:
@@ -481,39 +585,44 @@ ata_end_transaction(struct ata_request *request)
request->error = ATA_IDX_INB(ch, ATA_ERROR);
else if (request->dmastat & ATA_BMSTAT_ERROR)
request->status |= ATA_S_ERROR;
- else
+ else if (!(request->flags & ATA_R_TIMEOUT))
request->donecount = request->bytecount;
/* release SG list etc */
ch->dma->unload(ch);
/* done with HW */
- return ATA_OP_FINISHED;
+ //return ATA_OP_FINISHED;
+ break;
}
+
+ /* disable interrupt */
+ //ATA_IDX_OUTB(ch, ATA_ALTSTAT, ATA_A_4BIT | ATA_A_IDS);
+
+ return ATA_OP_FINISHED;
}
/* must be called with ATA channel locked */
static void
ata_generic_reset(struct ata_channel *ch)
{
- u_int8_t err = 0, lsb = 0, msb = 0, ostat0, ostat1;
- u_int8_t stat0 = 0, stat1 = 0;
+ u_int8_t ostat0 = 0, stat0 = 0, ostat1 = 0, stat1 = 0;
+ u_int8_t err = 0, lsb = 0, msb = 0;
int mask = 0, timeout;
/* if DMA functionality present stop it */
if (ch->dma) {
- if (ch->dma->stop)
- ch->dma->stop(ch);
- if (ch->dma->flags & ATA_DMA_LOADED)
- ch->dma->unload(ch);
+ if (ch->dma->stop)
+ ch->dma->stop(ch);
+ if (ch->dma->flags & ATA_DMA_LOADED)
+ ch->dma->unload(ch);
}
/* reset host end of channel (if supported) */
- if (ch->reset)
- ch->reset(ch);
+ ATA_RESET(device_get_parent(ch->dev), ch->dev);
/* do we have any signs of ATA/ATAPI HW being present ? */
- ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_MASTER);
+ ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | ATA_MASTER);
DELAY(10);
ostat0 = ATA_IDX_INB(ch, ATA_STATUS);
if ((ostat0 & 0xf8) != 0xf8 && ostat0 != 0xa5) {
@@ -521,12 +630,11 @@ ata_generic_reset(struct ata_channel *ch)
mask |= 0x01;
}
- ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_SLAVE);
- DELAY(10);
- ostat1 = ATA_IDX_INB(ch, ATA_STATUS);
-
/* in some setups we dont want to test for a slave */
if (!(ch->flags & ATA_NO_SLAVE)) {
+ ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | ATA_SLAVE);
+ DELAY(10);
+ ostat1 = ATA_IDX_INB(ch, ATA_STATUS);
if ((ostat1 & 0xf8) != 0xf8 && ostat1 != 0xa5) {
stat1 = ATA_S_BUSY;
mask |= 0x02;
@@ -534,8 +642,8 @@ ata_generic_reset(struct ata_channel *ch)
}
if (bootverbose)
- ata_printf(ch, -1, "reset tp1 mask=%02x ostat0=%02x ostat1=%02x\n",
- mask, ostat0, ostat1);
+ device_printf(ch->dev, "reset tp1 mask=%02x ostat0=%02x ostat1=%02x\n",
+ mask, ostat0, ostat1);
/* if nothing showed up there is no need to get any further */
/* SOS is that too strong?, we just might loose devices here XXX */
@@ -544,7 +652,7 @@ ata_generic_reset(struct ata_channel *ch)
return;
/* reset (both) devices on this channel */
- ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_MASTER);
+ ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | ATA_MASTER);
DELAY(10);
ATA_IDX_OUTB(ch, ATA_ALTSTAT, ATA_A_IDS | ATA_A_RESET);
ata_udelay(10000);
@@ -554,17 +662,19 @@ ata_generic_reset(struct ata_channel *ch)
/* wait for BUSY to go inactive */
for (timeout = 0; timeout < 310; timeout++) {
- if (stat0 & ATA_S_BUSY) {
+ if ((mask & 0x01) && (stat0 & ATA_S_BUSY)) {
ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_MASTER);
DELAY(10);
- err = ATA_IDX_INB(ch, ATA_ERROR);
+ err = ATA_IDX_INB(ch, ATA_ERROR);
lsb = ATA_IDX_INB(ch, ATA_CYL_LSB);
msb = ATA_IDX_INB(ch, ATA_CYL_MSB);
stat0 = ATA_IDX_INB(ch, ATA_STATUS);
if (bootverbose)
- ata_printf(ch, ATA_MASTER,
- "stat=0x%02x err=0x%02x lsb=0x%02x msb=0x%02x\n",
- stat0, err, lsb, msb);
+ device_printf(ch->dev,
+ "stat0=0x%02x err=0x%02x lsb=0x%02x msb=0x%02x\n",
+ stat0, err, lsb, msb);
+ if (stat0 == err && lsb == err && msb == err && timeout > 10)
+ mask &= ~0x01;
if (!(stat0 & ATA_S_BUSY)) {
if ((err & 0x7f) == ATA_E_ILI) {
if (lsb == ATAPI_MAGIC_LSB && msb == ATAPI_MAGIC_MSB) {
@@ -574,22 +684,25 @@ ata_generic_reset(struct ata_channel *ch)
ch->devices |= ATA_ATA_MASTER;
}
}
- else if ((stat0 & 0x4f) && err == lsb && err == msb) {
+ else if ((stat0 & 0x0f) && err == lsb && err == msb) {
stat0 |= ATA_S_BUSY;
}
}
}
- if (!((mask == 0x03) && (stat0 & ATA_S_BUSY)) && (stat1 & ATA_S_BUSY)) {
+
+ if ((mask & 0x02) && (stat1 & ATA_S_BUSY)) {
ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_SLAVE);
DELAY(10);
- err = ATA_IDX_INB(ch, ATA_ERROR);
+ err = ATA_IDX_INB(ch, ATA_ERROR);
lsb = ATA_IDX_INB(ch, ATA_CYL_LSB);
msb = ATA_IDX_INB(ch, ATA_CYL_MSB);
stat1 = ATA_IDX_INB(ch, ATA_STATUS);
if (bootverbose)
- ata_printf(ch, ATA_SLAVE,
- " stat=0x%02x err=0x%02x lsb=0x%02x msb=0x%02x\n",
- stat1, err, lsb, msb);
+ device_printf(ch->dev,
+ "stat1=0x%02x err=0x%02x lsb=0x%02x msb=0x%02x\n",
+ stat1, err, lsb, msb);
+ if (stat1 == err && lsb == err && msb == err && timeout > 10)
+ mask &= ~0x02;
if (!(stat1 & ATA_S_BUSY)) {
if ((err & 0x7f) == ATA_E_ILI) {
if (lsb == ATAPI_MAGIC_LSB && msb == ATAPI_MAGIC_MSB) {
@@ -599,44 +712,39 @@ ata_generic_reset(struct ata_channel *ch)
ch->devices |= ATA_ATA_SLAVE;
}
}
- else if ((stat1 & 0x4f) && err == lsb && err == msb) {
- stat1 |= ATA_S_BUSY;
+ else if ((stat0 & 0x0f) && err == lsb && err == msb) {
+ stat0 |= ATA_S_BUSY;
}
}
}
- if (mask == 0x01) /* wait for master only */
- if (!(stat0 & ATA_S_BUSY) || (stat0 == 0xff && timeout > 5) ||
- (stat0 == err && lsb == err && msb == err && timeout > 5))
+
+ if (mask == 0x00) /* nothing to wait for */
+ break;
+ if (mask == 0x01) /* wait for master only */
+ if (!(stat0 & ATA_S_BUSY) || (stat0 == 0xff && timeout > 10))
break;
- if (mask == 0x02) /* wait for slave only */
- if (!(stat1 & ATA_S_BUSY) || (stat1 == 0xff && timeout > 5) ||
- (stat1 == err && lsb == err && msb == err && timeout > 5))
+ if (mask == 0x02) /* wait for slave only */
+ if (!(stat1 & ATA_S_BUSY) || (stat1 == 0xff && timeout > 10))
break;
- if (mask == 0x03) { /* wait for both master & slave */
+ if (mask == 0x03) { /* wait for both master & slave */
if (!(stat0 & ATA_S_BUSY) && !(stat1 & ATA_S_BUSY))
break;
- if ((stat0 == 0xff && timeout > 5) ||
- (stat0 == err && lsb == err && msb == err && timeout > 5))
+ if ((stat0 == 0xff) && (timeout > 20))
mask &= ~0x01;
- if ((stat1 == 0xff && timeout > 5) ||
- (stat1 == err && lsb == err && msb == err && timeout > 5))
+ if ((stat1 == 0xff) && (timeout > 20))
mask &= ~0x02;
}
- if (mask == 0 && !(stat0 & ATA_S_BUSY) && !(stat1 & ATA_S_BUSY))
- break;
-
ata_udelay(100000);
}
if (bootverbose)
- ata_printf(ch, -1,
- "reset tp2 stat0=%02x stat1=%02x devices=0x%b\n",
- stat0, stat1, ch->devices,
- "\20\4ATAPI_SLAVE\3ATAPI_MASTER\2ATA_SLAVE\1ATA_MASTER");
+ device_printf(ch->dev, "reset tp2 stat0=%02x stat1=%02x devices=0x%b\n",
+ stat0, stat1, ch->devices,
+ "\20\4ATAPI_SLAVE\3ATAPI_MASTER\2ATA_SLAVE\1ATA_MASTER");
}
static int
-ata_wait(struct ata_device *atadev, u_int8_t mask)
+ata_wait(struct ata_channel *ch, struct ata_device *atadev, u_int8_t mask)
{
u_int8_t status;
int timeout = 0;
@@ -645,21 +753,19 @@ ata_wait(struct ata_device *atadev, u_int8_t mask)
/* wait 5 seconds for device to get !BUSY */
while (timeout < 5000000) {
- status = ATA_IDX_INB(atadev->channel, ATA_STATUS);
+ status = ATA_IDX_INB(ch, ATA_ALTSTAT);
- /* if drive fails status, reselect the drive just to be sure */
+ /* if drive fails status, reselect the drive and try again */
if (status == 0xff) {
- ata_prtdev(atadev, "WARNING no status, reselecting device\n");
- ATA_IDX_OUTB(atadev->channel, ATA_DRIVE, ATA_D_IBM | atadev->unit);
- DELAY(10);
- status = ATA_IDX_INB(atadev->channel, ATA_STATUS);
- if (status == 0xff)
- return -1;
+ ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | atadev->unit);
+ timeout += 1000;
+ DELAY(1000);
+ continue;
}
/* are we done ? */
if (!(status & ATA_S_BUSY))
- break;
+ break;
if (timeout > 1000) {
timeout += 1000;
@@ -669,50 +775,46 @@ ata_wait(struct ata_device *atadev, u_int8_t mask)
timeout += 10;
DELAY(10);
}
- }
- if (timeout >= 5000000)
- return -1;
- if (!mask)
- return (status & ATA_S_ERROR);
+ }
+ if (timeout >= 5000000)
+ return -2;
+ if (!mask)
+ return (status & ATA_S_ERROR);
DELAY(1);
- /* wait 50 msec for bits wanted */
+ /* wait 50 msec for bits wanted */
timeout = 5000;
- while (timeout--) {
- status = ATA_IDX_INB(atadev->channel, ATA_STATUS);
+ while (timeout--) {
+ status = ATA_IDX_INB(ch, ATA_ALTSTAT);
if ((status & mask) == mask)
- return (status & ATA_S_ERROR);
- DELAY (10);
- }
- return -1;
+ return (status & ATA_S_ERROR);
+ DELAY(10);
+ }
+ return -3;
}
int
ata_generic_command(struct ata_device *atadev, u_int8_t command,
- u_int64_t lba, u_int16_t count, u_int16_t feature)
+ u_int64_t lba, u_int16_t count, u_int16_t feature)
{
- if (atadebug)
- ata_prtdev(atadev, "ata_command: addr=%04lx, command=%02x, "
- "lba=%jd, count=%d, feature=%d\n",
- rman_get_start(atadev->channel->r_io[ATA_DATA].res),
- command, (intmax_t)lba, count, feature);
+ struct ata_channel *ch = device_get_softc(device_get_parent(atadev->dev));
/* select device */
- ATA_IDX_OUTB(atadev->channel, ATA_DRIVE, ATA_D_IBM | atadev->unit);
+ ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | atadev->unit);
/* ready to issue command ? */
- if (ata_wait(atadev, 0) < 0) {
- ata_prtdev(atadev, "timeout sending command=%02x\n", command);
+ if (ata_wait(ch, atadev, 0) < 0) {
+ device_printf(atadev->dev, "timeout sending command=%02x\n", command);
return -1;
}
/* enable interrupt */
- ATA_IDX_OUTB(atadev->channel, ATA_ALTSTAT, ATA_A_4BIT);
+ ATA_IDX_OUTB(ch, ATA_ALTSTAT, ATA_A_4BIT);
/* only use 48bit addressing if needed (avoid bugs and overhead) */
- if ((lba >= ATA_MAX_28BIT_LBA || count > 256) && atadev->param &&
- atadev->param->support.command2 & ATA_SUPPORT_ADDRESS48) {
+ if ((lba >= ATA_MAX_28BIT_LBA || count > 256) &&
+ atadev->param.support.command2 & ATA_SUPPORT_ADDRESS48) {
/* translate command into 48bit version */
switch (command) {
@@ -735,39 +837,54 @@ ata_generic_command(struct ata_device *atadev, u_int8_t command,
case ATA_FLUSHCACHE:
command = ATA_FLUSHCACHE48; break;
default:
- ata_prtdev(atadev, "can't translate cmd to 48bit version\n");
+ device_printf(atadev->dev,"can't translate cmd to 48bit version\n");
return -1;
}
- ATA_IDX_OUTB(atadev->channel, ATA_FEATURE, (feature>>8) & 0xff);
- ATA_IDX_OUTB(atadev->channel, ATA_FEATURE, feature & 0xff);
- ATA_IDX_OUTB(atadev->channel, ATA_COUNT, (count>>8) & 0xff);
- ATA_IDX_OUTB(atadev->channel, ATA_COUNT, count & 0xff);
- ATA_IDX_OUTB(atadev->channel, ATA_SECTOR, (lba>>24) & 0xff);
- ATA_IDX_OUTB(atadev->channel, ATA_SECTOR, lba & 0xff);
- ATA_IDX_OUTB(atadev->channel, ATA_CYL_LSB, (lba>>32) & 0xff);
- ATA_IDX_OUTB(atadev->channel, ATA_CYL_LSB, (lba>>8) & 0xff);
- ATA_IDX_OUTB(atadev->channel, ATA_CYL_MSB, (lba>>40) & 0xff);
- ATA_IDX_OUTB(atadev->channel, ATA_CYL_MSB, (lba>>16) & 0xff);
- ATA_IDX_OUTB(atadev->channel, ATA_DRIVE, ATA_D_LBA | atadev->unit);
- atadev->channel->flags |= ATA_48BIT_ACTIVE;
+ ATA_IDX_OUTB(ch, ATA_FEATURE, (feature>>8) & 0xff);
+ ATA_IDX_OUTB(ch, ATA_FEATURE, feature & 0xff);
+ ATA_IDX_OUTB(ch, ATA_COUNT, (count>>8) & 0xff);
+ ATA_IDX_OUTB(ch, ATA_COUNT, count & 0xff);
+ ATA_IDX_OUTB(ch, ATA_SECTOR, (lba>>24) & 0xff);
+ ATA_IDX_OUTB(ch, ATA_SECTOR, lba & 0xff);
+ ATA_IDX_OUTB(ch, ATA_CYL_LSB, (lba>>32) & 0xff);
+ ATA_IDX_OUTB(ch, ATA_CYL_LSB, (lba>>8) & 0xff);
+ ATA_IDX_OUTB(ch, ATA_CYL_MSB, (lba>>40) & 0xff);
+ ATA_IDX_OUTB(ch, ATA_CYL_MSB, (lba>>16) & 0xff);
+ ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_LBA | atadev->unit);
+ ch->flags |= ATA_48BIT_ACTIVE;
}
else {
- ATA_IDX_OUTB(atadev->channel, ATA_FEATURE, feature);
- ATA_IDX_OUTB(atadev->channel, ATA_COUNT, count);
- ATA_IDX_OUTB(atadev->channel, ATA_SECTOR, lba & 0xff);
- ATA_IDX_OUTB(atadev->channel, ATA_CYL_LSB, (lba>>8) & 0xff);
- ATA_IDX_OUTB(atadev->channel, ATA_CYL_MSB, (lba>>16) & 0xff);
- if (atadev->flags & ATA_D_USE_CHS)
- ATA_IDX_OUTB(atadev->channel, ATA_DRIVE,
- ATA_D_IBM | atadev->unit | ((lba>>24) & 0xf));
- else
- ATA_IDX_OUTB(atadev->channel, ATA_DRIVE,
- ATA_D_IBM | ATA_D_LBA | atadev->unit|((lba>>24)&0xf));
- atadev->channel->flags &= ~ATA_48BIT_ACTIVE;
+ ATA_IDX_OUTB(ch, ATA_FEATURE, feature);
+ ATA_IDX_OUTB(ch, ATA_COUNT, count);
+ if (atadev->flags & ATA_D_USE_CHS) {
+ int heads, sectors;
+
+ if (atadev->param.atavalid & ATA_FLAG_54_58) {
+ heads = atadev->param.current_heads;
+ sectors = atadev->param.current_sectors;
+ }
+ else {
+ heads = atadev->param.heads;
+ sectors = atadev->param.sectors;
+ }
+ ATA_IDX_OUTB(ch, ATA_SECTOR, (lba % sectors) + 1);
+ ATA_IDX_OUTB(ch, ATA_CYL_LSB, (lba / (sectors * heads)));
+ ATA_IDX_OUTB(ch, ATA_CYL_MSB, (lba / (sectors * heads)) >> 8);
+ ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | atadev->unit |
+ (((lba % (sectors * heads)) / sectors) & 0xf));
+ }
+ else {
+ ATA_IDX_OUTB(ch, ATA_SECTOR, lba & 0xff);
+ ATA_IDX_OUTB(ch, ATA_CYL_LSB, (lba>>8) & 0xff);
+ ATA_IDX_OUTB(ch, ATA_CYL_MSB, (lba>>16) & 0xff);
+ ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | atadev->unit |
+ ((lba>>24) & 0x0f));
+ }
+ ch->flags &= ~ATA_48BIT_ACTIVE;
}
/* issue command to controller */
- ATA_IDX_OUTB(atadev->channel, ATA_CMD, command);
+ ATA_IDX_OUTB(ch, ATA_CMD, command);
return 0;
}
@@ -775,8 +892,8 @@ ata_generic_command(struct ata_device *atadev, u_int8_t command,
static void
ata_pio_read(struct ata_request *request, int length)
{
+ struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
int size = min(request->transfersize, length);
- struct ata_channel *ch = request->device->channel;
int resid;
if (ch->flags & ATA_USE_16BIT || (size % sizeof(int32_t)))
@@ -789,7 +906,7 @@ ata_pio_read(struct ata_request *request, int length)
size / sizeof(int32_t));
if (request->transfersize < length) {
- ata_prtdev(request->device, "WARNING - %s read data overrun %d>%d\n",
+ device_printf(request->dev, "WARNING - %s read data overrun %d>%d\n",
ata_cmd2str(request), length, request->transfersize);
for (resid = request->transfersize; resid < length;
resid += sizeof(int16_t))
@@ -800,8 +917,8 @@ ata_pio_read(struct ata_request *request, int length)
static void
ata_pio_write(struct ata_request *request, int length)
{
+ struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
int size = min(request->transfersize, length);
- struct ata_channel *ch = request->device->channel;
int resid;
if (ch->flags & ATA_USE_16BIT || (size % sizeof(int32_t)))
@@ -814,10 +931,54 @@ ata_pio_write(struct ata_request *request, int length)
size / sizeof(int32_t));
if (request->transfersize < length) {
- ata_prtdev(request->device, "WARNING - %s write data underrun %d>%d\n",
+ device_printf(request->dev, "WARNING - %s write data underrun %d>%d\n",
ata_cmd2str(request), length, request->transfersize);
for (resid = request->transfersize; resid < length;
resid += sizeof(int16_t))
ATA_IDX_OUTW(ch, ATA_DATA, 0);
}
}
+
+static void
+bswap(int8_t *buf, int len)
+{
+ u_int16_t *ptr = (u_int16_t*)(buf + len);
+
+ while (--ptr >= (u_int16_t*)buf)
+ *ptr = ntohs(*ptr);
+}
+
+static void
+btrim(int8_t *buf, int len)
+{
+ int8_t *ptr;
+
+ for (ptr = buf; ptr < buf+len; ++ptr)
+ if (!*ptr || *ptr == '_')
+ *ptr = ' ';
+ for (ptr = buf + len - 1; ptr >= buf && *ptr == ' '; --ptr)
+ *ptr = 0;
+}
+
+static void
+bpack(int8_t *src, int8_t *dst, int len)
+{
+ int i, j, blank;
+
+ for (i = j = blank = 0 ; i < len; i++) {
+ if (blank && src[i] == ' ') continue;
+ if (blank && src[i] != ' ') {
+ dst[j++] = src[i];
+ blank = 0;
+ continue;
+ }
+ if (src[i] == ' ') {
+ blank = 1;
+ if (i == 0)
+ continue;
+ }
+ dst[j++] = src[i];
+ }
+ if (j < len)
+ dst[j] = 0x00;
+}
diff --git a/sys/dev/ata/ata-pci.c b/sys/dev/ata/ata-pci.c
index 747ba41..523ee8e 100644
--- a/sys/dev/ata/ata-pci.c
+++ b/sys/dev/ata/ata-pci.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2004 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2005 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
+#include <sys/ata.h>
#include <sys/bus.h>
#include <sys/malloc.h>
#include <sys/sema.h>
@@ -50,17 +51,17 @@ __FBSDID("$FreeBSD$");
#include <dev/pci/pcireg.h>
#include <dev/ata/ata-all.h>
#include <dev/ata/ata-pci.h>
+#include <ata_if.h>
/* local vars */
static MALLOC_DEFINE(M_ATAPCI, "ATA PCI", "ATA driver PCI");
/* misc defines */
-#define IOMASK 0xfffffffc
+#define IOMASK 0xfffffffc
/* prototypes */
-static int ata_pci_allocate(device_t, struct ata_channel *);
+static int ata_pci_allocate(device_t dev, struct ata_channel *ch);
static void ata_pci_dmainit(struct ata_channel *);
-static int ata_pci_locknoop(struct ata_channel *, int);
int
ata_legacy(device_t dev)
@@ -71,7 +72,7 @@ ata_legacy(device_t dev)
(PCIP_STORAGE_IDE_MODEPRIM | PCIP_STORAGE_IDE_MODESEC)));
}
-static int
+int
ata_pci_probe(device_t dev)
{
if (pci_get_class(dev) != PCIC_STORAGE)
@@ -164,7 +165,7 @@ ata_pci_probe(device_t dev)
return ENXIO;
}
-static int
+int
ata_pci_attach(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(dev);
@@ -178,7 +179,7 @@ ata_pci_attach(device_t dev)
ctlr->channels = 1;
ctlr->allocate = ata_pci_allocate;
ctlr->dmainit = ata_pci_dmainit;
- ctlr->locking = ata_pci_locknoop;
+ ctlr->dev = dev;
/* if needed try to enable busmastering */
cmd = pci_read_config(dev, PCIR_COMMAND, 2);
@@ -209,24 +210,24 @@ ata_pci_attach(device_t dev)
}
device_add_child(dev, "ata", devclass_find_free_unit(ata_devclass, 2));
}
- return bus_generic_attach(dev);
+ bus_generic_attach(dev);
+ return 0;
}
-static int
+int
ata_pci_detach(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(dev);
- struct ata_channel *ch;
- int unit;
+ device_t *children;
+ int nchildren, i;
- /* mark HW as gone, we dont want to issue commands to HW no longer there */
- for (unit = 0; unit < ctlr->channels; unit++) {
- if ((ch = ctlr->interrupt[unit].argument))
- ch->flags |= ATA_HWGONE;
+ /* detach & delete all children */
+ if (!device_get_children(dev, &children, &nchildren)) {
+ for (i = 0; i < nchildren; i++)
+ device_delete_child(dev, children[i]);
+ free(children, M_TEMP);
}
- bus_generic_detach(dev);
-
if (ctlr->r_irq) {
bus_teardown_intr(dev, ctlr->r_irq, ctlr->handle);
bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, ctlr->r_irq);
@@ -239,19 +240,7 @@ ata_pci_detach(device_t dev)
return 0;
}
-static int
-ata_pci_print_child(device_t dev, device_t child)
-{
- struct ata_channel *ch = device_get_softc(child);
- int retval = 0;
-
- retval += bus_print_child_header(dev, child);
- retval += printf(": channel #%d", ch->unit);
- retval += bus_print_child_footer(dev, child);
- return retval;
-}
-
-static struct resource *
+struct resource *
ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags)
{
@@ -307,7 +296,7 @@ ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
return 0;
}
-static int
+int
ata_pci_release_resource(device_t dev, device_t child, int type, int rid,
struct resource *r)
{
@@ -348,7 +337,7 @@ ata_pci_release_resource(device_t dev, device_t child, int type, int rid,
return EINVAL;
}
-static int
+int
ata_pci_setup_intr(device_t dev, device_t child, struct resource *irq,
int flags, driver_intr_t *function, void *argument,
void **cookiep)
@@ -373,7 +362,7 @@ ata_pci_setup_intr(device_t dev, device_t child, struct resource *irq,
}
}
-static int
+int
ata_pci_teardown_intr(device_t dev, device_t child, struct resource *irq,
void *cookie)
{
@@ -435,12 +424,46 @@ ata_pci_allocate(device_t dev, struct ata_channel *ch)
return 0;
}
+static void
+ata_pci_setmode(device_t parent, device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(parent);
+ struct ata_device *atadev = device_get_softc(dev);
+ int mode = atadev->mode;
+
+ ctlr->setmode(atadev, ATA_PIO_MAX);
+ if (mode >= ATA_DMA)
+ ctlr->setmode(atadev, mode);
+}
+
+static int
+ata_pci_locking(device_t parent, device_t dev, int mode)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(parent);
+ struct ata_channel *ch = device_get_softc(dev);
+
+ if (ctlr->locking)
+ return ctlr->locking(ch, mode);
+ else
+ return ch->unit;
+}
+
+static void
+ata_pci_reset(device_t parent, device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(parent);
+ struct ata_channel *ch = device_get_softc(dev);
+
+ if (ctlr->reset)
+ ctlr->reset(ch);
+}
+
static int
ata_pci_dmastart(struct ata_channel *ch)
{
ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, (ATA_IDX_INB(ch, ATA_BMSTAT_PORT) |
(ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR)));
- ATA_IDX_OUTL(ch, ATA_BMDTP_PORT, ch->dma->mdmatab);
+ ATA_IDX_OUTL(ch, ATA_BMDTP_PORT, ch->dma->sg_bus);
ch->dma->flags |= ATA_DMA_ACTIVE;
ATA_IDX_OUTB(ch, ATA_BMCMD_PORT,
(ATA_IDX_INB(ch, ATA_BMCMD_PORT) & ~ATA_BMCMD_WRITE_READ) |
@@ -472,41 +495,41 @@ ata_pci_dmainit(struct ata_channel *ch)
}
}
-static int
-ata_pci_locknoop(struct ata_channel *ch, int flags)
-{
- return ch->unit;
-}
-
static device_method_t ata_pci_methods[] = {
/* device interface */
- DEVMETHOD(device_probe, ata_pci_probe),
- DEVMETHOD(device_attach, ata_pci_attach),
- DEVMETHOD(device_detach, ata_pci_detach),
- DEVMETHOD(device_shutdown, bus_generic_shutdown),
- DEVMETHOD(device_suspend, bus_generic_suspend),
- DEVMETHOD(device_resume, bus_generic_resume),
+ DEVMETHOD(device_probe, ata_pci_probe),
+ DEVMETHOD(device_attach, ata_pci_attach),
+ DEVMETHOD(device_detach, ata_pci_detach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
/* bus methods */
- DEVMETHOD(bus_print_child, ata_pci_print_child),
- DEVMETHOD(bus_alloc_resource, ata_pci_alloc_resource),
- DEVMETHOD(bus_release_resource, ata_pci_release_resource),
- DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
- DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
- DEVMETHOD(bus_setup_intr, ata_pci_setup_intr),
- DEVMETHOD(bus_teardown_intr, ata_pci_teardown_intr),
+ DEVMETHOD(bus_alloc_resource, ata_pci_alloc_resource),
+ DEVMETHOD(bus_release_resource, ata_pci_release_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_setup_intr, ata_pci_setup_intr),
+ DEVMETHOD(bus_teardown_intr, ata_pci_teardown_intr),
+
+ /* ATA methods */
+ DEVMETHOD(ata_setmode, ata_pci_setmode),
+ DEVMETHOD(ata_locking, ata_pci_locking),
+ DEVMETHOD(ata_reset, ata_pci_reset),
{ 0, 0 }
};
+devclass_t atapci_devclass;
+
static driver_t ata_pci_driver = {
"atapci",
ata_pci_methods,
sizeof(struct ata_pci_controller),
};
-static devclass_t ata_pci_devclass;
-
-DRIVER_MODULE(atapci, pci, ata_pci_driver, ata_pci_devclass, 0, 0);
+DRIVER_MODULE(atapci, pci, ata_pci_driver, atapci_devclass, 0, 0);
+MODULE_VERSION(atapci, 1);
+MODULE_DEPEND(atapci, ata, 1, 1, 1);
static int
ata_channel_probe(device_t dev)
@@ -514,6 +537,7 @@ ata_channel_probe(device_t dev)
struct ata_channel *ch = device_get_softc(dev);
device_t *children;
int count, i;
+ char buffer[32];
/* take care of green memory */
bzero(ch, sizeof(struct ata_channel));
@@ -526,6 +550,9 @@ ata_channel_probe(device_t dev)
}
free(children, M_TEMP);
+ sprintf(buffer, "ATA channel %d", ch->unit);
+ device_set_desc_copy(dev, buffer);
+
return ata_probe(dev);
}
@@ -536,11 +563,6 @@ ata_channel_attach(device_t dev)
struct ata_channel *ch = device_get_softc(dev);
int error;
- ch->device[MASTER].setmode = ctlr->setmode;
- ch->device[SLAVE].setmode = ctlr->setmode;
- ch->locking = ctlr->locking;
- ch->reset = ctlr->reset;
-
if (ctlr->r_res1)
ctlr->dmainit(ch);
if (ch->dma)
@@ -569,15 +591,16 @@ ata_channel_detach(device_t dev)
static device_method_t ata_channel_methods[] = {
/* device interface */
- DEVMETHOD(device_probe, ata_channel_probe),
- DEVMETHOD(device_attach, ata_channel_attach),
- DEVMETHOD(device_detach, ata_channel_detach),
- DEVMETHOD(device_suspend, ata_suspend),
- DEVMETHOD(device_resume, ata_resume),
+ DEVMETHOD(device_probe, ata_channel_probe),
+ DEVMETHOD(device_attach, ata_channel_attach),
+ DEVMETHOD(device_detach, ata_channel_detach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
{ 0, 0 }
};
-static driver_t ata_channel_driver = {
+driver_t ata_channel_driver = {
"ata",
ata_channel_methods,
sizeof(struct ata_channel),
diff --git a/sys/dev/ata/ata-pci.h b/sys/dev/ata/ata-pci.h
index 5189e70..be15b38 100644
--- a/sys/dev/ata/ata-pci.h
+++ b/sys/dev/ata/ata-pci.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2003, 2004 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 2003 - 2005 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,306 +30,321 @@
/* structure holding chipset config info */
struct ata_chip_id {
- u_int32_t chipid;
- u_int8_t chiprev;
- int cfg1;
- int cfg2;
- u_int8_t max_dma;
- char *text;
+ u_int32_t chipid;
+ u_int8_t chiprev;
+ int cfg1;
+ int cfg2;
+ u_int8_t max_dma;
+ char *text;
};
/* structure describing a PCI ATA controller */
struct ata_pci_controller {
- int r_type1;
- int r_rid1;
- struct resource *r_res1;
- int r_type2;
- int r_rid2;
- struct resource *r_res2;
- struct resource *r_irq;
- void *handle;
- struct ata_chip_id *chip;
- int channels;
- int (*chipinit)(device_t);
- int (*allocate)(device_t, struct ata_channel *);
- void (*reset)(struct ata_channel *);
- void (*dmainit)(struct ata_channel *);
- void (*setmode)(struct ata_device *, int);
- int (*locking)(struct ata_channel *, int);
+ device_t dev;
+ int r_type1;
+ int r_rid1;
+ struct resource *r_res1;
+ int r_type2;
+ int r_rid2;
+ struct resource *r_res2;
+ struct resource *r_irq;
+ void *handle;
+ struct ata_chip_id *chip;
+ int channels;
+ int (*chipinit)(device_t);
+ int (*allocate)(device_t, struct ata_channel *);
+ int (*locking)(struct ata_channel *, int);
+ void (*reset)(struct ata_channel *);
+ void (*dmainit)(struct ata_channel *);
+ void (*setmode)(struct ata_device *, int);
struct {
- void (*function)(void *);
- void *argument;
- } interrupt[8]; /* SOS max ch# for now XXX */
- void *driver;
+ void (*function)(void *);
+ void *argument;
+ } interrupt[8]; /* SOS max ch# for now XXX */
+};
+
+/* structure for SATA connection update hotplug/hotswap support */
+struct ata_connect_task {
+ struct task task;
+ device_t dev;
+ int action;
+#define ATA_C_ATTACH 1
+#define ATA_C_DETACH 2
};
/* defines for known chipset PCI id's */
-#define ATA_ACARD_ID 0x1191
-#define ATA_ATP850 0x00021191
-#define ATA_ATP850A 0x00041191
-#define ATA_ATP850R 0x00051191
-#define ATA_ATP860A 0x00061191
-#define ATA_ATP860R 0x00071191
-#define ATA_ATP865A 0x00081191
-#define ATA_ATP865R 0x00091191
-
-#define ATA_AMD_ID 0x1022
-#define ATA_AMD755 0x74011022
-#define ATA_AMD756 0x74091022
-#define ATA_AMD766 0x74111022
-#define ATA_AMD768 0x74411022
-#define ATA_AMD8111 0x74691022
-
-#define ATA_ACER_LABS_ID 0x10b9
-#define ATA_ALI_5229 0x522910b9
-
-#define ATA_CENATEK_ID 0x16ca
-#define ATA_CENATEK_ROCKET 0x000116ca
-
-#define ATA_CYRIX_ID 0x1078
-#define ATA_CYRIX_5530 0x01021078
-
-#define ATA_CYPRESS_ID 0x1080
-#define ATA_CYPRESS_82C693 0xc6931080
-
-#define ATA_DEC_21150 0x00221011
-#define ATA_DEC_21150_1 0x00231011
-
-#define ATA_HIGHPOINT_ID 0x1103
-#define ATA_HPT366 0x00041103
-#define ATA_HPT372 0x00051103
-#define ATA_HPT302 0x00061103
-#define ATA_HPT371 0x00071103
-#define ATA_HPT374 0x00081103
-
-#define ATA_INTEL_ID 0x8086
-#define ATA_I960RM 0x09628086
-#define ATA_I82371FB 0x12308086
-#define ATA_I82371SB 0x70108086
-#define ATA_I82371AB 0x71118086
-#define ATA_I82443MX 0x71998086
-#define ATA_I82451NX 0x84ca8086
-#define ATA_I82372FB 0x76018086
-#define ATA_I82801AB 0x24218086
-#define ATA_I82801AA 0x24118086
-#define ATA_I82801BA 0x244a8086
-#define ATA_I82801BA_1 0x244b8086
-#define ATA_I82801CA 0x248a8086
-#define ATA_I82801CA_1 0x248b8086
-#define ATA_I82801DB 0x24cb8086
-#define ATA_I82801DB_1 0x24ca8086
-#define ATA_I82801EB 0x24db8086
-#define ATA_I82801EB_S1 0x24d18086
-#define ATA_I82801EB_R1 0x24df8086
-#define ATA_I6300ESB 0x25a28086
-#define ATA_I6300ESB_S1 0x25a38086
-#define ATA_I6300ESB_R1 0x25b08086
-#define ATA_I82801FB 0x266f8086
-#define ATA_I82801FB_S1 0x26518086
-#define ATA_I82801FB_R1 0x26528086
-
-#define ATA_ITE_ID 0x1283
-#define ATA_IT8212F 0x82121283
-
-#define ATA_MICRON_ID 0x1042
-#define ATA_MICRON_RZ1000 0x10001042
-#define ATA_MICRON_RZ1001 0x10011042
-
-#define ATA_NATIONAL_ID 0x100b
-#define ATA_SC1100 0x0502100b
-
-#define ATA_NVIDIA_ID 0x10de
-#define ATA_NFORCE1 0x01bc10de
-#define ATA_NFORCE2 0x006510de
-#define ATA_NFORCE2_MCP 0x008510de
-#define ATA_NFORCE3 0x00d510de
-#define ATA_NFORCE3_PRO 0x00e510de
-#define ATA_NFORCE3_PRO_S1 0x00e310de
-#define ATA_NFORCE3_PRO_S2 0x00ee10de
-#define ATA_NFORCE3_MCP 0x003510de
-#define ATA_NFORCE3_MCP_S1 0x003610de
-#define ATA_NFORCE3_MCP_S2 0x003e10de
-#define ATA_NFORCE4 0x005310de
-#define ATA_NFORCE4_S1 0x005410de
-#define ATA_NFORCE4_S2 0x005510de
-
-
-#define ATA_PROMISE_ID 0x105a
-#define ATA_PDC20246 0x4d33105a
-#define ATA_PDC20262 0x4d38105a
-#define ATA_PDC20263 0x0d38105a
-#define ATA_PDC20265 0x0d30105a
-#define ATA_PDC20267 0x4d30105a
-#define ATA_PDC20268 0x4d68105a
-#define ATA_PDC20269 0x4d69105a
-#define ATA_PDC20270 0x6268105a
-#define ATA_PDC20271 0x6269105a
-#define ATA_PDC20275 0x1275105a
-#define ATA_PDC20276 0x5275105a
-#define ATA_PDC20277 0x7275105a
-#define ATA_PDC20318 0x3318105a
-#define ATA_PDC20319 0x3319105a
-#define ATA_PDC20371 0x3371105a
-#define ATA_PDC20375 0x3375105a
-#define ATA_PDC20376 0x3376105a
-#define ATA_PDC20377 0x3377105a
-#define ATA_PDC20378 0x3373105a
-#define ATA_PDC20379 0x3372105a
-#define ATA_PDC20571 0x3571105a
-#define ATA_PDC20575 0x3d75105a
-#define ATA_PDC20579 0x3574105a
-#define ATA_PDC20580 0x3570105a
-#define ATA_PDC40518 0x3d18105a
-#define ATA_PDC20617 0x6617105a
-#define ATA_PDC20618 0x6626105a
-#define ATA_PDC20619 0x6629105a
-#define ATA_PDC20620 0x6620105a
-#define ATA_PDC20621 0x6621105a
-#define ATA_PDC20622 0x6622105a
-
-#define ATA_SERVERWORKS_ID 0x1166
-#define ATA_ROSB4_ISA 0x02001166
-#define ATA_ROSB4 0x02111166
-#define ATA_CSB5 0x02121166
-#define ATA_CSB6 0x02131166
-#define ATA_CSB6_1 0x02171166
-
-#define ATA_SILICON_IMAGE_ID 0x1095
-#define ATA_SII3114 0x31141095
-#define ATA_SII3512 0x35121095
-#define ATA_SII3112 0x31121095
-#define ATA_SII3112_1 0x02401095
-#define ATA_SII0680 0x06801095
-#define ATA_CMD646 0x06461095
-#define ATA_CMD648 0x06481095
-#define ATA_CMD649 0x06491095
-
-#define ATA_SIS_ID 0x1039
-#define ATA_SISSOUTH 0x00081039
-#define ATA_SIS5511 0x55111039
-#define ATA_SIS5513 0x55131039
-#define ATA_SIS5517 0x55171039
-#define ATA_SIS5518 0x55181039
-#define ATA_SIS5571 0x55711039
-#define ATA_SIS5591 0x55911039
-#define ATA_SIS5596 0x55961039
-#define ATA_SIS5597 0x55971039
-#define ATA_SIS5598 0x55981039
-#define ATA_SIS5600 0x56001039
-#define ATA_SIS530 0x05301039
-#define ATA_SIS540 0x05401039
-#define ATA_SIS550 0x05501039
-#define ATA_SIS620 0x06201039
-#define ATA_SIS630 0x06301039
-#define ATA_SIS635 0x06351039
-#define ATA_SIS633 0x06331039
-#define ATA_SIS640 0x06401039
-#define ATA_SIS645 0x06451039
-#define ATA_SIS646 0x06461039
-#define ATA_SIS648 0x06481039
-#define ATA_SIS650 0x06501039
-#define ATA_SIS651 0x06511039
-#define ATA_SIS652 0x06521039
-#define ATA_SIS655 0x06551039
-#define ATA_SIS658 0x06581039
-#define ATA_SIS661 0x06611039
-#define ATA_SIS730 0x07301039
-#define ATA_SIS733 0x07331039
-#define ATA_SIS735 0x07351039
-#define ATA_SIS740 0x07401039
-#define ATA_SIS745 0x07451039
-#define ATA_SIS746 0x07461039
-#define ATA_SIS748 0x07481039
-#define ATA_SIS750 0x07501039
-#define ATA_SIS751 0x07511039
-#define ATA_SIS752 0x07521039
-#define ATA_SIS755 0x07551039
-#define ATA_SIS961 0x09611039
-#define ATA_SIS962 0x09621039
-#define ATA_SIS963 0x09631039
-#define ATA_SIS964 0x09641039
-#define ATA_SIS964_S 0x01801039
-
-#define ATA_VIA_ID 0x1106
-#define ATA_VIA82C571 0x05711106
-#define ATA_VIA82C586 0x05861106
-#define ATA_VIA82C596 0x05961106
-#define ATA_VIA82C686 0x06861106
-#define ATA_VIA8231 0x82311106
-#define ATA_VIA8233 0x30741106
-#define ATA_VIA8233A 0x31471106
-#define ATA_VIA8233C 0x31091106
-#define ATA_VIA8235 0x31771106
-#define ATA_VIA8237 0x32271106
-#define ATA_VIA8361 0x31121106
-#define ATA_VIA8363 0x03051106
-#define ATA_VIA8371 0x03911106
-#define ATA_VIA8662 0x31021106
-#define ATA_VIA6410 0x31641106
-#define ATA_VIA6420 0x31491106
+#define ATA_ACARD_ID 0x1191
+#define ATA_ATP850 0x00021191
+#define ATA_ATP850A 0x00041191
+#define ATA_ATP850R 0x00051191
+#define ATA_ATP860A 0x00061191
+#define ATA_ATP860R 0x00071191
+#define ATA_ATP865A 0x00081191
+#define ATA_ATP865R 0x00091191
+
+#define ATA_AMD_ID 0x1022
+#define ATA_AMD755 0x74011022
+#define ATA_AMD756 0x74091022
+#define ATA_AMD766 0x74111022
+#define ATA_AMD768 0x74411022
+#define ATA_AMD8111 0x74691022
+
+#define ATA_ACER_LABS_ID 0x10b9
+#define ATA_ALI_5229 0x522910b9
+
+#define ATA_CENATEK_ID 0x16ca
+#define ATA_CENATEK_ROCKET 0x000116ca
+
+#define ATA_CYRIX_ID 0x1078
+#define ATA_CYRIX_5530 0x01021078
+
+#define ATA_CYPRESS_ID 0x1080
+#define ATA_CYPRESS_82C693 0xc6931080
+
+#define ATA_DEC_21150 0x00221011
+#define ATA_DEC_21150_1 0x00231011
+
+#define ATA_HIGHPOINT_ID 0x1103
+#define ATA_HPT366 0x00041103
+#define ATA_HPT372 0x00051103
+#define ATA_HPT302 0x00061103
+#define ATA_HPT371 0x00071103
+#define ATA_HPT374 0x00081103
+
+#define ATA_INTEL_ID 0x8086
+#define ATA_I960RM 0x09628086
+#define ATA_I82371FB 0x12308086
+#define ATA_I82371SB 0x70108086
+#define ATA_I82371AB 0x71118086
+#define ATA_I82443MX 0x71998086
+#define ATA_I82451NX 0x84ca8086
+#define ATA_I82372FB 0x76018086
+#define ATA_I82801AB 0x24218086
+#define ATA_I82801AA 0x24118086
+#define ATA_I82801BA 0x244a8086
+#define ATA_I82801BA_1 0x244b8086
+#define ATA_I82801CA 0x248a8086
+#define ATA_I82801CA_1 0x248b8086
+#define ATA_I82801DB 0x24cb8086
+#define ATA_I82801DB_1 0x24ca8086
+#define ATA_I82801EB 0x24db8086
+#define ATA_I82801EB_S1 0x24d18086
+#define ATA_I82801EB_R1 0x24df8086
+#define ATA_I6300ESB 0x25a28086
+#define ATA_I6300ESB_S1 0x25a38086
+#define ATA_I6300ESB_R1 0x25b08086
+#define ATA_I82801FB 0x266f8086
+#define ATA_I82801FB_S1 0x26518086
+#define ATA_I82801FB_R1 0x26528086
+
+#define ATA_ITE_ID 0x1283
+#define ATA_IT8212F 0x82121283
+
+#define ATA_MICRON_ID 0x1042
+#define ATA_MICRON_RZ1000 0x10001042
+#define ATA_MICRON_RZ1001 0x10011042
+
+#define ATA_NATIONAL_ID 0x100b
+#define ATA_SC1100 0x0502100b
+
+#define ATA_NVIDIA_ID 0x10de
+#define ATA_NFORCE1 0x01bc10de
+#define ATA_NFORCE2 0x006510de
+#define ATA_NFORCE2_MCP 0x008510de
+#define ATA_NFORCE3 0x00d510de
+#define ATA_NFORCE3_PRO 0x00e510de
+#define ATA_NFORCE3_PRO_S1 0x00e310de
+#define ATA_NFORCE3_PRO_S2 0x00ee10de
+#define ATA_NFORCE3_MCP 0x003510de
+#define ATA_NFORCE3_MCP_S1 0x003610de
+#define ATA_NFORCE3_MCP_S2 0x003e10de
+#define ATA_NFORCE4 0x005310de
+#define ATA_NFORCE4_S1 0x005410de
+#define ATA_NFORCE4_S2 0x005510de
+
+
+#define ATA_PROMISE_ID 0x105a
+#define ATA_PDC20246 0x4d33105a
+#define ATA_PDC20262 0x4d38105a
+#define ATA_PDC20263 0x0d38105a
+#define ATA_PDC20265 0x0d30105a
+#define ATA_PDC20267 0x4d30105a
+#define ATA_PDC20268 0x4d68105a
+#define ATA_PDC20269 0x4d69105a
+#define ATA_PDC20270 0x6268105a
+#define ATA_PDC20271 0x6269105a
+#define ATA_PDC20275 0x1275105a
+#define ATA_PDC20276 0x5275105a
+#define ATA_PDC20277 0x7275105a
+#define ATA_PDC20318 0x3318105a
+#define ATA_PDC20319 0x3319105a
+#define ATA_PDC20371 0x3371105a
+#define ATA_PDC20375 0x3375105a
+#define ATA_PDC20376 0x3376105a
+#define ATA_PDC20377 0x3377105a
+#define ATA_PDC20378 0x3373105a
+#define ATA_PDC20379 0x3372105a
+#define ATA_PDC20571 0x3571105a
+#define ATA_PDC20575 0x3d75105a
+#define ATA_PDC20579 0x3574105a
+#define ATA_PDC20580 0x3570105a
+#define ATA_PDC40518 0x3d18105a
+#define ATA_PDC20617 0x6617105a
+#define ATA_PDC20618 0x6626105a
+#define ATA_PDC20619 0x6629105a
+#define ATA_PDC20620 0x6620105a
+#define ATA_PDC20621 0x6621105a
+#define ATA_PDC20622 0x6622105a
+
+#define ATA_SERVERWORKS_ID 0x1166
+#define ATA_ROSB4_ISA 0x02001166
+#define ATA_ROSB4 0x02111166
+#define ATA_CSB5 0x02121166
+#define ATA_CSB6 0x02131166
+#define ATA_CSB6_1 0x02171166
+
+#define ATA_SILICON_IMAGE_ID 0x1095
+#define ATA_SII3114 0x31141095
+#define ATA_SII3512 0x35121095
+#define ATA_SII3112 0x31121095
+#define ATA_SII3112_1 0x02401095
+#define ATA_SII0680 0x06801095
+#define ATA_CMD646 0x06461095
+#define ATA_CMD648 0x06481095
+#define ATA_CMD649 0x06491095
+
+#define ATA_SIS_ID 0x1039
+#define ATA_SISSOUTH 0x00081039
+#define ATA_SIS5511 0x55111039
+#define ATA_SIS5513 0x55131039
+#define ATA_SIS5517 0x55171039
+#define ATA_SIS5518 0x55181039
+#define ATA_SIS5571 0x55711039
+#define ATA_SIS5591 0x55911039
+#define ATA_SIS5596 0x55961039
+#define ATA_SIS5597 0x55971039
+#define ATA_SIS5598 0x55981039
+#define ATA_SIS5600 0x56001039
+#define ATA_SIS530 0x05301039
+#define ATA_SIS540 0x05401039
+#define ATA_SIS550 0x05501039
+#define ATA_SIS620 0x06201039
+#define ATA_SIS630 0x06301039
+#define ATA_SIS635 0x06351039
+#define ATA_SIS633 0x06331039
+#define ATA_SIS640 0x06401039
+#define ATA_SIS645 0x06451039
+#define ATA_SIS646 0x06461039
+#define ATA_SIS648 0x06481039
+#define ATA_SIS650 0x06501039
+#define ATA_SIS651 0x06511039
+#define ATA_SIS652 0x06521039
+#define ATA_SIS655 0x06551039
+#define ATA_SIS658 0x06581039
+#define ATA_SIS661 0x06611039
+#define ATA_SIS730 0x07301039
+#define ATA_SIS733 0x07331039
+#define ATA_SIS735 0x07351039
+#define ATA_SIS740 0x07401039
+#define ATA_SIS745 0x07451039
+#define ATA_SIS746 0x07461039
+#define ATA_SIS748 0x07481039
+#define ATA_SIS750 0x07501039
+#define ATA_SIS751 0x07511039
+#define ATA_SIS752 0x07521039
+#define ATA_SIS755 0x07551039
+#define ATA_SIS961 0x09611039
+#define ATA_SIS962 0x09621039
+#define ATA_SIS963 0x09631039
+#define ATA_SIS964 0x09641039
+#define ATA_SIS965 0x09641039
+#define ATA_SIS180 0x01801039
+#define ATA_SIS181 0x01811039
+
+#define ATA_VIA_ID 0x1106
+#define ATA_VIA82C571 0x05711106
+#define ATA_VIA82C586 0x05861106
+#define ATA_VIA82C596 0x05961106
+#define ATA_VIA82C686 0x06861106
+#define ATA_VIA8231 0x82311106
+#define ATA_VIA8233 0x30741106
+#define ATA_VIA8233A 0x31471106
+#define ATA_VIA8233C 0x31091106
+#define ATA_VIA8235 0x31771106
+#define ATA_VIA8237 0x32271106
+#define ATA_VIA8361 0x31121106
+#define ATA_VIA8363 0x03051106
+#define ATA_VIA8371 0x03911106
+#define ATA_VIA8662 0x31021106
+#define ATA_VIA6410 0x31641106
+#define ATA_VIA6420 0x31491106
/* chipset setup related defines */
-#define ATPOLD 1
-
-#define ALIOLD 0x01
-#define ALINEW 0x02
-
-#define HPT366 0
-#define HPT370 1
-#define HPT372 2
-#define HPT374 3
-#define HPTOLD 0x01
-
-#define PROLD 0
-#define PRNEW 1
-#define PRTX 2
-#define PRMIO 3
-#define PRTX4 0x01
-#define PRSX4X 0x02
-#define PRSX6K 0x04
-#define PRPATA 0x08
-#define PRCMBO 0x10
-#define PRCMBO2 0x20
-#define PRSATA 0x40
-#define PRSATA2 0x80
-
-#define SWKS33 0
-#define SWKS66 1
-#define SWKS100 2
-
-#define SIIMEMIO 1
-#define SIIINTR 0x01
-#define SIISETCLK 0x02
-#define SIIBUG 0x04
-#define SII4CH 0x08
-
-#define SIS_SOUTH 1
-#define SISSATA 2
-#define SIS133NEW 3
-#define SIS133OLD 4
-#define SIS100NEW 5
-#define SIS100OLD 6
-#define SIS66 7
-#define SIS33 8
-
-#define VIA33 0
-#define VIA66 1
-#define VIA100 2
-#define VIA133 3
-#define AMDNVIDIA 4
-#define AMDCABLE 0x01
-#define AMDBUG 0x02
-#define NVIDIA 0x04
-#define VIACLK 0x08
-#define VIABUG 0x10
-
-/* global prototypes */
-int ata_legacy(device_t);
+#define ATPOLD 1
-void ata_dmainit(struct ata_channel *);
-int ata_dmastart(struct ata_channel *, caddr_t, int32_t, int);
-int ata_dmastop(struct ata_channel *);
+#define ALIOLD 0x01
+#define ALINEW 0x02
+
+#define HPT366 0
+#define HPT370 1
+#define HPT372 2
+#define HPT374 3
+#define HPTOLD 0x01
+
+#define PROLD 0
+#define PRNEW 1
+#define PRTX 2
+#define PRMIO 3
+#define PRTX4 0x01
+#define PRSX4X 0x02
+#define PRSX6K 0x04
+#define PRPATA 0x08
+#define PRCMBO 0x10
+#define PRCMBO2 0x20
+#define PRSATA 0x40
+#define PRSATA2 0x80
+#define SWKS33 0
+#define SWKS66 1
+#define SWKS100 2
+
+#define SIIMEMIO 1
+#define SIIINTR 0x01
+#define SIISETCLK 0x02
+#define SIIBUG 0x04
+#define SII4CH 0x08
+
+#define SIS_SOUTH 1
+#define SISSATA 2
+#define SIS133NEW 3
+#define SIS133OLD 4
+#define SIS100NEW 5
+#define SIS100OLD 6
+#define SIS66 7
+#define SIS33 8
+
+#define VIA33 0
+#define VIA66 1
+#define VIA100 2
+#define VIA133 3
+#define AMDNVIDIA 4
+#define AMDCABLE 0x01
+#define AMDBUG 0x02
+#define NVIDIA 0x04
+#define VIACLK 0x08
+#define VIABUG 0x10
+
+/* global prototypes ata-pci.c */
+int ata_pci_probe(device_t dev);
+int ata_pci_attach(device_t dev);
+int ata_pci_detach(device_t dev);
+struct resource * ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags);
+int ata_pci_release_resource(device_t dev, device_t child, int type, int rid, struct resource *r);
+int ata_pci_setup_intr(device_t dev, device_t child, struct resource *irq, int flags, driver_intr_t *function, void *argument, void **cookiep);
+ int ata_pci_teardown_intr(device_t dev, device_t child, struct resource *irq, void *cookie);
+extern driver_t ata_channel_driver;
+
+/* global prototypes ata-chipset.c */
int ata_generic_ident(device_t);
int ata_acard_ident(device_t);
int ata_ali_ident(device_t);
@@ -346,3 +361,8 @@ int ata_serverworks_ident(device_t);
int ata_sii_ident(device_t);
int ata_sis_ident(device_t);
int ata_via_ident(device_t);
+int ata_legacy(device_t);
+struct ata_chip_id *ata_match_chip(device_t, struct ata_chip_id *);
+
+/* global prototypes ata-dma.c */
+void ata_dmainit(struct ata_channel *);
diff --git a/sys/dev/ata/ata-queue.c b/sys/dev/ata/ata-queue.c
index 8800230..603e85d 100644
--- a/sys/dev/ata/ata-queue.c
+++ b/sys/dev/ata/ata-queue.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2004 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2005 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -43,16 +43,18 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <sys/rman.h>
#include <dev/ata/ata-all.h>
+#include <ata_if.h>
/* prototypes */
static void ata_completed(void *, int);
static void ata_timeout(struct ata_request *);
+static void ata_sort_queue(struct ata_channel *ch, struct ata_request *request);
static char *ata_skey2str(u_int8_t);
void
ata_queue_request(struct ata_request *request)
{
- struct ata_channel *ch = request->device->channel;
+ struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
/* mark request as virgin */
request->result = request->status = request->error = 0;
@@ -61,16 +63,13 @@ ata_queue_request(struct ata_request *request)
if (!request->callback && !(request->flags & ATA_R_REQUEUE))
sema_init(&request->done, 0, "ATA request done");
- /* in IMMEDIATE_MODE we dont queue but call HW directly */
- /* used only during reinit for getparm and config */
- if ((ch->flags & ATA_IMMEDIATE_MODE) &&
- (request->flags & (ATA_R_CONTROL | ATA_R_IMMEDIATE))) {
+ /* in ATA_STALL_QUEUE state we call HW directly (used only during reinit) */
+ if ((ch->state & ATA_STALL_QUEUE) && (request->flags & ATA_R_CONTROL)) {
/* arm timeout */
if (!dumping)
callout_reset(&request->callout, request->timeout * hz,
(timeout_t*)ata_timeout, request);
-
/* kick HW into action */
ch->running = request;
if (ch->hw.begin_transaction(request) == ATA_OP_FINISHED) {
@@ -84,13 +83,15 @@ ata_queue_request(struct ata_request *request)
else {
/* put request on the locked queue at the specified location */
mtx_lock(&ch->queue_mtx);
- if (request->flags & ATA_R_IMMEDIATE)
+ if (request->flags & ATA_R_AT_HEAD)
TAILQ_INSERT_HEAD(&ch->ata_queue, request, chain);
+ else if (request->flags & ATA_R_ORDERED)
+ ata_sort_queue(ch, request);
else
TAILQ_INSERT_TAIL(&ch->ata_queue, request, chain);
mtx_unlock(&ch->queue_mtx);
ATA_DEBUG_RQ(request, "queued");
- ata_start(ch);
+ ata_start(ch->dev);
}
/* if this is a requeued request callback/sleep has been setup */
@@ -100,7 +101,12 @@ ata_queue_request(struct ata_request *request)
/* if this is not a callback wait until request is completed */
if (!request->callback) {
ATA_DEBUG_RQ(request, "wait for completition");
- sema_wait(&request->done);
+ while (sema_timedwait(&request->done, request->timeout * hz * 4)) {
+ device_printf(request->dev,
+ "req=%p %s semaphore timeout !! DANGER Will Robinson !!\n",
+ request, ata_cmd2str(request));
+ ata_start(ch->dev);
+ }
sema_destroy(&request->done);
}
}
@@ -113,13 +119,13 @@ ata_controlcmd(struct ata_device *atadev, u_int8_t command, u_int16_t feature,
int error = ENOMEM;
if (request) {
- request->device = atadev;
+ request->dev = atadev->dev;
request->u.ata.command = command;
request->u.ata.lba = lba;
request->u.ata.count = count;
request->u.ata.feature = feature;
request->flags = ATA_R_CONTROL;
- request->timeout = 5;
+ request->timeout = 1;
request->retries = 0;
ata_queue_request(request);
error = request->result;
@@ -136,8 +142,8 @@ ata_atapicmd(struct ata_device *atadev, u_int8_t *ccb, caddr_t data,
int error = ENOMEM;
if (request) {
- request->device = atadev;
- if ((atadev->param->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12)
+ request->dev = atadev->dev;
+ if ((atadev->param.config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12)
bcopy(ccb, request->u.atapi.ccb, 12);
else
bcopy(ccb, request->u.atapi.ccb, 16);
@@ -154,47 +160,58 @@ ata_atapicmd(struct ata_device *atadev, u_int8_t *ccb, caddr_t data,
}
void
-ata_start(struct ata_channel *ch)
+ata_start(device_t dev)
{
+ struct ata_channel *ch = device_get_softc(dev);
struct ata_request *request;
-
- /* if in immediate mode, just skip start requests (stall queue) */
- if (ch->flags & ATA_IMMEDIATE_MODE)
- return;
-
- /* if we dont have any work, ask the subdriver(s) */
- mtx_lock(&ch->queue_mtx);
- if (TAILQ_EMPTY(&ch->ata_queue)) {
- mtx_unlock(&ch->queue_mtx);
- if (ch->device[MASTER].start)
- ch->device[MASTER].start(&ch->device[MASTER]);
- if (ch->device[SLAVE].start)
- ch->device[SLAVE].start(&ch->device[SLAVE]);
- mtx_lock(&ch->queue_mtx);
- }
+ struct ata_composite *cptr;
+ int dependencies = 0;
/* if we have a request on the queue try to get it running */
+ mtx_lock(&ch->queue_mtx);
if ((request = TAILQ_FIRST(&ch->ata_queue))) {
/* we need the locking function to get the lock for this channel */
- if (ch->locking(ch, ATA_LF_LOCK) == ch->unit) {
+ if (ATA_LOCKING(device_get_parent(dev), dev, ATA_LF_LOCK) == ch->unit) {
+
+ /* check for composite dependencies */
+ if ((cptr = request->composite)) {
+ mtx_lock(&cptr->lock);
+ if ((request->flags & ATA_R_WRITE) &&
+ (cptr->wr_depend & cptr->rd_done) != cptr->wr_depend) {
+ dependencies = 1;
+ }
+ mtx_unlock(&cptr->lock);
+ }
- /* check for the right state */
+ /* check we are int the right state and has no dependencies */
mtx_lock(&ch->state_mtx);
- if (ch->state == ATA_IDLE) {
+ if (ch->state == ATA_IDLE && !dependencies) {
ATA_DEBUG_RQ(request, "starting");
+#if 0
+ if (request->sequence_count)
+ request = request->sequence[--request->sequence_count];
+ else
+#else
TAILQ_REMOVE(&ch->ata_queue, request, chain);
+#endif
ch->running = request;
ch->state = ATA_ACTIVE;
+
+ /* if we are the freezing point release it */
+ if (ch->freezepoint == request)
+ ch->freezepoint = NULL;
+
+ /* arm timeout for this request */
if (!dumping)
callout_reset(&request->callout, request->timeout * hz,
(timeout_t*)ata_timeout, request);
if (ch->hw.begin_transaction(request) == ATA_OP_FINISHED) {
ch->running = NULL;
ch->state = ATA_IDLE;
- mtx_unlock(&ch->queue_mtx);
mtx_unlock(&ch->state_mtx);
- ch->locking(ch, ATA_LF_UNLOCK);
+ mtx_unlock(&ch->queue_mtx);
+ ATA_LOCKING(device_get_parent(dev), dev, ATA_LF_UNLOCK);
ata_finish(request);
return;
}
@@ -208,25 +225,26 @@ ata_start(struct ata_channel *ch)
void
ata_finish(struct ata_request *request)
{
- struct ata_channel *ch = request->device->channel;
+ struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
- /* schedule it for completition */
- if (ch->flags & ATA_IMMEDIATE_MODE) {
+ /* if in STALL_QUEUE state or request is ATA_R_DIRECT call complete now */
+ if ((ch->state & ATA_STALL_QUEUE) || (request->flags & ATA_R_DIRECT)) {
ATA_DEBUG_RQ(request, "finish directly");
ata_completed(request, 0);
}
else {
- if (!dumping)
+ /* reset timeout and put on the proper taskqueue for completition */
+ if (!dumping && !(request->flags & ATA_R_TIMEOUT))
callout_reset(&request->callout, request->timeout * hz,
(timeout_t*)ata_timeout, request);
- if (request->bio && !(request->flags & ATA_R_TIMEOUT)) {
+ if (request->bio && !(request->flags & (ATA_R_THREAD | ATA_R_TIMEOUT))){
ATA_DEBUG_RQ(request, "finish bio_taskqueue");
bio_taskqueue(request->bio, (bio_task_t *)ata_completed, request);
}
else {
TASK_INIT(&request->task, 0, ata_completed, request);
- ATA_DEBUG_RQ(request, "finish taskqueue_thread");
- taskqueue_enqueue(taskqueue_thread, &request->task);
+ ATA_DEBUG_RQ(request, "finish taskqueue_swi");
+ taskqueue_enqueue(taskqueue_swi, &request->task);
}
}
}
@@ -235,7 +253,9 @@ static void
ata_completed(void *context, int dummy)
{
struct ata_request *request = (struct ata_request *)context;
- struct ata_channel *ch = request->device->channel;
+ struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
+ struct ata_device *atadev = device_get_softc(request->dev);
+ struct ata_composite *composite;
ATA_DEBUG_RQ(request, "completed entered");
@@ -245,21 +265,25 @@ ata_completed(void *context, int dummy)
* if reinit succeeds, retries still permit and device didn't
* get removed by the reinit, reinject request
*/
- if (!ata_reinit(ch) && request->retries-- > 0
- && request->device->param){
+ if (!ata_reinit(ch->dev) && request->dev && (request->retries-- > 0)) {
request->flags &= ~(ATA_R_TIMEOUT | ATA_R_DEBUG);
- request->flags |= (ATA_R_IMMEDIATE | ATA_R_REQUEUE);
- request->donecount = 0;
+ request->flags |= (ATA_R_AT_HEAD | ATA_R_REQUEUE);
ATA_DEBUG_RQ(request, "completed reinject");
ata_queue_request(request);
return;
}
/* nothing more to try so finish with error */
- if (!(request->flags & ATA_R_QUIET))
- ata_prtdev(request->device,
- "FAILURE - %s timed out\n",
- ata_cmd2str(request));
+ if (!(request->flags & ATA_R_QUIET)) {
+ if (request->dev) {
+ device_printf(request->dev,
+ "FAILURE - %s timed out",
+ ata_cmd2str(request));
+ if (!(request->flags & (ATA_R_ATAPI | ATA_R_CONTROL)))
+ printf(" LBA=%llu", (unsigned long long)request->u.ata.lba);
+ printf("\n");
+ }
+ }
if (!request->result)
request->result = EIO;
}
@@ -269,9 +293,9 @@ ata_completed(void *context, int dummy)
/* if this is a soft ECC error warn about it */
if ((request->status & (ATA_S_CORR | ATA_S_ERROR)) == ATA_S_CORR) {
- ata_prtdev(request->device,
- "WARNING - %s soft error (ECC corrected)",
- ata_cmd2str(request));
+ device_printf(request->dev,
+ "WARNING - %s soft error (ECC corrected)",
+ ata_cmd2str(request));
if (!(request->flags & (ATA_R_ATAPI | ATA_R_CONTROL)))
printf(" LBA=%llu", (unsigned long long)request->u.ata.lba);
printf("\n");
@@ -280,13 +304,13 @@ ata_completed(void *context, int dummy)
/* if this is a UDMA CRC error, retry request */
if (request->flags & ATA_R_DMA && request->error & ATA_E_ICRC) {
if (request->retries-- > 0) {
- ata_prtdev(request->device,
- "WARNING - %s UDMA ICRC error (retrying request)",
- ata_cmd2str(request));
+ device_printf(request->dev,
+ "WARNING - %s UDMA ICRC error (retrying request)",
+ ata_cmd2str(request));
if (!(request->flags & (ATA_R_ATAPI | ATA_R_CONTROL)))
printf(" LBA=%llu", (unsigned long long)request->u.ata.lba);
printf("\n");
- request->flags |= (ATA_R_IMMEDIATE | ATA_R_REQUEUE);
+ request->flags |= (ATA_R_AT_HEAD | ATA_R_REQUEUE);
ata_queue_request(request);
return;
}
@@ -299,14 +323,15 @@ ata_completed(void *context, int dummy)
default:
if (!request->result && request->status & ATA_S_ERROR) {
if (!(request->flags & ATA_R_QUIET)) {
- ata_prtdev(request->device,
- "FAILURE - %s status=%b error=%b",
- ata_cmd2str(request),
- request->status, "\20\10BUSY\7READY\6DMA_READY"
- "\5DSC\4DRQ\3CORRECTABLE\2INDEX\1ERROR",
- request->error, "\20\10ICRC\7UNCORRECTABLE"
- "\6MEDIA_CHANGED\5NID_NOT_FOUND\4MEDIA_CHANGE_REQEST"
- "\3ABORTED\2NO_MEDIA\1ILLEGAL_LENGTH");
+ device_printf(request->dev,
+ "FAILURE - %s status=%b error=%b",
+ ata_cmd2str(request),
+ request->status, "\20\10BUSY\7READY\6DMA_READY"
+ "\5DSC\4DRQ\3CORRECTABLE\2INDEX\1ERROR",
+ request->error, "\20\10ICRC\7UNCORRECTABLE"
+ "\6MEDIA_CHANGED\5NID_NOT_FOUND"
+ "\4MEDIA_CHANGE_REQEST"
+ "\3ABORTED\2NO_MEDIA\1ILLEGAL_LENGTH");
if ((request->flags & ATA_R_DMA) &&
(request->dmastat & ATA_BMSTAT_ERROR))
printf(" dma=0x%02x", request->dmastat);
@@ -314,8 +339,6 @@ ata_completed(void *context, int dummy)
printf(" LBA=%llu", (unsigned long long)request->u.ata.lba);
printf("\n");
}
-
- /* SOS this could be more precise ? XXX */
request->result = EIO;
}
break;
@@ -330,7 +353,7 @@ ata_completed(void *context, int dummy)
if (request->error & ATA_SK_MASK &&
request->u.atapi.ccb[0] != ATAPI_REQUEST_SENSE) {
static u_int8_t ccb[16] = { ATAPI_REQUEST_SENSE, 0, 0, 0,
- sizeof(struct atapi_sense),
+ sizeof(struct atapi_sense),
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
request->u.atapi.sense_key = request->error;
@@ -341,7 +364,7 @@ ata_completed(void *context, int dummy)
request->transfersize = sizeof(struct atapi_sense);
request->timeout = 5;
request->flags &= (ATA_R_ATAPI | ATA_R_QUIET);
- request->flags |= (ATA_R_READ | ATA_R_IMMEDIATE | ATA_R_REQUEUE);
+ request->flags |= (ATA_R_READ | ATA_R_AT_HEAD | ATA_R_REQUEUE);
ATA_DEBUG_RQ(request, "autoissue request sense");
ata_queue_request(request);
return;
@@ -349,8 +372,8 @@ ata_completed(void *context, int dummy)
switch (request->u.atapi.sense_key & ATA_SK_MASK) {
case ATA_SK_RECOVERED_ERROR:
- ata_prtdev(request->device, "WARNING - %s recovered error\n",
- ata_cmd2str(request));
+ device_printf(request->dev, "WARNING - %s recovered error\n",
+ ata_cmd2str(request));
/* FALLTHROUGH */
case ATA_SK_NO_SENSE:
@@ -362,7 +385,7 @@ ata_completed(void *context, int dummy)
break;
case ATA_SK_UNIT_ATTENTION:
- request->device->flags |= ATA_D_MEDIA_CHANGED;
+ atadev->flags |= ATA_D_MEDIA_CHANGED;
request->result = EIO;
break;
@@ -371,12 +394,12 @@ ata_completed(void *context, int dummy)
if (request->flags & ATA_R_QUIET)
break;
- ata_prtdev(request->device,
- "FAILURE - %s %s asc=0x%02x ascq=0x%02x ",
- ata_cmd2str(request), ata_skey2str(
- (request->u.atapi.sense_key & ATA_SK_MASK) >> 4),
- request->u.atapi.sense_data.asc,
- request->u.atapi.sense_data.ascq);
+ device_printf(request->dev,
+ "FAILURE - %s %s asc=0x%02x ascq=0x%02x ",
+ ata_cmd2str(request), ata_skey2str(
+ (request->u.atapi.sense_key & ATA_SK_MASK) >> 4),
+ request->u.atapi.sense_data.asc,
+ request->u.atapi.sense_data.ascq);
if (request->u.atapi.sense_data.sksv)
printf("sks=0x%02x 0x%02x 0x%02x ",
request->u.atapi.sense_data.sk_specific,
@@ -395,29 +418,50 @@ ata_completed(void *context, int dummy)
ATA_DEBUG_RQ(request, "completed callback/wakeup");
+ /* if we are part of a composite operation update progress */
+ if ((composite = request->composite)) {
+ int index = 0;
+
+ mtx_lock(&composite->lock);
+ if (request->flags & ATA_R_READ)
+ composite->rd_done |= (1 << request->this);
+ if (request->flags & ATA_R_WRITE)
+ composite->wr_done |= (1 << request->this);
+
+ if (composite->wr_depend &&
+ (composite->rd_done & composite->wr_depend)==composite->wr_depend &&
+ (composite->wr_needed & (~composite->wr_done))) {
+ index = ((composite->wr_needed & (~composite->wr_done))) - 1;
+ }
+ mtx_unlock(&composite->lock);
+ if (index)
+ ata_start(device_get_parent(composite->request[index]->dev));
+ }
+
/* get results back to the initiator */
if (request->callback)
(request->callback)(request);
else
sema_post(&request->done);
- ata_start(ch);
+ ata_start(ch->dev);
}
static void
ata_timeout(struct ata_request *request)
{
- struct ata_channel *ch = request->device->channel;
+ struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
mtx_lock(&ch->state_mtx);
+ //request->flags |= ATA_R_DEBUG;
ATA_DEBUG_RQ(request, "timeout");
/* if interrupt has been seen, shout and just rearm timeout */
if (request->flags & ATA_R_INTR_SEEN) {
- ata_prtdev(request->device,
- "WARNING - %s interrupt was seen but timeout fired",
- ata_cmd2str(request));
+ device_printf(request->dev,
+ "WARNING - %s interrupt was seen but timeout fired",
+ ata_cmd2str(request));
if (!(request->flags & (ATA_R_ATAPI | ATA_R_CONTROL)))
printf(" LBA=%llu", (unsigned long long)request->u.ata.lba);
printf("\n");
@@ -431,29 +475,29 @@ ata_timeout(struct ata_request *request)
}
/*
- * if we are waiting for a command to complete set ATA_TIMEOUT so
- * we wont loose the race with an eventual interrupt arriving late
+ * grap and hold the state lock so we wont loose the race with
+ * an eventual interrupt arriving late
*/
- if (ch->state == ATA_ACTIVE) {
+ if (ch->state == ATA_ACTIVE || ch->state == ATA_STALL_QUEUE) {
request->flags |= ATA_R_TIMEOUT;
- ch->state = ATA_TIMEOUT;
- ch->running = NULL;
if (!(request->flags & ATA_R_QUIET) && request->retries > 0) {
- ata_prtdev(request->device,
- "TIMEOUT - %s retrying (%d retr%s left)",
- ata_cmd2str(request), request->retries,
- request->retries == 1 ? "y" : "ies");
+ device_printf(request->dev,
+ "TIMEOUT - %s retrying (%d retr%s left)",
+ ata_cmd2str(request), request->retries,
+ request->retries == 1 ? "y" : "ies");
if (!(request->flags & (ATA_R_ATAPI | ATA_R_CONTROL)))
printf(" LBA=%llu", (unsigned long long)request->u.ata.lba);
printf("\n");
}
ch->hw.end_transaction(request);
+ ch->state |= ATA_TIMEOUT;
mtx_unlock(&ch->state_mtx);
+ ATA_LOCKING(device_get_parent(ch->dev), ch->dev, ATA_LF_UNLOCK);
ata_finish(request);
}
else {
mtx_unlock(&ch->state_mtx);
- ata_prtdev(request->device, "timeout state=%d unexpected\n", ch->state);
+ device_printf(request->dev, "timeout state=%d unexpected\n", ch->state);
}
}
@@ -468,33 +512,32 @@ ata_catch_inflight(struct ata_channel *ch)
mtx_unlock(&ch->state_mtx);
if (request) {
- callout_drain(&request->callout);
- ata_prtdev(request->device,
- "WARNING - %s requeued due to channel reset",
- ata_cmd2str(request));
- if (!(request->flags & (ATA_R_ATAPI | ATA_R_CONTROL)))
- printf(" LBA=%llu", (unsigned long long)request->u.ata.lba);
- printf("\n");
- request->flags |= ATA_R_REQUEUE;
- ata_queue_request(request);
+ callout_drain(&request->callout);
+ device_printf(request->dev,
+ "WARNING - %s requeued due to channel reset",
+ ata_cmd2str(request));
+ if (!(request->flags & (ATA_R_ATAPI | ATA_R_CONTROL)))
+ printf(" LBA=%llu", (unsigned long long)request->u.ata.lba);
+ printf("\n");
+ request->flags |= ATA_R_REQUEUE;
+ ata_queue_request(request);
}
}
void
-ata_fail_requests(struct ata_channel *ch, struct ata_device *device)
+ata_fail_requests(struct ata_channel *ch, device_t dev)
{
struct ata_request *request;
- /* fail all requests queued on this channel */
+ /* fail all requests queued on this channel for device dev if !NULL */
mtx_lock(&ch->queue_mtx);
while ((request = TAILQ_FIRST(&ch->ata_queue))) {
- if (!device || request->device == device) {
+ if (!dev || request->dev == dev) {
TAILQ_REMOVE(&ch->ata_queue, request, chain);
+ mtx_unlock(&ch->queue_mtx);
request->result = ENXIO;
- if (request->callback)
- (request->callback)(request);
- else
- sema_post(&request->done);
+ ata_finish(request);
+ mtx_lock(&ch->queue_mtx);
}
}
mtx_unlock(&ch->queue_mtx);
@@ -505,14 +548,86 @@ ata_fail_requests(struct ata_channel *ch, struct ata_device *device)
mtx_unlock(&ch->state_mtx);
/* if we have a request "in flight" fail it as well */
- if (request && (!device || request->device == device)) {
+ if (request && (!dev || request->dev == dev)) {
callout_drain(&request->callout);
request->result = ENXIO;
- if (request->callback)
- (request->callback)(request);
- else
- sema_post(&request->done);
+ ata_finish(request);
+ }
+}
+
+static u_int64_t
+ata_get_lba(struct ata_request *request)
+{
+ if (request->flags & ATA_R_ATAPI) {
+ switch (request->u.atapi.ccb[0]) {
+ case ATAPI_READ_BIG:
+ case ATAPI_WRITE_BIG:
+ case ATAPI_READ_CD:
+ return (request->u.atapi.ccb[5]) | (request->u.atapi.ccb[4]<<8) |
+ (request->u.atapi.ccb[3]<<16)|(request->u.atapi.ccb[2]<<24);
+ case ATAPI_READ:
+ case ATAPI_WRITE:
+ return (request->u.atapi.ccb[4]) | (request->u.atapi.ccb[3]<<8) |
+ (request->u.atapi.ccb[2]<<16);
+ default:
+ return 0;
+ }
}
+ else
+ return request->u.ata.lba;
+}
+
+static void
+ata_sort_queue(struct ata_channel *ch, struct ata_request *request)
+{
+ struct ata_request *this, *next;
+
+ this = TAILQ_FIRST(&ch->ata_queue);
+
+ /* if the queue is empty just insert */
+ if (!this) {
+ if (request->composite)
+ ch->freezepoint = request;
+ TAILQ_INSERT_TAIL(&ch->ata_queue, request, chain);
+ return;
+ }
+
+ /* dont sort frozen parts of the queue */
+ if (ch->freezepoint)
+ this = ch->freezepoint;
+
+ /* if position is less than head we add after tipping point */
+ if (ata_get_lba(request) < ata_get_lba(this)) {
+ while ((next = TAILQ_NEXT(this, chain))) {
+
+ /* have we reached the tipping point */
+ if (ata_get_lba(next) < ata_get_lba(this)) {
+
+ /* sort the insert */
+ do {
+ if (ata_get_lba(request) < ata_get_lba(next))
+ break;
+ this = next;
+ } while ((next = TAILQ_NEXT(this, chain)));
+ break;
+ }
+ this = next;
+ }
+ }
+
+ /* we are after head so sort the insert before tipping point */
+ else {
+ while ((next = TAILQ_NEXT(this, chain))) {
+ if (ata_get_lba(next) < ata_get_lba(this) ||
+ ata_get_lba(request) < ata_get_lba(next))
+ break;
+ this = next;
+ }
+ }
+
+ if (request->composite)
+ ch->freezepoint = request;
+ TAILQ_INSERT_AFTER(&ch->ata_queue, this, request, chain);
}
char *
@@ -579,7 +694,7 @@ ata_cmd2str(struct ata_request *request)
else {
switch (request->u.ata.command) {
case 0x00: return ("NOP");
- case 0x08: return ("ATAPI_RESET");
+ case 0x08: return ("DEVICE_RESET");
case 0x20: return ("READ");
case 0x24: return ("READ48");
case 0x25: return ("READ_DMA48");
@@ -590,6 +705,7 @@ ata_cmd2str(struct ata_request *request)
case 0x35: return ("WRITE_DMA48");
case 0x36: return ("WRITE_DMA_QUEUED48");
case 0x39: return ("WRITE_MUL48");
+ case 0x70: return ("SEEK");
case 0xa0: return ("PACKET_CMD");
case 0xa1: return ("ATAPI_IDENTIFY");
case 0xa2: return ("SERVICE");
@@ -612,7 +728,7 @@ ata_cmd2str(struct ata_request *request)
case 0xaa: return ("SETFEATURES ENABLE RCACHE");
case 0x55: return ("SETFEATURES DISABLE RCACHE");
}
- sprintf(buffer, "SETFEATURES 0x%02x", request->u.ata.feature);
+ sprintf(buffer, "SETFEATURES 0x%02x", request->u.ata.feature);
return buffer;
}
}
diff --git a/sys/dev/ata/ata-raid.c b/sys/dev/ata/ata-raid.c
index 4edaa79..ab9d902 100644
--- a/sys/dev/ata/ata-raid.c
+++ b/sys/dev/ata/ata-raid.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2000 - 2004 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 2000 - 2005 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,274 +34,781 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/ata.h>
#include <sys/kernel.h>
-#include <sys/proc.h>
#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/endian.h>
#include <sys/bio.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/disk.h>
#include <sys/cons.h>
-#include <sys/unistd.h>
-#include <sys/kthread.h>
#include <sys/sema.h>
#include <sys/taskqueue.h>
#include <vm/uma.h>
#include <machine/bus.h>
#include <sys/rman.h>
-#include <geom/geom_disk.h>
#include <dev/pci/pcivar.h>
-#include <dev/pci/pcireg.h>
+#include <geom/geom_disk.h>
#include <dev/ata/ata-all.h>
-#include <dev/ata/ata-pci.h>
#include <dev/ata/ata-disk.h>
#include <dev/ata/ata-raid.h>
+#include <dev/ata/ata-pci.h>
+#include <ata_if.h>
+
+/* prototypes */
+static void ata_raid_done(struct ata_request *request);
+static void ata_raid_config_changed(struct ar_softc *rdp, int writeback);
+static int ata_raid_status(int array, struct raid_status *status);
+static int ata_raid_create(struct raid_setup *setup);
+static int ata_raid_delete(int array);
+static int ata_raid_addspare(int array, int spare);
+static int ata_raid_rebuild(int array);
+static int ata_raid_read_metadata(device_t subdisk);
+static int ata_raid_write_metadata(struct ar_softc *rdp);
+static int ata_raid_adaptec_read_meta(device_t dev, struct ar_softc **raidp);
+static int ata_raid_hptv2_read_meta(device_t dev, struct ar_softc **raidp);
+static int ata_raid_hptv2_write_meta(struct ar_softc *rdp);
+static int ata_raid_hptv3_read_meta(device_t dev, struct ar_softc **raidp);
+//static int ata_raid_hptv3_write_meta(struct ar_softc *rdp);
+static int ata_raid_intel_read_meta(device_t dev, struct ar_softc **raidp);
+static int ata_raid_ite_read_meta(device_t dev, struct ar_softc **raidp);
+static int ata_raid_lsiv2_read_meta(device_t dev, struct ar_softc **raidp);
+static int ata_raid_lsiv3_read_meta(device_t dev, struct ar_softc **raidp);
+static int ata_raid_promise_read_meta(device_t dev, struct ar_softc **raidp, int native);
+static int ata_raid_promise_write_meta(struct ar_softc *rdp);
+static int ata_raid_sii_read_meta(device_t dev, struct ar_softc **raidp);
+static struct ata_request *ata_raid_init_request(struct ar_softc *rdp, struct bio *bio);
+static int ata_raid_send_request(struct ata_request *request);
+static int ata_raid_rw(device_t dev, u_int64_t lba, void *data, u_int bcount, int flags);
+static char * ata_raid_format(struct ar_softc *rdp);
+static char * ata_raid_type(struct ar_softc *rdp);
+static char * ata_raid_flags(struct ar_softc *rdp);
+
+/* debugging only */
+static void ata_raid_print_meta(struct ar_softc *meta);
+static void ata_raid_adaptec_print_meta(struct adaptec_raid_conf *meta);
+static void ata_raid_hptv2_print_meta(struct hptv2_raid_conf *meta);
+static void ata_raid_hptv3_print_meta(struct hptv3_raid_conf *meta);
+static void ata_raid_intel_print_meta(struct intel_raid_conf *meta);
+static void ata_raid_ite_print_meta(struct ite_raid_conf *meta);
+static void ata_raid_lsiv2_print_meta(struct lsiv2_raid_conf *meta);
+static void ata_raid_lsiv3_print_meta(struct lsiv3_raid_conf *meta);
+static void ata_raid_promise_print_meta(struct promise_raid_conf *meta);
+static void ata_raid_sii_print_meta(struct sii_raid_conf *meta);
+
+/* internal vars */
+static struct ar_softc *ata_raid_arrays[MAX_ARRAYS];
+static MALLOC_DEFINE(M_AR, "AR driver", "ATA PseudoRAID driver");
+static devclass_t ata_raid_sub_devclass;
+static int testing = 0;
/* device structures */
-static disk_strategy_t arstrategy;
-static dumper_t ardump;
+static disk_strategy_t ata_raid_strategy;
+//static dumper_t ata_raid_dump;
-/* prototypes */
-static void ar_attach_raid(struct ar_softc *, int);
-static void ar_done(struct bio *);
-static void ar_config_changed(struct ar_softc *, int);
-static void ar_rebuild(void *);
-static int ar_highpoint_read_conf(struct ad_softc *, struct ar_softc **);
-static int ar_highpoint_write_conf(struct ar_softc *);
-static int ar_lsi_read_conf(struct ad_softc *, struct ar_softc **);
-static int ar_lsi_write_conf(struct ar_softc *);
-static int ar_promise_read_conf(struct ad_softc *, struct ar_softc **, int);
-static int ar_promise_write_conf(struct ar_softc *);
-static int ar_rw(struct ad_softc *, u_int32_t, int, caddr_t, int);
-static struct ata_device *ar_locate_disk(int);
-static void ar_print_conf(struct ar_softc *);
-
-/* internal vars */
-static struct ar_softc **ar_table = NULL;
-static MALLOC_DEFINE(M_AR, "AR driver", "ATA RAID driver");
-
-#define AR_REBUILD_SIZE 128
-
-int
-ata_raiddisk_attach(struct ad_softc *adp)
+static void
+ata_raid_attach(struct ar_softc *rdp, int update)
{
- struct ar_softc *rdp;
- int array, disk;
+ int disk;
- 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].flags & AR_DF_ASSIGNED) &&
- 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);
- AD_SOFTC(rdp->disks[disk])->flags |= AD_F_RAID_SUBDISK;
- ar_config_changed(rdp, 1);
- return 1;
+ mtx_init(&rdp->lock, "ATA PseudoRAID metadata lock", NULL, MTX_DEF);
+ ata_raid_config_changed(rdp, update);
+
+ /* sanitize arrays total_size % (width * interleave) == 0 */
+ rdp->total_sectors = (rdp->total_sectors / (rdp->interleave * rdp->width)) *
+ (rdp->interleave * rdp->width);
+ rdp->disk = disk_alloc();
+ rdp->disk->d_strategy = ata_raid_strategy;
+ //rdp->disk->d_dump = ata_raid_dump;
+ rdp->disk->d_name = "ar";
+ rdp->disk->d_sectorsize = DEV_BSIZE;
+ rdp->disk->d_mediasize = (off_t)rdp->total_sectors * DEV_BSIZE;
+ rdp->disk->d_fwsectors = rdp->sectors;
+ rdp->disk->d_fwheads = rdp->heads;
+ rdp->disk->d_maxsize = 128 * DEV_BSIZE;
+ rdp->disk->d_drv1 = rdp;
+ rdp->disk->d_unit = rdp->lun;
+ disk_create(rdp->disk, DISK_VERSION);
+
+ printf("ar%d: %lluMB <%s %s array> status: %s\n", rdp->lun,
+ (unsigned long long)(rdp->total_sectors / ((1024L*1024L)/DEV_BSIZE)),
+ ata_raid_format(rdp), ata_raid_type(rdp), ata_raid_flags(rdp));
+
+ if (testing || bootverbose)
+ printf("ar%d: %llu sectors [%dC/%dH/%dS] <%s> subdisks defined as:\n",
+ rdp->lun, (unsigned long long)rdp->total_sectors,
+ rdp->cylinders, rdp->heads, rdp->sectors, rdp->name);
+
+ for (disk = 0; disk < rdp->total_disks; disk++) {
+ printf("ar%d: disk%d ", rdp->lun, disk);
+ if (rdp->disks[disk].dev) {
+ if (rdp->disks[disk].flags & AR_DF_PRESENT) {
+ /* status of this disk in the array */
+ if (rdp->disks[disk].flags & AR_DF_ONLINE)
+ printf("READY ");
+ else if (rdp->disks[disk].flags & AR_DF_SPARE)
+ printf("SPARE ");
+ else
+ printf("FREE ");
+
+ /* what type of disk is this in the array */
+ switch (rdp->type) {
+ case AR_T_RAID1:
+ case AR_T_RAID01:
+ if (disk < rdp->width)
+ printf("(master) ");
+ else
+ printf("(mirror) ");
}
+
+ /* which physical disk is used */
+ printf("using %s at ata%d-%s\n",
+ device_get_nameunit(rdp->disks[disk].dev),
+ device_get_unit(device_get_parent(rdp->disks[disk].dev)),
+ (((struct ata_device *)
+ device_get_softc(rdp->disks[disk].dev))->unit ==
+ ATA_MASTER) ? "master" : "slave");
}
+ else if (rdp->disks[disk].flags & AR_DF_ASSIGNED)
+ printf("DOWN\n");
+ else
+ printf("INVALID no RAID config on this subdisk\n");
}
+ else
+ printf("DOWN no device found for this subdisk\n");
}
+}
- 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 0;
+static int
+ata_raid_ioctl(struct ata_cmd *iocmd)
+{
+ int error = EOPNOTSUPP;
+
+ switch (iocmd->cmd) {
+ case ATARAIDSTATUS:
+ error = ata_raid_status(iocmd->channel, &iocmd->u.raid_status);
+ break;
+
+ case ATARAIDCREATE:
+ error = ata_raid_create(&iocmd->u.raid_setup);
+ break;
+
+ case ATARAIDDELETE:
+ error = ata_raid_delete(iocmd->channel);
+ break;
+
+ case ATARAIDADDSPARE:
+ error = ata_raid_addspare(iocmd->channel, iocmd->u.raid_spare.disk);
+ break;
+
+ case ATARAIDREBUILD:
+ error = ata_raid_rebuild(iocmd->channel);
+ break;
}
+ return error;
+}
- switch(pci_get_vendor(device_get_parent(adp->device->channel->dev))) {
- case ATA_PROMISE_ID:
- /* test RAID bit in PCI reg XXX */
- return (ar_promise_read_conf(adp, ar_table, 0));
+static void
+ata_raid_strategy(struct bio *bp)
+{
+ struct ar_softc *rdp = bp->bio_disk->d_drv1;
+ struct ata_request *request;
+ caddr_t data;
+ u_int64_t blkno, lba, blk = 0;
+ int count, chunk, drv, par = 0, change = 0;
- case ATA_HIGHPOINT_ID:
- return (ar_highpoint_read_conf(adp, ar_table));
+ if (!(rdp->status & AR_S_READY) ||
+ (bp->bio_cmd != BIO_READ && bp->bio_cmd != BIO_WRITE)) {
+ biofinish(bp, NULL, EIO);
+ return;
+ }
- case ATA_SILICON_IMAGE_ID:
- return (ar_lsi_read_conf(adp, ar_table));
+ bp->bio_resid = bp->bio_bcount;
+ for (count = howmany(bp->bio_bcount, DEV_BSIZE),
+ blkno = bp->bio_pblkno, data = bp->bio_data;
+ count > 0;
+ count -= chunk, blkno += chunk, data += (chunk * DEV_BSIZE)) {
- default:
- return (ar_promise_read_conf(adp, ar_table, 1));
- }
- return 0;
-}
+ switch (rdp->type) {
+ case AR_T_JBOD:
+ case AR_T_RAID1:
+ drv = 0;
+ lba = blkno;
+ chunk = count;
+ break;
+
+ case AR_T_SPAN:
+ drv = 0;
+ lba = blkno;
+ while (lba >= rdp->disks[drv].sectors)
+ lba -= rdp->disks[drv++].sectors;
+ chunk = min(rdp->disks[drv].sectors - lba, count);
+ break;
+
+ case AR_T_RAID0:
+ case AR_T_RAID01:
+ chunk = blkno % rdp->interleave;
+ drv = (blkno / rdp->interleave) % rdp->width;
+ lba = (((blkno/rdp->interleave)/rdp->width)*rdp->interleave)+chunk;
+ chunk = min(count, rdp->interleave - chunk);
+ break;
-int
-ata_raiddisk_detach(struct ad_softc *adp)
-{
- struct ar_softc *rdp;
- int array, disk;
+ case AR_T_RAID5:
+ drv = (blkno / rdp->interleave) % (rdp->width - 1);
+ par = rdp->width - 1 -
+ (blkno / (rdp->interleave * (rdp->width - 1))) % rdp->width;
+ if (drv >= par)
+ drv++;
+ lba = ((blkno/rdp->interleave)/(rdp->width-1))*(rdp->interleave) +
+ ((blkno%(rdp->interleave*(rdp->width-1)))%rdp->interleave);
+ chunk = min(count, rdp->interleave - (lba % rdp->interleave));
+ break;
+
+ default:
+ printf("ar%d: unknown array type in ata_raid_strategy\n", rdp->lun);
+ biofinish(bp, NULL, EIO);
+ return;
+ }
+
+ /* offset on all but "first on HPTv2" */
+ if (!(drv == 0 && rdp->format == AR_F_HPTV2_RAID))
+ lba += rdp->offset_sectors;
+
+ if (!(request = ata_raid_init_request(rdp, bp))) {
+ biofinish(bp, NULL, EIO);
+ return;
+ }
+ request->data = data;
+ request->bytecount = chunk * DEV_BSIZE;
+ request->u.ata.lba = lba;
+ request->u.ata.count = request->bytecount / DEV_BSIZE;
+
+ switch (rdp->type) {
+ case AR_T_JBOD:
+ case AR_T_SPAN:
+ case AR_T_RAID0:
+ if (((rdp->disks[drv].flags & (AR_DF_PRESENT|AR_DF_ONLINE)) ==
+ (AR_DF_PRESENT|AR_DF_ONLINE) && !rdp->disks[drv].dev)) {
+ rdp->disks[drv].flags &= ~AR_DF_ONLINE;
+ ata_raid_config_changed(rdp, 1);
+ ata_free_request(request);
+ biofinish(bp, NULL, EIO);
+ return;
+ }
+ request->this = drv;
+ request->dev = rdp->disks[request->this].dev;
+ ata_raid_send_request(request);
+ break;
+
+ case AR_T_RAID1:
+ case AR_T_RAID01:
+ if ((rdp->disks[drv].flags &
+ (AR_DF_PRESENT|AR_DF_ONLINE))==(AR_DF_PRESENT|AR_DF_ONLINE) &&
+ !rdp->disks[drv].dev) {
+ rdp->disks[drv].flags &= ~AR_DF_ONLINE;
+ change = 1;
+ }
+ if ((rdp->disks[drv + rdp->width].flags &
+ (AR_DF_PRESENT|AR_DF_ONLINE))==(AR_DF_PRESENT|AR_DF_ONLINE) &&
+ !rdp->disks[drv + rdp->width].dev) {
+ rdp->disks[drv + rdp->width].flags &= ~AR_DF_ONLINE;
+ change = 1;
+ }
+ if (change)
+ ata_raid_config_changed(rdp, 1);
+ if (!(rdp->status & AR_S_READY)) {
+ ata_free_request(request);
+ biofinish(bp, NULL, EIO);
+ return;
+ }
+
+ if (rdp->status & AR_S_REBUILDING)
+ blk = ((lba / rdp->interleave) * rdp->width) * rdp->interleave +
+ (rdp->interleave * (drv % rdp->width)) +
+ lba % rdp->interleave;;
- 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);
- AD_SOFTC(rdp->disks[disk])->flags &= ~AD_F_RAID_SUBDISK;
- rdp->disks[disk].device = NULL;
- ar_config_changed(rdp, 1);
- return 1;
+ if (bp->bio_cmd == BIO_READ) {
+ int src_online =
+ (rdp->disks[drv].flags & AR_DF_ONLINE);
+ int mir_online =
+ (rdp->disks[drv+rdp->width].flags & AR_DF_ONLINE);
+
+ /* if mirror gone or close to last access on source */
+ if (!mir_online ||
+ ((src_online) &&
+ bp->bio_pblkno >=
+ (rdp->disks[drv].last_lba - AR_PROXIMITY) &&
+ bp->bio_pblkno <=
+ (rdp->disks[drv].last_lba + AR_PROXIMITY))) {
+ rdp->toggle = 0;
+ }
+ /* if source gone or close to last access on mirror */
+ else if (!src_online ||
+ ((mir_online) &&
+ bp->bio_pblkno >=
+ (rdp->disks[drv+rdp->width].last_lba-AR_PROXIMITY) &&
+ bp->bio_pblkno <=
+ (rdp->disks[drv+rdp->width].last_lba+AR_PROXIMITY))) {
+ drv += rdp->width;
+ rdp->toggle = 1;
+ }
+ /* not close to any previous access, toggle */
+ else {
+ if (rdp->toggle)
+ rdp->toggle = 0;
+ else {
+ drv += rdp->width;
+ rdp->toggle = 1;
+ }
+ }
+
+ if ((rdp->status & AR_S_REBUILDING) &&
+ (blk <= rdp->rebuild_lba) &&
+ ((blk + chunk) > rdp->rebuild_lba)) {
+ struct ata_composite *composite;
+ struct ata_request *rebuild;
+ int this;
+
+ /* figure out what part to rebuild */
+ if (drv < rdp->width)
+ this = drv + rdp->width;
+ else
+ this = drv - rdp->width;
+
+ /* do we have a spare to rebuild on ? */
+ if (rdp->disks[this].flags & AR_DF_SPARE) {
+ if ((composite = malloc(sizeof(struct ata_composite),
+ M_AR, M_NOWAIT | M_ZERO))) {
+ if ((rebuild = ata_alloc_request())) {
+ rdp->rebuild_lba = blk + chunk;
+ bcopy(request, rebuild,
+ sizeof(struct ata_request));
+ rebuild->this = this;
+ rebuild->dev = rdp->disks[this].dev;
+ rebuild->flags &= ~ATA_R_READ;
+ rebuild->flags |= ATA_R_WRITE;
+ mtx_init(&composite->lock,
+ "ATA PseudoRAID rebuild lock",
+ NULL, MTX_DEF);
+ composite->rd_needed |= (1 << drv);
+ composite->wr_depend |= (1 << drv);
+ composite->wr_needed |= (1 << this);
+ composite->request[drv] = request;
+ composite->request[this] = rebuild;
+ request->composite = composite;
+ rebuild->composite = composite;
+ ata_raid_send_request(rebuild);
+ }
+ else {
+ free(composite, M_AR);
+ printf("DOH! ata_alloc_request failed!\n");
+ }
+ }
+ else
+ printf("DOH! composite malloc failed!\n");
+ }
+ else if (rdp->disks[this].flags & AR_DF_ONLINE) {
+ /*
+ * if we got here we are a chunk of a RAID01 that
+ * does not need a rebuild, but we need to increment
+ * the rebuild_lba address to get the rebuild to
+ * move to the next chunk correctly
+ */
+ rdp->rebuild_lba = blk + chunk;
+ }
+ else
+ printf("DOH! we didn't find the rebuild part\n");
+ }
+ }
+ if (bp->bio_cmd == BIO_WRITE) {
+ if ((rdp->disks[drv+rdp->width].flags & AR_DF_ONLINE) ||
+ ((rdp->status & AR_S_REBUILDING) &&
+ (rdp->disks[drv+rdp->width].flags & AR_DF_SPARE) &&
+ ((blk < rdp->rebuild_lba) ||
+ ((blk <= rdp->rebuild_lba) &&
+ ((blk + chunk) > rdp->rebuild_lba))))) {
+ if ((rdp->disks[drv].flags & AR_DF_ONLINE) ||
+ ((rdp->status & AR_S_REBUILDING) &&
+ (rdp->disks[drv].flags & AR_DF_SPARE) &&
+ ((blk < rdp->rebuild_lba) ||
+ ((blk <= rdp->rebuild_lba) &&
+ ((blk + chunk) > rdp->rebuild_lba))))) {
+ struct ata_request *mirror;
+ struct ata_composite *composite;
+ int this = drv + rdp->width;
+
+ if ((composite = malloc(sizeof(struct ata_composite),
+ M_AR, M_NOWAIT | M_ZERO)) &&
+ (mirror = ata_alloc_request())) {
+ rdp->rebuild_lba = blk + chunk;
+ bcopy(request, mirror, sizeof(struct ata_request));
+ mirror->this = this;
+ mirror->dev = rdp->disks[this].dev;
+ mtx_init(&composite->lock,
+ "ATA PseudoRAID mirror lock",
+ NULL, MTX_DEF);
+ composite->wr_needed |= (1 << drv);
+ composite->wr_needed |= (1 << this);
+ composite->request[drv] = request;
+ composite->request[this] = mirror;
+ request->composite = composite;
+ mirror->composite = composite;
+ ata_raid_send_request(mirror);
+ rdp->disks[this].last_lba = bp->bio_pblkno + chunk;
+ }
+ }
+ else
+ drv += rdp->width;
+ }
+ }
+ request->this = drv;
+ request->dev = rdp->disks[request->this].dev;
+ ata_raid_send_request(request);
+ rdp->disks[request->this].last_lba = bp->bio_pblkno + chunk;
+ break;
+
+ case AR_T_RAID5:
+ if (((rdp->disks[drv].flags & (AR_DF_PRESENT|AR_DF_ONLINE)) ==
+ (AR_DF_PRESENT|AR_DF_ONLINE) && !rdp->disks[drv].dev)) {
+ rdp->disks[drv].flags &= ~AR_DF_ONLINE;
+ change = 1;
+ }
+ if (((rdp->disks[par].flags & (AR_DF_PRESENT|AR_DF_ONLINE)) ==
+ (AR_DF_PRESENT|AR_DF_ONLINE) && !rdp->disks[par].dev)) {
+ rdp->disks[par].flags &= ~AR_DF_ONLINE;
+ change = 1;
+ }
+ if (change)
+ ata_raid_config_changed(rdp, 1);
+ if (!(rdp->status & AR_S_READY)) {
+ ata_free_request(request);
+ biofinish(bp, NULL, EIO);
+ return;
+ }
+ if (rdp->status & AR_S_DEGRADED) {
+ /* do the XOR game if possible */
+ }
+ else {
+ request->this = drv;
+ request->dev = rdp->disks[request->this].dev;
+ if (bp->bio_cmd == BIO_READ) {
+ ata_raid_send_request(request);
+ }
+ if (bp->bio_cmd == BIO_WRITE) {
+ ata_raid_send_request(request);
+ // sikre at læs-modify-skriv til hver disk er atomarisk.
+ // par kopi af request
+ // læse orgdata fra drv
+ // skriv nydata til drv
+ // læse parorgdata fra par
+ // skriv orgdata xor parorgdata xor nydata til par
}
}
+ break;
+
+ default:
+ printf("ar%d: unknown array type in ata_raid_strategy\n", rdp->lun);
}
}
- return 0;
}
-void
-ata_raid_attach()
+static void
+ata_raid_done(struct ata_request *request)
{
- struct ar_softc *rdp;
- int array;
+ struct ar_softc *rdp = request->driver;
+ struct ata_composite *composite = NULL;
+ struct bio *bp = request->bio;
+ int i, mirror, finished = 0;
+
+ switch (rdp->type) {
+ case AR_T_JBOD:
+ case AR_T_SPAN:
+ case AR_T_RAID0:
+ if (request->result) {
+ rdp->disks[request->this].flags &= ~AR_DF_ONLINE;
+ ata_raid_config_changed(rdp, 1);
+ bp->bio_error = request->result;
+ finished = 1;
+ }
+ else {
+ bp->bio_resid -= request->donecount;
+ if (bp->bio_resid == 0)
+ finished = 1;
+ }
+ break;
- if (!ar_table)
- return;
+ case AR_T_RAID1:
+ case AR_T_RAID01:
+ if (request->this < rdp->width)
+ mirror = request->this + rdp->width;
+ else
+ mirror = request->this - rdp->width;
+ if (request->result) {
+ rdp->disks[request->this].flags &= ~AR_DF_ONLINE;
+ ata_raid_config_changed(rdp, 1);
+ }
+ if (rdp->status & AR_S_READY) {
+ u_int64_t blk = 0;
- for (array = 0; array < MAX_ARRAYS; array++) {
- if (!(rdp = ar_table[array]) || !rdp->flags)
- continue;
- if (bootverbose)
- ar_print_conf(rdp);
- ar_attach_raid(rdp, 0);
+ if (rdp->status & AR_S_REBUILDING)
+ blk = ((request->u.ata.lba / rdp->interleave) * rdp->width) *
+ rdp->interleave + (rdp->interleave *
+ (request->this % rdp->width)) +
+ request->u.ata.lba % rdp->interleave;
+
+ if (bp->bio_cmd == BIO_READ) {
+
+ /* is this a rebuild composite */
+ if ((composite = request->composite)) {
+ mtx_lock(&composite->lock);
+
+ /* handle the read part of a rebuild composite */
+ if (request->flags & ATA_R_READ) {
+
+ /* if read failed array is now broken */
+ if (request->result) {
+ rdp->disks[request->this].flags &= ~AR_DF_ONLINE;
+ ata_raid_config_changed(rdp, 1);
+ bp->bio_error = request->result;
+ rdp->rebuild_lba = blk;
+ finished = 1;
+ }
+
+ /* good data, update how far we've gotten */
+ else {
+ bp->bio_resid -= request->donecount;
+ if (bp->bio_resid == 0) {
+ if (composite->wr_done & (1 << mirror))
+ finished = 1;
+ }
+ }
+ }
+
+ /* handle the write part of a rebuild composite */
+ else if (request->flags & ATA_R_WRITE) {
+ if (composite->rd_done & (1 << mirror)) {
+ if (request->result) {
+ printf("DOH! rebuild failed\n"); /* XXX SOS */
+ rdp->rebuild_lba = blk;
+ }
+ if (bp->bio_resid == 0)
+ finished = 1;
+ }
+ }
+ mtx_unlock(&composite->lock);
+ }
+
+ /* if read failed retry on the mirror */
+ else if (request->result) {
+ request->dev = rdp->disks[mirror].dev;
+ ata_raid_send_request(request);
+ return;
+ }
+
+ /* we have good data */
+ else {
+ bp->bio_resid -= request->donecount;
+ if (bp->bio_resid == 0)
+ finished = 1;
+ }
+ }
+ else if (bp->bio_cmd == BIO_WRITE) {
+ /* do we have a mirror or rebuild to deal with ? */
+ if ((composite = request->composite)) {
+ mtx_lock(&composite->lock);
+ if (composite->wr_done & (1 << mirror)) {
+ if (request->result) {
+ if (composite->request[mirror]->result) {
+ printf("DOH! all disks failed and got here\n");
+ bp->bio_error = EIO;
+ }
+ if (rdp->status & AR_S_REBUILDING) {
+ rdp->rebuild_lba = blk;
+ printf("DOH! rebuild failed\n"); /* XXX SOS */
+ }
+ bp->bio_resid -=
+ composite->request[mirror]->donecount;
+ }
+ else
+ bp->bio_resid -= request->donecount;
+ if (bp->bio_resid == 0)
+ finished = 1;
+ }
+ mtx_unlock(&composite->lock);
+ }
+ /* no mirror we are done */
+ else {
+ bp->bio_resid -= request->donecount;
+ if (bp->bio_resid == 0)
+ finished = 1;
+ }
+ }
+ }
+ else
+ biofinish(bp, NULL, request->result);
+ break;
+
+ case AR_T_RAID5:
+ if (request->result) {
+ rdp->disks[request->this].flags &= ~AR_DF_ONLINE;
+ ata_raid_config_changed(rdp, 1);
+ if (rdp->status & AR_S_READY) {
+ if (bp->bio_cmd == BIO_READ) {
+ /* do the XOR game to recover data */
+ }
+ if (bp->bio_cmd == BIO_WRITE) {
+ /* if the parity failed we're OK sortof */
+ /* otherwise wee need to do the XOR long dance */
+ }
+ finished = 1;
+ }
+ else
+ biofinish(bp, NULL, request->result);
+ }
+ else {
+ // did we have an XOR game going ??
+ bp->bio_resid -= request->donecount;
+ if (bp->bio_resid == 0)
+ finished = 1;
+ }
+ break;
+
+ default:
+ printf("ar%d: unknown array type in ata_raid_done\n", rdp->lun);
+ }
+
+ if (finished)
+ biodone(bp);
+
+ if (composite) {
+ if (finished) {
+ /* we are done with this composite, free all resources */
+ for (i = 0; i < 32; i++) {
+ if (composite->rd_needed & (1 << i) ||
+ composite->wr_needed & (1 << i)) {
+ ata_free_request(composite->request[i]);
+ }
+ }
+ mtx_destroy(&composite->lock);
+ free(composite, M_AR);
+ }
}
+ else
+ ata_free_request(request);
}
static void
-ar_attach_raid(struct ar_softc *rdp, int update)
+ata_raid_config_changed(struct ar_softc *rdp, int writeback)
{
- int disk;
+ int disk, count, status;
- ar_config_changed(rdp, update);
- rdp->disk = disk_alloc();
- rdp->disk->d_strategy = arstrategy;
- rdp->disk->d_dump = ardump;
- rdp->disk->d_name = "ar";
- rdp->disk->d_sectorsize = DEV_BSIZE;
- rdp->disk->d_mediasize = (off_t)rdp->total_sectors * DEV_BSIZE;
- rdp->disk->d_fwsectors = rdp->sectors;
- rdp->disk->d_fwheads = rdp->heads;
- rdp->disk->d_maxsize = 128 * DEV_BSIZE;
- rdp->disk->d_drv1 = rdp;
- rdp->disk->d_unit = rdp->lun;
- rdp->disk->d_flags = DISKFLAG_NEEDSGIANT;
- disk_create(rdp->disk, DISK_VERSION);
+ mtx_lock(&rdp->lock);
+ /* set default all working mode */
+ status = rdp->status;
+ rdp->status &= ~AR_S_DEGRADED;
+ rdp->status |= AR_S_READY;
- printf("ar%d: %lluMB <ATA ", 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:
- printf("RAID1 "); break;
- case AR_F_SPAN:
- printf("SPAN "); break;
- case (AR_F_RAID0 | AR_F_RAID1):
- printf("RAID0+1 "); break;
- default:
- printf("unknown 0x%x> ", rdp->flags);
- return;
+ /* make sure all lost drives are accounted for */
+ for (disk = 0; disk < rdp->total_disks; disk++) {
+ if (!(rdp->disks[disk].flags & AR_DF_PRESENT))
+ rdp->disks[disk].flags &= ~AR_DF_ONLINE;
}
- printf("array> [%d/%d/%d] status: ",
- rdp->cylinders, rdp->heads, rdp->sectors);
- switch (rdp->flags & (AR_F_DEGRADED | AR_F_READY)) {
- case AR_F_READY:
- printf("READY");
+
+ /* depending on RAID type figure out our health status */
+ switch (rdp->type) {
+ case AR_T_JBOD:
+ case AR_T_SPAN:
+ case AR_T_RAID0:
+ for (disk = 0; disk < rdp->total_disks; disk++)
+ if (!(rdp->disks[disk].flags & AR_DF_ONLINE))
+ rdp->status &= ~AR_S_READY;
break;
- case (AR_F_DEGRADED | AR_F_READY):
- printf("DEGRADED");
+
+ case AR_T_RAID1:
+ case AR_T_RAID01:
+ 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->status &= ~AR_S_READY;
+ }
+ 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->status |= AR_S_DEGRADED;
+ }
+ }
break;
- default:
- printf("BROKEN");
+
+ case AR_T_RAID5:
+ for (count = 0, disk = 0; disk < rdp->total_disks; disk++) {
+ if (!(rdp->disks[disk].flags & AR_DF_ONLINE))
+ count++;
+ }
+ if (count) {
+ if (count > 1)
+ rdp->status &= ~AR_S_READY;
+ else
+ rdp->status |= AR_S_DEGRADED;
+ }
break;
+ default:
+ rdp->status &= ~AR_S_READY;
}
- printf(" subdisks:\n");
- for (disk = 0; disk < rdp->total_disks; disk++) {
- if (rdp->disks[disk].device &&
- AD_SOFTC(rdp->disks[disk])->flags & AD_F_RAID_SUBDISK) {
- if (rdp->disks[disk].flags & AR_DF_PRESENT) {
- if (rdp->disks[disk].flags & AR_DF_ONLINE)
- printf(" disk%d READY ", disk);
- else if (rdp->disks[disk].flags & AR_DF_SPARE)
- printf(" disk%d SPARE ", disk);
- else
- printf(" disk%d FREE ", disk);
- printf("on %s at ata%d-%s\n", rdp->disks[disk].device->name,
- device_get_unit(rdp->disks[disk].device->channel->dev),
- (rdp->disks[disk].device->unit == ATA_MASTER) ?
- "master" : "slave");
- }
- else if (rdp->disks[disk].flags & AR_DF_ASSIGNED)
- printf(" disk%d DOWN\n", disk);
+
+ if (rdp->status != status) {
+ if (!(rdp->status & AR_S_READY)) {
+ printf("ar%d: FAILURE - %s array broken\n",
+ rdp->lun, ata_raid_type(rdp));
+ }
+ else if (rdp->status & AR_S_DEGRADED) {
+ if (rdp->type & (AR_T_RAID1 | AR_T_RAID01))
+ printf("ar%d: WARNING - mirror", rdp->lun);
else
- printf(" disk%d INVALID no RAID config on this disk\n", disk);
+ printf("ar%d: WARNING - parity", rdp->lun);
+ printf(" protection lost. %s array in DEGRADED mode\n",
+ ata_raid_type(rdp));
}
- else
- printf(" disk%d DOWN no device found for this disk\n", disk);
}
+ mtx_unlock(&rdp->lock);
+ if (writeback)
+ ata_raid_write_metadata(rdp);
+
}
-int
-ata_raid_addspare(int array, int disk)
+static int
+ata_raid_status(int array, struct raid_status *status)
{
struct ar_softc *rdp;
- struct ata_device *atadev;
int i;
-
- if (!ar_table || !(rdp = ar_table[array]))
- return ENXIO;
- if (!(rdp->flags & AR_F_RAID1))
- return EPERM;
- if (rdp->flags & AR_F_REBUILDING)
- return EBUSY;
- if (!(rdp->flags & AR_F_DEGRADED) || !(rdp->flags & AR_F_READY))
+
+ if (!(rdp = ata_raid_arrays[array]))
return ENXIO;
-
+
+ status->type = rdp->type;
+ status->total_disks = rdp->total_disks;
for (i = 0; i < rdp->total_disks; i++ ) {
- if (((rdp->disks[i].flags & (AR_DF_PRESENT | AR_DF_ONLINE)) ==
- (AR_DF_PRESENT | AR_DF_ONLINE)) && rdp->disks[i].device)
- continue;
- if ((atadev = ar_locate_disk(disk))) {
- if (((struct ad_softc*)(atadev->softc))->flags & AD_F_RAID_SUBDISK)
- return EBUSY;
- rdp->disks[i].device = atadev;
- rdp->disks[i].flags |= (AR_DF_PRESENT|AR_DF_ASSIGNED|AR_DF_SPARE);
- AD_SOFTC(rdp->disks[i])->flags |= AD_F_RAID_SUBDISK;
- ata_prtdev(rdp->disks[i].device,
- "inserted into ar%d disk%d as spare\n", array, i);
- ar_config_changed(rdp, 1);
- return 0;
- }
+ if ((rdp->disks[i].flags & AR_DF_PRESENT) && rdp->disks[i].dev)
+ status->disks[i] = device_get_unit(rdp->disks[i].dev);
+ else
+ status->disks[i] = -1;
}
- return ENXIO;
+ status->interleave = rdp->interleave;
+ status->status = rdp->status;
+ status->progress = 100 * rdp->rebuild_lba / rdp->total_sectors;
+ return 0;
}
-int
+static int
ata_raid_create(struct raid_setup *setup)
{
- struct ata_device *atadev;
struct ar_softc *rdp;
+ device_t subdisk;
int array, disk;
int ctlr = 0, disk_size = 0, total_disks = 0;
- if (!ar_table)
- ar_table = malloc(sizeof(struct ar_soft *) * MAX_ARRAYS,
- M_AR, M_NOWAIT | M_ZERO);
- if (!ar_table) {
- printf("ar: no memory for ATA raid array\n");
- return 0;
- }
for (array = 0; array < MAX_ARRAYS; array++) {
- if (!ar_table[array])
+ if (!ata_raid_arrays[array])
break;
}
if (array >= MAX_ARRAYS)
@@ -309,60 +816,80 @@ ata_raid_create(struct raid_setup *setup)
if (!(rdp = (struct ar_softc*)malloc(sizeof(struct ar_softc), M_AR,
M_NOWAIT | M_ZERO))) {
- printf("ar%d: failed to allocate raid config storage\n", array);
+ printf("ar%d: no memory for metadata storage\n", array);
return ENOMEM;
}
for (disk = 0; disk < setup->total_disks; disk++) {
- if ((atadev = ar_locate_disk(setup->disks[disk]))) {
- rdp->disks[disk].device = atadev;
- if (AD_SOFTC(rdp->disks[disk])->flags & AD_F_RAID_SUBDISK) {
+ if ((subdisk = devclass_get_device(ata_raid_sub_devclass,
+ setup->disks[disk]))) {
+ struct ata_raid_subdisk *ars = device_get_softc(subdisk);
+
+ /* is device already assigned to another array ? */
+ if (ars->raid) {
setup->disks[disk] = -1;
free(rdp, M_AR);
return EBUSY;
}
+ rdp->disks[disk].dev = device_get_parent(subdisk);
- switch(pci_get_vendor(device_get_parent(
- rdp->disks[disk].device->channel->dev))) {
+ switch (pci_get_vendor(GRANDPARENT(rdp->disks[disk].dev))) {
case ATA_HIGHPOINT_ID:
- ctlr |= AR_F_HIGHPOINT_RAID;
- rdp->disks[disk].disk_sectors =
- AD_SOFTC(rdp->disks[disk])->total_secs;
+ /*
+ * we need some way to decide if it should be v2 or v3
+ * for now just use v2 since the v3 BIOS knows how to
+ * handle that as well.
+ */
+ ctlr = AR_F_HPTV2_RAID;
+ rdp->disks[disk].sectors = HPTV3_LBA(rdp->disks[disk].dev);
break;
- case ATA_SILICON_IMAGE_ID:
- ctlr |= AR_F_LSI_RAID;
- rdp->disks[disk].disk_sectors =
- AD_SOFTC(rdp->disks[disk])->total_secs - 4208; /* SOS */
+ case ATA_ITE_ID:
+ ctlr = AR_F_ITE_RAID;
+ rdp->disks[disk].sectors = ITE_LBA(rdp->disks[disk].dev);
break;
- default:
- ctlr |= AR_F_FREEBSD_RAID;
- /* FALLTHROUGH */
+ case 0: /* XXX SOS cover up for bug in our PCI code */
+ case ATA_PROMISE_ID:
+ ctlr = AR_F_PROMISE_RAID;
+ rdp->disks[disk].sectors = PR_LBA(rdp->disks[disk].dev);
+ break;
- case ATA_PROMISE_ID:
- ctlr |= AR_F_PROMISE_RAID;
- rdp->disks[disk].disk_sectors =
- PR_LBA(AD_SOFTC(rdp->disks[disk]));
+ default:
+ /* XXX SOS
+ * right, so here we are, we have an ATA chip and we want
+ * to create a RAID and store the metadata.
+ * we need to find a way to tell what kind of metadata this
+ * hardware's BIOS might be using (good ideas are welcomed)
+ * for now we just use our own native FreeBSD format.
+ * the only way to get support for the BIOS format is to
+ * setup the RAID from there, in that case we pickup the
+ * metadata format from the disks (if we support it).
+ */
+ printf("WARNING!! - using FreeBSD PsuedoRAID metadata "
+ "since BIOS format is unknown on this hardware.\n"
+ "If that is not what you want, use the BIOS to "
+ "create the array\n");
+ ctlr = AR_F_FREEBSD_RAID;
+ rdp->disks[disk].sectors = PR_LBA(rdp->disks[disk].dev);
break;
}
- if ((rdp->flags &
- (AR_F_PROMISE_RAID | AR_F_LSI_RAID | AR_F_HIGHPOINT_RAID)) &&
- (rdp->flags &
- (AR_F_PROMISE_RAID | AR_F_LSI_RAID | AR_F_HIGHPOINT_RAID)) !=
- (ctlr &
- (AR_F_PROMISE_RAID | AR_F_LSI_RAID | AR_F_HIGHPOINT_RAID))) {
+ /* we need all disks to be of the same format */
+ if ((rdp->format & AR_F_FORMAT_MASK) &&
+ (rdp->format & AR_F_FORMAT_MASK) != (ctlr & AR_F_FORMAT_MASK)) {
free(rdp, M_AR);
return EXDEV;
}
else
- rdp->flags |= ctlr;
+ rdp->format = ctlr;
+ /* use the smallest disk of the lots size */
+ /* gigabyte boundry ??? XXX SOS */
if (disk_size)
- disk_size = min(rdp->disks[disk].disk_sectors, disk_size);
+ disk_size = min(rdp->disks[disk].sectors, disk_size);
else
- disk_size = rdp->disks[disk].disk_sectors;
+ disk_size = rdp->disks[disk].sectors;
rdp->disks[disk].flags =
(AR_DF_PRESENT | AR_DF_ASSIGNED | AR_DF_ONLINE);
@@ -374,1577 +901,2705 @@ ata_raid_create(struct raid_setup *setup)
return ENXIO;
}
}
- if (!total_disks) {
+
+ if (total_disks != setup->total_disks) {
free(rdp, M_AR);
return ENODEV;
}
switch (setup->type) {
- case 1:
- rdp->flags |= AR_F_RAID0;
+ case AR_T_JBOD:
+ case AR_T_SPAN:
+ case AR_T_RAID0:
break;
- case 2:
- rdp->flags |= AR_F_RAID1;
+
+ case AR_T_RAID1:
if (total_disks != 2) {
free(rdp, M_AR);
return EPERM;
}
break;
- case 3:
- rdp->flags |= (AR_F_RAID0 | AR_F_RAID1);
+
+ case AR_T_RAID01:
if (total_disks % 2 != 0) {
free(rdp, M_AR);
return EPERM;
}
break;
- case 4:
- rdp->flags |= AR_F_SPAN;
- break;
- }
- for (disk = 0; disk < total_disks; disk++)
- AD_SOFTC(rdp->disks[disk])->flags |= AD_F_RAID_SUBDISK;
+ case AR_T_RAID5:
+ if (total_disks < 3) {
+ free(rdp, M_AR);
+ return EPERM;
+ }
+ break;
+ default:
+ free(rdp, M_AR);
+ return EOPNOTSUPP;
+ }
+ rdp->type = setup->type;
rdp->lun = array;
- if (rdp->flags & AR_F_RAID0) {
+ if (rdp->type == AR_T_RAID0 || rdp->type == AR_T_RAID01 ||
+ rdp->type == AR_T_RAID5) {
int bit = 0;
while (setup->interleave >>= 1)
bit++;
- if (rdp->flags & AR_F_HIGHPOINT_RAID)
- rdp->interleave = min(max(32, 1 << bit), 128);
- if (rdp->flags & AR_F_LSI_RAID)
- rdp->interleave = min(max(2, 1 << bit), 4096);
- if (rdp->flags & AR_F_PROMISE_RAID)
- rdp->interleave = min(max(2, 1 << bit), 2048);
+ rdp->interleave = 1 << bit;
}
+ rdp->offset_sectors = 0;
+
+ /* values that depend on metadata format */
+ switch (rdp->format) {
+ case AR_F_ADAPTEC_RAID:
+ rdp->interleave = min(max(32, rdp->interleave), 128); /*+*/
+ break;
+
+ case AR_F_INTEL_RAID:
+ rdp->interleave = min(max(8, rdp->interleave), 256); /*+*/
+ break;
+
+ case AR_F_ITE_RAID:
+ rdp->interleave = min(max(2, rdp->interleave), 128); /*+*/
+ break;
+
+ case AR_F_SII_RAID:
+ rdp->interleave = min(max(8, rdp->interleave), 256); /*+*/
+ break;
+
+ case AR_F_HPTV2_RAID:
+ rdp->interleave = min(max(8, rdp->interleave), 128); /*+*/
+ rdp->offset_sectors = HPTV2_LBA(x) + 1;
+ break;
+
+ case AR_F_HPTV3_RAID:
+ rdp->interleave = min(max(32, rdp->interleave), 4096); /*+*/
+ break;
+
+ case AR_F_LSIV2_RAID:
+ rdp->interleave = min(max(2, rdp->interleave), 4096);
+ break;
+
+ case AR_F_LSIV3_RAID:
+ rdp->interleave = min(max(2, rdp->interleave), 256);
+ break;
+
+ case AR_F_PROMISE_RAID:
+ rdp->interleave = min(max(2, rdp->interleave), 2048); /*+*/
+ break;
+ }
+
rdp->total_disks = total_disks;
- rdp->width = total_disks / ((rdp->flags & AR_F_RAID1) ? 2 : 1);
- rdp->total_sectors = disk_size * rdp->width;
+ rdp->width = total_disks / (rdp->type & (AR_RAID1 | AR_T_RAID01) ? 2 : 1);
+ rdp->total_sectors = disk_size * (rdp->width - (rdp->type == AR_RAID5));
rdp->heads = 255;
rdp->sectors = 63;
rdp->cylinders = rdp->total_sectors / (255 * 63);
- if (rdp->flags & AR_F_PROMISE_RAID) {
- rdp->offset = 0;
- rdp->reserved = 63;
- }
- if (rdp->flags & AR_F_HIGHPOINT_RAID) {
- rdp->offset = HPT_LBA + 1;
- rdp->reserved = HPT_LBA + 1;
- }
- rdp->lock_start = rdp->lock_end = 0xffffffff;
- rdp->flags |= AR_F_READY;
+ rdp->rebuild_lba = 0;
+ rdp->status |= AR_S_READY;
- ar_table[array] = rdp;
-#if 0
- /* kick off rebuild here */
- if (setup->type == 2) {
- rdp->disks[1].flags &= ~AR_DF_ONLINE;
- rdp->disks[1].flags |= AR_DF_SPARE;
+ /* we are committed to this array, grap the subdisks */
+ for (disk = 0; disk < setup->total_disks; disk++) {
+ if ((subdisk = devclass_get_device(ata_raid_sub_devclass,
+ setup->disks[disk]))) {
+ struct ata_raid_subdisk *ars = device_get_softc(subdisk);
+
+ ars->raid = rdp;
+ ars->disk_number = disk;
+ }
}
-#endif
- ar_attach_raid(rdp, 1);
- ata_raid_rebuild(array);
+ ata_raid_attach(rdp, 1);
+ ata_raid_arrays[array] = rdp;
setup->unit = array;
return 0;
}
-int
+static int
ata_raid_delete(int array)
{
- struct ar_softc *rdp;
+ struct ar_softc *rdp;
+ device_t subdisk;
int disk;
- if (!ar_table) {
- printf("ar: no memory for ATA raid array\n");
- return 0;
- }
- if (!(rdp = ar_table[array]))
+ if (!(rdp = ata_raid_arrays[array]))
return ENXIO;
-
- rdp->flags &= ~AR_F_READY;
+
+ rdp->status &= ~AR_S_READY;
+ disk_destroy(rdp->disk);
+
for (disk = 0; disk < rdp->total_disks; disk++) {
- if ((rdp->disks[disk].flags&AR_DF_PRESENT) && rdp->disks[disk].device) {
- AD_SOFTC(rdp->disks[disk])->flags &= ~AD_F_RAID_SUBDISK;
-/* SOS
- ata_enclosure_leds(rdp->disks[disk].device, ATA_LED_GREEN);
- XXX */
+ if ((rdp->disks[disk].flags & AR_DF_PRESENT) && rdp->disks[disk].dev) {
+ if ((subdisk = devclass_get_device(ata_raid_sub_devclass,
+ device_get_unit(rdp->disks[disk].dev)))) {
+ struct ata_raid_subdisk *ars = device_get_softc(subdisk);
+
+ if (ars->raid != rdp) /* XXX SOS */
+ device_printf(subdisk, "DOH! this disk doesn't belong\n");
+ if (ars->disk_number != disk) /* XXX SOS */
+ device_printf(subdisk, "DOH! this disk number is wrong\n");
+ ars->raid = NULL;
+ ars->disk_number = -1;
+ }
rdp->disks[disk].flags = 0;
}
}
-
- if (rdp->flags & AR_F_HIGHPOINT_RAID)
- ar_highpoint_write_conf(rdp);
- if (rdp->flags & AR_F_LSI_RAID)
- ar_lsi_write_conf(rdp);
- if (rdp->flags & AR_F_PROMISE_RAID)
- ar_promise_write_conf(rdp);
-
- disk_destroy(rdp->disk);
+ ata_raid_write_metadata(rdp); /* wipe the metadata instead? XXX SOS */
+ ata_raid_arrays[array] = NULL;
free(rdp, M_AR);
- ar_table[array] = NULL;
return 0;
}
-int
-ata_raid_status(int array, struct raid_status *status)
+static int
+ata_raid_addspare(int array, int spare)
{
- struct ar_softc *rdp;
- int i;
+ struct ar_softc *rdp;
+ device_t subdisk;
+ int disk;
- if (!ar_table || !(rdp = ar_table[array]))
+ if (!(rdp = ata_raid_arrays[array]))
+ return ENXIO;
+ if (!(rdp->status & AR_S_DEGRADED) || !(rdp->status & AR_S_READY))
return ENXIO;
+ if (rdp->status & AR_S_REBUILDING)
+ return EBUSY;
+ switch (rdp->type) {
+ case AR_T_RAID1:
+ case AR_T_RAID01:
+ case AR_T_RAID5:
+ for (disk = 0; disk < rdp->total_disks; disk++ ) {
+
+ if (((rdp->disks[disk].flags & (AR_DF_PRESENT | AR_DF_ONLINE)) ==
+ (AR_DF_PRESENT | AR_DF_ONLINE)) && rdp->disks[disk].dev)
+ continue;
- switch (rdp->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) {
- case AR_F_RAID0:
- status->type = AR_RAID0;
- break;
- case AR_F_RAID1:
- status->type = AR_RAID1;
- break;
- case AR_F_RAID0 | AR_F_RAID1:
- status->type = AR_RAID0 | AR_RAID1;
- break;
- case AR_F_SPAN:
- status->type = AR_SPAN;
- break;
- }
- status->total_disks = rdp->total_disks;
- for (i = 0; i < rdp->total_disks; i++ ) {
- if ((rdp->disks[i].flags & AR_DF_PRESENT) && rdp->disks[i].device)
- status->disks[i] = AD_SOFTC(rdp->disks[i])->lun;
- else
- status->disks[i] = -1;
- }
- status->interleave = rdp->interleave;
- status->status = 0;
- if (rdp->flags & AR_F_READY)
- status->status |= AR_READY;
- if (rdp->flags & AR_F_DEGRADED)
- status->status |= AR_DEGRADED;
- if (rdp->flags & AR_F_REBUILDING) {
- status->status |= AR_REBUILDING;
- status->progress = 100*rdp->lock_start/(rdp->total_sectors/rdp->width);
+ if ((subdisk = devclass_get_device(ata_raid_sub_devclass, spare ))){
+ struct ata_raid_subdisk *ars = device_get_softc(subdisk);
+
+ if (ars->raid)
+ return EBUSY;
+
+ /* validate size etc etc XXX SOS */
+ ars->raid = rdp;
+ ars->disk_number = disk;
+ rdp->disks[disk].dev = device_get_parent(subdisk);
+ rdp->disks[disk].flags =
+ (AR_DF_PRESENT | AR_DF_ASSIGNED | AR_DF_SPARE);
+
+ device_printf(rdp->disks[disk].dev,
+ "inserted into ar%d disk%d as spare\n",
+ rdp->lun, disk);
+ ata_raid_config_changed(rdp, 1);
+ return 0;
+ }
+ }
+ return ENXIO;
+
+ default:
+ return EPERM;
}
- return 0;
}
-
-int
+
+static int
ata_raid_rebuild(int array)
{
- struct ar_softc *rdp;
+ struct ar_softc *rdp;
+ int disk, count;
- if (!ar_table || !(rdp = ar_table[array]))
+ if (!(rdp = ata_raid_arrays[array]))
return ENXIO;
- if (rdp->flags & AR_F_REBUILDING)
- return EBUSY;
- return kthread_create(ar_rebuild, rdp, &rdp->pid, RFNOWAIT, 0,
- "rebuilding ar%d", array);
-}
-
-static int
-ardump(void *arg, void *virtual, vm_offset_t physical,
- off_t offset, size_t length)
-{
- struct ar_softc *rdp;
- struct disk *dp, *ap;
- vm_offset_t pdata;
- caddr_t vdata;
- int blkno, count, chunk, error1, error2, lba, lbs, tmplba;
- int drv = 0;
-
- dp = arg;
- rdp = dp->d_drv1;
- if (!rdp || !(rdp->flags & AR_F_READY))
+ /* XXX SOS we should lock the rdp softc here */
+ if (!(rdp->status & AR_S_DEGRADED) || !(rdp->status & AR_S_READY))
return ENXIO;
-
- if (length == 0) {
- for (drv = 0; drv < rdp->total_disks; drv++) {
- if (rdp->disks[drv].flags & AR_DF_ONLINE) {
- ap = AD_SOFTC(rdp->disks[drv])->disk;
- (void) ap->d_dump(ap, NULL, 0, 0, 0);
+ if (rdp->status & AR_S_REBUILDING)
+ return EBUSY;
+
+ switch (rdp->type) {
+ case AR_T_RAID1:
+ case AR_T_RAID01:
+ case AR_T_RAID5:
+ for (count = 0, disk = 0; disk < rdp->total_disks; disk++ ) {
+ if (((rdp->disks[disk].flags &
+ (AR_DF_PRESENT|AR_DF_ASSIGNED|AR_DF_ONLINE|AR_DF_SPARE)) ==
+ (AR_DF_PRESENT | AR_DF_ASSIGNED | AR_DF_SPARE)) &&
+ rdp->disks[disk].dev) {
+ count++;
}
}
- return 0;
- }
-
- blkno = offset / DEV_BSIZE;
- vdata = virtual;
- pdata = physical;
-
- for (count = howmany(length, DEV_BSIZE); count > 0;
- count -= chunk, blkno += chunk, vdata += (chunk * DEV_BSIZE),
- pdata += (chunk * DEV_BSIZE)) {
- switch (rdp->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) {
- case AR_F_SPAN:
- 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:
- tmplba = blkno / rdp->interleave;
- chunk = blkno % rdp->interleave;
- if (blkno >= (rdp->total_sectors / (rdp->interleave * rdp->width)) *
- (rdp->interleave * rdp->width) ) {
- lbs = (rdp->total_sectors -
- ((rdp->total_sectors / (rdp->interleave * rdp->width)) *
- (rdp->interleave * rdp->width))) / rdp->width;
- drv = (blkno -
- ((rdp->total_sectors / (rdp->interleave * rdp->width)) *
- (rdp->interleave * rdp->width))) / lbs;
- lba = ((tmplba / rdp->width) * rdp->interleave) +
- (blkno - ((tmplba / rdp->width) * rdp->interleave)) % lbs;
- chunk = min(count, lbs);
- }
- else {
- drv = tmplba % rdp->width;
- lba = ((tmplba / rdp->width) * rdp->interleave) + chunk;
- chunk = min(count, rdp->interleave - chunk);
- }
- break;
-
- case AR_F_RAID1:
- drv = 0;
- lba = blkno;
- chunk = count;
- break;
-
- default:
- printf("ar%d: unknown array type in ardump\n", rdp->lun);
- return EIO;
- }
-
- if (drv > 0)
- lba += rdp->offset;
-
- switch (rdp->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) {
- case AR_F_SPAN:
- case AR_F_RAID0:
- if (rdp->disks[drv].flags & AR_DF_ONLINE) {
- ap = AD_SOFTC(rdp->disks[drv])->disk;
- error1 = ap->d_dump(ap, vdata, pdata,
- (off_t) lba * DEV_BSIZE,
- chunk * DEV_BSIZE);
- } else
- error1 = EIO;
- if (error1)
- return error1;
- break;
-
- case AR_F_RAID1:
- case AR_F_RAID0 | AR_F_RAID1:
- if ((rdp->disks[drv].flags & AR_DF_ONLINE) ||
- ((rdp->flags & AR_F_REBUILDING) &&
- (rdp->disks[drv].flags & AR_DF_SPARE))) {
- ap = AD_SOFTC(rdp->disks[drv])->disk;
- error1 = ap->d_dump(ap, vdata, pdata,
- (off_t) lba * DEV_BSIZE,
- chunk * DEV_BSIZE);
- } else
- error1 = EIO;
- if ((rdp->disks[drv + rdp->width].flags & AR_DF_ONLINE) ||
- ((rdp->flags & AR_F_REBUILDING) &&
- (rdp->disks[drv + rdp->width].flags & AR_DF_SPARE))) {
- ap = AD_SOFTC(rdp->disks[drv + rdp->width])->disk;
- error2 = ap->d_dump(ap, vdata, pdata,
- (off_t) lba * DEV_BSIZE,
- chunk * DEV_BSIZE);
- } else
- error2 = EIO;
- if (error1 && error2)
- return error1;
- break;
-
- default:
- printf("ar%d: unknown array type in ardump\n", rdp->lun);
- return EIO;
+ if (count) {
+ rdp->rebuild_lba = 0;
+ rdp->status |= AR_S_REBUILDING;
+ return 0;
}
+ return EIO;
+
+ default:
+ return EPERM;
}
- return 0;
}
-static void
-arstrategy(struct bio *bp)
+static int
+ata_raid_read_metadata(device_t subdisk)
{
- struct ar_softc *rdp = bp->bio_disk->d_drv1;
- int blkno, count, chunk, lba, lbs, tmplba;
- int drv = 0, change = 0;
- caddr_t data;
-
- if (!(rdp->flags & AR_F_READY)) {
- bp->bio_flags |= BIO_ERROR;
- bp->bio_error = EIO;
- biodone(bp);
- return;
- }
-
- bp->bio_resid = bp->bio_bcount;
- blkno = bp->bio_pblkno;
- data = bp->bio_data;
- for (count = howmany(bp->bio_bcount, DEV_BSIZE); count > 0;
- count -= chunk, blkno += chunk, data += (chunk * DEV_BSIZE)) {
- struct ar_buf *buf1, *buf2;
-
- switch (rdp->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) {
- case AR_F_SPAN:
- 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:
- tmplba = blkno / rdp->interleave;
- chunk = blkno % rdp->interleave;
- if (blkno >= (rdp->total_sectors / (rdp->interleave * rdp->width)) *
- (rdp->interleave * rdp->width) ) {
- lbs = (rdp->total_sectors -
- ((rdp->total_sectors / (rdp->interleave * rdp->width)) *
- (rdp->interleave * rdp->width))) / rdp->width;
- drv = (blkno -
- ((rdp->total_sectors / (rdp->interleave * rdp->width)) *
- (rdp->interleave * rdp->width))) / lbs;
- lba = ((tmplba / rdp->width) * rdp->interleave) +
- (blkno - ((tmplba / rdp->width) * rdp->interleave)) % lbs;
- chunk = min(count, lbs);
- }
- else {
- drv = tmplba % rdp->width;
- lba = ((tmplba / rdp->width) * rdp->interleave) + chunk;
- chunk = min(count, rdp->interleave - chunk);
- }
+ devclass_t pci_devclass = devclass_find("pci");
+ devclass_t devclass=device_get_devclass(GRANDPARENT(GRANDPARENT(subdisk)));
+
+ /* prioritize vendor native metadata layout if possible */
+ if (devclass == pci_devclass) {
+ switch (pci_get_vendor(GRANDPARENT(device_get_parent(subdisk)))) {
+ case ATA_HIGHPOINT_ID:
+ if (ata_raid_hptv3_read_meta(subdisk, ata_raid_arrays))
+ return 0;
+ if (ata_raid_hptv2_read_meta(subdisk, ata_raid_arrays))
+ return 0;
break;
- case AR_F_RAID1:
- drv = 0;
- lba = blkno;
- chunk = count;
+ case ATA_INTEL_ID:
+ if (ata_raid_intel_read_meta(subdisk, ata_raid_arrays))
+ return 0;
break;
- default:
- printf("ar%d: unknown array type in arstrategy\n", rdp->lun);
- bp->bio_flags |= BIO_ERROR;
- bp->bio_error = EIO;
- biodone(bp);
- return;
- }
-
- buf1 = malloc(sizeof(struct ar_buf), M_AR, M_NOWAIT | M_ZERO); /* XXX */
- buf1->bp.bio_pblkno = lba;
- if ((buf1->drive = drv) > 0)
- buf1->bp.bio_pblkno += rdp->offset;
- buf1->bp.bio_driver1 = (void *)rdp;
- buf1->bp.bio_bcount = chunk * DEV_BSIZE;
- buf1->bp.bio_data = data;
- buf1->bp.bio_cmd = bp->bio_cmd;
- buf1->bp.bio_flags = bp->bio_flags;
- buf1->bp.bio_done = ar_done;
- buf1->org = bp;
-
- switch (rdp->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) {
- case AR_F_SPAN:
- case AR_F_RAID0:
- if ((rdp->disks[buf1->drive].flags &
- (AR_DF_PRESENT|AR_DF_ONLINE))==(AR_DF_PRESENT|AR_DF_ONLINE) &&
- !rdp->disks[buf1->drive].device->softc) {
- rdp->disks[buf1->drive].flags &= ~AR_DF_ONLINE;
- ar_config_changed(rdp, 1);
- free(buf1, M_AR);
- bp->bio_flags |= BIO_ERROR;
- bp->bio_error = EIO;
- biodone(bp);
- return;
- }
- buf1->bp.bio_disk = AD_SOFTC(rdp->disks[buf1->drive])->disk;
- AR_STRATEGY((struct bio *)buf1);
+ case ATA_ITE_ID:
+ if (ata_raid_ite_read_meta(subdisk, ata_raid_arrays))
+ return 0;
break;
- case AR_F_RAID1:
- case AR_F_RAID0 | AR_F_RAID1:
- if (rdp->flags & AR_F_REBUILDING && bp->bio_cmd == BIO_WRITE) {
- 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)) {
- tsleep(rdp, PRIBIO, "arwait", 0);
- }
- }
- if ((rdp->disks[buf1->drive].flags &
- (AR_DF_PRESENT|AR_DF_ONLINE))==(AR_DF_PRESENT|AR_DF_ONLINE) &&
- !rdp->disks[buf1->drive].device->softc) {
- rdp->disks[buf1->drive].flags &= ~AR_DF_ONLINE;
- change = 1;
- }
- if ((rdp->disks[buf1->drive + rdp->width].flags &
- (AR_DF_PRESENT|AR_DF_ONLINE))==(AR_DF_PRESENT|AR_DF_ONLINE) &&
- !rdp->disks[buf1->drive + rdp->width].device->softc) {
- rdp->disks[buf1->drive + rdp->width].flags &= ~AR_DF_ONLINE;
- change = 1;
- }
- if (change)
- ar_config_changed(rdp, 1);
-
- if (!(rdp->flags & AR_F_READY)) {
- free(buf1, M_AR);
- bp->bio_flags |= BIO_ERROR;
- bp->bio_error = EIO;
- biodone(bp);
- return;
- }
- if (bp->bio_cmd == BIO_READ) {
- int src_online =
- (rdp->disks[buf1->drive].flags & AR_DF_ONLINE);
- int mir_online =
- (rdp->disks[buf1->drive+rdp->width].flags & AR_DF_ONLINE);
-
- /* if mirror gone or close to last access on source */
- if (!mir_online ||
- ((src_online) &&
- buf1->bp.bio_pblkno >=
- (rdp->disks[buf1->drive].last_lba - AR_PROXIMITY) &&
- buf1->bp.bio_pblkno <=
- (rdp->disks[buf1->drive].last_lba + AR_PROXIMITY))) {
- rdp->flags &= ~AR_F_TOGGLE;
- }
- /* if source gone or close to last access on mirror */
- else if (!src_online ||
- ((mir_online) &&
- buf1->bp.bio_pblkno >=
- (rdp->disks[buf1->drive + rdp->width].last_lba -
- AR_PROXIMITY) &&
- buf1->bp.bio_pblkno <=
- (rdp->disks[buf1->drive + rdp->width].last_lba +
- AR_PROXIMITY))) {
- buf1->drive = buf1->drive + rdp->width;
- rdp->flags |= AR_F_TOGGLE;
- }
- /* not close to any previous access, toggle */
- else {
- if (rdp->flags & AR_F_TOGGLE)
- rdp->flags &= ~AR_F_TOGGLE;
- else {
- buf1->drive = buf1->drive + rdp->width;
- rdp->flags |= AR_F_TOGGLE;
- }
- }
- }
- if (bp->bio_cmd == BIO_WRITE) {
- if ((rdp->disks[buf1->drive+rdp->width].flags & AR_DF_ONLINE) ||
- ((rdp->flags & AR_F_REBUILDING) &&
- (rdp->disks[buf1->drive+rdp->width].flags & AR_DF_SPARE) &&
- buf1->bp.bio_pblkno < rdp->lock_start)) {
- if ((rdp->disks[buf1->drive].flags & AR_DF_ONLINE) ||
- ((rdp->flags & AR_F_REBUILDING) &&
- (rdp->disks[buf1->drive].flags & AR_DF_SPARE) &&
- buf1->bp.bio_pblkno < rdp->lock_start)) {
- buf2 = malloc(sizeof(struct ar_buf), M_AR, M_NOWAIT); /* XXX */
- bcopy(buf1, buf2, sizeof(struct ar_buf));
- buf1->mirror = buf2;
- buf2->mirror = buf1;
- buf2->drive = buf1->drive + rdp->width;
- buf2->bp.bio_disk =
- AD_SOFTC(rdp->disks[buf2->drive])->disk;
- AR_STRATEGY((struct bio *)buf2);
- rdp->disks[buf2->drive].last_lba =
- buf2->bp.bio_pblkno + chunk;
- }
- else
- buf1->drive = buf1->drive + rdp->width;
- }
- }
- buf1->bp.bio_disk = AD_SOFTC(rdp->disks[buf1->drive])->disk;
- AR_STRATEGY((struct bio *)buf1);
- rdp->disks[buf1->drive].last_lba = buf1->bp.bio_pblkno + chunk;
+ case 0: /* XXX SOS cover up for bug in our PCI code */
+ case ATA_PROMISE_ID:
+ if (ata_raid_promise_read_meta(subdisk, ata_raid_arrays, 0))
+ return 0;
break;
- default:
- printf("ar%d: unknown array type in arstrategy\n", rdp->lun);
+ case ATA_SILICON_IMAGE_ID:
+ if (ata_raid_sii_read_meta(subdisk, ata_raid_arrays))
+ return 0;
+ break;
}
}
-}
+
+ /* handle controllers that have multiple layout possibilities */
+ /* NOTE: the order of these are not insignificant */
-static void
-ar_done(struct bio *bp)
-{
- struct ar_softc *rdp = (struct ar_softc *)bp->bio_driver1;
- struct ar_buf *buf = (struct ar_buf *)bp;
-
- switch (rdp->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) {
- case AR_F_SPAN:
- case AR_F_RAID0:
- if (buf->bp.bio_flags & BIO_ERROR) {
- rdp->disks[buf->drive].flags &= ~AR_DF_ONLINE;
- ar_config_changed(rdp, 1);
- buf->org->bio_flags |= BIO_ERROR;
- buf->org->bio_error = EIO;
- biodone(buf->org);
- }
- else {
- buf->org->bio_resid -= buf->bp.bio_bcount;
- if (buf->org->bio_resid == 0)
- biodone(buf->org);
- }
- break;
+ /* Adaptec HostRAID */
+ if (ata_raid_adaptec_read_meta(subdisk, ata_raid_arrays))
+ return 0;
- case AR_F_RAID1:
- case AR_F_RAID0 | AR_F_RAID1:
- if (buf->bp.bio_flags & BIO_ERROR) {
- rdp->disks[buf->drive].flags &= ~AR_DF_ONLINE;
- 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
- buf->drive = buf->drive - rdp->width;
- buf->bp.bio_disk = AD_SOFTC(rdp->disks[buf->drive])->disk;
- buf->bp.bio_flags = buf->org->bio_flags;
- buf->bp.bio_error = 0;
- AR_STRATEGY((struct bio *)buf);
- return;
- }
- 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 (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 -= buf->bp.bio_bcount;
- if (buf->org->bio_resid == 0)
- biodone(buf->org);
- }
- break;
-
- default:
- printf("ar%d: unknown array type in ar_done\n", rdp->lun);
- }
- free(buf, M_AR);
+ /* LSILogic v3 and v2 */
+ if (ata_raid_lsiv3_read_meta(subdisk, ata_raid_arrays))
+ return 0;
+ if (ata_raid_lsiv2_read_meta(subdisk, ata_raid_arrays))
+ return 0;
+
+ /* if none of the above matched, try FreeBSD native format */
+ return ata_raid_promise_read_meta(subdisk, ata_raid_arrays, 1);
}
-static void
-ar_config_changed(struct ar_softc *rdp, int writeback)
+static int
+ata_raid_write_metadata(struct ar_softc *rdp)
{
- int disk, flags;
+ switch (rdp->format) {
+ case AR_F_FREEBSD_RAID:
+ case AR_F_PROMISE_RAID:
+ return ata_raid_promise_write_meta(rdp);
+
+ case AR_F_HPTV3_RAID:
+ case AR_F_HPTV2_RAID:
+ /*
+ * always write HPT v2 metadata, the v3 BIOS knows it as well.
+ * this is handy since we cannot know what version BIOS is on there
+ */
+ return ata_raid_hptv2_write_meta(rdp);
+#if 0
+ case AR_F_HPTV3_RAID:
+ return ata_raid_hptv3_write_meta(rdp);
- flags = rdp->flags;
- rdp->flags |= AR_F_READY;
- rdp->flags &= ~AR_F_DEGRADED;
+ case AR_F_ADAPTEC_RAID:
+ return ata_raid_adaptec_write_meta(rdp);
- for (disk = 0; disk < rdp->total_disks; disk++)
- if (!(rdp->disks[disk].flags & AR_DF_PRESENT))
- rdp->disks[disk].flags &= ~AR_DF_ONLINE;
+ case ATA_INTEL_ID:
+ return ata_raid_intel_write_meta(rdp);
- 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 ATA_ITE_ID:
+ return ata_raid_ite_write_meta(rdp);
- 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) {
-/* SOS
- if (rdp->disks[disk].flags & AR_DF_ONLINE)
- ata_enclosure_leds(rdp->disks[disk].device, ATA_LED_GREEN);
- else
- ata_enclosure_leds(rdp->disks[disk].device, ATA_LED_RED);
- XXX */
- }
- }
- if (writeback) {
- if (rdp->flags & AR_F_HIGHPOINT_RAID)
- ar_highpoint_write_conf(rdp);
- if (rdp->flags & AR_F_LSI_RAID)
- ar_lsi_write_conf(rdp);
- if (rdp->flags & AR_F_PROMISE_RAID)
- ar_promise_write_conf(rdp);
+ case AR_F_LSIV2_RAID:
+ return ata_raid_lsiv2_write_meta(rdp);
+
+ case AR_F_LSIV3_RAID:
+ return ata_raid_lsiv3_write_meta(rdp);
+
+ case ATA_SILICON_IMAGE_ID:
+ return ata_raid_sii_write_meta(rdp);
+#endif
+ default:
+ printf("ar%d: writing of %s metadata is NOT supported yet\n",
+ rdp->lun, ata_raid_format(rdp));
}
+ return -1;
}
-static void
-ar_rebuild(void *arg)
+/* Adaptec HostRAID Metadata */
+static int
+ata_raid_adaptec_read_meta(device_t dev, struct ar_softc **raidp)
{
- struct ar_softc *rdp = arg;
- int disk, s, count = 0, error = 0;
- caddr_t buffer;
+ struct ata_raid_subdisk *ars = device_get_softc(dev);
+ device_t parent = device_get_parent(dev);
+ struct adaptec_raid_conf *meta;
+ struct ar_softc *raid;
+ int array, disk, retval = 0;
- mtx_lock(&Giant);
- if ((rdp->flags & (AR_F_READY|AR_F_DEGRADED)) != (AR_F_READY|AR_F_DEGRADED))
- kthread_exit(EEXIST);
+ if (!(meta = (struct adaptec_raid_conf *)
+ malloc(sizeof(struct adaptec_raid_conf), M_AR, M_NOWAIT | M_ZERO)))
+ return ENOMEM;
- 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");
-#if 0
- rdp->disks[disk].flags &= ~AR_DF_SPARE;
- AD_SOFTC(rdp->disks[disk])->flags &= ~AD_F_RAID_SUBDISK;
-#endif
- continue;
- }
-/* SOS
- ata_enclosure_leds(rdp->disks[disk].device, ATA_LED_ORANGE);
- XXX */
- count++;
- }
+ if (ata_raid_rw(parent, ADP_LBA(parent),
+ meta, sizeof(struct adaptec_raid_conf), ATA_R_READ)) {
+ if (testing || bootverbose)
+ device_printf(parent, "Adaptec read metadata failed\n");
+ goto adaptec_out;
}
- if (!count)
- kthread_exit(ENODEV);
- /* setup start conditions */
- s = splbio();
- rdp->lock_start = 0;
- rdp->lock_end = rdp->lock_start + AR_REBUILD_SIZE;
- rdp->flags |= AR_F_REBUILDING;
- splx(s);
- buffer = malloc(AR_REBUILD_SIZE * DEV_BSIZE, M_AR, M_NOWAIT | M_ZERO); /* XXX */
+ /* check if this is a Adaptec RAID struct */
+ if (meta->magic_0 != ADP_MAGIC_0 || meta->magic_3 != ADP_MAGIC_3) {
+ if (testing || bootverbose)
+ device_printf(parent, "Adaptec check1 failed\n");
+ goto adaptec_out;
+ }
- /* now go copy entire disk(s) */
- while (rdp->lock_end < (rdp->total_sectors / rdp->width)) {
- int size = min(AR_REBUILD_SIZE,
- (rdp->total_sectors / rdp->width) - rdp->lock_end);
+ if (testing || bootverbose)
+ ata_raid_adaptec_print_meta(meta);
- for (disk = 0; disk < rdp->width; disk++) {
- struct ad_softc *adp;
-
- 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;
+ /* now convert Adaptec metadata into our generic form */
+ for (array = 0; array < MAX_ARRAYS; array++) {
+ if (!raidp[array]) {
+ raidp[array] =
+ (struct ar_softc *)malloc(sizeof(struct ar_softc), M_AR,
+ M_NOWAIT | M_ZERO);
+ if (!raidp[array]) {
+ device_printf(parent, "failed to allocate metadata storage\n");
+ goto adaptec_out;
+ }
+ }
+ raid = raidp[array];
+ if (raid->format && (raid->format != AR_F_ADAPTEC_RAID))
+ continue;
- if (rdp->disks[disk].flags & AR_DF_ONLINE)
- adp = AD_SOFTC(rdp->disks[disk]);
- else
- adp = AD_SOFTC(rdp->disks[disk + rdp->width]);
- if ((error = ar_rw(adp, rdp->lock_start,
- size * DEV_BSIZE, buffer, AR_READ | AR_WAIT)))
- break;
+ if (raid->magic_0 && raid->magic_0 != meta->configs[0].magic_0)
+ continue;
- if (rdp->disks[disk].flags & AR_DF_ONLINE)
- adp = AD_SOFTC(rdp->disks[disk + rdp->width]);
- else
- adp = AD_SOFTC(rdp->disks[disk]);
- if ((error = ar_rw(adp, rdp->lock_start,
- size * DEV_BSIZE, buffer, AR_WRITE | AR_WAIT)))
+ if (!meta->generation || be32toh(meta->generation) > raid->generation) {
+ switch (meta->configs[0].type) {
+ case ADP_T_RAID0:
+ raid->magic_0 = meta->configs[0].magic_0;
+ raid->type = AR_T_RAID0;
+ raid->interleave = 1 << (meta->configs[0].stripe_shift >> 1);
+ raid->width = be16toh(meta->configs[0].total_disks);
+ break;
+
+ case ADP_T_RAID1:
+ raid->magic_0 = meta->configs[0].magic_0;
+ raid->type = AR_T_RAID1;
+ raid->width = be16toh(meta->configs[0].total_disks) / 2;
break;
+
+ default:
+ device_printf(parent, "Adaptec unknown RAID type 0x%02x\n",
+ meta->configs[0].type);
+ free(raidp[array], M_AR);
+ raidp[array] = NULL;
+ goto adaptec_out;
+ }
+
+ raid->format = AR_F_ADAPTEC_RAID;
+ raid->generation = be32toh(meta->generation);
+ raid->total_disks = be16toh(meta->configs[0].total_disks);
+ raid->total_sectors = be32toh(meta->configs[0].sectors);
+ raid->heads = 255;
+ raid->sectors = 63;
+ raid->cylinders = raid->total_sectors / (63 * 255);
+ raid->offset_sectors = 0;
+ raid->rebuild_lba = 0;
+ raid->lun = array;
+ strncpy(raid->name, meta->configs[0].name,
+ min(sizeof(raid->name), sizeof(meta->configs[0].name)));
+
+ /* clear out any old info */
+ if (raid->generation) {
+ for (disk = 0; disk < raid->total_disks; disk++) {
+ raid->disks[disk].dev = NULL;
+ raid->disks[disk].flags = 0;
+ }
+ }
}
- if (error) {
- wakeup(rdp);
- free(buffer, M_AR);
- kthread_exit(error);
- }
- s = splbio();
- rdp->lock_start = rdp->lock_end;
- rdp->lock_end = rdp->lock_start + size;
- splx(s);
- wakeup(rdp);
- sprintf(rdp->pid->p_comm, "rebuilding ar%d %lld%%", rdp->lun,
- (unsigned long long)(100 * rdp->lock_start /
- (rdp->total_sectors / rdp->width)));
- }
- 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);
- }
- }
- s = splbio();
- rdp->lock_start = 0xffffffff;
- rdp->lock_end = 0xffffffff;
- rdp->flags &= ~AR_F_REBUILDING;
- splx(s);
- ar_config_changed(rdp, 1);
- kthread_exit(0);
+ if (be32toh(meta->generation) >= raid->generation) {
+ struct ata_device *atadev = device_get_softc(parent);
+ struct ata_channel *ch = device_get_softc(GRANDPARENT(dev));
+ int disk_number = (ch->unit << !(ch->flags & ATA_NO_SLAVE)) +
+ (atadev->unit == ATA_MASTER ? 0 : 1);
+
+ raid->disks[disk_number].dev = parent;
+ raid->disks[disk_number].sectors =
+ be32toh(meta->configs[disk_number + 1].sectors);
+ raid->disks[disk_number].flags =
+ (AR_DF_ONLINE | AR_DF_PRESENT | AR_DF_ASSIGNED);
+ ars->raid = raid;
+ ars->disk_number = disk_number;
+ retval = 1;
+ }
+ break;
+ }
+
+adaptec_out:
+ free(meta, M_AR);
+ return retval;
}
+/* Highpoint V2 RocketRAID Metadata */
static int
-ar_highpoint_read_conf(struct ad_softc *adp, struct ar_softc **raidp)
+ata_raid_hptv2_read_meta(device_t dev, struct ar_softc **raidp)
{
- struct highpoint_raid_conf *info;
+ struct ata_raid_subdisk *ars = device_get_softc(dev);
+ device_t parent = device_get_parent(dev);
+ struct hptv2_raid_conf *meta;
struct ar_softc *raid = NULL;
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 retval;
+ if (!(meta = (struct hptv2_raid_conf *)
+ malloc(sizeof(struct hptv2_raid_conf), M_AR, M_NOWAIT | M_ZERO)))
+ return ENOMEM;
- 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;
+ if (ata_raid_rw(parent, HPTV2_LBA(parent),
+ meta, sizeof(struct hptv2_raid_conf), ATA_R_READ)) {
+ if (testing || bootverbose)
+ device_printf(parent, "HighPoint (v2) read metadata failed\n");
+ goto hptv2_out;
}
- /* check if this is a HighPoint RAID struct */
- if (info->magic != HPT_MAGIC_OK && info->magic != HPT_MAGIC_BAD) {
- if (bootverbose)
- printf("ar: HighPoint check1 failed\n");
- goto highpoint_out;
+ /* check if this is a HighPoint v2 RAID struct */
+ if (meta->magic != HPTV2_MAGIC_OK && meta->magic != HPTV2_MAGIC_BAD) {
+ if (testing || bootverbose)
+ device_printf(parent, "HighPoint (v2) check1 failed\n");
+ goto hptv2_out;
}
/* is this disk defined, or an old leftover/spare ? */
- if (!info->magic_0) {
- if (bootverbose)
- printf("ar: HighPoint check2 failed\n");
- goto highpoint_out;
+ if (!meta->magic_0) {
+ if (testing || bootverbose)
+ device_printf(parent, "HighPoint (v2) check2 failed\n");
+ goto hptv2_out;
}
- /* now convert HighPoint config info into our generic form */
+ if (testing || bootverbose)
+ ata_raid_hptv2_print_meta(meta);
+
+ /* now convert HighPoint (v2) metadata into our generic form */
for (array = 0; array < MAX_ARRAYS; array++) {
if (!raidp[array]) {
raidp[array] =
- (struct ar_softc*)malloc(sizeof(struct ar_softc), M_AR,
- M_NOWAIT | M_ZERO);
+ (struct ar_softc *)malloc(sizeof(struct ar_softc), M_AR,
+ M_NOWAIT | M_ZERO);
if (!raidp[array]) {
- printf("ar%d: failed to allocate raid config storage\n", array);
- goto highpoint_out;
+ device_printf(parent, "failed to allocate metadata storage\n");
+ goto hptv2_out;
}
}
raid = raidp[array];
- if (raid->flags & (AR_F_PROMISE_RAID | AR_F_LSI_RAID))
+ if (raid->format && (raid->format != AR_F_HPTV2_RAID))
continue;
- switch (info->type) {
- case HPT_T_RAID0:
- if ((info->order & (HPT_O_RAID0|HPT_O_OK))==(HPT_O_RAID0|HPT_O_OK))
+ switch (meta->type) {
+ case HPTV2_T_RAID0:
+ if ((meta->order & (HPTV2_O_RAID0|HPTV2_O_OK)) ==
+ (HPTV2_O_RAID0|HPTV2_O_OK))
goto highpoint_raid1;
- if (info->order & (HPT_O_RAID0 | HPT_O_RAID1))
+ if (meta->order & (HPTV2_O_RAID0 | HPTV2_O_RAID1))
goto highpoint_raid01;
- if (raid->magic_0 && raid->magic_0 != info->magic_0)
+ if (raid->magic_0 && raid->magic_0 != meta->magic_0)
continue;
- raid->magic_0 = info->magic_0;
- raid->flags |= AR_F_RAID0;
- raid->interleave = 1 << info->stripe_shift;
- disk_number = info->disk_number;
- if (!(info->order & HPT_O_OK))
- info->magic = 0; /* mark bad */
+ raid->magic_0 = meta->magic_0;
+ raid->type = AR_T_RAID0;
+ raid->interleave = 1 << meta->stripe_shift;
+ disk_number = meta->disk_number;
+ if (!(meta->order & HPTV2_O_OK))
+ meta->magic = 0; /* mark bad */
break;
- case HPT_T_RAID1:
+ case HPTV2_T_RAID1:
highpoint_raid1:
- if (raid->magic_0 && raid->magic_0 != info->magic_0)
+ if (raid->magic_0 && raid->magic_0 != meta->magic_0)
continue;
- raid->magic_0 = info->magic_0;
- raid->flags |= AR_F_RAID1;
- disk_number = (info->disk_number > 0);
+ raid->magic_0 = meta->magic_0;
+ raid->type = AR_T_RAID1;
+ disk_number = (meta->disk_number > 0);
break;
- case HPT_T_RAID01_RAID0:
+ case HPTV2_T_RAID01_RAID0:
highpoint_raid01:
- if (info->order & HPT_O_RAID0) {
- if ((raid->magic_0 && raid->magic_0 != info->magic_0) ||
- (raid->magic_1 && raid->magic_1 != info->magic_1))
+ if (meta->order & HPTV2_O_RAID0) {
+ if ((raid->magic_0 && raid->magic_0 != meta->magic_0) ||
+ (raid->magic_1 && raid->magic_1 != meta->magic_1))
continue;
- raid->magic_0 = info->magic_0;
- raid->magic_1 = info->magic_1;
- raid->flags |= (AR_F_RAID0 | AR_F_RAID1);
- raid->interleave = 1 << info->stripe_shift;
- disk_number = info->disk_number;
+ raid->magic_0 = meta->magic_0;
+ raid->magic_1 = meta->magic_1;
+ raid->type = AR_T_RAID01;
+ raid->interleave = 1 << meta->stripe_shift;
+ disk_number = meta->disk_number;
}
else {
- if (raid->magic_1 && raid->magic_1 != info->magic_1)
+ if (raid->magic_1 && raid->magic_1 != meta->magic_1)
continue;
- raid->magic_1 = info->magic_1;
- raid->flags |= (AR_F_RAID0 | AR_F_RAID1);
- raid->interleave = 1 << info->stripe_shift;
- disk_number = info->disk_number + info->array_width;
- if (!(info->order & HPT_O_RAID1))
- info->magic = 0; /* mark bad */
+ raid->magic_1 = meta->magic_1;
+ raid->type = AR_T_RAID01;
+ raid->interleave = 1 << meta->stripe_shift;
+ disk_number = meta->disk_number + meta->array_width;
+ if (!(meta->order & HPTV2_O_RAID1))
+ meta->magic = 0; /* mark bad */
}
break;
- case HPT_T_SPAN:
- if (raid->magic_0 && raid->magic_0 != info->magic_0)
+ case HPTV2_T_SPAN:
+ if (raid->magic_0 && raid->magic_0 != meta->magic_0)
continue;
- raid->magic_0 = info->magic_0;
- raid->flags |= AR_F_SPAN;
- disk_number = info->disk_number;
+ raid->magic_0 = meta->magic_0;
+ raid->type = AR_T_SPAN;
+ disk_number = meta->disk_number;
break;
default:
- printf("ar%d: HighPoint unknown RAID type 0x%02x\n",
- array, info->type);
+ device_printf(parent, "Highpoint (v2) unknown RAID type 0x%02x\n",
+ meta->type);
free(raidp[array], M_AR);
raidp[array] = NULL;
- goto highpoint_out;
+ goto hptv2_out;
}
- raid->flags |= AR_F_HIGHPOINT_RAID;
- raid->disks[disk_number].device = adp->device;
+ raid->format |= AR_F_HPTV2_RAID;
+ raid->disks[disk_number].dev = parent;
raid->disks[disk_number].flags = (AR_DF_PRESENT | AR_DF_ASSIGNED);
- AD_SOFTC(raid->disks[disk_number])->flags |= AD_F_RAID_SUBDISK;
raid->lun = array;
- if (info->magic == HPT_MAGIC_OK) {
+ strncpy(raid->name, meta->name_1,
+ min(sizeof(raid->name), sizeof(meta->name_1)));
+ if (meta->magic == HPTV2_MAGIC_OK) {
raid->disks[disk_number].flags |= AR_DF_ONLINE;
- raid->flags |= AR_F_READY;
- raid->width = info->array_width;
+ raid->width = meta->array_width;
+ raid->total_sectors = meta->total_sectors;
raid->heads = 255;
raid->sectors = 63;
- raid->cylinders = info->total_sectors / (63 * 255);
- raid->total_sectors = info->total_sectors;
- raid->offset = HPT_LBA + 1;
- raid->reserved = HPT_LBA + 1;
- raid->lock_start = raid->lock_end = info->rebuild_lba;
- raid->disks[disk_number].disk_sectors =
- info->total_sectors / info->array_width;
+ raid->cylinders = raid->total_sectors / (63 * 255);
+ raid->offset_sectors = HPTV2_LBA(parent) + 1;
+ raid->rebuild_lba = meta->rebuild_lba;
+ raid->disks[disk_number].sectors =
+ raid->total_sectors / raid->width;
}
else
- raid->disks[disk_number].flags &= ~ AR_DF_ONLINE;
+ raid->disks[disk_number].flags &= ~AR_DF_ONLINE;
- if ((raid->flags & AR_F_RAID0) && (raid->total_disks < raid->width))
+ if ((raid->type & AR_T_RAID0) && (raid->total_disks < raid->width))
raid->total_disks = raid->width;
if (disk_number >= raid->total_disks)
raid->total_disks = disk_number + 1;
+ ars->raid = raid;
+ ars->disk_number = disk_number;
retval = 1;
break;
}
-highpoint_out:
- free(info, M_AR);
+hptv2_out:
+ free(meta, M_AR);
return retval;
}
static int
-ar_highpoint_write_conf(struct ar_softc *rdp)
+ata_raid_hptv2_write_meta(struct ar_softc *rdp)
{
- struct highpoint_raid_conf *config;
+ struct hptv2_raid_conf *meta;
struct timeval timestamp;
- int disk;
+ int disk, error = 0;
+
+ if (!(meta = (struct hptv2_raid_conf *)
+ malloc(sizeof(struct hptv2_raid_conf), M_AR, M_NOWAIT | M_ZERO))) {
+ printf("ar%d: failed to allocate metadata storage\n", rdp->lun);
+ return ENOMEM;
+ }
microtime(&timestamp);
rdp->magic_0 = timestamp.tv_sec + 2;
rdp->magic_1 = timestamp.tv_sec;
for (disk = 0; disk < rdp->total_disks; disk++) {
- 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;
+ meta->magic = HPTV2_MAGIC_OK;
if (rdp->disks[disk].flags & AR_DF_ASSIGNED) {
- config->magic_0 = rdp->magic_0;
- strcpy(config->name_1, "FreeBSD");
+ meta->magic_0 = rdp->magic_0;
+ if (strlen(rdp->name))
+ strncpy(meta->name_1, rdp->name, sizeof(meta->name_1));
+ else
+ strcpy(meta->name_1, "FreeBSD");
}
- config->disk_number = disk;
+ meta->disk_number = disk;
- switch (rdp->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) {
- case AR_F_RAID0:
- config->type = HPT_T_RAID0;
- strcpy(config->name_2, "RAID 0");
+ switch (rdp->type) {
+ case AR_T_RAID0:
+ meta->type = HPTV2_T_RAID0;
+ strcpy(meta->name_2, "RAID 0");
if (rdp->disks[disk].flags & AR_DF_ONLINE)
- config->order = HPT_O_OK;
+ meta->order = HPTV2_O_OK;
break;
- case AR_F_RAID1:
- config->type = HPT_T_RAID0;
- strcpy(config->name_2, "RAID 1");
- config->disk_number = (disk < rdp->width) ? disk : disk + 5;
- config->order = HPT_O_RAID0 | HPT_O_OK;
+ case AR_T_RAID1:
+ meta->type = HPTV2_T_RAID0;
+ strcpy(meta->name_2, "RAID 1");
+ meta->disk_number = (disk < rdp->width) ? disk : disk + 5;
+ meta->order = HPTV2_O_RAID0 | HPTV2_O_OK;
break;
- case AR_F_RAID0 | AR_F_RAID1:
- config->type = HPT_T_RAID01_RAID0;
- strcpy(config->name_2, "RAID 0+1");
+ case AR_T_RAID01:
+ meta->type = HPTV2_T_RAID01_RAID0;
+ strcpy(meta->name_2, "RAID 0+1");
if (rdp->disks[disk].flags & AR_DF_ONLINE) {
if (disk < rdp->width) {
- config->order = (HPT_O_RAID0 | HPT_O_RAID1);
- config->magic_0 = rdp->magic_0 - 1;
+ meta->order = (HPTV2_O_RAID0 | HPTV2_O_RAID1);
+ meta->magic_0 = rdp->magic_0 - 1;
}
else {
- config->order = HPT_O_RAID1;
- config->disk_number -= rdp->width;
+ meta->order = HPTV2_O_RAID1;
+ meta->disk_number -= rdp->width;
}
}
else
- config->magic_0 = rdp->magic_0 - 1;
- config->magic_1 = rdp->magic_1;
+ meta->magic_0 = rdp->magic_0 - 1;
+ meta->magic_1 = rdp->magic_1;
break;
- case AR_F_SPAN:
- config->type = HPT_T_SPAN;
- strcpy(config->name_2, "SPAN");
+ case AR_T_SPAN:
+ meta->type = HPTV2_T_SPAN;
+ strcpy(meta->name_2, "SPAN");
break;
}
- config->array_width = rdp->width;
- config->stripe_shift = (rdp->width > 1) ? (ffs(rdp->interleave)-1) : 0;
- config->total_sectors = rdp->total_sectors;
- config->rebuild_lba = rdp->lock_start;
+ meta->array_width = rdp->width;
+ meta->stripe_shift = (rdp->width > 1) ? (ffs(rdp->interleave)-1) : 0;
+ meta->total_sectors = rdp->total_sectors;
+ meta->rebuild_lba = rdp->rebuild_lba;
+
+ if (rdp->disks[disk].dev &&
+ (rdp->disks[disk].flags & (AR_DF_PRESENT | AR_DF_ONLINE)) ==
+ (AR_DF_PRESENT | AR_DF_ONLINE)) {
+ if (ata_raid_rw(rdp->disks[disk].dev,
+ HPTV2_LBA(rdp->disks[disk].dev), meta,
+ sizeof(struct promise_raid_conf),
+ ATA_R_WRITE | ATA_R_DIRECT)) {
+ device_printf(rdp->disks[disk].dev, "write metadata failed\n");
+ error = EIO;
+ }
+ }
+ }
+ free(meta, M_AR);
+ return error;
+}
+
+/* Highpoint V3 RocketRAID Metadata */
+static int
+ata_raid_hptv3_read_meta(device_t dev, struct ar_softc **raidp)
+{
+ struct ata_raid_subdisk *ars = device_get_softc(dev);
+ device_t parent = device_get_parent(dev);
+ struct hptv3_raid_conf *meta;
+ struct ar_softc *raid = NULL;
+ int array, disk_number, retval = 0;
+
+ if (!(meta = (struct hptv3_raid_conf *)
+ malloc(sizeof(struct hptv3_raid_conf), M_AR, M_NOWAIT | M_ZERO)))
+ return ENOMEM;
+
+ if (ata_raid_rw(parent, HPTV3_LBA(parent),
+ meta, sizeof(struct hptv3_raid_conf), ATA_R_READ)) {
+ if (testing || bootverbose)
+ device_printf(parent, "HighPoint (v3) read metadata failed\n");
+ goto hptv3_out;
+ }
+
+ /* check if this is a HighPoint v3 RAID struct */
+ if (meta->magic != HPTV3_MAGIC) {
+ if (testing || bootverbose)
+ device_printf(parent, "HighPoint (v3) check1 failed\n");
+ goto hptv3_out;
+ }
- if (rdp->disks[disk].device && rdp->disks[disk].device->softc &&
- !(rdp->disks[disk].device->flags & ATA_D_DETACHING)) {
- if (ar_rw(AD_SOFTC(rdp->disks[disk]), HPT_LBA,
- sizeof(struct highpoint_raid_conf),
- (caddr_t)config, AR_WRITE)) {
- printf("ar%d: Highpoint write conf failed\n", rdp->lun);
- free(config, M_AR);
- return -1;
+ /* check if there are any config_entries */
+ if (meta->config_entries < 1) {
+ if (testing || bootverbose)
+ device_printf(parent, "HighPoint (v3) check2 failed\n");
+ goto hptv3_out;
+ }
+
+ if (testing || bootverbose)
+ ata_raid_hptv3_print_meta(meta);
+
+ /* now convert HighPoint (v3) metadata into our generic form */
+ for (array = 0; array < MAX_ARRAYS; array++) {
+ if (!raidp[array]) {
+ raidp[array] =
+ (struct ar_softc *)malloc(sizeof(struct ar_softc), M_AR,
+ M_NOWAIT | M_ZERO);
+ if (!raidp[array]) {
+ device_printf(parent, "failed to allocate metadata storage\n");
+ goto hptv3_out;
}
}
- else
- free(config, M_AR);
+ raid = raidp[array];
+ if (raid->format && (raid->format != AR_F_HPTV3_RAID))
+ continue;
+
+ if ((raid->format & AR_F_HPTV3_RAID) && raid->magic_0 != meta->magic_0)
+ continue;
+
+ switch (meta->configs[0].type) {
+ case HPTV3_T_RAID0:
+ raid->type = AR_T_RAID0;
+ raid->width = meta->configs[0].total_disks;
+ disk_number = meta->configs[0].disk_number;
+ break;
+
+ case HPTV3_T_RAID1:
+ raid->type = AR_T_RAID1;
+ raid->width = meta->configs[0].total_disks / 2;
+ disk_number = meta->configs[0].disk_number;
+ break;
+
+ case HPTV3_T_RAID5:
+ raid->type = AR_T_RAID5;
+ raid->width = meta->configs[0].total_disks;
+ disk_number = meta->configs[0].disk_number;
+ break;
+
+ case HPTV3_T_SPAN:
+ raid->type = AR_T_SPAN;
+ raid->width = meta->configs[0].total_disks;
+ disk_number = meta->configs[0].disk_number;
+ break;
+
+ default:
+ device_printf(parent, "Highpoint (v3) unknown RAID type 0x%02x\n",
+ meta->configs[0].type);
+ free(raidp[array], M_AR);
+ raidp[array] = NULL;
+ goto hptv3_out;
+ }
+ if (meta->config_entries == 2) {
+ switch (meta->configs[1].type) {
+ case HPTV3_T_RAID1:
+ if (raid->type == AR_T_RAID0) {
+ raid->type = AR_T_RAID01;
+ disk_number = meta->configs[1].disk_number +
+ (meta->configs[0].disk_number << 1);
+ break;
+ }
+ default:
+ device_printf(parent, "Highpoint (v3) unknown level 2 0x%02x\n",
+ meta->configs[1].type);
+ free(raidp[array], M_AR);
+ raidp[array] = NULL;
+ goto hptv3_out;
+ }
+ }
+
+ raid->magic_0 = meta->magic_0;
+ raid->format = AR_F_HPTV3_RAID;
+ raid->generation = meta->timestamp;
+ raid->interleave = 1 << meta->configs[0].stripe_shift;
+ raid->total_disks = meta->configs[0].total_disks +
+ meta->configs[1].total_disks;
+ raid->total_sectors = meta->configs[0].total_sectors +
+ ((u_int64_t)meta->configs_high[0].total_sectors << 32);
+ raid->heads = 255;
+ raid->sectors = 63;
+ raid->cylinders = raid->total_sectors / (63 * 255);
+ raid->offset_sectors = 0;
+ raid->rebuild_lba = meta->configs[0].rebuild_lba +
+ ((u_int64_t)meta->configs_high[0].rebuild_lba << 32);
+ raid->lun = array;
+ strncpy(raid->name, meta->name,
+ min(sizeof(raid->name), sizeof(meta->name)));
+ raid->disks[disk_number].sectors = raid->total_sectors /
+ (raid->type == AR_T_RAID5 ? raid->width - 1 : raid->width);
+ raid->disks[disk_number].dev = parent;
+ raid->disks[disk_number].flags =
+ (AR_DF_PRESENT | AR_DF_ASSIGNED | AR_DF_ONLINE);
+ ars->raid = raid;
+ ars->disk_number = disk_number;
+ retval = 1;
+ break;
}
- return 0;
+
+hptv3_out:
+ free(meta, M_AR);
+ return retval;
}
+#if 0
+static int
+ata_raid_hptv3_write_meta(struct ar_softc *rdp)
+{
+ struct hptv3_raid_conf *meta;
+ int error = 0;
+ if (!(meta = (struct hptv3_raid_conf *)
+ malloc(sizeof(struct hptv3_raid_conf), M_AR, M_NOWAIT | M_ZERO))) {
+ printf("ar%d: failed to allocate metadata storage\n", rdp->lun);
+ return ENOMEM;
+ }
+ return error;
+}
+#endif
+
+/* Intel MatrixRAID Metadata */
static int
-ar_lsi_read_conf(struct ad_softc *adp, struct ar_softc **raidp)
+ata_raid_intel_read_meta(device_t dev, struct ar_softc **raidp)
{
- struct lsi_raid_conf *info;
+ struct ata_raid_subdisk *ars = device_get_softc(dev);
+ device_t parent = device_get_parent(dev);
+ struct intel_raid_conf *meta;
+ struct ar_softc *raid = NULL;
+ u_int32_t checksum, *ptr;
+ int array, count, disk, retval = 0;
+
+ if (!(meta = (struct intel_raid_conf *)
+ malloc(1024, M_AR, M_NOWAIT | M_ZERO)))
+ return ENOMEM;
+
+ if (ata_raid_rw(parent, INTEL_LBA(parent),
+ meta, 1024, ATA_R_READ)) {
+ if (testing || bootverbose)
+ device_printf(parent, "Intel read metadata failed\n");
+ goto intel_out;
+ }
+
+ /* check if this is a Intel RAID struct */
+ if (strncmp(meta->intel_id, INTEL_MAGIC, strlen(INTEL_MAGIC))) {
+ if (testing || bootverbose)
+ device_printf(parent, "Intel check1 failed\n");
+ goto intel_out;
+ }
+ for (checksum = 0, ptr = (u_int32_t *)meta, count = 0;
+ count < (meta->config_size / sizeof(u_int32_t)); count++) {
+ checksum += *ptr++;
+ }
+
+/* XXX SOS needs to be fixed */
+device_printf(parent, "Intel calc=%08x meta=%08x\n", checksum, meta->checksum);
+
+ if (checksum != meta->checksum) {
+ if (testing || bootverbose)
+ device_printf(parent, "Intel check2 failed\n");
+ //goto intel_out;
+ }
+
+ if (testing || bootverbose)
+ ata_raid_intel_print_meta(meta);
+
+ /* now convert Intel metadata into our generic form */
+ for (array = 0; array < MAX_ARRAYS; array++) {
+ if (!raidp[array]) {
+ raidp[array] =
+ (struct ar_softc *)malloc(sizeof(struct ar_softc), M_AR,
+ M_NOWAIT | M_ZERO);
+ if (!raidp[array]) {
+ device_printf(parent, "failed to allocate metadata storage\n");
+ goto intel_out;
+ }
+ }
+ raid = raidp[array];
+ if (raid->format && (raid->format != AR_F_INTEL_RAID))
+ continue;
+
+ if ((raid->format & AR_F_INTEL_RAID) &&
+ (raid->magic_0 != meta->config_id))
+ continue;
+
+ /*
+ * update our knowledge about the array config based on generation
+ * we only grap the first volume description (yet) since the
+ * BIOS'n I have access to puts crap into the following XXX SOS
+ */
+ if (!meta->generation || meta->generation > raid->generation) {
+ struct intel_raid_mapping *map =
+ (struct intel_raid_mapping *)&meta->disk[meta->total_disks];
+
+ switch (map->type) {
+ case INTEL_T_RAID0:
+ raid->type = AR_T_RAID0;
+ raid->width = map->total_disks;
+ break;
+
+ case INTEL_T_RAID1:
+ raid->type = AR_T_RAID1;
+ raid->width = map->total_disks / 2;
+ break;
+
+ default:
+ device_printf(parent, "Intel unknown RAID type 0x%02x\n",
+ map->type);
+ free(raidp[array], M_AR);
+ raidp[array] = NULL;
+ goto intel_out;
+ }
+
+ switch (map->status) {
+ case INTEL_S_READY:
+ raid->status = AR_S_READY;
+ break;
+ case INTEL_S_DEGRADED:
+ raid->status |= AR_S_DEGRADED;
+ break;
+ case INTEL_S_DISABLED:
+ case INTEL_S_FAILURE:
+ raid->status = 0;
+ }
+
+ raid->magic_0 = meta->config_id;
+ raid->format = AR_F_INTEL_RAID;
+ raid->generation = meta->generation;
+ raid->interleave = map->stripe_sectors;
+ raid->total_disks = map->total_disks;
+ raid->total_sectors = map->total_sectors;
+ raid->heads = 255;
+ raid->sectors = 63;
+ raid->cylinders = raid->total_sectors / (63 * 255);
+ raid->offset_sectors = map->offset;
+ raid->rebuild_lba = 0;
+ raid->lun = array;
+ strncpy(raid->name, map->name,
+ min(sizeof(raid->name), sizeof(map->name)));
+
+ /* clear out any old info */
+ for (disk = 0; disk < raid->total_disks; disk++) {
+ raid->disks[disk].dev = NULL;
+ bcopy(meta->disk[map->disk_idx[disk]].serial,
+ raid->disks[disk].serial,
+ sizeof(raid->disks[disk].serial));
+ raid->disks[disk].sectors = map->disk_sectors;
+ raid->disks[disk].flags = 0;
+ if (meta->disk[map->disk_idx[disk]].flags & INTEL_F_ONLINE)
+ raid->disks[disk].flags |= AR_DF_ONLINE;
+ if (meta->disk[map->disk_idx[disk]].flags & INTEL_F_ASSIGNED)
+ raid->disks[disk].flags |= AR_DF_ASSIGNED;
+ if (meta->disk[map->disk_idx[disk]].flags & INTEL_F_SPARE) {
+ raid->disks[disk].flags &= ~(AR_DF_ONLINE | AR_DF_ASSIGNED);
+ raid->disks[disk].flags |= AR_DF_SPARE;
+ }
+ if (meta->disk[map->disk_idx[disk]].flags & INTEL_F_DOWN)
+ raid->disks[disk].flags &= ~AR_DF_ONLINE;
+ }
+ }
+ if (meta->generation >= raid->generation) {
+ for (disk = 0; disk < raid->total_disks; disk++) {
+ struct ata_device *atadev = device_get_softc(parent);
+
+ if (!strncmp(raid->disks[disk].serial, atadev->param.serial,
+ sizeof(raid->disks[disk].serial))) {
+ raid->disks[disk].dev = parent;
+ raid->disks[disk].flags |= (AR_DF_PRESENT | AR_DF_ONLINE);
+ ars->raid = raid;
+ ars->disk_number = disk;
+ retval = 1;
+ }
+ }
+ }
+ if (retval)
+ break;
+ }
+
+intel_out:
+ free(meta, M_AR);
+ return retval;
+}
+
+/* Integrated Technology Express Metadata */
+static int
+ata_raid_ite_read_meta(device_t dev, struct ar_softc **raidp)
+{
+ struct ata_raid_subdisk *ars = device_get_softc(dev);
+ device_t parent = device_get_parent(dev);
+ struct ite_raid_conf *meta;
+ struct ar_softc *raid = NULL;
+ int array, disk_number, count, retval = 0;
+ u_int16_t *ptr;
+
+ if (!(meta = (struct ite_raid_conf *)
+ malloc(sizeof(struct ite_raid_conf), M_AR, M_NOWAIT | M_ZERO)))
+ return ENOMEM;
+
+ if (ata_raid_rw(parent, ITE_LBA(parent),
+ meta, sizeof(struct ite_raid_conf), ATA_R_READ)) {
+ if (testing || bootverbose)
+ device_printf(parent, "ITE read metadata failed\n");
+ goto ite_out;
+ }
+
+ /* check if this is a ITE RAID struct */
+ for (ptr = (u_int16_t *)meta->ite_id, count = 0;
+ count < sizeof(meta->ite_id)/sizeof(uint16_t); count++)
+ ptr[count] = be16toh(ptr[count]);
+
+ if (strncmp(meta->ite_id, ITE_MAGIC, strlen(ITE_MAGIC))) {
+ if (testing || bootverbose)
+ device_printf(parent, "ITE check1 failed\n");
+ goto ite_out;
+ }
+
+ if (testing || bootverbose)
+ ata_raid_ite_print_meta(meta);
+
+ /* now convert ITE metadata into our generic form */
+ for (array = 0; array < MAX_ARRAYS; array++) {
+ if ((raid = raidp[array])) {
+ if (raid->format != AR_F_ITE_RAID)
+ continue;
+ if (raid->magic_0 != *((u_int64_t *)meta->timestamp_0))
+ continue;
+ }
+
+ /* if we dont have a disks timestamp the RAID is invalidated */
+ if (*((u_int64_t *)meta->timestamp_1) == 0)
+ goto ite_out;
+
+ if (!raid) {
+ raidp[array] = (struct ar_softc *)malloc(sizeof(struct ar_softc),
+ M_AR, M_NOWAIT | M_ZERO);
+ if (!(raid = raidp[array])) {
+ device_printf(parent, "failed to allocate metadata storage\n");
+ goto ite_out;
+ }
+ }
+
+ switch (meta->type) {
+ case ITE_T_RAID0:
+ raid->type = AR_T_RAID0;
+ raid->width = meta->array_width;
+ raid->total_disks = meta->array_width;
+ disk_number = meta->disk_number;
+ break;
+
+ case ITE_T_RAID1:
+ raid->type = AR_T_RAID1;
+ raid->width = 1;
+ raid->total_disks = 2;
+ disk_number = meta->disk_number;
+ break;
+
+ case ITE_T_RAID01:
+ raid->type = AR_T_RAID01;
+ raid->width = meta->array_width;
+ raid->total_disks = 4;
+ disk_number = ((meta->disk_number & 0x02) >> 1) |
+ ((meta->disk_number & 0x01) << 1);
+ break;
+
+ case ITE_T_SPAN:
+ raid->type = AR_T_SPAN;
+ raid->width = 1;
+ raid->total_disks = meta->array_width;
+ disk_number = meta->disk_number;
+ break;
+
+ default:
+ device_printf(parent, "ITE unknown RAID type 0x%02x\n", meta->type);
+ free(raidp[array], M_AR);
+ raidp[array] = NULL;
+ goto ite_out;
+ }
+
+ raid->magic_0 = *((u_int64_t *)meta->timestamp_0);
+ raid->format = AR_F_ITE_RAID;
+ raid->generation = 0;
+ raid->interleave = meta->stripe_sectors;
+ raid->total_sectors = meta->total_sectors;
+ raid->heads = 255;
+ raid->sectors = 63;
+ raid->cylinders = raid->total_sectors / (63 * 255);
+ raid->offset_sectors = 0;
+ raid->rebuild_lba = 0;
+ raid->lun = array;
+
+ raid->disks[disk_number].dev = parent;
+ raid->disks[disk_number].sectors = raid->total_sectors / raid->width;
+ raid->disks[disk_number].flags =
+ (AR_DF_PRESENT | AR_DF_ASSIGNED | AR_DF_ONLINE);
+ ars->raid = raid;
+ ars->disk_number = disk_number;
+ retval = 1;
+ break;
+ }
+ite_out:
+ free(meta, M_AR);
+ return retval;
+}
+
+/* LSILogic V2 MegaRAID Metadata */
+static int
+ata_raid_lsiv2_read_meta(device_t dev, struct ar_softc **raidp)
+{
+ struct ata_raid_subdisk *ars = device_get_softc(dev);
+ device_t parent = device_get_parent(dev);
+ struct lsiv2_raid_conf *meta;
struct ar_softc *raid = NULL;
int array, retval = 0;
- if (!(info = (struct lsi_raid_conf *)
- malloc(sizeof(struct lsi_raid_conf), M_AR, M_NOWAIT | M_ZERO)))
- return retval;
+ if (!(meta = (struct lsiv2_raid_conf *)
+ malloc(sizeof(struct lsiv2_raid_conf), M_AR, M_NOWAIT | M_ZERO)))
+ return ENOMEM;
- if (ar_rw(adp, LSI_LBA(adp), sizeof(struct lsi_raid_conf),
- (caddr_t)info, AR_READ | AR_WAIT)) {
- if (bootverbose)
- printf("ar: LSI read conf failed\n");
- goto lsi_out;
+ if (ata_raid_rw(parent, LSIV2_LBA(parent),
+ meta, sizeof(struct lsiv2_raid_conf), ATA_R_READ)) {
+ if (testing || bootverbose)
+ device_printf(parent, "LSI (v2) read metadata failed\n");
+ goto lsiv2_out;
}
/* check if this is a LSI RAID struct */
- if (strncmp(info->lsi_id, LSI_MAGIC, strlen(LSI_MAGIC))) {
- if (bootverbose)
- printf("ar: LSI check1 failed\n");
- goto lsi_out;
+ if (strncmp(meta->lsi_id, LSIV2_MAGIC, strlen(LSIV2_MAGIC))) {
+ if (testing || bootverbose)
+ device_printf(parent, "LSI (v2) check1 failed\n");
+ goto lsiv2_out;
}
- /* now convert LSI config info into our generic form */
+ if (testing || bootverbose)
+ ata_raid_lsiv2_print_meta(meta);
+
+ /* now convert LSI (v2) config meta into our generic form */
for (array = 0; array < MAX_ARRAYS; array++) {
int raid_entry, conf_entry;
- if (!raidp[array + info->raid_number]) {
- raidp[array + info->raid_number] =
- (struct ar_softc*)malloc(sizeof(struct ar_softc), M_AR,
- M_NOWAIT | M_ZERO);
- if (!raidp[array + info->raid_number]) {
- printf("ar%d: failed to allocate raid config storage\n", array);
- goto lsi_out;
+ if (!raidp[array + meta->raid_number]) {
+ raidp[array + meta->raid_number] =
+ (struct ar_softc *)malloc(sizeof(struct ar_softc), M_AR,
+ M_NOWAIT | M_ZERO);
+ if (!raidp[array + meta->raid_number]) {
+ device_printf(parent, "failed to allocate metadata storage\n");
+ goto lsiv2_out;
}
}
- raid = raidp[array + info->raid_number];
-
- if (raid->flags & (AR_F_PROMISE_RAID | AR_F_HIGHPOINT_RAID))
+ raid = raidp[array + meta->raid_number];
+ if (raid->format && (raid->format != AR_F_LSIV2_RAID))
continue;
if (raid->magic_0 &&
- ((raid->magic_0 != info->timestamp) ||
- (raid->magic_1 != info->raid_number)))
+ ((raid->magic_0 != meta->timestamp) ||
+ (raid->magic_1 != meta->raid_number)))
continue;
- array += info->raid_number;
+ array += meta->raid_number;
- raid_entry = info->raid_number;
- conf_entry = (info->configs[raid_entry].raid.config_offset >> 4) +
- info->disk_number - 1;
+ raid_entry = meta->raid_number;
+ conf_entry = (meta->configs[raid_entry].raid.config_offset >> 4) +
+ meta->disk_number - 1;
- switch (info->configs[raid_entry].raid.type) {
- case LSI_R_RAID0:
- raid->magic_0 = info->timestamp;
- raid->magic_1 = info->raid_number;
- raid->flags |= AR_F_RAID0;
- raid->interleave = info->configs[raid_entry].raid.stripe_size;
- raid->width = info->configs[raid_entry].raid.raid_width;
+ switch (meta->configs[raid_entry].raid.type) {
+ case LSIV2_T_RAID0:
+ raid->magic_0 = meta->timestamp;
+ raid->magic_1 = meta->raid_number;
+ raid->type = AR_T_RAID0;
+ raid->interleave = meta->configs[raid_entry].raid.stripe_sectors;
+ raid->width = meta->configs[raid_entry].raid.array_width;
break;
- case LSI_R_RAID1:
- raid->magic_0 = info->timestamp;
- raid->magic_1 = info->raid_number;
- raid->flags |= AR_F_RAID1;
- raid->width = info->configs[raid_entry].raid.raid_width;
+ case LSIV2_T_RAID1:
+ raid->magic_0 = meta->timestamp;
+ raid->magic_1 = meta->raid_number;
+ raid->type = AR_T_RAID1;
+ raid->width = meta->configs[raid_entry].raid.array_width;
break;
- case LSI_R_RAID0 | LSI_R_RAID1:
- raid->magic_0 = info->timestamp;
- raid->magic_1 = info->raid_number;
- raid->flags |= (AR_F_RAID0 | AR_F_RAID1);
- raid->interleave = info->configs[raid_entry].raid.stripe_size;
- raid->width = info->configs[raid_entry].raid.raid_width;
+ case LSIV2_T_RAID0 | LSIV2_T_RAID1:
+ raid->magic_0 = meta->timestamp;
+ raid->magic_1 = meta->raid_number;
+ raid->type = AR_T_RAID01;
+ raid->interleave = meta->configs[raid_entry].raid.stripe_sectors;
+ raid->width = meta->configs[raid_entry].raid.array_width;
break;
default:
- printf("ar%d: LSI unknown RAID type 0x%02x\n",
- array, info->configs[raid_entry].raid.type);
+ device_printf(parent, "LSI v2 unknown RAID type 0x%02x\n",
+ meta->configs[raid_entry].raid.type);
free(raidp[array], M_AR);
raidp[array] = NULL;
- goto lsi_out;
+ goto lsiv2_out;
}
- /* setup RAID specifics */
- raid->flags |= AR_F_LSI_RAID;
+ raid->format = AR_F_LSIV2_RAID;
raid->generation = 0;
- raid->total_disks = info->configs[raid_entry].raid.disk_count;
+ raid->total_disks = meta->configs[raid_entry].raid.disk_count;
+ raid->total_sectors = meta->configs[raid_entry].raid.total_sectors;
raid->heads = 255;
raid->sectors = 63;
- raid->cylinders = info->configs[raid_entry].raid.total_sectors/(63*255);
- raid->total_sectors = info->configs[raid_entry].raid.total_sectors;
- raid->offset = 0;
- raid->reserved = 1;
- raid->lock_start = raid->lock_end = 0;
+ raid->cylinders = raid->total_sectors / (63 * 255);
+ raid->offset_sectors = 0;
+ raid->rebuild_lba = 0;
raid->lun = array;
- /* setup RAID specifics of this disk */
- if (info->configs[conf_entry].disk.device != LSI_D_NONE) {
- raid->disks[info->disk_number].device = adp->device;
- raid->disks[info->disk_number].disk_sectors =
- info->configs[conf_entry].disk.disk_sectors;
- raid->disks[info->disk_number].flags =
+ if (meta->configs[conf_entry].disk.device != LSIV2_D_NONE) {
+ raid->disks[meta->disk_number].dev = parent;
+ raid->disks[meta->disk_number].sectors =
+ meta->configs[conf_entry].disk.disk_sectors;
+ raid->disks[meta->disk_number].flags =
(AR_DF_ONLINE | AR_DF_PRESENT | AR_DF_ASSIGNED);
- AD_SOFTC(raid->disks[info->disk_number])->flags |=
- AD_F_RAID_SUBDISK;
+ ars->raid = raid;
+ ars->disk_number = meta->disk_number;
retval = 1;
}
else
- raid->disks[info->disk_number].flags &= ~AR_DF_ONLINE;
+ raid->disks[meta->disk_number].flags &= ~AR_DF_ONLINE;
- return retval;
+ break;
}
-lsi_out:
- free(info, M_AR);
+lsiv2_out:
+ free(meta, M_AR);
return retval;
}
+/* LSILogic V3 MegaRAID Metadata */
static int
-ar_lsi_write_conf(struct ar_softc *rdp)
+ata_raid_lsiv3_read_meta(device_t dev, struct ar_softc **raidp)
{
- struct lsi_raid_conf *config;
- struct timeval timestamp;
- int disk, disk_entry;
+ struct ata_raid_subdisk *ars = device_get_softc(dev);
+ device_t parent = device_get_parent(dev);
+ struct lsiv3_raid_conf *meta;
+ struct ar_softc *raid = NULL;
+ u_int8_t checksum, *ptr;
+ int array, entry, count, disk_number, retval = 0;
- microtime(&timestamp);
- rdp->magic_0 = timestamp.tv_sec & 0xffffffc0;
- rdp->magic_1 = 0;
-
- for (disk = 0; disk < rdp->total_disks; disk++) {
- if (!(config = (struct lsi_raid_conf *)
- malloc(sizeof(struct lsi_raid_conf), M_AR, M_NOWAIT | M_ZERO))) {
- printf("ar%d: LSI write conf failed\n", rdp->lun);
- return -1;
- }
-
- bcopy(LSI_MAGIC, config->lsi_id, strlen(LSI_MAGIC));
- config->dummy_1 = 0x10;
- config->flags = 0x19; /* SOS X */
- config->version[0] = '2';
- config->version[1] = '0';
- config->config_entries = 2 + rdp->total_disks;
- config->raid_count = 1;
- config->total_disks = rdp->total_disks;
- config->dummy_e = 0xfc;
- config->disk_number = disk;
- config->raid_number = 0;
- config->timestamp = rdp->magic_0;
-
- switch (rdp->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) {
- case AR_F_RAID0:
- config->configs[0].raid.type = LSI_R_RAID0;
+ if (!(meta = (struct lsiv3_raid_conf *)
+ malloc(sizeof(struct lsiv3_raid_conf), M_AR, M_NOWAIT | M_ZERO)))
+ return ENOMEM;
+
+ if (ata_raid_rw(parent, LSIV3_LBA(parent),
+ meta, sizeof(struct lsiv3_raid_conf), ATA_R_READ)) {
+ if (testing || bootverbose)
+ device_printf(parent, "LSI (v3) read metadata failed\n");
+ goto lsiv3_out;
+ }
+
+ /* check if this is a LSI RAID struct */
+ if (strncmp(meta->lsi_id, LSIV3_MAGIC, strlen(LSIV3_MAGIC))) {
+ if (testing || bootverbose)
+ device_printf(parent, "LSI (v3) check1 failed\n");
+ goto lsiv3_out;
+ }
+
+ /* check if the checksum is OK */
+ for (checksum = 0, ptr = meta->lsi_id, count = 0; count < 512; count++)
+ checksum += *ptr++;
+ if (checksum) {
+ if (testing || bootverbose)
+ device_printf(parent, "LSI (v3) check2 failed\n");
+ goto lsiv3_out;
+ }
+
+ if (testing || bootverbose)
+ ata_raid_lsiv3_print_meta(meta);
+
+ /* now convert LSI (v3) config meta into our generic form */
+ for (array = 0, entry = 0; array < MAX_ARRAYS && entry < 8;) {
+ if (!raidp[array]) {
+ raidp[array] =
+ (struct ar_softc *)malloc(sizeof(struct ar_softc), M_AR,
+ M_NOWAIT | M_ZERO);
+ if (!raidp[array]) {
+ device_printf(parent, "failed to allocate metadata storage\n");
+ goto lsiv3_out;
+ }
+ }
+ raid = raidp[array];
+ if (raid->format && (raid->format != AR_F_LSIV3_RAID)) {
+ array++;
+ continue;
+ }
+
+ if ((raid->format == AR_F_LSIV3_RAID) &&
+ (raid->magic_0 != meta->timestamp)) {
+ array++;
+ continue;
+ }
+
+ switch (meta->raid[entry].total_disks) {
+ case 0:
+ entry++;
+ continue;
+ case 1:
+ if (meta->raid[entry].device == meta->device) {
+ disk_number = 0;
+ break;
+ }
+ if (raid->format)
+ array++;
+ entry++;
+ continue;
+ case 2:
+ disk_number = (meta->device & (LSIV3_D_DEVICE|LSIV3_D_CHANNEL))?1:0;
+ break;
+ default:
+ device_printf(parent, "lsiv3 > 2 disk support untested!!\n");
+ disk_number = (meta->device & LSIV3_D_DEVICE ? 1 : 0) +
+ (meta->device & LSIV3_D_CHANNEL ? 2 : 0);
break;
+ }
- case AR_F_RAID1:
- config->configs[0].raid.type = LSI_R_RAID1;
+ switch (meta->raid[entry].type) {
+ case LSIV3_T_RAID0:
+ raid->type = AR_T_RAID0;
+ raid->width = meta->raid[entry].total_disks;
break;
- case AR_F_RAID0 | AR_F_RAID1:
- config->flags = 0x15; /* SOS X */
- config->configs[0].raid.type = (LSI_R_RAID0 | LSI_R_RAID1);
+ case LSIV3_T_RAID1:
+ raid->type = AR_T_RAID1;
+ raid->width = meta->raid[entry].array_width;
break;
default:
- free(config, M_AR);
- return -1;
- }
-
- config->configs[0].raid.dummy_1 = 0x10;
- config->configs[0].raid.stripe_size = rdp->interleave;
- config->configs[0].raid.raid_width = rdp->width;
- config->configs[0].raid.disk_count = rdp->total_disks;
- config->configs[0].raid.config_offset = 2 * 0x10;
- config->configs[0].raid.total_sectors = rdp->total_sectors;
-
- for (disk_entry = 0; disk_entry < rdp->total_disks; disk_entry++) {
- if (rdp->disks[disk_entry].flags & AR_DF_ONLINE)
- config->configs[1 + disk_entry].disk.device =
- (rdp->disks[disk_entry].device->channel->unit ?
- LSI_D_CHANNEL1 : LSI_D_CHANNEL0) |
- (rdp->disks[disk_entry].device->unit ?
- LSI_D_SLAVE : LSI_D_MASTER);
- else {
- config->configs[1 + disk_entry].disk.device = LSI_D_NONE;
- config->configs[1 + disk_entry].disk.flags = LSI_D_GONE;
- }
- config->configs[1 + disk_entry].disk.dummy_1 = 0x10;
- config->configs[1 + disk_entry].disk.disk_sectors =
- rdp->disks[disk_entry].disk_sectors;
- config->configs[1 + disk_entry].disk.disk_number = disk_entry;
- config->configs[1 + disk_entry].disk.raid_number = 0;
- }
-
- if ((rdp->disks[disk].device && rdp->disks[disk].device->softc) &&
- !(rdp->disks[disk].device->flags & ATA_D_DETACHING)) {
-
- if (ar_rw(AD_SOFTC(rdp->disks[disk]),
- LSI_LBA(AD_SOFTC(rdp->disks[disk])),
- sizeof(struct lsi_raid_conf),
- (caddr_t)config, AR_WRITE)) {
- printf("ar%d: LSI write conf failed\n", rdp->lun);
- free(config, M_AR);
- return -1;
- }
+ device_printf(parent, "LSI v3 unknown RAID type 0x%02x\n",
+ meta->raid[entry].type);
+ free(raidp[array], M_AR);
+ raidp[array] = NULL;
+ entry++;
+ continue;
}
- else
- free(config, M_AR);
+
+ raid->magic_0 = meta->timestamp;
+ raid->format = AR_F_LSIV3_RAID;
+ raid->generation = 0;
+ raid->interleave = meta->raid[entry].stripe_pages * 8;
+ raid->total_disks = meta->raid[entry].total_disks;
+ raid->total_sectors = raid->width * meta->raid[entry].sectors;
+ raid->heads = 255;
+ raid->sectors = 63;
+ raid->cylinders = raid->total_sectors / (63 * 255);
+ raid->offset_sectors = meta->raid[entry].offset;
+ raid->rebuild_lba = 0;
+ raid->lun = array;
+
+ raid->disks[disk_number].dev = parent;
+ raid->disks[disk_number].sectors = raid->total_sectors / raid->width;
+ raid->disks[disk_number].flags =
+ (AR_DF_PRESENT | AR_DF_ASSIGNED | AR_DF_ONLINE);
+ ars->raid = raid;
+ ars->disk_number = disk_number;
+ retval = 1;
+ entry++;
+ array++;
}
- return 0;
+
+lsiv3_out:
+ free(meta, M_AR);
+ return retval;
}
+/* Promise FastTrak Metadata */
static int
-ar_promise_read_conf(struct ad_softc *adp, struct ar_softc **raidp, int local)
+ata_raid_promise_read_meta(device_t dev, struct ar_softc **raidp, int native)
{
- struct promise_raid_conf *info;
+ struct ata_raid_subdisk *ars = device_get_softc(dev);
+ device_t parent = device_get_parent(dev);
+ struct promise_raid_conf *meta;
struct ar_softc *raid;
- u_int32_t magic, cksum, *ckptr;
+ u_int32_t checksum, *ptr;
int array, count, disk, disksum = 0, retval = 0;
- if (!(info = (struct promise_raid_conf *)
+ if (!(meta = (struct promise_raid_conf *)
malloc(sizeof(struct promise_raid_conf), M_AR, M_NOWAIT | M_ZERO)))
- return retval;
+ return ENOMEM;
- if (ar_rw(adp, PR_LBA(adp), sizeof(struct promise_raid_conf),
- (caddr_t)info, AR_READ | AR_WAIT)) {
- if (bootverbose)
- printf("ar: %s read conf failed\n", local ? "FreeBSD" : "Promise");
+ if (ata_raid_rw(parent, PR_LBA(parent),
+ meta, sizeof(struct promise_raid_conf), ATA_R_READ)) {
+ if (testing || bootverbose)
+ device_printf(parent, "%s read metadata failed\n",
+ native ? "FreeBSD" : "Promise");
goto promise_out;
}
- /* check if this is a Promise RAID struct (or our local one) */
- if (local) {
- if (strncmp(info->promise_id, ATA_MAGIC, strlen(ATA_MAGIC))) {
- if (bootverbose)
- printf("ar: FreeBSD check1 failed\n");
+ /* check the signature */
+ if (native) {
+ if (strncmp(meta->promise_id, ATA_MAGIC, strlen(ATA_MAGIC))) {
+ if (testing || bootverbose)
+ device_printf(parent, "FreeBSD check1 failed\n");
goto promise_out;
}
}
else {
- if (strncmp(info->promise_id, PR_MAGIC, strlen(PR_MAGIC))) {
- if (bootverbose)
- printf("ar: Promise check1 failed\n");
+ if (strncmp(meta->promise_id, PR_MAGIC, strlen(PR_MAGIC))) {
+ if (testing || bootverbose)
+ device_printf(parent, "Promise check1 failed\n");
goto promise_out;
}
}
/* check if the checksum is OK */
- for (cksum = 0, ckptr = (int32_t *)info, count = 0; count < 511; count++)
- cksum += *ckptr++;
- if (cksum != *ckptr) {
- if (bootverbose)
- printf("ar: %s check2 failed\n", local ? "FreeBSD" : "Promise");
+ for (checksum = 0, ptr = (u_int32_t *)meta, count = 0; count < 511; count++)
+ checksum += *ptr++;
+ if (checksum != *ptr) {
+ if (testing || bootverbose)
+ device_printf(parent, "%s check2 failed\n",
+ native ? "FreeBSD" : "Promise");
goto promise_out;
}
- /* now convert Promise config info into our generic form */
- if (info->raid.integrity != PR_I_VALID) {
- if (bootverbose)
- printf("ar: %s check3 failed\n", local ? "FreeBSD" : "Promise");
+ /* check on disk integrity status */
+ if (meta->raid.integrity != PR_I_VALID) {
+ if (testing || bootverbose)
+ device_printf(parent, "%s check3 failed\n",
+ native ? "FreeBSD" : "Promise");
goto promise_out;
}
+ if (testing || bootverbose)
+ ata_raid_promise_print_meta(meta);
+
+ /* now convert Promise metadata into our generic form */
for (array = 0; array < MAX_ARRAYS; array++) {
if (!raidp[array]) {
raidp[array] =
- (struct ar_softc*)malloc(sizeof(struct ar_softc), M_AR,
- M_NOWAIT | M_ZERO);
+ (struct ar_softc *)malloc(sizeof(struct ar_softc), M_AR,
+ M_NOWAIT | M_ZERO);
if (!raidp[array]) {
- printf("ar%d: failed to allocate raid config storage\n", array);
+ device_printf(parent, "failed to allocate metadata storage\n");
goto promise_out;
}
}
raid = raidp[array];
- if (raid->flags & (AR_F_LSI_RAID | AR_F_HIGHPOINT_RAID))
+ if (raid->format && (raid->format != AR_F_PROMISE_RAID))
continue;
- magic = (pci_get_device(device_get_parent(
- adp->device->channel->dev)) >> 16) |
- (info->raid.array_number << 16);
-
- if (raid->flags & AR_F_PROMISE_RAID && magic != raid->magic_0)
+ if ((raid->format == AR_F_PROMISE_RAID) &&
+ !(meta->raid.magic_1 == (raid->magic_1)))
continue;
/* update our knowledge about the array config based on generation */
- if (!info->raid.generation || info->raid.generation > raid->generation){
- raid->generation = info->raid.generation;
- raid->flags = AR_F_PROMISE_RAID;
- if (local)
- raid->flags |= AR_F_FREEBSD_RAID;
- raid->magic_0 = magic;
- raid->lun = array;
- if ((info->raid.status &
- (PR_S_VALID | PR_S_ONLINE | PR_S_INITED | PR_S_READY)) ==
- (PR_S_VALID | PR_S_ONLINE | PR_S_INITED | PR_S_READY)) {
- raid->flags |= AR_F_READY;
- if (info->raid.status & PR_S_DEGRADED)
- raid->flags |= AR_F_DEGRADED;
- }
- else
- raid->flags &= ~AR_F_READY;
+ if (!meta->raid.generation || meta->raid.generation > raid->generation){
+ switch (meta->raid.type) {
+ case PR_T_SPAN:
+ raid->type = AR_T_SPAN;
+ break;
+
+ case PR_T_JBOD:
+ raid->type = AR_T_JBOD;
+ break;
- switch (info->raid.type) {
case PR_T_RAID0:
- raid->flags |= AR_F_RAID0;
+ raid->type = AR_T_RAID0;
break;
case PR_T_RAID1:
- raid->flags |= AR_F_RAID1;
- if (info->raid.array_width > 1)
- raid->flags |= AR_F_RAID0;
+ raid->type = AR_T_RAID1;
+ if (meta->raid.array_width > 1)
+ raid->type = AR_T_RAID01;
break;
- case PR_T_SPAN:
- raid->flags |= AR_F_SPAN;
+ case PR_T_RAID5:
+ raid->type = AR_T_RAID5;
break;
default:
- printf("ar%d: %s unknown RAID type 0x%02x\n",
- array, local ? "FreeBSD" : "Promise", info->raid.type);
+ device_printf(parent, "%s unknown RAID type 0x%02x\n",
+ native ? "FreeBSD" : "Promise", meta->raid.type);
free(raidp[array], M_AR);
raidp[array] = NULL;
goto promise_out;
}
- raid->interleave = 1 << info->raid.stripe_shift;
- raid->width = info->raid.array_width;
- raid->total_disks = info->raid.total_disks;
- raid->heads = info->raid.heads + 1;
- raid->sectors = info->raid.sectors;
- raid->cylinders = info->raid.cylinders + 1;
- raid->total_sectors = info->raid.total_sectors;
- raid->offset = 0;
- raid->reserved = 63;
- raid->lock_start = raid->lock_end = info->raid.rebuild_lba;
+ raid->magic_1 = meta->raid.magic_1;
+ if (native)
+ raid->format = AR_F_FREEBSD_RAID;
+ else
+ raid->format = AR_F_PROMISE_RAID;
+ raid->generation = meta->raid.generation;
+ raid->interleave = 1 << meta->raid.stripe_shift;
+ raid->width = meta->raid.array_width;
+ raid->total_disks = meta->raid.total_disks;
+ raid->heads = meta->raid.heads + 1;
+ raid->sectors = meta->raid.sectors;
+ raid->cylinders = meta->raid.cylinders + 1;
+ raid->total_sectors = meta->raid.total_sectors;
+ raid->offset_sectors = 0;
+ raid->rebuild_lba = meta->raid.rebuild_lba;
+ raid->lun = array;
+ if ((meta->raid.status &
+ (PR_S_VALID | PR_S_ONLINE | PR_S_INITED | PR_S_READY)) ==
+ (PR_S_VALID | PR_S_ONLINE | PR_S_INITED | PR_S_READY)) {
+ raid->status |= AR_S_READY;
+ if (meta->raid.status & PR_S_DEGRADED)
+ raid->status |= AR_S_DEGRADED;
+ }
+ else
+ raid->status &= ~AR_S_READY;
/* convert disk flags to our internal types */
- for (disk = 0; disk < info->raid.total_disks; disk++) {
+ for (disk = 0; disk < meta->raid.total_disks; disk++) {
+ raid->disks[disk].dev = NULL;
raid->disks[disk].flags = 0;
- disksum += info->raid.disk[disk].flags;
- if (info->raid.disk[disk].flags & PR_F_ONLINE)
+ *((u_int64_t *)(raid->disks[disk].serial)) =
+ meta->raid.disk[disk].magic_0;
+ disksum += meta->raid.disk[disk].flags;
+ if (meta->raid.disk[disk].flags & PR_F_ONLINE)
raid->disks[disk].flags |= AR_DF_ONLINE;
- if (info->raid.disk[disk].flags & PR_F_ASSIGNED)
+ if (meta->raid.disk[disk].flags & PR_F_ASSIGNED)
raid->disks[disk].flags |= AR_DF_ASSIGNED;
- if (info->raid.disk[disk].flags & PR_F_SPARE) {
- raid->disks[disk].flags &= ~AR_DF_ONLINE;
+ if (meta->raid.disk[disk].flags & PR_F_SPARE) {
+ raid->disks[disk].flags &= ~(AR_DF_ONLINE | AR_DF_ASSIGNED);
raid->disks[disk].flags |= AR_DF_SPARE;
}
- if (info->raid.disk[disk].flags & (PR_F_REDIR | PR_F_DOWN))
+ if (meta->raid.disk[disk].flags & (PR_F_REDIR | PR_F_DOWN))
raid->disks[disk].flags &= ~AR_DF_ONLINE;
}
if (!disksum) {
+ device_printf(parent, "%s subdisks has no flags\n",
+ native ? "FreeBSD" : "Promise");
free(raidp[array], M_AR);
raidp[array] = NULL;
goto promise_out;
}
}
- if (info->raid.generation >= raid->generation) {
- 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;
- raid->disks[info->raid.disk_number].disk_sectors =
- info->raid.disk_sectors;
- if ((raid->disks[info->raid.disk_number].flags &
+ if (meta->raid.generation >= raid->generation) {
+ int disk_number = meta->raid.disk_number;
+
+ if (raid->disks[disk_number].flags && (meta->magic_0 ==
+ *((u_int64_t *)(raid->disks[disk_number].serial)))) {
+ raid->disks[disk_number].dev = parent;
+ raid->disks[disk_number].flags |= AR_DF_PRESENT;
+ raid->disks[disk_number].sectors = meta->raid.disk_sectors;
+ if ((raid->disks[disk_number].flags &
(AR_DF_PRESENT | AR_DF_ASSIGNED | AR_DF_ONLINE)) ==
(AR_DF_PRESENT | AR_DF_ASSIGNED | AR_DF_ONLINE)) {
- AD_SOFTC(raid->disks[info->raid.disk_number])->flags |=
- AD_F_RAID_SUBDISK;
+ ars->raid = raid;
+ ars->disk_number = disk_number;
retval = 1;
}
}
}
break;
}
+
promise_out:
- free(info, M_AR);
+ free(meta, M_AR);
return retval;
}
static int
-ar_promise_write_conf(struct ar_softc *rdp)
+ata_raid_promise_write_meta(struct ar_softc *rdp)
{
- struct promise_raid_conf *config;
+ struct promise_raid_conf *meta;
struct timeval timestamp;
u_int32_t *ckptr;
- int count, disk, drive;
- int local = rdp->flags & AR_F_FREEBSD_RAID;
+ int count, disk, drive, error = 0;
+
+ if (!(meta = (struct promise_raid_conf *)
+ malloc(sizeof(struct promise_raid_conf), M_AR, M_NOWAIT))) {
+ printf("ar%d: failed to allocate metadata storage\n", rdp->lun);
+ return ENOMEM;
+ }
rdp->generation++;
microtime(&timestamp);
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: %s write conf failed\n",
- rdp->lun, local ? "FreeBSD" : "Promise");
- return -1;
- }
for (count = 0; count < sizeof(struct promise_raid_conf); count++)
- *(((u_int8_t *)config) + count) = 255 - (count % 256);
-
- config->dummy_0 = 0x00020000;
- config->magic_0 = PR_MAGIC0(rdp->disks[disk]) | timestamp.tv_sec;
- config->magic_1 = timestamp.tv_sec >> 16;
- config->magic_2 = timestamp.tv_sec;
- config->raid.integrity = PR_I_VALID;
-
- config->raid.disk_number = disk;
- 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 (rdp->disks[disk].device->softc)
- config->raid.disk_sectors = PR_LBA(AD_SOFTC(rdp->disks[disk]));
- /*config->raid.disk_offset*/
- }
- config->raid.magic_0 = config->magic_0;
- config->raid.rebuild_lba = rdp->lock_start;
- config->raid.generation = rdp->generation;
-
- if (rdp->flags & AR_F_READY) {
- config->raid.flags = (PR_F_VALID | PR_F_ASSIGNED | PR_F_ONLINE);
- config->raid.status =
+ *(((u_int8_t *)meta) + count) = 255 - (count % 256);
+ meta->dummy_0 = 0x00020000;
+ meta->raid.disk_number = disk;
+
+ if ((rdp->disks[disk].flags & AR_DF_PRESENT) && rdp->disks[disk].dev) {
+ struct ata_device *atadev = device_get_softc(rdp->disks[disk].dev);
+ struct ata_channel *ch =
+ device_get_softc(device_get_parent(rdp->disks[disk].dev));
+
+ meta->raid.channel = ch->unit;
+ meta->raid.device = (atadev->unit != 0);
+ meta->raid.disk_sectors = rdp->disks[disk].sectors;
+ meta->raid.disk_offset = rdp->offset_sectors;
+ }
+ else {
+ meta->raid.channel = 0;
+ meta->raid.device = 0;
+ meta->raid.disk_sectors = 0;
+ meta->raid.disk_offset = 0;
+ }
+ meta->magic_0 = PR_MAGIC0(meta->raid) | timestamp.tv_sec;
+ meta->magic_1 = timestamp.tv_sec >> 16;
+ meta->magic_2 = timestamp.tv_sec;
+ meta->raid.integrity = PR_I_VALID;
+ meta->raid.magic_0 = meta->magic_0;
+ meta->raid.rebuild_lba = rdp->rebuild_lba;
+ meta->raid.generation = rdp->generation;
+
+ if (rdp->status & AR_S_READY) {
+ meta->raid.flags = (PR_F_VALID | PR_F_ASSIGNED | PR_F_ONLINE);
+ meta->raid.status =
(PR_S_VALID | PR_S_ONLINE | PR_S_INITED | PR_S_READY);
- if (rdp->flags & AR_F_DEGRADED)
- config->raid.status |= PR_S_DEGRADED;
+ if (rdp->status & AR_S_DEGRADED)
+ meta->raid.status |= PR_S_DEGRADED;
else
- config->raid.status |= PR_S_FUNCTIONAL;
+ meta->raid.status |= PR_S_FUNCTIONAL;
}
else {
- config->raid.flags = PR_F_DOWN;
- config->raid.status = 0;
+ meta->raid.flags = PR_F_DOWN;
+ meta->raid.status = 0;
}
- switch (rdp->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) {
- case AR_F_RAID0:
- config->raid.type = PR_T_RAID0;
+ switch (rdp->type) {
+ case AR_T_RAID0:
+ meta->raid.type = PR_T_RAID0;
break;
- case AR_F_RAID1:
- config->raid.type = PR_T_RAID1;
+ case AR_T_RAID1:
+ meta->raid.type = PR_T_RAID1;
break;
- case AR_F_RAID0 | AR_F_RAID1:
- config->raid.type = PR_T_RAID1;
+ case AR_T_RAID01:
+ meta->raid.type = PR_T_RAID1;
break;
- case AR_F_SPAN:
- config->raid.type = PR_T_SPAN;
+ case AR_T_RAID5:
+ meta->raid.type = PR_T_RAID5;
+ break;
+ case AR_T_SPAN:
+ meta->raid.type = PR_T_SPAN;
+ break;
+ case AR_T_JBOD:
+ meta->raid.type = PR_T_JBOD;
break;
}
- config->raid.total_disks = rdp->total_disks;
- config->raid.stripe_shift = ffs(rdp->interleave) - 1;
- config->raid.array_width = rdp->width;
- config->raid.array_number = rdp->lun;
- config->raid.total_sectors = rdp->total_sectors;
- config->raid.cylinders = rdp->cylinders - 1;
- config->raid.heads = rdp->heads - 1;
- config->raid.sectors = rdp->sectors;
- config->raid.magic_1 = (u_int64_t)config->magic_2<<16 | config->magic_1;
-
- bzero(&config->raid.disk, 8 * 12);
+ meta->raid.total_disks = rdp->total_disks;
+ meta->raid.stripe_shift = ffs(rdp->interleave) - 1;
+ meta->raid.array_width = rdp->width;
+ meta->raid.array_number = rdp->lun;
+ meta->raid.total_sectors = rdp->total_sectors;
+ meta->raid.cylinders = rdp->cylinders - 1;
+ meta->raid.heads = rdp->heads - 1;
+ meta->raid.sectors = rdp->sectors;
+ meta->raid.magic_1 = (u_int64_t)meta->magic_2<<16 | meta->magic_1;
+
+ bzero(&meta->raid.disk, 8 * 12);
for (drive = 0; drive < rdp->total_disks; drive++) {
- config->raid.disk[drive].flags = 0;
+ meta->raid.disk[drive].flags = 0;
if (rdp->disks[drive].flags & AR_DF_PRESENT)
- config->raid.disk[drive].flags |= PR_F_VALID;
+ meta->raid.disk[drive].flags |= PR_F_VALID;
if (rdp->disks[drive].flags & AR_DF_ASSIGNED)
- config->raid.disk[drive].flags |= PR_F_ASSIGNED;
+ meta->raid.disk[drive].flags |= PR_F_ASSIGNED;
if (rdp->disks[drive].flags & AR_DF_ONLINE)
- config->raid.disk[drive].flags |= PR_F_ONLINE;
+ meta->raid.disk[drive].flags |= PR_F_ONLINE;
else
if (rdp->disks[drive].flags & AR_DF_PRESENT)
- config->raid.disk[drive].flags = (PR_F_REDIR | PR_F_DOWN);
+ meta->raid.disk[drive].flags = (PR_F_REDIR | PR_F_DOWN);
if (rdp->disks[drive].flags & AR_DF_SPARE)
- config->raid.disk[drive].flags |= PR_F_SPARE;
- config->raid.disk[drive].dummy_0 = 0x0;
- if (rdp->disks[drive].device) {
- config->raid.disk[drive].channel =
- rdp->disks[drive].device->channel->unit;
- config->raid.disk[drive].device =
- (rdp->disks[drive].device->unit != 0);
+ meta->raid.disk[drive].flags |= PR_F_SPARE;
+ meta->raid.disk[drive].dummy_0 = 0x0;
+ if (rdp->disks[drive].dev) {
+ struct ata_channel *ch =
+ device_get_softc(device_get_parent(rdp->disks[drive].dev));
+ struct ata_device *atadev =
+ device_get_softc(rdp->disks[drive].dev);
+
+ meta->raid.disk[drive].channel = ch->unit;
+ meta->raid.disk[drive].device = (atadev->unit != 0);
}
- config->raid.disk[drive].magic_0 =
- PR_MAGIC0(rdp->disks[drive]) | timestamp.tv_sec;
+ meta->raid.disk[drive].magic_0 =
+ PR_MAGIC0(meta->raid.disk[drive]) | timestamp.tv_sec;
}
- if (rdp->disks[disk].device && rdp->disks[disk].device->softc &&
- !(rdp->disks[disk].device->flags & ATA_D_DETACHING)) {
+ if (rdp->disks[disk].dev) {
if ((rdp->disks[disk].flags & (AR_DF_PRESENT | AR_DF_ONLINE)) ==
(AR_DF_PRESENT | AR_DF_ONLINE)) {
- if (local)
- bcopy(ATA_MAGIC, config->promise_id, sizeof(ATA_MAGIC));
+ if (rdp->format == AR_F_FREEBSD_RAID)
+ bcopy(ATA_MAGIC, meta->promise_id, sizeof(ATA_MAGIC));
else
- bcopy(PR_MAGIC, config->promise_id, sizeof(PR_MAGIC));
+ bcopy(PR_MAGIC, meta->promise_id, sizeof(PR_MAGIC));
}
else
- bzero(config->promise_id, sizeof(config->promise_id));
- config->checksum = 0;
- for (ckptr = (int32_t *)config, count = 0; count < 511; count++)
- config->checksum += *ckptr++;
- 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)) {
- printf("ar%d: %s write conf failed\n",
- rdp->lun, local ? "FreeBSD" : "Promise");
- free(config, M_AR);
- return -1;
+ bzero(meta->promise_id, sizeof(meta->promise_id));
+ meta->checksum = 0;
+ for (ckptr = (int32_t *)meta, count = 0; count < 511; count++)
+ meta->checksum += *ckptr++;
+ if (ata_raid_rw(rdp->disks[disk].dev, PR_LBA(rdp->disks[disk].dev),
+ meta, sizeof(struct promise_raid_conf),
+ ATA_R_WRITE | ATA_R_DIRECT)) {
+ device_printf(rdp->disks[disk].dev, "write metadata failed\n");
+ error = EIO;
+ }
+ }
+ }
+ free(meta, M_AR);
+ return error;
+}
+
+/* Silicon Image Medley Metadata */
+static int
+ata_raid_sii_read_meta(device_t dev, struct ar_softc **raidp)
+{
+ struct ata_raid_subdisk *ars = device_get_softc(dev);
+ device_t parent = device_get_parent(dev);
+ struct sii_raid_conf *meta;
+ struct ar_softc *raid = NULL;
+ u_int16_t checksum, *ptr;
+ int array, count, disk, retval = 0;
+
+ if (!(meta = (struct sii_raid_conf *)
+ malloc(sizeof(struct sii_raid_conf), M_AR, M_NOWAIT | M_ZERO)))
+ return ENOMEM;
+
+ if (ata_raid_rw(parent, SII_LBA(parent),
+ meta, sizeof(struct sii_raid_conf), ATA_R_READ)) {
+ if (testing || bootverbose)
+ device_printf(parent, "Silicon Image read metadata failed\n");
+ goto sii_out;
+ }
+
+ /* check if this is a Silicon Image (Medley) RAID struct */
+ for (checksum = 0, ptr = (u_int16_t *)meta, count = 0; count < 160; count++)
+ checksum += *ptr++;
+ if (checksum) {
+ if (testing || bootverbose)
+ device_printf(parent, "Silicon Image check1 failed\n");
+ goto sii_out;
+ }
+
+ for (checksum = 0, ptr = (u_int16_t *)meta, count = 0; count < 256; count++)
+ checksum += *ptr++;
+ if (checksum != meta->checksum_1) {
+ if (testing || bootverbose)
+ device_printf(parent, "Silicon Image check2 failed\n");
+ goto sii_out;
+ }
+
+ /* check verison */
+ if (meta->version_major != 0x0002 ||
+ (meta->version_minor != 0x0000 && meta->version_minor != 0x0001)) {
+ if (testing || bootverbose)
+ device_printf(parent, "Silicon Image check3 failed\n");
+ goto sii_out;
+ }
+
+ if (testing || bootverbose)
+ ata_raid_sii_print_meta(meta);
+
+ /* now convert Silicon Image meta into our generic form */
+ for (array = 0; array < MAX_ARRAYS; array++) {
+ if (!raidp[array]) {
+ raidp[array] =
+ (struct ar_softc *)malloc(sizeof(struct ar_softc), M_AR,
+ M_NOWAIT | M_ZERO);
+ if (!raidp[array]) {
+ device_printf(parent, "failed to allocate metadata storage\n");
+ goto sii_out;
}
}
+ raid = raidp[array];
+ if (raid->format && (raid->format != AR_F_SII_RAID))
+ continue;
+
+ if (raid->format == AR_F_SII_RAID &&
+ (raid->magic_0 != *((u_int64_t *)meta->timestamp))) {
+ continue;
+ }
+
+ /* update our knowledge about the array config based on generation */
+ if (!meta->generation || meta->generation > raid->generation) {
+ switch (meta->type) {
+ case SII_T_RAID0:
+ raid->type = AR_T_RAID0;
+ break;
+
+ case SII_T_RAID1:
+ raid->type = AR_T_RAID1;
+ break;
+
+ case SII_T_RAID01:
+ raid->type = AR_T_RAID01;
+ break;
+
+ case SII_T_SPARE:
+ device_printf(parent, "Silicon Image SPARE disk\n");
+ free(raidp[array], M_AR);
+ raidp[array] = NULL;
+ goto sii_out;
+
+ default:
+ device_printf(parent,"Silicon Image unknown RAID type 0x%02x\n",
+ meta->type);
+ free(raidp[array], M_AR);
+ raidp[array] = NULL;
+ goto sii_out;
+ }
+ raid->magic_0 = *((u_int64_t *)meta->timestamp);
+ raid->format = AR_F_SII_RAID;
+ raid->generation = meta->generation;
+ raid->interleave = meta->stripe_sectors;
+ raid->width = (meta->raid0_disks != 0xff) ? meta->raid0_disks : 1;
+ raid->total_disks =
+ ((meta->raid0_disks != 0xff) ? meta->raid0_disks : 0) +
+ ((meta->raid1_disks != 0xff) ? meta->raid1_disks : 0);
+ raid->total_sectors = meta->total_sectors;
+ raid->heads = 255;
+ raid->sectors = 63;
+ raid->cylinders = raid->total_sectors / (63 * 255);
+ raid->offset_sectors = 0;
+ raid->rebuild_lba = meta->rebuild_lba;
+ raid->lun = array;
+ strncpy(raid->name, meta->name,
+ min(sizeof(raid->name), sizeof(meta->name)));
+
+ /* clear out any old info */
+ if (raid->generation) {
+ for (disk = 0; disk < raid->total_disks; disk++) {
+ raid->disks[disk].dev = NULL;
+ raid->disks[disk].flags = 0;
+ }
+ }
+ }
+ if (meta->generation >= raid->generation) {
+ /* XXX SOS add check for the right physical disk by serial# */
+ if (meta->status & SII_S_READY) {
+ int disk_number = (raid->type == AR_T_RAID01) ?
+ meta->raid1_ident + (meta->raid0_ident << 1) :
+ meta->disk_number;
+
+ raid->disks[disk_number].dev = parent;
+ raid->disks[disk_number].sectors =
+ raid->total_sectors / raid->total_disks;
+ raid->disks[disk_number].flags =
+ (AR_DF_ONLINE | AR_DF_PRESENT | AR_DF_ASSIGNED);
+ ars->raid = raid;
+ ars->disk_number = disk_number;
+ retval = 1;
+ }
+ }
+ break;
+ }
+
+sii_out:
+ free(meta, M_AR);
+ return retval;
+}
+
+static struct ata_request *
+ata_raid_init_request(struct ar_softc *rdp, struct bio *bio)
+{
+ struct ata_request *request;
+
+ if (!(request = ata_alloc_request())) {
+ printf("FAILURE - out of memory in ata_raid_init_request\n");
+ return 0;
+ }
+ request->timeout = 5;
+ request->retries = 2;
+ request->callback = ata_raid_done;
+ request->driver = rdp;
+ request->bio = bio;
+ switch (request->bio->bio_cmd) {
+ case BIO_READ:
+ request->flags = ATA_R_READ;
+ break;
+ case BIO_WRITE:
+ request->flags = ATA_R_WRITE;
+ break;
+ }
+ return request;
+}
+
+static int
+ata_raid_send_request(struct ata_request *request)
+{
+ struct ata_device *atadev = device_get_softc(request->dev);
+
+ request->transfersize = min(request->bytecount, atadev->max_iosize);
+ request->transfersize = DEV_BSIZE;
+ if (request->flags & ATA_R_READ) {
+ if (atadev->mode >= ATA_DMA) {
+ request->flags |= ATA_R_DMA;
+ request->u.ata.command = ATA_READ_DMA;
+ }
+ else if (atadev->max_iosize > DEV_BSIZE)
+ request->u.ata.command = ATA_READ_MUL;
else
- free(config, M_AR);
+ request->u.ata.command = ATA_READ;
}
+ else if (request->flags & ATA_R_WRITE) {
+ if (atadev->mode >= ATA_DMA) {
+ request->flags |= ATA_R_DMA;
+ request->u.ata.command = ATA_WRITE_DMA;
+ }
+ else if (atadev->max_iosize > DEV_BSIZE)
+ request->u.ata.command = ATA_WRITE_MUL;
+ else
+ request->u.ata.command = ATA_WRITE;
+ }
+ else {
+ device_printf(request->dev, "FAILURE - unknown IO operation\n");
+ ata_free_request(request);
+ return EIO;
+ }
+ request->flags |= (ATA_R_ORDERED | ATA_R_THREAD);
+ ata_queue_request(request);
return 0;
}
-static void
-ar_rw_done(struct bio *bp)
+static int
+ata_raid_rw(device_t dev, u_int64_t lba, void *data, u_int bcount, int flags)
{
- free(bp->bio_data, M_AR);
- free(bp, M_AR);
+ struct ata_device *atadev = device_get_softc(dev);
+ struct ata_request *request;
+ int error;
+
+ if (bcount % DEV_BSIZE) {
+ device_printf(dev, "FAILURE - transfers must be modulo sectorsize\n");
+ return ENOMEM;
+ }
+
+ if (!(request = ata_alloc_request())) {
+ device_printf(dev, "FAILURE - out of memory in ata_raid_rw\n");
+ return ENOMEM;
+ }
+
+ /* setup request */
+ request->dev = dev;
+ request->timeout = 10;
+ request->retries = 0;
+ request->data = data;
+ request->bytecount = bcount;
+ request->transfersize = DEV_BSIZE;
+ request->u.ata.lba = lba;
+ request->u.ata.count = request->bytecount / DEV_BSIZE;
+ request->flags = flags;
+
+ if (flags & ATA_R_READ) {
+ if (atadev->mode >= ATA_DMA) {
+ request->u.ata.command = ATA_READ_DMA;
+ request->flags |= ATA_R_DMA;
+ }
+ else
+ request->u.ata.command = ATA_READ;
+ ata_queue_request(request);
+ }
+ else if (flags & ATA_R_WRITE) {
+ if (atadev->mode >= ATA_DMA) {
+ request->u.ata.command = ATA_WRITE_DMA;
+ request->flags |= ATA_R_DMA;
+ }
+ else
+ request->u.ata.command = ATA_WRITE;
+ ata_queue_request(request);
+ }
+ else {
+ device_printf(dev, "FAILURE - unknown IO operation\n");
+ request->result = EIO;
+ }
+ error = request->result;
+ ata_free_request(request);
+ return error;
+}
+
+/*
+ * module handeling
+ */
+static int
+ata_raid_subdisk_probe(device_t dev)
+{
+ device_quiet(dev);
+ return 0;
}
static int
-ar_rw(struct ad_softc *adp, u_int32_t lba, int count, caddr_t data, int flags)
+ata_raid_subdisk_attach(device_t dev)
{
- struct bio *bp;
- int retry = 0, error = 0;
-
- if (!(bp = (struct bio *)malloc(sizeof(struct bio), M_AR, M_NOWAIT|M_ZERO)))
- return 1;
- bp->bio_disk = adp->disk;
- 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;
+ struct ata_raid_subdisk *ars = device_get_softc(dev);
- AR_STRATEGY(bp);
+ ars->raid = NULL;
+ ars->disk_number = -1;
+ return ata_raid_read_metadata(dev);
+}
- if (flags & AR_WAIT) {
- while ((retry++ < (15*hz/10)) && (error = !(bp->bio_flags & BIO_DONE)))
- error = tsleep(bp, PRIBIO, "arrw", 10);
- if (!error && bp->bio_flags & BIO_ERROR)
- error = bp->bio_error;
- free(bp, M_AR);
+static int
+ata_raid_subdisk_detach(device_t dev)
+{
+ struct ata_raid_subdisk *ars = device_get_softc(dev);
+
+ if (ars->raid) {
+ ars->raid->disks[ars->disk_number].flags &=
+ ~(AR_DF_PRESENT | AR_DF_ONLINE);
+ ars->raid->disks[ars->disk_number].dev = NULL;
+ ata_raid_config_changed(ars->raid, 1);
+ ars->raid = NULL;
+ ars->disk_number = -1;
}
- return error;
+ return 0;
}
-static struct ata_device *
-ar_locate_disk(int diskno)
+static device_method_t ata_raid_sub_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_probe, ata_raid_subdisk_probe),
+ DEVMETHOD(device_attach, ata_raid_subdisk_attach),
+ DEVMETHOD(device_detach, ata_raid_subdisk_detach),
+ { 0, 0 }
+};
+
+static driver_t ata_raid_sub_driver = {
+ "subdisk",
+ ata_raid_sub_methods,
+ sizeof(struct ata_raid_subdisk)
+};
+
+DRIVER_MODULE(subdisk, ad, ata_raid_sub_driver, ata_raid_sub_devclass, NULL, NULL);
+
+static int
+ata_raid_module_event_handler(module_t mod, int what, void *arg)
{
- struct ata_channel *ch;
- int ctlr;
+ int i;
- for (ctlr = 0; ctlr < devclass_get_maxunit(ata_devclass); ctlr++) {
- if (!(ch = devclass_get_softc(ata_devclass, ctlr)))
- continue;
- if (ch->devices & ATA_ATA_MASTER)
- if (ch->device[MASTER].softc &&
- ((struct ad_softc *)(ch->device[MASTER].softc))->lun == diskno)
- return &ch->device[MASTER];
- if (ch->devices & ATA_ATA_SLAVE)
- if (ch->device[SLAVE].softc &&
- ((struct ad_softc *)(ch->device[SLAVE].softc))->lun == diskno)
- return &ch->device[SLAVE];
- }
- return NULL;
+ switch (what) {
+ case MOD_LOAD:
+ printf("ATA PseudoRAID loaded\n");
+#if 0
+ /* setup table to hold metadata for all ATA PseudoRAID arrays */
+ ata_raid_arrays = malloc(sizeof(struct ar_soft *) * MAX_ARRAYS,
+ M_AR, M_NOWAIT | M_ZERO);
+ if (!ata_raid_arrays) {
+ printf("ataraid: no memory for metadata storage\n");
+ return ENOMEM;
+ }
+#endif
+ /* attach found PseudoRAID arrays */
+ for (i = 0; i < MAX_ARRAYS; i++) {
+ struct ar_softc *rdp = ata_raid_arrays[i];
+
+ if (!rdp || !rdp->format)
+ continue;
+ if (testing || bootverbose)
+ ata_raid_print_meta(rdp);
+ ata_raid_attach(rdp, 0);
+ }
+ ata_ioctl_func = ata_raid_ioctl;
+ return 0;
+
+ case MOD_UNLOAD:
+ /* detach found PseudoRAID arrays */
+ for (i = 0; i < MAX_ARRAYS; i++) {
+ struct ar_softc *rdp = ata_raid_arrays[i];
+
+ if (!rdp || !rdp->status)
+ continue;
+ disk_destroy(rdp->disk);
+ }
+ printf("ATA PseudoRAID unloaded\n");
+#if 0
+ free(ata_raid_arrays, M_AR);
+#endif
+ ata_ioctl_func = NULL;
+ return 0;
+
+ default:
+ return EOPNOTSUPP;
+ }
+}
+
+static moduledata_t ata_raid_moduledata =
+ { "ataraid", ata_raid_module_event_handler, NULL };
+DECLARE_MODULE(ata, ata_raid_moduledata, SI_SUB_RAID, SI_ORDER_FIRST);
+MODULE_VERSION(ataraid, 1);
+MODULE_DEPEND(ataraid, ata, 1, 1, 1);
+MODULE_DEPEND(ataraid, ad, 1, 1, 1);
+
+static char *
+ata_raid_format(struct ar_softc *rdp)
+{
+ switch (rdp->format) {
+ case AR_F_FREEBSD_RAID: return "FreeBSD PseudoRAID";
+ case AR_F_ADAPTEC_RAID: return "Adaptec HostRAID";
+ case AR_F_HPTV2_RAID: return "HighPoint v2 RocketRAID";
+ case AR_F_HPTV3_RAID: return "HighPoint v3 RocketRAID";
+ case AR_F_INTEL_RAID: return "Intel MatrixRAID";
+ case AR_F_ITE_RAID: return "Integrated Technology Express";
+ case AR_F_LSIV2_RAID: return "LSILogic v2 MegaRAID";
+ case AR_F_LSIV3_RAID: return "LSILogic v3 MegaRAID";
+ case AR_F_PROMISE_RAID: return "Promise Fasttrak";
+ case AR_F_SII_RAID: return "Silicon Image Medley";
+ default: return "UNKNOWN";
+ }
+}
+
+static char *
+ata_raid_type(struct ar_softc *rdp)
+{
+ switch (rdp->type) {
+ case AR_T_JBOD: return "JBOD";
+ case AR_T_SPAN: return "SPAN";
+ case AR_T_RAID0: return "RAID0";
+ case AR_T_RAID1: return "RAID1";
+ case AR_T_RAID3: return "RAID3";
+ case AR_T_RAID4: return "RAID4";
+ case AR_T_RAID5: return "RAID5";
+ case AR_T_RAID01: return "RAID0+1";
+ default: return "UNKNOWN";
+ }
+}
+
+static char *
+ata_raid_flags(struct ar_softc *rdp)
+{
+ switch (rdp->status & (AR_S_READY | AR_S_DEGRADED | AR_S_REBUILDING)) {
+ case AR_S_READY: return "READY";
+ case AR_S_READY | AR_S_DEGRADED: return "DEGRADED";
+ case AR_S_READY | AR_S_REBUILDING:
+ case AR_S_READY | AR_S_DEGRADED | AR_S_REBUILDING: return "REBUILDING";
+ default: return "BROKEN";
+ }
+}
+
+/* debugging gunk */
+static void
+ata_raid_print_meta(struct ar_softc *raid)
+{
+ int i;
+
+ printf("********** ATA PseudoRAID ar%d Metadata **********\n", raid->lun);
+ printf("=================================================\n");
+ printf("format %s\n", ata_raid_format(raid));
+ printf("type %s\n", ata_raid_type(raid));
+ printf("flags 0x%02x %b\n", raid->status, raid->status,
+ "\20\3REBUILDING\2DEGRADED\1READY\n");
+ printf("magic_0 0x%016llx\n",(unsigned long long)raid->magic_0);
+ printf("magic_1 0x%016llx\n",(unsigned long long)raid->magic_1);
+ printf("generation %u\n", raid->generation);
+ printf("total_sectors %llu\n",
+ (unsigned long long)raid->total_sectors);
+ printf("offset_sectors %llu\n",
+ (unsigned long long)raid->offset_sectors);
+ printf("heads %u\n", raid->heads);
+ printf("sectors %u\n", raid->sectors);
+ printf("cylinders %u\n", raid->cylinders);
+ printf("width %u\n", raid->width);
+ printf("interleave %u\n", raid->interleave);
+ printf("total_disks %u\n", raid->total_disks);
+ for (i = 0; i < raid->total_disks; i++) {
+ printf(" disk %d: flags = 0x%02x %b\n", i, raid->disks[i].flags,
+ raid->disks[i].flags, "\20\4ONLINE\3SPARE\2ASSIGNED\1PRESENT\n");
+ if (raid->disks[i].dev) {
+ printf(" ");
+ device_printf(raid->disks[i].dev, " sectors %lld\n",
+ (long long)raid->disks[i].sectors);
+ }
+ }
+ printf("=================================================\n");
+}
+
+static char *
+ata_raid_adaptec_type(int type)
+{
+ static char buffer[16];
+
+ switch (type) {
+ case ADP_T_RAID0: return "RAID0";
+ case ADP_T_RAID1: return "RAID1";
+ default: sprintf(buffer, "UNKNOWN 0x%02x", type);
+ return buffer;
+ }
+}
+
+static void
+ata_raid_adaptec_print_meta(struct adaptec_raid_conf *meta)
+{
+ int i;
+
+ printf("********* ATA Adaptec HostRAID Metadata *********\n");
+ printf("magic_0 <0x%08x>\n", be32toh(meta->magic_0));
+ printf("generation 0x%08x\n", be32toh(meta->generation));
+ printf("dummy_0 0x%04x\n", be16toh(meta->dummy_0));
+ printf("total_configs %u\n", be16toh(meta->total_configs));
+ printf("dummy_1 0x%04x\n", be16toh(meta->dummy_1));
+ printf("checksum 0x%04x\n", be16toh(meta->checksum));
+ printf("dummy_2 0x%08x\n", be32toh(meta->dummy_2));
+ printf("dummy_3 0x%08x\n", be32toh(meta->dummy_3));
+ printf("flags 0x%08x\n", be32toh(meta->flags));
+ printf("timestamp 0x%08x\n", be32toh(meta->timestamp));
+ printf("dummy_4 0x%08x 0x%08x 0x%08x 0x%08x\n",
+ be32toh(meta->dummy_4[0]), be32toh(meta->dummy_4[1]),
+ be32toh(meta->dummy_4[2]), be32toh(meta->dummy_4[3]));
+ printf("dummy_5 0x%08x 0x%08x 0x%08x 0x%08x\n",
+ be32toh(meta->dummy_5[0]), be32toh(meta->dummy_5[1]),
+ be32toh(meta->dummy_5[2]), be32toh(meta->dummy_5[3]));
+
+ for (i = 0; i < be16toh(meta->total_configs); i++) {
+ printf(" %d total_disks %u\n", i,
+ be16toh(meta->configs[i].disk_number));
+ printf(" %d generation %u\n", i,
+ be16toh(meta->configs[i].generation));
+ printf(" %d magic_0 0x%08x\n", i,
+ be32toh(meta->configs[i].magic_0));
+ printf(" %d dummy_0 0x%02x\n", i, meta->configs[i].dummy_0);
+ printf(" %d type %s\n", i,
+ ata_raid_adaptec_type(meta->configs[i].type));
+ printf(" %d dummy_1 0x%02x\n", i, meta->configs[i].dummy_1);
+ printf(" %d flags %d\n", i,
+ be32toh(meta->configs[i].flags));
+ printf(" %d dummy_2 0x%02x\n", i, meta->configs[i].dummy_2);
+ printf(" %d dummy_3 0x%02x\n", i, meta->configs[i].dummy_3);
+ printf(" %d dummy_4 0x%02x\n", i, meta->configs[i].dummy_4);
+ printf(" %d dummy_5 0x%02x\n", i, meta->configs[i].dummy_5);
+ printf(" %d disk_number %u\n", i,
+ be32toh(meta->configs[i].disk_number));
+ printf(" %d dummy_6 0x%08x\n", i,
+ be32toh(meta->configs[i].dummy_6));
+ printf(" %d sectors %u\n", i,
+ be32toh(meta->configs[i].sectors));
+ printf(" %d stripe_shift %u\n", i,
+ be16toh(meta->configs[i].stripe_shift));
+ printf(" %d dummy_7 0x%08x\n", i,
+ be32toh(meta->configs[i].dummy_7));
+ printf(" %d dummy_8 0x%08x 0x%08x 0x%08x 0x%08x\n", i,
+ be32toh(meta->configs[i].dummy_8[0]),
+ be32toh(meta->configs[i].dummy_8[1]),
+ be32toh(meta->configs[i].dummy_8[2]),
+ be32toh(meta->configs[i].dummy_8[3]));
+ printf(" %d name <%s>\n", i, meta->configs[i].name);
+ }
+ printf("magic_1 <0x%08x>\n", be32toh(meta->magic_1));
+ printf("magic_2 <0x%08x>\n", be32toh(meta->magic_2));
+ printf("magic_3 <0x%08x>\n", be32toh(meta->magic_3));
+ printf("magic_4 <0x%08x>\n", be32toh(meta->magic_4));
+ printf("=================================================\n");
+}
+
+static char *
+ata_raid_hptv2_type(int type)
+{
+ static char buffer[16];
+
+ switch (type) {
+ case HPTV2_T_RAID0: return "RAID0";
+ case HPTV2_T_RAID1: return "RAID1";
+ case HPTV2_T_RAID01_RAID0: return "RAID01_RAID0";
+ case HPTV2_T_SPAN: return "SPAN";
+ case HPTV2_T_RAID_3: return "RAID3";
+ case HPTV2_T_RAID_5: return "RAID5";
+ case HPTV2_T_JBOD: return "JBOD";
+ case HPTV2_T_RAID01_RAID1: return "RAID01_RAID1";
+ default: sprintf(buffer, "UNKNOWN 0x%02x", type);
+ return buffer;
+ }
+}
+
+static void
+ata_raid_hptv2_print_meta(struct hptv2_raid_conf *meta)
+{
+ int i;
+
+ printf("****** ATA Highpoint V2 RocketRAID Metadata *****\n");
+ printf("magic 0x%08x\n", meta->magic);
+ printf("magic_0 0x%08x\n", meta->magic_0);
+ printf("magic_1 0x%08x\n", meta->magic_1);
+ printf("order 0x%08x\n", meta->order);
+ printf("array_width %u\n", meta->array_width);
+ printf("stripe_shift %u\n", meta->stripe_shift);
+ printf("type %s\n", ata_raid_hptv2_type(meta->type));
+ printf("disk_number %u\n", meta->disk_number);
+ printf("total_sectors %u\n", meta->total_sectors);
+ printf("disk_mode 0x%08x\n", meta->disk_mode);
+ printf("boot_mode 0x%08x\n", meta->boot_mode);
+ printf("boot_disk 0x%02x\n", meta->boot_disk);
+ printf("boot_protect 0x%02x\n", meta->boot_protect);
+ printf("log_entries 0x%02x\n", meta->error_log_entries);
+ printf("log_index 0x%02x\n", meta->error_log_index);
+ if (meta->error_log_entries) {
+ printf(" timestamp reason disk status sectors lba\n");
+ for (i = meta->error_log_index;
+ i < meta->error_log_index + meta->error_log_entries; i++)
+ printf(" 0x%08x 0x%02x 0x%02x 0x%02x 0x%02x 0x%08x\n",
+ meta->errorlog[i%32].timestamp,
+ meta->errorlog[i%32].reason,
+ meta->errorlog[i%32].disk, meta->errorlog[i%32].status,
+ meta->errorlog[i%32].sectors, meta->errorlog[i%32].lba);
+ }
+ printf("rebuild_lba 0x%08x\n", meta->rebuild_lba);
+ printf("dummy_1 0x%02x\n", meta->dummy_1);
+ printf("name_1 <%.15s>\n", meta->name_1);
+ printf("dummy_2 0x%02x\n", meta->dummy_2);
+ printf("name_2 <%.15s>\n", meta->name_2);
+ printf("=================================================\n");
+}
+
+static char *
+ata_raid_hptv3_type(int type)
+{
+ static char buffer[16];
+
+ switch (type) {
+ case HPTV3_T_SPARE: return "SPARE";
+ case HPTV3_T_JBOD: return "JBOD";
+ case HPTV3_T_SPAN: return "SPAN";
+ case HPTV3_T_RAID0: return "RAID0";
+ case HPTV3_T_RAID1: return "RAID1";
+ case HPTV3_T_RAID3: return "RAID3";
+ case HPTV3_T_RAID5: return "RAID5";
+ default: sprintf(buffer, "UNKNOWN 0x%02x", type);
+ return buffer;
+ }
}
static void
-ar_print_conf(struct ar_softc *config)
+ata_raid_hptv3_print_meta(struct hptv3_raid_conf *meta)
{
int i;
- printf("lun %d\n", config->lun);
- printf("magic_0 0x%08x\n", config->magic_0);
- printf("magic_1 0x%08x\n", config->magic_1);
- printf("flags 0x%02x %b\n", config->flags, config->flags,
- "\20\16HIGHPOINT\15PROMISE\13REBUILDING\12DEGRADED\11READY\3SPAN\2RAID1\1RAID0\n");
- printf("total_disks %d\n", config->total_disks);
- printf("generation %d\n", config->generation);
- printf("width %d\n", config->width);
- printf("heads %d\n", config->heads);
- printf("sectors %d\n", config->sectors);
- printf("cylinders %d\n", config->cylinders);
- printf("total_sectors %lld\n", (long long)config->total_sectors);
- printf("interleave %d\n", config->interleave);
- printf("reserved %d\n", config->reserved);
- printf("offset %d\n", config->offset);
- for (i = 0; i < config->total_disks; i++) {
- printf("disk %d: flags = 0x%02x %b\n", i, config->disks[i].flags, config->disks[i].flags, "\20\4ONLINE\3SPARE\2ASSIGNED\1PRESENT\n");
- if (config->disks[i].device)
- printf(" %s\n", config->disks[i].device->name);
- printf(" sectors %lld\n", (long long)config->disks[i].disk_sectors);
+ printf("****** ATA Highpoint V3 RocketRAID Metadata *****\n");
+ printf("magic 0x%08x\n", meta->magic);
+ printf("magic_0 0x%08x\n", meta->magic_0);
+ printf("checksum_0 0x%02x\n", meta->checksum_0);
+ printf("mode 0x%02x\n", meta->mode);
+ printf("user_mode 0x%02x\n", meta->user_mode);
+ printf("config_entries 0x%02x\n", meta->config_entries);
+ for (i = 0; i < meta->config_entries; i++) {
+ printf("config %d:\n", i);
+ printf(" total_sectors %llu\n",
+ (unsigned long long)(meta->configs[0].total_sectors +
+ ((u_int64_t)meta->configs_high[0].total_sectors << 32)));
+ printf(" type %s\n",
+ ata_raid_hptv3_type(meta->configs[i].type));
+ printf(" total_disks %u\n", meta->configs[i].total_disks);
+ printf(" disk_number %u\n", meta->configs[i].disk_number);
+ printf(" stripe_shift %u\n", meta->configs[i].stripe_shift);
+ printf(" status %b\n", meta->configs[i].status,
+ "\20\2RAID5\1NEED_REBUILD\n");
+ printf(" critical_disks %u\n", meta->configs[i].critical_disks);
+ printf(" rebuild_lba %llu\n",
+ (unsigned long long)(meta->configs_high[0].rebuild_lba +
+ ((u_int64_t)meta->configs_high[0].rebuild_lba << 32)));
}
+ printf("name <%.16s>\n", meta->name);
+ printf("timestamp 0x%08x\n", meta->timestamp);
+ printf("description <%.16s>\n", meta->description);
+ printf("creator <%.16s>\n", meta->creator);
+ printf("checksum_1 0x%02x\n", meta->checksum_1);
+ printf("dummy_0 0x%02x\n", meta->dummy_0);
+ printf("dummy_1 0x%02x\n", meta->dummy_1);
+ printf("flags %b\n", meta->flags,
+ "\20\4RCACHE\3WCACHE\2NCQ\1TCQ\n");
+ printf("=================================================\n");
+}
+
+static char *
+ata_raid_intel_type(int type)
+{
+ static char buffer[16];
+
+ switch (type) {
+ case INTEL_T_RAID0: return "RAID0";
+ case INTEL_T_RAID1: return "RAID1";
+ default: sprintf(buffer, "UNKNOWN 0x%02x", type);
+ return buffer;
+ }
+}
+
+static void
+ata_raid_intel_print_meta(struct intel_raid_conf *meta)
+{
+ struct intel_raid_mapping *map;
+ int i, j;
+
+ printf("********* ATA Intel MatrixRAID Metadata *********\n");
+ printf("intel_id <%.24s>\n", meta->intel_id);
+ printf("version <%.6s>\n", meta->version);
+ printf("checksum 0x%08x\n", meta->checksum);
+ printf("config_size 0x%08x\n", meta->config_size);
+ printf("config_id 0x%08x\n", meta->config_id);
+ printf("generation 0x%08x\n", meta->generation);
+ printf("total_disks %u\n", meta->total_disks);
+ printf("total_volumes %u\n", meta->total_volumes);
+ printf("DISK# serial disk_sectors disk_id flags\n");
+ for (i = 0; i < meta->total_disks; i++ ) {
+ printf(" %d <%.16s> %u 0x%08x 0x%08x\n", i,
+ meta->disk[i].serial, meta->disk[i].sectors,
+ meta->disk[i].id, meta->disk[i].flags);
+ }
+ map = (struct intel_raid_mapping *)&meta->disk[meta->total_disks];
+ for (j = 0; j < meta->total_volumes; j++) {
+ printf("name %.16s\n", map->name);
+ printf("total_sectors %llu\n",
+ (unsigned long long)map->total_sectors);
+ printf("state %u\n", map->state);
+ printf("reserved %u\n", map->reserved);
+ printf("offset %u\n", map->offset);
+ printf("disk_sectors %u\n", map->disk_sectors);
+ printf("stripe_count %u\n", map->stripe_count);
+ printf("stripe_sectors %u\n", map->stripe_sectors);
+ printf("status %u\n", map->status);
+ printf("type %s\n", ata_raid_intel_type(map->type));
+ printf("total_disks %u\n", map->total_disks);
+ for (i = 0; i < map->total_disks; i++ ) {
+ printf(" disk %d at disk_idx 0x%08x\n", i, map->disk_idx[i]);
+ }
+ map = (struct intel_raid_mapping *)&map->disk_idx[i];
+ }
+ printf("=================================================\n");
+}
+
+static char *
+ata_raid_ite_type(int type)
+{
+ static char buffer[16];
+
+ switch (type) {
+ case ITE_T_RAID0: return "RAID0";
+ case ITE_T_RAID1: return "RAID1";
+ case ITE_T_RAID01: return "RAID0+1";
+ case ITE_T_SPAN: return "SPAN";
+ default: sprintf(buffer, "UNKNOWN 0x%02x", type);
+ return buffer;
+ }
+}
+
+static void
+ata_raid_ite_print_meta(struct ite_raid_conf *meta)
+{
+ printf("*** ATA Integrated Technology Express Metadata **\n");
+ printf("ite_id <%.40s>\n", meta->ite_id);
+ printf("timestamp_0 %04x/%02x/%02x %02x:%02x:%02x.%02x\n",
+ *((u_int16_t *)meta->timestamp_0), meta->timestamp_0[2],
+ meta->timestamp_0[3], meta->timestamp_0[5], meta->timestamp_0[4],
+ meta->timestamp_0[7], meta->timestamp_0[6]);
+ printf("total_sectors %lld\n",
+ (unsigned long long)meta->total_sectors);
+ printf("type %s\n", ata_raid_ite_type(meta->type));
+ printf("stripe_1kblocks %u\n", meta->stripe_1kblocks);
+ printf("timestamp_1 %04x/%02x/%02x %02x:%02x:%02x.%02x\n",
+ *((u_int16_t *)meta->timestamp_1), meta->timestamp_1[2],
+ meta->timestamp_1[3], meta->timestamp_1[5], meta->timestamp_1[4],
+ meta->timestamp_1[7], meta->timestamp_1[6]);
+ printf("stripe_sectors %u\n", meta->stripe_sectors);
+ printf("array_width %u\n", meta->array_width);
+ printf("disk_number %u\n", meta->disk_number);
+ printf("disk_sectors %u\n", meta->disk_sectors);
+ printf("=================================================\n");
+}
+
+static char *
+ata_raid_lsiv2_type(int type)
+{
+ static char buffer[16];
+
+ switch (type) {
+ case LSIV2_T_RAID0: return "RAID0";
+ case LSIV2_T_RAID1: return "RAID1";
+ case LSIV2_T_SPARE: return "SPARE";
+ default: sprintf(buffer, "UNKNOWN 0x%02x", type);
+ return buffer;
+ }
+}
+
+static void
+ata_raid_lsiv2_print_meta(struct lsiv2_raid_conf *meta)
+{
+ int i;
+
+ printf("******* ATA LSILogic V2 MegaRAID Metadata *******\n");
+ printf("lsi_id <%s>\n", meta->lsi_id);
+ printf("dummy_0 0x%02x\n", meta->dummy_0);
+ printf("flags 0x%02x\n", meta->flags);
+ printf("version 0x%04x\n", meta->version);
+ printf("config_entries 0x%02x\n", meta->config_entries);
+ printf("raid_count 0x%02x\n", meta->raid_count);
+ printf("total_disks 0x%02x\n", meta->total_disks);
+ printf("dummy_1 0x%02x\n", meta->dummy_1);
+ printf("dummy_2 0x%04x\n", meta->dummy_2);
+ for (i = 0; i < meta->config_entries; i++) {
+ printf(" type %s\n",
+ ata_raid_lsiv2_type(meta->configs[i].raid.type));
+ printf(" dummy_0 %02x\n", meta->configs[i].raid.dummy_0);
+ printf(" stripe_sectors %u\n",
+ meta->configs[i].raid.stripe_sectors);
+ printf(" array_width %u\n",
+ meta->configs[i].raid.array_width);
+ printf(" disk_count %u\n", meta->configs[i].raid.disk_count);
+ printf(" config_offset %u\n",
+ meta->configs[i].raid.config_offset);
+ printf(" dummy_1 %u\n", meta->configs[i].raid.dummy_1);
+ printf(" flags %02x\n", meta->configs[i].raid.flags);
+ printf(" total_sectors %u\n",
+ meta->configs[i].raid.total_sectors);
+ }
+ printf("disk_number 0x%02x\n", meta->disk_number);
+ printf("raid_number 0x%02x\n", meta->raid_number);
+ printf("timestamp 0x%08x\n", meta->timestamp);
+ printf("=================================================\n");
+}
+
+static char *
+ata_raid_lsiv3_type(int type)
+{
+ static char buffer[16];
+
+ switch (type) {
+ case LSIV3_T_RAID0: return "RAID0";
+ case LSIV3_T_RAID1: return "RAID1";
+ default: sprintf(buffer, "UNKNOWN 0x%02x", type);
+ return buffer;
+ }
+}
+
+static void
+ata_raid_lsiv3_print_meta(struct lsiv3_raid_conf *meta)
+{
+ int i;
+
+ printf("******* ATA LSILogic V3 MegaRAID Metadata *******\n");
+ printf("lsi_id <%.6s>\n", meta->lsi_id);
+ printf("dummy_0 0x%04x\n", meta->dummy_0);
+ printf("version 0x%04x\n", meta->version);
+ printf("dummy_0 0x%04x\n", meta->dummy_1);
+ printf("RAID configs:\n");
+ for (i = 0; i < 8; i++) {
+ if (meta->raid[i].total_disks) {
+ printf("%02d stripe_pages %u\n", i,
+ meta->raid[i].stripe_pages);
+ printf("%02d type %s\n", i,
+ ata_raid_lsiv3_type(meta->raid[i].type));
+ printf("%02d total_disks %u\n", i,
+ meta->raid[i].total_disks);
+ printf("%02d array_width %u\n", i,
+ meta->raid[i].array_width);
+ printf("%02d sectors %u\n", i, meta->raid[i].sectors);
+ printf("%02d offset %u\n", i, meta->raid[i].offset);
+ printf("%02d device 0x%02x\n", i,
+ meta->raid[i].device);
+ }
+ }
+ printf("DISK configs:\n");
+ for (i = 0; i < 6; i++) {
+ if (meta->disk[i].disk_sectors) {
+ printf("%02d disk_sectors %u\n", i,
+ meta->disk[i].disk_sectors);
+ printf("%02d flags 0x%02x\n", i, meta->disk[i].flags);
+ }
+ }
+ printf("device 0x%02x\n", meta->device);
+ printf("timestamp 0x%08x\n", meta->timestamp);
+ printf("checksum_1 0x%02x\n", meta->checksum_1);
+ printf("=================================================\n");
+}
+
+static char *
+ata_raid_promise_type(int type)
+{
+ static char buffer[16];
+
+ switch (type) {
+ case PR_T_RAID0: return "RAID0";
+ case PR_T_RAID1: return "RAID1";
+ case PR_T_RAID3: return "RAID3";
+ case PR_T_RAID5: return "RAID5";
+ case PR_T_SPAN: return "SPAN";
+ default: sprintf(buffer, "UNKNOWN 0x%02x", type);
+ return buffer;
+ }
+}
+
+static void
+ata_raid_promise_print_meta(struct promise_raid_conf *meta)
+{
+ int i;
+
+ printf("********* ATA Promise FastTrak Metadata *********\n");
+ printf("promise_id <%s>\n", meta->promise_id);
+ printf("dummy_0 0x%08x\n", meta->dummy_0);
+ printf("magic_0 0x%016llx\n",(unsigned long long)meta->magic_0);
+ printf("magic_1 0x%04x\n", meta->magic_1);
+ printf("magic_2 0x%08x\n", meta->magic_2);
+ printf("integrity 0x%08x %b\n", meta->raid.integrity,
+ meta->raid.integrity, "\20\10VALID\n" );
+ printf("flags 0x%02x %b\n",
+ meta->raid.flags, meta->raid.flags,
+ "\20\10READY\7DOWN\6REDIR\5DUPLICATE\4SPARE"
+ "\3ASSIGNED\2ONLINE\1VALID\n");
+ printf("disk_number %d\n", meta->raid.disk_number);
+ printf("channel 0x%02x\n", meta->raid.channel);
+ printf("device 0x%02x\n", meta->raid.device);
+ printf("magic_0 0x%016llx\n",
+ (unsigned long long)meta->raid.magic_0);
+ printf("disk_offset %u\n", meta->raid.disk_offset);
+ printf("disk_sectors %u\n", meta->raid.disk_sectors);
+ printf("rebuild_lba 0x%08x\n", meta->raid.rebuild_lba);
+ printf("generation 0x%04x\n", meta->raid.generation);
+ printf("status 0x%02x %b\n",
+ meta->raid.status, meta->raid.status,
+ "\20\6MARKED\5DEGRADED\4READY\3INITED\2ONLINE\1VALID\n");
+ printf("type %s\n", ata_raid_promise_type(meta->raid.type));
+ printf("total_disks %u\n", meta->raid.total_disks);
+ printf("stripe_shift %u\n", meta->raid.stripe_shift);
+ printf("array_width %u\n", meta->raid.array_width);
+ printf("array_number %u\n", meta->raid.array_number);
+ printf("total_sectors %u\n", meta->raid.total_sectors);
+ printf("cylinders %u\n", meta->raid.cylinders);
+ printf("heads %u\n", meta->raid.heads);
+ printf("sectors %u\n", meta->raid.sectors);
+ printf("magic_1 0x%016llx\n",
+ (unsigned long long)meta->raid.magic_1);
+ printf("DISK# flags dummy_0 channel device magic_0\n");
+ for (i = 0; i < 8; i++) {
+ printf(" %d %b 0x%02x 0x%02x 0x%02x ",
+ i, meta->raid.disk[i].flags,
+ "\20\10READY\7DOWN\6REDIR\5DUPLICATE\4SPARE"
+ "\3ASSIGNED\2ONLINE\1VALID\n", meta->raid.disk[i].dummy_0,
+ meta->raid.disk[i].channel, meta->raid.disk[i].device);
+ printf("0x%016llx\n",
+ (unsigned long long)meta->raid.disk[i].magic_0);
+ }
+ printf("checksum 0x%08x\n", meta->checksum);
+ printf("=================================================\n");
+}
+
+static char *
+ata_raid_sii_type(int type)
+{
+ static char buffer[16];
+
+ switch (type) {
+ case SII_T_RAID0: return "RAID0";
+ case SII_T_RAID1: return "RAID1";
+ case SII_T_RAID01: return "RAID0+1";
+ case SII_T_SPARE: return "SPARE";
+ default: sprintf(buffer, "UNKNOWN 0x%02x", type);
+ return buffer;
+ }
+}
+
+static void
+ata_raid_sii_print_meta(struct sii_raid_conf *meta)
+{
+ printf("******* ATA Silicon Image Medley Metadata *******\n");
+ printf("total_sectors %llu\n",
+ (unsigned long long)meta->total_sectors);
+ printf("dummy_0 0x%04x\n", meta->dummy_0);
+ printf("dummy_1 0x%04x\n", meta->dummy_1);
+ printf("controller_pci_id 0x%08x\n", meta->controller_pci_id);
+ printf("version_minor 0x%04x\n", meta->version_minor);
+ printf("version_major 0x%04x\n", meta->version_major);
+ printf("timestamp 20%02x/%02x/%02x %02x:%02x:%02x\n",
+ meta->timestamp[5], meta->timestamp[4], meta->timestamp[3],
+ meta->timestamp[2], meta->timestamp[1], meta->timestamp[0]);
+ printf("stripe_sectors %u\n", meta->stripe_sectors);
+ printf("dummy_2 0x%04x\n", meta->dummy_2);
+ printf("disk_number %u\n", meta->disk_number);
+ printf("type %s\n", ata_raid_sii_type(meta->type));
+ printf("raid0_disks %u\n", meta->raid0_disks);
+ printf("raid0_ident %u\n", meta->raid0_ident);
+ printf("raid1_disks %u\n", meta->raid1_disks);
+ printf("raid1_ident %u\n", meta->raid1_ident);
+ printf("rebuild_lba %llu\n", (unsigned long long)meta->rebuild_lba);
+ printf("generation 0x%08x\n", meta->generation);
+ printf("status 0x%02x %b\n",
+ meta->status, meta->status,
+ "\20\1READY\n");
+ printf("base_raid1_position %02x\n", meta->base_raid1_position);
+ printf("base_raid0_position %02x\n", meta->base_raid0_position);
+ printf("position %02x\n", meta->position);
+ printf("dummy_3 %04x\n", meta->dummy_3);
+ printf("name <%.16s>\n", meta->name);
+ printf("checksum_0 0x%04x\n", meta->checksum_0);
+ printf("checksum_1 0x%04x\n", meta->checksum_1);
+ printf("=================================================\n");
}
diff --git a/sys/dev/ata/ata-raid.h b/sys/dev/ata/ata-raid.h
index 7a3e7a9..31c785d 100644
--- a/sys/dev/ata/ata-raid.h
+++ b/sys/dev/ata/ata-raid.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2000 - 2003 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 2000 - 2005 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,273 +29,614 @@
*/
/* misc defines */
-#define MAX_ARRAYS 16
-#define MAX_DISKS 16
-#define AR_PROXIMITY 2048
-#define AR_READ 0x01
-#define AR_WRITE 0x02
-#define AR_WAIT 0x04
-#define AR_STRATEGY(x) (x)->bio_disk->d_strategy((x))
-#define AD_SOFTC(x) ((struct ad_softc *)(x.device->softc))
-#define ATA_MAGIC "FreeBSD ATA driver RAID "
-
-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
-#define AR_DF_ASSIGNED 0x00000002
-#define AR_DF_SPARE 0x00000004
-#define AR_DF_ONLINE 0x00000008
+#define MAX_ARRAYS 16
+#define MAX_DISKS 16
+#define AR_PROXIMITY 2048 /* how many sectors is "close" */
+
+#define ATA_MAGIC "FreeBSD ATA driver RAID "
+
+struct ata_raid_subdisk {
+ struct ar_softc *raid;
+ int disk_number;
};
+/* ATA PseudoRAID Metadata */
struct ar_softc {
- int lun;
- int32_t magic_0; /* ident for this array */
- int32_t magic_1; /* ident for this array */
- int flags;
-#define AR_F_SPAN 0x00000001
-#define AR_F_RAID0 0x00000002
-#define AR_F_RAID1 0x00000004
-#define AR_F_RAID3 0x00000008
-#define AR_F_RAID5 0x00000010
-
-#define AR_F_READY 0x00000100
-#define AR_F_DEGRADED 0x00000200
-#define AR_F_REBUILDING 0x00000400
-#define AR_F_TOGGLE 0x00000800
-
-#define AR_F_FREEBSD_RAID 0x00010000
-#define AR_F_PROMISE_RAID 0x00020000
-#define AR_F_HIGHPOINT_RAID 0x00040000
-#define AR_F_ADAPTEC_RAID 0x00080000
-#define AR_F_LSI_RAID 0x00100000
-#define AR_F_INTEL_RAID 0x00200000
-#define AR_F_QTEC_RAID 0x00400000
-
- int total_disks; /* number of disks in this array */
- int generation; /* generation of this array */
- struct ar_disk disks[MAX_DISKS+1]; /* ptr to each disk in array */
- int width; /* array width in disks */
- u_int16_t heads;
- u_int16_t sectors;
- u_int32_t cylinders;
- u_int64_t total_sectors;
- int interleave; /* interleave in blocks */
- int reserved; /* sectors that are NOT to be used */
- int offset; /* offset from start of disk */
- u_int64_t lock_start; /* start of locked area for rebuild */
- u_int64_t lock_end; /* end of locked area for rebuild */
- struct disk *disk; /* disklabel/slice stuff */
- struct proc *pid; /* rebuilder process id */
-};
+ int lun; /* logical unit number of this RAID */
+ u_int8_t name[32]; /* name of array if any */
+ u_int64_t magic_0; /* magic for this array */
+ u_int64_t magic_1; /* magic for this array */
+ int type;
+#define AR_T_JBOD 0x0001
+#define AR_T_SPAN 0x0002
+#define AR_T_RAID0 0x0004
+#define AR_T_RAID1 0x0008
+#define AR_T_RAID01 0x0010
+#define AR_T_RAID3 0x0020
+#define AR_T_RAID4 0x0040
+#define AR_T_RAID5 0x0080
+
+ int status;
+#define AR_S_READY 0x0001
+#define AR_S_DEGRADED 0x0002
+#define AR_S_REBUILDING 0x0004
+
+ int format;
+#define AR_F_FREEBSD_RAID 0x0001
+#define AR_F_ADAPTEC_RAID 0x0002
+#define AR_F_HPTV2_RAID 0x0004
+#define AR_F_HPTV3_RAID 0x0008
+#define AR_F_INTEL_RAID 0x0010
+#define AR_F_ITE_RAID 0x0020
+#define AR_F_LSIV2_RAID 0x0040
+#define AR_F_LSIV3_RAID 0x0080
+#define AR_F_PROMISE_RAID 0x0100
+#define AR_F_SII_RAID 0x0200
+#define AR_F_FORMAT_MASK 0x03ff
-struct ar_buf {
- struct bio bp; /* must be first element! */
- struct bio *org;
- struct ar_buf *mirror;
- int drive;
- int flags;
-#define AB_F_DONE 0x01
+ u_int generation; /* generation of this array */
+ u_int64_t total_sectors;
+ u_int64_t offset_sectors; /* offset from start of disk */
+ u_int16_t heads;
+ u_int16_t sectors;
+ u_int32_t cylinders;
+ u_int width; /* array width in disks */
+ u_int interleave; /* interleave in blocks */
+ u_int total_disks; /* number of disks in this array */
+ struct ar_disk {
+ device_t dev;
+ u_int8_t serial[16]; /* serial # of physical disk */
+ u_int64_t sectors; /* useable sectors on this disk */
+ off_t last_lba; /* last lba used (for performance) */
+ u_int flags;
+#define AR_DF_PRESENT 0x0001 /* this HW pos has a disk present */
+#define AR_DF_ASSIGNED 0x0002 /* this HW pos assigned to an array */
+#define AR_DF_SPARE 0x0004 /* this HW pos is a spare */
+#define AR_DF_ONLINE 0x0008 /* this HW pos is online and in use */
+
+ } disks[MAX_DISKS];
+ int toggle; /* performance hack for RAID1's */
+ u_int64_t rebuild_lba; /* rebuild progress indicator */
+ struct mtx lock; /* metadata lock */
+ struct disk *disk; /* disklabel/slice stuff */
+ struct proc *pid; /* rebuilder process id */
};
+/* Adaptec HostRAID Metadata */
+#define ADP_LBA(dev) \
+ (((struct ad_softc *)device_get_ivars(dev))->total_secs - 17)
+
+/* note all entries are big endian */
+struct adaptec_raid_conf {
+ u_int32_t magic_0; /* 0x0000 */
+#define ADP_MAGIC_0 0xc4650790
+
+ u_int32_t generation;
+ u_int16_t dummy_0;
+ u_int16_t total_configs;
+ u_int16_t dummy_1;
+ u_int16_t checksum;
+ u_int32_t dummy_2; /* 0x0010 */
+ u_int32_t dummy_3;
+ u_int32_t flags;
+ u_int32_t timestamp;
+ u_int32_t dummy_4[4]; /* 0x0020 */
+ u_int32_t dummy_5[4]; /* 0x0030 */
+ struct { /* 0x0040 */
+ u_int16_t total_disks;
+ u_int16_t generation;
+ u_int32_t magic_0;
+ u_int8_t dummy_0;
+ u_int8_t type;
+#define ADP_T_RAID0 0x00
+#define ADP_T_RAID1 0x01
+ u_int8_t dummy_1;
+ u_int8_t flags;
+
+ u_int8_t dummy_2;
+ u_int8_t dummy_3;
+ u_int8_t dummy_4;
+ u_int8_t dummy_5;
-#define HPT_LBA 9
-
-struct highpoint_raid_conf {
- int8_t filler1[32];
- u_int32_t magic;
-#define HPT_MAGIC_OK 0x5a7816f0
-#define HPT_MAGIC_BAD 0x5a7816fd
-
- u_int32_t magic_0;
- u_int32_t magic_1;
- u_int32_t order;
-#define HPT_O_RAID0 0x01
-#define HPT_O_RAID1 0x02
-#define HPT_O_OK 0x04
-
- u_int8_t array_width;
- u_int8_t stripe_shift;
- u_int8_t type;
-#define HPT_T_RAID0 0x00
-#define HPT_T_RAID1 0x01
-#define HPT_T_RAID01_RAID0 0x02
-#define HPT_T_SPAN 0x03
-#define HPT_T_RAID_3 0x04
-#define HPT_T_RAID_5 0x05
-#define HPT_T_SINGLEDISK 0x06
-#define HPT_T_RAID01_RAID1 0x07
-
- u_int8_t disk_number;
- u_int32_t total_sectors;
- u_int32_t disk_mode;
- u_int32_t boot_mode;
- u_int8_t boot_disk;
- u_int8_t boot_protect;
- u_int8_t error_log_entries;
- u_int8_t error_log_index;
+ u_int32_t disk_number;
+ u_int32_t dummy_6;
+ u_int32_t sectors;
+ u_int16_t stripe_shift;
+ u_int16_t dummy_7;
+
+ u_int32_t dummy_8[4];
+ u_int8_t name[16];
+ } configs[127]; /* x 0x40 bytes */
+
+ u_int32_t dummy_6[13]; /* 0x2000 */
+ u_int32_t magic_1;
+#define ADP_MAGIC_1 0x9ff85009
+ u_int32_t dummy_7[3];
+ u_int32_t magic_2;
+ u_int32_t dummy_8[46];
+ u_int32_t magic_3;
+#define ADP_MAGIC_3 0x4d545044
+ u_int32_t magic_4;
+#define ADP_MAGIC_4 0x9ff85009
+ u_int32_t dummy_9[62];
+} __packed;
+
+
+/* Highpoint V2 RocketRAID Metadata */
+#define HPTV2_LBA(dev) 9
+
+struct hptv2_raid_conf {
+ int8_t filler1[32];
+ u_int32_t magic;
+#define HPTV2_MAGIC_OK 0x5a7816f0
+#define HPTV2_MAGIC_BAD 0x5a7816fd
+
+ u_int32_t magic_0;
+ u_int32_t magic_1;
+ u_int32_t order;
+#define HPTV2_O_RAID0 0x01
+#define HPTV2_O_RAID1 0x02
+#define HPTV2_O_OK 0x04
+
+ u_int8_t array_width;
+ u_int8_t stripe_shift;
+ u_int8_t type;
+#define HPTV2_T_RAID0 0x00
+#define HPTV2_T_RAID1 0x01
+#define HPTV2_T_RAID01_RAID0 0x02
+#define HPTV2_T_SPAN 0x03
+#define HPTV2_T_RAID_3 0x04
+#define HPTV2_T_RAID_5 0x05
+#define HPTV2_T_JBOD 0x06
+#define HPTV2_T_RAID01_RAID1 0x07
+
+ u_int8_t disk_number;
+ u_int32_t total_sectors;
+ u_int32_t disk_mode;
+ u_int32_t boot_mode;
+ u_int8_t boot_disk;
+ u_int8_t boot_protect;
+ u_int8_t error_log_entries;
+ u_int8_t error_log_index;
struct {
- u_int32_t timestamp;
- u_int8_t reason;
-#define HPT_R_REMOVED 0xfe
-#define HPT_R_BROKEN 0xff
+ u_int32_t timestamp;
+ u_int8_t reason;
+#define HPTV2_R_REMOVED 0xfe
+#define HPTV2_R_BROKEN 0xff
- u_int8_t disk;
- u_int8_t status;
- u_int8_t sectors;
- u_int32_t lba;
+ u_int8_t disk;
+ u_int8_t status;
+ u_int8_t sectors;
+ u_int32_t lba;
} errorlog[32];
- int8_t filler2[16];
- u_int32_t rebuild_lba;
- u_int8_t dummy_1;
- u_int8_t name_1[15];
- u_int8_t dummy_2;
- u_int8_t name_2[15];
- int8_t filler3[8];
+ int8_t filler2[16];
+ u_int32_t rebuild_lba;
+ u_int8_t dummy_1;
+ u_int8_t name_1[15];
+ u_int8_t dummy_2;
+ u_int8_t name_2[15];
+ int8_t filler3[8];
} __packed;
-#define LSI_LBA(adp) (adp->total_secs - 1)
+/* Highpoint V3 RocketRAID Metadata */
+#define HPTV3_LBA(dev) \
+ (((struct ad_softc *)device_get_ivars(dev))->total_secs - 11)
+
+struct hptv3_raid_conf {
+ u_int32_t magic;
+#define HPTV3_MAGIC 0x5a7816f3
-struct lsi_raid_conf {
- u_int8_t lsi_id[6];
-#define LSI_MAGIC "$XIDE$"
+ u_int32_t magic_0;
+ u_int8_t checksum_0;
+ u_int8_t mode;
+#define HPTV3_BOOT_MARK 0x01
+#define HPTV3_USER_MODE 0x02
+
+ u_int8_t user_mode;
+ u_int8_t config_entries;
+ struct {
+ u_int32_t total_sectors;
+ u_int8_t type;
+#define HPTV3_T_SPARE 0x00
+#define HPTV3_T_JBOD 0x03
+#define HPTV3_T_SPAN 0x04
+#define HPTV3_T_RAID0 0x05
+#define HPTV3_T_RAID1 0x06
+#define HPTV3_T_RAID3 0x07
+#define HPTV3_T_RAID5 0x08
+
+ u_int8_t total_disks;
+ u_int8_t disk_number;
+ u_int8_t stripe_shift;
+ u_int16_t status;
+#define HPTV3_T_NEED_REBUILD 0x01
+#define HPTV3_T_RAID5_FLAG 0x02
+
+ u_int16_t critical_disks;
+ u_int32_t rebuild_lba;
+ } __packed configs[2];
+ u_int8_t name[16];
+ u_int32_t timestamp;
+ u_int8_t description[64];
+ u_int8_t creator[16];
+ u_int8_t checksum_1;
+ u_int8_t dummy_0;
+ u_int8_t dummy_1;
+ u_int8_t flags;
+#define HPTV3_T_ENABLE_TCQ 0x01
+#define HPTV3_T_ENABLE_NCQ 0x02
+#define HPTV3_T_ENABLE_WCACHE 0x04
+#define HPTV3_T_ENABLE_RCACHE 0x08
+
+ struct {
+ u_int32_t total_sectors;
+ u_int32_t rebuild_lba;
+ } __packed configs_high[2];
+ u_int32_t filler[87];
+} __packed;
+
+
+/* Intel MatrixRAID Metadata */
+#define INTEL_LBA(dev) \
+ (((struct ad_softc *)device_get_ivars(dev))->total_secs - 2)
+
+struct intel_raid_conf {
+ u_int8_t intel_id[24];
+#define INTEL_MAGIC "Intel Raid ISM Cfg Sig. "
+
+ u_int8_t version[6];
+ u_int8_t dummy_0[2];
+ u_int32_t checksum;
+ u_int32_t config_size;
+ u_int32_t config_id;
+ u_int32_t generation;
+ u_int32_t dummy_1[2];
+ u_int8_t total_disks;
+ u_int8_t total_volumes;
+ u_int8_t dummy_2[2];
+ u_int32_t filler_0[39];
+ struct {
+ u_int8_t serial[16];
+ u_int32_t sectors;
+ u_int32_t id;
+ u_int32_t flags;
+#define INTEL_F_SPARE 0x01
+#define INTEL_F_ASSIGNED 0x02
+#define INTEL_F_DOWN 0x04
+#define INTEL_F_ONLINE 0x08
+
+ u_int32_t filler[5];
+ } __packed disk[1];
+ u_int32_t filler_1[62];
+} __packed;
+
+struct intel_raid_mapping {
+ u_int8_t name[16];
+ u_int64_t total_sectors __packed;
+ u_int32_t state;
+ u_int32_t reserved;
+ u_int32_t filler_1[20];
+ u_int32_t offset;
+ u_int32_t disk_sectors;
+ u_int32_t stripe_count;
+ u_int16_t stripe_sectors;
+ u_int8_t status;
+#define INTEL_S_READY 0x00
+#define INTEL_S_DISABLED 0x01
+#define INTEL_S_DEGRADED 0x02
+#define INTEL_S_FAILURE 0x03
+
+ u_int8_t type;
+#define INTEL_T_RAID0 0x00
+#define INTEL_T_RAID1 0x01
+
+ u_int8_t total_disks;
+ u_int8_t dummy_2[3];
+ u_int32_t filler_2[7];
+ u_int32_t disk_idx[1];
+} __packed;
- u_int8_t dummy_1;
- u_int8_t flags;
- u_int8_t version[2];
- u_int8_t config_entries;
- u_int8_t raid_count;
- u_int8_t total_disks;
- u_int8_t dummy_d;
- u_int8_t dummy_e;
- u_int8_t dummy_f;
+
+/* Integrated Technology Express Metadata */
+#define ITE_LBA(dev) \
+ (((struct ad_softc *)device_get_ivars(dev))->total_secs - 2)
+
+struct ite_raid_conf {
+ u_int32_t filler_1[5];
+ u_int8_t timestamp_0[8]; /* BCD coded y:Y:M:D:m:h:f:s */
+ u_int32_t dummy_1;
+ u_int32_t filler_2[5];
+ u_int16_t filler_3;
+ u_int8_t ite_id[40]; /* byte swapped */
+#define ITE_MAGIC "Integrated Technology Express Inc "
+
+ u_int16_t filler_4;
+ u_int32_t filler_5[6];
+ u_int32_t dummy_2;
+ u_int32_t dummy_3;
+ u_int32_t filler_6[12];
+ u_int32_t dummy_4;
+ u_int32_t filler_7[5];
+ u_int64_t total_sectors __packed;
+ u_int32_t filler_8[12];
+
+ u_int16_t filler_9; /* 0x100 */
+ u_int8_t type;
+#define ITE_T_RAID0 0x00
+#define ITE_T_RAID1 0x01
+#define ITE_T_RAID01 0x02
+#define ITE_T_SPAN 0x03
+
+ u_int8_t filler_10;
+ u_int32_t dummy_5[8];
+ u_int8_t stripe_1kblocks;
+ u_int8_t filler_11[3];
+ u_int32_t filler_12[54];
+
+ u_int32_t dummy_6[4]; /* 0x200 */
+ u_int8_t timestamp_1[8]; /* same as timestamp_0 */
+ u_int32_t filler_13[9];
+ u_int8_t stripe_sectors;
+ u_int8_t filler_14[3];
+ u_int8_t array_width;
+ u_int8_t filler_15[3];
+ u_int32_t filler_16;
+ u_int8_t filler_17;
+ u_int8_t disk_number;
+ u_int32_t disk_sectors;
+ u_int16_t filler_18;
+ u_int32_t dummy_7[4];
+ u_int32_t filler_20[104];
+} __packed;
+
+
+/* LSILogic V2 MegaRAID Metadata */
+#define LSIV2_LBA(dev) \
+ (((struct ad_softc *)device_get_ivars(dev))->total_secs - 1)
+
+struct lsiv2_raid_conf {
+ u_int8_t lsi_id[6];
+#define LSIV2_MAGIC "$XIDE$"
+
+ u_int8_t dummy_0;
+ u_int8_t flags;
+ u_int16_t version;
+ u_int8_t config_entries;
+ u_int8_t raid_count;
+ u_int8_t total_disks;
+ u_int8_t dummy_1;
+ u_int16_t dummy_2;
union {
struct {
- u_int8_t type;
-#define LSI_R_RAID0 0x01
-#define LSI_R_RAID1 0x02
-#define LSI_R_SPARE 0x08
-
- u_int8_t dummy_1;
- u_int16_t stripe_size;
- u_int8_t raid_width;
- u_int8_t disk_count;
- u_int8_t config_offset;
- u_int8_t dummy_7;
- u_int8_t flags;
-#define LSI_R_DEGRADED 0x02
-
- u_int32_t total_sectors;
- u_int8_t filler[3];
+ u_int8_t type;
+#define LSIV2_T_RAID0 0x01
+#define LSIV2_T_RAID1 0x02
+#define LSIV2_T_SPARE 0x08
+
+ u_int8_t dummy_0;
+ u_int16_t stripe_sectors;
+ u_int8_t array_width;
+ u_int8_t disk_count;
+ u_int8_t config_offset;
+ u_int8_t dummy_1;
+ u_int8_t flags;
+#define LSIV2_R_DEGRADED 0x02
+
+ u_int32_t total_sectors;
+ u_int8_t filler[3];
} __packed raid;
struct {
- u_int8_t device;
-#define LSI_D_MASTER 0x00
-#define LSI_D_SLAVE 0x01
-#define LSI_D_CHANNEL0 0x00
-#define LSI_D_CHANNEL1 0x10
-#define LSI_D_NONE 0xff
-
- u_int8_t dummy_1;
- u_int32_t disk_sectors;
- u_int8_t disk_number;
- u_int8_t raid_number;
- u_int8_t flags;
-#define LSI_D_GONE 0x02
-
- u_int8_t filler[7];
+ u_int8_t device;
+#define LSIV2_D_MASTER 0x00
+#define LSIV2_D_SLAVE 0x01
+#define LSIV2_D_CHANNEL0 0x00
+#define LSIV2_D_CHANNEL1 0x10
+#define LSIV2_D_NONE 0xff
+
+ u_int8_t dummy_0;
+ u_int32_t disk_sectors;
+ u_int8_t disk_number;
+ u_int8_t raid_number;
+ u_int8_t flags;
+#define LSIV2_D_GONE 0x02
+
+ u_int8_t filler[7];
} __packed disk;
} configs[30];
- u_int8_t disk_number;
- u_int8_t raid_number;
- u_int32_t timestamp;
- u_int8_t filler[10];
+ u_int8_t disk_number;
+ u_int8_t raid_number;
+ u_int32_t timestamp;
+ u_int8_t filler[10];
+} __packed;
+
+
+/* LSILogic V3 MegaRAID Metadata */
+#define LSIV3_LBA(dev) \
+ (((struct ad_softc *)device_get_ivars(dev))->total_secs - 4)
+
+struct lsiv3_raid_conf {
+ u_int32_t magic_0; /* 0xa0203200 */
+ u_int32_t filler_0[3];
+ u_int8_t magic_1[4]; /* "SATA" */
+ u_int32_t filler_1[40];
+ u_int32_t dummy_0; /* 0x0d000003 */
+ u_int32_t filler_2[7];
+ u_int32_t dummy_1; /* 0x0d000003 */
+ u_int32_t filler_3[70];
+ u_int8_t magic_2[8]; /* "$_ENQ$31" */
+ u_int8_t filler_4[7];
+ u_int8_t checksum_0;
+ u_int8_t filler_5[512*2];
+ u_int8_t lsi_id[6];
+#define LSIV3_MAGIC "$_IDE$"
+
+ u_int16_t dummy_2; /* 0x33de for OK disk */
+ u_int16_t version; /* 0x0131 for this version */
+ u_int16_t dummy_3; /* 0x0440 always */
+ u_int32_t filler_6;
+
+ struct {
+ u_int16_t stripe_pages;
+ u_int8_t type;
+#define LSIV3_T_RAID0 0x00
+#define LSIV3_T_RAID1 0x01
+
+ u_int8_t dummy_0;
+ u_int8_t total_disks;
+ u_int8_t array_width;
+ u_int8_t filler_0[10];
+
+ u_int32_t sectors;
+ u_int16_t dummy_1;
+ u_int32_t offset;
+ u_int16_t dummy_2;
+ u_int8_t device;
+#define LSIV3_D_DEVICE 0x01
+#define LSIV3_D_CHANNEL 0x10
+
+ u_int8_t dummy_3;
+ u_int8_t dummy_4;
+ u_int8_t dummy_5;
+ u_int8_t filler_1[16];
+ } __packed raid[8];
+ struct {
+ u_int32_t disk_sectors;
+ u_int32_t dummy_0;
+ u_int32_t dummy_1;
+ u_int8_t dummy_2;
+ u_int8_t dummy_3;
+ u_int8_t flags;
+#define LSIV3_D_MIRROR 0x00
+#define LSIV3_D_STRIPE 0xff
+ u_int8_t dummy_4;
+ } __packed disk[6];
+ u_int8_t filler_7[7];
+ u_int8_t device;
+ u_int32_t timestamp;
+ u_int8_t filler_8[3];
+ u_int8_t checksum_1;
} __packed;
-#define PR_LBA(adp) \
- (((adp->total_secs / (adp->heads * adp->sectors)) * \
- adp->heads * adp->sectors) - adp->sectors)
+/* Promise FastTrak Metadata */
+#define PR_LBA(dev) \
+ (((struct ad_softc *)device_get_ivars(dev))->total_secs - 63)
+#if 0
+ (((((struct ad_softc *)device_get_ivars(dev))->total_secs / (((struct ad_softc *)device_get_ivars(dev))->heads * ((struct ad_softc *)device_get_ivars(dev))->sectors)) * ((struct ad_softc *)device_get_ivars(dev))->heads * ((struct ad_softc *)device_get_ivars(dev))->sectors) - ((struct ad_softc *)device_get_ivars(dev))->sectors)
+#endif
struct promise_raid_conf {
- char promise_id[24];
-#define PR_MAGIC "Promise Technology, Inc."
-
- u_int32_t dummy_0;
- u_int64_t magic_0;
-#define PR_MAGIC0(x) (x.device ? ((u_int64_t)x.device->channel->unit<<48) | \
- ((u_int64_t)(x.device->unit != 0) << 56) : 0)
- u_int16_t magic_1;
- u_int32_t magic_2;
- u_int8_t filler1[470];
+ char promise_id[24];
+#define PR_MAGIC "Promise Technology, Inc."
+
+ u_int32_t dummy_0;
+ u_int64_t magic_0;
+#define PR_MAGIC0(x) (((u_int64_t)(x.channel) << 48) | \
+ ((u_int64_t)(x.device != 0) << 56))
+ u_int16_t magic_1;
+ u_int32_t magic_2;
+ u_int8_t filler1[470];
struct {
- u_int32_t integrity;
-#define PR_I_VALID 0x00000080
-
- u_int8_t flags;
-#define PR_F_VALID 0x00000001
-#define PR_F_ONLINE 0x00000002
-#define PR_F_ASSIGNED 0x00000004
-#define PR_F_SPARE 0x00000008
-#define PR_F_DUPLICATE 0x00000010
-#define PR_F_REDIR 0x00000020
-#define PR_F_DOWN 0x00000040
-#define PR_F_READY 0x00000080
-
- u_int8_t disk_number;
- u_int8_t channel;
- u_int8_t device;
- u_int64_t magic_0 __packed;
- u_int32_t disk_offset;
- u_int32_t disk_sectors;
- u_int32_t rebuild_lba;
- u_int16_t generation;
- u_int8_t status;
-#define PR_S_VALID 0x01
-#define PR_S_ONLINE 0x02
-#define PR_S_INITED 0x04
-#define PR_S_READY 0x08
-#define PR_S_DEGRADED 0x10
-#define PR_S_MARKED 0x20
-#define PR_S_FUNCTIONAL 0x80
-
- u_int8_t type;
-#define PR_T_RAID0 0x00
-#define PR_T_RAID1 0x01
-#define PR_T_RAID3 0x02
-#define PR_T_RAID5 0x04
-#define PR_T_SPAN 0x08
-
- u_int8_t total_disks;
- u_int8_t stripe_shift;
- u_int8_t array_width;
- u_int8_t array_number;
- u_int32_t total_sectors;
- u_int16_t cylinders;
- u_int8_t heads;
- u_int8_t sectors;
- int64_t magic_1 __packed;
+ u_int32_t integrity;
+#define PR_I_VALID 0x00000080
+
+ u_int8_t flags;
+#define PR_F_VALID 0x00000001
+#define PR_F_ONLINE 0x00000002
+#define PR_F_ASSIGNED 0x00000004
+#define PR_F_SPARE 0x00000008
+#define PR_F_DUPLICATE 0x00000010
+#define PR_F_REDIR 0x00000020
+#define PR_F_DOWN 0x00000040
+#define PR_F_READY 0x00000080
+
+ u_int8_t disk_number;
+ u_int8_t channel;
+ u_int8_t device;
+ u_int64_t magic_0 __packed;
+ u_int32_t disk_offset;
+ u_int32_t disk_sectors;
+ u_int32_t rebuild_lba;
+ u_int16_t generation;
+ u_int8_t status;
+#define PR_S_VALID 0x01
+#define PR_S_ONLINE 0x02
+#define PR_S_INITED 0x04
+#define PR_S_READY 0x08
+#define PR_S_DEGRADED 0x10
+#define PR_S_MARKED 0x20
+#define PR_S_FUNCTIONAL 0x80
+
+ u_int8_t type;
+#define PR_T_RAID0 0x00
+#define PR_T_RAID1 0x01
+#define PR_T_RAID3 0x02
+#define PR_T_RAID5 0x04
+#define PR_T_SPAN 0x08
+#define PR_T_JBOD 0x10
+
+ u_int8_t total_disks;
+ u_int8_t stripe_shift;
+ u_int8_t array_width;
+ u_int8_t array_number;
+ u_int32_t total_sectors;
+ u_int16_t cylinders;
+ u_int8_t heads;
+ u_int8_t sectors;
+ u_int64_t magic_1 __packed;
struct {
- u_int8_t flags;
- u_int8_t dummy_0;
- u_int8_t channel;
- u_int8_t device;
- u_int64_t magic_0 __packed;
+ u_int8_t flags;
+ u_int8_t dummy_0;
+ u_int8_t channel;
+ u_int8_t device;
+ u_int64_t magic_0 __packed;
} disk[8];
} raid;
- int32_t filler2[346];
- u_int32_t checksum;
+ int32_t filler2[346];
+ u_int32_t checksum;
} __packed;
-int ata_raiddisk_attach(struct ad_softc *);
-int ata_raiddisk_detach(struct ad_softc *);
-void ata_raid_attach(void);
-int ata_raid_create(struct raid_setup *);
-int ata_raid_delete(int);
-int ata_raid_status(int, struct raid_status *);
-int ata_raid_addspare(int, int);
-int ata_raid_rebuild(int);
+
+/* Silicon Image Medley Metadata */
+#define SII_LBA(dev) \
+ ( ((struct ad_softc *)device_get_ivars(dev))->total_secs - 1)
+
+struct sii_raid_conf {
+ u_int16_t ata_params_00_53[54];
+ u_int64_t total_sectors;
+ u_int16_t ata_params_58_79[70];
+ u_int16_t dummy_0;
+ u_int16_t dummy_1;
+ u_int32_t controller_pci_id;
+ u_int16_t version_minor;
+ u_int16_t version_major;
+ u_int8_t timestamp[6]; /* BCD coded s:m:h:D:M:Y */
+ u_int16_t stripe_sectors;
+ u_int16_t dummy_2;
+ u_int8_t disk_number;
+ u_int8_t type;
+#define SII_T_RAID0 0x00
+#define SII_T_RAID1 0x01
+#define SII_T_RAID01 0x02
+#define SII_T_SPARE 0x03
+
+ u_int8_t raid0_disks;
+ u_int8_t raid0_ident;
+ u_int8_t raid1_disks;
+ u_int8_t raid1_ident;
+ u_int64_t rebuild_lba;
+ u_int32_t generation;
+ u_int8_t status;
+#define SII_S_READY 0x01
+
+ u_int8_t base_raid1_position;
+ u_int8_t base_raid0_position;
+ u_int8_t position;
+ u_int16_t dummy_3;
+ u_int8_t name[16];
+ u_int16_t checksum_0;
+ int8_t filler1[190];
+ u_int16_t checksum_1; /* sum of all 128 shorts == 0 */
+} __packed;
diff --git a/sys/dev/ata/atapi-cd.c b/sys/dev/ata/atapi-cd.c
index 4a7df80..7f7efa7 100644
--- a/sys/dev/ata/atapi-cd.c
+++ b/sys/dev/ata/atapi-cd.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2004 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2005 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/ata.h>
#include <sys/kernel.h>
+#include <sys/module.h>
#include <sys/malloc.h>
#include <sys/proc.h>
#include <sys/bio.h>
@@ -52,49 +53,47 @@ __FBSDID("$FreeBSD$");
#include <geom/geom.h>
#include <dev/ata/ata-all.h>
#include <dev/ata/atapi-cd.h>
+#include <ata_if.h>
/* prototypes */
-static void acd_detach(struct ata_device *);
-static void acd_start(struct ata_device *);
-static struct acd_softc *acd_init_lun(struct ata_device *);
-static void acd_geom_create(void *, int);
-static void acd_set_ioparm(struct acd_softc *);
-static void acd_describe(struct acd_softc *);
+static void acd_geom_attach(void *, int);
+static void acd_geom_detach(void *, int);
+static void acd_set_ioparm(device_t);
+static void acd_describe(device_t);
static void lba2msf(u_int32_t, u_int8_t *, u_int8_t *, u_int8_t *);
static u_int32_t msf2lba(u_int8_t, u_int8_t, u_int8_t);
static int acd_geom_access(struct g_provider *, int, int, int);
static g_ioctl_t acd_geom_ioctl;
static void acd_geom_start(struct bio *);
+static void acd_strategy(struct bio *);
static void acd_done(struct ata_request *);
-static void acd_read_toc(struct acd_softc *);
-static int acd_play(struct acd_softc *, int, int);
-static int acd_setchan(struct acd_softc *, u_int8_t, u_int8_t, u_int8_t, u_int8_t);
-static void acd_select_slot(struct acd_softc *);
-static int acd_init_writer(struct acd_softc *, int);
-static int acd_fixate(struct acd_softc *, int);
-static int acd_init_track(struct acd_softc *, struct cdr_track *);
-static int acd_flush(struct acd_softc *);
-static int acd_read_track_info(struct acd_softc *, int32_t, struct acd_track_info *);
-static int acd_get_progress(struct acd_softc *, int *);
-static int acd_send_cue(struct acd_softc *, struct cdr_cuesheet *);
-static int acd_report_key(struct acd_softc *, struct dvd_authinfo *);
-static int acd_send_key(struct acd_softc *, struct dvd_authinfo *);
-static int acd_read_structure(struct acd_softc *, struct dvd_struct *);
-static int acd_tray(struct acd_softc *, int);
-static int acd_blank(struct acd_softc *, int);
-static int acd_prevent_allow(struct acd_softc *, int);
-static int acd_start_stop(struct acd_softc *, int);
-static int acd_pause_resume(struct acd_softc *, int);
-static int acd_mode_sense(struct acd_softc *, int, caddr_t, int);
-static int acd_mode_select(struct acd_softc *, caddr_t, int);
-static int acd_set_speed(struct acd_softc *, int, int);
-static void acd_get_cap(struct acd_softc *);
-static int acd_read_format_caps(struct acd_softc *, struct cdr_format_capacities *);
-static int acd_format(struct acd_softc *, struct cdr_format_params *);
-static int acd_test_ready(struct ata_device *);
+static void acd_read_toc(device_t);
+static int acd_play(device_t, int, int);
+static int acd_setchan(device_t, u_int8_t, u_int8_t, u_int8_t, u_int8_t);
+static int acd_init_writer(device_t, int);
+static int acd_fixate(device_t, int);
+static int acd_init_track(device_t, struct cdr_track *);
+static int acd_flush(device_t);
+static int acd_read_track_info(device_t, int32_t, struct acd_track_info *);
+static int acd_get_progress(device_t, int *);
+static int acd_send_cue(device_t, struct cdr_cuesheet *);
+static int acd_report_key(device_t, struct dvd_authinfo *);
+static int acd_send_key(device_t, struct dvd_authinfo *);
+static int acd_read_structure(device_t, struct dvd_struct *);
+static int acd_tray(device_t, int);
+static int acd_blank(device_t, int);
+static int acd_prevent_allow(device_t, int);
+static int acd_start_stop(device_t, int);
+static int acd_pause_resume(device_t, int);
+static int acd_mode_sense(device_t, int, caddr_t, int);
+static int acd_mode_select(device_t, caddr_t, int);
+static int acd_set_speed(device_t, int, int);
+static void acd_get_cap(device_t);
+static int acd_read_format_caps(device_t, struct cdr_format_capacities *);
+static int acd_format(device_t, struct cdr_format_params *);
+static int acd_test_ready(device_t);
/* internal vars */
-static u_int32_t acd_lun_map = 0;
static MALLOC_DEFINE(M_ACD, "ACD driver", "ATAPI CD driver buffers");
static struct g_class acd_class = {
.name = "ACD",
@@ -103,503 +102,166 @@ static struct g_class acd_class = {
.ioctl = acd_geom_ioctl,
.start = acd_geom_start,
};
-DECLARE_GEOM_CLASS(acd_class, acd);
+//DECLARE_GEOM_CLASS(acd_class, acd);
-void
-acd_attach(struct ata_device *atadev)
+static void
+acd_identify(driver_t *driver, device_t parent)
{
- struct acd_softc *cdp;
- struct changer *chp;
-
- if ((cdp = acd_init_lun(atadev)) == NULL) {
- ata_prtdev(atadev, "out of memory\n");
- return;
- }
+ ata_identify(driver, parent, ATA_ATAPI_TYPE_CDROM, "acd");
+}
- ata_set_name(atadev, "acd", cdp->lun);
- acd_get_cap(cdp);
+static int
+acd_probe(device_t dev)
+{
+ return 0;
+}
- /* if this is a changer device, allocate the neeeded lun's */
- if ((cdp->cap.mechanism & MST_MECH_MASK) == MST_MECH_CHANGER) {
- int8_t ccb[16] = { ATAPI_MECH_STATUS, 0, 0, 0, 0, 0, 0, 0,
- sizeof(struct changer)>>8, sizeof(struct changer),
- 0, 0, 0, 0, 0, 0 };
+static int
+acd_attach(device_t dev)
+{
+ struct ata_device *atadev = device_get_softc(dev);
+ struct acd_softc *cdp;
- if (!(chp = malloc(sizeof(struct changer), M_ACD, M_NOWAIT | M_ZERO))) {
- ata_prtdev(atadev, "out of memory\n");
- free(cdp, M_ACD);
- return;
- }
- if (!ata_atapicmd(cdp->device, ccb, (caddr_t)chp,
- sizeof(struct changer), ATA_R_READ, 60)) {
- struct acd_softc *tmpcdp = cdp;
- struct acd_softc **cdparr;
- char *name;
- int count;
-
- chp->table_length = htons(chp->table_length);
- if (!(cdparr = malloc(sizeof(struct acd_softc) * chp->slots,
- M_ACD, M_NOWAIT))) {
- ata_prtdev(atadev, "out of memory\n");
- free(chp, M_ACD);
- free(cdp, M_ACD);
- return;
- }
- for (count = 0; count < chp->slots; count++) {
- if (count > 0) {
- tmpcdp = acd_init_lun(atadev);
- if (!tmpcdp) {
- ata_prtdev(atadev, "out of memory\n");
- break;
- }
- }
- cdparr[count] = tmpcdp;
- tmpcdp->driver = cdparr;
- tmpcdp->slot = count;
- tmpcdp->changer_info = chp;
- g_post_event(acd_geom_create, tmpcdp, M_WAITOK, NULL);
- }
- if (!(name = malloc(strlen(atadev->name) + 2, M_ACD, M_NOWAIT))) {
- ata_prtdev(atadev, "out of memory\n");
- free(cdp, M_ACD);
- return;
- }
- strcpy(name, atadev->name);
- strcat(name, "-");
- ata_free_name(atadev);
- ata_set_name(atadev, name, cdp->lun + cdp->changer_info->slots - 1);
- free(name, M_ACD);
- }
+ if (!(cdp = malloc(sizeof(struct acd_softc), M_ACD, M_NOWAIT | M_ZERO))) {
+ device_printf(dev, "out of memory\n");
+ device_set_softc(dev, NULL);
+ free(atadev, M_ATA);
+ return ENOMEM;
}
- else
- g_post_event(acd_geom_create, cdp, M_WAITOK, NULL);
-
- /* setup the function ptrs */
- atadev->detach = acd_detach;
- atadev->start = acd_start;
- atadev->softc = cdp;
+ cdp->block_size = 2048;
+ device_set_ivars(dev, cdp);
+ ATA_SETMODE(GRANDPARENT(dev), dev);
+ acd_get_cap(dev);
+ g_post_event(acd_geom_attach, dev, M_WAITOK, NULL);
/* announce we are here */
- acd_describe(cdp);
+ acd_describe(dev);
+ return 0;
}
-static void
-acd_geom_detach(void *arg, int flag)
+static int
+acd_detach(device_t dev)
{
- struct ata_device *atadev = arg;
- struct acd_softc *cdp = atadev->softc;
- int subdev;
-
- g_wither_geom(cdp->gp, ENXIO);
- if (cdp->changer_info) {
- for (subdev = 0; subdev < cdp->changer_info->slots; subdev++) {
- if (cdp->driver[subdev] == cdp)
- continue;
- mtx_lock(&cdp->driver[subdev]->queue_mtx);
- bioq_flush(&cdp->driver[subdev]->queue, NULL, ENXIO);
- mtx_unlock(&cdp->driver[subdev]->queue_mtx);
- ata_free_lun(&acd_lun_map, cdp->driver[subdev]->lun);
- free(cdp->driver[subdev], M_ACD);
- }
- free(cdp->driver, M_ACD);
- free(cdp->changer_info, M_ACD);
- }
- mtx_lock(&cdp->queue_mtx);
- bioq_flush(&cdp->queue, NULL, ENXIO);
- mtx_unlock(&cdp->queue_mtx);
- mtx_destroy(&cdp->queue_mtx);
- ata_prtdev(atadev, "WARNING - removed from configuration\n");
- ata_free_name(atadev);
- ata_free_lun(&acd_lun_map, cdp->lun);
- atadev->attach = NULL;
- atadev->detach = NULL;
- atadev->start = NULL;
- atadev->softc = NULL;
- atadev->flags = 0;
- free(cdp, M_ACD);
+ g_waitfor_event(acd_geom_detach, dev, M_WAITOK, NULL);
+ return 0;
}
static void
-acd_detach(struct ata_device *atadev)
-{
- g_waitfor_event(acd_geom_detach, atadev, M_WAITOK, NULL);
+acd_shutdown(device_t dev)
+{
+ struct ata_device *atadev = device_get_softc(dev);
+
+ if (atadev->param.support.command2 & ATA_SUPPORT_FLUSHCACHE)
+ ata_controlcmd(atadev, ATA_FLUSHCACHE, 0, 0, 0);
}
-static struct acd_softc *
-acd_init_lun(struct ata_device *atadev)
+static int
+acd_reinit(device_t dev)
{
- struct acd_softc *cdp;
-
- if (!(cdp = malloc(sizeof(struct acd_softc), M_ACD, M_NOWAIT | M_ZERO)))
- return NULL;
- bioq_init(&cdp->queue);
- mtx_init(&cdp->queue_mtx, "ATAPI CD bioqueue lock", NULL, MTX_DEF);
- cdp->device = atadev;
- cdp->lun = ata_get_lun(&acd_lun_map);
- cdp->block_size = 2048;
- cdp->slot = -1;
- cdp->changer_info = NULL;
- return cdp;
+ struct ata_channel *ch = device_get_softc(device_get_parent(dev));
+ struct ata_device *atadev = device_get_softc(dev);
+ struct acd_softc *cdp = device_get_ivars(dev);
+
+ if (((atadev->unit == ATA_MASTER) && !(ch->devices & ATA_ATAPI_MASTER)) ||
+ ((atadev->unit == ATA_SLAVE) && !(ch->devices & ATA_ATAPI_SLAVE))) {
+ device_set_ivars(dev, NULL);
+ free(cdp, M_ACD);
+ return 1;
+ }
+ ATA_SETMODE(GRANDPARENT(dev), dev);
+ return 0;
}
static void
-acd_geom_create(void *arg, int flag)
+acd_geom_attach(void *arg, int flag)
{
- struct acd_softc *cdp;
+ struct ata_device *atadev = device_get_softc(arg);
+ struct acd_softc *cdp = device_get_ivars(arg);
struct g_geom *gp;
struct g_provider *pp;
- cdp = arg;
g_topology_assert();
- gp = g_new_geomf(&acd_class, "acd%d", cdp->lun);
- gp->softc = cdp;
+ gp = g_new_geomf(&acd_class, "acd%d", device_get_unit(arg));
+ gp->softc = arg;
cdp->gp = gp;
- pp = g_new_providerf(gp, "acd%d", cdp->lun);
+ pp = g_new_providerf(gp, "acd%d", device_get_unit(arg));
pp->index = 0;
cdp->pp[0] = pp;
g_error_provider(pp, 0);
- cdp->device->flags |= ATA_D_MEDIA_CHANGED;
- acd_set_ioparm(cdp);
+ atadev->flags |= ATA_D_MEDIA_CHANGED;
+ acd_set_ioparm(arg);
}
static void
-acd_set_ioparm(struct acd_softc *cdp)
-{
-
- if (cdp->device->channel->dma)
- cdp->iomax = min(cdp->device->channel->dma->max_iosize, 65534);
- else
- cdp->iomax = min(DFLTPHYS, 65534);
-}
-
-static void
-acd_describe(struct acd_softc *cdp)
-{
- int comma = 0;
- char *mechanism;
-
- if (bootverbose) {
- ata_prtdev(cdp->device, "<%.40s/%.8s> %s drive at ata%d as %s\n",
- cdp->device->param->model, cdp->device->param->revision,
- (cdp->cap.media & MST_WRITE_DVDR) ? "DVDR" :
- (cdp->cap.media & MST_WRITE_DVDRAM) ? "DVDRAM" :
- (cdp->cap.media & MST_WRITE_CDRW) ? "CDRW" :
- (cdp->cap.media & MST_WRITE_CDR) ? "CDR" :
- (cdp->cap.media & MST_READ_DVDROM) ? "DVDROM" : "CDROM",
- device_get_unit(cdp->device->channel->dev),
- (cdp->device->unit == ATA_MASTER) ? "master" : "slave");
-
- ata_prtdev(cdp->device, "%s", "");
- if (cdp->cap.cur_read_speed) {
- printf("read %dKB/s", cdp->cap.cur_read_speed * 1000 / 1024);
- if (cdp->cap.max_read_speed)
- printf(" (%dKB/s)", cdp->cap.max_read_speed * 1000 / 1024);
- if ((cdp->cap.cur_write_speed) &&
- (cdp->cap.media & (MST_WRITE_CDR | MST_WRITE_CDRW |
- MST_WRITE_DVDR | MST_WRITE_DVDRAM))) {
- printf(" write %dKB/s", cdp->cap.cur_write_speed * 1000 / 1024);
- if (cdp->cap.max_write_speed)
- printf(" (%dKB/s)", cdp->cap.max_write_speed * 1000 / 1024);
- }
- comma = 1;
- }
- if (cdp->cap.buf_size) {
- printf("%s %dKB buffer", comma ? "," : "", cdp->cap.buf_size);
- comma = 1;
- }
- printf("%s %s\n", comma ? "," : "", ata_mode2str(cdp->device->mode));
-
- ata_prtdev(cdp->device, "Reads:");
- comma = 0;
- if (cdp->cap.media & MST_READ_CDR) {
- printf(" CDR"); comma = 1;
- }
- if (cdp->cap.media & MST_READ_CDRW) {
- printf("%s CDRW", comma ? "," : ""); comma = 1;
- }
- if (cdp->cap.capabilities & MST_READ_CDDA) {
- if (cdp->cap.capabilities & MST_CDDA_STREAM)
- printf("%s CDDA stream", comma ? "," : "");
- else
- printf("%s CDDA", comma ? "," : "");
- comma = 1;
- }
- if (cdp->cap.media & MST_READ_DVDROM) {
- printf("%s DVDROM", comma ? "," : ""); comma = 1;
- }
- if (cdp->cap.media & MST_READ_DVDR) {
- printf("%s DVDR", comma ? "," : ""); comma = 1;
- }
- if (cdp->cap.media & MST_READ_DVDRAM) {
- printf("%s DVDRAM", comma ? "," : ""); comma = 1;
- }
- if (cdp->cap.media & MST_READ_PACKET)
- printf("%s packet", comma ? "," : "");
-
- printf("\n");
- ata_prtdev(cdp->device, "Writes:");
- if (cdp->cap.media & (MST_WRITE_CDR | MST_WRITE_CDRW |
- MST_WRITE_DVDR | MST_WRITE_DVDRAM)) {
- comma = 0;
- if (cdp->cap.media & MST_WRITE_CDR) {
- printf(" CDR" ); comma = 1;
- }
- if (cdp->cap.media & MST_WRITE_CDRW) {
- printf("%s CDRW", comma ? "," : ""); comma = 1;
- }
- if (cdp->cap.media & MST_WRITE_DVDR) {
- printf("%s DVDR", comma ? "," : ""); comma = 1;
- }
- if (cdp->cap.media & MST_WRITE_DVDRAM) {
- printf("%s DVDRAM", comma ? "," : ""); comma = 1;
- }
- if (cdp->cap.media & MST_WRITE_TEST) {
- printf("%s test write", comma ? "," : ""); comma = 1;
- }
- if (cdp->cap.capabilities & MST_BURNPROOF)
- printf("%s burnproof", comma ? "," : "");
- }
- printf("\n");
- if (cdp->cap.capabilities & MST_AUDIO_PLAY) {
- ata_prtdev(cdp->device, "Audio: ");
- if (cdp->cap.capabilities & MST_AUDIO_PLAY)
- printf("play");
- if (cdp->cap.max_vol_levels)
- printf(", %d volume levels", cdp->cap.max_vol_levels);
- printf("\n");
- }
- ata_prtdev(cdp->device, "Mechanism: ");
- switch (cdp->cap.mechanism & MST_MECH_MASK) {
- case MST_MECH_CADDY:
- mechanism = "caddy"; break;
- case MST_MECH_TRAY:
- mechanism = "tray"; break;
- case MST_MECH_POPUP:
- mechanism = "popup"; break;
- case MST_MECH_CHANGER:
- mechanism = "changer"; break;
- case MST_MECH_CARTRIDGE:
- mechanism = "cartridge"; break;
- default:
- mechanism = 0; break;
- }
- if (mechanism)
- printf("%s%s", (cdp->cap.mechanism & MST_EJECT) ?
- "ejectable " : "", mechanism);
- else if (cdp->cap.mechanism & MST_EJECT)
- printf("ejectable");
-
- if (cdp->cap.mechanism & MST_LOCKABLE)
- printf((cdp->cap.mechanism & MST_LOCKED) ? ", locked":", unlocked");
- if (cdp->cap.mechanism & MST_PREVENT)
- printf(", lock protected");
- printf("\n");
-
- if ((cdp->cap.mechanism & MST_MECH_MASK) != MST_MECH_CHANGER) {
- ata_prtdev(cdp->device, "Medium: ");
- switch (cdp->cap.medium_type & MST_TYPE_MASK_HIGH) {
- case MST_CDROM:
- printf("CD-ROM "); break;
- case MST_CDR:
- printf("CD-R "); break;
- case MST_CDRW:
- printf("CD-RW "); break;
- case MST_DOOR_OPEN:
- printf("door open"); break;
- case MST_NO_DISC:
- printf("no/blank disc"); break;
- case MST_FMT_ERROR:
- printf("medium format error"); break;
- }
- if ((cdp->cap.medium_type & MST_TYPE_MASK_HIGH)<MST_TYPE_MASK_HIGH){
- switch (cdp->cap.medium_type & MST_TYPE_MASK_LOW) {
- case MST_DATA_120:
- printf("120mm data disc"); break;
- case MST_AUDIO_120:
- printf("120mm audio disc"); break;
- case MST_COMB_120:
- printf("120mm data/audio disc"); break;
- case MST_PHOTO_120:
- printf("120mm photo disc"); break;
- case MST_DATA_80:
- printf("80mm data disc"); break;
- case MST_AUDIO_80:
- printf("80mm audio disc"); break;
- case MST_COMB_80:
- printf("80mm data/audio disc"); break;
- case MST_PHOTO_80:
- printf("80mm photo disc"); break;
- case MST_FMT_NONE:
- switch (cdp->cap.medium_type & MST_TYPE_MASK_HIGH) {
- case MST_CDROM:
- printf("unknown"); break;
- case MST_CDR:
- case MST_CDRW:
- printf("blank"); break;
- }
- break;
- default:
- printf("unknown (0x%x)", cdp->cap.medium_type); break;
- }
- }
- printf("\n");
- }
- }
- else {
- ata_prtdev(cdp->device, "%s ",
- (cdp->cap.media & MST_WRITE_DVDR) ? "DVDR" :
- (cdp->cap.media & MST_WRITE_DVDRAM) ? "DVDRAM" :
- (cdp->cap.media & MST_WRITE_CDRW) ? "CDRW" :
- (cdp->cap.media & MST_WRITE_CDR) ? "CDR" :
- (cdp->cap.media & MST_READ_DVDROM) ? "DVDROM" : "CDROM");
- if (cdp->changer_info)
- printf("with %d CD changer ", cdp->changer_info->slots);
- printf("<%.40s/%.8s> at ata%d-%s %s\n",
- cdp->device->param->model, cdp->device->param->revision,
- device_get_unit(cdp->device->channel->dev),
- (cdp->device->unit == ATA_MASTER) ? "master" : "slave",
- ata_mode2str(cdp->device->mode) );
- }
-}
-
-static __inline void
-lba2msf(u_int32_t lba, u_int8_t *m, u_int8_t *s, u_int8_t *f)
-{
- lba += 150;
- lba &= 0xffffff;
- *m = lba / (60 * 75);
- lba %= (60 * 75);
- *s = lba / 75;
- *f = lba % 75;
-}
-
-static __inline u_int32_t
-msf2lba(u_int8_t m, u_int8_t s, u_int8_t f)
-{
- return (m * 60 + s) * 75 + f - 150;
-}
-
-static int
-acd_geom_access(struct g_provider *pp, int dr, int dw, int de)
-{
- struct acd_softc *cdp;
- struct ata_request *request;
- int8_t ccb[16] = { ATAPI_TEST_UNIT_READY, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- int timeout = 60, track;
-
-
- cdp = pp->geom->softc;
- if (cdp->device->flags & ATA_D_DETACHING)
- return ENXIO;
-
- if (!(request = ata_alloc_request()))
- return ENOMEM;
-
- /* wait if drive is not finished loading the medium */
- while (timeout--) {
- bzero(request, sizeof(struct ata_request));
- request->device = cdp->device;
- request->driver = cdp;
- bcopy(ccb, request->u.atapi.ccb, 16);
- request->flags = ATA_R_ATAPI;
- request->timeout = 5;
- ata_queue_request(request);
- if (!request->error &&
- (request->u.atapi.sense_data.sense_key == 2 ||
- request->u.atapi.sense_data.sense_key == 7) &&
- request->u.atapi.sense_data.asc == 4 &&
- request->u.atapi.sense_data.ascq == 1)
- tsleep(&timeout, PRIBIO, "acdld", hz / 2);
- else
- break;
- }
- ata_free_request(request);
-
- if (pp->acr == 0) {
- if (cdp->changer_info && cdp->slot != cdp->changer_info->current_slot) {
- acd_select_slot(cdp);
- tsleep(&cdp->changer_info, PRIBIO, "acdopn", 0);
- }
- acd_prevent_allow(cdp, 1);
- cdp->flags |= F_LOCKED;
- acd_read_toc(cdp);
- }
+acd_geom_detach(void *arg, int flag)
+{
+ struct ata_channel *ch = device_get_softc(device_get_parent(arg));
+ struct ata_device *atadev = device_get_softc(arg);
+ struct acd_softc *cdp = device_get_ivars(arg);
- if (dr + pp->acr == 0) {
- if (cdp->changer_info && cdp->slot != cdp->changer_info->current_slot) {
- acd_select_slot(cdp);
- tsleep(&cdp->changer_info, PRIBIO, "acdclo", 0);
- }
- acd_prevent_allow(cdp, 0);
- cdp->flags &= ~F_LOCKED;
- }
+ /* signal geom so we dont get any further requests */
+ g_wither_geom(cdp->gp, ENXIO);
- if ((track = pp->index)) {
- pp->sectorsize = (cdp->toc.tab[track - 1].control & 4) ? 2048 : 2352;
- pp->mediasize = ntohl(cdp->toc.tab[track].addr.lba) -
- ntohl(cdp->toc.tab[track - 1].addr.lba);
- }
- else {
- pp->sectorsize = cdp->block_size;
- pp->mediasize = cdp->disk_size;
- }
- pp->mediasize *= pp->sectorsize;
+ /* fail requests on the queue and any thats "in flight" for this device */
+ ata_fail_requests(ch, arg);
- return 0;
+ /* dont leave anything behind */
+ device_set_ivars(arg, NULL);
+ free(cdp, M_ACD);
+ device_set_softc(arg, NULL);
+ free(atadev, M_ATA);
}
static int
acd_geom_ioctl(struct g_provider *pp, u_long cmd, void *addr, int fflag, struct thread *td)
{
- struct acd_softc *cdp = pp->geom->softc;
- int error = 0, nocopyout;
+ device_t dev = pp->geom->softc;
+ struct ata_device *atadev = device_get_softc(dev);
+ struct acd_softc *cdp = device_get_ivars(dev);
+ int error = 0, nocopyout = 0;
if (!cdp)
return ENXIO;
- if (cdp->changer_info && cdp->slot != cdp->changer_info->current_slot) {
- acd_select_slot(cdp);
- tsleep(&cdp->changer_info, PRIBIO, "acdctl", 0);
- }
- if (cdp->device->flags & ATA_D_MEDIA_CHANGED)
+ if (atadev->flags & ATA_D_MEDIA_CHANGED) {
switch (cmd) {
case CDIOCRESET:
- acd_test_ready(cdp->device);
+ acd_test_ready(dev);
break;
default:
- acd_read_toc(cdp);
- acd_prevent_allow(cdp, 1);
+ acd_read_toc(dev);
+ acd_prevent_allow(dev, 1);
cdp->flags |= F_LOCKED;
break;
}
- nocopyout = 0;
+ }
+
switch (cmd) {
case CDIOCRESUME:
- error = acd_pause_resume(cdp, 1);
+ error = acd_pause_resume(dev, 1);
break;
case CDIOCPAUSE:
- error = acd_pause_resume(cdp, 0);
+ error = acd_pause_resume(dev, 0);
break;
case CDIOCSTART:
- error = acd_start_stop(cdp, 1);
+ error = acd_start_stop(dev, 1);
break;
case CDIOCSTOP:
- error = acd_start_stop(cdp, 0);
+ error = acd_start_stop(dev, 0);
break;
case CDIOCALLOW:
- error = acd_prevent_allow(cdp, 0);
+ error = acd_prevent_allow(dev, 0);
cdp->flags &= ~F_LOCKED;
break;
case CDIOCPREVENT:
- error = acd_prevent_allow(cdp, 1);
+ error = acd_prevent_allow(dev, 1);
cdp->flags |= F_LOCKED;
break;
@@ -607,7 +269,7 @@ acd_geom_ioctl(struct g_provider *pp, u_long cmd, void *addr, int fflag, struct
error = suser(td);
if (error)
break;
- error = acd_test_ready(cdp->device);
+ error = acd_test_ready(dev);
break;
case CDIOCEJECT:
@@ -615,13 +277,13 @@ acd_geom_ioctl(struct g_provider *pp, u_long cmd, void *addr, int fflag, struct
error = EBUSY;
break;
}
- error = acd_tray(cdp, 0);
+ error = acd_tray(dev, 0);
break;
case CDIOCCLOSE:
if (pp->acr != 1)
break;
- error = acd_tray(cdp, 1);
+ error = acd_tray(dev, 1);
break;
case CDIOREADTOCHEADER:
@@ -739,9 +401,12 @@ acd_geom_ioctl(struct g_provider *pp, u_long cmd, void *addr, int fflag, struct
}
break;
+#if __FreeBSD_version > 600008
case CDIOCREADSUBCHANNEL_SYSSPACE:
- nocopyout = 1;
- /* Fallthrough */
+ nocopyout = 1;
+ /* FALLTHROUGH */
+
+#endif
case CDIOCREADSUBCHANNEL:
{
struct ioc_read_subchannel *args =
@@ -766,7 +431,7 @@ acd_geom_ioctl(struct g_provider *pp, u_long cmd, void *addr, int fflag, struct
ccb[1] = args->address_format & CD_MSF_FORMAT;
- if ((error = ata_atapicmd(cdp->device, ccb, (caddr_t)&cdp->subchan,
+ if ((error = ata_atapicmd(atadev, ccb, (caddr_t)&cdp->subchan,
sizeof(cdp->subchan), ATA_R_READ, 10)))
break;
@@ -780,17 +445,16 @@ acd_geom_ioctl(struct g_provider *pp, u_long cmd, void *addr, int fflag, struct
if (format == CD_TRACK_INFO)
ccb[6] = args->track;
- if ((error = ata_atapicmd(cdp->device, ccb,
- (caddr_t)&cdp->subchan,
+ if ((error = ata_atapicmd(atadev, ccb, (caddr_t)&cdp->subchan,
sizeof(cdp->subchan),ATA_R_READ,10))){
break;
}
}
if (nocopyout == 0) {
- error = copyout(&cdp->subchan, args->data, args->data_len);
+ error = copyout(&cdp->subchan, args->data, args->data_len);
} else {
- error = 0;
- bcopy(&cdp->subchan, args->data, args->data_len);
+ error = 0;
+ bcopy(&cdp->subchan, args->data, args->data_len);
}
}
break;
@@ -800,7 +464,7 @@ acd_geom_ioctl(struct g_provider *pp, u_long cmd, void *addr, int fflag, struct
struct ioc_play_msf *args = (struct ioc_play_msf *)addr;
error =
- acd_play(cdp,
+ acd_play(dev,
msf2lba(args->start_m, args->start_s, args->start_f),
msf2lba(args->end_m, args->end_s, args->end_f));
}
@@ -810,7 +474,7 @@ acd_geom_ioctl(struct g_provider *pp, u_long cmd, void *addr, int fflag, struct
{
struct ioc_play_blocks *args = (struct ioc_play_blocks *)addr;
- error = acd_play(cdp, args->blk, args->blk + args->len);
+ error = acd_play(dev, args->blk, args->blk + args->len);
}
break;
@@ -834,7 +498,7 @@ acd_geom_ioctl(struct g_provider *pp, u_long cmd, void *addr, int fflag, struct
error = EINVAL;
break;
}
- error = acd_play(cdp, ntohl(cdp->toc.tab[t1].addr.lba),
+ error = acd_play(dev, ntohl(cdp->toc.tab[t1].addr.lba),
ntohl(cdp->toc.tab[t2].addr.lba));
}
break;
@@ -843,7 +507,7 @@ acd_geom_ioctl(struct g_provider *pp, u_long cmd, void *addr, int fflag, struct
{
struct ioc_vol *arg = (struct ioc_vol *)addr;
- if ((error = acd_mode_sense(cdp, ATAPI_CDROM_AUDIO_PAGE,
+ if ((error = acd_mode_sense(dev, ATAPI_CDROM_AUDIO_PAGE,
(caddr_t)&cdp->au, sizeof(cdp->au))))
break;
@@ -862,14 +526,14 @@ acd_geom_ioctl(struct g_provider *pp, u_long cmd, void *addr, int fflag, struct
{
struct ioc_vol *arg = (struct ioc_vol *)addr;
- if ((error = acd_mode_sense(cdp, ATAPI_CDROM_AUDIO_PAGE,
+ if ((error = acd_mode_sense(dev, ATAPI_CDROM_AUDIO_PAGE,
(caddr_t)&cdp->au, sizeof(cdp->au))))
break;
if (cdp->au.page_code != ATAPI_CDROM_AUDIO_PAGE) {
error = EIO;
break;
}
- if ((error = acd_mode_sense(cdp, ATAPI_CDROM_AUDIO_PAGE_MASK,
+ if ((error = acd_mode_sense(dev, ATAPI_CDROM_AUDIO_PAGE_MASK,
(caddr_t)&cdp->aumask,
sizeof(cdp->aumask))))
break;
@@ -880,7 +544,7 @@ acd_geom_ioctl(struct g_provider *pp, u_long cmd, void *addr, int fflag, struct
cdp->au.port[1].volume = arg->vol[1] & cdp->aumask.port[1].volume;
cdp->au.port[2].volume = arg->vol[2] & cdp->aumask.port[2].volume;
cdp->au.port[3].volume = arg->vol[3] & cdp->aumask.port[3].volume;
- error = acd_mode_select(cdp, (caddr_t)&cdp->au, sizeof(cdp->au));
+ error = acd_mode_select(dev, (caddr_t)&cdp->au, sizeof(cdp->au));
}
break;
@@ -888,40 +552,40 @@ acd_geom_ioctl(struct g_provider *pp, u_long cmd, void *addr, int fflag, struct
{
struct ioc_patch *arg = (struct ioc_patch *)addr;
- error = acd_setchan(cdp, arg->patch[0], arg->patch[1],
+ error = acd_setchan(dev, arg->patch[0], arg->patch[1],
arg->patch[2], arg->patch[3]);
}
break;
case CDIOCSETMONO:
- error = acd_setchan(cdp, CHANNEL_0|CHANNEL_1, CHANNEL_0|CHANNEL_1, 0,0);
+ error = acd_setchan(dev, CHANNEL_0|CHANNEL_1, CHANNEL_0|CHANNEL_1, 0,0);
break;
case CDIOCSETSTEREO:
- error = acd_setchan(cdp, CHANNEL_0, CHANNEL_1, 0, 0);
+ error = acd_setchan(dev, CHANNEL_0, CHANNEL_1, 0, 0);
break;
case CDIOCSETMUTE:
- error = acd_setchan(cdp, 0, 0, 0, 0);
+ error = acd_setchan(dev, 0, 0, 0, 0);
break;
case CDIOCSETLEFT:
- error = acd_setchan(cdp, CHANNEL_0, CHANNEL_0, 0, 0);
+ error = acd_setchan(dev, CHANNEL_0, CHANNEL_0, 0, 0);
break;
case CDIOCSETRIGHT:
- error = acd_setchan(cdp, CHANNEL_1, CHANNEL_1, 0, 0);
+ error = acd_setchan(dev, CHANNEL_1, CHANNEL_1, 0, 0);
break;
case CDRIOCBLANK:
- error = acd_blank(cdp, (*(int *)addr));
+ error = acd_blank(dev, (*(int *)addr));
break;
case CDRIOCNEXTWRITEABLEADDR:
{
struct acd_track_info track_info;
- if ((error = acd_read_track_info(cdp, 0xff, &track_info)))
+ if ((error = acd_read_track_info(dev, 0xff, &track_info)))
break;
if (!track_info.nwa_valid) {
@@ -933,19 +597,19 @@ acd_geom_ioctl(struct g_provider *pp, u_long cmd, void *addr, int fflag, struct
break;
case CDRIOCINITWRITER:
- error = acd_init_writer(cdp, (*(int *)addr));
+ error = acd_init_writer(dev, (*(int *)addr));
break;
case CDRIOCINITTRACK:
- error = acd_init_track(cdp, (struct cdr_track *)addr);
+ error = acd_init_track(dev, (struct cdr_track *)addr);
break;
case CDRIOCFLUSH:
- error = acd_flush(cdp);
+ error = acd_flush(dev);
break;
case CDRIOCFIXATE:
- error = acd_fixate(cdp, (*(int *)addr));
+ error = acd_fixate(dev, (*(int *)addr));
break;
case CDRIOCREADSPEED:
@@ -955,7 +619,7 @@ acd_geom_ioctl(struct g_provider *pp, u_long cmd, void *addr, int fflag, struct
/* Preserve old behavior: units in multiples of CDROM speed */
if (speed < 177)
speed *= 177;
- error = acd_set_speed(cdp, speed, CDR_MAX_SPEED);
+ error = acd_set_speed(dev, speed, CDR_MAX_SPEED);
}
break;
@@ -965,7 +629,7 @@ acd_geom_ioctl(struct g_provider *pp, u_long cmd, void *addr, int fflag, struct
if (speed < 177)
speed *= 177;
- error = acd_set_speed(cdp, CDR_MAX_SPEED, speed);
+ error = acd_set_speed(dev, CDR_MAX_SPEED, speed);
}
break;
@@ -975,43 +639,43 @@ acd_geom_ioctl(struct g_provider *pp, u_long cmd, void *addr, int fflag, struct
case CDRIOCSETBLOCKSIZE:
cdp->block_size = *(int *)addr;
- pp->sectorsize = cdp->block_size; /* hack for GEOM SOS */
- acd_set_ioparm(cdp);
+ pp->sectorsize = cdp->block_size; /* hack for GEOM SOS */
+ acd_set_ioparm(dev);
break;
case CDRIOCGETPROGRESS:
- error = acd_get_progress(cdp, (int *)addr);
+ error = acd_get_progress(dev, (int *)addr);
break;
case CDRIOCSENDCUE:
- error = acd_send_cue(cdp, (struct cdr_cuesheet *)addr);
+ error = acd_send_cue(dev, (struct cdr_cuesheet *)addr);
break;
case CDRIOCREADFORMATCAPS:
- error = acd_read_format_caps(cdp, (struct cdr_format_capacities *)addr);
+ error = acd_read_format_caps(dev, (struct cdr_format_capacities *)addr);
break;
case CDRIOCFORMAT:
- error = acd_format(cdp, (struct cdr_format_params *)addr);
+ error = acd_format(dev, (struct cdr_format_params *)addr);
break;
case DVDIOCREPORTKEY:
if (cdp->cap.media & MST_READ_DVDROM)
- error = acd_report_key(cdp, (struct dvd_authinfo *)addr);
+ error = acd_report_key(dev, (struct dvd_authinfo *)addr);
else
error = EINVAL;
break;
case DVDIOCSENDKEY:
if (cdp->cap.media & MST_READ_DVDROM)
- error = acd_send_key(cdp, (struct dvd_authinfo *)addr);
+ error = acd_send_key(dev, (struct dvd_authinfo *)addr);
else
error = EINVAL;
break;
case DVDIOCREADSTRUCTURE:
if (cdp->cap.media & MST_READ_DVDROM)
- error = acd_read_structure(cdp, (struct dvd_struct *)addr);
+ error = acd_read_structure(dev, (struct dvd_struct *)addr);
else
error = EINVAL;
break;
@@ -1022,16 +686,69 @@ acd_geom_ioctl(struct g_provider *pp, u_long cmd, void *addr, int fflag, struct
return error;
}
-static void
-acd_geom_start(struct bio *bp)
+static int
+acd_geom_access(struct g_provider *pp, int dr, int dw, int de)
{
- struct acd_softc *cdp = bp->bio_to->geom->softc;
+ device_t dev = pp->geom->softc;
+ struct acd_softc *cdp = device_get_ivars(dev);
+ struct ata_request *request;
+ int8_t ccb[16] = { ATAPI_TEST_UNIT_READY, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ int timeout = 60, track;
- if (cdp->device->flags & ATA_D_DETACHING) {
- g_io_deliver(bp, ENXIO);
- return;
+ if (!(request = ata_alloc_request()))
+ return ENOMEM;
+
+ /* wait if drive is not finished loading the medium */
+ while (timeout--) {
+ bzero(request, sizeof(struct ata_request));
+ request->dev = dev;
+ bcopy(ccb, request->u.atapi.ccb, 16);
+ request->flags = ATA_R_ATAPI;
+ request->timeout = 5;
+ ata_queue_request(request);
+ if (!request->error &&
+ (request->u.atapi.sense_data.sense_key == 2 ||
+ request->u.atapi.sense_data.sense_key == 7) &&
+ request->u.atapi.sense_data.asc == 4 &&
+ request->u.atapi.sense_data.ascq == 1)
+ tsleep(&timeout, PRIBIO, "acdld", hz / 2);
+ else
+ break;
+ }
+ ata_free_request(request);
+
+ if (pp->acr == 0) {
+ acd_prevent_allow(dev, 1);
+ cdp->flags |= F_LOCKED;
+ acd_read_toc(dev);
+ }
+
+ if (dr + pp->acr == 0) {
+ acd_prevent_allow(dev, 0);
+ cdp->flags &= ~F_LOCKED;
}
+ if ((track = pp->index)) {
+ pp->sectorsize = (cdp->toc.tab[track - 1].control & 4) ? 2048 : 2352;
+ pp->mediasize = ntohl(cdp->toc.tab[track].addr.lba) -
+ ntohl(cdp->toc.tab[track - 1].addr.lba);
+ }
+ else {
+ pp->sectorsize = cdp->block_size;
+ pp->mediasize = cdp->disk_size;
+ }
+ pp->mediasize *= pp->sectorsize;
+
+ return 0;
+}
+
+static void
+acd_geom_start(struct bio *bp)
+{
+ device_t dev = bp->bio_to->geom->softc;
+ struct acd_softc *cdp = device_get_ivars(dev);
+
if (bp->bio_cmd != BIO_READ && bp->bio_cmd != BIO_WRITE) {
g_io_deliver(bp, EOPNOTSUPP);
return;
@@ -1044,10 +761,8 @@ acd_geom_start(struct bio *bp)
/* GEOM classes must do their own request limiting */
if (bp->bio_length <= cdp->iomax) {
- mtx_lock(&cdp->queue_mtx);
bp->bio_pblkno = bp->bio_offset / bp->bio_to->sectorsize;
- bioq_disksort(&cdp->queue, bp);
- mtx_unlock(&cdp->queue_mtx);
+ acd_strategy(bp);
}
else {
u_int pos, size = cdp->iomax - cdp->iomax % bp->bio_to->sectorsize;
@@ -1063,59 +778,25 @@ acd_geom_start(struct bio *bp)
bp2->bio_offset += pos;
bp2->bio_data += pos;
bp2->bio_length = MIN(size, bp->bio_length - pos);
- mtx_lock(&cdp->queue_mtx);
bp2->bio_pblkno = bp2->bio_offset / bp2->bio_to->sectorsize;
- bioq_disksort(&cdp->queue, bp2);
- mtx_unlock(&cdp->queue_mtx);
+ acd_strategy(bp2);
}
}
- ata_start(cdp->device->channel);
}
static void
-acd_start(struct ata_device *atadev)
+acd_strategy(struct bio *bp)
{
- struct acd_softc *cdp = atadev->softc;
- struct bio *bp;
+ device_t dev = bp->bio_to->geom->softc;
+ struct ata_device *atadev = device_get_softc(dev);
+ struct acd_softc *cdp = device_get_ivars(dev);
struct ata_request *request;
u_int32_t lba, lastlba, count;
int8_t ccb[16];
int track, blocksize;
- if (cdp->changer_info) {
- int i;
-
- cdp = cdp->driver[cdp->changer_info->current_slot];
- mtx_lock(&cdp->queue_mtx);
- bp = bioq_first(&cdp->queue);
- mtx_unlock(&cdp->queue_mtx);
-
- /* check for work pending on any other slot */
- for (i = 0; i < cdp->changer_info->slots; i++) {
- if (i == cdp->changer_info->current_slot)
- continue;
- mtx_lock(&cdp->queue_mtx);
- if (bioq_first(&(cdp->driver[i]->queue))) {
- if (!bp || time_second > (cdp->timestamp + 10)) {
- mtx_unlock(&cdp->queue_mtx);
- acd_select_slot(cdp->driver[i]);
- return;
- }
- }
- mtx_unlock(&cdp->queue_mtx);
-
- }
- }
- mtx_lock(&cdp->queue_mtx);
- bp = bioq_first(&cdp->queue);
- if (bp)
- bioq_remove(&cdp->queue, bp);
- mtx_unlock(&cdp->queue_mtx);
- if (!bp)
- return;
-
/* reject all queued entries if media changed */
- if (cdp->device->flags & ATA_D_MEDIA_CHANGED) {
+ if (atadev->flags & ATA_D_MEDIA_CHANGED) {
g_io_deliver(bp, EIO);
return;
}
@@ -1179,10 +860,10 @@ acd_start(struct ata_device *atadev)
g_io_deliver(bp, ENOMEM);
return;
}
- request->device = atadev;
+ request->dev = dev;
request->driver = bp;
bcopy(ccb, request->u.atapi.ccb,
- (request->device->param->config & ATA_PROTO_MASK) ==
+ (atadev->param.config & ATA_PROTO_MASK) ==
ATA_PROTO_ATAPI_12 ? 16 : 12);
request->data = bp->bio_data;
request->bytecount = count * blocksize;
@@ -1191,7 +872,7 @@ acd_start(struct ata_device *atadev)
request->retries = 2;
request->callback = acd_done;
request->flags = ATA_R_ATAPI;
- if (request->device->mode >= ATA_DMA)
+ if (atadev->mode >= ATA_DMA)
request->flags |= ATA_R_DMA;
switch (bp->bio_cmd) {
case BIO_READ:
@@ -1201,7 +882,7 @@ acd_start(struct ata_device *atadev)
request->flags |= ATA_R_WRITE;
break;
default:
- ata_prtdev(atadev, "unknown BIO operation\n");
+ device_printf(dev, "unknown BIO operation\n");
ata_free_request(request);
g_io_deliver(bp, EIO);
return;
@@ -1220,30 +901,61 @@ acd_done(struct ata_request *request)
ata_free_request(request);
}
+static void
+acd_set_ioparm(device_t dev)
+{
+ struct ata_channel *ch = device_get_softc(device_get_parent(dev));
+ struct acd_softc *cdp = device_get_ivars(dev);
+
+ if (ch->dma)
+ cdp->iomax = min(ch->dma->max_iosize, 65534);
+ else
+ cdp->iomax = min(DFLTPHYS, 65534);
+}
+
static void
-acd_read_toc(struct acd_softc *cdp)
+lba2msf(u_int32_t lba, u_int8_t *m, u_int8_t *s, u_int8_t *f)
{
- int track, ntracks, len;
+ lba += 150;
+ lba &= 0xffffff;
+ *m = lba / (60 * 75);
+ lba %= (60 * 75);
+ *s = lba / 75;
+ *f = lba % 75;
+}
+
+static u_int32_t
+msf2lba(u_int8_t m, u_int8_t s, u_int8_t f)
+{
+ return (m * 60 + s) * 75 + f - 150;
+}
+
+static void
+acd_read_toc(device_t dev)
+{
+ struct ata_device *atadev = device_get_softc(dev);
+ struct acd_softc *cdp = device_get_ivars(dev);
+ struct g_provider *pp;
u_int32_t sizes[2];
int8_t ccb[16];
- struct g_provider *pp;
+ int track, ntracks, len;
- if (acd_test_ready(cdp->device))
+ if (acd_test_ready(dev))
return;
- if (!(cdp->device->flags & ATA_D_MEDIA_CHANGED))
+ if (!(atadev->flags & ATA_D_MEDIA_CHANGED))
return;
- cdp->device->flags &= ~ATA_D_MEDIA_CHANGED;
+ atadev->flags &= ~ATA_D_MEDIA_CHANGED;
bzero(&cdp->toc, sizeof(cdp->toc));
bzero(ccb, sizeof(ccb));
- cdp->disk_size = -1; /* hack for GEOM SOS */
+ cdp->disk_size = -1; /* hack for GEOM SOS */
len = sizeof(struct ioc_toc_header) + sizeof(struct cd_toc_entry);
ccb[0] = ATAPI_READ_TOC;
ccb[7] = len>>8;
ccb[8] = len;
- if (ata_atapicmd(cdp->device, ccb, (caddr_t)&cdp->toc, len,
+ if (ata_atapicmd(atadev, ccb, (caddr_t)&cdp->toc, len,
ATA_R_READ | ATA_R_QUIET, 30)) {
bzero(&cdp->toc, sizeof(cdp->toc));
return;
@@ -1259,7 +971,7 @@ acd_read_toc(struct acd_softc *cdp)
ccb[0] = ATAPI_READ_TOC;
ccb[7] = len>>8;
ccb[8] = len;
- if (ata_atapicmd(cdp->device, ccb, (caddr_t)&cdp->toc, len,
+ if (ata_atapicmd(atadev, ccb, (caddr_t)&cdp->toc, len,
ATA_R_READ | ATA_R_QUIET, 30)) {
bzero(&cdp->toc, sizeof(cdp->toc));
return;
@@ -1267,10 +979,10 @@ acd_read_toc(struct acd_softc *cdp)
cdp->toc.hdr.len = ntohs(cdp->toc.hdr.len);
cdp->block_size = (cdp->toc.tab[0].control & 4) ? 2048 : 2352;
- acd_set_ioparm(cdp);
+ acd_set_ioparm(dev);
bzero(ccb, sizeof(ccb));
ccb[0] = ATAPI_READ_CAPACITY;
- if (ata_atapicmd(cdp->device, ccb, (caddr_t)sizes, sizeof(sizes),
+ if (ata_atapicmd(atadev, ccb, (caddr_t)sizes, sizeof(sizes),
ATA_R_READ | ATA_R_QUIET, 30)) {
bzero(&cdp->toc, sizeof(cdp->toc));
return;
@@ -1280,7 +992,7 @@ acd_read_toc(struct acd_softc *cdp)
for (track = 1; track <= ntracks; track ++) {
if (cdp->pp[track] != NULL)
continue;
- pp = g_new_providerf(cdp->gp, "acd%dt%02d", cdp->lun, track);
+ pp = g_new_providerf(cdp->gp, "acd%dt%02d", device_get_unit(dev),track);
pp->index = track;
cdp->pp[track] = pp;
g_error_provider(pp, 0);
@@ -1295,9 +1007,9 @@ acd_read_toc(struct acd_softc *cdp)
#ifdef ACD_DEBUG
if (cdp->disk_size && cdp->toc.hdr.ending_track) {
- ata_prtdev(cdp->device, "(%d sectors (%d bytes)), %d tracks ",
- cdp->disk_size, cdp->block_size,
- cdp->toc.hdr.ending_track - cdp->toc.hdr.starting_track + 1);
+ device_printd(dev, "(%d sectors (%d bytes)), %d tracks ",
+ cdp->disk_size, cdp->block_size,
+ cdp->toc.hdr.ending_track-cdp->toc.hdr.starting_track+1);
if (cdp->toc.tab[0].control & 4)
printf("%dMB\n", cdp->disk_size / 512);
else
@@ -1308,24 +1020,25 @@ acd_read_toc(struct acd_softc *cdp)
}
static int
-acd_play(struct acd_softc *cdp, int start, int end)
+acd_play(device_t dev, int start, int end)
{
+ struct ata_device *atadev = device_get_softc(dev);
int8_t ccb[16];
bzero(ccb, sizeof(ccb));
ccb[0] = ATAPI_PLAY_MSF;
lba2msf(start, &ccb[3], &ccb[4], &ccb[5]);
lba2msf(end, &ccb[6], &ccb[7], &ccb[8]);
- return ata_atapicmd(cdp->device, ccb, NULL, 0, 0, 10);
+ return ata_atapicmd(atadev, ccb, NULL, 0, 0, 10);
}
static int
-acd_setchan(struct acd_softc *cdp,
- u_int8_t c0, u_int8_t c1, u_int8_t c2, u_int8_t c3)
+acd_setchan(device_t dev, u_int8_t c0, u_int8_t c1, u_int8_t c2, u_int8_t c3)
{
+ struct acd_softc *cdp = device_get_ivars(dev);
int error;
- if ((error = acd_mode_sense(cdp, ATAPI_CDROM_AUDIO_PAGE, (caddr_t)&cdp->au,
+ if ((error = acd_mode_sense(dev, ATAPI_CDROM_AUDIO_PAGE, (caddr_t)&cdp->au,
sizeof(cdp->au))))
return error;
if (cdp->au.page_code != ATAPI_CDROM_AUDIO_PAGE)
@@ -1335,81 +1048,36 @@ acd_setchan(struct acd_softc *cdp,
cdp->au.port[1].channels = c1;
cdp->au.port[2].channels = c2;
cdp->au.port[3].channels = c3;
- return acd_mode_select(cdp, (caddr_t)&cdp->au, sizeof(cdp->au));
-}
-
-static void
-acd_load_done(struct ata_request *request)
-{
- struct acd_softc *cdp = request->driver;
-
- /* finish the slot select and wakeup caller */
- cdp->changer_info->current_slot = cdp->slot;
- cdp->driver[cdp->changer_info->current_slot]->timestamp = time_second;
- wakeup(&cdp->changer_info);
-}
-
-static void
-acd_unload_done(struct ata_request *request)
-{
- struct acd_softc *cdp = request->driver;
- int8_t ccb[16] = { ATAPI_LOAD_UNLOAD, 0, 0, 0, 3, 0, 0, 0,
- cdp->slot, 0, 0, 0, 0, 0, 0, 0 };
-
- /* load the wanted slot */
- bcopy(ccb, request->u.atapi.ccb,
- (request->device->param->config & ATA_PROTO_MASK) ==
- ATA_PROTO_ATAPI_12 ? 16 : 12);
- request->callback = acd_load_done;
- ata_queue_request(request);
-}
-
-static void
-acd_select_slot(struct acd_softc *cdp)
-{
- struct ata_request *request;
- int8_t ccb[16] = { ATAPI_LOAD_UNLOAD, 0, 0, 0, 2, 0, 0, 0,
- cdp->changer_info->current_slot, 0, 0, 0, 0, 0, 0, 0 };
-
- /* unload the current media from player */
- if (!(request = ata_alloc_request()))
- return;
-
- request->device = cdp->device;
- request->driver = cdp;
- bcopy(ccb, request->u.atapi.ccb,
- (request->device->param->config & ATA_PROTO_MASK) ==
- ATA_PROTO_ATAPI_12 ? 16 : 12);
- request->timeout = 30;
- request->callback = acd_unload_done;
- request->flags |= (ATA_R_ATAPI | ATA_R_IMMEDIATE);
- ata_queue_request(request);
+ return acd_mode_select(dev, (caddr_t)&cdp->au, sizeof(cdp->au));
}
static int
-acd_init_writer(struct acd_softc *cdp, int test_write)
+acd_init_writer(device_t dev, int test_write)
{
+ struct ata_device *atadev = device_get_softc(dev);
int8_t ccb[16];
bzero(ccb, sizeof(ccb));
ccb[0] = ATAPI_REZERO;
- ata_atapicmd(cdp->device, ccb, NULL, 0, ATA_R_QUIET, 60);
+ ata_atapicmd(atadev, ccb, NULL, 0, ATA_R_QUIET, 60);
ccb[0] = ATAPI_SEND_OPC_INFO;
ccb[1] = 0x01;
- ata_atapicmd(cdp->device, ccb, NULL, 0, ATA_R_QUIET, 30);
+ ata_atapicmd(atadev, ccb, NULL, 0, ATA_R_QUIET, 30);
return 0;
}
static int
-acd_fixate(struct acd_softc *cdp, int multisession)
+acd_fixate(device_t dev, int multisession)
{
+ struct ata_device *atadev = device_get_softc(dev);
+ struct acd_softc *cdp = device_get_ivars(dev);
int8_t ccb[16] = { ATAPI_CLOSE_TRACK, 0x01, 0x02, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 };
int timeout = 5*60*2;
int error, dummy;
struct write_param param;
- if ((error = acd_mode_sense(cdp, ATAPI_CDROM_WRITE_PARAMETERS_PAGE,
+ if ((error = acd_mode_sense(dev, ATAPI_CDROM_WRITE_PARAMETERS_PAGE,
(caddr_t)&param, sizeof(param))))
return error;
@@ -1419,24 +1087,24 @@ acd_fixate(struct acd_softc *cdp, int multisession)
else
param.session_type = CDR_SESS_NONE;
- if ((error = acd_mode_select(cdp, (caddr_t)&param, param.page_length + 10)))
+ if ((error = acd_mode_select(dev, (caddr_t)&param, param.page_length + 10)))
return error;
- error = ata_atapicmd(cdp->device, ccb, NULL, 0, 0, 30);
+ error = ata_atapicmd(atadev, ccb, NULL, 0, 0, 30);
if (error)
return error;
/* some drives just return ready, wait for the expected fixate time */
- if ((error = acd_test_ready(cdp->device)) != EBUSY) {
+ if ((error = acd_test_ready(dev)) != EBUSY) {
timeout = timeout / (cdp->cap.cur_write_speed / 177);
tsleep(&error, PRIBIO, "acdfix", timeout * hz / 2);
- return acd_test_ready(cdp->device);
+ return acd_test_ready(dev);
}
while (timeout-- > 0) {
- if ((error = acd_get_progress(cdp, &dummy)))
+ if ((error = acd_get_progress(dev, &dummy)))
return error;
- if ((error = acd_test_ready(cdp->device)) != EBUSY)
+ if ((error = acd_test_ready(dev)) != EBUSY)
return error;
tsleep(&error, PRIBIO, "acdcld", hz / 2);
}
@@ -1444,12 +1112,13 @@ acd_fixate(struct acd_softc *cdp, int multisession)
}
static int
-acd_init_track(struct acd_softc *cdp, struct cdr_track *track)
+acd_init_track(device_t dev, struct cdr_track *track)
{
+ struct acd_softc *cdp = device_get_ivars(dev);
struct write_param param;
int error;
- if ((error = acd_mode_sense(cdp, ATAPI_CDROM_WRITE_PARAMETERS_PAGE,
+ if ((error = acd_mode_sense(dev, ATAPI_CDROM_WRITE_PARAMETERS_PAGE,
(caddr_t)&param, sizeof(param))))
return error;
@@ -1519,30 +1188,31 @@ acd_init_track(struct acd_softc *cdp, struct cdr_track *track)
param.session_format = CDR_SESS_CDROM_XA;
break;
}
- acd_set_ioparm(cdp);
- return acd_mode_select(cdp, (caddr_t)&param, param.page_length + 10);
+ acd_set_ioparm(dev);
+ return acd_mode_select(dev, (caddr_t)&param, param.page_length + 10);
}
static int
-acd_flush(struct acd_softc *cdp)
+acd_flush(device_t dev)
{
+ struct ata_device *atadev = device_get_softc(dev);
int8_t ccb[16] = { ATAPI_SYNCHRONIZE_CACHE, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 };
- return ata_atapicmd(cdp->device, ccb, NULL, 0, ATA_R_QUIET, 60);
+ return ata_atapicmd(atadev, ccb, NULL, 0, ATA_R_QUIET, 60);
}
static int
-acd_read_track_info(struct acd_softc *cdp,
- int32_t lba, struct acd_track_info *info)
+acd_read_track_info(device_t dev, int32_t lba, struct acd_track_info *info)
{
+ struct ata_device *atadev = device_get_softc(dev);
int8_t ccb[16] = { ATAPI_READ_TRACK_INFO, 1,
lba>>24, lba>>16, lba>>8, lba, 0,
sizeof(*info)>>8, sizeof(*info),
0, 0, 0, 0, 0, 0, 0 };
int error;
- if ((error = ata_atapicmd(cdp->device, ccb, (caddr_t)info, sizeof(*info),
+ if ((error = ata_atapicmd(atadev, ccb, (caddr_t)info, sizeof(*info),
ATA_R_READ, 30)))
return error;
info->track_start_addr = ntohl(info->track_start_addr);
@@ -1554,7 +1224,7 @@ acd_read_track_info(struct acd_softc *cdp,
}
static int
-acd_get_progress(struct acd_softc *cdp, int *finished)
+acd_get_progress(device_t dev, int *finished)
{
int8_t ccb[16] = { ATAPI_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 };
@@ -1564,8 +1234,7 @@ acd_get_progress(struct acd_softc *cdp, int *finished)
if (!(request = ata_alloc_request()))
return ENOMEM;
- request->device = cdp->device;
- request->driver = cdp;
+ request->dev = dev;
bcopy(ccb, request->u.atapi.ccb, 16);
request->data = dummy;
request->bytecount = sizeof(dummy);
@@ -1583,8 +1252,10 @@ acd_get_progress(struct acd_softc *cdp, int *finished)
}
static int
-acd_send_cue(struct acd_softc *cdp, struct cdr_cuesheet *cuesheet)
+acd_send_cue(device_t dev, struct cdr_cuesheet *cuesheet)
{
+ struct ata_device *atadev = device_get_softc(dev);
+ struct acd_softc *cdp = device_get_ivars(dev);
struct write_param param;
int8_t ccb[16] = { ATAPI_SEND_CUE_SHEET, 0, 0, 0, 0, 0,
cuesheet->len>>16, cuesheet->len>>8, cuesheet->len,
@@ -1595,7 +1266,7 @@ acd_send_cue(struct acd_softc *cdp, struct cdr_cuesheet *cuesheet)
int i;
#endif
- if ((error = acd_mode_sense(cdp, ATAPI_CDROM_WRITE_PARAMETERS_PAGE,
+ if ((error = acd_mode_sense(dev, ATAPI_CDROM_WRITE_PARAMETERS_PAGE,
(caddr_t)&param, sizeof(param))))
return error;
@@ -1613,7 +1284,7 @@ acd_send_cue(struct acd_softc *cdp, struct cdr_cuesheet *cuesheet)
if (cdp->cap.capabilities & MST_BURNPROOF)
param.burnproof = 1;
- if ((error = acd_mode_select(cdp, (caddr_t)&param, param.page_length + 10)))
+ if ((error = acd_mode_select(dev, (caddr_t)&param, param.page_length + 10)))
return error;
if (!(buffer = malloc(cuesheet->len, M_ACD, M_NOWAIT)))
@@ -1629,15 +1300,16 @@ acd_send_cue(struct acd_softc *cdp, struct cdr_cuesheet *cuesheet)
printf("\n%02x", buffer[i]);
printf("\n");
#endif
- error = ata_atapicmd(cdp->device, ccb, buffer, cuesheet->len, 0, 30);
+ error = ata_atapicmd(atadev, ccb, buffer, cuesheet->len, 0, 30);
}
free(buffer, M_ACD);
return error;
}
static int
-acd_report_key(struct acd_softc *cdp, struct dvd_authinfo *ai)
+acd_report_key(device_t dev, struct dvd_authinfo *ai)
{
+ struct ata_device *atadev = device_get_softc(dev);
struct dvd_miscauth *d = NULL;
u_int32_t lba = 0;
int16_t length;
@@ -1683,7 +1355,7 @@ acd_report_key(struct acd_softc *cdp, struct dvd_authinfo *ai)
d->length = htons(length - 2);
}
- error = ata_atapicmd(cdp->device, ccb, (caddr_t)d, length,
+ error = ata_atapicmd(atadev, ccb, (caddr_t)d, length,
ai->format == DVD_INVALIDATE_AGID ? 0 : ATA_R_READ,10);
if (error) {
free(d, M_ACD);
@@ -1733,8 +1405,9 @@ acd_report_key(struct acd_softc *cdp, struct dvd_authinfo *ai)
}
static int
-acd_send_key(struct acd_softc *cdp, struct dvd_authinfo *ai)
+acd_send_key(device_t dev, struct dvd_authinfo *ai)
{
+ struct ata_device *atadev = device_get_softc(dev);
struct dvd_miscauth *d;
int16_t length;
int8_t ccb[16];
@@ -1772,14 +1445,15 @@ acd_send_key(struct acd_softc *cdp, struct dvd_authinfo *ai)
ccb[9] = length & 0xff;
ccb[10] = (ai->agid << 6) | ai->format;
d->length = htons(length - 2);
- error = ata_atapicmd(cdp->device, ccb, (caddr_t)d, length, 0, 10);
+ error = ata_atapicmd(atadev, ccb, (caddr_t)d, length, 0, 10);
free(d, M_ACD);
return error;
}
static int
-acd_read_structure(struct acd_softc *cdp, struct dvd_struct *s)
+acd_read_structure(device_t dev, struct dvd_struct *s)
{
+ struct ata_device *atadev = device_get_softc(dev);
struct dvd_miscauth *d;
u_int16_t length;
int8_t ccb[16];
@@ -1831,7 +1505,7 @@ acd_read_structure(struct acd_softc *cdp, struct dvd_struct *s)
ccb[8] = (length >> 8) & 0xff;
ccb[9] = length & 0xff;
ccb[10] = s->agid << 6;
- error = ata_atapicmd(cdp->device, ccb, (caddr_t)d, length, ATA_R_READ, 30);
+ error = ata_atapicmd(atadev, ccb, (caddr_t)d, length, ATA_R_READ, 30);
if (error) {
free(d, M_ACD);
return error;
@@ -1884,74 +1558,81 @@ acd_read_structure(struct acd_softc *cdp, struct dvd_struct *s)
}
static int
-acd_tray(struct acd_softc *cdp, int close)
+acd_tray(device_t dev, int close)
{
+ struct ata_device *atadev = device_get_softc(dev);
+ struct acd_softc *cdp = device_get_ivars(dev);
int error = ENODEV;
if (cdp->cap.mechanism & MST_EJECT) {
if (close) {
- if (!(error = acd_start_stop(cdp, 3))) {
- acd_read_toc(cdp);
- acd_prevent_allow(cdp, 1);
+ if (!(error = acd_start_stop(dev, 3))) {
+ acd_read_toc(dev);
+ acd_prevent_allow(dev, 1);
cdp->flags |= F_LOCKED;
}
}
else {
- acd_start_stop(cdp, 0);
- acd_prevent_allow(cdp, 0);
+ acd_start_stop(dev, 0);
+ acd_prevent_allow(dev, 0);
cdp->flags &= ~F_LOCKED;
- cdp->device->flags |= ATA_D_MEDIA_CHANGED;
- error = acd_start_stop(cdp, 2);
+ atadev->flags |= ATA_D_MEDIA_CHANGED;
+ error = acd_start_stop(dev, 2);
}
}
return error;
}
static int
-acd_blank(struct acd_softc *cdp, int blanktype)
+acd_blank(device_t dev, int blanktype)
{
+ struct ata_device *atadev = device_get_softc(dev);
int8_t ccb[16] = { ATAPI_BLANK, 0x10 | (blanktype & 0x7), 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 };
- cdp->device->flags |= ATA_D_MEDIA_CHANGED;
- return ata_atapicmd(cdp->device, ccb, NULL, 0, 0, 30);
+ atadev->flags |= ATA_D_MEDIA_CHANGED;
+ return ata_atapicmd(atadev, ccb, NULL, 0, 0, 30);
}
static int
-acd_prevent_allow(struct acd_softc *cdp, int lock)
+acd_prevent_allow(device_t dev, int lock)
{
+ struct ata_device *atadev = device_get_softc(dev);
int8_t ccb[16] = { ATAPI_PREVENT_ALLOW, 0, 0, 0, lock,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- return ata_atapicmd(cdp->device, ccb, NULL, 0, 0, 30);
+ return ata_atapicmd(atadev, ccb, NULL, 0, 0, 30);
}
static int
-acd_start_stop(struct acd_softc *cdp, int start)
+acd_start_stop(device_t dev, int start)
{
+ struct ata_device *atadev = device_get_softc(dev);
int8_t ccb[16] = { ATAPI_START_STOP, 0, 0, 0, start,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- return ata_atapicmd(cdp->device, ccb, NULL, 0, 0, 30);
+ return ata_atapicmd(atadev, ccb, NULL, 0, 0, 30);
}
static int
-acd_pause_resume(struct acd_softc *cdp, int pause)
+acd_pause_resume(device_t dev, int pause)
{
+ struct ata_device *atadev = device_get_softc(dev);
int8_t ccb[16] = { ATAPI_PAUSE, 0, 0, 0, 0, 0, 0, 0, pause,
0, 0, 0, 0, 0, 0, 0 };
- return ata_atapicmd(cdp->device, ccb, NULL, 0, 0, 30);
+ return ata_atapicmd(atadev, ccb, NULL, 0, 0, 30);
}
static int
-acd_mode_sense(struct acd_softc *cdp, int page, caddr_t pagebuf, int pagesize)
+acd_mode_sense(device_t dev, int page, caddr_t pagebuf, int pagesize)
{
+ struct ata_device *atadev = device_get_softc(dev);
int8_t ccb[16] = { ATAPI_MODE_SENSE_BIG, 0, page, 0, 0, 0, 0,
pagesize>>8, pagesize, 0, 0, 0, 0, 0, 0, 0 };
int error;
- error = ata_atapicmd(cdp->device, ccb, pagebuf, pagesize, ATA_R_READ, 10);
+ error = ata_atapicmd(atadev, ccb, pagebuf, pagesize, ATA_R_READ, 10);
#ifdef ACD_DEBUG
atapi_dump("acd: mode sense ", pagebuf, pagesize);
#endif
@@ -1959,40 +1640,42 @@ acd_mode_sense(struct acd_softc *cdp, int page, caddr_t pagebuf, int pagesize)
}
static int
-acd_mode_select(struct acd_softc *cdp, caddr_t pagebuf, int pagesize)
+acd_mode_select(device_t dev, caddr_t pagebuf, int pagesize)
{
+ struct ata_device *atadev = device_get_softc(dev);
int8_t ccb[16] = { ATAPI_MODE_SELECT_BIG, 0x10, 0, 0, 0, 0, 0,
pagesize>>8, pagesize, 0, 0, 0, 0, 0, 0, 0 };
#ifdef ACD_DEBUG
- ata_prtdev(cdp->device,
- "modeselect pagesize=%d\n", pagesize);
+ device_printf(dev, "modeselect pagesize=%d\n", pagesize);
atapi_dump("mode select ", pagebuf, pagesize);
#endif
- return ata_atapicmd(cdp->device, ccb, pagebuf, pagesize, 0, 30);
+ return ata_atapicmd(atadev, ccb, pagebuf, pagesize, 0, 30);
}
static int
-acd_set_speed(struct acd_softc *cdp, int rdspeed, int wrspeed)
+acd_set_speed(device_t dev, int rdspeed, int wrspeed)
{
+ struct ata_device *atadev = device_get_softc(dev);
int8_t ccb[16] = { ATAPI_SET_SPEED, 0, rdspeed >> 8, rdspeed,
wrspeed >> 8, wrspeed, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int error;
- error = ata_atapicmd(cdp->device, ccb, NULL, 0, 0, 30);
+ error = ata_atapicmd(atadev, ccb, NULL, 0, 0, 30);
if (!error)
- acd_get_cap(cdp);
+ acd_get_cap(dev);
return error;
}
static void
-acd_get_cap(struct acd_softc *cdp)
+acd_get_cap(device_t dev)
{
+ struct acd_softc *cdp = device_get_ivars(dev);
int count;
/* get drive capabilities, some bugridden drives needs this repeated */
for (count = 0 ; count < 5 ; count++) {
- if (!acd_mode_sense(cdp, ATAPI_CDROM_CAP_PAGE,
+ if (!acd_mode_sense(dev, ATAPI_CDROM_CAP_PAGE,
(caddr_t)&cdp->cap, sizeof(cdp->cap)) &&
cdp->cap.page_code == ATAPI_CDROM_CAP_PAGE) {
cdp->cap.max_read_speed = ntohs(cdp->cap.max_read_speed);
@@ -2006,34 +1689,277 @@ acd_get_cap(struct acd_softc *cdp)
}
static int
-acd_read_format_caps(struct acd_softc *cdp, struct cdr_format_capacities *caps)
+acd_read_format_caps(device_t dev, struct cdr_format_capacities *caps)
{
+ struct ata_device *atadev = device_get_softc(dev);
int8_t ccb[16] = { ATAPI_READ_FORMAT_CAPACITIES, 0, 0, 0, 0, 0, 0,
(sizeof(struct cdr_format_capacities) >> 8) & 0xff,
sizeof(struct cdr_format_capacities) & 0xff,
0, 0, 0, 0, 0, 0, 0 };
- return ata_atapicmd(cdp->device, ccb, (caddr_t)caps,
+ return ata_atapicmd(atadev, ccb, (caddr_t)caps,
sizeof(struct cdr_format_capacities), ATA_R_READ, 30);
}
static int
-acd_format(struct acd_softc *cdp, struct cdr_format_params* params)
+acd_format(device_t dev, struct cdr_format_params* params)
{
- int error;
+ struct ata_device *atadev = device_get_softc(dev);
int8_t ccb[16] = { ATAPI_FORMAT, 0x11, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0 };
+ int error;
- error = ata_atapicmd(cdp->device, ccb, (u_int8_t *)params,
+ error = ata_atapicmd(atadev, ccb, (u_int8_t *)params,
sizeof(struct cdr_format_params), 0, 30);
return error;
}
static int
-acd_test_ready(struct ata_device *atadev)
+acd_test_ready(device_t dev)
{
+ struct ata_device *atadev = device_get_softc(dev);
int8_t ccb[16] = { ATAPI_TEST_UNIT_READY, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
return ata_atapicmd(atadev, ccb, NULL, 0, 0, 30);
}
+
+static void
+acd_describe(device_t dev)
+{
+ struct ata_channel *ch = device_get_softc(device_get_parent(dev));
+ struct ata_device *atadev = device_get_softc(dev);
+ struct acd_softc *cdp = device_get_ivars(dev);
+ int comma = 0;
+ char *mechanism;
+
+ if (bootverbose) {
+ device_printf(dev, "<%.40s/%.8s> %s drive at ata%d as %s\n",
+ atadev->param.model, atadev->param.revision,
+ (cdp->cap.media & MST_WRITE_DVDR) ? "DVDR" :
+ (cdp->cap.media & MST_WRITE_DVDRAM) ? "DVDRAM" :
+ (cdp->cap.media & MST_WRITE_CDRW) ? "CDRW" :
+ (cdp->cap.media & MST_WRITE_CDR) ? "CDR" :
+ (cdp->cap.media & MST_READ_DVDROM) ? "DVDROM":"CDROM",
+ device_get_unit(ch->dev),
+ (atadev->unit == ATA_MASTER) ? "master" : "slave");
+
+ device_printf(dev, "%s", "");
+ if (cdp->cap.cur_read_speed) {
+ printf("read %dKB/s", cdp->cap.cur_read_speed * 1000 / 1024);
+ if (cdp->cap.max_read_speed)
+ printf(" (%dKB/s)", cdp->cap.max_read_speed * 1000 / 1024);
+ if ((cdp->cap.cur_write_speed) &&
+ (cdp->cap.media & (MST_WRITE_CDR | MST_WRITE_CDRW |
+ MST_WRITE_DVDR | MST_WRITE_DVDRAM))) {
+ printf(" write %dKB/s", cdp->cap.cur_write_speed * 1000 / 1024);
+ if (cdp->cap.max_write_speed)
+ printf(" (%dKB/s)", cdp->cap.max_write_speed * 1000 / 1024);
+ }
+ comma = 1;
+ }
+ if (cdp->cap.buf_size) {
+ printf("%s %dKB buffer", comma ? "," : "", cdp->cap.buf_size);
+ comma = 1;
+ }
+ printf("%s %s\n", comma ? "," : "", ata_mode2str(atadev->mode));
+
+ device_printf(dev, "Reads:");
+ comma = 0;
+ if (cdp->cap.media & MST_READ_CDR) {
+ printf(" CDR"); comma = 1;
+ }
+ if (cdp->cap.media & MST_READ_CDRW) {
+ printf("%s CDRW", comma ? "," : ""); comma = 1;
+ }
+ if (cdp->cap.capabilities & MST_READ_CDDA) {
+ if (cdp->cap.capabilities & MST_CDDA_STREAM)
+ printf("%s CDDA stream", comma ? "," : "");
+ else
+ printf("%s CDDA", comma ? "," : "");
+ comma = 1;
+ }
+ if (cdp->cap.media & MST_READ_DVDROM) {
+ printf("%s DVDROM", comma ? "," : ""); comma = 1;
+ }
+ if (cdp->cap.media & MST_READ_DVDR) {
+ printf("%s DVDR", comma ? "," : ""); comma = 1;
+ }
+ if (cdp->cap.media & MST_READ_DVDRAM) {
+ printf("%s DVDRAM", comma ? "," : ""); comma = 1;
+ }
+ if (cdp->cap.media & MST_READ_PACKET)
+ printf("%s packet", comma ? "," : "");
+
+ printf("\n");
+ device_printf(dev, "Writes:");
+ if (cdp->cap.media & (MST_WRITE_CDR | MST_WRITE_CDRW |
+ MST_WRITE_DVDR | MST_WRITE_DVDRAM)) {
+ comma = 0;
+ if (cdp->cap.media & MST_WRITE_CDR) {
+ printf(" CDR" ); comma = 1;
+ }
+ if (cdp->cap.media & MST_WRITE_CDRW) {
+ printf("%s CDRW", comma ? "," : ""); comma = 1;
+ }
+ if (cdp->cap.media & MST_WRITE_DVDR) {
+ printf("%s DVDR", comma ? "," : ""); comma = 1;
+ }
+ if (cdp->cap.media & MST_WRITE_DVDRAM) {
+ printf("%s DVDRAM", comma ? "," : ""); comma = 1;
+ }
+ if (cdp->cap.media & MST_WRITE_TEST) {
+ printf("%s test write", comma ? "," : ""); comma = 1;
+ }
+ if (cdp->cap.capabilities & MST_BURNPROOF)
+ printf("%s burnproof", comma ? "," : "");
+ }
+ printf("\n");
+ if (cdp->cap.capabilities & MST_AUDIO_PLAY) {
+ device_printf(dev, "Audio: ");
+ if (cdp->cap.capabilities & MST_AUDIO_PLAY)
+ printf("play");
+ if (cdp->cap.max_vol_levels)
+ printf(", %d volume levels", cdp->cap.max_vol_levels);
+ printf("\n");
+ }
+ device_printf(dev, "Mechanism: ");
+ switch (cdp->cap.mechanism & MST_MECH_MASK) {
+ case MST_MECH_CADDY:
+ mechanism = "caddy"; break;
+ case MST_MECH_TRAY:
+ mechanism = "tray"; break;
+ case MST_MECH_POPUP:
+ mechanism = "popup"; break;
+ case MST_MECH_CHANGER:
+ mechanism = "changer"; break;
+ case MST_MECH_CARTRIDGE:
+ mechanism = "cartridge"; break;
+ default:
+ mechanism = 0; break;
+ }
+ if (mechanism)
+ printf("%s%s", (cdp->cap.mechanism & MST_EJECT) ?
+ "ejectable " : "", mechanism);
+ else if (cdp->cap.mechanism & MST_EJECT)
+ printf("ejectable");
+
+ if (cdp->cap.mechanism & MST_LOCKABLE)
+ printf((cdp->cap.mechanism & MST_LOCKED) ? ", locked":", unlocked");
+ if (cdp->cap.mechanism & MST_PREVENT)
+ printf(", lock protected");
+ printf("\n");
+
+ if ((cdp->cap.mechanism & MST_MECH_MASK) != MST_MECH_CHANGER) {
+ device_printf(dev, "Medium: ");
+ switch (cdp->cap.medium_type & MST_TYPE_MASK_HIGH) {
+ case MST_CDROM:
+ printf("CD-ROM "); break;
+ case MST_CDR:
+ printf("CD-R "); break;
+ case MST_CDRW:
+ printf("CD-RW "); break;
+ case MST_DOOR_OPEN:
+ printf("door open"); break;
+ case MST_NO_DISC:
+ printf("no/blank disc"); break;
+ case MST_FMT_ERROR:
+ printf("medium format error"); break;
+ }
+ if ((cdp->cap.medium_type & MST_TYPE_MASK_HIGH)<MST_TYPE_MASK_HIGH){
+ switch (cdp->cap.medium_type & MST_TYPE_MASK_LOW) {
+ case MST_DATA_120:
+ printf("120mm data disc"); break;
+ case MST_AUDIO_120:
+ printf("120mm audio disc"); break;
+ case MST_COMB_120:
+ printf("120mm data/audio disc"); break;
+ case MST_PHOTO_120:
+ printf("120mm photo disc"); break;
+ case MST_DATA_80:
+ printf("80mm data disc"); break;
+ case MST_AUDIO_80:
+ printf("80mm audio disc"); break;
+ case MST_COMB_80:
+ printf("80mm data/audio disc"); break;
+ case MST_PHOTO_80:
+ printf("80mm photo disc"); break;
+ case MST_FMT_NONE:
+ switch (cdp->cap.medium_type & MST_TYPE_MASK_HIGH) {
+ case MST_CDROM:
+ printf("unknown"); break;
+ case MST_CDR:
+ case MST_CDRW:
+ printf("blank"); break;
+ }
+ break;
+ default:
+ printf("unknown (0x%x)", cdp->cap.medium_type); break;
+ }
+ }
+ printf("\n");
+ }
+ }
+ else {
+ device_printf(dev, "%s ",
+ (cdp->cap.media & MST_WRITE_DVDR) ? "DVDR" :
+ (cdp->cap.media & MST_WRITE_DVDRAM) ? "DVDRAM" :
+ (cdp->cap.media & MST_WRITE_CDRW) ? "CDRW" :
+ (cdp->cap.media & MST_WRITE_CDR) ? "CDR" :
+ (cdp->cap.media & MST_READ_DVDROM) ? "DVDROM" :
+ "CDROM");
+ if (cdp->changer_info)
+ printf("with %d CD changer ", cdp->changer_info->slots);
+ printf("<%.40s/%.8s> at ata%d-%s %s\n",
+ atadev->param.model, atadev->param.revision,
+ device_get_unit(ch->dev),
+ (atadev->unit == ATA_MASTER) ? "master" : "slave",
+ ata_mode2str(atadev->mode) );
+ }
+}
+
+static device_method_t acd_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_identify, acd_identify),
+ DEVMETHOD(device_probe, acd_probe),
+ DEVMETHOD(device_attach, acd_attach),
+ DEVMETHOD(device_detach, acd_detach),
+ DEVMETHOD(device_shutdown, acd_shutdown),
+
+ /* ATA methods */
+ DEVMETHOD(ata_reinit, acd_reinit),
+
+ { 0, 0 }
+};
+
+static driver_t acd_driver = {
+ "acd",
+ acd_methods,
+ sizeof(struct acd_softc)
+};
+
+static devclass_t acd_devclass;
+
+static int
+acd_modevent(module_t mod, int what, void *arg)
+{
+ device_t *devs;
+ int ndevs, i;
+
+ if (what == MOD_LOAD) {
+ g_modevent(0, what, &acd_class);
+ }
+ if (what == MOD_UNLOAD) {
+ if (!devclass_get_devices(acd_devclass, &devs, &ndevs) && devs) {
+ for (i = 0; i < ndevs; i++)
+ device_delete_child(device_get_parent(devs[i]), devs[i]);
+ free(devs, M_TEMP);
+ }
+ g_modevent(0, what, &acd_class);
+ }
+ return 0;
+}
+
+DRIVER_MODULE(acd, ata, acd_driver, acd_devclass, acd_modevent, NULL);
+MODULE_VERSION(acd, 1);
+MODULE_DEPEND(acd, ata, 1, 1, 1);
diff --git a/sys/dev/ata/atapi-cd.h b/sys/dev/ata/atapi-cd.h
index 1618df5..ba16837 100644
--- a/sys/dev/ata/atapi-cd.h
+++ b/sys/dev/ata/atapi-cd.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2004 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2005 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,48 +31,48 @@
/* CDROM Table Of Contents */
#define MAXTRK 99
struct toc {
- struct ioc_toc_header hdr;
- struct cd_toc_entry tab[MAXTRK + 1];
+ struct ioc_toc_header hdr;
+ struct cd_toc_entry tab[MAXTRK + 1];
};
/* DVD CSS authentication */
struct dvd_miscauth {
- u_int16_t length;
- u_int16_t reserved;
- u_int8_t data[2048];
+ u_int16_t length;
+ u_int16_t reserved;
+ u_int8_t data[2048];
};
/* CDROM Audio Control Parameters Page */
struct audiopage {
/* mode page data header */
- u_int16_t data_length;
- u_int8_t medium_type;
- u_int8_t dev_spec;
- u_int8_t unused[2];
- u_int16_t blk_desc_len;
+ u_int16_t data_length;
+ u_int8_t medium_type;
+ u_int8_t dev_spec;
+ u_int8_t unused[2];
+ u_int16_t blk_desc_len;
/* audio control page */
- u_int8_t page_code;
-#define ATAPI_CDROM_AUDIO_PAGE 0x0e
+ u_int8_t page_code;
+#define ATAPI_CDROM_AUDIO_PAGE 0x0e
#define ATAPI_CDROM_AUDIO_PAGE_MASK 0x4e
- u_int8_t param_len;
- u_int8_t flags;
-#define CD_PA_SOTC 0x02
-#define CD_PA_IMMED 0x04
+ u_int8_t param_len;
+ u_int8_t flags;
+#define CD_PA_SOTC 0x02
+#define CD_PA_IMMED 0x04
- u_int8_t reserved3;
- u_int8_t reserved4;
- u_int8_t reserved5;
- u_int16_t lb_per_sec;
+ u_int8_t reserved3;
+ u_int8_t reserved4;
+ u_int8_t reserved5;
+ u_int16_t lb_per_sec;
struct port_control {
- u_int8_t channels:4;
-#define CHANNEL_0 1
-#define CHANNEL_1 2
-#define CHANNEL_2 4
-#define CHANNEL_3 8
+ u_int8_t channels:4;
+#define CHANNEL_0 1
+#define CHANNEL_1 2
+#define CHANNEL_2 4
+#define CHANNEL_3 8
- u_int8_t volume;
+ u_int8_t volume;
} port[4];
};
@@ -80,241 +80,237 @@ struct audiopage {
/* CDROM Capabilities and Mechanical Status Page */
struct cappage {
/* mode page data header */
- u_int16_t data_length;
- u_int8_t medium_type;
-#define MST_TYPE_MASK_LOW 0x0f
-#define MST_FMT_NONE 0x00
-#define MST_DATA_120 0x01
-#define MST_AUDIO_120 0x02
-#define MST_COMB_120 0x03
-#define MST_PHOTO_120 0x04
-#define MST_DATA_80 0x05
-#define MST_AUDIO_80 0x06
-#define MST_COMB_80 0x07
-#define MST_PHOTO_80 0x08
-
-#define MST_TYPE_MASK_HIGH 0x70
-#define MST_CDROM 0x00
-#define MST_CDR 0x10
-#define MST_CDRW 0x20
-
-#define MST_NO_DISC 0x70
-#define MST_DOOR_OPEN 0x71
-#define MST_FMT_ERROR 0x72
-
- u_int8_t dev_spec;
- u_int16_t unused;
- u_int16_t blk_desc_len;
+ u_int16_t data_length;
+ u_int8_t medium_type;
+#define MST_TYPE_MASK_LOW 0x0f
+#define MST_FMT_NONE 0x00
+#define MST_DATA_120 0x01
+#define MST_AUDIO_120 0x02
+#define MST_COMB_120 0x03
+#define MST_PHOTO_120 0x04
+#define MST_DATA_80 0x05
+#define MST_AUDIO_80 0x06
+#define MST_COMB_80 0x07
+#define MST_PHOTO_80 0x08
+
+#define MST_TYPE_MASK_HIGH 0x70
+#define MST_CDROM 0x00
+#define MST_CDR 0x10
+#define MST_CDRW 0x20
+
+#define MST_NO_DISC 0x70
+#define MST_DOOR_OPEN 0x71
+#define MST_FMT_ERROR 0x72
+
+ u_int8_t dev_spec;
+ u_int16_t unused;
+ u_int16_t blk_desc_len;
/* capabilities page */
- u_int8_t page_code;
-#define ATAPI_CDROM_CAP_PAGE 0x2a
-
- u_int8_t param_len;
-
- u_int16_t media;
-#define MST_READ_CDR 0x0001
-#define MST_READ_CDRW 0x0002
-#define MST_READ_PACKET 0x0004
-#define MST_READ_DVDROM 0x0008
-#define MST_READ_DVDR 0x0010
-#define MST_READ_DVDRAM 0x0020
-#define MST_WRITE_CDR 0x0100
-#define MST_WRITE_CDRW 0x0200
-#define MST_WRITE_TEST 0x0400
-#define MST_WRITE_DVDR 0x1000
-#define MST_WRITE_DVDRAM 0x2000
-
- u_int16_t capabilities;
-#define MST_AUDIO_PLAY 0x0001
-#define MST_COMPOSITE 0x0002
-#define MST_AUDIO_P1 0x0004
-#define MST_AUDIO_P2 0x0008
-#define MST_MODE2_f1 0x0010
-#define MST_MODE2_f2 0x0020
-#define MST_MULTISESSION 0x0040
-#define MST_BURNPROOF 0x0080
-#define MST_READ_CDDA 0x0100
-#define MST_CDDA_STREAM 0x0200
-#define MST_COMBINED_RW 0x0400
-#define MST_CORRECTED_RW 0x0800
-#define MST_SUPPORT_C2 0x1000
-#define MST_ISRC 0x2000
-#define MST_UPC 0x4000
-
- u_int8_t mechanism;
-#define MST_LOCKABLE 0x01
-#define MST_LOCKED 0x02
-#define MST_PREVENT 0x04
-#define MST_EJECT 0x08
-#define MST_MECH_MASK 0xe0
-#define MST_MECH_CADDY 0x00
-#define MST_MECH_TRAY 0x20
-#define MST_MECH_POPUP 0x40
-#define MST_MECH_CHANGER 0x80
-#define MST_MECH_CARTRIDGE 0xa0
-
- uint8_t audio;
-#define MST_SEP_VOL 0x01
-#define MST_SEP_MUTE 0x02
-
- u_int16_t max_read_speed; /* max raw data rate in bytes/1000 */
- u_int16_t max_vol_levels; /* number of discrete volume levels */
- u_int16_t buf_size; /* internal buffer size in bytes/1024 */
- u_int16_t cur_read_speed; /* current data rate in bytes/1000 */
-
- u_int8_t reserved3;
- u_int8_t misc;
-
- u_int16_t max_write_speed; /* max raw data rate in bytes/1000 */
- u_int16_t cur_write_speed; /* current data rate in bytes/1000 */
- u_int16_t copy_protect_rev;
- u_int16_t reserved4;
+ u_int8_t page_code;
+#define ATAPI_CDROM_CAP_PAGE 0x2a
+
+ u_int8_t param_len;
+
+ u_int16_t media;
+#define MST_READ_CDR 0x0001
+#define MST_READ_CDRW 0x0002
+#define MST_READ_PACKET 0x0004
+#define MST_READ_DVDROM 0x0008
+#define MST_READ_DVDR 0x0010
+#define MST_READ_DVDRAM 0x0020
+#define MST_WRITE_CDR 0x0100
+#define MST_WRITE_CDRW 0x0200
+#define MST_WRITE_TEST 0x0400
+#define MST_WRITE_DVDR 0x1000
+#define MST_WRITE_DVDRAM 0x2000
+
+ u_int16_t capabilities;
+#define MST_AUDIO_PLAY 0x0001
+#define MST_COMPOSITE 0x0002
+#define MST_AUDIO_P1 0x0004
+#define MST_AUDIO_P2 0x0008
+#define MST_MODE2_f1 0x0010
+#define MST_MODE2_f2 0x0020
+#define MST_MULTISESSION 0x0040
+#define MST_BURNPROOF 0x0080
+#define MST_READ_CDDA 0x0100
+#define MST_CDDA_STREAM 0x0200
+#define MST_COMBINED_RW 0x0400
+#define MST_CORRECTED_RW 0x0800
+#define MST_SUPPORT_C2 0x1000
+#define MST_ISRC 0x2000
+#define MST_UPC 0x4000
+
+ u_int8_t mechanism;
+#define MST_LOCKABLE 0x01
+#define MST_LOCKED 0x02
+#define MST_PREVENT 0x04
+#define MST_EJECT 0x08
+#define MST_MECH_MASK 0xe0
+#define MST_MECH_CADDY 0x00
+#define MST_MECH_TRAY 0x20
+#define MST_MECH_POPUP 0x40
+#define MST_MECH_CHANGER 0x80
+#define MST_MECH_CARTRIDGE 0xa0
+
+ uint8_t audio;
+#define MST_SEP_VOL 0x01
+#define MST_SEP_MUTE 0x02
+
+ u_int16_t max_read_speed; /* max raw data rate in bytes/1000 */
+ u_int16_t max_vol_levels; /* number of discrete volume levels */
+ u_int16_t buf_size; /* internal buffer size in bytes/1024 */
+ u_int16_t cur_read_speed; /* current data rate in bytes/1000 */
+
+ u_int8_t reserved3;
+ u_int8_t misc;
+
+ u_int16_t max_write_speed; /* max raw data rate in bytes/1000 */
+ u_int16_t cur_write_speed; /* current data rate in bytes/1000 */
+ u_int16_t copy_protect_rev;
+ u_int16_t reserved4;
};
-#define CH_READY 0
-#define CH_LOADING 1
-#define CH_UNLOADING 2
-#define CH_INITIALIZING 3
+#define CH_READY 0
+#define CH_LOADING 1
+#define CH_UNLOADING 2
+#define CH_INITIALIZING 3
-#define CD_IDLE 0
-#define CD_AUDIO_ACTIVE 1
-#define CD_AUDIO_SCAN 2
-#define CD_HOST_ACTIVE 3
-#define CD_NO_STATE 7
+#define CD_IDLE 0
+#define CD_AUDIO_ACTIVE 1
+#define CD_AUDIO_SCAN 2
+#define CD_HOST_ACTIVE 3
+#define CD_NO_STATE 7
/* CDROM Changer mechanism status structure */
struct changer {
- u_int8_t current_slot :5; /* active changer slot */
- u_int8_t mech_state :2; /* current changer state */
+ u_int8_t current_slot :5; /* active changer slot */
+ u_int8_t mech_state :2; /* current changer state */
- u_int8_t fault :1; /* fault in last operation */
- u_int8_t reserved0 :5;
- u_int8_t cd_state :3; /* current mechanism state */
+ u_int8_t fault :1; /* fault in last operation */
+ u_int8_t reserved0 :5;
+ u_int8_t cd_state :3; /* current mechanism state */
- u_int8_t current_lba[3]; /* current LBA */
- u_int8_t slots; /* number of available slots */
- u_int16_t table_length; /* slot table length */
+ u_int8_t current_lba[3]; /* current LBA */
+ u_int8_t slots; /* number of available slots */
+ u_int16_t table_length; /* slot table length */
struct {
- u_int8_t changed :1; /* media has changed in this slot */
- u_int8_t unused :6;
- u_int8_t present :1; /* slot has a CD present */
- u_int8_t reserved0;
- u_int8_t reserved1;
- u_int8_t reserved2;
+ u_int8_t changed :1; /* media has changed in this slot */
+ u_int8_t unused :6;
+ u_int8_t present :1; /* slot has a CD present */
+ u_int8_t reserved0;
+ u_int8_t reserved1;
+ u_int8_t reserved2;
} slot[32];
};
/* CDROM Write Parameters Mode Page (Burners ONLY) */
struct write_param {
/* mode page data header */
- u_int16_t data_length;
- u_int8_t medium_type;
- u_int8_t dev_spec;
- u_int8_t unused[2];
- u_int16_t blk_desc_len;
+ u_int16_t data_length;
+ u_int8_t medium_type;
+ u_int8_t dev_spec;
+ u_int8_t unused[2];
+ u_int16_t blk_desc_len;
/* write parameters page */
- u_int8_t page_code;
+ u_int8_t page_code;
#define ATAPI_CDROM_WRITE_PARAMETERS_PAGE 0x05
- u_int8_t page_length; /* 0x32 */
- u_int8_t write_type :4; /* write stream type */
-#define CDR_WTYPE_PACKET 0x00
-#define CDR_WTYPE_TRACK 0x01
-#define CDR_WTYPE_SESSION 0x02
-#define CDR_WTYPE_RAW 0x03
-
- u_int8_t test_write :1; /* test write enable */
- u_int8_t link_size_valid :1;
- u_int8_t burnproof :1; /* BurnProof enable */
- u_int8_t reserved2_7 :1;
- u_int8_t track_mode :4; /* track mode */
-#define CDR_TMODE_AUDIO 0x00
-#define CDR_TMODE_AUDIO_PREEMP 0x01
-#define CDR_TMODE_ALLOW_COPY 0x02
-#define CDR_TMODE_DATA 0x04
-#define CDR_TMODE_QUAD_AUDIO 0x08
-
- u_int8_t copy :1; /* generation stamp */
- u_int8_t fp :1; /* fixed packet type */
- u_int8_t session_type :2; /* session type */
-#define CDR_SESS_NONE 0x00
-#define CDR_SESS_FINAL 0x01
-#define CDR_SESS_RESERVED 0x02
-#define CDR_SESS_MULTI 0x03
-
- u_int8_t datablock_type :4; /* data type code (see cdrio.h) */
- u_int8_t reserved4_4567 :4;
- u_int8_t link_size;
- u_int8_t reserved6;
- u_int8_t host_app_code :6; /* host application code */
- u_int8_t reserved7_67 :2;
- u_int8_t session_format; /* session format */
-#define CDR_SESS_CDROM 0x00
-#define CDR_SESS_CDI 0x10
-#define CDR_SESS_CDROM_XA 0x20
-
- u_int8_t reserved9;
- u_int32_t packet_size; /* packet size in bytes */
- u_int16_t audio_pause_length; /* audio pause length in secs */
- u_int8_t media_catalog_number[16];
- u_int8_t isr_code[16];
- u_int8_t sub_hdr_byte0;
- u_int8_t sub_hdr_byte1;
- u_int8_t sub_hdr_byte2;
- u_int8_t sub_hdr_byte3;
- u_int8_t vendor_specific_byte0;
- u_int8_t vendor_specific_byte1;
- u_int8_t vendor_specific_byte2;
- u_int8_t vendor_specific_byte3;
+ u_int8_t page_length; /* 0x32 */
+ u_int8_t write_type :4; /* write stream type */
+#define CDR_WTYPE_PACKET 0x00
+#define CDR_WTYPE_TRACK 0x01
+#define CDR_WTYPE_SESSION 0x02
+#define CDR_WTYPE_RAW 0x03
+
+ u_int8_t test_write :1; /* test write enable */
+ u_int8_t link_size_valid :1;
+ u_int8_t burnproof :1; /* BurnProof enable */
+ u_int8_t reserved2_7 :1;
+ u_int8_t track_mode :4; /* track mode */
+#define CDR_TMODE_AUDIO 0x00
+#define CDR_TMODE_AUDIO_PREEMP 0x01
+#define CDR_TMODE_ALLOW_COPY 0x02
+#define CDR_TMODE_DATA 0x04
+#define CDR_TMODE_QUAD_AUDIO 0x08
+
+ u_int8_t copy :1; /* generation stamp */
+ u_int8_t fp :1; /* fixed packet type */
+ u_int8_t session_type :2; /* session type */
+#define CDR_SESS_NONE 0x00
+#define CDR_SESS_FINAL 0x01
+#define CDR_SESS_RESERVED 0x02
+#define CDR_SESS_MULTI 0x03
+
+ u_int8_t datablock_type :4; /* data type code (see cdrio.h) */
+ u_int8_t reserved4_4567 :4;
+ u_int8_t link_size;
+ u_int8_t reserved6;
+ u_int8_t host_app_code :6; /* host application code */
+ u_int8_t reserved7_67 :2;
+ u_int8_t session_format; /* session format */
+#define CDR_SESS_CDROM 0x00
+#define CDR_SESS_CDI 0x10
+#define CDR_SESS_CDROM_XA 0x20
+
+ u_int8_t reserved9;
+ u_int32_t packet_size; /* packet size in bytes */
+ u_int16_t audio_pause_length; /* audio pause length in secs */
+ u_int8_t media_catalog_number[16];
+ u_int8_t isr_code[16];
+ u_int8_t sub_hdr_byte0;
+ u_int8_t sub_hdr_byte1;
+ u_int8_t sub_hdr_byte2;
+ u_int8_t sub_hdr_byte3;
+ u_int8_t vendor_specific_byte0;
+ u_int8_t vendor_specific_byte1;
+ u_int8_t vendor_specific_byte2;
+ u_int8_t vendor_specific_byte3;
} __packed;
/* CDROM Read Track Information structure */
struct acd_track_info {
- u_int16_t data_length;
- u_int8_t track_number; /* current track number */
- u_int8_t session_number; /* current session number */
- u_int8_t reserved4;
- u_int8_t track_mode :4; /* mode of this track */
- u_int8_t copy :1; /* generation stamp */
- u_int8_t damage :1; /* damaged track */
- u_int8_t reserved5_67 :2;
- u_int8_t data_mode :4; /* data mode of this disc */
- u_int8_t fp :1; /* fixed packet */
- u_int8_t packet :1; /* packet track */
- u_int8_t blank :1; /* blank (empty) track */
- u_int8_t rt :1; /* reserved track */
- u_int8_t nwa_valid :1; /* next_writeable_addr field valid */
- u_int8_t reserved7_17 :7;
- u_int track_start_addr; /* start of this track */
- u_int next_writeable_addr; /* next writeable addr on this disc */
- u_int free_blocks; /* free block on this disc */
- u_int fixed_packet_size; /* size of packets on this track */
- u_int track_length; /* length of this track */
+ u_int16_t data_length;
+ u_int8_t track_number; /* current track number */
+ u_int8_t session_number; /* current session number */
+ u_int8_t reserved4;
+ u_int8_t track_mode :4; /* mode of this track */
+ u_int8_t copy :1; /* generation stamp */
+ u_int8_t damage :1; /* damaged track */
+ u_int8_t reserved5_67 :2;
+ u_int8_t data_mode :4; /* data mode of this disc */
+ u_int8_t fp :1; /* fixed packet */
+ u_int8_t packet :1; /* packet track */
+ u_int8_t blank :1; /* blank (empty) track */
+ u_int8_t rt :1; /* reserved track */
+ u_int8_t nwa_valid :1; /* next_writeable_addr field valid */
+ u_int8_t reserved7_17 :7;
+ u_int track_start_addr; /* start of this track */
+ u_int next_writeable_addr; /* next writeable addr on this disc */
+ u_int free_blocks; /* free block on this disc */
+ u_int fixed_packet_size; /* size of packets on this track */
+ u_int track_length; /* length of this track */
};
/* Structure describing an ATAPI CDROM device */
struct acd_softc {
- struct ata_device *device; /* device softc */
- int lun; /* logical device unit */
- int flags; /* device state flags */
-#define F_LOCKED 0x0001 /* this unit is locked */
-
- struct mtx queue_mtx; /* bio queue lock */
- struct bio_queue_head queue; /* queue of i/o requests */
- struct toc toc; /* table of disc contents */
- struct audiopage au; /* audio page info */
- struct audiopage aumask; /* audio page mask */
- struct cappage cap; /* capabilities page info */
- struct cd_sub_channel_info subchan; /* subchannel info */
- struct changer *changer_info; /* changer info */
- struct acd_softc **driver; /* softc's of changer slots */
- int slot; /* this instance slot number */
- time_t timestamp; /* this instance timestamp */
- u_int32_t disk_size; /* size of current media */
- u_int32_t block_size; /* blocksize currently used */
- u_int32_t iomax; /* Max I/O request (bytes) */
- struct g_geom *gp; /* geom instance */
- struct g_provider *pp[MAXTRK+1]; /* providers */
+ int flags; /* device state flags */
+#define F_LOCKED 0x0001 /* this unit is locked */
+
+ struct toc toc; /* table of disc contents */
+ struct audiopage au; /* audio page info */
+ struct audiopage aumask; /* audio page mask */
+ struct cappage cap; /* capabilities page info */
+ struct cd_sub_channel_info subchan; /* subchannel info */
+ struct changer *changer_info; /* changer info */
+ struct acd_softc **driver; /* softc's of changer slots */
+ int slot; /* this instance slot number */
+ time_t timestamp; /* this instance timestamp */
+ u_int32_t disk_size; /* size of current media */
+ u_int32_t block_size; /* blocksize currently used */
+ u_int32_t iomax; /* Max I/O request (bytes) */
+ struct g_geom *gp; /* geom instance */
+ struct g_provider *pp[MAXTRK+1]; /* providers */
};
diff --git a/sys/dev/ata/atapi-fd.c b/sys/dev/ata/atapi-fd.c
index 9fda140..0c701c4 100644
--- a/sys/dev/ata/atapi-fd.c
+++ b/sys/dev/ata/atapi-fd.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2004 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2005 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/ata.h>
#include <sys/kernel.h>
+#include <sys/module.h>
#include <sys/malloc.h>
#include <sys/bio.h>
#include <sys/bus.h>
@@ -45,196 +46,143 @@ __FBSDID("$FreeBSD$");
#include <geom/geom_disk.h>
#include <dev/ata/ata-all.h>
#include <dev/ata/atapi-fd.h>
+#include <ata_if.h>
+
/* prototypes */
-static disk_open_t afd_open;
-static disk_close_t afd_close;
-#ifdef notyet
-static disk_ioctl_t afd_ioctl;
-#endif
-static disk_strategy_t afdstrategy;
-static void afd_detach(struct ata_device *);
-static void afd_start(struct ata_device *);
-static int afd_sense(struct afd_softc *);
-static void afd_describe(struct afd_softc *);
+static disk_open_t afd_open;
+static disk_close_t afd_close;
+static disk_strategy_t afd_strategy;
+static int afd_sense(device_t);
+static void afd_describe(device_t);
static void afd_done(struct ata_request *);
-static int afd_eject(struct afd_softc *, int);
-static int afd_start_stop(struct afd_softc *, int);
-static int afd_prevent_allow(struct afd_softc *, int);
-static int afd_test_ready(struct ata_device *);
+static int afd_prevent_allow(device_t, int);
+static int afd_test_ready(device_t);
/* internal vars */
-static u_int32_t afd_lun_map = 0;
static MALLOC_DEFINE(M_AFD, "AFD driver", "ATAPI floppy driver buffers");
-void
-afd_attach(struct ata_device *atadev)
+static void
+afd_identify(driver_t *driver, device_t parent)
+{
+ ata_identify(driver, parent, ATA_ATAPI_TYPE_DIRECT, "afd");
+}
+
+static int
+afd_probe(device_t dev)
+{
+ return 0;
+}
+
+static int
+afd_attach(device_t dev)
{
+ struct ata_channel *ch = device_get_softc(device_get_parent(dev));
+ struct ata_device *atadev = device_get_softc(dev);
struct afd_softc *fdp;
- fdp = malloc(sizeof(struct afd_softc), M_AFD, M_NOWAIT | M_ZERO);
- if (!fdp) {
- ata_prtdev(atadev, "out of memory\n");
- return;
+ if (!(fdp = malloc(sizeof(struct afd_softc), M_AFD, M_NOWAIT | M_ZERO))) {
+ device_printf(dev, "out of memory\n");
+ device_set_softc(dev, NULL);
+ free(atadev, M_ATA);
+ return ENOMEM;
}
+ device_set_ivars(dev, fdp);
+ ATA_SETMODE(GRANDPARENT(dev), dev);
- fdp->device = atadev;
- fdp->lun = ata_get_lun(&afd_lun_map);
- ata_set_name(atadev, "afd", fdp->lun);
- bioq_init(&fdp->queue);
- mtx_init(&fdp->queue_mtx, "ATAPI FD bioqueue lock", NULL, MTX_DEF);
-
- if (afd_sense(fdp)) {
+ if (afd_sense(dev)) {
+ device_set_ivars(dev, NULL);
free(fdp, M_AFD);
- return;
+ device_set_softc(dev, NULL);
+ free(atadev, M_ATA);
+ return ENXIO;
}
-
- /* setup the function ptrs */
- atadev->detach = afd_detach;
- atadev->start = afd_start;
- atadev->softc = fdp;
atadev->flags |= ATA_D_MEDIA_CHANGED;
- /* lets create the disk device */
+ /* announce we are here */
+ afd_describe(dev);
+
+ /* create the disk device */
fdp->disk = disk_alloc();
fdp->disk->d_open = afd_open;
fdp->disk->d_close = afd_close;
-#ifdef notyet
- fdp->disk->d_ioctl = afd_ioctl;
-#endif
- fdp->disk->d_strategy = afdstrategy;
+ fdp->disk->d_strategy = afd_strategy;
fdp->disk->d_name = "afd";
- fdp->disk->d_drv1 = fdp;
- if (atadev->channel->dma)
- fdp->disk->d_maxsize = atadev->channel->dma->max_iosize;
+ fdp->disk->d_drv1 = dev;
+ if (ch->dma)
+ fdp->disk->d_maxsize = ch->dma->max_iosize;
else
fdp->disk->d_maxsize = DFLTPHYS;
- fdp->disk->d_unit = fdp->lun;
+ fdp->disk->d_unit = device_get_unit(dev);
disk_create(fdp->disk, DISK_VERSION);
-
- /* announce we are here */
- afd_describe(fdp);
+ return 0;
}
-static void
-afd_detach(struct ata_device *atadev)
+static int
+afd_detach(device_t dev)
{
- struct afd_softc *fdp = atadev->softc;
+ struct ata_channel *ch = device_get_softc(device_get_parent(dev));
+ struct ata_device *atadev = device_get_softc(dev);
+ struct afd_softc *fdp = device_get_ivars(dev);
- mtx_lock(&fdp->queue_mtx);
- bioq_flush(&fdp->queue, NULL, ENXIO);
- mtx_unlock(&fdp->queue_mtx);
- mtx_destroy(&fdp->queue_mtx);
+ /* detroy disk from the system so we dont get any further requests */
disk_destroy(fdp->disk);
- ata_prtdev(atadev, "WARNING - removed from configuration\n");
- ata_free_name(atadev);
- ata_free_lun(&afd_lun_map, fdp->lun);
- atadev->attach = NULL;
- atadev->detach = NULL;
- atadev->start = NULL;
- atadev->softc = NULL;
- atadev->flags = 0;
- free(fdp, M_AFD);
-}
-static int
-afd_sense(struct afd_softc *fdp)
-{
- int8_t ccb[16] = { ATAPI_MODE_SENSE_BIG, 0, ATAPI_REWRITEABLE_CAP_PAGE,
- 0, 0, 0, 0, sizeof(struct afd_cappage) >> 8,
- sizeof(struct afd_cappage) & 0xff, 0, 0, 0, 0, 0, 0, 0 };
- int count;
+ /* fail requests on the queue and any thats "in flight" for this device */
+ ata_fail_requests(ch, dev);
- /* The IOMEGA Clik! doesn't support reading the cap page, fake it */
- if (!strncmp(fdp->device->param->model, "IOMEGA Clik!", 12)) {
- fdp->cap.transfer_rate = 500;
- fdp->cap.heads = 1;
- fdp->cap.sectors = 2;
- fdp->cap.cylinders = 39441;
- fdp->cap.sector_size = 512;
- afd_test_ready(fdp->device);
- return 0;
- }
-
- /* get drive capabilities, some bugridden drives needs this repeated */
- for (count = 0 ; count < 5 ; count++) {
- if (!ata_atapicmd(fdp->device, ccb, (caddr_t)&fdp->cap,
- sizeof(struct afd_cappage), ATA_R_READ, 30) &&
- fdp->cap.page_code == ATAPI_REWRITEABLE_CAP_PAGE) {
- fdp->cap.cylinders = ntohs(fdp->cap.cylinders);
- fdp->cap.sector_size = ntohs(fdp->cap.sector_size);
- fdp->cap.transfer_rate = ntohs(fdp->cap.transfer_rate);
- return 0;
- }
- }
- return 1;
+ /* dont leave anything behind */
+ device_set_ivars(dev, NULL);
+ free(fdp, M_AFD);
+ device_set_softc(dev, NULL);
+ free(atadev, M_ATA);
+ return 0;
}
-static void
-afd_describe(struct afd_softc *fdp)
+static void
+afd_shutdown(device_t dev)
{
- if (bootverbose) {
- ata_prtdev(fdp->device,
- "<%.40s/%.8s> removable drive at ata%d as %s\n",
- fdp->device->param->model, fdp->device->param->revision,
- device_get_unit(fdp->device->channel->dev),
- (fdp->device->unit == ATA_MASTER) ? "master" : "slave");
- ata_prtdev(fdp->device,
- "%luMB (%u sectors), %u cyls, %u heads, %u S/T, %u B/S\n",
- (fdp->cap.cylinders * fdp->cap.heads * fdp->cap.sectors) /
- ((1024L * 1024L) / fdp->cap.sector_size),
- fdp->cap.cylinders * fdp->cap.heads * fdp->cap.sectors,
- fdp->cap.cylinders, fdp->cap.heads, fdp->cap.sectors,
- fdp->cap.sector_size);
- ata_prtdev(fdp->device, "%dKB/s,", fdp->cap.transfer_rate / 8);
- printf(" %s\n", ata_mode2str(fdp->device->mode));
- if (fdp->cap.medium_type) {
- ata_prtdev(fdp->device, "Medium: ");
- switch (fdp->cap.medium_type) {
- case MFD_2DD:
- printf("720KB DD disk"); break;
+ struct ata_device *atadev = device_get_softc(dev);
- case MFD_HD_12:
- printf("1.2MB HD disk"); break;
-
- case MFD_HD_144:
- printf("1.44MB HD disk"); break;
-
- case MFD_UHD:
- printf("120MB UHD disk"); break;
+ if (atadev->param.support.command2 & ATA_SUPPORT_FLUSHCACHE)
+ ata_controlcmd(atadev, ATA_FLUSHCACHE, 0, 0, 0);
+}
- default:
- printf("Unknown (0x%x)", fdp->cap.medium_type);
- }
- if (fdp->cap.wp) printf(", writeprotected");
- printf("\n");
- }
- }
- else {
- ata_prtdev(fdp->device, "REMOVABLE <%.40s/%.8s> at ata%d-%s %s\n",
- fdp->device->param->model, fdp->device->param->revision,
- device_get_unit(fdp->device->channel->dev),
- (fdp->device->unit == ATA_MASTER) ? "master" : "slave",
- ata_mode2str(fdp->device->mode));
+static int
+afd_reinit(device_t dev)
+{
+ struct ata_channel *ch = device_get_softc(device_get_parent(dev));
+ struct ata_device *atadev = device_get_softc(dev);
+ struct afd_softc *fdp = device_get_ivars(dev);
+
+ if (((atadev->unit == ATA_MASTER) && !(ch->devices & ATA_ATAPI_MASTER)) ||
+ ((atadev->unit == ATA_SLAVE) && !(ch->devices & ATA_ATAPI_SLAVE))) {
+ device_set_ivars(dev, NULL);
+ free(fdp, M_AFD);
+ return 1;
}
+ ATA_SETMODE(GRANDPARENT(dev), dev);
+ return 0;
}
static int
afd_open(struct disk *dp)
{
- struct afd_softc *fdp = dp->d_drv1;
+ device_t dev = dp->d_drv1;
+ struct ata_device *atadev = device_get_softc(dev);
+ struct afd_softc *fdp = device_get_ivars(dev);
- if (fdp->device->flags & ATA_D_DETACHING)
+ if (!fdp)
return ENXIO;
+ if (!device_is_attached(dev))
+ return EBUSY;
- afd_test_ready(fdp->device);
-
- afd_prevent_allow(fdp, 1);
-
- if (afd_sense(fdp))
- ata_prtdev(fdp->device, "sense media type failed\n");
+ afd_test_ready(dev);
+ afd_prevent_allow(dev, 1);
- fdp->device->flags &= ~ATA_D_MEDIA_CHANGED;
+ if (afd_sense(dev))
+ device_printf(dev, "sense media type failed\n");
+ atadev->flags &= ~ATA_D_MEDIA_CHANGED;
fdp->disk->d_sectorsize = fdp->cap.sector_size;
fdp->disk->d_mediasize = (off_t)fdp->cap.sector_size * fdp->cap.sectors *
@@ -248,47 +196,21 @@ afd_open(struct disk *dp)
static int
afd_close(struct disk *dp)
{
- struct afd_softc *fdp = dp->d_drv1;
-
- afd_prevent_allow(fdp, 0);
- if (0)
- afd_eject(fdp, 0); /* to keep gcc quiet */
+ device_t dev = dp->d_drv1;
+ afd_prevent_allow(dev, 0);
return 0;
}
-#ifdef notyet
-static int
-afd_ioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
-{
- struct afd_softc *fdp = dp->d_drv1;
-
- switch (cmd) {
- case CDIOCEJECT:
- if (count_dev(dev) > 1)
- return EBUSY;
- return afd_eject(fdp, 0);
-
- case CDIOCCLOSE:
- if (count_dev(dev) > 1)
- return 0;
- return afd_eject(fdp, 1);
-
- default:
- return ENOIOCTL;
- }
-}
-#endif
-
static void
-afdstrategy(struct bio *bp)
+afd_strategy(struct bio *bp)
{
- struct afd_softc *fdp = bp->bio_disk->d_drv1;
-
- if (fdp->device->flags & ATA_D_DETACHING) {
- biofinish(bp, NULL, ENXIO);
- return;
- }
+ device_t dev = bp->bio_disk->d_drv1;
+ struct ata_device *atadev = device_get_softc(dev);
+ struct afd_softc *fdp = device_get_ivars(dev);
+ struct ata_request *request;
+ u_int16_t count;
+ int8_t ccb[16];
/* if it's a null transfer, return immediatly. */
if (bp->bio_bcount == 0) {
@@ -297,39 +219,12 @@ afdstrategy(struct bio *bp)
return;
}
- mtx_lock(&fdp->queue_mtx);
- bioq_disksort(&fdp->queue, bp);
- mtx_unlock(&fdp->queue_mtx);
- ata_start(fdp->device->channel);
-}
-
-static void
-afd_start(struct ata_device *atadev)
-{
- struct afd_softc *fdp = atadev->softc;
- struct bio *bp;
- struct ata_request *request;
- u_int32_t lba;
- u_int16_t count;
- int8_t ccb[16];
-
-
- mtx_lock(&fdp->queue_mtx);
- bp = bioq_first(&fdp->queue);
- if (!bp) {
- mtx_unlock(&fdp->queue_mtx);
- return;
- }
- bioq_remove(&fdp->queue, bp);
- mtx_unlock(&fdp->queue_mtx);
-
/* should reject all queued entries if media have changed. */
- if (fdp->device->flags & ATA_D_MEDIA_CHANGED) {
+ if (atadev->flags & ATA_D_MEDIA_CHANGED) {
biofinish(bp, NULL, EIO);
return;
}
- lba = bp->bio_pblkno;
count = bp->bio_bcount / fdp->cap.sector_size;
bp->bio_resid = bp->bio_bcount;
@@ -340,10 +235,10 @@ afd_start(struct ata_device *atadev)
else
ccb[0] = ATAPI_WRITE_BIG;
- ccb[2] = lba>>24;
- ccb[3] = lba>>16;
- ccb[4] = lba>>8;
- ccb[5] = lba;
+ ccb[2] = bp->bio_pblkno >> 24;
+ ccb[3] = bp->bio_pblkno >> 16;
+ ccb[4] = bp->bio_pblkno >> 8;
+ ccb[5] = bp->bio_pblkno;
ccb[7] = count>>8;
ccb[8] = count;
@@ -351,10 +246,10 @@ afd_start(struct ata_device *atadev)
biofinish(bp, NULL, ENOMEM);
return;
}
- request->device = atadev;
- request->driver = bp;
+ request->dev = dev;
+ request->bio = bp;
bcopy(ccb, request->u.atapi.ccb,
- (request->device->param->config & ATA_PROTO_MASK) ==
+ (atadev->param.config & ATA_PROTO_MASK) ==
ATA_PROTO_ATAPI_12 ? 16 : 12);
request->data = bp->bio_data;
request->bytecount = count * fdp->cap.sector_size;
@@ -364,25 +259,27 @@ afd_start(struct ata_device *atadev)
request->callback = afd_done;
switch (bp->bio_cmd) {
case BIO_READ:
- request->flags |= (ATA_R_ATAPI | ATA_R_READ);
+ request->flags = (ATA_R_ATAPI | ATA_R_READ);
break;
case BIO_WRITE:
- request->flags |= (ATA_R_ATAPI | ATA_R_WRITE);
+ request->flags = (ATA_R_ATAPI | ATA_R_WRITE);
break;
default:
- ata_prtdev(atadev, "unknown BIO operation\n");
+ device_printf(dev, "unknown BIO operation\n");
ata_free_request(request);
biofinish(bp, NULL, EIO);
return;
}
+ if (atadev->mode >= ATA_DMA)
+ request->flags |= ATA_R_DMA;
+ request->flags |= ATA_R_ORDERED;
ata_queue_request(request);
-
}
static void
afd_done(struct ata_request *request)
{
- struct bio *bp = request->driver;
+ struct bio *bp = request->bio;
/* finish up transfer */
if ((bp->bio_error = request->result))
@@ -393,52 +290,153 @@ afd_done(struct ata_request *request)
}
static int
-afd_eject(struct afd_softc *fdp, int close)
+afd_sense(device_t dev)
{
- int error;
-
- if ((error = afd_start_stop(fdp, 0)) == EBUSY) {
- if (!close)
- return 0;
- if ((error = afd_start_stop(fdp, 3)))
- return error;
- return afd_prevent_allow(fdp, 1);
- }
- if (error)
- return error;
- if (close)
- return 0;
- if ((error = afd_prevent_allow(fdp, 0)))
- return error;
- fdp->device->flags |= ATA_D_MEDIA_CHANGED;
- return afd_start_stop(fdp, 2);
-}
+ struct ata_device *atadev = device_get_softc(dev);
+ struct afd_softc *fdp = device_get_ivars(dev);
+ int8_t ccb[16] = { ATAPI_MODE_SENSE_BIG, 0, ATAPI_REWRITEABLE_CAP_PAGE,
+ 0, 0, 0, 0, sizeof(struct afd_cappage) >> 8,
+ sizeof(struct afd_cappage) & 0xff, 0, 0, 0, 0, 0, 0, 0 };
+ int count;
-static int
-afd_start_stop(struct afd_softc *fdp, int start)
-{
- int8_t ccb[16] = { ATAPI_START_STOP, 0, 0, 0, start,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ /* The IOMEGA Clik! doesn't support reading the cap page, fake it */
+ if (!strncmp(atadev->param.model, "IOMEGA Clik!", 12)) {
+ fdp->cap.transfer_rate = 500;
+ fdp->cap.heads = 1;
+ fdp->cap.sectors = 2;
+ fdp->cap.cylinders = 39441;
+ fdp->cap.sector_size = 512;
+ afd_test_ready(dev);
+ return 0;
+ }
- return ata_atapicmd(fdp->device, ccb, NULL, 0, 0, 30);
+ /* get drive capabilities, some bugridden drives needs this repeated */
+ for (count = 0 ; count < 5 ; count++) {
+ if (!ata_atapicmd(atadev, ccb, (caddr_t)&fdp->cap,
+ sizeof(struct afd_cappage), ATA_R_READ, 30) &&
+ fdp->cap.page_code == ATAPI_REWRITEABLE_CAP_PAGE) {
+ fdp->cap.cylinders = ntohs(fdp->cap.cylinders);
+ fdp->cap.sector_size = ntohs(fdp->cap.sector_size);
+ fdp->cap.transfer_rate = ntohs(fdp->cap.transfer_rate);
+ return 0;
+ }
+ }
+ return 1;
}
static int
-afd_prevent_allow(struct afd_softc *fdp, int lock)
+afd_prevent_allow(device_t dev, int lock)
{
+ struct ata_device *atadev = device_get_softc(dev);
int8_t ccb[16] = { ATAPI_PREVENT_ALLOW, 0, 0, 0, lock,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- if (!strncmp(fdp->device->param->model, "IOMEGA Clik!", 12))
+ if (!strncmp(atadev->param.model, "IOMEGA Clik!", 12))
return 0;
- return ata_atapicmd(fdp->device, ccb, NULL, 0, 0, 30);
+ return ata_atapicmd(atadev, ccb, NULL, 0, 0, 30);
}
static int
-afd_test_ready(struct ata_device *atadev)
+afd_test_ready(device_t dev)
{
+ struct ata_device *atadev = device_get_softc(dev);
int8_t ccb[16] = { ATAPI_TEST_UNIT_READY, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
return ata_atapicmd(atadev, ccb, NULL, 0, 0, 30);
}
+
+static void
+afd_describe(device_t dev)
+{
+ struct ata_channel *ch = device_get_softc(device_get_parent(dev));
+ struct ata_device *atadev = device_get_softc(dev);
+ struct afd_softc *fdp = device_get_ivars(dev);
+
+ if (bootverbose) {
+ device_printf(dev, "<%.40s/%.8s> removable drive at ata%d as %s\n",
+ atadev->param.model, atadev->param.revision,
+ device_get_unit(ch->dev),
+ (atadev->unit == ATA_MASTER) ? "master" : "slave");
+ device_printf(dev,
+ "%luMB (%u sectors), %u cyls, %u heads, %u S/T, %u B/S\n",
+ (fdp->cap.cylinders * fdp->cap.heads * fdp->cap.sectors) /
+ ((1024L * 1024L) / fdp->cap.sector_size),
+ fdp->cap.cylinders * fdp->cap.heads * fdp->cap.sectors,
+ fdp->cap.cylinders, fdp->cap.heads, fdp->cap.sectors,
+ fdp->cap.sector_size);
+ device_printf(dev, "%dKB/s,", fdp->cap.transfer_rate / 8);
+ printf(" %s\n", ata_mode2str(atadev->mode));
+ if (fdp->cap.medium_type) {
+ device_printf(dev, "Medium: ");
+ switch (fdp->cap.medium_type) {
+ case MFD_2DD:
+ printf("720KB DD disk"); break;
+
+ case MFD_HD_12:
+ printf("1.2MB HD disk"); break;
+
+ case MFD_HD_144:
+ printf("1.44MB HD disk"); break;
+
+ case MFD_UHD:
+ printf("120MB UHD disk"); break;
+
+ default:
+ printf("Unknown (0x%x)", fdp->cap.medium_type);
+ }
+ if (fdp->cap.wp) printf(", writeprotected");
+ printf("\n");
+ }
+ }
+ else {
+ device_printf(dev, "REMOVABLE <%.40s/%.8s> at ata%d-%s %s\n",
+ atadev->param.model, atadev->param.revision,
+ device_get_unit(ch->dev),
+ (atadev->unit == ATA_MASTER) ? "master" : "slave",
+ ata_mode2str(atadev->mode));
+ }
+}
+
+static device_method_t afd_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_identify, afd_identify),
+ DEVMETHOD(device_probe, afd_probe),
+ DEVMETHOD(device_attach, afd_attach),
+ DEVMETHOD(device_detach, afd_detach),
+ DEVMETHOD(device_shutdown, afd_shutdown),
+
+ /* ATA methods */
+ DEVMETHOD(ata_reinit, afd_reinit),
+
+ { 0, 0 }
+};
+
+static driver_t afd_driver = {
+ "afd",
+ afd_methods,
+ sizeof(struct afd_softc)
+};
+
+static devclass_t afd_devclass;
+
+static int
+afd_modevent(module_t mod, int what, void *arg)
+{
+ device_t *devs;
+ int ndevs, i;
+
+ if (what == MOD_UNLOAD) {
+ if (!devclass_get_devices(afd_devclass, &devs, &ndevs) && devs) {
+ for (i = 0; i < ndevs; i++)
+ device_delete_child(device_get_parent(devs[i]), devs[i]);
+ free(devs, M_TEMP);
+ }
+ }
+ return 0;
+}
+
+DRIVER_MODULE(afd, ata, afd_driver, afd_devclass, afd_modevent, NULL);
+MODULE_VERSION(afd, 1);
+MODULE_DEPEND(afd, ata, 1, 1, 1);
+
diff --git a/sys/dev/ata/atapi-fd.h b/sys/dev/ata/atapi-fd.h
index 4f37b0d..2a2f699 100644
--- a/sys/dev/ata/atapi-fd.h
+++ b/sys/dev/ata/atapi-fd.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2004 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2005 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,50 +30,46 @@
/* ATAPI Rewriteable drive Capabilities and Mechanical Status Page */
struct afd_cappage {
- u_int16_t data_length;
- u_int8_t medium_type;
-#define MFD_2DD_UN 0x10
-#define MFD_2DD 0x11
-#define MFD_HD_UN 0x20
-#define MFD_HD_12_98 0x22
-#define MFD_HD_12 0x23
-#define MFD_HD_144 0x24
-#define MFD_UHD 0x31
+ u_int16_t data_length;
+ u_int8_t medium_type;
+#define MFD_2DD_UN 0x10
+#define MFD_2DD 0x11
+#define MFD_HD_UN 0x20
+#define MFD_HD_12_98 0x22
+#define MFD_HD_12 0x23
+#define MFD_HD_144 0x24
+#define MFD_UHD 0x31
-#define MFD_UNKNOWN 0x00
-#define MFD_NO_DISC 0x70
-#define MFD_DOOR_OPEN 0x71
-#define MFD_FMT_ERROR 0x72
+#define MFD_UNKNOWN 0x00
+#define MFD_NO_DISC 0x70
+#define MFD_DOOR_OPEN 0x71
+#define MFD_FMT_ERROR 0x72
- u_int8_t reserved0 :7;
- u_int8_t wp :1; /* write protect */
- u_int8_t unused[4];
+ u_int8_t reserved0 :7;
+ u_int8_t wp :1; /* write protect */
+ u_int8_t unused[4];
/* capabilities page */
- u_int8_t page_code :6;
-#define ATAPI_REWRITEABLE_CAP_PAGE 0x05
+ u_int8_t page_code :6;
+#define ATAPI_REWRITEABLE_CAP_PAGE 0x05
- u_int8_t reserved1_6 :1;
- u_int8_t ps :1; /* page save supported */
- u_int8_t page_length; /* page length */
- u_int16_t transfer_rate; /* in kilobits per second */
- u_int8_t heads; /* number of heads */
- u_int8_t sectors; /* number of sectors pr track */
- u_int16_t sector_size; /* number of bytes per sector */
- u_int16_t cylinders; /* number of cylinders */
- u_int8_t reserved10[10];
- u_int8_t motor_delay; /* motor off delay */
- u_int8_t reserved21[7];
- u_int16_t rpm; /* rotations per minute */
- u_int8_t reserved30[2];
+ u_int8_t reserved1_6 :1;
+ u_int8_t ps :1; /* page save supported */
+ u_int8_t page_length; /* page length */
+ u_int16_t transfer_rate; /* in kilobits per second */
+ u_int8_t heads; /* number of heads */
+ u_int8_t sectors; /* number of sectors pr track */
+ u_int16_t sector_size; /* number of bytes per sector */
+ u_int16_t cylinders; /* number of cylinders */
+ u_int8_t reserved10[10];
+ u_int8_t motor_delay; /* motor off delay */
+ u_int8_t reserved21[7];
+ u_int16_t rpm; /* rotations per minute */
+ u_int8_t reserved30[2];
};
struct afd_softc {
- struct ata_device *device; /* device softc */
- int lun; /* logical device unit */
- struct mtx queue_mtx; /* bio queue lock */
- struct bio_queue_head queue; /* queue of i/o requests */
- struct afd_cappage cap; /* capabilities page info */
- struct disk *disk; /* virtual drives */
+ struct afd_cappage cap; /* capabilities page info */
+ struct disk *disk; /* virtual drives */
};
diff --git a/sys/dev/ata/atapi-tape.c b/sys/dev/ata/atapi-tape.c
index 827edec..b1e90f0 100644
--- a/sys/dev/ata/atapi-tape.c
+++ b/sys/dev/ata/atapi-tape.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2004 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2005 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,8 +34,9 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/ata.h>
#include <sys/kernel.h>
-#include <sys/conf.h>
+#include <sys/module.h>
#include <sys/malloc.h>
+#include <sys/conf.h>
#include <sys/bio.h>
#include <sys/bus.h>
#include <sys/mtio.h>
@@ -46,281 +47,234 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <dev/ata/ata-all.h>
#include <dev/ata/atapi-tape.h>
+#include <ata_if.h>
-/* device structures */
-static d_open_t ast_open;
-static d_close_t ast_close;
-static d_ioctl_t ast_ioctl;
-static d_strategy_t ast_strategy;
+/* device structure */
+static d_open_t ast_open;
+static d_close_t ast_close;
+static d_ioctl_t ast_ioctl;
+static d_strategy_t ast_strategy;
static struct cdevsw ast_cdevsw = {
- .d_version = D_VERSION,
- .d_open = ast_open,
- .d_close = ast_close,
- .d_read = physread,
- .d_write = physwrite,
- .d_ioctl = ast_ioctl,
- .d_strategy = ast_strategy,
- .d_name = "ast",
- .d_flags = D_TAPE | D_TRACKCLOSE,
+ .d_version = D_VERSION,
+ .d_open = ast_open,
+ .d_close = ast_close,
+ .d_read = physread,
+ .d_write = physwrite,
+ .d_ioctl = ast_ioctl,
+ .d_strategy = ast_strategy,
+ .d_name = "ast",
+ .d_flags = D_TAPE | D_TRACKCLOSE,
};
/* prototypes */
-static void ast_detach(struct ata_device *);
-static void ast_start(struct ata_device *);
-static int ast_sense(struct ast_softc *);
-static void ast_describe(struct ast_softc *);
+static int ast_sense(device_t);
+static void ast_describe(device_t);
static void ast_done(struct ata_request *);
-static int ast_mode_sense(struct ast_softc *, int, void *, int);
-static int ast_mode_select(struct ast_softc *, void *, int);
-static int ast_write_filemark(struct ast_softc *, u_int8_t);
-static int ast_read_position(struct ast_softc *, int, struct ast_readposition *);
-static int ast_space(struct ast_softc *, u_int8_t, int32_t);
-static int ast_locate(struct ast_softc *, int, u_int32_t);
-static int ast_prevent_allow(struct ast_softc *stp, int);
-static int ast_load_unload(struct ast_softc *, u_int8_t);
-static int ast_rewind(struct ast_softc *);
-static int ast_erase(struct ast_softc *);
-static int ast_test_ready(struct ata_device *);
-static int ast_wait_dsc(struct ata_device *, int);
+static int ast_mode_sense(device_t, int, void *, int);
+static int ast_mode_select(device_t, void *, int);
+static int ast_write_filemark(device_t, u_int8_t);
+static int ast_read_position(device_t, int, struct ast_readposition *);
+static int ast_space(device_t, u_int8_t, int32_t);
+static int ast_locate(device_t, int, u_int32_t);
+static int ast_prevent_allow(device_t, int);
+static int ast_load_unload(device_t, u_int8_t);
+static int ast_rewind(device_t);
+static int ast_erase(device_t);
+static int ast_test_ready(device_t);
+static int ast_wait_dsc(device_t, int);
/* internal vars */
-static u_int32_t ast_lun_map = 0;
static u_int64_t ast_total = 0;
static MALLOC_DEFINE(M_AST, "AST driver", "ATAPI tape driver buffers");
-void
-ast_attach(struct ata_device *atadev)
+static void
+ast_identify(driver_t *driver, device_t parent)
+{
+ ata_identify(driver, parent, ATA_ATAPI_TYPE_TAPE, "ast");
+}
+
+static int
+ast_probe(device_t dev)
+{
+ return 0;
+}
+
+static int
+ast_attach(device_t dev)
{
+ struct ata_channel *ch = device_get_softc(device_get_parent(dev));
+ struct ata_device *atadev = device_get_softc(dev);
struct ast_softc *stp;
struct ast_readposition position;
- struct cdev *dev;
+ struct cdev *device;
- stp = malloc(sizeof(struct ast_softc), M_AST, M_NOWAIT | M_ZERO);
- if (!stp) {
- ata_prtdev(atadev, "out of memory\n");
- return;
+ if (!(stp = malloc(sizeof(struct ast_softc), M_AST, M_NOWAIT | M_ZERO))) {
+ device_printf(dev, "out of memory\n");
+ device_set_softc(dev, NULL);
+ free(atadev, M_ATA);
+ return ENOMEM;
}
+ device_set_ivars(dev, stp);
+ ATA_SETMODE(GRANDPARENT(dev), dev);
- stp->device = atadev;
- stp->lun = ata_get_lun(&ast_lun_map);
- ata_set_name(atadev, "ast", stp->lun);
- bioq_init(&stp->queue);
- mtx_init(&stp->queue_mtx, "ATAPI TAPE bioqueue lock", NULL, MTX_DEF);
-
- if (ast_sense(stp)) {
+ if (ast_sense(dev)) {
+ device_set_ivars(dev, NULL);
free(stp, M_AST);
- return;
+ device_set_softc(dev, NULL);
+ free(atadev, M_ATA);
+ return ENXIO;
}
-
- if (!strcmp(atadev->param->model, "OnStream DI-30")) {
+ if (!strcmp(atadev->param.model, "OnStream DI-30")) {
struct ast_transferpage transfer;
struct ast_identifypage identify;
stp->flags |= F_ONSTREAM;
bzero(&transfer, sizeof(struct ast_transferpage));
- ast_mode_sense(stp, ATAPI_TAPE_TRANSFER_PAGE,
+ ast_mode_sense(dev, ATAPI_TAPE_TRANSFER_PAGE,
&transfer, sizeof(transfer));
bzero(&identify, sizeof(struct ast_identifypage));
- ast_mode_sense(stp, ATAPI_TAPE_IDENTIFY_PAGE,
+ ast_mode_sense(dev, ATAPI_TAPE_IDENTIFY_PAGE,
&identify, sizeof(identify));
strncpy(identify.ident, "FBSD", 4);
- ast_mode_select(stp, &identify, sizeof(identify));
- ast_read_position(stp, 0, &position);
+ ast_mode_select(dev, &identify, sizeof(identify));
+ ast_read_position(dev, 0, &position);
}
- stp->stats = devstat_new_entry("ast", stp->lun, DEV_BSIZE,
+ stp->stats = devstat_new_entry("ast", device_get_unit(dev), DEV_BSIZE,
DEVSTAT_NO_ORDERED_TAGS,
DEVSTAT_TYPE_SEQUENTIAL | DEVSTAT_TYPE_IF_IDE,
DEVSTAT_PRIORITY_TAPE);
- dev = make_dev(&ast_cdevsw, 2 * stp->lun,
- UID_ROOT, GID_OPERATOR, 0640, "ast%d", stp->lun);
- dev->si_drv1 = stp;
- if (atadev->channel->dma)
- dev->si_iosize_max = atadev->channel->dma->max_iosize;
+ device = make_dev(&ast_cdevsw, 2 * device_get_unit(dev),
+ UID_ROOT, GID_OPERATOR, 0640, "ast%d",
+ device_get_unit(dev));
+ device->si_drv1 = dev;
+ if (ch->dma)
+ device->si_iosize_max = ch->dma->max_iosize;
else
- dev->si_iosize_max = DFLTPHYS;
- stp->dev1 = dev;
- dev = make_dev(&ast_cdevsw, 2 * stp->lun + 1,
- UID_ROOT, GID_OPERATOR, 0640, "nast%d", stp->lun);
-
- dev->si_drv1 = stp;
- if (atadev->channel->dma)
- dev->si_iosize_max = atadev->channel->dma->max_iosize;
+ device->si_iosize_max = DFLTPHYS;
+ stp->dev1 = device;
+ device = make_dev(&ast_cdevsw, 2 * device_get_unit(dev) + 1,
+ UID_ROOT, GID_OPERATOR, 0640, "nast%d",
+ device_get_unit(dev));
+ device->si_drv1 = dev;
+ if (ch->dma)
+ device->si_iosize_max = ch->dma->max_iosize;
else
- dev->si_iosize_max = DFLTPHYS;
- stp->dev2 = dev;
-
- /* setup the function ptrs */
- atadev->detach = ast_detach;
- atadev->start = ast_start;
- atadev->softc = stp;
- atadev->flags |= ATA_D_MEDIA_CHANGED;
+ device->si_iosize_max = DFLTPHYS;
+ stp->dev2 = device;
- /* announce we are here */
- ast_describe(stp);
+ /* announce we are here and ready */
+ ast_describe(dev);
+ return 0;
}
-static void
-ast_detach(struct ata_device *atadev)
+static int
+ast_detach(device_t dev)
{
- struct ast_softc *stp = atadev->softc;
+ struct ata_channel *ch = device_get_softc(device_get_parent(dev));
+ struct ata_device *atadev = device_get_softc(dev);
+ struct ast_softc *stp = device_get_ivars(dev);
- mtx_lock(&stp->queue_mtx);
- bioq_flush(&stp->queue, NULL, ENXIO);
- mtx_unlock(&stp->queue_mtx);
- mtx_destroy(&stp->queue_mtx);
+ /* detroy devices from the system so we dont get any further requests */
destroy_dev(stp->dev1);
destroy_dev(stp->dev2);
+
+ /* fail requests on the queue and any thats "in flight" for this device */
+ ata_fail_requests(ch, dev);
+
+ /* dont leave anything behind */
devstat_remove_entry(stp->stats);
- ata_prtdev(atadev, "WARNING - removed from configuration\n");
- ata_free_name(atadev);
- ata_free_lun(&ast_lun_map, stp->lun);
- atadev->attach = NULL;
- atadev->detach = NULL;
- atadev->start = NULL;
- atadev->softc = NULL;
- atadev->flags = 0;
+ device_set_ivars(dev, NULL);
free(stp, M_AST);
+ device_set_softc(dev, NULL);
+ free(atadev, M_ATA);
+ return 0;
}
-static int
-ast_sense(struct ast_softc *stp)
+static void
+ast_shutdown(device_t dev)
{
- int count;
+ struct ata_device *atadev = device_get_softc(dev);
- /* get drive capabilities, some bugridden drives needs this repeated */
- for (count = 0 ; count < 5 ; count++) {
- if (!ast_mode_sense(stp, ATAPI_TAPE_CAP_PAGE,
- &stp->cap, sizeof(stp->cap)) &&
- stp->cap.page_code == ATAPI_TAPE_CAP_PAGE) {
- if (stp->cap.blk32k)
- stp->blksize = 32768;
- if (stp->cap.blk1024)
- stp->blksize = 1024;
- if (stp->cap.blk512)
- stp->blksize = 512;
- if (!stp->blksize)
- continue;
- stp->cap.max_speed = ntohs(stp->cap.max_speed);
- stp->cap.max_defects = ntohs(stp->cap.max_defects);
- stp->cap.ctl = ntohs(stp->cap.ctl);
- stp->cap.speed = ntohs(stp->cap.speed);
- stp->cap.buffer_size = ntohs(stp->cap.buffer_size);
- return 0;
- }
- }
- return 1;
+ if (atadev->param.support.command2 & ATA_SUPPORT_FLUSHCACHE)
+ ata_controlcmd(atadev, ATA_FLUSHCACHE, 0, 0, 0);
}
-static void
-ast_describe(struct ast_softc *stp)
+static int
+ast_reinit(device_t dev)
{
- if (bootverbose) {
- ata_prtdev(stp->device, "<%.40s/%.8s> tape drive at ata%d as %s\n",
- stp->device->param->model, stp->device->param->revision,
- device_get_unit(stp->device->channel->dev),
- (stp->device->unit == ATA_MASTER) ? "master" : "slave");
- ata_prtdev(stp->device, "%dKB/s, ", stp->cap.max_speed);
- printf("transfer limit %d blk%s, ",
- stp->cap.ctl, (stp->cap.ctl > 1) ? "s" : "");
- printf("%dKB buffer, ", (stp->cap.buffer_size * DEV_BSIZE) / 1024);
- printf("%s\n", ata_mode2str(stp->device->mode));
- ata_prtdev(stp->device, "Medium: ");
- switch (stp->cap.medium_type) {
- case 0x00:
- printf("none"); break;
- case 0x17:
- printf("Travan 1 (400 Mbyte)"); break;
- case 0xb6:
- printf("Travan 4 (4 Gbyte)"); break;
- case 0xda:
- printf("OnStream ADR (15Gyte)"); break;
- default:
- printf("unknown (0x%x)", stp->cap.medium_type);
- }
- if (stp->cap.readonly) printf(", readonly");
- if (stp->cap.reverse) printf(", reverse");
- if (stp->cap.eformat) printf(", eformat");
- if (stp->cap.qfa) printf(", qfa");
- if (stp->cap.lock) printf(", lock");
- if (stp->cap.locked) printf(", locked");
- if (stp->cap.prevent) printf(", prevent");
- if (stp->cap.eject) printf(", eject");
- if (stp->cap.disconnect) printf(", disconnect");
- if (stp->cap.ecc) printf(", ecc");
- if (stp->cap.compress) printf(", compress");
- if (stp->cap.blk512) printf(", 512b");
- if (stp->cap.blk1024) printf(", 1024b");
- if (stp->cap.blk32k) printf(", 32kb");
- printf("\n");
- }
- else {
- ata_prtdev(stp->device, "TAPE <%.40s/%.8s> at ata%d-%s %s\n",
- stp->device->param->model, stp->device->param->revision,
- device_get_unit(stp->device->channel->dev),
- (stp->device->unit == ATA_MASTER) ? "master" : "slave",
- ata_mode2str(stp->device->mode));
+ struct ata_channel *ch = device_get_softc(device_get_parent(dev));
+ struct ata_device *atadev = device_get_softc(dev);
+ struct ast_softc *stp = device_get_ivars(dev);
+
+ if (((atadev->unit == ATA_MASTER) && !(ch->devices & ATA_ATAPI_MASTER)) ||
+ ((atadev->unit == ATA_SLAVE) && !(ch->devices & ATA_ATAPI_SLAVE))) {
+ device_set_ivars(dev, NULL);
+ free(stp, M_AST);
+ return 1;
}
+ ATA_SETMODE(GRANDPARENT(dev), dev);
+ return 0;
}
static int
-ast_open(struct cdev *dev, int flags, int fmt, struct thread *td)
+ast_open(struct cdev *cdev, int flags, int fmt, struct thread *td)
{
- struct ast_softc *stp = dev->si_drv1;
+ device_t dev = cdev->si_drv1;
+ struct ata_device *atadev = device_get_softc(dev);
+ struct ast_softc *stp = device_get_ivars(dev);
- if (!stp || stp->device->flags & ATA_D_DETACHING)
+ if (!stp)
return ENXIO;
-
- if (count_dev(dev) > 1)
+ if (!device_is_attached(dev))
return EBUSY;
- ast_test_ready(stp->device);
-
+ ast_test_ready(dev);
if (stp->cap.lock)
- ast_prevent_allow(stp, 1);
-
- if (ast_sense(stp))
- ata_prtdev(stp->device, "sense media type failed\n");
+ ast_prevent_allow(dev, 1);
+ if (ast_sense(dev))
+ device_printf(dev, "sense media type failed\n");
- stp->device->flags &= ~ATA_D_MEDIA_CHANGED;
+ atadev->flags &= ~ATA_D_MEDIA_CHANGED;
stp->flags &= ~(F_DATA_WRITTEN | F_FM_WRITTEN);
ast_total = 0;
return 0;
}
static int
-ast_close(struct cdev *dev, int flags, int fmt, struct thread *td)
+ast_close(struct cdev *cdev, int flags, int fmt, struct thread *td)
{
- struct ast_softc *stp = dev->si_drv1;
+ device_t dev = cdev->si_drv1;
+ struct ast_softc *stp = device_get_ivars(dev);
/* flush buffers, some drives fail here, they should report ctl = 0 */
if (stp->cap.ctl && (stp->flags & F_DATA_WRITTEN))
- ast_write_filemark(stp, 0);
+ ast_write_filemark(dev, 0);
/* write filemark if data written to tape */
if (!(stp->flags & F_ONSTREAM) &&
(stp->flags & (F_DATA_WRITTEN | F_FM_WRITTEN)) == F_DATA_WRITTEN)
- ast_write_filemark(stp, ATAPI_WF_WRITE);
+ ast_write_filemark(dev, ATAPI_WF_WRITE);
/* if minor is even rewind on close */
- if (!(minor(dev) & 0x01))
- ast_rewind(stp);
+ if (!(minor(cdev) & 0x01))
+ ast_rewind(dev);
- if (stp->cap.lock && count_dev(dev) == 1)
- ast_prevent_allow(stp, 0);
+ if (stp->cap.lock && count_dev(cdev) == 1)
+ ast_prevent_allow(dev, 0);
stp->flags &= ~F_CTL_WARN;
#ifdef AST_DEBUG
- ata_prtdev(stp->device, "%ju total bytes transferred\n",
- (uintmax_t)ast_total);
+ device_printf(dev, "%ju total bytes transferred\n", (uintmax_t)ast_total);
#endif
return 0;
}
static int
-ast_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
+ast_ioctl(struct cdev *cdev, u_long cmd, caddr_t addr, int flag, struct thread *td)
{
- struct ast_softc *stp = dev->si_drv1;
+ device_t dev = cdev->si_drv1;
+ struct ast_softc *stp = device_get_ivars(dev);
int error = 0;
switch (cmd) {
@@ -340,10 +294,10 @@ ast_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *t
g->mt_comp0 = 0; g->mt_comp1 = 0;
g->mt_comp2 = 0; g->mt_comp3 = 0;
}
- break;
+ break;
case MTIOCTOP:
- {
+ {
int i;
struct mtop *mt = (struct mtop *)addr;
@@ -351,44 +305,44 @@ ast_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *t
case MTWEOF:
for (i=0; i < mt->mt_count && !error; i++)
- error = ast_write_filemark(stp, ATAPI_WF_WRITE);
+ error = ast_write_filemark(dev, ATAPI_WF_WRITE);
break;
case MTFSF:
if (mt->mt_count)
- error = ast_space(stp, ATAPI_SP_FM, mt->mt_count);
+ error = ast_space(dev, ATAPI_SP_FM, mt->mt_count);
break;
case MTBSF:
if (mt->mt_count)
- error = ast_space(stp, ATAPI_SP_FM, -(mt->mt_count));
+ error = ast_space(dev, ATAPI_SP_FM, -(mt->mt_count));
break;
case MTREW:
- error = ast_rewind(stp);
+ error = ast_rewind(dev);
break;
case MTOFFL:
- error = ast_load_unload(stp, ATAPI_SS_EJECT);
+ error = ast_load_unload(dev, ATAPI_SS_EJECT);
break;
case MTNOP:
- error = ast_write_filemark(stp, 0);
+ error = ast_write_filemark(dev, 0);
break;
case MTERASE:
- error = ast_erase(stp);
+ error = ast_erase(dev);
break;
case MTEOD:
- error = ast_space(stp, ATAPI_SP_EOD, 0);
+ error = ast_space(dev, ATAPI_SP_EOD, 0);
break;
case MTRETENS:
- error = ast_load_unload(stp, ATAPI_SS_RETENSION|ATAPI_SS_LOAD);
+ error = ast_load_unload(dev, ATAPI_SS_RETENSION|ATAPI_SS_LOAD);
break;
- case MTFSR:
+ case MTFSR:
case MTBSR:
case MTCACHE:
case MTNOCACHE:
@@ -405,7 +359,7 @@ ast_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *t
{
struct ast_readposition position;
- if ((error = ast_read_position(stp, 0, &position)))
+ if ((error = ast_read_position(dev, 0, &position)))
break;
*(u_int32_t *)addr = position.tape;
}
@@ -415,18 +369,18 @@ ast_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *t
{
struct ast_readposition position;
- if ((error = ast_read_position(stp, 1, &position)))
+ if ((error = ast_read_position(dev, 1, &position)))
break;
*(u_int32_t *)addr = position.tape;
}
break;
case MTIOCSLOCATE:
- error = ast_locate(stp, 0, *(u_int32_t *)addr);
+ error = ast_locate(dev, 0, *(u_int32_t *)addr);
break;
case MTIOCHLOCATE:
- error = ast_locate(stp, 1, *(u_int32_t *)addr);
+ error = ast_locate(dev, 1, *(u_int32_t *)addr);
break;
default:
@@ -438,12 +392,12 @@ ast_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *t
static void
ast_strategy(struct bio *bp)
{
- struct ast_softc *stp = bp->bio_dev->si_drv1;
-
- if (stp->device->flags & ATA_D_DETACHING) {
- biofinish(bp, NULL, ENXIO);
- return;
- }
+ device_t dev = bp->bio_dev->si_drv1;
+ struct ata_device *atadev = device_get_softc(dev);
+ struct ast_softc *stp = device_get_ivars(dev);
+ struct ata_request *request;
+ u_int32_t blkcount;
+ int8_t ccb[16];
/* if it's a null transfer, return immediatly. */
if (bp->bio_bcount == 0) {
@@ -458,45 +412,20 @@ ast_strategy(struct bio *bp)
/* check for != blocksize requests */
if (bp->bio_bcount % stp->blksize) {
- ata_prtdev(stp->device, "transfers must be multiple of %d\n",
- stp->blksize);
+ device_printf(dev, "transfers must be multiple of %d\n", stp->blksize);
biofinish(bp, NULL, EIO);
return;
}
/* warn about transfers bigger than the device suggests */
- if (bp->bio_bcount > stp->blksize * stp->cap.ctl) {
+ if (bp->bio_bcount > stp->blksize * stp->cap.ctl) {
if ((stp->flags & F_CTL_WARN) == 0) {
- ata_prtdev(stp->device, "WARNING: CTL exceeded %ld>%d\n",
- bp->bio_bcount, stp->blksize * stp->cap.ctl);
+ device_printf(dev, "WARNING: CTL exceeded %ld>%d\n",
+ bp->bio_bcount, stp->blksize * stp->cap.ctl);
stp->flags |= F_CTL_WARN;
}
}
- mtx_lock(&stp->queue_mtx);
- bioq_insert_tail(&stp->queue, bp);
- mtx_unlock(&stp->queue_mtx);
- ata_start(stp->device->channel);
-}
-
-static void
-ast_start(struct ata_device *atadev)
-{
- struct ast_softc *stp = atadev->softc;
- struct bio *bp;
- struct ata_request *request;
- u_int32_t blkcount;
- int8_t ccb[16];
-
- mtx_lock(&stp->queue_mtx);
- bp = bioq_first(&stp->queue);
- if (!bp) {
- mtx_unlock(&stp->queue_mtx);
- return;
- }
- bioq_remove(&stp->queue, bp);
- mtx_unlock(&stp->queue_mtx);
-
bzero(ccb, sizeof(ccb));
if (bp->bio_cmd == BIO_READ)
@@ -507,18 +436,18 @@ ast_start(struct ata_device *atadev)
blkcount = bp->bio_bcount / stp->blksize;
ccb[1] = 1;
- ccb[2] = blkcount>>16;
- ccb[3] = blkcount>>8;
+ ccb[2] = blkcount >> 16;
+ ccb[3] = blkcount >> 8;
ccb[4] = blkcount;
if (!(request = ata_alloc_request())) {
biofinish(bp, NULL, ENOMEM);
return;
}
- request->device = atadev;
+ request->dev = dev;
request->driver = bp;
bcopy(ccb, request->u.atapi.ccb,
- (request->device->param->config & ATA_PROTO_MASK) ==
+ (atadev->param.config & ATA_PROTO_MASK) ==
ATA_PROTO_ATAPI_12 ? 16 : 12);
request->data = bp->bio_data;
request->bytecount = blkcount * stp->blksize;
@@ -534,7 +463,7 @@ ast_start(struct ata_device *atadev)
request->flags |= (ATA_R_ATAPI | ATA_R_WRITE);
break;
default:
- ata_prtdev(atadev, "unknown BIO operation\n");
+ device_printf(dev, "unknown BIO operation\n");
ata_free_request(request);
biofinish(bp, NULL, EIO);
return;
@@ -546,8 +475,8 @@ ast_start(struct ata_device *atadev)
static void
ast_done(struct ata_request *request)
{
+ struct ast_softc *stp = device_get_ivars(request->dev);
struct bio *bp = request->driver;
- struct ast_softc *stp = request->device->softc;
/* finish up transfer */
if ((bp->bio_error = request->result))
@@ -561,41 +490,68 @@ ast_done(struct ata_request *request)
}
static int
-ast_mode_sense(struct ast_softc *stp, int page, void *pagebuf, int pagesize)
+ast_sense(device_t dev)
{
+ struct ast_softc *stp = device_get_ivars(dev);
+ int count;
+
+ /* get drive capabilities, some bugridden drives needs this repeated */
+ for (count = 0 ; count < 5 ; count++) {
+ if (!ast_mode_sense(dev, ATAPI_TAPE_CAP_PAGE,
+ &stp->cap, sizeof(stp->cap)) &&
+ stp->cap.page_code == ATAPI_TAPE_CAP_PAGE) {
+ if (stp->cap.blk32k)
+ stp->blksize = 32768;
+ if (stp->cap.blk1024)
+ stp->blksize = 1024;
+ if (stp->cap.blk512)
+ stp->blksize = 512;
+ if (!stp->blksize)
+ continue;
+ stp->cap.max_speed = ntohs(stp->cap.max_speed);
+ stp->cap.max_defects = ntohs(stp->cap.max_defects);
+ stp->cap.ctl = ntohs(stp->cap.ctl);
+ stp->cap.speed = ntohs(stp->cap.speed);
+ stp->cap.buffer_size = ntohs(stp->cap.buffer_size);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int
+ast_mode_sense(device_t dev, int page, void *pagebuf, int pagesize)
+{
+ struct ata_device *atadev = device_get_softc(dev);
int8_t ccb[16] = { ATAPI_MODE_SENSE, 0x08, page, pagesize>>8, pagesize,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int error;
- error = ata_atapicmd(stp->device, ccb, pagebuf, pagesize, ATA_R_READ, 10);
-#ifdef AST_DEBUG
- atapi_dump("ast: mode sense ", pagebuf, pagesize);
-#endif
+ error = ata_atapicmd(atadev, ccb, pagebuf, pagesize, ATA_R_READ, 10);
return error;
}
-static int
-ast_mode_select(struct ast_softc *stp, void *pagebuf, int pagesize)
+static int
+ast_mode_select(device_t dev, void *pagebuf, int pagesize)
{
+ struct ata_device *atadev = device_get_softc(dev);
int8_t ccb[16] = { ATAPI_MODE_SELECT, 0x10, 0, pagesize>>8, pagesize,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-#ifdef AST_DEBUG
- ata_prtdev(stp->device, "modeselect pagesize=%d\n", pagesize);
- atapi_dump("mode select ", pagebuf, pagesize);
-#endif
- return ata_atapicmd(stp->device, ccb, pagebuf, pagesize, 0, 10);
+ return ata_atapicmd(atadev, ccb, pagebuf, pagesize, 0, 10);
}
static int
-ast_write_filemark(struct ast_softc *stp, u_int8_t function)
+ast_write_filemark(device_t dev, u_int8_t function)
{
+ struct ata_device *atadev = device_get_softc(dev);
+ struct ast_softc *stp = device_get_ivars(dev);
int8_t ccb[16] = { ATAPI_WEOF, 0x01, 0, 0, function, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 };
int error;
if (stp->flags & F_ONSTREAM)
- ccb[4] = 0x00; /* only flush buffers supported */
+ ccb[4] = 0x00; /* only flush buffers supported */
else {
if (function) {
if (stp->flags & F_FM_WRITTEN)
@@ -604,21 +560,21 @@ ast_write_filemark(struct ast_softc *stp, u_int8_t function)
stp->flags |= F_FM_WRITTEN;
}
}
- error = ata_atapicmd(stp->device, ccb, NULL, 0, 0, 10);
+ error = ata_atapicmd(atadev, ccb, NULL, 0, 0, 10);
if (error)
return error;
- return ast_wait_dsc(stp->device, 10*60);
+ return ast_wait_dsc(dev, 10*60);
}
static int
-ast_read_position(struct ast_softc *stp, int hard,
- struct ast_readposition *position)
+ast_read_position(device_t dev, int hard, struct ast_readposition *position)
{
+ struct ata_device *atadev = device_get_softc(dev);
int8_t ccb[16] = { ATAPI_READ_POSITION, (hard ? 0x01 : 0), 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 };
int error;
- error = ata_atapicmd(stp->device, ccb, (caddr_t)position,
+ error = ata_atapicmd(atadev, ccb, (caddr_t)position,
sizeof(struct ast_readposition), ATA_R_READ, 10);
position->tape = ntohl(position->tape);
position->host = ntohl(position->host);
@@ -626,84 +582,93 @@ ast_read_position(struct ast_softc *stp, int hard,
}
static int
-ast_space(struct ast_softc *stp, u_int8_t function, int32_t count)
+ast_space(device_t dev, u_int8_t function, int32_t count)
{
+ struct ata_device *atadev = device_get_softc(dev);
int8_t ccb[16] = { ATAPI_SPACE, function, count>>16, count>>8, count,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- return ata_atapicmd(stp->device, ccb, NULL, 0, 0, 60*60);
+ return ata_atapicmd(atadev, ccb, NULL, 0, 0, 60*60);
}
static int
-ast_locate(struct ast_softc *stp, int hard, u_int32_t pos)
+ast_locate(device_t dev, int hard, u_int32_t pos)
{
+ struct ata_device *atadev = device_get_softc(dev);
int8_t ccb[16] = { ATAPI_LOCATE, 0x01 | (hard ? 0x4 : 0), 0,
pos>>24, pos>>16, pos>>8, pos,
0, 0, 0, 0, 0, 0, 0, 0, 0 };
int error;
- error = ata_atapicmd(stp->device, ccb, NULL, 0, 0, 10);
+ error = ata_atapicmd(atadev, ccb, NULL, 0, 0, 10);
if (error)
return error;
- return ast_wait_dsc(stp->device, 60*60);
+ return ast_wait_dsc(dev, 60*60);
}
static int
-ast_prevent_allow(struct ast_softc *stp, int lock)
+ast_prevent_allow(device_t dev, int lock)
{
+ struct ata_device *atadev = device_get_softc(dev);
int8_t ccb[16] = { ATAPI_PREVENT_ALLOW, 0, 0, 0, lock,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- return ata_atapicmd(stp->device, ccb, NULL, 0, 0, 30);
+ return ata_atapicmd(atadev, ccb, NULL, 0, 0, 30);
}
static int
-ast_load_unload(struct ast_softc *stp, u_int8_t function)
+ast_load_unload(device_t dev, u_int8_t function)
{
+ struct ata_device *atadev = device_get_softc(dev);
+ struct ast_softc *stp = device_get_ivars(dev);
int8_t ccb[16] = { ATAPI_START_STOP, 0x01, 0, 0, function, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 };
int error;
if ((function & ATAPI_SS_EJECT) && !stp->cap.eject)
return 0;
- error = ata_atapicmd(stp->device, ccb, NULL, 0, 0, 10);
+ error = ata_atapicmd(atadev, ccb, NULL, 0, 0, 10);
if (error)
return error;
tsleep((caddr_t)&error, PRIBIO, "astlu", 1 * hz);
if (function == ATAPI_SS_EJECT)
return 0;
- return ast_wait_dsc(stp->device, 60*60);
+ return ast_wait_dsc(dev, 60*60);
}
static int
-ast_rewind(struct ast_softc *stp)
+ast_rewind(device_t dev)
{
+ struct ata_device *atadev = device_get_softc(dev);
int8_t ccb[16] = { ATAPI_REZERO, 0x01, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 };
int error;
- error = ata_atapicmd(stp->device, ccb, NULL, 0, 0, 10);
+ error = ata_atapicmd(atadev, ccb, NULL, 0, 0, 10);
if (error)
return error;
- return ast_wait_dsc(stp->device, 60*60);
+ return ast_wait_dsc(dev, 60*60);
}
static int
-ast_erase(struct ast_softc *stp)
+ast_erase(device_t dev)
{
+ struct ata_device *atadev = device_get_softc(dev);
int8_t ccb[16] = { ATAPI_ERASE, 3, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 };
int error;
- if ((error = ast_rewind(stp)))
+ if ((error = ast_rewind(dev)))
return error;
- return ata_atapicmd(stp->device, ccb, NULL, 0, 0, 60*60);
+ return ata_atapicmd(atadev, ccb, NULL, 0, 0, 60*60);
}
static int
-ast_test_ready(struct ata_device *atadev)
+ast_test_ready(device_t dev)
{
+ struct ata_device *atadev = device_get_softc(dev);
+
int8_t ccb[16] = { ATAPI_TEST_UNIT_READY, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
@@ -711,8 +676,10 @@ ast_test_ready(struct ata_device *atadev)
}
static int
-ast_wait_dsc(struct ata_device *atadev, int timeout)
+ast_wait_dsc(device_t dev, int timeout)
{
+ struct ata_device *atadev = device_get_softc(dev);
+
int error = 0;
int8_t ccb[16] = { ATAPI_POLL_DSC, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
@@ -727,3 +694,100 @@ ast_wait_dsc(struct ata_device *atadev, int timeout)
}
return error;
}
+
+static void
+ast_describe(device_t dev)
+{
+ struct ata_channel *ch = device_get_softc(device_get_parent(dev));
+ struct ata_device *atadev = device_get_softc(dev);
+ struct ast_softc *stp = device_get_ivars(dev);
+
+ if (bootverbose) {
+ device_printf(dev, "<%.40s/%.8s> tape drive at ata%d as %s\n",
+ atadev->param.model, atadev->param.revision,
+ device_get_unit(ch->dev),
+ (atadev->unit == ATA_MASTER) ? "master" : "slave");
+ device_printf(dev, "%dKB/s, ", stp->cap.max_speed);
+ printf("transfer limit %d blk%s, ",
+ stp->cap.ctl, (stp->cap.ctl > 1) ? "s" : "");
+ printf("%dKB buffer, ", (stp->cap.buffer_size * DEV_BSIZE) / 1024);
+ printf("%s\n", ata_mode2str(atadev->mode));
+ device_printf(dev, "Medium: ");
+ switch (stp->cap.medium_type) {
+ case 0x00:
+ printf("none"); break;
+ case 0x17:
+ printf("Travan 1 (400 Mbyte)"); break;
+ case 0xb6:
+ printf("Travan 4 (4 Gbyte)"); break;
+ case 0xda:
+ printf("OnStream ADR (15Gyte)"); break;
+ default:
+ printf("unknown (0x%x)", stp->cap.medium_type);
+ }
+ if (stp->cap.readonly) printf(", readonly");
+ if (stp->cap.reverse) printf(", reverse");
+ if (stp->cap.eformat) printf(", eformat");
+ if (stp->cap.qfa) printf(", qfa");
+ if (stp->cap.lock) printf(", lock");
+ if (stp->cap.locked) printf(", locked");
+ if (stp->cap.prevent) printf(", prevent");
+ if (stp->cap.eject) printf(", eject");
+ if (stp->cap.disconnect) printf(", disconnect");
+ if (stp->cap.ecc) printf(", ecc");
+ if (stp->cap.compress) printf(", compress");
+ if (stp->cap.blk512) printf(", 512b");
+ if (stp->cap.blk1024) printf(", 1024b");
+ if (stp->cap.blk32k) printf(", 32kb");
+ printf("\n");
+ }
+ else {
+ device_printf(dev, "TAPE <%.40s/%.8s> at ata%d-%s %s\n",
+ atadev->param.model, atadev->param.revision,
+ device_get_unit(ch->dev),
+ (atadev->unit == ATA_MASTER) ? "master" : "slave",
+ ata_mode2str(atadev->mode));
+ }
+}
+
+static device_method_t ast_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_identify, ast_identify),
+ DEVMETHOD(device_probe, ast_probe),
+ DEVMETHOD(device_attach, ast_attach),
+ DEVMETHOD(device_detach, ast_detach),
+ DEVMETHOD(device_shutdown, ast_shutdown),
+
+ /* ATA methods */
+ DEVMETHOD(ata_reinit, ast_reinit),
+
+ { 0, 0 }
+};
+
+static driver_t ast_driver = {
+ "ast",
+ ast_methods,
+ sizeof(struct ast_softc)
+};
+
+static devclass_t ast_devclass;
+
+static int
+ast_modevent(module_t mod, int what, void *arg)
+{
+ device_t *devs;
+ int ndevs, i;
+
+ if (what == MOD_UNLOAD) {
+ if (!devclass_get_devices(ast_devclass, &devs, &ndevs) && devs) {
+ for (i = 0; i < ndevs; i++)
+ device_delete_child(device_get_parent(devs[i]), devs[i]);
+ free(devs, M_TEMP);
+ }
+ }
+ return 0;
+}
+
+DRIVER_MODULE(ast, ata, ast_driver, ast_devclass, ast_modevent, NULL);
+MODULE_VERSION(ast, 1);
+MODULE_DEPEND(ast, ata, 1, 1, 1);
diff --git a/sys/dev/ata/atapi-tape.h b/sys/dev/ata/atapi-tape.h
index f34328d..e51cff2 100644
--- a/sys/dev/ata/atapi-tape.h
+++ b/sys/dev/ata/atapi-tape.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2004 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2005 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,133 +31,129 @@
/* ATAPI tape drive Capabilities and Mechanical Status Page */
struct ast_cappage {
/* mode page data header */
- u_int8_t data_length; /* total length of data */
- u_int8_t medium_type; /* medium type (if any) */
- u_int8_t reserved :4;
- u_int8_t mode :3; /* buffering mode */
- u_int8_t write_protect :1; /* media is writeprotected */
- u_int8_t blk_desc_len; /* block Descriptor Length */
+ u_int8_t data_length; /* total length of data */
+ u_int8_t medium_type; /* medium type (if any) */
+ u_int8_t reserved :4;
+ u_int8_t mode :3; /* buffering mode */
+ u_int8_t write_protect :1; /* media is writeprotected */
+ u_int8_t blk_desc_len; /* block Descriptor Length */
/* capabilities page */
- u_int8_t page_code :6;
-#define ATAPI_TAPE_CAP_PAGE 0x2a
+ u_int8_t page_code :6;
+#define ATAPI_TAPE_CAP_PAGE 0x2a
- u_int8_t reserved0_6 :1;
- u_int8_t ps :1; /* parameters saveable */
- u_int8_t page_length; /* page Length == 0x12 */
- u_int8_t reserved2;
- u_int8_t reserved3;
- u_int8_t readonly :1; /* read Only Mode */
- u_int8_t reserved4_1234 :4;
- u_int8_t reverse :1; /* supports reverse direction */
- u_int8_t reserved4_67 :2;
- u_int8_t reserved5_012 :3;
- u_int8_t eformat :1; /* supports ERASE formatting */
- u_int8_t reserved5_4 :1;
- u_int8_t qfa :1; /* supports QFA formats */
- u_int8_t reserved5_67 :2;
- u_int8_t lock :1; /* supports locking media */
- u_int8_t locked :1; /* the media is locked */
- u_int8_t prevent :1; /* defaults to prevent state */
- u_int8_t eject :1; /* supports eject */
- u_int8_t disconnect :1; /* can break request > ctl */
- u_int8_t reserved6_5 :1;
- u_int8_t ecc :1; /* supports error correction */
- u_int8_t compress :1; /* supports data compression */
- u_int8_t reserved7_0 :1;
- u_int8_t blk512 :1; /* supports 512b block size */
- u_int8_t blk1024 :1; /* supports 1024b block size */
- u_int8_t reserved7_3456 :4;
- u_int8_t blk32k :1; /* supports 32kb block size */
- u_int16_t max_speed; /* supported speed in KBps */
- u_int16_t max_defects; /* max stored defect entries */
- u_int16_t ctl; /* continuous transfer limit */
- u_int16_t speed; /* current Speed, in KBps */
- u_int16_t buffer_size; /* buffer Size, in 512 bytes */
- u_int8_t reserved18;
- u_int8_t reserved19;
+ u_int8_t reserved0_6 :1;
+ u_int8_t ps :1; /* parameters saveable */
+ u_int8_t page_length; /* page Length == 0x12 */
+ u_int8_t reserved2;
+ u_int8_t reserved3;
+ u_int8_t readonly :1; /* read Only Mode */
+ u_int8_t reserved4_1234 :4;
+ u_int8_t reverse :1; /* supports reverse direction */
+ u_int8_t reserved4_67 :2;
+ u_int8_t reserved5_012 :3;
+ u_int8_t eformat :1; /* supports ERASE formatting */
+ u_int8_t reserved5_4 :1;
+ u_int8_t qfa :1; /* supports QFA formats */
+ u_int8_t reserved5_67 :2;
+ u_int8_t lock :1; /* supports locking media */
+ u_int8_t locked :1; /* the media is locked */
+ u_int8_t prevent :1; /* defaults to prevent state */
+ u_int8_t eject :1; /* supports eject */
+ u_int8_t disconnect :1; /* can break request > ctl */
+ u_int8_t reserved6_5 :1;
+ u_int8_t ecc :1; /* supports error correction */
+ u_int8_t compress :1; /* supports data compression */
+ u_int8_t reserved7_0 :1;
+ u_int8_t blk512 :1; /* supports 512b block size */
+ u_int8_t blk1024 :1; /* supports 1024b block size */
+ u_int8_t reserved7_3456 :4;
+ u_int8_t blk32k :1; /* supports 32kb block size */
+ u_int16_t max_speed; /* supported speed in KBps */
+ u_int16_t max_defects; /* max stored defect entries */
+ u_int16_t ctl; /* continuous transfer limit */
+ u_int16_t speed; /* current Speed, in KBps */
+ u_int16_t buffer_size; /* buffer Size, in 512 bytes */
+ u_int8_t reserved18;
+ u_int8_t reserved19;
};
/* ATAPI OnStream ADR data transfer mode page (ADR unique) */
struct ast_transferpage {
/* mode page data header */
- u_int8_t data_length; /* total length of data */
- u_int8_t medium_type; /* medium type (if any) */
- u_int8_t dsp; /* device specific parameter */
- u_int8_t blk_desc_len; /* block Descriptor Length */
+ u_int8_t data_length; /* total length of data */
+ u_int8_t medium_type; /* medium type (if any) */
+ u_int8_t dsp; /* device specific parameter */
+ u_int8_t blk_desc_len; /* block Descriptor Length */
/* data transfer page */
- u_int8_t page_code :6;
+ u_int8_t page_code :6;
#define ATAPI_TAPE_TRANSFER_PAGE 0x30
- u_int8_t reserved0_6 :1;
- u_int8_t ps :1; /* parameters saveable */
- u_int8_t page_length; /* page Length == 0x02 */
- u_int8_t reserved2;
- u_int8_t read32k :1; /* 32k blk size (data only) */
- u_int8_t read32k5 :1; /* 32.5k blk size (data&AUX) */
- u_int8_t reserved3_23 :2;
- u_int8_t write32k :1; /* 32k blk size (data only) */
- u_int8_t write32k5 :1; /* 32.5k blk size (data&AUX) */
- u_int8_t reserved3_6 :1;
- u_int8_t streaming :1; /* streaming mode enable */
+ u_int8_t reserved0_6 :1;
+ u_int8_t ps :1; /* parameters saveable */
+ u_int8_t page_length; /* page Length == 0x02 */
+ u_int8_t reserved2;
+ u_int8_t read32k :1; /* 32k blk size (data only) */
+ u_int8_t read32k5 :1; /* 32.5k blk size (data&AUX) */
+ u_int8_t reserved3_23 :2;
+ u_int8_t write32k :1; /* 32k blk size (data only) */
+ u_int8_t write32k5 :1; /* 32.5k blk size (data&AUX) */
+ u_int8_t reserved3_6 :1;
+ u_int8_t streaming :1; /* streaming mode enable */
};
/* ATAPI OnStream ADR vendor identification mode page (ADR unique) */
struct ast_identifypage {
/* mode page data header */
- u_int8_t data_length; /* total length of data */
- u_int8_t medium_type; /* medium type (if any) */
- u_int8_t dsp; /* device specific parameter */
- u_int8_t blk_desc_len; /* block Descriptor Length */
+ u_int8_t data_length; /* total length of data */
+ u_int8_t medium_type; /* medium type (if any) */
+ u_int8_t dsp; /* device specific parameter */
+ u_int8_t blk_desc_len; /* block Descriptor Length */
/* data transfer page */
- u_int8_t page_code :6;
+ u_int8_t page_code :6;
#define ATAPI_TAPE_IDENTIFY_PAGE 0x36
- u_int8_t reserved0_6 :1;
- u_int8_t ps :1; /* parameters saveable */
- u_int8_t page_length; /* page Length == 0x06 */
- u_int8_t ident[4]; /* host id string */
- u_int8_t reserved6;
- u_int8_t reserved7;
+ u_int8_t reserved0_6 :1;
+ u_int8_t ps :1; /* parameters saveable */
+ u_int8_t page_length; /* page Length == 0x06 */
+ u_int8_t ident[4]; /* host id string */
+ u_int8_t reserved6;
+ u_int8_t reserved7;
};
/* ATAPI read position structure */
struct ast_readposition {
- u_int8_t reserved0_05 :6;
- u_int8_t eop :1; /* end of partition */
- u_int8_t bop :1; /* beginning of partition */
- u_int8_t reserved1;
- u_int8_t reserved2;
- u_int8_t reserved3;
- u_int32_t host; /* frame address in buffer */
- u_int32_t tape; /* frame address on tape */
- u_int8_t reserved12;
- u_int8_t reserved13;
- u_int8_t reserved14;
- u_int8_t blks_in_buf; /* blocks in buffer */
- u_int8_t reserved16;
- u_int8_t reserved17;
- u_int8_t reserved18;
- u_int8_t reserved19;
+ u_int8_t reserved0_05 :6;
+ u_int8_t eop :1; /* end of partition */
+ u_int8_t bop :1; /* beginning of partition */
+ u_int8_t reserved1;
+ u_int8_t reserved2;
+ u_int8_t reserved3;
+ u_int32_t host; /* frame address in buffer */
+ u_int32_t tape; /* frame address on tape */
+ u_int8_t reserved12;
+ u_int8_t reserved13;
+ u_int8_t reserved14;
+ u_int8_t blks_in_buf; /* blocks in buffer */
+ u_int8_t reserved16;
+ u_int8_t reserved17;
+ u_int8_t reserved18;
+ u_int8_t reserved19;
};
struct ast_softc {
- struct ata_device *device; /* device softc */
- int lun; /* logical device unit */
- int flags; /* device state flags */
-#define F_CTL_WARN 0x0001 /* warned about CTL wrong? */
-#define F_WRITEPROTECT 0x0002 /* media is writeprotected */
-#define F_DATA_WRITTEN 0x0004 /* data has been written */
-#define F_FM_WRITTEN 0x0008 /* filemark has been written */
-#define F_ONSTREAM 0x0100 /* OnStream ADR device */
+ int flags; /* device state flags */
+#define F_CTL_WARN 0x0001 /* warned about CTL wrong? */
+#define F_WRITEPROTECT 0x0002 /* media is writeprotected */
+#define F_DATA_WRITTEN 0x0004 /* data has been written */
+#define F_FM_WRITTEN 0x0008 /* filemark has been written */
+#define F_ONSTREAM 0x0100 /* OnStream ADR device */
- int blksize; /* block size (512 | 1024) */
- struct mtx queue_mtx; /* bio queue lock */
- struct bio_queue_head queue; /* queue of i/o requests */
- struct atapi_params *param; /* drive parameters table */
- struct ast_cappage cap; /* capabilities page info */
- struct devstat *stats; /* devstat entry */
- struct cdev *dev1, *dev2; /* device place holders */
+ int blksize; /* block size (512 | 1024) */
+ struct atapi_params *param; /* drive parameters table */
+ struct ast_cappage cap; /* capabilities page info */
+ struct devstat *stats; /* devstat entry */
+ struct cdev *dev1, *dev2; /* device place holders */
};
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index a196b78..deb74b4 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -23,6 +23,7 @@ SUBDIR= ${_3dfx} \
${_arcnet} \
${_arl} \
${_asr} \
+ ata \
ath \
${_ath_hal} \
ath_rate_amrr \
diff --git a/sys/modules/ata/Makefile b/sys/modules/ata/Makefile
new file mode 100644
index 0000000..b01d00f
--- /dev/null
+++ b/sys/modules/ata/Makefile
@@ -0,0 +1,13 @@
+# $FreeBSD$
+
+SUBDIR = ata
+SUBDIR += atacard
+.if ${MACHINE} == "pc98"
+SUBDIR += atacbus
+.else
+SUBDIR += ataisa
+.endif
+SUBDIR += atapci
+SUBDIR += atadisk atapicd atapifd atapist ataraid #atacam
+
+.include <bsd.subdir.mk>
diff --git a/sys/modules/ata/Makefile.inc b/sys/modules/ata/Makefile.inc
new file mode 100644
index 0000000..265f86d
--- /dev/null
+++ b/sys/modules/ata/Makefile.inc
@@ -0,0 +1,3 @@
+# $FreeBSD$
+
+.include "../Makefile.inc"
diff --git a/sys/modules/ata/ata/Makefile b/sys/modules/ata/ata/Makefile
new file mode 100644
index 0000000..262984e
--- /dev/null
+++ b/sys/modules/ata/ata/Makefile
@@ -0,0 +1,10 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../../dev/ata
+
+KMOD= ata
+SRCS= ata-all.c ata-queue.c ata-lowlevel.c ata_if.c
+# ata-pci.c ata-dma.c ata-chipset.c
+SRCS+= opt_ata.h ata_if.h device_if.h bus_if.h
+
+.include <bsd.kmod.mk>
diff --git a/sys/modules/ata/atacam/Makefile b/sys/modules/ata/atacam/Makefile
new file mode 100644
index 0000000..dcaf847a
--- /dev/null
+++ b/sys/modules/ata/atacam/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../../dev/ata
+
+KMOD= atacam
+SRCS= ata-cam.c
+SRCS+= opt_ata.h opt_cam.h ata_if.h device_if.h bus_if.h pci_if.h
+
+.include <bsd.kmod.mk>
diff --git a/sys/modules/ata/atacard/Makefile b/sys/modules/ata/atacard/Makefile
new file mode 100644
index 0000000..1bb8b5b
--- /dev/null
+++ b/sys/modules/ata/atacard/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../../dev/ata
+
+KMOD= atacard
+SRCS= ata-card.c
+SRCS+= opt_ata.h pccarddevs.h ata_if.h device_if.h bus_if.h isa_if.h card_if.h
+
+.include <bsd.kmod.mk>
diff --git a/sys/modules/ata/atacbus/Makefile b/sys/modules/ata/atacbus/Makefile
new file mode 100644
index 0000000..2b11a89
--- /dev/null
+++ b/sys/modules/ata/atacbus/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../../dev/ata
+
+KMOD= atacbus
+SRCS= ata-cbus.c
+SRCS+= opt_ata.h ata_if.h device_if.h bus_if.h isa_if.h
+
+.include <bsd.kmod.mk>
diff --git a/sys/modules/ata/atadisk/Makefile b/sys/modules/ata/atadisk/Makefile
new file mode 100644
index 0000000..c64cd3f
--- /dev/null
+++ b/sys/modules/ata/atadisk/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../../dev/ata
+
+KMOD= atadisk
+SRCS= ata-disk.c
+SRCS+= opt_ata.h ata_if.h device_if.h bus_if.h pci_if.h
+
+.include <bsd.kmod.mk>
diff --git a/sys/modules/ata/ataisa/Makefile b/sys/modules/ata/ataisa/Makefile
new file mode 100644
index 0000000..b43fd2e
--- /dev/null
+++ b/sys/modules/ata/ataisa/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../../dev/ata
+
+KMOD= ataisa
+SRCS= ata-isa.c
+SRCS+= opt_ata.h ata_if.h device_if.h bus_if.h isa_if.h
+
+.include <bsd.kmod.mk>
diff --git a/sys/modules/ata/atapci/Makefile b/sys/modules/ata/atapci/Makefile
new file mode 100644
index 0000000..00d188b
--- /dev/null
+++ b/sys/modules/ata/atapci/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../../dev/ata
+
+KMOD= atapci
+SRCS= ata-pci.c ata-dma.c ata-chipset.c
+SRCS+= opt_ata.h ata_if.h device_if.h bus_if.h pci_if.h
+
+.include <bsd.kmod.mk>
diff --git a/sys/modules/ata/atapicd/Makefile b/sys/modules/ata/atapicd/Makefile
new file mode 100644
index 0000000..bcc2319
--- /dev/null
+++ b/sys/modules/ata/atapicd/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../../dev/ata
+
+KMOD= atapicd
+SRCS= atapi-cd.c
+SRCS+= opt_ata.h ata_if.h device_if.h bus_if.h pci_if.h
+
+.include <bsd.kmod.mk>
diff --git a/sys/modules/ata/atapifd/Makefile b/sys/modules/ata/atapifd/Makefile
new file mode 100644
index 0000000..f563748
--- /dev/null
+++ b/sys/modules/ata/atapifd/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../../dev/ata
+
+KMOD= atapifd
+SRCS= atapi-fd.c
+SRCS+= opt_ata.h ata_if.h device_if.h bus_if.h pci_if.h
+
+.include <bsd.kmod.mk>
diff --git a/sys/modules/ata/atapist/Makefile b/sys/modules/ata/atapist/Makefile
new file mode 100644
index 0000000..86c19b5
--- /dev/null
+++ b/sys/modules/ata/atapist/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../../dev/ata
+
+KMOD= atapist
+SRCS= atapi-tape.c
+SRCS+= opt_ata.h ata_if.h device_if.h bus_if.h pci_if.h
+
+.include <bsd.kmod.mk>
diff --git a/sys/modules/ata/ataraid/Makefile b/sys/modules/ata/ataraid/Makefile
new file mode 100644
index 0000000..8f41bd7
--- /dev/null
+++ b/sys/modules/ata/ataraid/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../../dev/ata
+
+KMOD= ataraid
+SRCS= ata-raid.c
+SRCS+= opt_ata.h ata_if.h device_if.h bus_if.h pci_if.h
+
+.include <bsd.kmod.mk>
diff --git a/sys/sys/ata.h b/sys/sys/ata.h
index be12cf3..fa214c9 100644
--- a/sys/sys/ata.h
+++ b/sys/sys/ata.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2000 - 2004 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 2000 - 2005 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,7 +37,7 @@
struct ata_params {
/*000*/ u_int16_t config; /* configuration info */
#define ATA_PROTO_MASK 0x8003
-#define ATA_PROTO_ATA 0x0002
+#define ATA_PROTO_ATA 0x0000
#define ATA_PROTO_ATAPI_12 0x8000
#define ATA_PROTO_ATAPI_16 0x8001
#define ATA_ATAPI_TYPE_MASK 0x1f00
@@ -82,7 +82,11 @@ struct ata_params {
#define ATA_FLAG_64_70 0x0002 /* words 64-70 valid */
#define ATA_FLAG_88 0x0004 /* word 88 valid */
-/*054*/ u_int16_t obsolete54[5];
+/*054*/ u_int16_t current_cylinders;
+/*055*/ u_int16_t current_heads;
+/*056*/ u_int16_t current_sectors;
+/*057*/ u_int16_t current_size_1;
+/*058*/ u_int16_t current_size_2;
/*059*/ u_int16_t multi;
#define ATA_MULTI_VALID 0x0100
@@ -155,7 +159,7 @@ struct ata_params {
#define ATA_SUPPORT_FLUSHCACHE48 0x2000
/*084/087*/ u_int16_t extension;
- } support, enabled;
+ } __packed support, enabled;
/*088*/ u_int16_t udmamodes; /* UltraDMA modes */
/*089*/ u_int16_t erase_time;
@@ -182,11 +186,11 @@ struct ata_params {
/*128*/ u_int16_t security_status;
u_int16_t reserved129[31];
/*160*/ u_int16_t cfa_powermode1;
- u_int16_t reserved161[14];
+ u_int16_t reserved161[15];
/*176*/ u_int16_t media_serial[30];
u_int16_t reserved206[49];
/*255*/ u_int16_t integrity;
-};
+} __packed;
/* ATA transfer modes */
#define ATA_MODE_MASK 0x0f
@@ -368,9 +372,14 @@ struct ata_cmd {
struct raid_setup {
int type;
-#define AR_RAID0 1
-#define AR_RAID1 2
-#define AR_SPAN 4
+#define AR_JBOD 0x01
+#define AR_SPAN 0x02
+#define AR_RAID0 0x04
+#define AR_RAID1 0x08
+#define AR_RAID01 0x10
+#define AR_RAID3 0x20
+#define AR_RAID4 0x40
+#define AR_RAID5 0x80
int total_disks;
int disks[16];
OpenPOWER on IntegriCloud