summaryrefslogtreecommitdiffstats
path: root/sys/dev/ata/ata-lowlevel.c
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2009-10-31 13:24:14 +0000
committermav <mav@FreeBSD.org>2009-10-31 13:24:14 +0000
commit0bf5f10c46aea8f2fe18b9a91167a9aefc33bc31 (patch)
tree92fd162ac0493f8aac178ae1620be42aeb377f24 /sys/dev/ata/ata-lowlevel.c
parent789d8ecfb76d1350ba654a835108b98bc15c8c98 (diff)
downloadFreeBSD-src-0bf5f10c46aea8f2fe18b9a91167a9aefc33bc31.zip
FreeBSD-src-0bf5f10c46aea8f2fe18b9a91167a9aefc33bc31.tar.gz
MFp4:
- Remove most of direct relations between ATA(4) peripherial and controller levels. It makes logic more transparent and is a mandatory step to wrap ATA(4) controller level into ATA-native CAM SIM. - Tune AHCI and SATA2 SiI drivers memory allocation a bit to allow bigger I/O transaction sizes without additional cost.
Diffstat (limited to 'sys/dev/ata/ata-lowlevel.c')
-rw-r--r--sys/dev/ata/ata-lowlevel.c91
1 files changed, 45 insertions, 46 deletions
diff --git a/sys/dev/ata/ata-lowlevel.c b/sys/dev/ata/ata-lowlevel.c
index c46caa6..2dbb986 100644
--- a/sys/dev/ata/ata-lowlevel.c
+++ b/sys/dev/ata/ata-lowlevel.c
@@ -47,7 +47,7 @@ __FBSDID("$FreeBSD$");
/* prototypes */
static int ata_generic_status(device_t dev);
-static int ata_wait(struct ata_channel *ch, struct ata_device *, u_int8_t);
+static int ata_wait(struct ata_channel *ch, int unit, u_int8_t);
static void ata_pio_read(struct ata_request *, int);
static void ata_pio_write(struct ata_request *, int);
static void ata_tf_read(struct ata_request *);
@@ -77,7 +77,6 @@ int
ata_begin_transaction(struct ata_request *request)
{
struct ata_channel *ch = device_get_softc(request->parent);
- struct ata_device *atadev = device_get_softc(request->dev);
int dummy, error;
ATA_DEBUG_RQ(request, "begin transaction");
@@ -88,9 +87,6 @@ ata_begin_transaction(struct ata_request *request)
(ATA_R_ATAPI | ATA_R_DMA | ATA_R_WRITE)))
request->flags &= ~ATA_R_DMA;
- /* check for 48 bit access and convert if needed */
- ata_modify_if_48bit(request);
-
switch (request->flags & (ATA_R_ATAPI | ATA_R_DMA)) {
/* ATA PIO data transfer and control commands */
@@ -101,7 +97,7 @@ ata_begin_transaction(struct ata_request *request)
/* issue command */
if (ch->hw.command(request)) {
- device_printf(request->dev, "error issuing %s command\n",
+ device_printf(request->parent, "error issuing %s command\n",
ata_cmd2str(request));
request->result = EIO;
goto begin_finished;
@@ -122,8 +118,8 @@ ata_begin_transaction(struct ata_request *request)
/* if write command output the data */
if (write) {
- if (ata_wait(ch, atadev, (ATA_S_READY | ATA_S_DRQ)) < 0) {
- device_printf(request->dev,
+ if (ata_wait(ch, request->unit, (ATA_S_READY | ATA_S_DRQ)) < 0) {
+ device_printf(request->parent,
"timeout waiting for write DRQ\n");
request->result = EIO;
goto begin_finished;
@@ -137,14 +133,14 @@ ata_begin_transaction(struct ata_request *request)
case ATA_R_DMA:
/* check sanity, setup SG list and DMA engine */
if ((error = ch->dma.load(request, NULL, &dummy))) {
- device_printf(request->dev, "setting up DMA failed\n");
+ device_printf(request->parent, "setting up DMA failed\n");
request->result = error;
goto begin_finished;
}
/* issue command */
if (ch->hw.command(request)) {
- device_printf(request->dev, "error issuing %s command\n",
+ device_printf(request->parent, "error issuing %s command\n",
ata_cmd2str(request));
request->result = EIO;
goto begin_finished;
@@ -152,7 +148,7 @@ ata_begin_transaction(struct ata_request *request)
/* start DMA engine */
if (ch->dma.start && ch->dma.start(request)) {
- device_printf(request->dev, "error starting DMA\n");
+ device_printf(request->parent, "error starting DMA\n");
request->result = EIO;
goto begin_finished;
}
@@ -162,7 +158,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 | ATA_DEV(atadev->unit));
+ ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(request->unit));
DELAY(10);
if (!(ATA_IDX_INB(ch, ATA_ALTSTAT) & ATA_S_DSC))
request->result = EBUSY;
@@ -171,7 +167,7 @@ ata_begin_transaction(struct ata_request *request)
/* start ATAPI operation */
if (ch->hw.command(request)) {
- device_printf(request->dev, "error issuing ATA PACKET command\n");
+ device_printf(request->parent, "error issuing ATA PACKET command\n");
request->result = EIO;
goto begin_finished;
}
@@ -181,7 +177,7 @@ ata_begin_transaction(struct ata_request *request)
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 | ATA_DEV(atadev->unit));
+ ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(request->unit));
DELAY(10);
if (!(ATA_IDX_INB(ch, ATA_ALTSTAT) & ATA_S_DSC))
request->result = EBUSY;
@@ -190,14 +186,14 @@ ata_begin_transaction(struct ata_request *request)
/* check sanity, setup SG list and DMA engine */
if ((error = ch->dma.load(request, NULL, &dummy))) {
- device_printf(request->dev, "setting up DMA failed\n");
+ device_printf(request->parent, "setting up DMA failed\n");
request->result = error;
goto begin_finished;
}
/* start ATAPI operation */
if (ch->hw.command(request)) {
- device_printf(request->dev, "error issuing ATA PACKET command\n");
+ device_printf(request->parent, "error issuing ATA PACKET command\n");
request->result = EIO;
goto begin_finished;
}
@@ -229,7 +225,6 @@ int
ata_end_transaction(struct ata_request *request)
{
struct ata_channel *ch = device_get_softc(request->parent);
- struct ata_device *atadev = device_get_softc(request->dev);
int length;
ATA_DEBUG_RQ(request, "end transaction");
@@ -266,8 +261,8 @@ ata_end_transaction(struct ata_request *request)
if (request->u.ata.command != ATA_ATAPI_IDENTIFY)
flags |= ATA_S_READY;
- if (ata_wait(ch, atadev, flags) < 0) {
- device_printf(request->dev,
+ if (ata_wait(ch, request->unit, flags) < 0) {
+ device_printf(request->parent,
"timeout waiting for read DRQ\n");
request->result = EIO;
goto end_finished;
@@ -290,8 +285,8 @@ ata_end_transaction(struct ata_request *request)
if (request->flags & ATA_R_WRITE) {
/* if we get an error here we are done with the HW */
- if (ata_wait(ch, atadev, (ATA_S_READY | ATA_S_DRQ)) < 0) {
- device_printf(request->dev,
+ if (ata_wait(ch, request->unit, (ATA_S_READY | ATA_S_DRQ)) < 0) {
+ device_printf(request->parent,
"timeout waiting for write DRQ\n");
request->status = ATA_IDX_INB(ch, ATA_STATUS);
goto end_finished;
@@ -347,20 +342,19 @@ ata_end_transaction(struct ata_request *request)
DELAY(10);
if (!(request->status & ATA_S_DRQ)) {
- device_printf(request->dev, "command interrupt without DRQ\n");
+ device_printf(request->parent, "command interrupt without DRQ\n");
request->status = ATA_S_ERROR;
goto end_finished;
}
ATA_IDX_OUTSW_STRM(ch, ATA_DATA, (int16_t *)request->u.atapi.ccb,
- (atadev->param.config &
- ATA_PROTO_MASK)== ATA_PROTO_ATAPI_12 ? 6 : 8);
+ (request->flags & ATA_R_ATAPI16) ? 8 : 6);
/* return wait for interrupt */
goto end_continue;
case ATAPI_P_WRITE:
if (request->flags & ATA_R_READ) {
request->status = ATA_S_ERROR;
- device_printf(request->dev,
+ device_printf(request->parent,
"%s trying to write on read buffer\n",
ata_cmd2str(request));
goto end_finished;
@@ -378,7 +372,7 @@ ata_end_transaction(struct ata_request *request)
case ATAPI_P_READ:
if (request->flags & ATA_R_WRITE) {
request->status = ATA_S_ERROR;
- device_printf(request->dev,
+ device_printf(request->parent,
"%s trying to read on write buffer\n",
ata_cmd2str(request));
goto end_finished;
@@ -393,7 +387,7 @@ ata_end_transaction(struct ata_request *request)
goto end_continue;
case ATAPI_P_DONEDRQ:
- device_printf(request->dev,
+ device_printf(request->parent,
"WARNING - %s DONEDRQ non conformant device\n",
ata_cmd2str(request));
if (request->flags & ATA_R_READ) {
@@ -415,7 +409,7 @@ ata_end_transaction(struct ata_request *request)
goto end_finished;
default:
- device_printf(request->dev, "unknown transfer phase\n");
+ device_printf(request->parent, "unknown transfer phase\n");
request->status = ATA_S_ERROR;
}
@@ -603,7 +597,7 @@ ata_generic_status(device_t dev)
}
static int
-ata_wait(struct ata_channel *ch, struct ata_device *atadev, u_int8_t mask)
+ata_wait(struct ata_channel *ch, int unit, u_int8_t mask)
{
u_int8_t status;
int timeout = 0;
@@ -616,7 +610,7 @@ ata_wait(struct ata_channel *ch, struct ata_device *atadev, u_int8_t mask)
/* if drive fails status, reselect the drive and try again */
if (status == 0xff) {
- ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(atadev->unit));
+ ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(unit));
timeout += 1000;
DELAY(1000);
continue;
@@ -657,14 +651,13 @@ int
ata_generic_command(struct ata_request *request)
{
struct ata_channel *ch = device_get_softc(request->parent);
- struct ata_device *atadev = device_get_softc(request->dev);
/* select device */
- ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | ATA_DEV(atadev->unit));
+ ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | ATA_DEV(request->unit));
/* ready to issue command ? */
- if (ata_wait(ch, atadev, 0) < 0) {
- device_printf(request->dev, "timeout waiting to issue command\n");
+ if (ata_wait(ch, request->unit, 0) < 0) {
+ device_printf(request->parent, "timeout waiting to issue command\n");
return -1;
}
@@ -673,6 +666,7 @@ ata_generic_command(struct ata_request *request)
if (request->flags & ATA_R_ATAPI) {
int timeout = 5000;
+ int res;
/* issue packet command to controller */
if (request->flags & ATA_R_DMA) {
@@ -688,9 +682,16 @@ ata_generic_command(struct ata_request *request)
ATA_IDX_OUTB(ch, ATA_COMMAND, ATA_PACKET_CMD);
/* command interrupt device ? just return and wait for interrupt */
- if ((atadev->param.config & ATA_DRQ_MASK) == ATA_DRQ_INTR)
+ if (request->flags & ATA_R_ATAPI_INTR)
return 0;
+ /* command processed ? */
+ res = ata_wait(ch, request->unit, 0);
+ if (res != 0) {
+ if (res < 0)
+ device_printf(request->parent, "timeout waiting for PACKET command\n");
+ return (-1);
+ }
/* wait for ready to write ATAPI command block */
while (timeout--) {
int reason = ATA_IDX_INB(ch, ATA_IREASON);
@@ -702,7 +703,7 @@ ata_generic_command(struct ata_request *request)
DELAY(20);
}
if (timeout <= 0) {
- device_printf(request->dev, "timeout waiting for ATAPI ready\n");
+ device_printf(request->parent, "timeout waiting for ATAPI ready\n");
request->result = EIO;
return -1;
}
@@ -712,8 +713,7 @@ ata_generic_command(struct ata_request *request)
/* output command block */
ATA_IDX_OUTSW_STRM(ch, ATA_DATA, (int16_t *)request->u.atapi.ccb,
- (atadev->param.config & ATA_PROTO_MASK) ==
- ATA_PROTO_ATAPI_12 ? 6 : 8);
+ (request->flags & ATA_R_ATAPI16) ? 8 : 6);
}
else {
ch->hw.tf_write(request);
@@ -728,9 +728,8 @@ static void
ata_tf_read(struct ata_request *request)
{
struct ata_channel *ch = device_get_softc(request->parent);
- struct ata_device *atadev = device_get_softc(request->dev);
- if (atadev->flags & ATA_D_48BIT_ACTIVE) {
+ if (request->flags & ATA_R_48BIT) {
ATA_IDX_OUTB(ch, ATA_CONTROL, ATA_A_4BIT | ATA_A_HOB);
request->u.ata.count = (ATA_IDX_INB(ch, ATA_COUNT) << 8);
request->u.ata.lba =
@@ -760,7 +759,7 @@ ata_tf_write(struct ata_request *request)
struct ata_channel *ch = device_get_softc(request->parent);
struct ata_device *atadev = device_get_softc(request->dev);
- if (atadev->flags & ATA_D_48BIT_ACTIVE) {
+ if (request->flags & ATA_R_48BIT) {
ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature >> 8);
ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature);
ATA_IDX_OUTB(ch, ATA_COUNT, request->u.ata.count >> 8);
@@ -771,7 +770,7 @@ ata_tf_write(struct ata_request *request)
ATA_IDX_OUTB(ch, ATA_CYL_LSB, request->u.ata.lba >> 8);
ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 40);
ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 16);
- ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_LBA | ATA_DEV(atadev->unit));
+ ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_LBA | ATA_DEV(request->unit));
}
else {
ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature);
@@ -793,7 +792,7 @@ ata_tf_write(struct ata_request *request)
(request->u.ata.lba / (sectors * heads)));
ATA_IDX_OUTB(ch, ATA_CYL_MSB,
(request->u.ata.lba / (sectors * heads)) >> 8);
- ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(atadev->unit) |
+ ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(request->unit) |
(((request->u.ata.lba% (sectors * heads)) /
sectors) & 0xf));
}
@@ -802,7 +801,7 @@ ata_tf_write(struct ata_request *request)
ATA_IDX_OUTB(ch, ATA_CYL_LSB, request->u.ata.lba >> 8);
ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 16);
ATA_IDX_OUTB(ch, ATA_DRIVE,
- ATA_D_IBM | ATA_D_LBA | ATA_DEV(atadev->unit) |
+ ATA_D_IBM | ATA_D_LBA | ATA_DEV(request->unit) |
((request->u.ata.lba >> 24) & 0x0f));
}
}
@@ -825,7 +824,7 @@ ata_pio_read(struct ata_request *request, int length)
size / sizeof(int32_t));
if (request->transfersize < length) {
- device_printf(request->dev, "WARNING - %s read data overrun %d>%d\n",
+ device_printf(request->parent, "WARNING - %s read data overrun %d>%d\n",
ata_cmd2str(request), length, request->transfersize);
for (resid = request->transfersize; resid < length;
resid += sizeof(int16_t))
@@ -850,7 +849,7 @@ ata_pio_write(struct ata_request *request, int length)
size / sizeof(int32_t));
if (request->transfersize < length) {
- device_printf(request->dev, "WARNING - %s write data underrun %d>%d\n",
+ device_printf(request->parent, "WARNING - %s write data underrun %d>%d\n",
ata_cmd2str(request), length, request->transfersize);
for (resid = request->transfersize; resid < length;
resid += sizeof(int16_t))
OpenPOWER on IntegriCloud