aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/ahci/ahci.c
diff options
context:
space:
mode:
authorWarner Losh <imp@FreeBSD.org>2014-09-04 22:22:53 +0000
committerWarner Losh <imp@FreeBSD.org>2014-09-04 22:22:53 +0000
commit802df3ace64925cb23b020c9cf9b06118b7b7d5d (patch)
treea3ad8758add198b046ae114713f6fb6bf4bea80c /sys/dev/ahci/ahci.c
parentfcb3a37075b9fb3335085b68c18e6a3ba2379a25 (diff)
downloadsrc-802df3ace64925cb23b020c9cf9b06118b7b7d5d.tar.gz
src-802df3ace64925cb23b020c9cf9b06118b7b7d5d.zip
Separate out PCI attachment from the main AHCI driver. Move checks of
PCI IDs into quirks, which mostly fit (though you'd get no argument from me that AHCI_Q_SATA1_UNIT0 is oddly specific). Set these quirks in the PCI attachment. Make some shared functions public so that PCI and possibly other bus attachments can use them. The split isn't perfect yet, but it is functional. The split will be perfected as other bus attachments for AHCI are written. Sponsored by: Netflix Reviewed by: kan, mav Differential Revision: https://reviews.freebsd.org/D699
Notes
Notes: svn path=/head/; revision=271146
Diffstat (limited to 'sys/dev/ahci/ahci.c')
-rw-r--r--sys/dev/ahci/ahci.c601
1 files changed, 75 insertions, 526 deletions
diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c
index b2148339e5b1..b81440aff0d3 100644
--- a/sys/dev/ahci/ahci.c
+++ b/sys/dev/ahci/ahci.c
@@ -41,8 +41,6 @@ __FBSDID("$FreeBSD$");
#include <machine/resource.h>
#include <machine/bus.h>
#include <sys/rman.h>
-#include <dev/pci/pcivar.h>
-#include <dev/pci/pcireg.h>
#include "ahci.h"
#include <cam/cam.h>
@@ -52,12 +50,9 @@ __FBSDID("$FreeBSD$");
#include <cam/cam_debug.h>
/* local prototypes */
-static int ahci_setup_interrupt(device_t dev);
static void ahci_intr(void *data);
static void ahci_intr_one(void *data);
static void ahci_intr_one_edge(void *data);
-static int ahci_suspend(device_t dev);
-static int ahci_resume(device_t dev);
static int ahci_ch_init(device_t dev);
static int ahci_ch_deinit(device_t dev);
static int ahci_ch_suspend(device_t dev);
@@ -66,8 +61,6 @@ static void ahci_ch_pm(void *arg);
static void ahci_ch_intr(void *arg);
static void ahci_ch_intr_direct(void *arg);
static void ahci_ch_intr_main(struct ahci_channel *ch, uint32_t istatus);
-static int ahci_ctlr_reset(device_t dev);
-static int ahci_ctlr_setup(device_t dev);
static void ahci_begin_transaction(device_t dev, union ccb *ccb);
static void ahci_dmasetprd(void *arg, bus_dma_segment_t *segs, int nsegs, int error);
static void ahci_execute_transaction(struct ahci_slot *slot);
@@ -99,366 +92,76 @@ static void ahcipoll(struct cam_sim *sim);
static MALLOC_DEFINE(M_AHCI, "AHCI driver", "AHCI driver data buffers");
-static struct {
- uint32_t id;
- uint8_t rev;
- const char *name;
- int quirks;
-#define AHCI_Q_NOFORCE 1
-#define AHCI_Q_NOPMP 2
-#define AHCI_Q_NONCQ 4
-#define AHCI_Q_1CH 8
-#define AHCI_Q_2CH 16
-#define AHCI_Q_4CH 32
-#define AHCI_Q_EDGEIS 64
-#define AHCI_Q_SATA2 128
-#define AHCI_Q_NOBSYRES 256
-#define AHCI_Q_NOAA 512
-#define AHCI_Q_NOCOUNT 1024
-#define AHCI_Q_ALTSIG 2048
-#define AHCI_Q_NOMSI 4096
-
-#define AHCI_Q_BIT_STRING \
- "\020" \
- "\001NOFORCE" \
- "\002NOPMP" \
- "\003NONCQ" \
- "\0041CH" \
- "\0052CH" \
- "\0064CH" \
- "\007EDGEIS" \
- "\010SATA2" \
- "\011NOBSYRES" \
- "\012NOAA" \
- "\013NOCOUNT" \
- "\014ALTSIG" \
- "\015NOMSI"
-} ahci_ids[] = {
- {0x43801002, 0x00, "AMD SB600", AHCI_Q_NOMSI},
- {0x43901002, 0x00, "AMD SB7x0/SB8x0/SB9x0", 0},
- {0x43911002, 0x00, "AMD SB7x0/SB8x0/SB9x0", 0},
- {0x43921002, 0x00, "AMD SB7x0/SB8x0/SB9x0", 0},
- {0x43931002, 0x00, "AMD SB7x0/SB8x0/SB9x0", 0},
- {0x43941002, 0x00, "AMD SB7x0/SB8x0/SB9x0", 0},
- {0x43951002, 0x00, "AMD SB8x0/SB9x0", 0},
- {0x78001022, 0x00, "AMD Hudson-2", 0},
- {0x78011022, 0x00, "AMD Hudson-2", 0},
- {0x78021022, 0x00, "AMD Hudson-2", 0},
- {0x78031022, 0x00, "AMD Hudson-2", 0},
- {0x78041022, 0x00, "AMD Hudson-2", 0},
- {0x06111b21, 0x00, "ASMedia ASM2106", 0},
- {0x06121b21, 0x00, "ASMedia ASM1061", 0},
- {0x26528086, 0x00, "Intel ICH6", AHCI_Q_NOFORCE},
- {0x26538086, 0x00, "Intel ICH6M", AHCI_Q_NOFORCE},
- {0x26818086, 0x00, "Intel ESB2", 0},
- {0x26828086, 0x00, "Intel ESB2", 0},
- {0x26838086, 0x00, "Intel ESB2", 0},
- {0x27c18086, 0x00, "Intel ICH7", 0},
- {0x27c38086, 0x00, "Intel ICH7", 0},
- {0x27c58086, 0x00, "Intel ICH7M", 0},
- {0x27c68086, 0x00, "Intel ICH7M", 0},
- {0x28218086, 0x00, "Intel ICH8", 0},
- {0x28228086, 0x00, "Intel ICH8", 0},
- {0x28248086, 0x00, "Intel ICH8", 0},
- {0x28298086, 0x00, "Intel ICH8M", 0},
- {0x282a8086, 0x00, "Intel ICH8M", 0},
- {0x29228086, 0x00, "Intel ICH9", 0},
- {0x29238086, 0x00, "Intel ICH9", 0},
- {0x29248086, 0x00, "Intel ICH9", 0},
- {0x29258086, 0x00, "Intel ICH9", 0},
- {0x29278086, 0x00, "Intel ICH9", 0},
- {0x29298086, 0x00, "Intel ICH9M", 0},
- {0x292a8086, 0x00, "Intel ICH9M", 0},
- {0x292b8086, 0x00, "Intel ICH9M", 0},
- {0x292c8086, 0x00, "Intel ICH9M", 0},
- {0x292f8086, 0x00, "Intel ICH9M", 0},
- {0x294d8086, 0x00, "Intel ICH9", 0},
- {0x294e8086, 0x00, "Intel ICH9M", 0},
- {0x3a058086, 0x00, "Intel ICH10", 0},
- {0x3a228086, 0x00, "Intel ICH10", 0},
- {0x3a258086, 0x00, "Intel ICH10", 0},
- {0x3b228086, 0x00, "Intel 5 Series/3400 Series", 0},
- {0x3b238086, 0x00, "Intel 5 Series/3400 Series", 0},
- {0x3b258086, 0x00, "Intel 5 Series/3400 Series", 0},
- {0x3b298086, 0x00, "Intel 5 Series/3400 Series", 0},
- {0x3b2c8086, 0x00, "Intel 5 Series/3400 Series", 0},
- {0x3b2f8086, 0x00, "Intel 5 Series/3400 Series", 0},
- {0x1c028086, 0x00, "Intel Cougar Point", 0},
- {0x1c038086, 0x00, "Intel Cougar Point", 0},
- {0x1c048086, 0x00, "Intel Cougar Point", 0},
- {0x1c058086, 0x00, "Intel Cougar Point", 0},
- {0x1d028086, 0x00, "Intel Patsburg", 0},
- {0x1d048086, 0x00, "Intel Patsburg", 0},
- {0x1d068086, 0x00, "Intel Patsburg", 0},
- {0x28268086, 0x00, "Intel Patsburg (RAID)", 0},
- {0x1e028086, 0x00, "Intel Panther Point", 0},
- {0x1e038086, 0x00, "Intel Panther Point", 0},
- {0x1e048086, 0x00, "Intel Panther Point (RAID)", 0},
- {0x1e058086, 0x00, "Intel Panther Point (RAID)", 0},
- {0x1e068086, 0x00, "Intel Panther Point (RAID)", 0},
- {0x1e078086, 0x00, "Intel Panther Point (RAID)", 0},
- {0x1e0e8086, 0x00, "Intel Panther Point (RAID)", 0},
- {0x1e0f8086, 0x00, "Intel Panther Point (RAID)", 0},
- {0x1f228086, 0x00, "Intel Avoton", 0},
- {0x1f238086, 0x00, "Intel Avoton", 0},
- {0x1f248086, 0x00, "Intel Avoton (RAID)", 0},
- {0x1f258086, 0x00, "Intel Avoton (RAID)", 0},
- {0x1f268086, 0x00, "Intel Avoton (RAID)", 0},
- {0x1f278086, 0x00, "Intel Avoton (RAID)", 0},
- {0x1f2e8086, 0x00, "Intel Avoton (RAID)", 0},
- {0x1f2f8086, 0x00, "Intel Avoton (RAID)", 0},
- {0x1f328086, 0x00, "Intel Avoton", 0},
- {0x1f338086, 0x00, "Intel Avoton", 0},
- {0x1f348086, 0x00, "Intel Avoton (RAID)", 0},
- {0x1f358086, 0x00, "Intel Avoton (RAID)", 0},
- {0x1f368086, 0x00, "Intel Avoton (RAID)", 0},
- {0x1f378086, 0x00, "Intel Avoton (RAID)", 0},
- {0x1f3e8086, 0x00, "Intel Avoton (RAID)", 0},
- {0x1f3f8086, 0x00, "Intel Avoton (RAID)", 0},
- {0x23a38086, 0x00, "Intel Coleto Creek", 0},
- {0x28238086, 0x00, "Intel Wellsburg (RAID)", 0},
- {0x28278086, 0x00, "Intel Wellsburg (RAID)", 0},
- {0x8c028086, 0x00, "Intel Lynx Point", 0},
- {0x8c038086, 0x00, "Intel Lynx Point", 0},
- {0x8c048086, 0x00, "Intel Lynx Point (RAID)", 0},
- {0x8c058086, 0x00, "Intel Lynx Point (RAID)", 0},
- {0x8c068086, 0x00, "Intel Lynx Point (RAID)", 0},
- {0x8c078086, 0x00, "Intel Lynx Point (RAID)", 0},
- {0x8c0e8086, 0x00, "Intel Lynx Point (RAID)", 0},
- {0x8c0f8086, 0x00, "Intel Lynx Point (RAID)", 0},
- {0x8d028086, 0x00, "Intel Wellsburg", 0},
- {0x8d048086, 0x00, "Intel Wellsburg (RAID)", 0},
- {0x8d068086, 0x00, "Intel Wellsburg (RAID)", 0},
- {0x8d628086, 0x00, "Intel Wellsburg", 0},
- {0x8d648086, 0x00, "Intel Wellsburg (RAID)", 0},
- {0x8d668086, 0x00, "Intel Wellsburg (RAID)", 0},
- {0x8d6e8086, 0x00, "Intel Wellsburg (RAID)", 0},
- {0x9c028086, 0x00, "Intel Lynx Point-LP", 0},
- {0x9c038086, 0x00, "Intel Lynx Point-LP", 0},
- {0x9c048086, 0x00, "Intel Lynx Point-LP (RAID)", 0},
- {0x9c058086, 0x00, "Intel Lynx Point-LP (RAID)", 0},
- {0x9c068086, 0x00, "Intel Lynx Point-LP (RAID)", 0},
- {0x9c078086, 0x00, "Intel Lynx Point-LP (RAID)", 0},
- {0x9c0e8086, 0x00, "Intel Lynx Point-LP (RAID)", 0},
- {0x9c0f8086, 0x00, "Intel Lynx Point-LP (RAID)", 0},
- {0x23238086, 0x00, "Intel DH89xxCC", 0},
- {0x2360197b, 0x00, "JMicron JMB360", 0},
- {0x2361197b, 0x00, "JMicron JMB361", AHCI_Q_NOFORCE},
- {0x2362197b, 0x00, "JMicron JMB362", 0},
- {0x2363197b, 0x00, "JMicron JMB363", AHCI_Q_NOFORCE},
- {0x2365197b, 0x00, "JMicron JMB365", AHCI_Q_NOFORCE},
- {0x2366197b, 0x00, "JMicron JMB366", AHCI_Q_NOFORCE},
- {0x2368197b, 0x00, "JMicron JMB368", AHCI_Q_NOFORCE},
- {0x611111ab, 0x00, "Marvell 88SE6111", AHCI_Q_NOFORCE | AHCI_Q_1CH |
- AHCI_Q_EDGEIS},
- {0x612111ab, 0x00, "Marvell 88SE6121", AHCI_Q_NOFORCE | AHCI_Q_2CH |
- AHCI_Q_EDGEIS | AHCI_Q_NONCQ | AHCI_Q_NOCOUNT},
- {0x614111ab, 0x00, "Marvell 88SE6141", AHCI_Q_NOFORCE | AHCI_Q_4CH |
- AHCI_Q_EDGEIS | AHCI_Q_NONCQ | AHCI_Q_NOCOUNT},
- {0x614511ab, 0x00, "Marvell 88SE6145", AHCI_Q_NOFORCE | AHCI_Q_4CH |
- AHCI_Q_EDGEIS | AHCI_Q_NONCQ | AHCI_Q_NOCOUNT},
- {0x91201b4b, 0x00, "Marvell 88SE912x", AHCI_Q_EDGEIS|AHCI_Q_NOBSYRES},
- {0x91231b4b, 0x11, "Marvell 88SE912x", AHCI_Q_NOBSYRES|AHCI_Q_ALTSIG},
- {0x91231b4b, 0x00, "Marvell 88SE912x", AHCI_Q_EDGEIS|AHCI_Q_SATA2|AHCI_Q_NOBSYRES},
- {0x91251b4b, 0x00, "Marvell 88SE9125", AHCI_Q_NOBSYRES},
- {0x91281b4b, 0x00, "Marvell 88SE9128", AHCI_Q_NOBSYRES|AHCI_Q_ALTSIG},
- {0x91301b4b, 0x00, "Marvell 88SE9130", AHCI_Q_NOBSYRES|AHCI_Q_ALTSIG},
- {0x91721b4b, 0x00, "Marvell 88SE9172", AHCI_Q_NOBSYRES},
- {0x91821b4b, 0x00, "Marvell 88SE9182", AHCI_Q_NOBSYRES},
- {0x91831b4b, 0x00, "Marvell 88SS9183", AHCI_Q_NOBSYRES},
- {0x91a01b4b, 0x00, "Marvell 88SE91Ax", AHCI_Q_NOBSYRES},
- {0x92151b4b, 0x00, "Marvell 88SE9215", AHCI_Q_NOBSYRES},
- {0x92201b4b, 0x00, "Marvell 88SE9220", AHCI_Q_NOBSYRES|AHCI_Q_ALTSIG},
- {0x92301b4b, 0x00, "Marvell 88SE9230", AHCI_Q_NOBSYRES|AHCI_Q_ALTSIG},
- {0x92351b4b, 0x00, "Marvell 88SE9235", AHCI_Q_NOBSYRES},
- {0x06201103, 0x00, "HighPoint RocketRAID 620", AHCI_Q_NOBSYRES},
- {0x06201b4b, 0x00, "HighPoint RocketRAID 620", AHCI_Q_NOBSYRES},
- {0x06221103, 0x00, "HighPoint RocketRAID 622", AHCI_Q_NOBSYRES},
- {0x06221b4b, 0x00, "HighPoint RocketRAID 622", AHCI_Q_NOBSYRES},
- {0x06401103, 0x00, "HighPoint RocketRAID 640", AHCI_Q_NOBSYRES},
- {0x06401b4b, 0x00, "HighPoint RocketRAID 640", AHCI_Q_NOBSYRES},
- {0x06441103, 0x00, "HighPoint RocketRAID 644", AHCI_Q_NOBSYRES},
- {0x06441b4b, 0x00, "HighPoint RocketRAID 644", AHCI_Q_NOBSYRES},
- {0x06411103, 0x00, "HighPoint RocketRAID 640L", AHCI_Q_NOBSYRES},
- {0x06421103, 0x00, "HighPoint RocketRAID 642L", AHCI_Q_NOBSYRES},
- {0x06451103, 0x00, "HighPoint RocketRAID 644L", AHCI_Q_NOBSYRES},
- {0x044c10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA},
- {0x044d10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA},
- {0x044e10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA},
- {0x044f10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA},
- {0x045c10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA},
- {0x045d10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA},
- {0x045e10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA},
- {0x045f10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA},
- {0x055010de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
- {0x055110de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
- {0x055210de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
- {0x055310de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
- {0x055410de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
- {0x055510de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
- {0x055610de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
- {0x055710de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
- {0x055810de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
- {0x055910de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
- {0x055A10de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
- {0x055B10de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
- {0x058410de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
- {0x07f010de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
- {0x07f110de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
- {0x07f210de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
- {0x07f310de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
- {0x07f410de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
- {0x07f510de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
- {0x07f610de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
- {0x07f710de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
- {0x07f810de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
- {0x07f910de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
- {0x07fa10de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
- {0x07fb10de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
- {0x0ad010de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
- {0x0ad110de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
- {0x0ad210de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
- {0x0ad310de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
- {0x0ad410de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
- {0x0ad510de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
- {0x0ad610de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
- {0x0ad710de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
- {0x0ad810de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
- {0x0ad910de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
- {0x0ada10de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
- {0x0adb10de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
- {0x0ab410de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
- {0x0ab510de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
- {0x0ab610de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
- {0x0ab710de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
- {0x0ab810de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
- {0x0ab910de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
- {0x0aba10de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
- {0x0abb10de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
- {0x0abc10de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
- {0x0abd10de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
- {0x0abe10de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
- {0x0abf10de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
- {0x0d8410de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
- {0x0d8510de, 0x00, "NVIDIA MCP89", AHCI_Q_NOFORCE|AHCI_Q_NOAA},
- {0x0d8610de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
- {0x0d8710de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
- {0x0d8810de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
- {0x0d8910de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
- {0x0d8a10de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
- {0x0d8b10de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
- {0x0d8c10de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
- {0x0d8d10de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
- {0x0d8e10de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
- {0x0d8f10de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
- {0x33491106, 0x00, "VIA VT8251", AHCI_Q_NOPMP|AHCI_Q_NONCQ},
- {0x62871106, 0x00, "VIA VT8251", AHCI_Q_NOPMP|AHCI_Q_NONCQ},
- {0x11841039, 0x00, "SiS 966", 0},
- {0x11851039, 0x00, "SiS 968", 0},
- {0x01861039, 0x00, "SiS 968", 0},
- {0x00000000, 0x00, NULL, 0}
-};
-
#define recovery_type spriv_field0
#define RECOVERY_NONE 0
#define RECOVERY_READ_LOG 1
#define RECOVERY_REQUEST_SENSE 2
#define recovery_slot spriv_field1
-static int force_ahci = 1;
-TUNABLE_INT("hw.ahci.force", &force_ahci);
-
-static int
-ahci_probe(device_t dev)
+int
+ahci_ctlr_setup(device_t dev)
{
- char buf[64];
- int i, valid = 0;
- uint32_t devid = pci_get_devid(dev);
- uint8_t revid = pci_get_revid(dev);
-
- /*
- * Ensure it is not a PCI bridge (some vendors use
- * the same PID and VID in PCI bridge and AHCI cards).
- */
- if (pci_get_class(dev) == PCIC_BRIDGE)
- return (ENXIO);
-
- /* Is this a possible AHCI candidate? */
- if (pci_get_class(dev) == PCIC_STORAGE &&
- pci_get_subclass(dev) == PCIS_STORAGE_SATA &&
- pci_get_progif(dev) == PCIP_STORAGE_SATA_AHCI_1_0)
- valid = 1;
- /* Is this a known AHCI chip? */
- for (i = 0; ahci_ids[i].id != 0; i++) {
- if (ahci_ids[i].id == devid &&
- ahci_ids[i].rev <= revid &&
- (valid || (force_ahci == 1 &&
- !(ahci_ids[i].quirks & AHCI_Q_NOFORCE)))) {
- /* Do not attach JMicrons with single PCI function. */
- if (pci_get_vendor(dev) == 0x197b &&
- (pci_read_config(dev, 0xdf, 1) & 0x40) == 0)
- return (ENXIO);
- snprintf(buf, sizeof(buf), "%s AHCI SATA controller",
- ahci_ids[i].name);
- device_set_desc_copy(dev, buf);
- return (BUS_PROBE_VENDOR);
+ struct ahci_controller *ctlr = device_get_softc(dev);
+ /* Clear interrupts */
+ ATA_OUTL(ctlr->r_mem, AHCI_IS, ATA_INL(ctlr->r_mem, AHCI_IS));
+ /* Configure CCC */
+ if (ctlr->ccc) {
+ ATA_OUTL(ctlr->r_mem, AHCI_CCCP, ATA_INL(ctlr->r_mem, AHCI_PI));
+ ATA_OUTL(ctlr->r_mem, AHCI_CCCC,
+ (ctlr->ccc << AHCI_CCCC_TV_SHIFT) |
+ (4 << AHCI_CCCC_CC_SHIFT) |
+ AHCI_CCCC_EN);
+ ctlr->cccv = (ATA_INL(ctlr->r_mem, AHCI_CCCC) &
+ AHCI_CCCC_INT_MASK) >> AHCI_CCCC_INT_SHIFT;
+ if (bootverbose) {
+ device_printf(dev,
+ "CCC with %dms/4cmd enabled on vector %d\n",
+ ctlr->ccc, ctlr->cccv);
}
}
- if (!valid)
- return (ENXIO);
- device_set_desc_copy(dev, "AHCI SATA controller");
- return (BUS_PROBE_VENDOR);
+ /* Enable AHCI interrupts */
+ ATA_OUTL(ctlr->r_mem, AHCI_GHC,
+ ATA_INL(ctlr->r_mem, AHCI_GHC) | AHCI_GHC_IE);
+ return (0);
}
-static int
-ahci_ata_probe(device_t dev)
+int
+ahci_ctlr_reset(device_t dev)
{
- char buf[64];
- int i;
- uint32_t devid = pci_get_devid(dev);
- uint8_t revid = pci_get_revid(dev);
+ struct ahci_controller *ctlr = device_get_softc(dev);
+ int timeout;
- if ((intptr_t)device_get_ivars(dev) >= 0)
- return (ENXIO);
- /* Is this a known AHCI chip? */
- for (i = 0; ahci_ids[i].id != 0; i++) {
- if (ahci_ids[i].id == devid &&
- ahci_ids[i].rev <= revid) {
- snprintf(buf, sizeof(buf), "%s AHCI SATA controller",
- ahci_ids[i].name);
- device_set_desc_copy(dev, buf);
- return (BUS_PROBE_VENDOR);
- }
+ /* Enable AHCI mode */
+ ATA_OUTL(ctlr->r_mem, AHCI_GHC, AHCI_GHC_AE);
+ /* Reset AHCI controller */
+ ATA_OUTL(ctlr->r_mem, AHCI_GHC, AHCI_GHC_AE|AHCI_GHC_HR);
+ for (timeout = 1000; timeout > 0; timeout--) {
+ DELAY(1000);
+ if ((ATA_INL(ctlr->r_mem, AHCI_GHC) & AHCI_GHC_HR) == 0)
+ break;
}
- device_set_desc_copy(dev, "AHCI SATA controller");
- return (BUS_PROBE_VENDOR);
+ if (timeout == 0) {
+ device_printf(dev, "AHCI controller reset failure\n");
+ return ENXIO;
+ }
+ /* Reenable AHCI mode */
+ ATA_OUTL(ctlr->r_mem, AHCI_GHC, AHCI_GHC_AE);
+ return (0);
}
-static int
+
+int
ahci_attach(device_t dev)
{
struct ahci_controller *ctlr = device_get_softc(dev);
- device_t child;
- int error, unit, speed, i;
- u_int u;
- uint32_t devid = pci_get_devid(dev);
- uint8_t revid = pci_get_revid(dev);
+ int error, i, u, speed, unit;
u_int32_t version;
+ device_t child;
ctlr->dev = dev;
- i = 0;
- while (ahci_ids[i].id != 0 &&
- (ahci_ids[i].id != devid ||
- ahci_ids[i].rev > revid))
- i++;
- ctlr->quirks = ahci_ids[i].quirks;
resource_int_value(device_get_name(dev),
device_get_unit(dev), "ccc", &ctlr->ccc);
- /* if we have a memory BAR(5) we are likely on an AHCI part */
- ctlr->r_rid = PCIR_BAR(5);
- if (!(ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
- &ctlr->r_rid, RF_ACTIVE)))
- return ENXIO;
+
/* Setup our own memory management for channels. */
ctlr->sc_iomem.rm_start = rman_get_start(ctlr->r_mem);
ctlr->sc_iomem.rm_end = rman_get_end(ctlr->r_mem);
@@ -474,13 +177,6 @@ ahci_attach(device_t dev)
rman_fini(&ctlr->sc_iomem);
return (error);
}
- pci_enable_busmaster(dev);
- /* Reset controller */
- if ((error = ahci_ctlr_reset(dev)) != 0) {
- bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
- rman_fini(&ctlr->sc_iomem);
- return (error);
- };
/* Get the HW capabilities */
version = ATA_INL(ctlr->r_mem, AHCI_VS);
ctlr->caps = ATA_INL(ctlr->r_mem, AHCI_CAP);
@@ -533,13 +229,7 @@ ahci_attach(device_t dev)
}
ahci_ctlr_setup(dev);
- /* Setup interrupts. */
- if (ahci_setup_interrupt(dev)) {
- bus_dma_tag_destroy(ctlr->dma_tag);
- bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
- rman_fini(&ctlr->sc_iomem);
- return ENXIO;
- }
+
i = 0;
for (u = ctlr->ichannels; u != 0; u >>= 1)
i += (u & 1);
@@ -619,7 +309,7 @@ ahci_attach(device_t dev)
return 0;
}
-static int
+int
ahci_detach(device_t dev)
{
struct ahci_controller *ctlr = device_get_softc(dev);
@@ -637,7 +327,6 @@ ahci_detach(device_t dev)
ctlr->irqs[i].r_irq_rid, ctlr->irqs[i].r_irq);
}
}
- pci_release_msi(dev);
bus_dma_tag_destroy(ctlr->dma_tag);
/* Free memory. */
rman_fini(&ctlr->sc_iomem);
@@ -646,109 +335,12 @@ ahci_detach(device_t dev)
return (0);
}
-static int
-ahci_ctlr_reset(device_t dev)
-{
- struct ahci_controller *ctlr = device_get_softc(dev);
- int timeout;
-
- if (pci_read_config(dev, PCIR_DEVVENDOR, 4) == 0x28298086 &&
- (pci_read_config(dev, 0x92, 1) & 0xfe) == 0x04)
- pci_write_config(dev, 0x92, 0x01, 1);
- /* Enable AHCI mode */
- ATA_OUTL(ctlr->r_mem, AHCI_GHC, AHCI_GHC_AE);
- /* Reset AHCI controller */
- ATA_OUTL(ctlr->r_mem, AHCI_GHC, AHCI_GHC_AE|AHCI_GHC_HR);
- for (timeout = 1000; timeout > 0; timeout--) {
- DELAY(1000);
- if ((ATA_INL(ctlr->r_mem, AHCI_GHC) & AHCI_GHC_HR) == 0)
- break;
- }
- if (timeout == 0) {
- device_printf(dev, "AHCI controller reset failure\n");
- return ENXIO;
- }
- /* Reenable AHCI mode */
- ATA_OUTL(ctlr->r_mem, AHCI_GHC, AHCI_GHC_AE);
- return (0);
-}
-
-static int
-ahci_ctlr_setup(device_t dev)
-{
- struct ahci_controller *ctlr = device_get_softc(dev);
- /* Clear interrupts */
- ATA_OUTL(ctlr->r_mem, AHCI_IS, ATA_INL(ctlr->r_mem, AHCI_IS));
- /* Configure CCC */
- if (ctlr->ccc) {
- ATA_OUTL(ctlr->r_mem, AHCI_CCCP, ATA_INL(ctlr->r_mem, AHCI_PI));
- ATA_OUTL(ctlr->r_mem, AHCI_CCCC,
- (ctlr->ccc << AHCI_CCCC_TV_SHIFT) |
- (4 << AHCI_CCCC_CC_SHIFT) |
- AHCI_CCCC_EN);
- ctlr->cccv = (ATA_INL(ctlr->r_mem, AHCI_CCCC) &
- AHCI_CCCC_INT_MASK) >> AHCI_CCCC_INT_SHIFT;
- if (bootverbose) {
- device_printf(dev,
- "CCC with %dms/4cmd enabled on vector %d\n",
- ctlr->ccc, ctlr->cccv);
- }
- }
- /* Enable AHCI interrupts */
- ATA_OUTL(ctlr->r_mem, AHCI_GHC,
- ATA_INL(ctlr->r_mem, AHCI_GHC) | AHCI_GHC_IE);
- return (0);
-}
-
-static int
-ahci_suspend(device_t dev)
-{
- struct ahci_controller *ctlr = device_get_softc(dev);
-
- bus_generic_suspend(dev);
- /* Disable interupts, so the state change(s) doesn't trigger */
- ATA_OUTL(ctlr->r_mem, AHCI_GHC,
- ATA_INL(ctlr->r_mem, AHCI_GHC) & (~AHCI_GHC_IE));
- return 0;
-}
-
-static int
-ahci_resume(device_t dev)
-{
- int res;
-
- if ((res = ahci_ctlr_reset(dev)) != 0)
- return (res);
- ahci_ctlr_setup(dev);
- return (bus_generic_resume(dev));
-}
-
-static int
+int
ahci_setup_interrupt(device_t dev)
{
struct ahci_controller *ctlr = device_get_softc(dev);
int i;
- ctlr->msi = 2;
- /* Process hints. */
- if (ctlr->quirks & AHCI_Q_NOMSI)
- ctlr->msi = 0;
- resource_int_value(device_get_name(dev),
- device_get_unit(dev), "msi", &ctlr->msi);
- ctlr->numirqs = 1;
- if (ctlr->msi < 0)
- ctlr->msi = 0;
- else if (ctlr->msi == 1)
- ctlr->msi = min(1, pci_msi_count(dev));
- else if (ctlr->msi > 1) {
- ctlr->msi = 2;
- ctlr->numirqs = pci_msi_count(dev);
- }
- /* Allocate MSI if needed/present. */
- if (ctlr->msi && pci_alloc_msi(dev, &ctlr->numirqs) != 0) {
- ctlr->msi = 0;
- ctlr->numirqs = 1;
- }
/* Check for single MSI vector fallback. */
if (ctlr->numirqs > 1 &&
(ATA_INL(ctlr->r_mem, AHCI_GHC) & AHCI_GHC_MRSM) != 0) {
@@ -864,9 +456,9 @@ ahci_intr_one_edge(void *data)
ctlr->interrupt[unit].function(arg);
}
-static struct resource *
+struct resource *
ahci_alloc_resource(device_t dev, device_t child, int type, int *rid,
- u_long start, u_long end, u_long count, u_int flags)
+ u_long start, u_long end, u_long count, u_int flags)
{
struct ahci_controller *ctlr = device_get_softc(dev);
struct resource *res;
@@ -915,9 +507,9 @@ ahci_alloc_resource(device_t dev, device_t child, int type, int *rid,
return (res);
}
-static int
+int
ahci_release_resource(device_t dev, device_t child, int type, int rid,
- struct resource *r)
+ struct resource *r)
{
switch (type) {
@@ -932,10 +524,10 @@ ahci_release_resource(device_t dev, device_t child, int type, int rid,
return (EINVAL);
}
-static int
+int
ahci_setup_intr(device_t dev, device_t child, struct resource *irq,
- int flags, driver_filter_t *filter, driver_intr_t *function,
- void *argument, void **cookiep)
+ int flags, driver_filter_t *filter, driver_intr_t *function,
+ void *argument, void **cookiep)
{
struct ahci_controller *ctlr = device_get_softc(dev);
int unit = (intptr_t)device_get_ivars(child);
@@ -949,9 +541,9 @@ ahci_setup_intr(device_t dev, device_t child, struct resource *irq,
return (0);
}
-static int
+int
ahci_teardown_intr(device_t dev, device_t child, struct resource *irq,
- void *cookie)
+ void *cookie)
{
struct ahci_controller *ctlr = device_get_softc(dev);
int unit = (intptr_t)device_get_ivars(child);
@@ -961,7 +553,7 @@ ahci_teardown_intr(device_t dev, device_t child, struct resource *irq,
return (0);
}
-static int
+int
ahci_print_child(device_t dev, device_t child)
{
int retval, channel;
@@ -974,7 +566,7 @@ ahci_print_child(device_t dev, device_t child)
return (retval);
}
-static int
+int
ahci_child_location_str(device_t dev, device_t child, char *buf,
size_t buflen)
{
@@ -986,7 +578,7 @@ ahci_child_location_str(device_t dev, device_t child, char *buf,
return (0);
}
-static bus_dma_tag_t
+bus_dma_tag_t
ahci_get_dma_tag(device_t dev, device_t child)
{
struct ahci_controller *ctlr = device_get_softc(dev);
@@ -994,51 +586,6 @@ ahci_get_dma_tag(device_t dev, device_t child)
return (ctlr->dma_tag);
}
-devclass_t ahci_devclass;
-static device_method_t ahci_methods[] = {
- DEVMETHOD(device_probe, ahci_probe),
- DEVMETHOD(device_attach, ahci_attach),
- DEVMETHOD(device_detach, ahci_detach),
- DEVMETHOD(device_suspend, ahci_suspend),
- DEVMETHOD(device_resume, ahci_resume),
- DEVMETHOD(bus_print_child, ahci_print_child),
- DEVMETHOD(bus_alloc_resource, ahci_alloc_resource),
- DEVMETHOD(bus_release_resource, ahci_release_resource),
- DEVMETHOD(bus_setup_intr, ahci_setup_intr),
- DEVMETHOD(bus_teardown_intr,ahci_teardown_intr),
- DEVMETHOD(bus_child_location_str, ahci_child_location_str),
- DEVMETHOD(bus_get_dma_tag, ahci_get_dma_tag),
- { 0, 0 }
-};
-static driver_t ahci_driver = {
- "ahci",
- ahci_methods,
- sizeof(struct ahci_controller)
-};
-DRIVER_MODULE(ahci, pci, ahci_driver, ahci_devclass, 0, 0);
-static device_method_t ahci_ata_methods[] = {
- DEVMETHOD(device_probe, ahci_ata_probe),
- DEVMETHOD(device_attach, ahci_attach),
- DEVMETHOD(device_detach, ahci_detach),
- DEVMETHOD(device_suspend, ahci_suspend),
- DEVMETHOD(device_resume, ahci_resume),
- DEVMETHOD(bus_print_child, ahci_print_child),
- DEVMETHOD(bus_alloc_resource, ahci_alloc_resource),
- DEVMETHOD(bus_release_resource, ahci_release_resource),
- DEVMETHOD(bus_setup_intr, ahci_setup_intr),
- DEVMETHOD(bus_teardown_intr,ahci_teardown_intr),
- DEVMETHOD(bus_child_location_str, ahci_child_location_str),
- { 0, 0 }
-};
-static driver_t ahci_ata_driver = {
- "ahci",
- ahci_ata_methods,
- sizeof(struct ahci_controller)
-};
-DRIVER_MODULE(ahci, atapci, ahci_ata_driver, ahci_devclass, 0, 0);
-MODULE_VERSION(ahci, 1);
-MODULE_DEPEND(ahci, cam, 1, 1, 1);
-
static int
ahci_ch_probe(device_t dev)
{
@@ -1061,6 +608,10 @@ ahci_ch_attach(device_t dev)
ch->caps = ctlr->caps;
ch->caps2 = ctlr->caps2;
ch->quirks = ctlr->quirks;
+ ch->vendorid = ctlr->vendorid;
+ ch->deviceid = ctlr->deviceid;
+ ch->subvendorid = ctlr->subvendorid;
+ ch->subdeviceid = ctlr->subdeviceid;
ch->numslots = ((ch->caps & AHCI_CAP_NCS) >> AHCI_CAP_NCS_SHIFT) + 1;
mtx_init(&ch->mtx, "AHCI channel lock", NULL, MTX_DEF);
resource_int_value(device_get_name(dev),
@@ -1069,12 +620,8 @@ ahci_ch_attach(device_t dev)
if (ch->pm_level > 3)
callout_init_mtx(&ch->pm_timer, &ch->mtx, 0);
callout_init_mtx(&ch->reset_timer, &ch->mtx, 0);
- /* Limit speed for my onboard JMicron external port.
- * It is not eSATA really. */
- if (pci_get_devid(ctlr->dev) == 0x2363197b &&
- pci_get_subvendor(ctlr->dev) == 0x1043 &&
- pci_get_subdevice(ctlr->dev) == 0x81e4 &&
- ch->unit == 0)
+ /* JMicron external ports (0) sometimes limited */
+ if ((ctlr->quirks & AHCI_Q_SATA1_UNIT0) && ch->unit == 0)
sata_rev = 1;
if (ch->quirks & AHCI_Q_SATA2)
sata_rev = 2;
@@ -1979,7 +1526,7 @@ ahci_execute_transaction(struct ahci_slot *slot)
}
/* Workaround for ATI SB600/SB700 chipsets. */
if (ccb->ccb_h.target_id == 15 &&
- pci_get_vendor(device_get_parent(dev)) == 0x1002 &&
+ (ch->quirks & AHCI_Q_ATI_PMP_BUG) &&
(ATA_INL(ch->r_mem, AHCI_P_IS) & AHCI_P_IX_IPM)) {
et = AHCI_ERR_TIMEOUT;
break;
@@ -3085,12 +2632,12 @@ ahciaction(struct cam_sim *sim, union ccb *ccb)
cpi->protocol_version = PROTO_VERSION_UNSPECIFIED;
cpi->maxio = MAXPHYS;
/* ATI SB600 can't handle 256 sectors with FPDMA (NCQ). */
- if (pci_get_devid(parent) == 0x43801002)
+ if (ch->quirks & AHCI_Q_MAXIO_64K)
cpi->maxio = min(cpi->maxio, 128 * 512);
- cpi->hba_vendor = pci_get_vendor(parent);
- cpi->hba_device = pci_get_device(parent);
- cpi->hba_subvendor = pci_get_subvendor(parent);
- cpi->hba_subdevice = pci_get_subdevice(parent);
+ cpi->hba_vendor = ch->vendorid;
+ cpi->hba_device = ch->deviceid;
+ cpi->hba_subvendor = ch->subvendorid;
+ cpi->hba_subdevice = ch->subdeviceid;
cpi->ccb_h.status = CAM_REQ_CMP;
break;
}
@@ -3117,3 +2664,5 @@ ahcipoll(struct cam_sim *sim)
ahci_reset_to(ch->dev);
}
}
+MODULE_VERSION(ahci, 1);
+MODULE_DEPEND(ahci, cam, 1, 1, 1);