version 1.172.2.4, 2004/06/24 13:57:07 |
version 1.172.2.5, 2004/08/11 19:43:58 |
Line 146 const struct ata_bustype wdc_ata_bustype |
|
Line 146 const struct ata_bustype wdc_ata_bustype |
|
static int wdcprobe1(struct wdc_channel*, int); |
static int wdcprobe1(struct wdc_channel*, int); |
static void __wdcerror(struct wdc_channel*, char *); |
static void __wdcerror(struct wdc_channel*, char *); |
static int __wdcwait_reset(struct wdc_channel *, int, int); |
static int __wdcwait_reset(struct wdc_channel *, int, int); |
|
static void __wdc_reset_channel(struct wdc_channel *, int); |
static void __wdccommand_done(struct wdc_channel *, struct ata_xfer *); |
static void __wdccommand_done(struct wdc_channel *, struct ata_xfer *); |
|
static void __wdccommand_done_end(struct wdc_channel *, struct ata_xfer *); |
|
static void __wdccommand_kill_xfer(struct wdc_channel *, |
|
struct ata_xfer *, int); |
static void __wdccommand_start(struct wdc_channel *, struct ata_xfer *); |
static void __wdccommand_start(struct wdc_channel *, struct ata_xfer *); |
static int __wdccommand_intr(struct wdc_channel *, struct ata_xfer *, |
static int __wdccommand_intr(struct wdc_channel *, struct ata_xfer *, int); |
int); |
|
static int __wdcwait(struct wdc_channel *, int, int, int); |
static int __wdcwait(struct wdc_channel *, int, int, int); |
|
|
#define DEBUG_INTR 0x01 |
#define DEBUG_INTR 0x01 |
Line 955 wdc_reset_channel(struct ata_drive_datas |
|
Line 958 wdc_reset_channel(struct ata_drive_datas |
|
{ |
{ |
struct wdc_channel *chp = drvp->chnl_softc; |
struct wdc_channel *chp = drvp->chnl_softc; |
struct wdc_softc *wdc = chp->ch_wdc; |
struct wdc_softc *wdc = chp->ch_wdc; |
int drive; |
|
|
|
WDCDEBUG_PRINT(("ata_reset_channel %s:%d for drive %d\n", |
WDCDEBUG_PRINT(("ata_reset_channel %s:%d for drive %d\n", |
wdc->sc_dev.dv_xname, chp->ch_channel, drvp->drive), |
wdc->sc_dev.dv_xname, chp->ch_channel, drvp->drive), |
DEBUG_FUNCS); |
DEBUG_FUNCS); |
|
|
|
|
|
__wdc_reset_channel(chp, flags); |
|
} |
|
|
|
static void |
|
__wdc_reset_channel(struct wdc_channel *chp, int flags) |
|
{ |
|
struct ata_xfer *xfer; |
|
int drive; |
|
|
|
/* |
|
* look for pending xfers. If we have a shared queue, we'll also reset |
|
* the other channel if the current xfer is running on it. |
|
* Then we'll freese the queue, and dequeue only the xfers for this |
|
* channel. xfer->c_kill_xfer() will reset any ATAPI device when |
|
* needed. |
|
*/ |
|
chp->ch_queue->queue_freeze++; |
|
if ((flags & AT_RST_NOCMD) == 0) { |
|
xfer = TAILQ_FIRST(&chp->ch_queue->queue_xfer); |
|
if (xfer && xfer->c_chp != chp) |
|
__wdc_reset_channel(xfer->c_chp, flags); |
|
for (xfer = TAILQ_FIRST(&chp->ch_queue->queue_xfer); |
|
xfer != 0; ) { |
|
if (xfer->c_chp != chp) |
|
continue; |
|
if ((flags & AT_RST_EMERG) == 0) |
|
xfer->c_kill_xfer(chp, xfer, KILL_RESET); |
|
} |
|
} |
if ((flags & AT_POLL) == 0) { |
if ((flags & AT_POLL) == 0) { |
if (chp->ch_flags & WDCF_TH_RESET) { |
if (chp->ch_flags & WDCF_TH_RESET) { |
/* no need to schedule a reset more than one time */ |
/* no need to schedule a reset more than one time */ |
return; |
return; |
} |
} |
chp->ch_flags |= WDCF_TH_RESET; |
chp->ch_flags |= WDCF_TH_RESET; |
chp->ch_queue->queue_freeze++; |
|
wakeup(&chp->ch_thread); |
wakeup(&chp->ch_thread); |
return; |
return; |
} |
} |
Line 974 wdc_reset_channel(struct ata_drive_datas |
|
Line 1005 wdc_reset_channel(struct ata_drive_datas |
|
for (drive = 0; drive < 2; drive++) { |
for (drive = 0; drive < 2; drive++) { |
chp->ch_drive[drive].state = 0; |
chp->ch_drive[drive].state = 0; |
} |
} |
|
if ((flags & AT_RST_EMERG) == 0) { |
|
chp->ch_queue->queue_freeze--; |
|
wdcstart(chp); |
|
} else { |
|
/* make sure that we can use polled commands */ |
|
TAILQ_INIT(&chp->ch_queue->queue_xfer); |
|
chp->ch_queue->queue_freeze = 0; |
|
} |
} |
} |
|
|
int |
int |
Line 1567 wdc_downgrade_mode(struct ata_drive_data |
|
Line 1606 wdc_downgrade_mode(struct ata_drive_data |
|
wdc->set_modes(chp); |
wdc->set_modes(chp); |
wdc_print_modes(chp); |
wdc_print_modes(chp); |
/* reset the channel, which will shedule all drives for setup */ |
/* reset the channel, which will shedule all drives for setup */ |
wdc_reset_channel(drvp, flags); |
wdc_reset_channel(drvp, flags | AT_RST_NOCMD); |
return 1; |
return 1; |
} |
} |
|
|
Line 1600 wdc_exec_command(struct ata_drive_datas |
|
Line 1639 wdc_exec_command(struct ata_drive_datas |
|
xfer->c_cmd = wdc_c; |
xfer->c_cmd = wdc_c; |
xfer->c_start = __wdccommand_start; |
xfer->c_start = __wdccommand_start; |
xfer->c_intr = __wdccommand_intr; |
xfer->c_intr = __wdccommand_intr; |
xfer->c_kill_xfer = __wdccommand_done; |
xfer->c_kill_xfer = __wdccommand_kill_xfer; |
|
|
s = splbio(); |
s = splbio(); |
wdc_exec_xfer(chp, xfer); |
wdc_exec_xfer(chp, xfer); |
Line 1782 __wdccommand_done(struct wdc_channel *ch |
|
Line 1821 __wdccommand_done(struct wdc_channel *ch |
|
wdc->sc_dev.dv_xname, chp->ch_channel, xfer->c_drive), |
wdc->sc_dev.dv_xname, chp->ch_channel, xfer->c_drive), |
DEBUG_FUNCS); |
DEBUG_FUNCS); |
|
|
callout_stop(&chp->ch_callout); |
|
|
|
if (chp->ch_status & WDCS_DWF) |
if (chp->ch_status & WDCS_DWF) |
wdc_c->flags |= AT_DF; |
wdc_c->flags |= AT_DF; |
Line 1790 __wdccommand_done(struct wdc_channel *ch |
|
Line 1828 __wdccommand_done(struct wdc_channel *ch |
|
wdc_c->flags |= AT_ERROR; |
wdc_c->flags |= AT_ERROR; |
wdc_c->r_error = chp->ch_error; |
wdc_c->r_error = chp->ch_error; |
} |
} |
wdc_c->flags |= AT_DONE; |
|
if ((wdc_c->flags & AT_READREG) != 0 && |
if ((wdc_c->flags & AT_READREG) != 0 && |
(wdc->sc_dev.dv_flags & DVF_ACTIVE) != 0 && |
(wdc->sc_dev.dv_flags & DVF_ACTIVE) != 0 && |
(wdc_c->flags & (AT_ERROR | AT_DF)) == 0) { |
(wdc_c->flags & (AT_ERROR | AT_DF)) == 0) { |
Line 1809 __wdccommand_done(struct wdc_channel *ch |
|
Line 1846 __wdccommand_done(struct wdc_channel *ch |
|
wdc_c->r_precomp = bus_space_read_1(chp->cmd_iot, |
wdc_c->r_precomp = bus_space_read_1(chp->cmd_iot, |
chp->cmd_iohs[wd_precomp], 0); |
chp->cmd_iohs[wd_precomp], 0); |
} |
} |
|
__wdccommand_done_end(chp, xfer); |
|
} |
|
|
|
static void |
|
__wdccommand_done_end(struct wdc_channel *chp, struct ata_xfer *xfer) |
|
{ |
|
struct wdc_command *wdc_c = xfer->c_cmd; |
|
|
|
callout_stop(&chp->ch_callout); |
|
wdc_c->flags |= AT_DONE; |
if (wdc_c->flags & AT_POLL) { |
if (wdc_c->flags & AT_POLL) { |
/* enable interrupts */ |
/* enable interrupts */ |
bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr, |
bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr, |
Line 1825 __wdccommand_done(struct wdc_channel *ch |
|
Line 1871 __wdccommand_done(struct wdc_channel *ch |
|
return; |
return; |
} |
} |
|
|
|
static void |
|
__wdccommand_kill_xfer(struct wdc_channel *chp, struct ata_xfer *xfer, |
|
int reason) |
|
{ |
|
struct wdc_command *wdc_c = xfer->c_cmd; |
|
|
|
switch (reason) { |
|
case KILL_GONE: |
|
wdc_c->flags |= AT_GONE; |
|
break; |
|
case KILL_RESET: |
|
wdc_c->flags |= AT_RESET; |
|
break; |
|
default: |
|
printf("__wdccommand_kill_xfer: unknown reason %d\n", |
|
reason); |
|
panic("__wdccommand_kill_xfer"); |
|
} |
|
__wdccommand_done_end(chp, xfer); |
|
|
|
} |
|
|
/* |
/* |
* Send a command. The drive should be ready. |
* Send a command. The drive should be ready. |
* Assumes interrupts are blocked. |
* Assumes interrupts are blocked. |
Line 1942 wdc_exec_xfer(struct wdc_channel *chp, s |
|
Line 2010 wdc_exec_xfer(struct wdc_channel *chp, s |
|
/* complete xfer setup */ |
/* complete xfer setup */ |
xfer->c_chp = chp; |
xfer->c_chp = chp; |
|
|
/* |
|
* If we are a polled command, and the list is not empty, |
|
* we are doing a dump. Drop the list to allow the polled command |
|
* to complete, we're going to reboot soon anyway. |
|
*/ |
|
if ((xfer->c_flags & C_POLL) != 0 && |
|
TAILQ_FIRST(&chp->ch_queue->queue_xfer) != NULL) { |
|
TAILQ_INIT(&chp->ch_queue->queue_xfer); |
|
} |
|
/* insert at the end of command list */ |
/* insert at the end of command list */ |
TAILQ_INSERT_TAIL(&chp->ch_queue->queue_xfer, xfer, c_xferchain); |
TAILQ_INSERT_TAIL(&chp->ch_queue->queue_xfer, xfer, c_xferchain); |
WDCDEBUG_PRINT(("wdcstart from wdc_exec_xfer, flags 0x%x\n", |
WDCDEBUG_PRINT(("wdcstart from wdc_exec_xfer, flags 0x%x\n", |
Line 2001 wdc_kill_pending(struct wdc_channel *chp |
|
Line 2060 wdc_kill_pending(struct wdc_channel *chp |
|
|
|
while ((xfer = TAILQ_FIRST(&chp->ch_queue->queue_xfer)) != NULL) { |
while ((xfer = TAILQ_FIRST(&chp->ch_queue->queue_xfer)) != NULL) { |
chp = xfer->c_chp; |
chp = xfer->c_chp; |
(*xfer->c_kill_xfer)(chp, xfer); |
(*xfer->c_kill_xfer)(chp, xfer, KILL_GONE); |
} |
} |
} |
} |
|
|