freebsd-skq/sys/dev/ata/chipsets/ata-ahci.c

795 lines
25 KiB
C
Raw Normal View History

This is the roumored ATA modulerisation works, and it needs a little explanation. If you just config KERNEL as usual there should be no apparent changes, you'll get all chipset support code compiled in. However there is now a way to only compile in code for chipsets needed on a pr vendor basis. ATA now has the following "device" entries: atacore: ATA core functionality, always needed for any ATA setup atacard: CARDBUS support atacbus: PC98 cbus support ataisa: ISA bus support atapci: PCI bus support only generic chipset support. ataahci: AHCI support, also pulled in by some vendor modules. ataacard, ataacerlabs, ataadaptec, ataamd, ataati, atacenatek, atacypress, atacyrix, atahighpoint, ataintel, ataite, atajmicron, atamarvell, atamicron, atanational, atanetcell, atanvidia, atapromise, ataserverworks, atasiliconimage, atasis, atavia; Vendor support, ie atavia for VIA chipsets atadisk: ATA disk driver ataraid: ATA softraid driver atapicd: ATAPI cd/dvd driver atapifd: ATAPI floppy/flashdisk driver atapist: ATAPI tape driver atausb: ATA<>USB bridge atapicam: ATA<>CAM bridge This makes it possible to config a kernel with just VIA chipset support by having the following ATA lines in the kernel config file: device atacore device atapci device atavia And then you need the atadisk, atapicd etc lines in there just as usual. If you use ATA as modules loaded at boot there is few changes except the rename of the "ata" module to "atacore", things looks just as usual. However under atapci you now have a whole bunch of vendor specific drivers, that you can kldload individually depending on you needs. Drivers have the same names as used in the kernel config explained above.
2008-10-09 12:56:57 +00:00
/*-
* Copyright (c) 1998 - 2008 S<EFBFBD>ren Schmidt <sos@FreeBSD.org>
* 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,
* without modification, immediately at the beginning of the file.
* 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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_ata.h"
#include <sys/param.h>
#include <sys/module.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/ata.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/malloc.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/sema.h>
#include <sys/taskqueue.h>
#include <vm/uma.h>
#include <machine/stdarg.h>
#include <machine/resource.h>
#include <machine/bus.h>
#include <sys/rman.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/ata/ata-all.h>
#include <dev/ata/ata-pci.h>
#include <ata_if.h>
/* local prototypes */
static int ata_ahci_ctlr_reset(device_t dev);
static int ata_ahci_suspend(device_t dev);
static int ata_ahci_status(device_t dev);
static int ata_ahci_begin_transaction(struct ata_request *request);
static int ata_ahci_end_transaction(struct ata_request *request);
static int ata_ahci_pm_read(device_t dev, int port, int reg, u_int32_t *result);
static int ata_ahci_pm_write(device_t dev, int port, int reg, u_int32_t result);
static u_int32_t ata_ahci_softreset(device_t dev, int port);
static void ata_ahci_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error);
static int ata_ahci_setup_fis(struct ata_ahci_cmd_tab *ctp, struct ata_request *equest);
/*
* AHCI v1.x compliant SATA chipset support functions
*/
static int
ata_ahci_probe(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(dev);
char buffer[64];
/* is this a possible AHCI candidate ? */
if (pci_get_class(dev) != PCIC_STORAGE ||
pci_get_subclass(dev) != PCIS_STORAGE_SATA)
return (ENXIO);
This is the roumored ATA modulerisation works, and it needs a little explanation. If you just config KERNEL as usual there should be no apparent changes, you'll get all chipset support code compiled in. However there is now a way to only compile in code for chipsets needed on a pr vendor basis. ATA now has the following "device" entries: atacore: ATA core functionality, always needed for any ATA setup atacard: CARDBUS support atacbus: PC98 cbus support ataisa: ISA bus support atapci: PCI bus support only generic chipset support. ataahci: AHCI support, also pulled in by some vendor modules. ataacard, ataacerlabs, ataadaptec, ataamd, ataati, atacenatek, atacypress, atacyrix, atahighpoint, ataintel, ataite, atajmicron, atamarvell, atamicron, atanational, atanetcell, atanvidia, atapromise, ataserverworks, atasiliconimage, atasis, atavia; Vendor support, ie atavia for VIA chipsets atadisk: ATA disk driver ataraid: ATA softraid driver atapicd: ATAPI cd/dvd driver atapifd: ATAPI floppy/flashdisk driver atapist: ATAPI tape driver atausb: ATA<>USB bridge atapicam: ATA<>CAM bridge This makes it possible to config a kernel with just VIA chipset support by having the following ATA lines in the kernel config file: device atacore device atapci device atavia And then you need the atadisk, atapicd etc lines in there just as usual. If you use ATA as modules loaded at boot there is few changes except the rename of the "ata" module to "atacore", things looks just as usual. However under atapci you now have a whole bunch of vendor specific drivers, that you can kldload individually depending on you needs. Drivers have the same names as used in the kernel config explained above.
2008-10-09 12:56:57 +00:00
/* is this PCI device flagged as an AHCI compliant chip ? */
if (pci_read_config(dev, PCIR_PROGIF, 1) != PCIP_STORAGE_SATA_AHCI_1_0)
return ENXIO;
if (bootverbose)
sprintf(buffer, "%s (ID=%08x) AHCI controller",
ata_pcivendor2str(dev), pci_get_devid(dev));
else
sprintf(buffer, "%s AHCI controller", ata_pcivendor2str(dev));
device_set_desc_copy(dev, buffer);
ctlr->chipinit = ata_ahci_chipinit;
return 0;
}
int
ata_ahci_chipinit(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(dev);
int error;
This is the roumored ATA modulerisation works, and it needs a little explanation. If you just config KERNEL as usual there should be no apparent changes, you'll get all chipset support code compiled in. However there is now a way to only compile in code for chipsets needed on a pr vendor basis. ATA now has the following "device" entries: atacore: ATA core functionality, always needed for any ATA setup atacard: CARDBUS support atacbus: PC98 cbus support ataisa: ISA bus support atapci: PCI bus support only generic chipset support. ataahci: AHCI support, also pulled in by some vendor modules. ataacard, ataacerlabs, ataadaptec, ataamd, ataati, atacenatek, atacypress, atacyrix, atahighpoint, ataintel, ataite, atajmicron, atamarvell, atamicron, atanational, atanetcell, atanvidia, atapromise, ataserverworks, atasiliconimage, atasis, atavia; Vendor support, ie atavia for VIA chipsets atadisk: ATA disk driver ataraid: ATA softraid driver atapicd: ATAPI cd/dvd driver atapifd: ATAPI floppy/flashdisk driver atapist: ATAPI tape driver atausb: ATA<>USB bridge atapicam: ATA<>CAM bridge This makes it possible to config a kernel with just VIA chipset support by having the following ATA lines in the kernel config file: device atacore device atapci device atavia And then you need the atadisk, atapicd etc lines in there just as usual. If you use ATA as modules loaded at boot there is few changes except the rename of the "ata" module to "atacore", things looks just as usual. However under atapci you now have a whole bunch of vendor specific drivers, that you can kldload individually depending on you needs. Drivers have the same names as used in the kernel config explained above.
2008-10-09 12:56:57 +00:00
u_int32_t version;
/* if we have a memory BAR(5) we are likely on an AHCI part */
ctlr->r_type2 = SYS_RES_MEMORY;
ctlr->r_rid2 = PCIR_BAR(5);
if (!(ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2,
&ctlr->r_rid2, RF_ACTIVE)))
return ENXIO;
/* setup interrupt delivery if not done allready by a vendor driver */
if (!ctlr->r_irq) {
if (ata_setup_interrupt(dev, ata_generic_intr)) {
bus_release_resource(dev, ctlr->r_type2, ctlr->r_rid2, ctlr->r_res2);
This is the roumored ATA modulerisation works, and it needs a little explanation. If you just config KERNEL as usual there should be no apparent changes, you'll get all chipset support code compiled in. However there is now a way to only compile in code for chipsets needed on a pr vendor basis. ATA now has the following "device" entries: atacore: ATA core functionality, always needed for any ATA setup atacard: CARDBUS support atacbus: PC98 cbus support ataisa: ISA bus support atapci: PCI bus support only generic chipset support. ataahci: AHCI support, also pulled in by some vendor modules. ataacard, ataacerlabs, ataadaptec, ataamd, ataati, atacenatek, atacypress, atacyrix, atahighpoint, ataintel, ataite, atajmicron, atamarvell, atamicron, atanational, atanetcell, atanvidia, atapromise, ataserverworks, atasiliconimage, atasis, atavia; Vendor support, ie atavia for VIA chipsets atadisk: ATA disk driver ataraid: ATA softraid driver atapicd: ATAPI cd/dvd driver atapifd: ATAPI floppy/flashdisk driver atapist: ATAPI tape driver atausb: ATA<>USB bridge atapicam: ATA<>CAM bridge This makes it possible to config a kernel with just VIA chipset support by having the following ATA lines in the kernel config file: device atacore device atapci device atavia And then you need the atadisk, atapicd etc lines in there just as usual. If you use ATA as modules loaded at boot there is few changes except the rename of the "ata" module to "atacore", things looks just as usual. However under atapci you now have a whole bunch of vendor specific drivers, that you can kldload individually depending on you needs. Drivers have the same names as used in the kernel config explained above.
2008-10-09 12:56:57 +00:00
return ENXIO;
}
This is the roumored ATA modulerisation works, and it needs a little explanation. If you just config KERNEL as usual there should be no apparent changes, you'll get all chipset support code compiled in. However there is now a way to only compile in code for chipsets needed on a pr vendor basis. ATA now has the following "device" entries: atacore: ATA core functionality, always needed for any ATA setup atacard: CARDBUS support atacbus: PC98 cbus support ataisa: ISA bus support atapci: PCI bus support only generic chipset support. ataahci: AHCI support, also pulled in by some vendor modules. ataacard, ataacerlabs, ataadaptec, ataamd, ataati, atacenatek, atacypress, atacyrix, atahighpoint, ataintel, ataite, atajmicron, atamarvell, atamicron, atanational, atanetcell, atanvidia, atapromise, ataserverworks, atasiliconimage, atasis, atavia; Vendor support, ie atavia for VIA chipsets atadisk: ATA disk driver ataraid: ATA softraid driver atapicd: ATAPI cd/dvd driver atapifd: ATAPI floppy/flashdisk driver atapist: ATAPI tape driver atausb: ATA<>USB bridge atapicam: ATA<>CAM bridge This makes it possible to config a kernel with just VIA chipset support by having the following ATA lines in the kernel config file: device atacore device atapci device atavia And then you need the atadisk, atapicd etc lines in there just as usual. If you use ATA as modules loaded at boot there is few changes except the rename of the "ata" module to "atacore", things looks just as usual. However under atapci you now have a whole bunch of vendor specific drivers, that you can kldload individually depending on you needs. Drivers have the same names as used in the kernel config explained above.
2008-10-09 12:56:57 +00:00
}
else
device_printf(dev, "AHCI called from vendor specific driver\n");
/* reset controller */
if ((error = ata_ahci_ctlr_reset(dev)) != 0) {
bus_release_resource(dev, ctlr->r_type2, ctlr->r_rid2, ctlr->r_res2);
return (error);
};
This is the roumored ATA modulerisation works, and it needs a little explanation. If you just config KERNEL as usual there should be no apparent changes, you'll get all chipset support code compiled in. However there is now a way to only compile in code for chipsets needed on a pr vendor basis. ATA now has the following "device" entries: atacore: ATA core functionality, always needed for any ATA setup atacard: CARDBUS support atacbus: PC98 cbus support ataisa: ISA bus support atapci: PCI bus support only generic chipset support. ataahci: AHCI support, also pulled in by some vendor modules. ataacard, ataacerlabs, ataadaptec, ataamd, ataati, atacenatek, atacypress, atacyrix, atahighpoint, ataintel, ataite, atajmicron, atamarvell, atamicron, atanational, atanetcell, atanvidia, atapromise, ataserverworks, atasiliconimage, atasis, atavia; Vendor support, ie atavia for VIA chipsets atadisk: ATA disk driver ataraid: ATA softraid driver atapicd: ATAPI cd/dvd driver atapifd: ATAPI floppy/flashdisk driver atapist: ATAPI tape driver atausb: ATA<>USB bridge atapicam: ATA<>CAM bridge This makes it possible to config a kernel with just VIA chipset support by having the following ATA lines in the kernel config file: device atacore device atapci device atavia And then you need the atadisk, atapicd etc lines in there just as usual. If you use ATA as modules loaded at boot there is few changes except the rename of the "ata" module to "atacore", things looks just as usual. However under atapci you now have a whole bunch of vendor specific drivers, that you can kldload individually depending on you needs. Drivers have the same names as used in the kernel config explained above.
2008-10-09 12:56:57 +00:00
/* get the number of HW channels */
ctlr->channels =
MAX(flsl(ATA_INL(ctlr->r_res2, ATA_AHCI_PI)),
(ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_NPMASK) + 1);
ctlr->reset = ata_ahci_reset;
ctlr->dmainit = ata_ahci_dmainit;
ctlr->allocate = ata_ahci_allocate;
ctlr->setmode = ata_sata_setmode;
ctlr->suspend = ata_ahci_suspend;
ctlr->resume = ata_ahci_ctlr_reset;
/* enable PCI interrupt */
pci_write_config(dev, PCIR_COMMAND,
pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400, 2);
/* announce we support the HW */
version = ATA_INL(ctlr->r_res2, ATA_AHCI_VS);
device_printf(dev,
"AHCI Version %x%x.%x%x controller with %d ports PM %s\n",
(version >> 24) & 0xff, (version >> 16) & 0xff,
(version >> 8) & 0xff, version & 0xff,
(ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_NPMASK) + 1,
(ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_SPM) ?
"supported" : "not supported");
return 0;
}
static int
ata_ahci_ctlr_reset(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(dev);
int timeout;
This is the roumored ATA modulerisation works, and it needs a little explanation. If you just config KERNEL as usual there should be no apparent changes, you'll get all chipset support code compiled in. However there is now a way to only compile in code for chipsets needed on a pr vendor basis. ATA now has the following "device" entries: atacore: ATA core functionality, always needed for any ATA setup atacard: CARDBUS support atacbus: PC98 cbus support ataisa: ISA bus support atapci: PCI bus support only generic chipset support. ataahci: AHCI support, also pulled in by some vendor modules. ataacard, ataacerlabs, ataadaptec, ataamd, ataati, atacenatek, atacypress, atacyrix, atahighpoint, ataintel, ataite, atajmicron, atamarvell, atamicron, atanational, atanetcell, atanvidia, atapromise, ataserverworks, atasiliconimage, atasis, atavia; Vendor support, ie atavia for VIA chipsets atadisk: ATA disk driver ataraid: ATA softraid driver atapicd: ATAPI cd/dvd driver atapifd: ATAPI floppy/flashdisk driver atapist: ATAPI tape driver atausb: ATA<>USB bridge atapicam: ATA<>CAM bridge This makes it possible to config a kernel with just VIA chipset support by having the following ATA lines in the kernel config file: device atacore device atapci device atavia And then you need the atadisk, atapicd etc lines in there just as usual. If you use ATA as modules loaded at boot there is few changes except the rename of the "ata" module to "atacore", things looks just as usual. However under atapci you now have a whole bunch of vendor specific drivers, that you can kldload individually depending on you needs. Drivers have the same names as used in the kernel config explained above.
2008-10-09 12:56:57 +00:00
/* enable AHCI mode */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, ATA_AHCI_GHC_AE);
/* reset AHCI controller */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, ATA_AHCI_GHC_AE|ATA_AHCI_GHC_HR);
for (timeout = 1000; timeout > 0; timeout--) {
DELAY(1000);
if ((ATA_INL(ctlr->r_res2, ATA_AHCI_GHC) & ATA_AHCI_GHC_HR) == 0)
break;
}
if (timeout == 0) {
This is the roumored ATA modulerisation works, and it needs a little explanation. If you just config KERNEL as usual there should be no apparent changes, you'll get all chipset support code compiled in. However there is now a way to only compile in code for chipsets needed on a pr vendor basis. ATA now has the following "device" entries: atacore: ATA core functionality, always needed for any ATA setup atacard: CARDBUS support atacbus: PC98 cbus support ataisa: ISA bus support atapci: PCI bus support only generic chipset support. ataahci: AHCI support, also pulled in by some vendor modules. ataacard, ataacerlabs, ataadaptec, ataamd, ataati, atacenatek, atacypress, atacyrix, atahighpoint, ataintel, ataite, atajmicron, atamarvell, atamicron, atanational, atanetcell, atanvidia, atapromise, ataserverworks, atasiliconimage, atasis, atavia; Vendor support, ie atavia for VIA chipsets atadisk: ATA disk driver ataraid: ATA softraid driver atapicd: ATAPI cd/dvd driver atapifd: ATAPI floppy/flashdisk driver atapist: ATAPI tape driver atausb: ATA<>USB bridge atapicam: ATA<>CAM bridge This makes it possible to config a kernel with just VIA chipset support by having the following ATA lines in the kernel config file: device atacore device atapci device atavia And then you need the atadisk, atapicd etc lines in there just as usual. If you use ATA as modules loaded at boot there is few changes except the rename of the "ata" module to "atacore", things looks just as usual. However under atapci you now have a whole bunch of vendor specific drivers, that you can kldload individually depending on you needs. Drivers have the same names as used in the kernel config explained above.
2008-10-09 12:56:57 +00:00
device_printf(dev, "AHCI controller reset failure\n");
return ENXIO;
}
/* reenable AHCI mode */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, ATA_AHCI_GHC_AE);
/* clear interrupts */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_IS, ATA_INL(ctlr->r_res2, ATA_AHCI_IS));
/* enable AHCI interrupts */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC,
ATA_INL(ctlr->r_res2, ATA_AHCI_GHC) | ATA_AHCI_GHC_IE);
return 0;
}
static int
ata_ahci_suspend(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(dev);
/* disable interupts so the state change(s) doesn't trigger */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC,
ATA_INL(ctlr->r_res2, ATA_AHCI_GHC) & (~ATA_AHCI_GHC_IE));
return 0;
}
int
ata_ahci_allocate(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
int offset = ch->unit << 7;
/* set the SATA resources */
ch->r_io[ATA_SSTATUS].res = ctlr->r_res2;
ch->r_io[ATA_SSTATUS].offset = ATA_AHCI_P_SSTS + offset;
ch->r_io[ATA_SERROR].res = ctlr->r_res2;
ch->r_io[ATA_SERROR].offset = ATA_AHCI_P_SERR + offset;
ch->r_io[ATA_SCONTROL].res = ctlr->r_res2;
ch->r_io[ATA_SCONTROL].offset = ATA_AHCI_P_SCTL + offset;
ch->r_io[ATA_SACTIVE].res = ctlr->r_res2;
ch->r_io[ATA_SACTIVE].offset = ATA_AHCI_P_SACT + offset;
ch->hw.status = ata_ahci_status;
ch->hw.begin_transaction = ata_ahci_begin_transaction;
ch->hw.end_transaction = ata_ahci_end_transaction;
ch->hw.command = NULL; /* not used here */
ch->hw.softreset = ata_ahci_softreset;
ch->hw.pm_read = ata_ahci_pm_read;
ch->hw.pm_write = ata_ahci_pm_write;
return 0;
}
static int
ata_ahci_status(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
u_int32_t action = ATA_INL(ctlr->r_res2, ATA_AHCI_IS);
int offset = ch->unit << 7;
#define ATA_AHCI_STATBITS \
(ATA_AHCI_P_IX_IF|ATA_AHCI_P_IX_HBD|ATA_AHCI_P_IX_HBF|ATA_AHCI_P_IX_TFE)
if (action & (1 << ch->unit)) {
u_int32_t istatus = ATA_INL(ctlr->r_res2, ATA_AHCI_P_IS + offset);
u_int32_t cstatus = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CI + offset);
/* clear interrupt(s) */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IS + offset, istatus);
ATA_OUTL(ctlr->r_res2, ATA_AHCI_IS, action & (1 << ch->unit));
/* do we have any PHY events ? */
if (istatus & (ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC))
ata_sata_phy_check_events(dev);
/* do we have a potentially hanging engine to take care of? */
/* XXX SOS what todo on NCQ */
if ((istatus & ATA_AHCI_STATBITS) && (cstatus & 1)) {
u_int32_t cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset);
int timeout = 0;
/* kill off all activity on this channel */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset,
cmd & ~(ATA_AHCI_P_CMD_FRE | ATA_AHCI_P_CMD_ST));
/* XXX SOS this is not entirely wrong */
do {
DELAY(1000);
if (timeout++ > 1000) {
device_printf(dev, "stopping AHCI engine failed\n");
break;
}
} while (ATA_INL(ctlr->r_res2,
ATA_AHCI_P_CMD + offset) & ATA_AHCI_P_CMD_CR);
/* start operations on this channel */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset,
cmd | (ATA_AHCI_P_CMD_FRE | ATA_AHCI_P_CMD_ST));
return 1;
}
else
/* XXX SOS what todo on NCQ */
return (!(cstatus & 1));
}
return 0;
}
/* must be called with ATA channel locked and state_mtx held */
static int
ata_ahci_begin_transaction(struct ata_request *request)
{
struct ata_pci_controller *ctlr=device_get_softc(GRANDPARENT(request->dev));
struct ata_channel *ch = device_get_softc(request->parent);
struct ata_device *atadev = device_get_softc(request->dev);
struct ata_ahci_cmd_tab *ctp;
struct ata_ahci_cmd_list *clp;
int offset = ch->unit << 7;
int port = atadev->unit & 0x0f;
int entries = 0;
int fis_size;
/* get a piece of the workspace for this request */
ctp = (struct ata_ahci_cmd_tab *)
(ch->dma.work + ATA_AHCI_CT_OFFSET + (ATA_AHCI_CT_SIZE*request->tag));
/* setup the FIS for this request */
if (!(fis_size = ata_ahci_setup_fis(ctp, request))) {
device_printf(request->dev, "setting up SATA FIS failed\n");
request->result = EIO;
return ATA_OP_FINISHED;
}
/* if request moves data setup and load SG list */
if (request->flags & (ATA_R_READ | ATA_R_WRITE)) {
if (ch->dma.load(request, ctp->prd_tab, &entries)) {
device_printf(request->dev, "setting up DMA failed\n");
request->result = EIO;
return ATA_OP_FINISHED;
}
}
/* setup the command list entry */
clp = (struct ata_ahci_cmd_list *)
(ch->dma.work + ATA_AHCI_CL_OFFSET + (ATA_AHCI_CL_SIZE*request->tag));
clp->prd_length = entries;
clp->cmd_flags = (request->flags & ATA_R_WRITE ? ATA_AHCI_CMD_WRITE : 0) |
(request->flags & ATA_R_ATAPI ?
(ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH) : 0) |
(fis_size / sizeof(u_int32_t)) |
(port << 12);
clp->bytecount = 0;
clp->cmd_table_phys = htole64(ch->dma.work_bus + ATA_AHCI_CT_OFFSET +
(ATA_AHCI_CT_SIZE * request->tag));
/* clear eventual ACTIVE bit */
ATA_IDX_OUTL(ch, ATA_SACTIVE,
ATA_IDX_INL(ch, ATA_SACTIVE) & (1 << request->tag));
/* set command type bit */
if (request->flags & ATA_R_ATAPI)
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset,
ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset) |
ATA_AHCI_P_CMD_ATAPI);
else
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset,
ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset) &
~ATA_AHCI_P_CMD_ATAPI);
/* set PM port to address */
//ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBS + offset, (port << 8) | 0x00000001);
/* issue command to controller */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CI + offset, (1 << request->tag));
if (!(request->flags & ATA_R_ATAPI)) {
/* device reset doesn't interrupt */
if (request->u.ata.command == ATA_DEVICE_RESET) {
u_int32_t tf_data;
int timeout = 1000000;
do {
DELAY(10);
tf_data = ATA_INL(ctlr->r_res2, ATA_AHCI_P_TFD + (ch->unit<<7));
} while ((tf_data & ATA_S_BUSY) && timeout--);
if (bootverbose)
device_printf(ch->dev, "device_reset timeout=%dus\n",
(1000000-timeout)*10);
request->status = tf_data;
if (request->status & ATA_S_ERROR)
request->error = tf_data >> 8;
return ATA_OP_FINISHED;
}
}
/* start the timeout */
callout_reset(&request->callout, request->timeout * hz,
(timeout_t*)ata_timeout, request);
return ATA_OP_CONTINUES;
}
/* must be called with ATA channel locked and state_mtx held */
static int
ata_ahci_end_transaction(struct ata_request *request)
{
struct ata_pci_controller *ctlr=device_get_softc(GRANDPARENT(request->dev));
struct ata_channel *ch = device_get_softc(request->parent);
struct ata_ahci_cmd_list *clp;
u_int32_t tf_data;
int offset = ch->unit << 7;
/* kill the timeout */
callout_stop(&request->callout);
/* get status */
tf_data = ATA_INL(ctlr->r_res2, ATA_AHCI_P_TFD + offset);
request->status = tf_data;
/* if error status get details */
if (request->status & ATA_S_ERROR)
request->error = tf_data >> 8;
/* on control commands read back registers to the request struct */
if (request->flags & ATA_R_CONTROL) {
struct ata_device *atadev = device_get_softc(request->dev);
u_int8_t *fis = ch->dma.work + ATA_AHCI_FB_OFFSET + 0x40;
request->u.ata.count = fis[12] | ((u_int16_t)fis[13] << 8);
request->u.ata.lba = fis[4] | ((u_int64_t)fis[5] << 8) |
((u_int64_t)fis[6] << 16);
if (atadev->flags & ATA_D_48BIT_ACTIVE)
request->u.ata.lba |= ((u_int64_t)fis[8] << 24) |
((u_int64_t)fis[9] << 32) |
((u_int64_t)fis[10] << 40);
else
request->u.ata.lba |= ((u_int64_t)(fis[7] & 0x0f) << 24);
}
/* record how much data we actually moved */
clp = (struct ata_ahci_cmd_list *)
(ch->dma.work + ATA_AHCI_CL_OFFSET + (ATA_AHCI_CL_SIZE*request->tag));
request->donecount = clp->bytecount;
/* release SG list etc */
ch->dma.unload(request);
return ATA_OP_FINISHED;
}
static int
ata_ahci_issue_cmd(device_t dev, u_int16_t flags, int timeout)
{
struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
struct ata_ahci_cmd_list *clp =
(struct ata_ahci_cmd_list *)(ch->dma.work + ATA_AHCI_CL_OFFSET);
struct ata_ahci_cmd_tab *ctp =
(struct ata_ahci_cmd_tab *)(ch->dma.work + ATA_AHCI_CT_OFFSET);
u_int32_t status = 0;
int offset = ch->unit << 7;
int port = (ctp->cfis[1] & 0x0f);
int count;
clp->prd_length = 0;
clp->cmd_flags = (20 / sizeof(u_int32_t)) | flags | (port << 12);
clp->bytecount = 0;
clp->cmd_table_phys = htole64(ch->dma.work_bus + ATA_AHCI_CT_OFFSET);
/* set PM port */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBS + offset, (port << 8) | 0x00000001);
/* issue command to controller */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CI + offset, 1);
/* poll for command finished */
for (count = 0; count < timeout; count++) {
DELAY(1000);
if (!((status = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CI + offset)) & 1))
break;
}
/* clear interrupts */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IS + offset,
ATA_INL(ctlr->r_res2, ATA_AHCI_P_IS + offset));
if (bootverbose)
device_printf(dev, "ahci_issue_cmd time=%dms cnt=%dms status=%08x\n",
timeout, count, status);
if (timeout && (count >= timeout))
return EIO;
return 0;
}
static int
ata_ahci_pm_read(device_t dev, int port, int reg, u_int32_t *result)
{
struct ata_channel *ch = device_get_softc(dev);
struct ata_ahci_cmd_tab *ctp =
(struct ata_ahci_cmd_tab *)(ch->dma.work + ATA_AHCI_CT_OFFSET);
u_int8_t *fis = ch->dma.work + ATA_AHCI_FB_OFFSET + 0x40;
bzero(ctp->cfis, 64);
ctp->cfis[0] = 0x27; /* host to device */
ctp->cfis[1] = 0x8f; /* command FIS to PM port */
ctp->cfis[2] = ATA_READ_PM;
ctp->cfis[3] = reg;
ctp->cfis[7] = port | ATA_D_LBA;
ctp->cfis[15] = ATA_A_4BIT;
if (ata_ahci_issue_cmd(dev, 0, 10)) {
device_printf(dev, "error reading PM port\n");
return EIO;
}
*result = fis[12] | (fis[4] << 8) | (fis[5] << 16) | (fis[6] << 24);
return 0;
}
static int
ata_ahci_pm_write(device_t dev, int port, int reg, u_int32_t value)
{
struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
struct ata_ahci_cmd_tab *ctp =
(struct ata_ahci_cmd_tab *)(ch->dma.work + ATA_AHCI_CT_OFFSET);
int offset = ch->unit << 7;
bzero(ctp->cfis, 64);
ctp->cfis[0] = 0x27; /* host to device */
ctp->cfis[1] = 0x8f; /* command FIS to PM port */
ctp->cfis[2] = ATA_WRITE_PM;
ctp->cfis[3] = reg;
ctp->cfis[7] = port | ATA_D_LBA;
ctp->cfis[12] = value & 0xff;
ctp->cfis[4] = (value >> 8) & 0xff;;
ctp->cfis[5] = (value >> 16) & 0xff;;
ctp->cfis[6] = (value >> 24) & 0xff;;
ctp->cfis[15] = ATA_A_4BIT;
if (ata_ahci_issue_cmd(dev, 0, 100)) {
device_printf(dev, "error writing PM port\n");
return ATA_E_ABORT;
}
return (ATA_INL(ctlr->r_res2, ATA_AHCI_P_TFD + offset) >> 8) & 0xff;
}
static void
ata_ahci_stop(device_t dev)
This is the roumored ATA modulerisation works, and it needs a little explanation. If you just config KERNEL as usual there should be no apparent changes, you'll get all chipset support code compiled in. However there is now a way to only compile in code for chipsets needed on a pr vendor basis. ATA now has the following "device" entries: atacore: ATA core functionality, always needed for any ATA setup atacard: CARDBUS support atacbus: PC98 cbus support ataisa: ISA bus support atapci: PCI bus support only generic chipset support. ataahci: AHCI support, also pulled in by some vendor modules. ataacard, ataacerlabs, ataadaptec, ataamd, ataati, atacenatek, atacypress, atacyrix, atahighpoint, ataintel, ataite, atajmicron, atamarvell, atamicron, atanational, atanetcell, atanvidia, atapromise, ataserverworks, atasiliconimage, atasis, atavia; Vendor support, ie atavia for VIA chipsets atadisk: ATA disk driver ataraid: ATA softraid driver atapicd: ATAPI cd/dvd driver atapifd: ATAPI floppy/flashdisk driver atapist: ATAPI tape driver atausb: ATA<>USB bridge atapicam: ATA<>CAM bridge This makes it possible to config a kernel with just VIA chipset support by having the following ATA lines in the kernel config file: device atacore device atapci device atavia And then you need the atadisk, atapicd etc lines in there just as usual. If you use ATA as modules loaded at boot there is few changes except the rename of the "ata" module to "atacore", things looks just as usual. However under atapci you now have a whole bunch of vendor specific drivers, that you can kldload individually depending on you needs. Drivers have the same names as used in the kernel config explained above.
2008-10-09 12:56:57 +00:00
{
struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
u_int32_t cmd;
int offset = ch->unit << 7;
int timeout;
/* kill off all activity on this channel */
cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset);
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset,
cmd & ~(ATA_AHCI_P_CMD_FRE | ATA_AHCI_P_CMD_ST));
/* XXX SOS this is not entirely wrong */
timeout = 0;
do {
DELAY(1000);
if (timeout++ > 1000) {
device_printf(dev, "stopping AHCI engine failed\n");
break;
}
}
while (ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset) & ATA_AHCI_P_CMD_CR);
}
static void
ata_ahci_clo(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
u_int32_t cmd;
int offset = ch->unit << 7;
int timeout;
This is the roumored ATA modulerisation works, and it needs a little explanation. If you just config KERNEL as usual there should be no apparent changes, you'll get all chipset support code compiled in. However there is now a way to only compile in code for chipsets needed on a pr vendor basis. ATA now has the following "device" entries: atacore: ATA core functionality, always needed for any ATA setup atacard: CARDBUS support atacbus: PC98 cbus support ataisa: ISA bus support atapci: PCI bus support only generic chipset support. ataahci: AHCI support, also pulled in by some vendor modules. ataacard, ataacerlabs, ataadaptec, ataamd, ataati, atacenatek, atacypress, atacyrix, atahighpoint, ataintel, ataite, atajmicron, atamarvell, atamicron, atanational, atanetcell, atanvidia, atapromise, ataserverworks, atasiliconimage, atasis, atavia; Vendor support, ie atavia for VIA chipsets atadisk: ATA disk driver ataraid: ATA softraid driver atapicd: ATAPI cd/dvd driver atapifd: ATAPI floppy/flashdisk driver atapist: ATAPI tape driver atausb: ATA<>USB bridge atapicam: ATA<>CAM bridge This makes it possible to config a kernel with just VIA chipset support by having the following ATA lines in the kernel config file: device atacore device atapci device atavia And then you need the atadisk, atapicd etc lines in there just as usual. If you use ATA as modules loaded at boot there is few changes except the rename of the "ata" module to "atacore", things looks just as usual. However under atapci you now have a whole bunch of vendor specific drivers, that you can kldload individually depending on you needs. Drivers have the same names as used in the kernel config explained above.
2008-10-09 12:56:57 +00:00
/* issue Command List Override if supported */
if (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_CLO) {
cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset);
cmd |= ATA_AHCI_P_CMD_CLO;
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, cmd);
timeout = 0;
do {
DELAY(1000);
if (timeout++ > 1000) {
device_printf(dev, "executing CLO failed\n");
break;
}
}
while (ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD+offset)&ATA_AHCI_P_CMD_CLO);
}
}
static void
ata_ahci_start(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
u_int32_t cmd;
int offset = ch->unit << 7;
This is the roumored ATA modulerisation works, and it needs a little explanation. If you just config KERNEL as usual there should be no apparent changes, you'll get all chipset support code compiled in. However there is now a way to only compile in code for chipsets needed on a pr vendor basis. ATA now has the following "device" entries: atacore: ATA core functionality, always needed for any ATA setup atacard: CARDBUS support atacbus: PC98 cbus support ataisa: ISA bus support atapci: PCI bus support only generic chipset support. ataahci: AHCI support, also pulled in by some vendor modules. ataacard, ataacerlabs, ataadaptec, ataamd, ataati, atacenatek, atacypress, atacyrix, atahighpoint, ataintel, ataite, atajmicron, atamarvell, atamicron, atanational, atanetcell, atanvidia, atapromise, ataserverworks, atasiliconimage, atasis, atavia; Vendor support, ie atavia for VIA chipsets atadisk: ATA disk driver ataraid: ATA softraid driver atapicd: ATAPI cd/dvd driver atapifd: ATAPI floppy/flashdisk driver atapist: ATAPI tape driver atausb: ATA<>USB bridge atapicam: ATA<>CAM bridge This makes it possible to config a kernel with just VIA chipset support by having the following ATA lines in the kernel config file: device atacore device atapci device atavia And then you need the atadisk, atapicd etc lines in there just as usual. If you use ATA as modules loaded at boot there is few changes except the rename of the "ata" module to "atacore", things looks just as usual. However under atapci you now have a whole bunch of vendor specific drivers, that you can kldload individually depending on you needs. Drivers have the same names as used in the kernel config explained above.
2008-10-09 12:56:57 +00:00
/* clear SATA error register */
ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR));
/* clear any interrupts pending on this channel */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IS + offset,
ATA_INL(ctlr->r_res2, ATA_AHCI_P_IS + offset));
/* start operations on this channel */
cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset);
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset,
cmd | (ATA_AHCI_P_CMD_FRE | ATA_AHCI_P_CMD_ST) |
(ch->devices & ATA_PORTMULTIPLIER ? ATA_AHCI_P_CMD_PMA : 0));
}
static int
ata_ahci_wait_ready(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
int offset = ch->unit << 7;
int timeout = 0;
while (ATA_INL(ctlr->r_res2, ATA_AHCI_P_TFD + offset) &
(ATA_S_BUSY | ATA_S_DRQ)) {
DELAY(1000);
if (timeout++ > 1000) {
device_printf(dev, "port is not ready\n");
return (-1);
}
}
if (bootverbose)
device_printf(dev, "ready wait time=%dms\n", timeout);
return (0);
}
This is the roumored ATA modulerisation works, and it needs a little explanation. If you just config KERNEL as usual there should be no apparent changes, you'll get all chipset support code compiled in. However there is now a way to only compile in code for chipsets needed on a pr vendor basis. ATA now has the following "device" entries: atacore: ATA core functionality, always needed for any ATA setup atacard: CARDBUS support atacbus: PC98 cbus support ataisa: ISA bus support atapci: PCI bus support only generic chipset support. ataahci: AHCI support, also pulled in by some vendor modules. ataacard, ataacerlabs, ataadaptec, ataamd, ataati, atacenatek, atacypress, atacyrix, atahighpoint, ataintel, ataite, atajmicron, atamarvell, atamicron, atanational, atanetcell, atanvidia, atapromise, ataserverworks, atasiliconimage, atasis, atavia; Vendor support, ie atavia for VIA chipsets atadisk: ATA disk driver ataraid: ATA softraid driver atapicd: ATAPI cd/dvd driver atapifd: ATAPI floppy/flashdisk driver atapist: ATAPI tape driver atausb: ATA<>USB bridge atapicam: ATA<>CAM bridge This makes it possible to config a kernel with just VIA chipset support by having the following ATA lines in the kernel config file: device atacore device atapci device atavia And then you need the atadisk, atapicd etc lines in there just as usual. If you use ATA as modules loaded at boot there is few changes except the rename of the "ata" module to "atacore", things looks just as usual. However under atapci you now have a whole bunch of vendor specific drivers, that you can kldload individually depending on you needs. Drivers have the same names as used in the kernel config explained above.
2008-10-09 12:56:57 +00:00
static u_int32_t
ata_ahci_softreset(device_t dev, int port)
{
struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
int offset = ch->unit << 7;
struct ata_ahci_cmd_tab *ctp =
(struct ata_ahci_cmd_tab *)(ch->dma.work + ATA_AHCI_CT_OFFSET);
/* kick controller into sane state */
ata_ahci_stop(dev);
ata_ahci_clo(dev);
ata_ahci_start(dev);
This is the roumored ATA modulerisation works, and it needs a little explanation. If you just config KERNEL as usual there should be no apparent changes, you'll get all chipset support code compiled in. However there is now a way to only compile in code for chipsets needed on a pr vendor basis. ATA now has the following "device" entries: atacore: ATA core functionality, always needed for any ATA setup atacard: CARDBUS support atacbus: PC98 cbus support ataisa: ISA bus support atapci: PCI bus support only generic chipset support. ataahci: AHCI support, also pulled in by some vendor modules. ataacard, ataacerlabs, ataadaptec, ataamd, ataati, atacenatek, atacypress, atacyrix, atahighpoint, ataintel, ataite, atajmicron, atamarvell, atamicron, atanational, atanetcell, atanvidia, atapromise, ataserverworks, atasiliconimage, atasis, atavia; Vendor support, ie atavia for VIA chipsets atadisk: ATA disk driver ataraid: ATA softraid driver atapicd: ATAPI cd/dvd driver atapifd: ATAPI floppy/flashdisk driver atapist: ATAPI tape driver atausb: ATA<>USB bridge atapicam: ATA<>CAM bridge This makes it possible to config a kernel with just VIA chipset support by having the following ATA lines in the kernel config file: device atacore device atapci device atavia And then you need the atadisk, atapicd etc lines in there just as usual. If you use ATA as modules loaded at boot there is few changes except the rename of the "ata" module to "atacore", things looks just as usual. However under atapci you now have a whole bunch of vendor specific drivers, that you can kldload individually depending on you needs. Drivers have the same names as used in the kernel config explained above.
2008-10-09 12:56:57 +00:00
/* pull reset active */
bzero(ctp->cfis, 64);
ctp->cfis[0] = 0x27;
ctp->cfis[1] = port & 0x0f;
//ctp->cfis[7] = ATA_D_LBA | ATA_D_IBM;
ctp->cfis[15] = (ATA_A_4BIT | ATA_A_RESET);
if (ata_ahci_issue_cmd(dev, ATA_AHCI_CMD_RESET | ATA_AHCI_CMD_CLR_BUSY,100))
device_printf(dev, "setting SRST failed ??\n");
//return -1;
ata_udelay(5000);
/* pull reset inactive -> device softreset */
bzero(ctp->cfis, 64);
ctp->cfis[0] = 0x27;
ctp->cfis[1] = port & 0x0f;
//ctp->cfis[7] = ATA_D_LBA | ATA_D_IBM;
ctp->cfis[15] = ATA_A_4BIT;
if (ata_ahci_issue_cmd(dev, 0, 0))
return -1;
if (ata_ahci_wait_ready(dev))
return (-1);
This is the roumored ATA modulerisation works, and it needs a little explanation. If you just config KERNEL as usual there should be no apparent changes, you'll get all chipset support code compiled in. However there is now a way to only compile in code for chipsets needed on a pr vendor basis. ATA now has the following "device" entries: atacore: ATA core functionality, always needed for any ATA setup atacard: CARDBUS support atacbus: PC98 cbus support ataisa: ISA bus support atapci: PCI bus support only generic chipset support. ataahci: AHCI support, also pulled in by some vendor modules. ataacard, ataacerlabs, ataadaptec, ataamd, ataati, atacenatek, atacypress, atacyrix, atahighpoint, ataintel, ataite, atajmicron, atamarvell, atamicron, atanational, atanetcell, atanvidia, atapromise, ataserverworks, atasiliconimage, atasis, atavia; Vendor support, ie atavia for VIA chipsets atadisk: ATA disk driver ataraid: ATA softraid driver atapicd: ATAPI cd/dvd driver atapifd: ATAPI floppy/flashdisk driver atapist: ATAPI tape driver atausb: ATA<>USB bridge atapicam: ATA<>CAM bridge This makes it possible to config a kernel with just VIA chipset support by having the following ATA lines in the kernel config file: device atacore device atapci device atavia And then you need the atadisk, atapicd etc lines in there just as usual. If you use ATA as modules loaded at boot there is few changes except the rename of the "ata" module to "atacore", things looks just as usual. However under atapci you now have a whole bunch of vendor specific drivers, that you can kldload individually depending on you needs. Drivers have the same names as used in the kernel config explained above.
2008-10-09 12:56:57 +00:00
return ATA_INL(ctlr->r_res2, ATA_AHCI_P_SIG + offset);
}
void
ata_ahci_reset(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
u_int64_t work;
u_int32_t signature;
This is the roumored ATA modulerisation works, and it needs a little explanation. If you just config KERNEL as usual there should be no apparent changes, you'll get all chipset support code compiled in. However there is now a way to only compile in code for chipsets needed on a pr vendor basis. ATA now has the following "device" entries: atacore: ATA core functionality, always needed for any ATA setup atacard: CARDBUS support atacbus: PC98 cbus support ataisa: ISA bus support atapci: PCI bus support only generic chipset support. ataahci: AHCI support, also pulled in by some vendor modules. ataacard, ataacerlabs, ataadaptec, ataamd, ataati, atacenatek, atacypress, atacyrix, atahighpoint, ataintel, ataite, atajmicron, atamarvell, atamicron, atanational, atanetcell, atanvidia, atapromise, ataserverworks, atasiliconimage, atasis, atavia; Vendor support, ie atavia for VIA chipsets atadisk: ATA disk driver ataraid: ATA softraid driver atapicd: ATAPI cd/dvd driver atapifd: ATAPI floppy/flashdisk driver atapist: ATAPI tape driver atausb: ATA<>USB bridge atapicam: ATA<>CAM bridge This makes it possible to config a kernel with just VIA chipset support by having the following ATA lines in the kernel config file: device atacore device atapci device atavia And then you need the atadisk, atapicd etc lines in there just as usual. If you use ATA as modules loaded at boot there is few changes except the rename of the "ata" module to "atacore", things looks just as usual. However under atapci you now have a whole bunch of vendor specific drivers, that you can kldload individually depending on you needs. Drivers have the same names as used in the kernel config explained above.
2008-10-09 12:56:57 +00:00
int offset = ch->unit << 7;
if (!(ATA_INL(ctlr->r_res2, ATA_AHCI_PI) & (1 << ch->unit))) {
device_printf(dev, "port not implemented\n");
return;
}
/* setup work areas */
work = ch->dma.work_bus + ATA_AHCI_CL_OFFSET;
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLB + offset, work & 0xffffffff);
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLBU + offset, work >> 32);
work = ch->dma.work_bus + ATA_AHCI_FB_OFFSET;
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FB + offset, work & 0xffffffff);
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBU + offset, work >> 32);
/* activate the channel and power/spin up device */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset,
(ATA_AHCI_P_CMD_ACTIVE | ATA_AHCI_P_CMD_POD | ATA_AHCI_P_CMD_SUD));
ata_ahci_stop(dev);
This is the roumored ATA modulerisation works, and it needs a little explanation. If you just config KERNEL as usual there should be no apparent changes, you'll get all chipset support code compiled in. However there is now a way to only compile in code for chipsets needed on a pr vendor basis. ATA now has the following "device" entries: atacore: ATA core functionality, always needed for any ATA setup atacard: CARDBUS support atacbus: PC98 cbus support ataisa: ISA bus support atapci: PCI bus support only generic chipset support. ataahci: AHCI support, also pulled in by some vendor modules. ataacard, ataacerlabs, ataadaptec, ataamd, ataati, atacenatek, atacypress, atacyrix, atahighpoint, ataintel, ataite, atajmicron, atamarvell, atamicron, atanational, atanetcell, atanvidia, atapromise, ataserverworks, atasiliconimage, atasis, atavia; Vendor support, ie atavia for VIA chipsets atadisk: ATA disk driver ataraid: ATA softraid driver atapicd: ATAPI cd/dvd driver atapifd: ATAPI floppy/flashdisk driver atapist: ATAPI tape driver atausb: ATA<>USB bridge atapicam: ATA<>CAM bridge This makes it possible to config a kernel with just VIA chipset support by having the following ATA lines in the kernel config file: device atacore device atapci device atavia And then you need the atadisk, atapicd etc lines in there just as usual. If you use ATA as modules loaded at boot there is few changes except the rename of the "ata" module to "atacore", things looks just as usual. However under atapci you now have a whole bunch of vendor specific drivers, that you can kldload individually depending on you needs. Drivers have the same names as used in the kernel config explained above.
2008-10-09 12:56:57 +00:00
/* enable FIS based switching */
//ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBS + offset, 0x00000003);
if (!ata_sata_phy_reset(dev)) {
if (bootverbose)
device_printf(dev, "phy reset found no device\n");
ch->devices = 0;
/* enable wanted port interrupts */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IE + offset,
(ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC));
This is the roumored ATA modulerisation works, and it needs a little explanation. If you just config KERNEL as usual there should be no apparent changes, you'll get all chipset support code compiled in. However there is now a way to only compile in code for chipsets needed on a pr vendor basis. ATA now has the following "device" entries: atacore: ATA core functionality, always needed for any ATA setup atacard: CARDBUS support atacbus: PC98 cbus support ataisa: ISA bus support atapci: PCI bus support only generic chipset support. ataahci: AHCI support, also pulled in by some vendor modules. ataacard, ataacerlabs, ataadaptec, ataamd, ataati, atacenatek, atacypress, atacyrix, atahighpoint, ataintel, ataite, atajmicron, atamarvell, atamicron, atanational, atanetcell, atanvidia, atapromise, ataserverworks, atasiliconimage, atasis, atavia; Vendor support, ie atavia for VIA chipsets atadisk: ATA disk driver ataraid: ATA softraid driver atapicd: ATAPI cd/dvd driver atapifd: ATAPI floppy/flashdisk driver atapist: ATAPI tape driver atausb: ATA<>USB bridge atapicam: ATA<>CAM bridge This makes it possible to config a kernel with just VIA chipset support by having the following ATA lines in the kernel config file: device atacore device atapci device atavia And then you need the atadisk, atapicd etc lines in there just as usual. If you use ATA as modules loaded at boot there is few changes except the rename of the "ata" module to "atacore", things looks just as usual. However under atapci you now have a whole bunch of vendor specific drivers, that you can kldload individually depending on you needs. Drivers have the same names as used in the kernel config explained above.
2008-10-09 12:56:57 +00:00
return;
}
ata_ahci_start(dev);
/* enable wanted port interrupts */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IE + offset,
(ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_TFE | ATA_AHCI_P_IX_HBF |
ATA_AHCI_P_IX_HBD | ATA_AHCI_P_IX_IF | ATA_AHCI_P_IX_OF |
ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC | ATA_AHCI_P_IX_DP |
ATA_AHCI_P_IX_UF | ATA_AHCI_P_IX_SDB | ATA_AHCI_P_IX_DS |
ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DHR));
/* Wait for initial TFD from device. */
ata_ahci_wait_ready(dev);
This is the roumored ATA modulerisation works, and it needs a little explanation. If you just config KERNEL as usual there should be no apparent changes, you'll get all chipset support code compiled in. However there is now a way to only compile in code for chipsets needed on a pr vendor basis. ATA now has the following "device" entries: atacore: ATA core functionality, always needed for any ATA setup atacard: CARDBUS support atacbus: PC98 cbus support ataisa: ISA bus support atapci: PCI bus support only generic chipset support. ataahci: AHCI support, also pulled in by some vendor modules. ataacard, ataacerlabs, ataadaptec, ataamd, ataati, atacenatek, atacypress, atacyrix, atahighpoint, ataintel, ataite, atajmicron, atamarvell, atamicron, atanational, atanetcell, atanvidia, atapromise, ataserverworks, atasiliconimage, atasis, atavia; Vendor support, ie atavia for VIA chipsets atadisk: ATA disk driver ataraid: ATA softraid driver atapicd: ATAPI cd/dvd driver atapifd: ATAPI floppy/flashdisk driver atapist: ATAPI tape driver atausb: ATA<>USB bridge atapicam: ATA<>CAM bridge This makes it possible to config a kernel with just VIA chipset support by having the following ATA lines in the kernel config file: device atacore device atapci device atavia And then you need the atadisk, atapicd etc lines in there just as usual. If you use ATA as modules loaded at boot there is few changes except the rename of the "ata" module to "atacore", things looks just as usual. However under atapci you now have a whole bunch of vendor specific drivers, that you can kldload individually depending on you needs. Drivers have the same names as used in the kernel config explained above.
2008-10-09 12:56:57 +00:00
/* only probe for PortMultiplier if HW has support */
if (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_SPM) {
This is the roumored ATA modulerisation works, and it needs a little explanation. If you just config KERNEL as usual there should be no apparent changes, you'll get all chipset support code compiled in. However there is now a way to only compile in code for chipsets needed on a pr vendor basis. ATA now has the following "device" entries: atacore: ATA core functionality, always needed for any ATA setup atacard: CARDBUS support atacbus: PC98 cbus support ataisa: ISA bus support atapci: PCI bus support only generic chipset support. ataahci: AHCI support, also pulled in by some vendor modules. ataacard, ataacerlabs, ataadaptec, ataamd, ataati, atacenatek, atacypress, atacyrix, atahighpoint, ataintel, ataite, atajmicron, atamarvell, atamicron, atanational, atanetcell, atanvidia, atapromise, ataserverworks, atasiliconimage, atasis, atavia; Vendor support, ie atavia for VIA chipsets atadisk: ATA disk driver ataraid: ATA softraid driver atapicd: ATAPI cd/dvd driver atapifd: ATAPI floppy/flashdisk driver atapist: ATAPI tape driver atausb: ATA<>USB bridge atapicam: ATA<>CAM bridge This makes it possible to config a kernel with just VIA chipset support by having the following ATA lines in the kernel config file: device atacore device atapci device atavia And then you need the atadisk, atapicd etc lines in there just as usual. If you use ATA as modules loaded at boot there is few changes except the rename of the "ata" module to "atacore", things looks just as usual. However under atapci you now have a whole bunch of vendor specific drivers, that you can kldload individually depending on you needs. Drivers have the same names as used in the kernel config explained above.
2008-10-09 12:56:57 +00:00
signature = ata_ahci_softreset(dev, ATA_PM);
/* Workaround for some ATI chips, failing to soft-reset
* when port multiplicator supported, but absent.
* XXX: We can also check PxIS.IPMS==1 here to be sure. */
if (signature == 0xffffffff)
signature = ata_ahci_softreset(dev, 0);
} else {
This is the roumored ATA modulerisation works, and it needs a little explanation. If you just config KERNEL as usual there should be no apparent changes, you'll get all chipset support code compiled in. However there is now a way to only compile in code for chipsets needed on a pr vendor basis. ATA now has the following "device" entries: atacore: ATA core functionality, always needed for any ATA setup atacard: CARDBUS support atacbus: PC98 cbus support ataisa: ISA bus support atapci: PCI bus support only generic chipset support. ataahci: AHCI support, also pulled in by some vendor modules. ataacard, ataacerlabs, ataadaptec, ataamd, ataati, atacenatek, atacypress, atacyrix, atahighpoint, ataintel, ataite, atajmicron, atamarvell, atamicron, atanational, atanetcell, atanvidia, atapromise, ataserverworks, atasiliconimage, atasis, atavia; Vendor support, ie atavia for VIA chipsets atadisk: ATA disk driver ataraid: ATA softraid driver atapicd: ATAPI cd/dvd driver atapifd: ATAPI floppy/flashdisk driver atapist: ATAPI tape driver atausb: ATA<>USB bridge atapicam: ATA<>CAM bridge This makes it possible to config a kernel with just VIA chipset support by having the following ATA lines in the kernel config file: device atacore device atapci device atavia And then you need the atadisk, atapicd etc lines in there just as usual. If you use ATA as modules loaded at boot there is few changes except the rename of the "ata" module to "atacore", things looks just as usual. However under atapci you now have a whole bunch of vendor specific drivers, that you can kldload individually depending on you needs. Drivers have the same names as used in the kernel config explained above.
2008-10-09 12:56:57 +00:00
signature = ata_ahci_softreset(dev, 0);
}
if (bootverbose)
device_printf(dev, "SIGNATURE: %08x\n", signature);
switch (signature) {
case 0x00000101:
ch->devices = ATA_ATA_MASTER;
break;
case 0x96690101:
ch->devices = ATA_PORTMULTIPLIER;
ata_pm_identify(dev);
break;
case 0xeb140101:
ch->devices = ATA_ATAPI_MASTER;
break;
default: /* SOS XXX */
if (bootverbose)
device_printf(dev, "No signature, asuming disk device\n");
ch->devices = ATA_ATA_MASTER;
}
if (bootverbose)
device_printf(dev, "ahci_reset devices=%08x\n", ch->devices);
}
static void
ata_ahci_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error)
{
struct ata_dmasetprd_args *args = xsc;
struct ata_ahci_dma_prd *prd = args->dmatab;
int i;
if (!(args->error = error)) {
for (i = 0; i < nsegs; i++) {
prd[i].dba = htole64(segs[i].ds_addr);
prd[i].dbc = htole32((segs[i].ds_len - 1) & ATA_AHCI_PRD_MASK);
}
}
KASSERT(nsegs <= ATA_AHCI_DMA_ENTRIES, ("too many DMA segment entries\n"));
args->nsegs = nsegs;
}
void
ata_ahci_dmainit(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
ata_dmainit(dev);
/* note start and stop are not used here */
ch->dma.setprd = ata_ahci_dmasetprd;
ch->dma.max_iosize = 8192 * DEV_BSIZE;
if (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_64BIT)
ch->dma.max_address = BUS_SPACE_MAXADDR;
}
static int
ata_ahci_setup_fis(struct ata_ahci_cmd_tab *ctp, struct ata_request *request)
{
bzero(ctp->cfis, 64);
if (request->flags & ATA_R_ATAPI) {
bzero(ctp->acmd, 32);
bcopy(request->u.atapi.ccb, ctp->acmd, 16);
}
return ata_request2fis_h2d(request, &ctp->cfis[0]);
}
ATA_DECLARE_DRIVER(ata_ahci);