summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsos <sos@FreeBSD.org>2005-04-29 11:30:03 +0000
committersos <sos@FreeBSD.org>2005-04-29 11:30:03 +0000
commit44e51c4adc8a1316838a9c81e1cd004d4153f2df (patch)
tree34e4ea41ed82100a76d3d7871c6eaf678311334c
parentcc6dd6e0642fedbd23cee68f6ad2dab807e4f717 (diff)
downloadFreeBSD-src-44e51c4adc8a1316838a9c81e1cd004d4153f2df.zip
FreeBSD-src-44e51c4adc8a1316838a9c81e1cd004d4153f2df.tar.gz
Now that probing is working in the new fashion, we need to go back to
having ata_getparm issue an ata_request and not fool around with the HW on its own. Needed for new HW support.
-rw-r--r--sys/dev/ata/ata-all.c218
-rw-r--r--sys/dev/ata/ata-all.h1
-rw-r--r--sys/dev/ata/ata-lowlevel.c138
-rw-r--r--sys/dev/ata/ata-queue.c1
4 files changed, 165 insertions, 193 deletions
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c
index a2f0bab..2c7a895 100644
--- a/sys/dev/ata/ata-all.c
+++ b/sys/dev/ata/ata-all.c
@@ -68,7 +68,10 @@ static struct cdevsw ata_cdevsw = {
/* prototypes */
static void ata_interrupt(void *);
static void ata_boot_attach(void);
-static device_t ata_add_child(device_t parent, struct ata_device *atadev, int unit);
+static device_t ata_add_child(device_t, struct ata_device *, int);
+static void bswap(int8_t *, int);
+static void btrim(int8_t *, int);
+static void bpack(int8_t *, int8_t *, int);
/* global vars */
MALLOC_DEFINE(M_ATA, "ATA generic", "ATA driver generic layer");
@@ -566,7 +569,6 @@ ata_boot_attach(void)
static device_t
ata_add_child(device_t parent, struct ata_device *atadev, int unit)
{
- struct ata_channel *ch = device_get_softc(parent);
device_t child;
if ((child = device_add_child(parent, NULL, unit))) {
@@ -580,83 +582,146 @@ ata_add_child(device_t parent, struct ata_device *atadev, int unit)
atadev->dev = child;
atadev->max_iosize = DEV_BSIZE;
atadev->mode = ATA_PIO_MAX;
+ }
+ return child;
+}
+
+static int
+ata_getparam(device_t parent, struct ata_device *atadev)
+{
+ struct ata_channel *ch = device_get_softc(parent);
+ struct ata_request *request;
+ u_int8_t command = 0;
+ int error = ENOMEM, retries = 2;
+
+ if (ch->devices &
+ (atadev->unit == ATA_MASTER ? ATA_ATA_MASTER : ATA_ATA_SLAVE))
+ command = ATA_ATA_IDENTIFY;
+ if (ch->devices &
+ (atadev->unit == ATA_MASTER ? ATA_ATAPI_MASTER : ATA_ATAPI_SLAVE))
+ command = ATA_ATAPI_IDENTIFY;
+ if (!command)
+ return ENXIO;
+
+ while (retries-- > 0 && error) {
+ if (!(request = ata_alloc_request()))
+ break;
+ request->dev = atadev->dev;
+ request->timeout = 1;
+ request->retries = 0;
+ request->u.ata.command = command;
+ request->flags = (ATA_R_READ|ATA_R_AT_HEAD|ATA_R_DIRECT|ATA_R_QUIET);
+ request->data = (void *)&atadev->param;
+ request->bytecount = sizeof(struct ata_params);
+ request->donecount = 0;
+ request->transfersize = DEV_BSIZE;
+ ata_queue_request(request);
+ error = request->result;
+ 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)
+ 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");
+
if (atadev->param.config & ATA_PROTO_ATAPI) {
- if (atapi_dma && ch->dma &&
+ if (atapi_dma && ch->dma &&
(atadev->param.config & ATA_DRQ_MASK) != ATA_DRQ_INTR &&
- ata_umode(&atadev->param) >= ATA_UDMA2)
+ ata_umode(&atadev->param) >= ATA_UDMA2)
atadev->mode = ATA_DMA_MAX;
}
- else {
+ else {
if (ata_dma && ch->dma)
atadev->mode = ATA_DMA_MAX;
}
}
- return child;
+ else {
+ if (!error)
+ error = ENXIO;
+ }
+ return error;
}
int
ata_identify(device_t dev)
{
struct ata_channel *ch = device_get_softc(dev);
- struct ata_device *master, *slave;
- int master_res = EIO, slave_res = EIO, master_unit = -1, slave_unit = -1;
-
- if (!(master = malloc(sizeof(struct ata_device),
- M_ATA, M_NOWAIT | M_ZERO))) {
- device_printf(dev, "out of memory\n");
- return ENOMEM;
- }
- master->unit = ATA_MASTER;
- if (!(slave = malloc(sizeof(struct ata_device),
- M_ATA, M_NOWAIT | M_ZERO))) {
- free(master, M_ATA);
- device_printf(dev, "out of memory\n");
- return ENOMEM;
+ struct ata_device *master = NULL, *slave = NULL;
+ device_t master_child = NULL, slave_child = NULL;
+ int master_unit = -1, slave_unit = -1;
+
+ if (ch->devices & (ATA_ATA_MASTER | ATA_ATAPI_MASTER)) {
+ if (!(master = malloc(sizeof(struct ata_device),
+ M_ATA, M_NOWAIT | M_ZERO))) {
+ device_printf(dev, "out of memory\n");
+ return ENOMEM;
+ }
+ master->unit = ATA_MASTER;
}
- slave->unit = ATA_SLAVE;
-
- /* wait for the channel to be IDLE then grab it before touching HW */
- while (ATA_LOCKING(dev, ATA_LF_LOCK) != ch->unit)
- tsleep(ch, PRIBIO, "ataidnt1", 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, "ataidnt2", 1);
+ if (ch->devices & (ATA_ATA_SLAVE | ATA_ATAPI_SLAVE)) {
+ if (!(slave = malloc(sizeof(struct ata_device),
+ M_ATA, M_NOWAIT | M_ZERO))) {
+ free(master, M_ATA);
+ device_printf(dev, "out of memory\n");
+ return ENOMEM;
+ }
+ slave->unit = ATA_SLAVE;
}
- if (ch->devices & ATA_ATA_SLAVE) {
- slave_res = ata_getparam(dev, slave, ATA_ATA_IDENTIFY);
#ifdef ATA_STATIC_ID
- slave_unit = (device_get_unit(dev) << 1) + 1;
+ if (ch->devices & ATA_ATA_MASTER)
+ master_unit = (device_get_unit(dev) << 1);
#endif
+ if (master && !(master_child = ata_add_child(dev, master, master_unit))) {
+ free(master, M_ATA);
+ master = NULL;
}
- else if (ch->devices & ATA_ATAPI_SLAVE)
- slave_res = ata_getparam(dev, slave, ATA_ATAPI_IDENTIFY);
-
- if (ch->devices & ATA_ATA_MASTER) {
- master_res = ata_getparam(dev, master, ATA_ATA_IDENTIFY);
#ifdef ATA_STATIC_ID
- master_unit = (device_get_unit(dev) << 1);
+ if (ch->devices & ATA_ATA_SLAVE)
+ slave_unit = (device_get_unit(dev) << 1) + 1;
#endif
+ if (slave && !(slave_child = ata_add_child(dev, slave, slave_unit))) {
+ free(slave, M_ATA);
+ slave = NULL;
}
- else if (ch->devices & ATA_ATAPI_MASTER)
- master_res = ata_getparam(dev, master, ATA_ATAPI_IDENTIFY);
- if (master_res || !ata_add_child(dev, master, master_unit))
- free(master, M_ATA);
-
- if (slave_res || !ata_add_child(dev, slave, slave_unit))
+ if (slave && ata_getparam(dev, slave)) {
+ device_delete_child(dev, slave_child);
free(slave, M_ATA);
-
- mtx_lock(&ch->state_mtx);
- ch->state = ATA_IDLE;
- mtx_unlock(&ch->state_mtx);
- ATA_LOCKING(dev, ATA_LF_UNLOCK);
+ }
+ if (master && ata_getparam(dev, master)) {
+ device_delete_child(dev, master_child);
+ free(master, M_ATA);
+ }
bus_generic_probe(dev);
bus_generic_attach(dev);
@@ -791,6 +856,51 @@ ata_limit_mode(struct ata_device *atadev, int mode, int maxmode)
return mode;
}
+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;
+}
+
+
/*
* module handeling
*/
diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h
index 141e534..eabb23c 100644
--- a/sys/dev/ata/ata-all.h
+++ b/sys/dev/ata/ata-all.h
@@ -471,7 +471,6 @@ void ata_fail_requests(struct ata_channel *ch, device_t dev);
char *ata_cmd2str(struct ata_request *request);
/* ata-lowlevel.c: */
-int ata_getparam(device_t parent, struct ata_device *atadev, u_int8_t command);
void ata_generic_hw(struct ata_channel *ch);
void ata_generic_reset(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);
diff --git a/sys/dev/ata/ata-lowlevel.c b/sys/dev/ata/ata-lowlevel.c
index a723fa9..7974e38 100644
--- a/sys/dev/ata/ata-lowlevel.c
+++ b/sys/dev/ata/ata-lowlevel.c
@@ -54,100 +54,6 @@ static int ata_end_transaction(struct ata_request *);
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);
-
- /* wait a bit to let slow devices settle */
- DELAY(100);
-
- /* disable interrupt */
- ATA_IDX_OUTB(ch, ATA_CONTROL, 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_COMMAND, 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;
- }
-
- return error;
-}
/*
* low level ATA functions
@@ -948,47 +854,3 @@ ata_pio_write(struct ata_request *request, int length)
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-queue.c b/sys/dev/ata/ata-queue.c
index 133f8ad..889a311 100644
--- a/sys/dev/ata/ata-queue.c
+++ b/sys/dev/ata/ata-queue.c
@@ -454,6 +454,7 @@ ata_timeout(struct ata_request *request)
if (ch->state == ATA_ACTIVE || ch->state == ATA_STALL_QUEUE) {
request->flags |= ATA_R_TIMEOUT;
ch->state |= ATA_TIMEOUT;
+ ch->running = NULL;
mtx_unlock(&ch->state_mtx);
ATA_LOCKING(ch->dev, ATA_LF_UNLOCK);
ata_finish(request);
OpenPOWER on IntegriCloud