version 1.129, 2017/10/17 18:52:51 |
version 1.129.4.1, 2019/06/10 22:07:32 |
Line 67 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 67 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#define DEBUG_FUNCS 0x08 |
#define DEBUG_FUNCS 0x08 |
#define DEBUG_PROBE 0x10 |
#define DEBUG_PROBE 0x10 |
#ifdef ATADEBUG |
#ifdef ATADEBUG |
int wdcdebug_atapi_mask = 0; |
#ifndef ATADEBUG_ATAPI_MASK |
|
#define ATADEBUG_ATAPI_MASK 0x0 |
|
#endif |
|
int wdcdebug_atapi_mask = ATADEBUG_ATAPI_MASK; |
#define ATADEBUG_PRINT(args, level) \ |
#define ATADEBUG_PRINT(args, level) \ |
if (wdcdebug_atapi_mask & (level)) \ |
if (wdcdebug_atapi_mask & (level)) \ |
printf args |
printf args |
Line 86 static int wdc_atapi_start(struct ata_ch |
|
Line 89 static int wdc_atapi_start(struct ata_ch |
|
static int wdc_atapi_intr(struct ata_channel *, struct ata_xfer *, int); |
static int wdc_atapi_intr(struct ata_channel *, struct ata_xfer *, int); |
static void wdc_atapi_kill_xfer(struct ata_channel *, |
static void wdc_atapi_kill_xfer(struct ata_channel *, |
struct ata_xfer *, int); |
struct ata_xfer *, int); |
static void wdc_atapi_phase_complete(struct ata_xfer *); |
static void wdc_atapi_phase_complete(struct ata_xfer *, int); |
static void wdc_atapi_poll(struct ata_channel *, struct ata_xfer *); |
static void wdc_atapi_poll(struct ata_channel *, struct ata_xfer *); |
static void wdc_atapi_done(struct ata_channel *, struct ata_xfer *); |
static void wdc_atapi_done(struct ata_channel *, struct ata_xfer *); |
static void wdc_atapi_reset(struct ata_channel *, struct ata_xfer *); |
static void wdc_atapi_reset(struct ata_channel *, struct ata_xfer *); |
Line 208 wdc_atapi_get_params(struct scsipi_chann |
|
Line 211 wdc_atapi_get_params(struct scsipi_chann |
|
struct ata_xfer *xfer; |
struct ata_xfer *xfer; |
int rv; |
int rv; |
|
|
xfer = ata_get_xfer(chp); |
xfer = ata_get_xfer(chp, false); |
if (xfer == NULL) { |
if (xfer == NULL) { |
printf("wdc_atapi_get_params: no xfer\n"); |
printf("wdc_atapi_get_params: no xfer\n"); |
return EBUSY; |
return EBUSY; |
Line 359 wdc_atapi_probe_device(struct atapibus_s |
|
Line 362 wdc_atapi_probe_device(struct atapibus_s |
|
} |
} |
} |
} |
|
|
|
static const struct ata_xfer_ops wdc_atapi_xfer_ops = { |
|
.c_start = wdc_atapi_start, |
|
.c_intr = wdc_atapi_intr, |
|
.c_poll = wdc_atapi_poll, |
|
.c_abort = wdc_atapi_reset, |
|
.c_kill_xfer = wdc_atapi_kill_xfer, |
|
}; |
|
|
static void |
static void |
wdc_atapi_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req, |
wdc_atapi_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req, |
void *arg) |
void *arg) |
Line 387 wdc_atapi_scsipi_request(struct scsipi_c |
|
Line 398 wdc_atapi_scsipi_request(struct scsipi_c |
|
return; |
return; |
} |
} |
|
|
xfer = ata_get_xfer_ext(atac->atac_channels[channel], false, 0); |
xfer = ata_get_xfer(atac->atac_channels[channel], false); |
if (xfer == NULL) { |
if (xfer == NULL) { |
sc_xfer->error = XS_RESOURCE_SHORTAGE; |
sc_xfer->error = XS_RESOURCE_SHORTAGE; |
scsipi_done(sc_xfer); |
scsipi_done(sc_xfer); |
Line 449 wdc_atapi_scsipi_request(struct scsipi_c |
|
Line 460 wdc_atapi_scsipi_request(struct scsipi_c |
|
xfer->c_flags &= ~C_DMA; |
xfer->c_flags &= ~C_DMA; |
#endif /* NATA_DMA */ |
#endif /* NATA_DMA */ |
|
|
xfer->c_scsipi = sc_xfer; |
|
xfer->c_databuf = sc_xfer->data; |
xfer->c_databuf = sc_xfer->data; |
xfer->c_bcount = sc_xfer->datalen; |
xfer->c_bcount = sc_xfer->datalen; |
xfer->c_start = wdc_atapi_start; |
xfer->ops = &wdc_atapi_xfer_ops; |
xfer->c_intr = wdc_atapi_intr; |
xfer->c_scsipi = sc_xfer; |
xfer->c_poll = wdc_atapi_poll; |
xfer->c_atapi.c_dscpoll = 0; |
xfer->c_abort = wdc_atapi_reset; |
|
xfer->c_kill_xfer = wdc_atapi_kill_xfer; |
|
xfer->c_dscpoll = 0; |
|
s = splbio(); |
s = splbio(); |
ata_exec_xfer(atac->atac_channels[channel], xfer); |
ata_exec_xfer(atac->atac_channels[channel], xfer); |
#ifdef DIAGNOSTIC |
#ifdef DIAGNOSTIC |
|
|
} |
} |
/* start timeout machinery */ |
/* start timeout machinery */ |
if ((sc_xfer->xs_control & XS_CTL_POLL) == 0) |
if ((sc_xfer->xs_control & XS_CTL_POLL) == 0) |
callout_reset(&xfer->c_timo_callout, mstohz(sc_xfer->timeout), |
callout_reset(&chp->c_timo_callout, mstohz(sc_xfer->timeout), |
wdctimeout, xfer); |
wdctimeout, chp); |
|
|
if (wdc->select) |
if (wdc->select) |
wdc->select(chp, xfer->c_drive); |
wdc->select(chp, xfer->c_drive); |
Line 777 wdc_atapi_intr(struct ata_channel *chp, |
|
Line 784 wdc_atapi_intr(struct ata_channel *chp, |
|
|
|
/* restore transfer length */ |
/* restore transfer length */ |
len = xfer->c_bcount; |
len = xfer->c_bcount; |
if (xfer->c_lenoff < 0) |
if (xfer->c_atapi.c_lenoff < 0) |
len += xfer->c_lenoff; |
len += xfer->c_atapi.c_lenoff; |
|
|
if (sc_xfer->xs_control & XS_CTL_DATA_IN) |
if (sc_xfer->xs_control & XS_CTL_DATA_IN) |
goto end_piobm_datain; |
goto end_piobm_datain; |
Line 801 wdc_atapi_intr(struct ata_channel *chp, |
|
Line 808 wdc_atapi_intr(struct ata_channel *chp, |
|
printf("%s:%d:%d: device timeout, c_bcount=%d, c_skip=%d\n", |
printf("%s:%d:%d: device timeout, c_bcount=%d, c_skip=%d\n", |
device_xname(atac->atac_dev), chp->ch_channel, |
device_xname(atac->atac_dev), chp->ch_channel, |
xfer->c_drive, xfer->c_bcount, xfer->c_skip); |
xfer->c_drive, xfer->c_bcount, xfer->c_skip); |
ata_channel_unlock(chp); |
|
#if NATA_DMA |
#if NATA_DMA |
if (xfer->c_flags & C_DMA) { |
if (xfer->c_flags & C_DMA) { |
ata_dmaerr(drvp, |
ata_dmaerr(drvp, |
Line 809 wdc_atapi_intr(struct ata_channel *chp, |
|
Line 815 wdc_atapi_intr(struct ata_channel *chp, |
|
} |
} |
#endif |
#endif |
sc_xfer->error = XS_TIMEOUT; |
sc_xfer->error = XS_TIMEOUT; |
|
ata_channel_unlock(chp); |
wdc_atapi_reset(chp, xfer); |
wdc_atapi_reset(chp, xfer); |
return 1; |
return 1; |
} |
} |
Line 821 wdc_atapi_intr(struct ata_channel *chp, |
|
Line 828 wdc_atapi_intr(struct ata_channel *chp, |
|
* and reset device. |
* and reset device. |
*/ |
*/ |
if ((xfer->c_flags & C_TIMEOU) && (xfer->c_flags & C_DMA)) { |
if ((xfer->c_flags & C_TIMEOU) && (xfer->c_flags & C_DMA)) { |
ata_channel_unlock(chp); |
|
ata_dmaerr(drvp, (xfer->c_flags & C_POLL) ? AT_POLL : 0); |
ata_dmaerr(drvp, (xfer->c_flags & C_POLL) ? AT_POLL : 0); |
sc_xfer->error = XS_RESET; |
sc_xfer->error = XS_RESET; |
|
ata_channel_unlock(chp); |
wdc_atapi_reset(chp, xfer); |
wdc_atapi_reset(chp, xfer); |
return (1); |
return (1); |
} |
} |
|
|
if ((sc_xfer->xs_control & XS_CTL_DATA_OUT) == 0 || |
if ((sc_xfer->xs_control & XS_CTL_DATA_OUT) == 0 || |
(xfer->c_flags & C_DMA) != 0) { |
(xfer->c_flags & C_DMA) != 0) { |
printf("wdc_atapi_intr: bad data phase DATAOUT\n"); |
printf("wdc_atapi_intr: bad data phase DATAOUT\n"); |
ata_channel_unlock(chp); |
|
if (xfer->c_flags & C_DMA) { |
if (xfer->c_flags & C_DMA) { |
ata_dmaerr(drvp, |
ata_dmaerr(drvp, |
(xfer->c_flags & C_POLL) ? AT_POLL : 0); |
(xfer->c_flags & C_POLL) ? AT_POLL : 0); |
} |
} |
sc_xfer->error = XS_TIMEOUT; |
sc_xfer->error = XS_TIMEOUT; |
|
ata_channel_unlock(chp); |
wdc_atapi_reset(chp, xfer); |
wdc_atapi_reset(chp, xfer); |
return 1; |
return 1; |
} |
} |
#endif |
#endif |
xfer->c_lenoff = len - xfer->c_bcount; |
xfer->c_atapi.c_lenoff = len - xfer->c_bcount; |
if (xfer->c_bcount < len) { |
if (xfer->c_bcount < len) { |
printf("wdc_atapi_intr: warning: write only " |
printf("wdc_atapi_intr: warning: write only " |
"%d of %d requested bytes\n", xfer->c_bcount, len); |
"%d of %d requested bytes\n", xfer->c_bcount, len); |
|
|
#if NATA_PIOBM |
#if NATA_PIOBM |
end_piobm_dataout: |
end_piobm_dataout: |
#endif |
#endif |
for (i = xfer->c_lenoff; i > 0; i -= 2) |
for (i = xfer->c_atapi.c_lenoff; i > 0; i -= 2) |
bus_space_write_2(wdr->cmd_iot, |
bus_space_write_2(wdr->cmd_iot, |
wdr->cmd_iohs[wd_data], 0, 0); |
wdr->cmd_iohs[wd_data], 0, 0); |
|
|
|
|
if ((sc_xfer->xs_control & XS_CTL_DATA_IN) == 0 || |
if ((sc_xfer->xs_control & XS_CTL_DATA_IN) == 0 || |
(xfer->c_flags & C_DMA) != 0) { |
(xfer->c_flags & C_DMA) != 0) { |
printf("wdc_atapi_intr: bad data phase DATAIN\n"); |
printf("wdc_atapi_intr: bad data phase DATAIN\n"); |
ata_channel_unlock(chp); |
|
if (xfer->c_flags & C_DMA) { |
if (xfer->c_flags & C_DMA) { |
ata_dmaerr(drvp, |
ata_dmaerr(drvp, |
(xfer->c_flags & C_POLL) ? AT_POLL : 0); |
(xfer->c_flags & C_POLL) ? AT_POLL : 0); |
} |
} |
sc_xfer->error = XS_TIMEOUT; |
sc_xfer->error = XS_TIMEOUT; |
|
ata_channel_unlock(chp); |
wdc_atapi_reset(chp, xfer); |
wdc_atapi_reset(chp, xfer); |
return 1; |
return 1; |
} |
} |
#endif |
#endif |
xfer->c_lenoff = len - xfer->c_bcount; |
xfer->c_atapi.c_lenoff = len - xfer->c_bcount; |
if (xfer->c_bcount < len) { |
if (xfer->c_bcount < len) { |
printf("wdc_atapi_intr: warning: reading only " |
printf("wdc_atapi_intr: warning: reading only " |
"%d of %d bytes\n", xfer->c_bcount, len); |
"%d of %d bytes\n", xfer->c_bcount, len); |
|
|
#if NATA_PIOBM |
#if NATA_PIOBM |
end_piobm_datain: |
end_piobm_datain: |
#endif |
#endif |
if (xfer->c_lenoff > 0) |
if (xfer->c_atapi.c_lenoff > 0) |
wdcbit_bucket(chp, xfer->c_lenoff); |
wdcbit_bucket(chp, xfer->c_atapi.c_lenoff); |
|
|
xfer->c_skip += len; |
xfer->c_skip += len; |
xfer->c_bcount -= len; |
xfer->c_bcount -= len; |
|
|
#endif |
#endif |
sc_xfer->resid = xfer->c_bcount; |
sc_xfer->resid = xfer->c_bcount; |
/* this will unlock channel lock too */ |
/* this will unlock channel lock too */ |
wdc_atapi_phase_complete(xfer); |
wdc_atapi_phase_complete(xfer, tfd); |
return(1); |
return(1); |
|
|
default: |
default: |
|
|
sc_xfer->error = XS_SHORTSENSE; |
sc_xfer->error = XS_SHORTSENSE; |
sc_xfer->sense.atapi_sense = ATACH_ERR(tfd); |
sc_xfer->sense.atapi_sense = ATACH_ERR(tfd); |
} else { |
} else { |
ata_channel_unlock(chp); |
|
#if NATA_DMA |
#if NATA_DMA |
if (xfer->c_flags & C_DMA) { |
if (xfer->c_flags & C_DMA) { |
ata_dmaerr(drvp, |
ata_dmaerr(drvp, |
|
|
} |
} |
#endif |
#endif |
sc_xfer->error = XS_RESET; |
sc_xfer->error = XS_RESET; |
|
ata_channel_unlock(chp); |
wdc_atapi_reset(chp, xfer); |
wdc_atapi_reset(chp, xfer); |
return (1); |
return (1); |
} |
} |
|
|
} |
} |
|
|
static void |
static void |
wdc_atapi_phase_complete(struct ata_xfer *xfer) |
wdc_atapi_phase_complete(struct ata_xfer *xfer, int tfd) |
{ |
{ |
struct ata_channel *chp = xfer->c_chp; |
struct ata_channel *chp = xfer->c_chp; |
struct atac_softc *atac = chp->ch_atac; |
struct atac_softc *atac = chp->ch_atac; |
Line 1060 wdc_atapi_phase_complete(struct ata_xfer |
|
Line 1067 wdc_atapi_phase_complete(struct ata_xfer |
|
#endif |
#endif |
struct scsipi_xfer *sc_xfer = xfer->c_scsipi; |
struct scsipi_xfer *sc_xfer = xfer->c_scsipi; |
struct ata_drive_datas *drvp = &chp->ch_drive[xfer->c_drive]; |
struct ata_drive_datas *drvp = &chp->ch_drive[xfer->c_drive]; |
int tfd = 0; |
|
|
|
ata_channel_lock_owned(chp); |
ata_channel_lock_owned(chp); |
|
|
Line 1069 wdc_atapi_phase_complete(struct ata_xfer |
|
Line 1075 wdc_atapi_phase_complete(struct ata_xfer |
|
ATADEBUG_PRINT(("wdc_atapi_phase_complete(%s:%d:%d) " |
ATADEBUG_PRINT(("wdc_atapi_phase_complete(%s:%d:%d) " |
"polldsc %d\n", device_xname(atac->atac_dev), |
"polldsc %d\n", device_xname(atac->atac_dev), |
chp->ch_channel, |
chp->ch_channel, |
xfer->c_drive, xfer->c_dscpoll), DEBUG_XFERS); |
xfer->c_drive, xfer->c_atapi.c_dscpoll), DEBUG_XFERS); |
#if 1 |
#if 1 |
if (cold) |
if (cold) |
panic("wdc_atapi_phase_complete: cold"); |
panic("wdc_atapi_phase_complete: cold"); |
Line 1077 wdc_atapi_phase_complete(struct ata_xfer |
|
Line 1083 wdc_atapi_phase_complete(struct ata_xfer |
|
if (wdcwait(chp, WDCS_DSC, WDCS_DSC, 10, |
if (wdcwait(chp, WDCS_DSC, WDCS_DSC, 10, |
AT_POLL, &tfd) == WDCWAIT_TOUT) { |
AT_POLL, &tfd) == WDCWAIT_TOUT) { |
/* 10ms not enough, try again in 1 tick */ |
/* 10ms not enough, try again in 1 tick */ |
if (xfer->c_dscpoll++ > |
if (xfer->c_atapi.c_dscpoll++ > |
mstohz(sc_xfer->timeout)) { |
mstohz(sc_xfer->timeout)) { |
printf("%s:%d:%d: wait_for_dsc " |
printf("%s:%d:%d: wait_for_dsc " |
"failed\n", |
"failed\n", |
Line 1087 wdc_atapi_phase_complete(struct ata_xfer |
|
Line 1093 wdc_atapi_phase_complete(struct ata_xfer |
|
sc_xfer->error = XS_TIMEOUT; |
sc_xfer->error = XS_TIMEOUT; |
wdc_atapi_reset(chp, xfer); |
wdc_atapi_reset(chp, xfer); |
} else { |
} else { |
callout_reset(&xfer->c_timo_callout, 1, |
callout_reset(&chp->c_timo_callout, 1, |
wdc_atapi_polldsc, xfer); |
wdc_atapi_polldsc, chp); |
ata_channel_unlock(chp); |
ata_channel_unlock(chp); |
} |
} |
return; |
return; |
Line 1116 wdc_atapi_phase_complete(struct ata_xfer |
|
Line 1122 wdc_atapi_phase_complete(struct ata_xfer |
|
#if NATA_DMA || NATA_PIOBM |
#if NATA_DMA || NATA_PIOBM |
else if (wdc->dma_status & |
else if (wdc->dma_status & |
(WDC_DMAST_NOIRQ | WDC_DMAST_ERR)) { |
(WDC_DMAST_NOIRQ | WDC_DMAST_ERR)) { |
ata_channel_unlock(chp); |
|
#if NATA_DMA |
#if NATA_DMA |
ata_dmaerr(drvp, |
ata_dmaerr(drvp, |
(xfer->c_flags & C_POLL) ? AT_POLL : 0); |
(xfer->c_flags & C_POLL) ? AT_POLL : 0); |
#endif |
#endif |
sc_xfer->error = XS_RESET; |
sc_xfer->error = XS_RESET; |
|
ata_channel_unlock(chp); |
wdc_atapi_reset(chp, xfer); |
wdc_atapi_reset(chp, xfer); |
return; |
return; |
} |
} |
Line 1192 wdc_atapi_reset(struct ata_channel *chp, |
|
Line 1198 wdc_atapi_reset(struct ata_channel *chp, |
|
static void |
static void |
wdc_atapi_polldsc(void *arg) |
wdc_atapi_polldsc(void *arg) |
{ |
{ |
struct ata_xfer *xfer = arg; |
struct ata_channel *chp = arg; |
struct ata_channel *chp = xfer->c_chp; |
struct ata_xfer *xfer = ata_queue_get_active_xfer(chp); |
|
|
|
KASSERT(xfer != NULL); |
|
|
ata_channel_lock(chp); |
ata_channel_lock(chp); |
|
|
/* this will unlock channel lock too */ |
/* this will unlock channel lock too */ |
wdc_atapi_phase_complete(xfer); |
wdc_atapi_phase_complete(xfer, 0); |
} |
} |