/* $NetBSD: mvsata.c,v 1.62 2021/12/05 04:37:11 msaitoh Exp $ */
/*
* Copyright (c) 2008 KIYOHARA Takashi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <dev/scsipi/scsi_all.h> /* for SCSI status */
#include "atapibus.h"
#include <dev/pci/pcidevs.h> /* XXX should not be here */
/*
* Nice things to do:
*
* - MSI/MSI-X support - though on some models MSI actually doesn't work
* even when hardware claims to support it, according to FreeBSD/OpenBSD
* - move pci-specific code to the pci attach code
* - mvsata(4) use 64-bit DMA on hardware which claims to support it
* - e.g. AHA1430SA does not really work, crash in mvsata_intr() on boot
*/
#define DPRINTF(n,x) if (mvsata_debug & (n)) printf x
int mvsata_debug = 0;
#else
#define DPRINTF(n,x)
#endif
#define ATA_DELAY 10000 /* 10s for a drive I/O */
#define ATAPI_DELAY 10 /* 10 ms, this is used only before
sending a cmd */
#define ATAPI_MODE_DELAY 1000 /* 1s, timeout for SET_FEATURE cmds */
static int
mvsata_nondma_handle(struct mvsata_port *mvport)
{
struct ata_channel *chp = &mvport->port_ata_channel;
struct ata_xfer *xfer;
int ret;
/*
* The chip doesn't support several pending non-DMA commands,
* and the ata middle layer never issues several non-NCQ commands,
* so there must be exactly one active command at this moment.
*/
xfer = ata_queue_get_active_xfer(chp);
if (xfer == NULL) {
/* Can happen after error recovery, ignore */
DPRINTF(DEBUG_FUNCS|DEBUG_XFERS,
("%s:%d: %s: intr without xfer\n",
device_xname(MVSATA_DEV2(mvport)), chp->ch_channel,
__func__));
return 0;
}
ret = xfer->ops->c_intr(chp, xfer, 1);
return (ret);
}
cause &= MVSATA_EDMA_READ_4(mvport, EDMA_IEM);
if (!cause)
return 0;
if (cause & EDMA_IE_EDEVDIS) {
aprint_normal("%s:%d:%d: device disconnect\n",
device_xname(MVSATA_DEV2(mvport)),
mvport->port_hc->hc, mvport->port);
}
if (cause & EDMA_IE_EDEVCON) {
if (sc->sc_gen == gen1)
mvsata_devconn_gen1(mvport);
DPRINTF(DEBUG_INTR, (" device connected\n"));
}
#ifndef MVSATA_WITHOUTDMA
if ((sc->sc_gen == gen1 && cause & EDMA_IE_ETRANSINT) ||
(sc->sc_gen != gen1 && cause & EDMA_IE_ESELFDIS)) {
switch (mvport->port_edmamode_curr) {
case dma:
case queued:
case ncq:
mvsata_edma_reset_qptr(mvport);
mvsata_edma_enable(mvport);
if (cause & EDMA_IE_EDEVERR)
break;
/* FALLTHROUGH */
case nodma:
default:
DPRINTF(DEBUG_INTR,
("%s:%d:%d: EDMA self disable happen 0x%x\n",
device_xname(MVSATA_DEV2(mvport)),
mvport->port_hc->hc, mvport->port, cause));
break;
}
}
#endif
if (cause & EDMA_IE_ETRANSINT) {
/* hot plug the Port Multiplier */
aprint_normal("%s:%d:%d: detect Port Multiplier?\n",
device_xname(MVSATA_DEV2(mvport)),
mvport->port_hc->hc, mvport->port);
}
if (cause & EDMA_IE_EDEVERR) {
struct ata_channel *chp = &mvport->port_ata_channel;
if (chp->ch_ndrives > PMP_PORT_CTL) {
/* Get PM port number for the device in error. This device
* doesn't seem to have dedicated register for this, so just
* assume last selected port was the one. */
/* XXX FIS-based switching */
drive = MVSATA_EDMA_READ_4(mvport, SATA_SATAICTL) & 0xf;
} else
drive = 0;
/*
* Controller doesn't need any special action. Simply execute
* READ LOG EXT for NCQ to unblock device processing, then continue
* as if nothing happened.
*/
ata_recovery_resume(chp, drive, tfd, AT_POLL);
/* Drive unblocked, back to normal operation */
return;
}
#endif /* !MVSATA_WITHOUTDMA */
/* skip if already attached */
if (scsipi_lookup_periph(chan, target, 0) != NULL)
return;
/* if no ATAPI device detected at attach time, skip */
if (drvp->drive_type != ATA_DRIVET_ATAPI) {
DPRINTF(DEBUG_PROBE, ("%s:%d: mvsata_atapi_probe_device:"
" drive %d not present\n",
device_xname(atac->atac_dev), chp->ch_channel, target));
return;
}
/* Some ATAPI devices need a bit more time after software reset. */
delay(5000);
if (ata_get_params(drvp, AT_WAIT, id) == 0) {
#ifdef ATAPI_DEBUG_PROBE
printf("%s drive %d: cmdsz 0x%x drqtype 0x%x\n",
device_xname(sc->sc_dev), target,
id->atap_config & ATAPI_CFG_CMD_MASK,
id->atap_config & ATAPI_CFG_DRQ_MASK);
#endif
periph = scsipi_alloc_periph(M_WAITOK);
periph->periph_dev = NULL;
periph->periph_channel = chan;
periph->periph_switch = &atapi_probe_periphsw;
periph->periph_target = target;
periph->periph_lun = 0;
periph->periph_quirks = PQUIRK_ONLYBIG;
#ifdef SCSIPI_DEBUG
if (SCSIPI_DEBUG_TYPE == SCSIPI_BUSTYPE_ATAPI &&
SCSIPI_DEBUG_TARGET == target)
periph->periph_dbflags |= SCSIPI_DEBUG_FLAGS;
#endif
periph->periph_type = ATAPI_CFG_TYPE(id->atap_config);
if (id->atap_config & ATAPI_CFG_REMOV)
periph->periph_flags |= PERIPH_REMOVABLE;
if (periph->periph_type == T_SEQUENTIAL) {
s = splbio();
drvp->drive_flags |= ATA_DRIVE_ATAPIDSCW;
splx(s);
}
if (drvp->drv_softc)
ata_probe_caps(drvp);
else {
s = splbio();
drvp->drive_type = ATA_DRIVET_NONE;
splx(s);
}
} else {
DPRINTF(DEBUG_PROBE, ("%s:%d: mvsata_atapi_probe_device:"
" ATAPI_IDENTIFY_DEVICE failed for drive %d: error\n",
device_xname(atac->atac_dev), chp->ch_channel, target));
s = splbio();
drvp->drive_type = ATA_DRIVET_NONE;
splx(s);
}
}
/*
* Kill off all pending xfers for a periph.
*
* Must be called at splbio().
*/
static void
mvsata_atapi_kill_pending(struct scsipi_periph *periph)
{
struct atac_softc *atac =
device_private(periph->periph_channel->chan_adapter->adapt_dev);
struct ata_channel *chp =
atac->atac_channels[periph->periph_channel->chan_channel];
if (xfer->c_flags & C_DMA)
if (drvp->n_xfers <= NXFER)
drvp->n_xfers++;
/*
*
* When starting a multi-sector transfer, or doing single-sector
* transfers...
*/
if (xfer->c_skip == 0 || (ata_bio->flags & ATA_SINGLE) != 0) {
if (ata_bio->flags & ATA_SINGLE)
nblks = 1;
else
nblks = xfer->c_bcount / drvp->lp->d_secsize;
/* Check for bad sectors and adjust transfer, if necessary. */
if ((drvp->lp->d_flags & D_BADSECT) != 0) {
long blkdiff;
int i;
for (i = 0; (blkdiff = drvp->badsect[i]) != -1;
i++) {
blkdiff -= ata_bio->blkno;
if (blkdiff < 0)
continue;
if (blkdiff == 0)
/* Replace current block of transfer. */
ata_bio->blkno =
drvp->lp->d_secperunit -
drvp->lp->d_nsectors - i - 1;
if (blkdiff < nblks) {
/* Bad block inside transfer. */
ata_bio->flags |= ATA_SINGLE;
nblks = 1;
}
break;
}
/* Transfer is okay now. */
}
if (xfer->c_flags & C_DMA) {
enum mvsata_edmamode dmamode;
/* switch to appropriate dma mode if necessary */
dmamode = (xfer->c_flags & C_NCQ) ? ncq : dma;
if (mvport->port_edmamode_curr != dmamode)
mvsata_edma_config(mvport, dmamode);
if (xfer->c_flags & C_POLL)
sc->sc_enable_intr(mvport, 0 /*off*/);
error = mvsata_edma_enqueue(mvport, xfer);
if (error) {
if (error == EINVAL) {
/*
* We can't do DMA on this transfer
* for some reason. Fall back to
* PIO.
*/
xfer->c_flags &= ~C_DMA;
error = 0;
goto do_pio;
}
if (error == EBUSY) {
aprint_error_dev(atac->atac_dev,
"channel %d: EDMA Queue full\n",
chp->ch_channel);
/*
* XXX: Perhaps, after it waits for
* a while, it is necessary to call
* bio_start again.
*/
}
ata_bio->error = ERR_DMA;
ata_bio->r_error = 0;
return ATASTART_ABORT;
}
chp->ch_flags |= ATACH_DMA_WAIT;
/* wait for irq */
goto intr;
} /* else not DMA */
do_pio:
if (ata_bio->flags & ATA_LBA48) {
sect = 0;
cyl = 0;
head = 0;
} else if (ata_bio->flags & ATA_LBA) {
sect = (ata_bio->blkno >> 0) & 0xff;
cyl = (ata_bio->blkno >> 8) & 0xffff;
head = (ata_bio->blkno >> 24) & 0x0f;
head |= WDSD_LBA;
} else {
int blkno = ata_bio->blkno;
sect = blkno % drvp->lp->d_nsectors;
sect++; /* Sectors begin with 1, not 0. */
blkno /= drvp->lp->d_nsectors;
head = blkno % drvp->lp->d_ntracks;
blkno /= drvp->lp->d_ntracks;
cyl = blkno;
head |= WDSD_CHS;
}
ata_bio->nblks = uimin(nblks, drvp->multi);
ata_bio->nbytes = ata_bio->nblks * drvp->lp->d_secsize;
KASSERT(nblks == 1 || (ata_bio->flags & ATA_SINGLE) == 0);
if (ata_bio->nblks > 1)
cmd = (ata_bio->flags & ATA_READ) ?
WDCC_READMULTI : WDCC_WRITEMULTI;
else
cmd = (ata_bio->flags & ATA_READ) ?
WDCC_READ : WDCC_WRITE;
/* EDMA disable, if enabled this channel. */
KASSERT((chp->ch_flags & ATACH_NCQ) == 0);
if (mvport->port_edmamode_curr != nodma)
mvsata_edma_disable(mvport, 10 /* ms */, wait_flags);
mvsata_pmp_select(mvport, xfer->c_drive);
/* Do control operations specially. */
if (__predict_false(drvp->state < READY)) {
/*
* Actually, we want to be careful not to mess with
* the control state if the device is currently busy,
* but we can assume that we never get to this point
* if that's the case.
*/
/*
* If it's not a polled command, we need the kernel
* thread
*/
if ((xfer->c_flags & C_POLL) == 0
&& !ata_is_thread_run(chp))
return ATASTART_TH;
/* Wait for at last 400ns for status bit to be valid */
delay(1);
if (chp->ch_flags & ATACH_DMA_WAIT) {
mvsata_edma_wait(mvport, xfer, ATA_DELAY);
sc->sc_enable_intr(mvport, 1 /*on*/);
chp->ch_flags &= ~ATACH_DMA_WAIT;
}
/* Cleanup EDMA if invoked from wdctimeout()/ata_timeout() */
if (ISSET(xfer->c_flags, C_TIMEOU) && ISSET(xfer->c_flags, C_DMA)
&& !ISSET(xfer->c_flags, C_POLL)) {
mvsata_edma_rqq_remove((struct mvsata_port *)chp, xfer);
}
ata_channel_lock(chp);
chp->ch_flags &= ~(ATACH_DMA_WAIT);
/*
* If we missed an interrupt transfer, reset and restart.
* Don't try to continue transfer, we may have missed cycles.
*/
if (xfer->c_flags & C_TIMEOU) {
ata_bio->error = TIMEOUT;
ata_channel_unlock(chp);
mvsata_bio_done(chp, xfer);
return 1;
}
/* Is it not a transfer, but a control operation? */
if (!(xfer->c_flags & C_DMA) && drvp->state < READY) {
aprint_error_dev(atac->atac_dev,
"channel %d: drive %d bad state %d in %s\n",
chp->ch_channel, xfer->c_drive, drvp->state, __func__);
panic("%s: bad state", __func__);
}
/* Ack interrupt done by wdc_wait_for_unbusy */
if (!(xfer->c_flags & C_DMA) &&
(wdc_wait_for_unbusy(chp, (irq == 0) ? ATA_DELAY : 0, AT_POLL, &tfd)
== WDCWAIT_TOUT)) {
if (irq && (xfer->c_flags & C_TIMEOU) == 0) {
ata_channel_unlock(chp);
return 0; /* IRQ was not for us */
}
aprint_error_dev(atac->atac_dev,
"channel %d: drive %d timeout, c_bcount=%d, c_skip%d\n",
chp->ch_channel, xfer->c_drive, xfer->c_bcount,
xfer->c_skip);
ata_bio->error = TIMEOUT;
ata_channel_unlock(chp);
mvsata_bio_done(chp, xfer);
return 1;
}
if (xfer->c_flags & C_DMA) {
if (ata_bio->error == NOERROR)
goto end;
if (ata_bio->error == ERR_DMA) {
ata_dmaerr(drvp,
(xfer->c_flags & C_POLL) ? AT_POLL : 0);
ata_channel_unlock(chp);
goto err;
}
}
/* if we had an error, end */
if (ata_bio->error != NOERROR) {
ata_channel_unlock(chp);
err:
mvsata_bio_done(chp, xfer);
return 1;
}
/* If this was a read and not using DMA, fetch the data. */
if ((ata_bio->flags & ATA_READ) != 0) {
if ((ATACH_ST(tfd) & WDCS_DRQ) != WDCS_DRQ) {
aprint_error_dev(atac->atac_dev,
"channel %d: drive %d read intr before drq\n",
chp->ch_channel, xfer->c_drive);
ata_bio->error = TIMEOUT;
ata_channel_unlock(chp);
mvsata_bio_done(chp, xfer);
return 1;
}
wdc->datain_pio(chp, drvp->drive_flags,
(char *)xfer->c_databuf + xfer->c_skip, ata_bio->nbytes);
}
/* See if this transfer is complete. */
if (xfer->c_bcount > 0) {
if ((ata_bio->flags & ATA_POLL) == 0) {
/* Start the next operation */
ata_xfer_start(xfer);
} else {
/*
* Let ata_xfer_start() do the loop;
* see mvsata_bio_poll().
*/
}
ata_channel_unlock(chp);
} else { /* Done with this transfer */
ata_bio->error = NOERROR;
ata_channel_unlock(chp);
mvsata_bio_done(chp, xfer);
}
return 1;
}
static int
mvsata_wdc_cmd_poll(struct ata_channel *chp, struct ata_xfer *xfer)
{
/*
* Polled command. Wait for drive ready or drq. Done in intr().
* Wait for at last 400ns for status bit to be valid.
*/
delay(10); /* 400ns delay */
mvsata_wdc_cmd_intr(chp, xfer, 0);
return ATAPOLL_DONE;
}
static int
mvsata_wdc_cmd_intr(struct ata_channel *chp, struct ata_xfer *xfer, int irq)
{
struct mvsata_port *mvport = (struct mvsata_port *)chp;
struct wdc_softc *wdc = CHAN_TO_WDC(chp);
struct ata_command *ata_c = &xfer->c_ata_c;
int bcount = ata_c->bcount;
char *data = ata_c->data;
int wflags;
int drive_flags;
int tfd;
ata_channel_lock(chp);
if (ata_c->r_command == WDCC_IDENTIFY ||
ata_c->r_command == ATAPI_IDENTIFY_DEVICE)
/*
* The IDENTIFY data has been designed as an array of
* u_int16_t, so we can byteswap it on the fly.
* Historically it's what we have always done so keeping it
* here ensure binary backward compatibility.
*/
drive_flags = ATA_DRIVE_NOSTREAM |
chp->ch_drive[xfer->c_drive].drive_flags;
else
/*
* Other data structure are opaque and should be transferred
* as is.
*/
drive_flags = chp->ch_drive[xfer->c_drive].drive_flags;
if ((ata_c->flags & (AT_WAIT | AT_POLL)) == (AT_WAIT | AT_POLL))
/* both wait and poll, we can kpause here */
wflags = AT_WAIT | AT_POLL;
else
wflags = AT_POLL;
/*
* after a ATAPI_SOFT_RESET, the device will have released the bus.
* Reselect again, it doesn't hurt for others commands, and the time
* penalty for the extra register write is acceptable,
* wdc_exec_command() isn't called often (mostly for autoconfig)
*/
if ((xfer->c_flags & C_ATAPI) != 0) {
MVSATA_WDC_WRITE_1(mvport, SRB_H, WDSD_IBM);
}
if ((ata_c->flags & AT_XFDONE) != 0) {
/*
* We have completed a data xfer. The drive should now be
* in its initial state
*/
if (wdcwait(chp, ata_c->r_st_bmask | WDCS_DRQ,
ata_c->r_st_bmask, (irq == 0) ? ata_c->timeout : 0,
wflags, &tfd) == WDCWAIT_TOUT) {
if (irq && (xfer->c_flags & C_TIMEOU) == 0) {
ata_channel_unlock(chp);
return 0; /* IRQ was not for us */
}
ata_c->flags |= AT_TIMEOU;
}
goto out;
}
if (wdcwait(chp, ata_c->r_st_pmask, ata_c->r_st_pmask,
(irq == 0) ? ata_c->timeout : 0, wflags, &tfd) == WDCWAIT_TOUT) {
if (irq && (xfer->c_flags & C_TIMEOU) == 0) {
ata_channel_unlock(chp);
return 0; /* IRQ was not for us */
}
ata_c->flags |= AT_TIMEOU;
goto out;
}
delay(20); /* XXXXX: Delay more times. */
if (ata_c->flags & AT_READ) {
if ((ATACH_ST(tfd) & WDCS_DRQ) == 0) {
ata_c->flags |= AT_TIMEOU;
goto out;
}
wdc->datain_pio(chp, drive_flags, data, bcount);
/* at this point the drive should be in its initial state */
ata_c->flags |= AT_XFDONE;
/*
* XXX checking the status register again here cause some
* hardware to timeout.
*/
} else if (ata_c->flags & AT_WRITE) {
if ((ATACH_ST(tfd) & WDCS_DRQ) == 0) {
ata_c->flags |= AT_TIMEOU;
goto out;
}
wdc->dataout_pio(chp, drive_flags, data, bcount);
ata_c->flags |= AT_XFDONE;
if ((ata_c->flags & AT_POLL) == 0) {
callout_reset(&chp->c_timo_callout,
mstohz(ata_c->timeout), wdctimeout, chp);
ata_channel_unlock(chp);
return 1;
} else
goto again;
}
out:
if (ATACH_ST(tfd) & WDCS_DWF)
ata_c->flags |= AT_DF;
if (ATACH_ST(tfd) & WDCS_ERR) {
ata_c->flags |= AT_ERROR;
ata_c->r_error = ATACH_ERR(tfd);
}
ata_channel_unlock(chp);
mvsata_wdc_cmd_done(chp, xfer);
if ((ATACH_ST(tfd) & WDCS_ERR) == 0)
atastart(chp);
if (ata_c->flags & AT_POLL) {
/* enable interrupts */
MVSATA_WDC_WRITE_1(mvport, SRB_CAS, WDCTL_4BIT);
delay(10); /* some drives need a little delay here */
}
KASSERT((chp->ch_flags & ATACH_NCQ) == 0);
if (mvport->port_edmamode_curr != nodma)
mvsata_edma_disable(mvport, 10 /* ms */, wait_flags);
mvsata_pmp_select(mvport, xfer->c_drive);
if ((xfer->c_flags & C_DMA) && (drvp->n_xfers <= NXFER))
drvp->n_xfers++;
/* Do control operations specially. */
if (__predict_false(drvp->state < READY)) {
/* If it's not a polled command, we need the kernel thread */
if ((sc_xfer->xs_control & XS_CTL_POLL) == 0
&& !ata_is_thread_run(chp))
return ATASTART_TH;
/*
* disable interrupts, all commands here should be quick
* enough to be able to poll, and we don't go here that often
*/
MVSATA_WDC_WRITE_1(mvport, SRB_CAS, WDCTL_4BIT | WDCTL_IDS);
MVSATA_WDC_WRITE_1(mvport, SRB_H, WDSD_IBM);
/* Don't try to set mode if controller can't be adjusted */
if (atac->atac_set_modes == NULL)
goto ready;
/* Also don't try if the drive didn't report its mode */
if ((drvp->drive_flags & ATA_DRIVE_MODE) == 0)
goto ready;
errstring = "unbusy";
if (wdc_wait_for_unbusy(chp, ATAPI_DELAY, wait_flags, &tfd))
goto timeout;
wdccommand(chp, 0, SET_FEATURES, 0, 0, 0,
0x08 | drvp->PIO_mode, WDSF_SET_MODE);
errstring = "piomode-atapi";
if (wdc_wait_for_unbusy(chp, ATAPI_MODE_DELAY, wait_flags,
&tfd))
goto timeout;
if (ATACH_ST(tfd) & WDCS_ERR) {
if (ATACH_ERR(tfd) == WDCE_ABRT) {
/*
* Some ATAPI drives reject PIO settings.
* Fall back to PIO mode 3 since that's the
* minimum for ATAPI.
*/
aprint_error_dev(atac->atac_dev,
"channel %d drive %d: PIO mode %d rejected,"
" falling back to PIO mode 3\n",
chp->ch_channel, xfer->c_drive,
drvp->PIO_mode);
if (drvp->PIO_mode > 3)
drvp->PIO_mode = 3;
} else
goto error;
}
if (drvp->drive_flags & ATA_DRIVE_UDMA)
wdccommand(chp, 0, SET_FEATURES, 0, 0, 0,
0x40 | drvp->UDMA_mode, WDSF_SET_MODE);
else
if (drvp->drive_flags & ATA_DRIVE_DMA)
wdccommand(chp, 0, SET_FEATURES, 0, 0, 0,
0x20 | drvp->DMA_mode, WDSF_SET_MODE);
else
goto ready;
errstring = "dmamode-atapi";
if (wdc_wait_for_unbusy(chp, ATAPI_MODE_DELAY, wait_flags,
&tfd))
goto timeout;
if (ATACH_ST(tfd) & WDCS_ERR) {
if (ATACH_ERR(tfd) == WDCE_ABRT) {
if (drvp->drive_flags & ATA_DRIVE_UDMA)
goto error;
else {
/*
* The drive rejected our DMA setting.
* Fall back to mode 1.
*/
aprint_error_dev(atac->atac_dev,
"channel %d drive %d:"
" DMA mode %d rejected,"
" falling back to DMA mode 0\n",
chp->ch_channel, xfer->c_drive,
drvp->DMA_mode);
if (drvp->DMA_mode > 0)
drvp->DMA_mode = 0;
}
} else
goto error;
}
ready:
drvp->state = READY;
MVSATA_WDC_WRITE_1(mvport, SRB_CAS, WDCTL_4BIT);
delay(10); /* some drives need a little delay here */
}
MVSATA_WDC_WRITE_1(mvport, SRB_H, WDSD_IBM);
if (wdc_wait_for_unbusy(chp, ATAPI_DELAY, wait_flags, &tfd) != 0) {
aprint_error_dev(atac->atac_dev, "not ready, st = %02x\n",
ATACH_ST(tfd));
sc_xfer->error = XS_TIMEOUT;
return ATASTART_ABORT;
}
/*
* Even with WDCS_ERR, the device should accept a command packet
* Limit length to what can be stuffed into the cylinder register
* (16 bits). Some CD-ROMs seem to interpret '0' as 65536,
* but not all devices do that and it's not obvious from the
* ATAPI spec that that behaviour should be expected. If more
* data is necessary, multiple data transfer phases will be done.
*/
/*
* If there is no interrupt for CMD input, busy-wait for it (done in
* the interrupt routine. Poll routine will exit early in this case.
*/
if ((sc_xfer->xs_periph->periph_cap & ATAPI_CFG_DRQ_MASK) !=
ATAPI_CFG_IRQ_DRQ || (sc_xfer->xs_control & XS_CTL_POLL))
return ATASTART_POLL;
else
return ATASTART_STARTED;
timeout:
aprint_error_dev(atac->atac_dev, "channel %d drive %d: %s timed out\n",
chp->ch_channel, xfer->c_drive, errstring);
sc_xfer->error = XS_TIMEOUT;
MVSATA_WDC_WRITE_1(mvport, SRB_CAS, WDCTL_4BIT);
delay(10); /* some drives need a little delay here */
return ATASTART_ABORT;
error:
aprint_error_dev(atac->atac_dev,
"channel %d drive %d: %s error (0x%x)\n",
chp->ch_channel, xfer->c_drive, errstring, ATACH_ERR(tfd));
sc_xfer->error = XS_SHORTSENSE;
sc_xfer->sense.atapi_sense = ATACH_ERR(tfd);
MVSATA_WDC_WRITE_1(mvport, SRB_CAS, WDCTL_4BIT);
delay(10); /* some drives need a little delay here */
return ATASTART_ABORT;
}
static int
mvsata_atapi_poll(struct ata_channel *chp, struct ata_xfer *xfer)
{
/*
* If there is no interrupt for CMD input, busy-wait for it (done in
* the interrupt routine. If it is a polled command, call the interrupt
* routine until command is done.
*/
const bool poll = ((xfer->c_scsipi->xs_control & XS_CTL_POLL) != 0);
/* Wait for at last 400ns for status bit to be valid */
DELAY(1);
mvsata_atapi_intr(chp, xfer, 0);
while ((xfer->c_scsipi->xs_status & XS_STS_DONE) == 0) {
/* Wait for at last 400ns for status bit to be valid */
DELAY(1);
mvsata_atapi_intr(chp, xfer, 0);
}
/* Is it not a transfer, but a control operation? */
if (drvp->state < READY) {
aprint_error_dev(atac->atac_dev,
"channel %d drive %d: bad state %d\n",
chp->ch_channel, xfer->c_drive, drvp->state);
panic("mvsata_atapi_intr: bad state");
}
/*
* If we missed an interrupt in a PIO transfer, reset and restart.
* Don't try to continue transfer, we may have missed cycles.
*/
if ((xfer->c_flags & (C_TIMEOU | C_DMA)) == C_TIMEOU) {
ata_channel_unlock(chp);
sc_xfer->error = XS_TIMEOUT;
mvsata_atapi_reset(chp, xfer);
return 1;
}
/* Ack interrupt done in wdc_wait_for_unbusy */
MVSATA_WDC_WRITE_1(mvport, SRB_H, WDSD_IBM);
if (wdc_wait_for_unbusy(chp,
(irq == 0) ? sc_xfer->timeout : 0, AT_POLL, &tfd) == WDCWAIT_TOUT) {
if (irq && (xfer->c_flags & C_TIMEOU) == 0) {
ata_channel_unlock(chp);
return 0; /* IRQ was not for us */
}
aprint_error_dev(atac->atac_dev,
"channel %d: device timeout, c_bcount=%d, c_skip=%d\n",
chp->ch_channel, xfer->c_bcount, xfer->c_skip);
if (xfer->c_flags & C_DMA)
ata_dmaerr(drvp,
(xfer->c_flags & C_POLL) ? AT_POLL : 0);
sc_xfer->error = XS_TIMEOUT;
ata_channel_unlock(chp);
mvsata_atapi_reset(chp, xfer);
return 1;
}
/*
* If we missed an IRQ and were using DMA, flag it as a DMA error
* and reset device.
*/
if ((xfer->c_flags & C_TIMEOU) && (xfer->c_flags & C_DMA)) {
ata_dmaerr(drvp, (xfer->c_flags & C_POLL) ? AT_POLL : 0);
sc_xfer->error = XS_RESET;
ata_channel_unlock(chp);
mvsata_atapi_reset(chp, xfer);
return (1);
}
/*
* if the request sense command was aborted, report the short sense
* previously recorded, else continue normal processing
*/
switch (phase) {
case PHASE_CMDOUT:
cmd = sc_xfer->cmd;
DPRINTF(DEBUG_FUNCS|DEBUG_XFERS, ("PHASE_CMDOUT\n"));
/* Init the DMA channel if necessary */
if (xfer->c_flags & C_DMA) {
error = mvsata_bdma_init(mvport, xfer);
if (error) {
if (error == EINVAL) {
/*
* We can't do DMA on this transfer
* for some reason. Fall back to PIO.
*/
xfer->c_flags &= ~C_DMA;
error = 0;
} else {
sc_xfer->error = XS_DRIVER_STUFFUP;
break;
}
}
}
case PHASE_ABORTED:
case PHASE_COMPLETED:
DPRINTF(DEBUG_XFERS, ("PHASE_COMPLETED\n"));
if (xfer->c_flags & C_DMA)
xfer->c_bcount -= sc_xfer->datalen;
sc_xfer->resid = xfer->c_bcount;
/* this will unlock channel lock too */
mvsata_atapi_phase_complete(xfer, tfd);
return 1;
/* wait for DSC if needed */
if (drvp->drive_flags & ATA_DRIVE_ATAPIDSCW) {
DPRINTF(DEBUG_XFERS,
("%s:%d:%d: mvsata_atapi_phase_complete: polldsc %d\n",
device_xname(atac->atac_dev), chp->ch_channel,
xfer->c_drive, xfer->c_atapi.c_dscpoll));
if (cold)
panic("mvsata_atapi_phase_complete: cold");
if (wdcwait(chp, WDCS_DSC, WDCS_DSC, 10, AT_POLL, &tfd) ==
WDCWAIT_TOUT) {
/* 10ms not enough, try again in 1 tick */
if (xfer->c_atapi.c_dscpoll++ >
mstohz(sc_xfer->timeout)) {
aprint_error_dev(atac->atac_dev,
"channel %d: wait_for_dsc failed\n",
chp->ch_channel);
ata_channel_unlock(chp);
sc_xfer->error = XS_TIMEOUT;
mvsata_atapi_reset(chp, xfer);
} else {
callout_reset(&chp->c_timo_callout, 1,
mvsata_atapi_polldsc, chp);
ata_channel_unlock(chp);
}
return;
}
}
/*
* Some drive occasionally set WDCS_ERR with
* "ATA illegal length indication" in the error
* register. If we read some data the sense is valid
* anyway, so don't report the error.
*/
if (ATACH_ST(tfd) & WDCS_ERR &&
((sc_xfer->xs_control & XS_CTL_REQSENSE) == 0 ||
sc_xfer->resid == sc_xfer->datalen)) {
/* save the short sense */
sc_xfer->error = XS_SHORTSENSE;
sc_xfer->sense.atapi_sense = ATACH_ERR(tfd);
if ((sc_xfer->xs_periph->periph_quirks & PQUIRK_NOSENSE) == 0) {
/* ask scsipi to send a REQUEST_SENSE */
sc_xfer->error = XS_BUSY;
sc_xfer->status = SCSI_CHECK;
} else
if (wdc->dma_status & (WDC_DMAST_NOIRQ | WDC_DMAST_ERR)) {
ata_dmaerr(drvp,
(xfer->c_flags & C_POLL) ? AT_POLL : 0);
sc_xfer->error = XS_RESET;
ata_channel_unlock(chp);
mvsata_atapi_reset(chp, xfer);
return;
}
}
if (xfer->c_bcount != 0) {
DPRINTF(DEBUG_XFERS, ("%s:%d:%d: mvsata_atapi_intr:"
" bcount value is %d after io\n",
device_xname(atac->atac_dev), chp->ch_channel,
xfer->c_drive, xfer->c_bcount));
}
#ifdef DIAGNOSTIC
if (xfer->c_bcount < 0) {
aprint_error_dev(atac->atac_dev,
"channel %d drive %d: mvsata_atapi_intr:"
" warning: bcount value is %d after io\n",
chp->ch_channel, xfer->c_drive, xfer->c_bcount);
}
#endif
/* this will unlock channel lock too */
mvsata_atapi_phase_complete(xfer, 0);
}
#endif /* NATAPIBUS > 0 */
/*
* XXXX: Shall we need lock for race condition in mvsata_edma_enqueue{,_gen2}(),
* if supported queuing command by atabus? The race condition will not happen
* if this is called only to the thread of atabus.
*/
static int
mvsata_edma_enqueue(struct mvsata_port *mvport, struct ata_xfer *xfer)
{
struct mvsata_softc *sc = device_private(MVSATA_DEV2(mvport));
struct ata_bio *ata_bio = &xfer->c_bio;
void *databuf = (uint8_t *)xfer->c_databuf + xfer->c_skip;
struct eprd *eprd;
bus_addr_t crqb_base_addr;
bus_dmamap_t data_dmamap;
uint32_t reg;
int erqqip, erqqop, next, rv, i;
for (i = 0, erqqip = 0; i < MVSATA_EDMAQ_LEN; i++) {
struct ata_xfer *rqxfer;
if ((aslots & __BIT(i)) == 0)
continue;
if (i == xfer->c_slot) {
/* remove xfer from EDMA request queue */
bus_dmamap_sync(mvport->port_dmat,
mvport->port_eprd_dmamap,
mvport->port_reqtbl[i].eprd_offset,
MVSATA_EPRD_MAX_SIZE, BUS_DMASYNC_POSTWRITE);
mvsata_dma_bufunload(mvport, i, xfer->c_bio.flags);
/* quetag freed by caller later */
continue;
}
/*
* Keep the SS during power on and the reference clock bits (reset
* sample)
*/
val = MVSATA_HC_READ_4(mvhc, 0x020);
val &= 0x1c1c1c1c;
val |= 0x03030303;
MVSATA_HC_READ_4(mvhc, 0x020, 0);
#endif
}
if (mode == ncq)
reg |= EDMA_IE_EDEVERR;
MVSATA_EDMA_WRITE_4(mvport, EDMA_IEM, reg);
reg = MVSATA_EDMA_READ_4(mvport, EDMA_HC);
reg &= ~EDMA_IE_EDEVERR;
if (mode != ncq)
reg |= EDMA_IE_EDEVERR;
MVSATA_EDMA_WRITE_4(mvport, EDMA_HC, reg);
if (sc->sc_gen == gen2e) {
/*
* Clear FISWait4HostRdyEn[0] and [2].
* [0]: Device to Host FIS with <ERR> or <DF> bit set to 1.
* [2]: SDB FIS is received with <ERR> bit set to 1.
*/
reg = MVSATA_EDMA_READ_4(mvport, SATA_FISC);
reg &= ~(SATA_FISC_FISWAIT4HOSTRDYEN_B0 |
SATA_FISC_FISWAIT4HOSTRDYEN_B2);
MVSATA_EDMA_WRITE_4(mvport, SATA_FISC, reg);
}
/* Revert values of pre-emphasis and signal amps to the saved ones */
reg = MVSATA_HC_READ_4(mvhc, SATAHC_I_PHYMODE(port));
reg &= ~0x000018e0; /* pre and amps mask */
reg |= mvport->_fix_phy_param.pre_amps;
MVSATA_HC_WRITE_4(mvhc, SATAHC_I_PHYMODE(port), reg);
}
/* 88SX60x1 FEr SATA #13 */
if (sc->sc_gen == 2 && sc->sc_rev == 0x07)
tmp = MVSATA_EDMA_READ_4(mvport, SATA_PHYM3);
reg = MVSATA_EDMA_READ_4(mvport, SATA_PHYM4);
reg |= (1 << 0);
reg &= ~(1 << 1);
/* PHY Mode 4 Register of Gen IIE has some restriction */
if (sc->sc_gen == gen2e) {
reg &= ~0x5de3fffc;
reg |= (1 << 2);
}
MVSATA_EDMA_WRITE_4(mvport, SATA_PHYM4, reg);
/* 88SX60x1 FEr SATA #13 */
if (sc->sc_gen == 2 && sc->sc_rev == 0x07)
MVSATA_EDMA_WRITE_4(mvport, SATA_PHYM3, tmp);
}
/* Revert values of pre-emphasis and signal amps to the saved ones */
reg = MVSATA_EDMA_READ_4(mvport, SATA_PHYM2);
reg &= ~0x000007e0; /* pre and amps mask */
reg |= mvport->_fix_phy_param.pre_amps;
reg &= ~(1 << 16);
if (sc->sc_gen == gen2e) {
/*
* according to mvSata 3.6.1, some IIE values are fixed.
* some reserved fields must be written with fixed values.
*/
reg &= ~0xC30FF01F;
reg |= 0x0000900F;
}
MVSATA_EDMA_WRITE_4(mvport, SATA_PHYM2, reg);
}
crqb->atacommand[0] = 0;
crqb->atacommand[1] = 0;
/* copy over the ATA command part of the fis */
memcpy(&crqb->atacommand[2], &fis[rhd_command],
MIN(sizeof(crqb->atacommand) - 2, RHD_FISLEN - rhd_command));
}
#ifdef MVSATA_DEBUG
#define MVSATA_DEBUG_PRINT(type, size, n, p) \
do { \
int _i; \
u_char *_p = (p); \
\
printf(#type "(%d)", (n)); \
for (_i = 0; _i < (size); _i++, _p++) { \
if (_i % 16 == 0) \
printf("\n "); \
printf(" %02x", *_p); \
} \
printf("\n"); \
} while (0 /* CONSTCOND */)
static void
mvsata_print_crqb(struct mvsata_port *mvport, int n)
{
MVSATA_DEBUG_PRINT(crqb, sizeof(union mvsata_crqb),
n, (u_char *)(mvport->port_crqb + n));
}
static void
mvsata_print_crpb(struct mvsata_port *mvport, int n)
{
MVSATA_DEBUG_PRINT(crpb, sizeof(struct crpb),
n, (u_char *)(mvport->port_crpb + n));
}
static void
mvsata_print_eprd(struct mvsata_port *mvport, int n)
{
struct eprd *eprd;
int i = 0;
eprd = mvport->port_reqtbl[n].eprd;
while (1 /*CONSTCOND*/) {
MVSATA_DEBUG_PRINT(eprd, sizeof(struct eprd),
i, (u_char *)eprd);
if (eprd->eot & EPRD_EOT)
break;
eprd++;
i++;
}
}
#endif
#endif