Further updates to the Marvell support code.
Should be reliable enough for actual use by now.
This commit is contained in:
parent
086745614c
commit
796bd93e5e
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=153789
@ -2261,12 +2261,20 @@ ata_marvell_allocate(device_t dev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ata_marvell_response {
|
||||||
|
u_int16_t tag;
|
||||||
|
u_int8_t edma_status;
|
||||||
|
u_int8_t dev_status;
|
||||||
|
u_int32_t timestamp;
|
||||||
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ata_marvell_intr(void *data)
|
ata_marvell_intr(void *data)
|
||||||
{
|
{
|
||||||
struct ata_pci_controller *ctlr = data;
|
struct ata_pci_controller *ctlr = data;
|
||||||
struct ata_channel *ch;
|
struct ata_channel *ch;
|
||||||
struct ata_request *request;
|
struct ata_request *request;
|
||||||
|
struct ata_marvell_response *response;
|
||||||
u_int32_t cause, icr0 = 0, icr1 = 0;
|
u_int32_t cause, icr0 = 0, icr1 = 0;
|
||||||
int unit;
|
int unit;
|
||||||
|
|
||||||
@ -2318,16 +2326,22 @@ ata_marvell_intr(void *data)
|
|||||||
slot = (((rsp_in & ~0xffffff00) >> 3)) & 0x1f;
|
slot = (((rsp_in & ~0xffffff00) >> 3)) & 0x1f;
|
||||||
rsp_out &= 0xffffff00;
|
rsp_out &= 0xffffff00;
|
||||||
rsp_out += (slot << 3);
|
rsp_out += (slot << 3);
|
||||||
|
response = (struct ata_marvell_response *)
|
||||||
|
(u_int8_t *)(ch->dma->work) + 1024 + (slot << 3);
|
||||||
|
|
||||||
/* XXX SOS get status and error into request */
|
/* record status for this request */
|
||||||
request->status = 0; /* XXX SOS */
|
request->status = response->dev_status;
|
||||||
request->error = 0; /* XXX SOS */
|
request->error = 0;
|
||||||
if (!(request->flags & ATA_R_TIMEOUT))
|
|
||||||
request->donecount = request->bytecount;
|
|
||||||
|
|
||||||
/* ack response */
|
/* ack response */
|
||||||
ATA_OUTL(ctlr->r_res1, 0x02024 + ATA_MV_EDMA_BASE(ch), rsp_out);
|
ATA_OUTL(ctlr->r_res1, 0x02024 + ATA_MV_EDMA_BASE(ch), rsp_out);
|
||||||
|
|
||||||
|
/* update progress */
|
||||||
|
if (!(request->status & ATA_S_ERROR) &&
|
||||||
|
!(request->flags & ATA_R_TIMEOUT))
|
||||||
|
request->donecount = request->bytecount;
|
||||||
|
|
||||||
|
/* finish up this request */
|
||||||
ch->running = NULL;
|
ch->running = NULL;
|
||||||
if (ch->state == ATA_ACTIVE)
|
if (ch->state == ATA_ACTIVE)
|
||||||
ch->state = ATA_IDLE;
|
ch->state = ATA_IDLE;
|
||||||
@ -2412,7 +2426,7 @@ ata_marvell_command(struct ata_request *request)
|
|||||||
{
|
{
|
||||||
struct ata_pci_controller *ctlr=device_get_softc(GRANDPARENT(request->dev));
|
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_channel *ch = device_get_softc(device_get_parent(request->dev));
|
||||||
u_int32_t req_in, req_out;
|
u_int32_t req_in;
|
||||||
u_int8_t *bytep;
|
u_int8_t *bytep;
|
||||||
u_int16_t *wordp;
|
u_int16_t *wordp;
|
||||||
u_int32_t *quadp;
|
u_int32_t *quadp;
|
||||||
@ -2420,7 +2434,6 @@ ata_marvell_command(struct ata_request *request)
|
|||||||
int slot;
|
int slot;
|
||||||
|
|
||||||
/* only DMA R/W goes through the EMDA machine */
|
/* only DMA R/W goes through the EMDA machine */
|
||||||
/* XXX SOS add ATAPI commands support later */
|
|
||||||
if (request->u.ata.command != ATA_READ_DMA &&
|
if (request->u.ata.command != ATA_READ_DMA &&
|
||||||
request->u.ata.command != ATA_READ_DMA48 &&
|
request->u.ata.command != ATA_READ_DMA48 &&
|
||||||
request->u.ata.command != ATA_WRITE_DMA &&
|
request->u.ata.command != ATA_WRITE_DMA &&
|
||||||
@ -2432,17 +2445,15 @@ ata_marvell_command(struct ata_request *request)
|
|||||||
return ata_generic_command(request);
|
return ata_generic_command(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
req_out = ATA_INL(ctlr->r_res1, 0x02018 + ATA_MV_EDMA_BASE(ch));
|
|
||||||
|
|
||||||
/* get next free request queue slot */
|
/* get next free request queue slot */
|
||||||
req_in = ATA_INL(ctlr->r_res1, 0x02014 + ATA_MV_EDMA_BASE(ch));
|
req_in = ATA_INL(ctlr->r_res1, 0x02014 + ATA_MV_EDMA_BASE(ch));
|
||||||
slot = (((req_in & ~0xfffffc00) >> 5) + 0) & 0x1f;
|
slot = (((req_in & ~0xfffffc00) >> 5) + 0) & 0x1f;
|
||||||
|
|
||||||
bytep = (u_int8_t *)(ch->dma->work);
|
bytep = (u_int8_t *)(ch->dma->work);
|
||||||
bytep += (slot << 5);
|
bytep += (slot << 5);
|
||||||
wordp = (u_int16_t *)bytep;
|
wordp = (u_int16_t *)bytep;
|
||||||
quadp = (u_int32_t *)bytep;
|
quadp = (u_int32_t *)bytep;
|
||||||
|
|
||||||
|
/* fill in this request */
|
||||||
quadp[0] = (long)ch->dma->sg_bus & 0xffffffff;
|
quadp[0] = (long)ch->dma->sg_bus & 0xffffffff;
|
||||||
quadp[1] = (ch->dma->sg_bus & 0xffffffff00000000) >> 32;
|
quadp[1] = (ch->dma->sg_bus & 0xffffffff00000000) >> 32;
|
||||||
wordp[4] = (request->flags & ATA_R_READ ? 0x01 : 0x00) | (tag<<1);
|
wordp[4] = (request->flags & ATA_R_READ ? 0x01 : 0x00) | (tag<<1);
|
||||||
@ -2481,11 +2492,10 @@ ata_marvell_command(struct ata_request *request)
|
|||||||
DELAY(10);
|
DELAY(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* tell EDMA it has a new request */
|
||||||
slot = (((req_in & ~0xfffffc00) >> 5) + 1) & 0x1f;
|
slot = (((req_in & ~0xfffffc00) >> 5) + 1) & 0x1f;
|
||||||
req_in &= 0xfffffc00;
|
req_in &= 0xfffffc00;
|
||||||
req_in += (slot << 5);
|
req_in += (slot << 5);
|
||||||
|
|
||||||
/* tell EDMA it has a new request */
|
|
||||||
ATA_OUTL(ctlr->r_res1, 0x02014 + ATA_MV_EDMA_BASE(ch), req_in);
|
ATA_OUTL(ctlr->r_res1, 0x02014 + ATA_MV_EDMA_BASE(ch), req_in);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -2499,7 +2509,8 @@ ata_marvell_reset(device_t dev)
|
|||||||
|
|
||||||
/* disable the EDMA machinery */
|
/* disable the EDMA machinery */
|
||||||
ATA_OUTL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch), 0x00000002);
|
ATA_OUTL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch), 0x00000002);
|
||||||
DELAY(100000); /* SOS should poll for disabled */
|
while ((ATA_INL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch)) & 0x00000001))
|
||||||
|
DELAY(10);
|
||||||
|
|
||||||
/* clear SATA error register */
|
/* clear SATA error register */
|
||||||
ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR));
|
ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR));
|
||||||
|
Loading…
Reference in New Issue
Block a user