summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/ata/ata-chipset.c117
-rw-r--r--sys/dev/ata/ata-disk.c2
2 files changed, 81 insertions, 38 deletions
diff --git a/sys/dev/ata/ata-chipset.c b/sys/dev/ata/ata-chipset.c
index bdc02df..6e5f8ca 100644
--- a/sys/dev/ata/ata-chipset.c
+++ b/sys/dev/ata/ata-chipset.c
@@ -4621,12 +4621,11 @@ struct ata_siiprb_dma_prdentry {
} __packed;
struct ata_siiprb_ata_command {
- u_int32_t reserved0;
struct ata_siiprb_dma_prdentry prd[126];
} __packed;
struct ata_siiprb_atapi_command {
- u_int8_t cdb[16];
+ u_int8_t ccb[16];
struct ata_siiprb_dma_prdentry prd[125];
} __packed;
@@ -4634,7 +4633,7 @@ struct ata_siiprb_command {
u_int16_t control;
u_int16_t protocol_override;
u_int32_t transfer_count;
- u_int8_t fis[20];
+ u_int8_t fis[24];
union {
struct ata_siiprb_ata_command ata;
struct ata_siiprb_atapi_command atapi;
@@ -4670,9 +4669,10 @@ ata_siiprb_status(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
+ u_int32_t action = ATA_INL(ctlr->r_res1, 0x0044);
int offset = ch->unit * 0x2000;
- if ((ATA_INL(ctlr->r_res1, 0x0044) & (1 << ch->unit))) {
+ if (action & (1 << ch->unit)) {
u_int32_t istatus = ATA_INL(ctlr->r_res2, 0x1008 + offset);
/* do we have any PHY events ? */
@@ -4682,7 +4682,7 @@ ata_siiprb_status(device_t dev)
ATA_OUTL(ctlr->r_res2, 0x1008 + offset, istatus);
/* do we have any device action ? */
- return (istatus & 0x00000001);
+ return (istatus & 0x00000003);
}
return 0;
}
@@ -4693,10 +4693,17 @@ ata_siiprb_begin_transaction(struct ata_request *request)
struct ata_pci_controller *ctlr=device_get_softc(GRANDPARENT(request->dev));
struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
struct ata_siiprb_command *prb;
+ struct ata_siiprb_dma_prdentry *prd;
int offset = ch->unit * 0x2000;
u_int64_t prb_bus;
int tag = 0, dummy;
+ /* SOS XXX */
+ if (request->u.ata.command == ATA_DEVICE_RESET) {
+ request->result = 0;
+ return ATA_OP_FINISHED;
+ }
+
/* check for 48 bit access and convert if needed */
ata_modify_if_48bit(request);
@@ -4714,14 +4721,26 @@ ata_siiprb_begin_transaction(struct ata_request *request)
return ATA_OP_FINISHED;
}
- /* if request moves data setup and load SG list */
- if (request->flags & (ATA_R_READ | ATA_R_WRITE)) {
- struct ata_siiprb_dma_prdentry *prd;
+ /* setup transfer type */
+ if (request->flags & ATA_R_ATAPI) {
+ struct ata_device *atadev = device_get_softc(request->dev);
- if (request->flags & ATA_R_ATAPI)
- prd = &prb->u.atapi.prd[0];
+ bcopy(request->u.atapi.ccb, prb->u.atapi.ccb, 16);
+ if ((atadev->param.config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12)
+ ATA_OUTL(ctlr->r_res2, 0x1004 + offset, 0x00000020);
else
- prd = &prb->u.ata.prd[0];
+ ATA_OUTL(ctlr->r_res2, 0x1000 + offset, 0x00000020);
+ if (request->flags & ATA_R_READ)
+ prb->control = htole16(0x0010);
+ if (request->flags & ATA_R_WRITE)
+ prb->control = htole16(0x0020);
+ prd = &prb->u.atapi.prd[0];
+ }
+ else
+ prd = &prb->u.ata.prd[0];
+
+ /* if request moves data setup and load SG list */
+ if (request->flags & (ATA_R_READ | ATA_R_WRITE)) {
if (ch->dma->load(ch->dev, request->data, request->bytecount,
request->flags & ATA_R_READ, prd, &dummy)) {
device_printf(request->dev, "setting up DMA failed\n");
@@ -4750,7 +4769,7 @@ ata_siiprb_end_transaction(struct ata_request *request)
struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
struct ata_siiprb_command *prb;
int offset = ch->unit * 0x2000;
- int error, tag = 0;
+ int error, timeout, tag = 0;
/* kill the timeout */
callout_stop(&request->callout);
@@ -4758,10 +4777,37 @@ ata_siiprb_end_transaction(struct ata_request *request)
prb = (struct ata_siiprb_command *)
((u_int8_t *)rman_get_virtual(ctlr->r_res2) + (tag << 7) + offset);
- /* if error status get details */
- request->status = prb->fis[2];
- if (request->status & ATA_S_ERROR)
- request->error = prb->fis[3];
+ /* any controller errors flagged ? */
+ if ((error = ATA_INL(ctlr->r_res2, 0x1024 + offset))) {
+ if (bootverbose)
+ printf("ata_siiprb_end_transaction %s error=%08x\n",
+ ata_cmd2str(request), error);
+
+ /* if device error status get details */
+ if (error == 1 || error == 2) {
+ request->status = prb->fis[2];
+ if (request->status & ATA_S_ERROR)
+ request->error = prb->fis[3];
+ }
+
+ /* SOS XXX handle other controller errors here */
+
+ /* initialize port */
+ ATA_OUTL(ctlr->r_res2, 0x1000 + offset, 0x00000004);
+
+ /* poll for port ready */
+ for (timeout = 0; timeout < 1000; timeout++) {
+ DELAY(1000);
+ if (ATA_INL(ctlr->r_res2, 0x1008 + offset) & 0x00040000)
+ break;
+ }
+ if (bootverbose) {
+ if (timeout >= 1000)
+ device_printf(ch->dev, "port initialize timeout\n");
+ else
+ device_printf(ch->dev, "port initialize time=%dms\n", timeout);
+ }
+ }
/* update progress */
if (!(request->status & ATA_S_ERROR) && !(request->flags & ATA_R_TIMEOUT)) {
@@ -4771,12 +4817,6 @@ ata_siiprb_end_transaction(struct ata_request *request)
request->donecount = request->bytecount;
}
- /* any controller errors flagged ? */
- if ((error = ATA_INL(ctlr->r_res2, 0x1024 + offset))) {
- printf("ata_siiprb_end_transaction %s error=%08x\n",
- ata_cmd2str(request), error);
- }
-
/* release SG list etc */
ch->dma->unload(ch->dev);
@@ -4802,17 +4842,17 @@ ata_siiprb_reset(device_t dev)
/* poll for channel ready */
for (timeout = 0; timeout < 1000; timeout++) {
- if ((status = ATA_INL(ctlr->r_res2, 0x1000 + offset)) & 0x00040000)
+ if ((status = ATA_INL(ctlr->r_res2, 0x1008 + offset)) & 0x00040000)
break;
DELAY(1000);
}
- if (timeout >= 1000) {
- device_printf(ch->dev, "channel HW reset timeout reset failure\n");
- ch->devices = 0;
- goto finish;
+
+ if (bootverbose) {
+ if (timeout >= 1000)
+ device_printf(ch->dev, "channel HW reset timeout\n");
+ else
+ device_printf(ch->dev, "channel HW reset time=%dms\n", timeout);
}
- if (bootverbose)
- device_printf(ch->dev, "channel HW reset time=%dms\n", timeout * 1);
/* reset phy */
if (!ata_sata_phy_reset(dev)) {
@@ -4835,8 +4875,8 @@ ata_siiprb_reset(device_t dev)
ATA_OUTL(ctlr->r_res2,
0x1c04 + offset + (tag * sizeof(u_int64_t)), prb_bus>>32);
- /* poll for channel ready */
- for (timeout = 0; timeout < 1000; timeout++) {
+ /* poll for command finished */
+ for (timeout = 0; timeout < 10000; timeout++) {
DELAY(1000);
if ((status = ATA_INL(ctlr->r_res2, 0x1008 + offset)) & 0x00010000)
break;
@@ -4856,24 +4896,25 @@ ata_siiprb_reset(device_t dev)
signature =
prb->fis[12]|(prb->fis[4]<<8)|(prb->fis[5]<<16)|(prb->fis[6]<<24);
if (bootverbose)
- device_printf(ch->dev, "signature=%08x\n", signature);
+ device_printf(ch->dev, "SIGNATURE=%08x\n", signature);
switch (signature) {
- case 0xeb140101:
- ch->devices = ATA_ATAPI_MASTER;
- device_printf(ch->dev, "SATA ATAPI devices not supported yet\n");
- ch->devices = 0;
+ case 0x00000101:
+ ch->devices = ATA_ATA_MASTER;
break;
case 0x96690101:
ch->devices = ATA_PORTMULTIPLIER;
device_printf(ch->dev, "Portmultipliers not supported yet\n");
ch->devices = 0;
break;
- case 0x00000101:
- ch->devices = ATA_ATA_MASTER;
+ case 0xeb140101:
+ ch->devices = ATA_ATAPI_MASTER;
break;
default:
ch->devices = 0;
}
+ if (bootverbose)
+ device_printf(dev, "siiprb_reset devices=0x%b\n", ch->devices,
+ "\20\4ATAPI_SLAVE\3ATAPI_MASTER\2ATA_SLAVE\1ATA_MASTER");
finish:
/* clear interrupt(s) */
diff --git a/sys/dev/ata/ata-disk.c b/sys/dev/ata/ata-disk.c
index f13de56..63a226c 100644
--- a/sys/dev/ata/ata-disk.c
+++ b/sys/dev/ata/ata-disk.c
@@ -391,6 +391,8 @@ ad_describe(device_t dev)
else {
if (!strncmp(atadev->param.model, "ST", 2))
strcpy(vendor, "Seagate ");
+ else if (!strncmp(atadev->param.model, "HDS", 3))
+ strcpy(vendor, "Hitachi ");
else
strcpy(vendor, "");
strncpy(product, atadev->param.model, 40);
OpenPOWER on IntegriCloud