newer at_wini.c (really incl atapi dma this time)
This commit is contained in:
parent
3017061093
commit
6b01026668
@ -257,7 +257,8 @@ struct command {
|
|||||||
/* Timeouts and max retries. */
|
/* Timeouts and max retries. */
|
||||||
int timeout_ticks = DEF_TIMEOUT_TICKS, max_errors = MAX_ERRORS;
|
int timeout_ticks = DEF_TIMEOUT_TICKS, max_errors = MAX_ERRORS;
|
||||||
long w_standard_timeouts = 0, w_pci_debug = 0, w_instance = 0,
|
long w_standard_timeouts = 0, w_pci_debug = 0, w_instance = 0,
|
||||||
disable_dma = 0, atapi_debug = 0, w_identify_wakeup_ticks, wakeup_ticks;
|
disable_dma = 0, atapi_debug = 0, w_identify_wakeup_ticks,
|
||||||
|
wakeup_ticks, w_atapi_dma;
|
||||||
|
|
||||||
int w_testing = 0, w_silent = 0;
|
int w_testing = 0, w_silent = 0;
|
||||||
|
|
||||||
@ -375,8 +376,8 @@ FORWARD _PROTOTYPE( int w_waitfor, (int mask, int value) );
|
|||||||
FORWARD _PROTOTYPE( int w_waitfor_dma, (int mask, int value) );
|
FORWARD _PROTOTYPE( int w_waitfor_dma, (int mask, int value) );
|
||||||
FORWARD _PROTOTYPE( void w_geometry, (struct partition *entry) );
|
FORWARD _PROTOTYPE( void w_geometry, (struct partition *entry) );
|
||||||
#if ENABLE_ATAPI
|
#if ENABLE_ATAPI
|
||||||
FORWARD _PROTOTYPE( int atapi_sendpacket, (u8_t *packet, unsigned cnt) );
|
FORWARD _PROTOTYPE( int atapi_sendpacket, (u8_t *packet, unsigned cnt, int do_dma) );
|
||||||
FORWARD _PROTOTYPE( int atapi_intr_wait, (void) );
|
FORWARD _PROTOTYPE( int atapi_intr_wait, (int dma, size_t max) );
|
||||||
FORWARD _PROTOTYPE( int atapi_open, (void) );
|
FORWARD _PROTOTYPE( int atapi_open, (void) );
|
||||||
FORWARD _PROTOTYPE( void atapi_close, (void) );
|
FORWARD _PROTOTYPE( void atapi_close, (void) );
|
||||||
FORWARD _PROTOTYPE( int atapi_transfer, (int proc_nr, int opcode,
|
FORWARD _PROTOTYPE( int atapi_transfer, (int proc_nr, int opcode,
|
||||||
@ -475,6 +476,7 @@ PRIVATE void init_params()
|
|||||||
env_parse(NO_DMA_VAR, "d", 0, &disable_dma, 0, 1);
|
env_parse(NO_DMA_VAR, "d", 0, &disable_dma, 0, 1);
|
||||||
env_parse("ata_id_timeout", "d", 0, &wakeup_secs, 1, 60);
|
env_parse("ata_id_timeout", "d", 0, &wakeup_secs, 1, 60);
|
||||||
env_parse("atapi_debug", "d", 0, &atapi_debug, 0, 1);
|
env_parse("atapi_debug", "d", 0, &atapi_debug, 0, 1);
|
||||||
|
env_parse("atapi_dma", "d", 0, &w_atapi_dma, 0, 1);
|
||||||
|
|
||||||
w_identify_wakeup_ticks = wakeup_secs * system_hz;
|
w_identify_wakeup_ticks = wakeup_secs * system_hz;
|
||||||
|
|
||||||
@ -860,6 +862,104 @@ prev_wn = w_wn;
|
|||||||
return(w_dv);
|
return(w_dv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define id_byte(n) (&tmp_buf[2 * (n)])
|
||||||
|
#define id_word(n) (((u16_t) id_byte(n)[0] << 0) \
|
||||||
|
|((u16_t) id_byte(n)[1] << 8))
|
||||||
|
#define id_longword(n) (((u32_t) id_byte(n)[0] << 0) \
|
||||||
|
|((u32_t) id_byte(n)[1] << 8) \
|
||||||
|
|((u32_t) id_byte(n)[2] << 16) \
|
||||||
|
|((u32_t) id_byte(n)[3] << 24))
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* check_dma *
|
||||||
|
*===========================================================================*/
|
||||||
|
void
|
||||||
|
check_dma(struct wini *wn)
|
||||||
|
{
|
||||||
|
unsigned long dma_status = 0;
|
||||||
|
u32_t dma_base;
|
||||||
|
int id_dma, ultra_dma;
|
||||||
|
u16_t w;
|
||||||
|
int driveno, drive1;
|
||||||
|
|
||||||
|
driveno = wn - wini;
|
||||||
|
drive1 = driveno % 2;
|
||||||
|
|
||||||
|
wn->dma= 0;
|
||||||
|
|
||||||
|
if (disable_dma)
|
||||||
|
return;
|
||||||
|
|
||||||
|
w= id_word(ID_CAPABILITIES);
|
||||||
|
id_dma= !!(w & ID_CAP_DMA);
|
||||||
|
w= id_byte(ID_FIELD_VALIDITY)[0];
|
||||||
|
ultra_dma= !!(w & ID_FV_88);
|
||||||
|
dma_base= wn->base_dma;
|
||||||
|
|
||||||
|
if (dma_base) {
|
||||||
|
if (sys_inb(dma_base + DMA_STATUS, &dma_status) != OK) {
|
||||||
|
panic(w_name(),
|
||||||
|
"unable to read DMA status register",
|
||||||
|
NO_NUM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id_dma && dma_base) {
|
||||||
|
w= id_word(ID_MULTIWORD_DMA);
|
||||||
|
if (w_pci_debug &&
|
||||||
|
(w & (ID_MWDMA_2_SUP|ID_MWDMA_1_SUP|ID_MWDMA_0_SUP))) {
|
||||||
|
printf(
|
||||||
|
"%s: multiword DMA modes supported:%s%s%s\n",
|
||||||
|
w_name(),
|
||||||
|
(w & ID_MWDMA_0_SUP) ? " 0" : "",
|
||||||
|
(w & ID_MWDMA_1_SUP) ? " 1" : "",
|
||||||
|
(w & ID_MWDMA_2_SUP) ? " 2" : "");
|
||||||
|
}
|
||||||
|
if (w_pci_debug &&
|
||||||
|
(w & (ID_MWDMA_0_SEL|ID_MWDMA_1_SEL|ID_MWDMA_2_SEL))) {
|
||||||
|
printf(
|
||||||
|
"%s: multiword DMA mode selected:%s%s%s\n",
|
||||||
|
w_name(),
|
||||||
|
(w & ID_MWDMA_0_SEL) ? " 0" : "",
|
||||||
|
(w & ID_MWDMA_1_SEL) ? " 1" : "",
|
||||||
|
(w & ID_MWDMA_2_SEL) ? " 2" : "");
|
||||||
|
}
|
||||||
|
if (w_pci_debug && ultra_dma) {
|
||||||
|
w= id_word(ID_ULTRA_DMA);
|
||||||
|
if (w & (ID_UDMA_0_SUP|ID_UDMA_1_SUP|
|
||||||
|
ID_UDMA_2_SUP|ID_UDMA_3_SUP|
|
||||||
|
ID_UDMA_4_SUP|ID_UDMA_5_SUP)) {
|
||||||
|
printf(
|
||||||
|
"%s: Ultra DMA modes supported:%s%s%s%s%s%s\n",
|
||||||
|
w_name(),
|
||||||
|
(w & ID_UDMA_0_SUP) ? " 0" : "",
|
||||||
|
(w & ID_UDMA_1_SUP) ? " 1" : "",
|
||||||
|
(w & ID_UDMA_2_SUP) ? " 2" : "",
|
||||||
|
(w & ID_UDMA_3_SUP) ? " 3" : "",
|
||||||
|
(w & ID_UDMA_4_SUP) ? " 4" : "",
|
||||||
|
(w & ID_UDMA_5_SUP) ? " 5" : "");
|
||||||
|
}
|
||||||
|
if (w & (ID_UDMA_0_SEL|ID_UDMA_1_SEL|
|
||||||
|
ID_UDMA_2_SEL|ID_UDMA_3_SEL|
|
||||||
|
ID_UDMA_4_SEL|ID_UDMA_5_SEL)) {
|
||||||
|
printf(
|
||||||
|
"%s: Ultra DMA mode selected:%s%s%s%s%s%s\n",
|
||||||
|
w_name(),
|
||||||
|
(w & ID_UDMA_0_SEL) ? " 0" : "",
|
||||||
|
(w & ID_UDMA_1_SEL) ? " 1" : "",
|
||||||
|
(w & ID_UDMA_2_SEL) ? " 2" : "",
|
||||||
|
(w & ID_UDMA_3_SEL) ? " 3" : "",
|
||||||
|
(w & ID_UDMA_4_SEL) ? " 4" : "",
|
||||||
|
(w & ID_UDMA_5_SEL) ? " 5" : "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wn->dma= 1;
|
||||||
|
} else if (id_dma || dma_base) {
|
||||||
|
printf("id_dma %d, dma_base 0x%x\n", id_dma, dma_base);
|
||||||
|
} else
|
||||||
|
printf("no DMA support\n");
|
||||||
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* w_identify *
|
* w_identify *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
@ -872,20 +972,10 @@ PRIVATE int w_identify()
|
|||||||
struct wini *wn = w_wn;
|
struct wini *wn = w_wn;
|
||||||
struct command cmd;
|
struct command cmd;
|
||||||
int i, s;
|
int i, s;
|
||||||
int id_dma, ultra_dma;
|
|
||||||
u32_t dma_base;
|
|
||||||
u16_t w;
|
u16_t w;
|
||||||
unsigned long dma_status;
|
|
||||||
unsigned long size;
|
unsigned long size;
|
||||||
int prev_wakeup;
|
int prev_wakeup;
|
||||||
int r;
|
int r;
|
||||||
#define id_byte(n) (&tmp_buf[2 * (n)])
|
|
||||||
#define id_word(n) (((u16_t) id_byte(n)[0] << 0) \
|
|
||||||
|((u16_t) id_byte(n)[1] << 8))
|
|
||||||
#define id_longword(n) (((u32_t) id_byte(n)[0] << 0) \
|
|
||||||
|((u32_t) id_byte(n)[1] << 8) \
|
|
||||||
|((u32_t) id_byte(n)[2] << 16) \
|
|
||||||
|((u32_t) id_byte(n)[3] << 24))
|
|
||||||
|
|
||||||
/* Try to identify the device. */
|
/* Try to identify the device. */
|
||||||
cmd.ldh = wn->ldhpref;
|
cmd.ldh = wn->ldhpref;
|
||||||
@ -954,96 +1044,7 @@ PRIVATE int w_identify()
|
|||||||
wn->lba48 = 1;
|
wn->lba48 = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for DMA. Assume that only LBA capable devices can do
|
check_dma(wn);
|
||||||
* DMA.
|
|
||||||
*/
|
|
||||||
w= id_word(ID_CAPABILITIES);
|
|
||||||
id_dma= !!(w & ID_CAP_DMA);
|
|
||||||
w= id_byte(ID_FIELD_VALIDITY)[0];
|
|
||||||
ultra_dma= !!(w & ID_FV_88);
|
|
||||||
dma_base= wn->base_dma;
|
|
||||||
if (dma_base)
|
|
||||||
{
|
|
||||||
if (sys_inb(dma_base + DMA_STATUS, &dma_status) != OK)
|
|
||||||
{
|
|
||||||
panic(w_name(),
|
|
||||||
"unable to read DMA status register",
|
|
||||||
NO_NUM);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (disable_dma)
|
|
||||||
; /* DMA is disabled */
|
|
||||||
else if (id_dma && dma_base)
|
|
||||||
{
|
|
||||||
w= id_word(ID_MULTIWORD_DMA);
|
|
||||||
if (w_pci_debug &&
|
|
||||||
(w & (ID_MWDMA_2_SUP|ID_MWDMA_1_SUP|ID_MWDMA_0_SUP)))
|
|
||||||
{
|
|
||||||
printf(
|
|
||||||
"%s: multiword DMA modes supported:%s%s%s\n",
|
|
||||||
w_name(),
|
|
||||||
(w & ID_MWDMA_0_SUP) ? " 0" : "",
|
|
||||||
(w & ID_MWDMA_1_SUP) ? " 1" : "",
|
|
||||||
(w & ID_MWDMA_2_SUP) ? " 2" : "");
|
|
||||||
}
|
|
||||||
if (w_pci_debug &&
|
|
||||||
(w & (ID_MWDMA_0_SEL|ID_MWDMA_1_SEL|ID_MWDMA_2_SEL)))
|
|
||||||
{
|
|
||||||
printf(
|
|
||||||
"%s: multiword DMA mode selected:%s%s%s\n",
|
|
||||||
w_name(),
|
|
||||||
(w & ID_MWDMA_0_SEL) ? " 0" : "",
|
|
||||||
(w & ID_MWDMA_1_SEL) ? " 1" : "",
|
|
||||||
(w & ID_MWDMA_2_SEL) ? " 2" : "");
|
|
||||||
}
|
|
||||||
if (w_pci_debug && ultra_dma)
|
|
||||||
{
|
|
||||||
w= id_word(ID_ULTRA_DMA);
|
|
||||||
if (w & (ID_UDMA_0_SUP|ID_UDMA_1_SUP|
|
|
||||||
ID_UDMA_2_SUP|ID_UDMA_3_SUP|
|
|
||||||
ID_UDMA_4_SUP|ID_UDMA_5_SUP))
|
|
||||||
{
|
|
||||||
printf(
|
|
||||||
"%s: Ultra DMA modes supported:%s%s%s%s%s%s\n",
|
|
||||||
w_name(),
|
|
||||||
(w & ID_UDMA_0_SUP) ? " 0" : "",
|
|
||||||
(w & ID_UDMA_1_SUP) ? " 1" : "",
|
|
||||||
(w & ID_UDMA_2_SUP) ? " 2" : "",
|
|
||||||
(w & ID_UDMA_3_SUP) ? " 3" : "",
|
|
||||||
(w & ID_UDMA_4_SUP) ? " 4" : "",
|
|
||||||
(w & ID_UDMA_5_SUP) ? " 5" : "");
|
|
||||||
}
|
|
||||||
if (w & (ID_UDMA_0_SEL|ID_UDMA_1_SEL|
|
|
||||||
ID_UDMA_2_SEL|ID_UDMA_3_SEL|
|
|
||||||
ID_UDMA_4_SEL|ID_UDMA_5_SEL))
|
|
||||||
{
|
|
||||||
printf(
|
|
||||||
"%s: Ultra DMA mode selected:%s%s%s%s%s%s\n",
|
|
||||||
w_name(),
|
|
||||||
(w & ID_UDMA_0_SEL) ? " 0" : "",
|
|
||||||
(w & ID_UDMA_1_SEL) ? " 1" : "",
|
|
||||||
(w & ID_UDMA_2_SEL) ? " 2" : "",
|
|
||||||
(w & ID_UDMA_3_SEL) ? " 3" : "",
|
|
||||||
(w & ID_UDMA_4_SEL) ? " 4" : "",
|
|
||||||
(w & ID_UDMA_5_SEL) ? " 5" : "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
wn->dma= 1;
|
|
||||||
}
|
|
||||||
else if (id_dma || dma_base)
|
|
||||||
{
|
|
||||||
printf("id_dma %d, dma_base 0x%x\n", id_dma, dma_base);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
printf("no DMA support\n");
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
if (wn->dma && wn == &wini[0])
|
|
||||||
{
|
|
||||||
printf("disabling DMA for drive 0\n");
|
|
||||||
wn->dma= 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wn->lcylinders == 0 || wn->lheads == 0 || wn->lsectors == 0) {
|
if (wn->lcylinders == 0 || wn->lheads == 0 || wn->lsectors == 0) {
|
||||||
@ -1069,6 +1070,7 @@ PRIVATE int w_identify()
|
|||||||
panic(w_name(),"Call to sys_insw() failed", s);
|
panic(w_name(),"Call to sys_insw() failed", s);
|
||||||
|
|
||||||
size = 0; /* Size set later. */
|
size = 0; /* Size set later. */
|
||||||
|
check_dma(wn);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
/* Not an ATA device; no translations, no special features. Don't
|
/* Not an ATA device; no translations, no special features. Don't
|
||||||
@ -1298,14 +1300,13 @@ PRIVATE int do_transfer(struct wini *wn, unsigned int precomp,
|
|||||||
return com_out(&cmd);
|
return com_out(&cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void stop_dma(struct wini *wn)
|
void stop_dma(struct wini *wn)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
/* Stop bus master operation */
|
/* Stop bus master operation */
|
||||||
r= sys_outb(wn->base_dma + DMA_COMMAND, 0);
|
r= sys_outb(wn->base_dma + DMA_COMMAND, 0);
|
||||||
if (r != 0) panic("at_wini", "setup_dma: sys_outb failed", r);
|
if (r != 0) panic("at_wini", "stop_dma: sys_outb failed", r);
|
||||||
}
|
}
|
||||||
|
|
||||||
void start_dma(struct wini *wn, int do_write)
|
void start_dma(struct wini *wn, int do_write)
|
||||||
@ -1321,9 +1322,41 @@ void start_dma(struct wini *wn, int do_write)
|
|||||||
v |= DMA_CMD_WRITE;
|
v |= DMA_CMD_WRITE;
|
||||||
}
|
}
|
||||||
r= sys_outb(wn->base_dma + DMA_COMMAND, v);
|
r= sys_outb(wn->base_dma + DMA_COMMAND, v);
|
||||||
if (r != 0) panic("at_wini", "setup_dma: sys_outb failed", r);
|
if (r != 0) panic("at_wini", "start_dma: sys_outb failed", r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int error_dma(struct wini *wn)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
u32_t v;
|
||||||
|
|
||||||
|
#define DMAERR(msg) \
|
||||||
|
printf("at_wini%d: bad DMA: %s. Disabling DMA for drive %d.\n", \
|
||||||
|
w_instance, msg, wn - wini); \
|
||||||
|
printf("at_wini%d: workaround: set %s=1 in boot monitor.\n", \
|
||||||
|
w_instance, NO_DMA_VAR); \
|
||||||
|
return 1; \
|
||||||
|
|
||||||
|
r= sys_inb(wn->base_dma + DMA_STATUS, &v);
|
||||||
|
if (r != 0) panic("at_wini", "w_transfer: sys_inb failed", r);
|
||||||
|
|
||||||
|
if (!wn->dma_intseen) {
|
||||||
|
/* DMA did not complete successfully */
|
||||||
|
if (v & DMA_ST_BM_ACTIVE) {
|
||||||
|
DMAERR("DMA did not complete");
|
||||||
|
} else if (v & DMA_ST_ERROR) {
|
||||||
|
DMAERR("DMA error");
|
||||||
|
} else {
|
||||||
|
DMAERR("DMA buffer too small");
|
||||||
|
}
|
||||||
|
} else if ((v & DMA_ST_BM_ACTIVE)) {
|
||||||
|
DMAERR("DMA buffer too large");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* w_transfer *
|
* w_transfer *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
@ -1378,10 +1411,8 @@ int safe; /* iov contains addresses (0) or grants? */
|
|||||||
/* First check to see if a reinitialization is needed. */
|
/* First check to see if a reinitialization is needed. */
|
||||||
if (!(wn->state & INITIALIZED) && w_specify() != OK) return(EIO);
|
if (!(wn->state & INITIALIZED) && w_specify() != OK) return(EIO);
|
||||||
|
|
||||||
|
if (do_dma) {
|
||||||
stop_dma(wn);
|
stop_dma(wn);
|
||||||
|
|
||||||
if (do_dma)
|
|
||||||
{
|
|
||||||
setup_dma(&nbytes, proc_nr, iov, addr_offset, do_write,
|
setup_dma(&nbytes, proc_nr, iov, addr_offset, do_write,
|
||||||
&do_copyout, safe);
|
&do_copyout, safe);
|
||||||
#if 0
|
#if 0
|
||||||
@ -1393,6 +1424,7 @@ int safe; /* iov contains addresses (0) or grants? */
|
|||||||
r = do_transfer(wn, wn->precomp, (nbytes >> SECTOR_SHIFT),
|
r = do_transfer(wn, wn->precomp, (nbytes >> SECTOR_SHIFT),
|
||||||
block, opcode, do_dma);
|
block, opcode, do_dma);
|
||||||
|
|
||||||
|
if (do_dma)
|
||||||
start_dma(wn, do_write);
|
start_dma(wn, do_write);
|
||||||
|
|
||||||
if (opcode == DEV_SCATTER_S) {
|
if (opcode == DEV_SCATTER_S) {
|
||||||
@ -1404,8 +1436,7 @@ int safe; /* iov contains addresses (0) or grants? */
|
|||||||
panic(w_name(), "couldn't get status", NO_NUM);
|
panic(w_name(), "couldn't get status", NO_NUM);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (do_dma)
|
if (do_dma) {
|
||||||
{
|
|
||||||
/* Wait for the interrupt, check DMA status and optionally
|
/* Wait for the interrupt, check DMA status and optionally
|
||||||
* copy out.
|
* copy out.
|
||||||
*/
|
*/
|
||||||
@ -1429,39 +1460,9 @@ int safe; /* iov contains addresses (0) or grants? */
|
|||||||
wn->dma_intseen = 1;
|
wn->dma_intseen = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
r= sys_inb(wn->base_dma + DMA_STATUS, &v);
|
if(error_dma(wn)) {
|
||||||
if (r != 0) panic("at_wini", "w_transfer: sys_inb failed", r);
|
wn->dma = 0;
|
||||||
#if 0
|
continue;
|
||||||
if (sys_outb(wn->base_dma + DMA_STATUS, v) != OK) {
|
|
||||||
panic(w_name(), "couldn't ack irq on (out dma)\n", NO_NUM);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define BAD_DMA_CONTINUE(msg) { \
|
|
||||||
printf("at_wini%d: bad DMA: %s. Disabling DMA for drive %d.\n", \
|
|
||||||
w_instance, msg, wn - wini); \
|
|
||||||
printf("at_wini%d: workaround: set %s=1 in boot monitor.\n", \
|
|
||||||
w_instance, NO_DMA_VAR); \
|
|
||||||
wn->dma = 0; \
|
|
||||||
continue; \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
printf("dma_status: 0x%x\n", v);
|
|
||||||
#endif
|
|
||||||
if (!wn->dma_intseen) {
|
|
||||||
/* DMA did not complete successfully */
|
|
||||||
if (v & DMA_ST_BM_ACTIVE) {
|
|
||||||
BAD_DMA_CONTINUE("DMA did not complete");
|
|
||||||
} else if (v & DMA_ST_ERROR) {
|
|
||||||
BAD_DMA_CONTINUE("DMA error");
|
|
||||||
} else {
|
|
||||||
BAD_DMA_CONTINUE("DMA buffer too small");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ((v & DMA_ST_BM_ACTIVE)) {
|
|
||||||
BAD_DMA_CONTINUE("DMA buffer too large");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stop_dma(wn);
|
stop_dma(wn);
|
||||||
@ -1702,7 +1703,6 @@ struct command *cmd; /* Command block */
|
|||||||
|
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* setup_dma *
|
* setup_dma *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
@ -1721,6 +1721,7 @@ int safe;
|
|||||||
int i, j, r, bad;
|
int i, j, r, bad;
|
||||||
unsigned long v;
|
unsigned long v;
|
||||||
struct wini *wn = w_wn;
|
struct wini *wn = w_wn;
|
||||||
|
int verbose = 0;
|
||||||
|
|
||||||
/* First try direct scatter/gather to the supplied buffers */
|
/* First try direct scatter/gather to the supplied buffers */
|
||||||
size= *sizep;
|
size= *sizep;
|
||||||
@ -1729,17 +1730,16 @@ int safe;
|
|||||||
bad= 0;
|
bad= 0;
|
||||||
offset= 0; /* Offset in current iov */
|
offset= 0; /* Offset in current iov */
|
||||||
|
|
||||||
#if 0
|
if(verbose)
|
||||||
printf("at_wini: setup_dma: proc_nr %d\n", proc_nr);
|
printf("at_wini: setup_dma: proc_nr %d\n", proc_nr);
|
||||||
#endif
|
|
||||||
|
|
||||||
while (size > 0)
|
while (size > 0)
|
||||||
{
|
{
|
||||||
#if 0
|
if(verbose) {
|
||||||
printf(
|
printf(
|
||||||
"at_wini: setup_dma: iov[%d]: addr 0x%x, size %d offset %d, size %d\n",
|
"at_wini: setup_dma: iov[%d]: addr 0x%x, size %d offset %d, size %d\n",
|
||||||
i, iov[i].iov_addr, iov[i].iov_size, offset, size);
|
i, iov[i].iov_addr, iov[i].iov_size, offset, size);
|
||||||
#endif
|
}
|
||||||
|
|
||||||
n= iov[i].iov_size-offset;
|
n= iov[i].iov_size-offset;
|
||||||
if (n > size)
|
if (n > size)
|
||||||
@ -1776,6 +1776,7 @@ int safe;
|
|||||||
if (j >= N_PRDTE)
|
if (j >= N_PRDTE)
|
||||||
{
|
{
|
||||||
/* Too many entries */
|
/* Too many entries */
|
||||||
|
|
||||||
bad= 1;
|
bad= 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1803,14 +1804,14 @@ int safe;
|
|||||||
panic("at_wini", "bad prdt index", j);
|
panic("at_wini", "bad prdt index", j);
|
||||||
prdt[j-1].prdte_flags |= PRDTE_FL_EOT;
|
prdt[j-1].prdte_flags |= PRDTE_FL_EOT;
|
||||||
|
|
||||||
#if 0
|
if(verbose) {
|
||||||
for (i= 0; i<j; i++)
|
printf("dma not bad\n");
|
||||||
{
|
for (i= 0; i<j; i++) {
|
||||||
printf("prdt[%d]: base 0x%x, size %d, flags 0x%x\n",
|
printf("prdt[%d]: base 0x%x, size %d, flags 0x%x\n",
|
||||||
i, prdt[i].prdte_base, prdt[i].prdte_count,
|
i, prdt[i].prdte_base, prdt[i].prdte_count,
|
||||||
prdt[i].prdte_flags);
|
prdt[i].prdte_flags);
|
||||||
}
|
}
|
||||||
#endif
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The caller needs to perform a copy-out from the dma buffer if
|
/* The caller needs to perform a copy-out from the dma buffer if
|
||||||
@ -1821,6 +1822,8 @@ int safe;
|
|||||||
|
|
||||||
if (bad)
|
if (bad)
|
||||||
{
|
{
|
||||||
|
if(verbose)
|
||||||
|
printf("partially bad dma\n");
|
||||||
/* Adjust request size */
|
/* Adjust request size */
|
||||||
size= *sizep;
|
size= *sizep;
|
||||||
if (size > ATA_DMA_BUF_SIZE)
|
if (size > ATA_DMA_BUF_SIZE)
|
||||||
@ -1899,14 +1902,14 @@ int safe;
|
|||||||
if (size != 0)
|
if (size != 0)
|
||||||
panic("at_wini", "size to large for prdt", NO_NUM);
|
panic("at_wini", "size to large for prdt", NO_NUM);
|
||||||
|
|
||||||
#if 0
|
if(verbose) {
|
||||||
for (i= 0; i<=j; i++)
|
for (i= 0; i<=j; i++)
|
||||||
{
|
{
|
||||||
printf("prdt[%d]: base 0x%x, size %d, flags 0x%x\n",
|
printf("prdt[%d]: base 0x%x, size %d, flags 0x%x\n",
|
||||||
i, prdt[i].prdte_base, prdt[i].prdte_count,
|
i, prdt[i].prdte_base, prdt[i].prdte_count,
|
||||||
prdt[i].prdte_flags);
|
prdt[i].prdte_flags);
|
||||||
}
|
}
|
||||||
#endif
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Verify that the bus master is not active */
|
/* Verify that the bus master is not active */
|
||||||
@ -1923,6 +1926,7 @@ int safe;
|
|||||||
/* Clear interrupt and error flags */
|
/* Clear interrupt and error flags */
|
||||||
r= sys_outb(wn->base_dma + DMA_STATUS, DMA_ST_INT | DMA_ST_ERROR);
|
r= sys_outb(wn->base_dma + DMA_STATUS, DMA_ST_INT | DMA_ST_ERROR);
|
||||||
if (r != 0) panic("at_wini", "setup_dma: sys_outb failed", r);
|
if (r != 0) panic("at_wini", "setup_dma: sys_outb failed", r);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2261,9 +2265,9 @@ void sense_request(void)
|
|||||||
packet[11] = 0;
|
packet[11] = 0;
|
||||||
|
|
||||||
for(i = 0; i < SENSE_PACKETSIZE; i++) sense[i] = 0xff;
|
for(i = 0; i < SENSE_PACKETSIZE; i++) sense[i] = 0xff;
|
||||||
r = atapi_sendpacket(packet, SENSE_PACKETSIZE);
|
r = atapi_sendpacket(packet, SENSE_PACKETSIZE, 0);
|
||||||
if (r != OK) { printf("request sense command failed\n"); return; }
|
if (r != OK) { printf("request sense command failed\n"); return; }
|
||||||
if (atapi_intr_wait() <= 0) { printf("WARNING: request response failed\n"); }
|
if (atapi_intr_wait(0, 0) <= 0) { printf("WARNING: request response failed\n"); }
|
||||||
|
|
||||||
if (sys_insw(w_wn->base_cmd + REG_DATA, SELF, (void *) sense, SENSE_PACKETSIZE) != OK)
|
if (sys_insw(w_wn->base_cmd + REG_DATA, SELF, (void *) sense, SENSE_PACKETSIZE) != OK)
|
||||||
printf("WARNING: sense reading failed\n");
|
printf("WARNING: sense reading failed\n");
|
||||||
@ -2290,13 +2294,15 @@ int safe; /* use safecopies? */
|
|||||||
u64_t pos;
|
u64_t pos;
|
||||||
unsigned long block;
|
unsigned long block;
|
||||||
u64_t dv_size = w_dv->dv_size;
|
u64_t dv_size = w_dv->dv_size;
|
||||||
unsigned nbytes, nblocks, count, before, chunk;
|
unsigned nbytes, nblocks, before, chunk;
|
||||||
static u8_t packet[ATAPI_PACKETSIZE];
|
static u8_t packet[ATAPI_PACKETSIZE];
|
||||||
size_t addr_offset = 0;
|
size_t addr_offset = 0;
|
||||||
|
int dmabytes = 0, piobytes = 0;
|
||||||
|
|
||||||
errors = fresh = 0;
|
errors = fresh = 0;
|
||||||
|
|
||||||
while (nr_req > 0 && !fresh) {
|
while (nr_req > 0 && !fresh) {
|
||||||
|
int do_dma = wn->dma && w_atapi_dma;
|
||||||
/* The Minix block size is smaller than the CD block size, so we
|
/* The Minix block size is smaller than the CD block size, so we
|
||||||
* may have to read extra before or after the good data.
|
* may have to read extra before or after the good data.
|
||||||
*/
|
*/
|
||||||
@ -2304,16 +2310,17 @@ int safe; /* use safecopies? */
|
|||||||
block = div64u(pos, CD_SECTOR_SIZE);
|
block = div64u(pos, CD_SECTOR_SIZE);
|
||||||
before = rem64u(pos, CD_SECTOR_SIZE);
|
before = rem64u(pos, CD_SECTOR_SIZE);
|
||||||
|
|
||||||
|
if(before)
|
||||||
|
do_dma = 0;
|
||||||
|
|
||||||
/* How many bytes to transfer? */
|
/* How many bytes to transfer? */
|
||||||
nbytes = count = 0;
|
nbytes = 0;
|
||||||
for (iop = iov; iop < iov_end; iop++) {
|
for (iop = iov; iop < iov_end; iop++) {
|
||||||
nbytes += iop->iov_size;
|
nbytes += iop->iov_size;
|
||||||
if ((before + nbytes) % CD_SECTOR_SIZE == 0) count = nbytes;
|
if(iop->iov_size % CD_SECTOR_SIZE)
|
||||||
|
do_dma = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Does one of the memory chunks end nicely on a CD sector multiple? */
|
|
||||||
if (count != 0) nbytes = count;
|
|
||||||
|
|
||||||
/* Data comes in as words, so we have to enforce even byte counts. */
|
/* Data comes in as words, so we have to enforce even byte counts. */
|
||||||
if ((before | nbytes) & 1) return(EINVAL);
|
if ((before | nbytes) & 1) return(EINVAL);
|
||||||
|
|
||||||
@ -2323,10 +2330,6 @@ int safe; /* use safecopies? */
|
|||||||
nbytes = diff64(dv_size, position);
|
nbytes = diff64(dv_size, position);
|
||||||
|
|
||||||
nblocks = (before + nbytes + CD_SECTOR_SIZE - 1) / CD_SECTOR_SIZE;
|
nblocks = (before + nbytes + CD_SECTOR_SIZE - 1) / CD_SECTOR_SIZE;
|
||||||
if (ATAPI_DEBUG) {
|
|
||||||
printf("block=%lu, before=%u, nbytes=%u, nblocks=%u\n",
|
|
||||||
block, before, nbytes, nblocks);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* First check to see if a reinitialization is needed. */
|
/* First check to see if a reinitialization is needed. */
|
||||||
if (!(wn->state & INITIALIZED) && w_specify() != OK) return(EIO);
|
if (!(wn->state & INITIALIZED) && w_specify() != OK) return(EIO);
|
||||||
@ -2345,24 +2348,62 @@ int safe; /* use safecopies? */
|
|||||||
packet[10] = 0;
|
packet[10] = 0;
|
||||||
packet[11] = 0;
|
packet[11] = 0;
|
||||||
|
|
||||||
|
if(do_dma) {
|
||||||
|
int do_copyout = 0;
|
||||||
|
stop_dma(wn);
|
||||||
|
setup_dma(&nbytes, proc_nr, iov, addr_offset, 0,
|
||||||
|
&do_copyout, safe);
|
||||||
|
if(do_copyout || (nbytes != nblocks * CD_SECTOR_SIZE)) {
|
||||||
|
stop_dma(wn);
|
||||||
|
do_dma = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Tell the controller to execute the packet command. */
|
/* Tell the controller to execute the packet command. */
|
||||||
r = atapi_sendpacket(packet, nblocks * CD_SECTOR_SIZE);
|
r = atapi_sendpacket(packet, nblocks * CD_SECTOR_SIZE, do_dma);
|
||||||
if (r != OK) goto err;
|
if (r != OK) goto err;
|
||||||
|
|
||||||
/* Read chunks of data. */
|
if(do_dma) {
|
||||||
while ((r = atapi_intr_wait()) > 0) {
|
wn->dma_intseen = 0;
|
||||||
count = r;
|
start_dma(wn, 0);
|
||||||
|
w_intr_wait();
|
||||||
if (ATAPI_DEBUG) {
|
if(!wn->dma_intseen) {
|
||||||
printf("before=%u, nbytes=%u, count=%u\n",
|
if(w_waitfor_dma(DMA_ST_INT, DMA_ST_INT)) {
|
||||||
before, nbytes, count);
|
wn->dma_intseen = 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if(error_dma(wn)) {
|
||||||
|
printf("Disabling DMA (ATAPI)\n");
|
||||||
|
wn->dma = 0;
|
||||||
|
} else {
|
||||||
|
dmabytes += nbytes;
|
||||||
|
while (nbytes > 0) {
|
||||||
|
size_t chunk;
|
||||||
|
chunk = nbytes;
|
||||||
|
if (chunk > iov->iov_size)
|
||||||
|
chunk = iov->iov_size;
|
||||||
|
position= add64ul(position, chunk);
|
||||||
|
nbytes -= chunk;
|
||||||
|
if ((iov->iov_size -= chunk) == 0) {
|
||||||
|
iov++;
|
||||||
|
nr_req--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read chunks of data. */
|
||||||
|
while ((r = atapi_intr_wait(do_dma, nblocks * CD_SECTOR_SIZE)) > 0) {
|
||||||
|
size_t count;
|
||||||
|
count = r;
|
||||||
|
|
||||||
while (before > 0 && count > 0) { /* Discard before. */
|
while (before > 0 && count > 0) { /* Discard before. */
|
||||||
chunk = before;
|
chunk = before;
|
||||||
if (chunk > count) chunk = count;
|
if (chunk > count) chunk = count;
|
||||||
if (chunk > DMA_BUF_SIZE) chunk = DMA_BUF_SIZE;
|
if (chunk > DMA_BUF_SIZE) chunk = DMA_BUF_SIZE;
|
||||||
if ((s=sys_insw(wn->base_cmd + REG_DATA, SELF, tmp_buf, chunk)) != OK)
|
if ((s=sys_insw(wn->base_cmd + REG_DATA,
|
||||||
|
SELF, tmp_buf, chunk)) != OK)
|
||||||
panic(w_name(),"Call to sys_insw() failed", s);
|
panic(w_name(),"Call to sys_insw() failed", s);
|
||||||
before -= chunk;
|
before -= chunk;
|
||||||
count -= chunk;
|
count -= chunk;
|
||||||
@ -2385,6 +2426,7 @@ int safe; /* use safecopies? */
|
|||||||
nbytes -= chunk;
|
nbytes -= chunk;
|
||||||
count -= chunk;
|
count -= chunk;
|
||||||
addr_offset += chunk;
|
addr_offset += chunk;
|
||||||
|
piobytes += chunk;
|
||||||
fresh = 0;
|
fresh = 0;
|
||||||
if ((iov->iov_size -= chunk) == 0) {
|
if ((iov->iov_size -= chunk) == 0) {
|
||||||
iov++;
|
iov++;
|
||||||
@ -2392,12 +2434,14 @@ int safe; /* use safecopies? */
|
|||||||
fresh = 1; /* new element is optional */
|
fresh = 1; /* new element is optional */
|
||||||
addr_offset = 0;
|
addr_offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (count > 0) { /* Excess data. */
|
while (count > 0) { /* Excess data. */
|
||||||
chunk = count;
|
chunk = count;
|
||||||
if (chunk > DMA_BUF_SIZE) chunk = DMA_BUF_SIZE;
|
if (chunk > DMA_BUF_SIZE) chunk = DMA_BUF_SIZE;
|
||||||
if ((s=sys_insw(wn->base_cmd + REG_DATA, SELF, tmp_buf, chunk)) != OK)
|
if ((s=sys_insw(wn->base_cmd + REG_DATA,
|
||||||
|
SELF, tmp_buf, chunk)) != OK)
|
||||||
panic(w_name(),"Call to sys_insw() failed", s);
|
panic(w_name(),"Call to sys_insw() failed", s);
|
||||||
count -= chunk;
|
count -= chunk;
|
||||||
}
|
}
|
||||||
@ -2415,6 +2459,12 @@ int safe; /* use safecopies? */
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if(dmabytes) printf("dmabytes %d ", dmabytes);
|
||||||
|
if(piobytes) printf("piobytes %d", piobytes);
|
||||||
|
if(dmabytes || piobytes) printf("\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
w_command = CMD_IDLE;
|
w_command = CMD_IDLE;
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
@ -2422,9 +2472,10 @@ int safe; /* use safecopies? */
|
|||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* atapi_sendpacket *
|
* atapi_sendpacket *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int atapi_sendpacket(packet, cnt)
|
PRIVATE int atapi_sendpacket(packet, cnt, do_dma)
|
||||||
u8_t *packet;
|
u8_t *packet;
|
||||||
unsigned cnt;
|
unsigned cnt;
|
||||||
|
int do_dma;
|
||||||
{
|
{
|
||||||
/* Send an Atapi Packet Command */
|
/* Send an Atapi Packet Command */
|
||||||
struct wini *wn = w_wn;
|
struct wini *wn = w_wn;
|
||||||
@ -2455,7 +2506,7 @@ unsigned cnt;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
w_command = ATAPI_PACKETCMD;
|
w_command = ATAPI_PACKETCMD;
|
||||||
pv_set(outbyte[0], wn->base_cmd + REG_FEAT, 0);
|
pv_set(outbyte[0], wn->base_cmd + REG_FEAT, do_dma ? FEAT_DMA : 0);
|
||||||
pv_set(outbyte[1], wn->base_cmd + REG_IRR, 0);
|
pv_set(outbyte[1], wn->base_cmd + REG_IRR, 0);
|
||||||
pv_set(outbyte[2], wn->base_cmd + REG_SAMTAG, 0);
|
pv_set(outbyte[2], wn->base_cmd + REG_SAMTAG, 0);
|
||||||
pv_set(outbyte[3], wn->base_cmd + REG_CNT_LO, (cnt >> 0) & 0xFF);
|
pv_set(outbyte[3], wn->base_cmd + REG_CNT_LO, (cnt >> 0) & 0xFF);
|
||||||
@ -2475,14 +2526,6 @@ unsigned cnt;
|
|||||||
if ((s=sys_outsw(wn->base_cmd + REG_DATA, SELF, packet, ATAPI_PACKETSIZE)) != OK)
|
if ((s=sys_outsw(wn->base_cmd + REG_DATA, SELF, packet, ATAPI_PACKETSIZE)) != OK)
|
||||||
panic(w_name(),"sys_outsw() failed", s);
|
panic(w_name(),"sys_outsw() failed", s);
|
||||||
|
|
||||||
{
|
|
||||||
int p;
|
|
||||||
if (atapi_debug) {
|
|
||||||
printf("sent command:");
|
|
||||||
for(p = 0; p < ATAPI_PACKETSIZE; p++) { printf(" %02x", packet[p]); }
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2656,7 +2699,7 @@ char *strerr(int e)
|
|||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* atapi_intr_wait *
|
* atapi_intr_wait *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int atapi_intr_wait()
|
PRIVATE int atapi_intr_wait(int do_dma, size_t max)
|
||||||
{
|
{
|
||||||
/* Wait for an interrupt and study the results. Returns a number of bytes
|
/* Wait for an interrupt and study the results. Returns a number of bytes
|
||||||
* that need to be transferred, or an error code.
|
* that need to be transferred, or an error code.
|
||||||
@ -2684,9 +2727,6 @@ PRIVATE int atapi_intr_wait()
|
|||||||
len |= inbyte[2].value << 8;
|
len |= inbyte[2].value << 8;
|
||||||
irr = inbyte[3].value;
|
irr = inbyte[3].value;
|
||||||
|
|
||||||
#if ATAPI_DEBUG
|
|
||||||
printf("wn %p S=%x=%s E=%02x=%s L=%04x I=%02x\n", wn, wn->w_status, strstatus(wn->w_status), e, strerr(e), len, irr);
|
|
||||||
#endif
|
|
||||||
if (wn->w_status & (STATUS_BSY | STATUS_CHECK)) {
|
if (wn->w_status & (STATUS_BSY | STATUS_CHECK)) {
|
||||||
if (atapi_debug) {
|
if (atapi_debug) {
|
||||||
printf("atapi fail: S=%x=%s E=%02x=%s L=%04x I=%02x\n", wn->w_status, strstatus(wn->w_status), e, strerr(e), len, irr);
|
printf("atapi fail: S=%x=%s E=%02x=%s L=%04x I=%02x\n", wn->w_status, strstatus(wn->w_status), e, strerr(e), len, irr);
|
||||||
@ -2723,12 +2763,6 @@ PRIVATE int atapi_intr_wait()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* retry if the media changed */
|
|
||||||
XXX while (phase == (IRR_IO | IRR_COD) && (wn->w_status & STATUS_CHECK)
|
|
||||||
&& (e & ERROR_SENSE) == SENSE_UATTN && --try > 0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
wn->w_status |= STATUS_ADMBSY; /* Assume not done yet. */
|
wn->w_status |= STATUS_ADMBSY; /* Assume not done yet. */
|
||||||
return(r);
|
return(r);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user