[Midnightbsd-cvs] src: dev/ata: save wip
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Mon Dec 1 12:43:52 EST 2008
Log Message:
-----------
save wip
Modified Files:
--------------
src/sys/dev/ata:
ata-chipset.c (r1.11 -> r1.12)
atapi-cd.c (r1.4 -> r1.5)
-------------- next part --------------
Index: ata-chipset.c
===================================================================
RCS file: /home/cvs/src/sys/dev/ata/ata-chipset.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -L sys/dev/ata/ata-chipset.c -L sys/dev/ata/ata-chipset.c -u -r1.11 -r1.12
--- sys/dev/ata/ata-chipset.c
+++ sys/dev/ata/ata-chipset.c
@@ -55,10 +55,12 @@
static int ata_generic_chipinit(device_t dev);
static void ata_generic_intr(void *data);
static void ata_generic_setmode(device_t dev, int mode);
-static void ata_sata_phy_enable(struct ata_channel *ch);
+static void ata_sata_phy_check_events(device_t dev);
static void ata_sata_phy_event(void *context, int dummy);
+static int ata_sata_phy_reset(device_t dev);
static int ata_sata_connect(struct ata_channel *ch);
static void ata_sata_setmode(device_t dev, int mode);
+static int ata_request2fis_h2d(struct ata_request *request, u_int8_t *fis);
static int ata_ahci_chipinit(device_t dev);
static int ata_ahci_allocate(device_t dev);
static int ata_ahci_status(device_t dev);
@@ -98,7 +100,7 @@
static void ata_intel_new_setmode(device_t dev, int mode);
static int ata_intel_31244_allocate(device_t dev);
static int ata_intel_31244_status(device_t dev);
-static int ata_intel_31244_command(struct ata_request *request);
+static void ata_intel_31244_tf_write(struct ata_request *request);
static void ata_intel_31244_reset(device_t dev);
static int ata_ite_chipinit(device_t dev);
static void ata_ite_setmode(device_t dev, int mode);
@@ -120,6 +122,8 @@
static void ata_marvell_edma_dmainit(device_t dev);
static int ata_national_chipinit(device_t dev);
static void ata_national_setmode(device_t dev, int mode);
+static int ata_netcell_chipinit(device_t dev);
+static int ata_netcell_allocate(device_t dev);
static int ata_nvidia_chipinit(device_t dev);
static int ata_nvidia_allocate(device_t dev);
static int ata_nvidia_status(device_t dev);
@@ -140,6 +144,7 @@
static int ata_promise_mio_command(struct ata_request *request);
static void ata_promise_mio_reset(device_t dev);
static void ata_promise_mio_dmainit(device_t dev);
+static void ata_promise_mio_setprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error);
static void ata_promise_mio_setmode(device_t dev, int mode);
static void ata_promise_sx4_intr(void *data);
static int ata_promise_sx4_command(struct ata_request *request);
@@ -148,6 +153,8 @@
static void ata_promise_next_hpkt(struct ata_pci_controller *ctlr);
static int ata_serverworks_chipinit(device_t dev);
static int ata_serverworks_allocate(device_t dev);
+static void ata_serverworks_tf_read(struct ata_request *request);
+static void ata_serverworks_tf_write(struct ata_request *request);
static void ata_serverworks_setmode(device_t dev, int mode);
static int ata_sii_chipinit(device_t dev);
static int ata_cmd_allocate(device_t dev);
@@ -157,6 +164,13 @@
static int ata_sii_status(device_t dev);
static void ata_sii_reset(device_t dev);
static void ata_sii_setmode(device_t dev, int mode);
+static int ata_siiprb_allocate(device_t dev);
+static int ata_siiprb_status(device_t dev);
+static int ata_siiprb_begin_transaction(struct ata_request *request);
+static int ata_siiprb_end_transaction(struct ata_request *request);
+static void ata_siiprb_reset(device_t dev);
+static void ata_siiprb_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error);
+static void ata_siiprb_dmainit(device_t dev);
static int ata_sis_chipinit(device_t dev);
static int ata_sis_allocate(device_t dev);
static void ata_sis_reset(device_t dev);
@@ -164,8 +178,10 @@
static int ata_via_chipinit(device_t dev);
static int ata_via_allocate(device_t dev);
static void ata_via_reset(device_t dev);
+static void ata_via_setmode(device_t dev, int mode);
static void ata_via_southbridge_fixup(device_t dev);
static void ata_via_family_setmode(device_t dev, int mode);
+static void ata_set_desc(device_t dev);
static struct ata_chip_id *ata_match_chip(device_t dev, struct ata_chip_id *index);
static struct ata_chip_id *ata_find_chip(device_t dev, struct ata_chip_id *index, int slot);
static int ata_setup_interrupt(device_t dev);
@@ -183,8 +199,10 @@
ata_generic_ident(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(dev);
+ char buffer[64];
- device_set_desc(dev, "GENERIC ATA controller");
+ sprintf(buffer, "%s ATA controller", ata_pcivendor2str(dev));
+ device_set_desc_copy(dev, buffer);
ctlr->chipinit = ata_generic_chipinit;
return 0;
}
@@ -229,33 +247,39 @@
* SATA support functions
*/
static void
-ata_sata_phy_enable(struct ata_channel *ch)
+ata_sata_phy_check_events(device_t dev)
{
- int loop, retry;
+ struct ata_channel *ch = device_get_softc(dev);
+ u_int32_t error = ATA_IDX_INL(ch, ATA_SERROR);
- if ((ATA_IDX_INL(ch, ATA_SCONTROL) & ATA_SC_DET_MASK) == ATA_SC_DET_IDLE) {
- ata_sata_connect(ch);
- return;
- }
+ /* clear error bits/interrupt */
+ ATA_IDX_OUTL(ch, ATA_SERROR, error);
- for (retry = 0; retry < 10; retry++) {
- for (loop = 0; loop < 10; loop++) {
- ATA_IDX_OUTL(ch, ATA_SCONTROL, ATA_SC_DET_RESET);
- ata_udelay(100);
- if ((ATA_IDX_INL(ch, ATA_SCONTROL) &
- ATA_SC_DET_MASK) == ATA_SC_DET_RESET)
- break;
- }
- ata_udelay(5000);
- for (loop = 0; loop < 10; loop++) {
- ATA_IDX_OUTL(ch, ATA_SCONTROL, ATA_SC_DET_IDLE |
- ATA_SC_IPM_DIS_PARTIAL |
- ATA_SC_IPM_DIS_SLUMBER);
- ata_udelay(100);
- if ((ATA_IDX_INL(ch, ATA_SCONTROL) & ATA_SC_DET_MASK) == 0) {
- ata_sata_connect(ch);
- return;
+ /* do we have any events flagged ? */
+ if (error) {
+ struct ata_connect_task *tp;
+ u_int32_t status = ATA_IDX_INL(ch, ATA_SSTATUS);
+
+ /* if we have a connection event deal with it */
+ if ((error & ATA_SE_PHY_CHANGED) &&
+ (tp = (struct ata_connect_task *)
+ malloc(sizeof(struct ata_connect_task),
+ M_ATA, M_NOWAIT | M_ZERO))) {
+
+ if (((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN1) ||
+ ((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN2)) {
+ if (bootverbose)
+ device_printf(ch->dev, "CONNECT requested\n");
+ tp->action = ATA_C_ATTACH;
}
+ else {
+ if (bootverbose)
+ device_printf(ch->dev, "DISCONNECT requested\n");
+ tp->action = ATA_C_DETACH;
+ }
+ tp->dev = ch->dev;
+ TASK_INIT(&tp->task, 0, ata_sata_phy_event, tp);
+ taskqueue_enqueue(taskqueue_thread, &tp->task);
}
}
}
@@ -272,7 +296,7 @@
if (tp->action == ATA_C_ATTACH) {
if (bootverbose)
device_printf(tp->dev, "CONNECTED\n");
- ata_sata_connect(ch);
+ ATA_RESET(tp->dev);
ata_identify(tp->dev);
}
if (tp->action == ATA_C_DETACH) {
@@ -293,6 +317,36 @@
}
static int
+ata_sata_phy_reset(device_t dev)
+{
+ struct ata_channel *ch = device_get_softc(dev);
+ int loop, retry;
+
+ if ((ATA_IDX_INL(ch, ATA_SCONTROL) & ATA_SC_DET_MASK) == ATA_SC_DET_IDLE)
+ return ata_sata_connect(ch);
+
+ for (retry = 0; retry < 10; retry++) {
+ for (loop = 0; loop < 10; loop++) {
+ ATA_IDX_OUTL(ch, ATA_SCONTROL, ATA_SC_DET_RESET);
+ ata_udelay(100);
+ if ((ATA_IDX_INL(ch, ATA_SCONTROL) & ATA_SC_DET_MASK) ==
+ ATA_SC_DET_RESET)
+ break;
+ }
+ ata_udelay(5000);
+ for (loop = 0; loop < 10; loop++) {
+ ATA_IDX_OUTL(ch, ATA_SCONTROL, ATA_SC_DET_IDLE |
+ ATA_SC_IPM_DIS_PARTIAL |
+ ATA_SC_IPM_DIS_SLUMBER);
+ ata_udelay(100);
+ if ((ATA_IDX_INL(ch, ATA_SCONTROL) & ATA_SC_DET_MASK) == 0)
+ return ata_sata_connect(ch);
+ }
+ }
+ return 0;
+}
+
+static int
ata_sata_connect(struct ata_channel *ch)
{
u_int32_t status;
@@ -311,6 +365,8 @@
device_printf(ch->dev, "SATA connect status=%08x\n", status);
return 0;
}
+ if (bootverbose)
+ device_printf(ch->dev, "SATA connect time=%dms\n", timeout * 10);
/* clear SATA error register */
ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR));
@@ -373,32 +429,72 @@
}
}
+static int
+ata_request2fis_h2d(struct ata_request *request, u_int8_t *fis)
+{
+ struct ata_device *atadev = device_get_softc(request->dev);
+
+ if (request->flags & ATA_R_ATAPI) {
+ fis[0] = 0x27; /* host to device */
+ fis[1] = 0x80; /* command FIS (note PM goes here) */
+ fis[2] = ATA_PACKET_CMD;
+ if (request->flags & (ATA_R_READ | ATA_R_WRITE))
+ fis[3] = ATA_F_DMA;
+ else {
+ fis[5] = request->transfersize;
+ fis[6] = request->transfersize >> 8;
+ }
+ fis[7] = ATA_D_LBA | atadev->unit;
+ fis[15] = ATA_A_4BIT;
+ return 20;
+ }
+ else {
+ ata_modify_if_48bit(request);
+ fis[0] = 0x27; /* host to device */
+ fis[1] = 0x80; /* command FIS (note PM goes here) */
+ fis[2] = request->u.ata.command;
+ fis[3] = request->u.ata.feature;
+ fis[4] = request->u.ata.lba;
+ fis[5] = request->u.ata.lba >> 8;
+ fis[6] = request->u.ata.lba >> 16;
+ fis[7] = ATA_D_LBA | atadev->unit;
+ if (!(atadev->flags & ATA_D_48BIT_ACTIVE))
+ fis[7] |= (request->u.ata.lba >> 24 & 0x0f);
+ fis[8] = request->u.ata.lba >> 24;
+ fis[9] = request->u.ata.lba >> 32;
+ fis[10] = request->u.ata.lba >> 40;
+ fis[11] = request->u.ata.feature >> 8;
+ fis[12] = request->u.ata.count;
+ fis[13] = request->u.ata.count >> 8;
+ fis[15] = ATA_A_4BIT;
+ return 20;
+ }
+ return 0;
+}
+
/*
- * AHCI v1.0 compliant SATA chipset support functions
+ * AHCI v1.x compliant SATA chipset support functions
*/
-struct ata_ahci_dma_prd {
- u_int64_t dba;
- u_int32_t reserved;
- u_int32_t dbc; /* 0 based */
-#define ATA_AHCI_PRD_MASK 0x003fffff /* max 4MB */
-#define ATA_AHCI_PRD_IPC (1<<31)
-} __packed;
-
-struct ata_ahci_cmd_tab {
- u_int8_t cfis[64];
- u_int8_t acmd[32];
- u_int8_t reserved[32];
- struct ata_ahci_dma_prd prd_tab[16];
-} __packed;
+int
+ata_ahci_ident(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+ char buffer[64];
-struct ata_ahci_cmd_list {
- u_int16_t cmd_flags;
- u_int16_t prd_length; /* PRD entries */
- u_int32_t bytecount;
- u_int64_t cmd_table_phys; /* 128byte aligned */
-} __packed;
+ /* 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;
+}
static int
ata_ahci_chipinit(device_t dev)
@@ -406,9 +502,26 @@
struct ata_pci_controller *ctlr = device_get_softc(dev);
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))
+ return ENXIO;
+ }
+ else
+ device_printf(dev, "AHCI called from vendor specific driver\n");
+
+ /* 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_INL(ctlr->r_res2, ATA_AHCI_GHC) | ATA_AHCI_GHC_HR);
+ ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, ATA_AHCI_GHC_HR);
DELAY(1000000);
if (ATA_INL(ctlr->r_res2, ATA_AHCI_GHC) & ATA_AHCI_GHC_HR) {
bus_release_resource(dev, ctlr->r_type2, ctlr->r_rid2, ctlr->r_res2);
@@ -416,12 +529,13 @@
return ENXIO;
}
- /* enable AHCI mode */
- ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC,
- ATA_INL(ctlr->r_res2, ATA_AHCI_GHC) | ATA_AHCI_GHC_AE);
+ /* reenable AHCI mode */
+ ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, ATA_AHCI_GHC_AE);
/* get the number of HW channels */
- ctlr->channels = (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_NPMASK)+1;
+ ctlr->channels =
+ MAX(flsl(ATA_INL(ctlr->r_res2, ATA_AHCI_PI)),
+ (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_NPMASK) + 1);
/* clear interrupts */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_IS, ATA_INL(ctlr->r_res2, ATA_AHCI_IS));
@@ -444,7 +558,8 @@
device_printf(dev,
"AHCI Version %x%x.%x%x controller with %d ports detected\n",
(version >> 24) & 0xff, (version >> 16) & 0xff,
- (version >> 8) & 0xff, version & 0xff, ctlr->channels);
+ (version >> 8) & 0xff, version & 0xff,
+ (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_NPMASK) + 1);
return 0;
}
@@ -453,17 +568,8 @@
{
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);
-
- /* setup legacy cruft we need */
- ch->r_io[ATA_CYL_LSB].res = ctlr->r_res2;
- ch->r_io[ATA_CYL_LSB].offset = ATA_AHCI_P_SIG + 2 + offset;
- ch->r_io[ATA_CYL_MSB].res = ctlr->r_res2;
- ch->r_io[ATA_CYL_MSB].offset = ATA_AHCI_P_SIG + 3 + offset;
- ch->r_io[ATA_STATUS].res = ctlr->r_res2;
- ch->r_io[ATA_STATUS].offset = ATA_AHCI_P_TFD + offset;
- ch->r_io[ATA_ALTSTAT].res = ctlr->r_res2;
- ch->r_io[ATA_ALTSTAT].offset = ATA_AHCI_P_TFD + offset;
+ u_int64_t work;
+ int offset = ch->unit << 7;
/* set the SATA resources */
ch->r_io[ATA_SSTATUS].res = ctlr->r_res2;
@@ -480,14 +586,14 @@
ch->hw.end_transaction = ata_ahci_end_transaction;
ch->hw.command = NULL; /* not used here */
- /* setup the work areas */
- ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLB + offset,
- ch->dma->work_bus + ATA_AHCI_CL_OFFSET);
- ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLBU + offset, 0x00000000);
-
- ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FB + offset,
- ch->dma->work_bus + ATA_AHCI_FB_OFFSET);
- ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBU + offset, 0x00000000);
+ /* 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);
/* enable wanted port interrupts */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IE + offset,
@@ -536,41 +642,33 @@
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IS + offset, istatus);
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_SERR + offset, error);
- /* do we have cold connect surprise */
- if (istatus & ATA_AHCI_P_IX_CPD) {
- printf("ata_ahci_status status=%08x sstatus=%08x error=%08x\n",
- istatus, sstatus, error);
- }
+ /* do we have any PHY events ? */
+ /* XXX SOS check istatus phy bits */
+ ata_sata_phy_check_events(dev);
- /* check for and handle connect events */
- if ((istatus & ATA_AHCI_P_IX_PC) &&
- (tp = (struct ata_connect_task *)
- malloc(sizeof(struct ata_connect_task),
- M_ATA, M_NOWAIT | M_ZERO))) {
+ /* do we have a potentially hanging engine to take care of? */
+ if ((istatus & 0x78400050) && (cstatus & (1 << tag))) {
- if (bootverbose)
- device_printf(ch->dev, "CONNECT requested\n");
- tp->action = ATA_C_ATTACH;
- tp->dev = ch->dev;
- TASK_INIT(&tp->task, 0, ata_sata_phy_event, tp);
- taskqueue_enqueue(taskqueue_thread, &tp->task);
- }
+ u_int32_t cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset);
+ int timeout = 0;
- /* check for and handle disconnect events */
- else if ((istatus & ATA_AHCI_P_IX_PRC) &&
- !((sstatus & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN1 ||
- (sstatus & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN2) &&
- (tp = (struct ata_connect_task *)
- malloc(sizeof(struct ata_connect_task),
- M_ATA, M_NOWAIT | M_ZERO))) {
+ /* 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));
- if (bootverbose)
- device_printf(ch->dev, "DISCONNECT requested\n");
- tp->action = ATA_C_DETACH;
- tp->dev = ch->dev;
- TASK_INIT(&tp->task, 0, ata_sata_phy_event, tp);
- taskqueue_enqueue(taskqueue_thread, &tp->task);
- }
+ /* XXX SOS this is not entirely wrong */
+ do {
+ DELAY(1000);
+ if (timeout++ > 500) {
+ 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));
/* do we have any device action ? */
if (!(issued & (1 << tag)))
@@ -603,9 +701,10 @@
struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
struct ata_ahci_cmd_tab *ctp;
struct ata_ahci_cmd_list *clp;
+ int offset = ch->unit << 7;
int tag = 0, 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 * tag));
@@ -658,28 +757,36 @@
/* clear eventual ACTIVE bit */
ATA_IDX_OUTL(ch, ATA_SACTIVE, ATA_IDX_INL(ch, ATA_SACTIVE) & (1 << tag));
- /* issue the command */
- ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CI + (ch->unit << 7), (1 << 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);
- /* rgb - handle ATA_DEVICE_RESET requests */
+ /* issue command to controller */
+ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CI + offset, (1 << 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--);
- request->status = tf_data;
- if (timeout <= 0) {
- device_printf(request->dev, "ATA_DEVICE_RESET timeout\n");
- /* should probably do softreset */
- }
- if (request->status & ATA_S_ERROR) {
- request->error = tf_data >> 8;
- ata_ahci_restart_engine(ch->dev);
- }
- return ATA_OP_FINISHED;
+ 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;
}
}
@@ -697,13 +804,14 @@
struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
struct ata_ahci_cmd_list *clp;
u_int32_t tf_data;
+ int offset = ch->unit << 7;
int tag = 0;
/* kill the timeout */
callout_stop(&request->callout);
/* get status */
- tf_data = ATA_INL(ctlr->r_res2, ATA_AHCI_P_TFD + (ch->unit << 7));
+ tf_data = ATA_INL(ctlr->r_res2, ATA_AHCI_P_TFD + offset);
request->status = tf_data;
/* if error status get details */
@@ -768,10 +876,11 @@
timeout = 0;
do {
DELAY(1000);
- if (timeout++ > 500)
+ if (timeout++ > 500) {
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);
/* issue Command List Override if supported */
@@ -782,33 +891,53 @@
timeout = 0;
do {
DELAY(1000);
- if (timeout++ > 500)
+ if (timeout++ > 500) {
device_printf(dev, "executing CLO failed\n");
break;
}
+ }
while (ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD+offset)&ATA_AHCI_P_CMD_CLO);
}
- /* spin up device */
- ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, ATA_AHCI_P_CMD_SUD);
+ /* reset PHY and decide what is present */
+ if (ata_sata_phy_reset(dev)) {
- ata_sata_phy_enable(ch);
+ /* 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));
- /* 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));
+ /* clear SATA error register */
+ ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR));
- /* start operations on this channel */
- /* rgb - add ATAPI cmd */
- if (ch->devices & ATA_ATAPI_MASTER)
- ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset,
- (ATA_AHCI_P_CMD_ACTIVE | ATA_AHCI_P_CMD_FRE |
- ATA_AHCI_P_CMD_ATAPI |
- ATA_AHCI_P_CMD_POD | ATA_AHCI_P_CMD_SUD | ATA_AHCI_P_CMD_ST));
- else
- ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset,
- (ATA_AHCI_P_CMD_ACTIVE | ATA_AHCI_P_CMD_FRE |
- ATA_AHCI_P_CMD_POD | ATA_AHCI_P_CMD_SUD | ATA_AHCI_P_CMD_ST));
+ /* start operations on this channel */
+ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset,
+ (ATA_AHCI_P_CMD_ACTIVE | ATA_AHCI_P_CMD_FRE |
+ ATA_AHCI_P_CMD_POD | ATA_AHCI_P_CMD_SUD | ATA_AHCI_P_CMD_ST));
+
+ signature = ATA_INL(ctlr->r_res2, ATA_AHCI_P_SIG + offset);
+ 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;
+ device_printf(ch->dev, "Portmultipliers not supported yet\n");
+ ch->devices = 0;
+ break;
+ case 0xeb140101:
+ ch->devices = ATA_ATAPI_MASTER;
+ break;
+ default: /* SOS XXX */
+ if (bootverbose)
+ device_printf(ch->dev, "No signature, asuming disk device\n");
+ ch->devices = ATA_ATA_MASTER;
+ }
+ }
+ if (bootverbose)
+ device_printf(dev, "ahci_reset devices=0x%b\n", ch->devices,
+ "\20\4ATAPI_SLAVE\3ATAPI_MASTER\2ATA_SLAVE\1ATA_MASTER");
}
static void
@@ -824,12 +953,14 @@
prd[i].dbc = htole32((segs[i].ds_len - 1) & ATA_AHCI_PRD_MASK);
}
}
+ KASSERT(nsegs <= ATA_DMA_ENTRIES, ("too many DMA segment entries\n"));
args->nsegs = nsegs;
}
static 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);
@@ -837,86 +968,20 @@
/* 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(u_int8_t *fis, struct ata_request *request)
+ata_ahci_setup_fis(struct ata_ahci_cmd_tab *ctp, struct ata_request *request)
{
- struct ata_device *atadev = device_get_softc(request->dev);
- int idx = 0;
-
- /* XXX SOS add ATAPI commands support later */
- ata_modify_if_48bit(request);
-
- fis[idx++] = 0x27; /* host to device */
- fis[idx++] = 0x80; /* command FIS (note PM goes here) */
-
- /* rgb - add atapi request */
- switch (request->flags & ATA_R_ATAPI) {
-
- default:
- fis[idx++] = request->u.ata.command;
- fis[idx++] = request->u.ata.feature;
-
- fis[idx++] = request->u.ata.lba;
- fis[idx++] = request->u.ata.lba >> 8;
- fis[idx++] = request->u.ata.lba >> 16;
- fis[idx] = ATA_D_LBA | atadev->unit;
- if (atadev->flags & ATA_D_48BIT_ACTIVE)
- idx++;
- else
- fis[idx++] |= (request->u.ata.lba >> 24 & 0x0f);
-
- fis[idx++] = request->u.ata.lba >> 24;
- fis[idx++] = request->u.ata.lba >> 32;
- fis[idx++] = request->u.ata.lba >> 40;
- fis[idx++] = request->u.ata.feature >> 8;
-
- fis[idx++] = request->u.ata.count;
- fis[idx++] = request->u.ata.count >> 8;
- fis[idx++] = 0x00;
- fis[idx++] = ATA_A_4BIT;
-
- fis[idx++] = 0x00;
- fis[idx++] = 0x00;
- fis[idx++] = 0x00;
- fis[idx++] = 0x00;
- break;
-
- case ATA_R_ATAPI:
- fis[idx++] = ATA_PACKET_CMD;
- if (request->flags & ATA_R_DMA) {
- fis[idx++] = ATA_F_DMA;
- fis[idx++] = 0x00;
- fis[idx++] = 0x00;
- fis[idx++] = 0x00;
+ bzero(ctp->cfis, 64);
+ if (request->flags & ATA_R_ATAPI) {
+ bzero(ctp->acmd, 32);
+ bcopy(request->u.atapi.ccb, ctp->acmd, 16);
}
- else {
- fis[idx++] = 0x00;
- fis[idx++] = 0x00;
- fis[idx++] = request->transfersize;
- fis[idx++] = request->transfersize >> 8;
- }
- fis[idx++] = atadev->unit;
-
- fis[idx++] = 0x00;
- fis[idx++] = 0x00;
- fis[idx++] = 0x00;
- fis[idx++] = 0x00;
- fis[idx++] = 0x00;
- fis[idx++] = 0x00;
- fis[idx++] = 0x00;
- fis[idx++] = ATA_A_4BIT;
-
- fis[idx++] = 0x00;
- fis[idx++] = 0x00;
- fis[idx++] = 0x00;
- fis[idx++] = 0x00;
- break;
- }
-
- return idx;
+ return ata_request2fis_h2d(request, &ctp->cfis[0]);
}
@@ -927,7 +992,6 @@
ata_acard_ident(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(dev);
- struct ata_chip_id *idx;
static struct ata_chip_id ids[] =
{{ ATA_ATP850R, 0, ATPOLD, 0x00, ATA_UDMA2, "ATP850" },
{ ATA_ATP860A, 0, 0, 0x00, ATA_UDMA4, "ATP860A" },
@@ -935,15 +999,11 @@
{ ATA_ATP865A, 0, 0, 0x00, ATA_UDMA6, "ATP865A" },
{ ATA_ATP865R, 0, 0, 0x00, ATA_UDMA6, "ATP865R" },
{ 0, 0, 0, 0, 0, 0}};
- char buffer[64];
- if (!(idx = ata_match_chip(dev, ids)))
+ if (!(ctlr->chip = ata_match_chip(dev, ids)))
return ENXIO;
- sprintf(buffer, "Acard %s %s controller",
- idx->text, ata_mode2str(idx->max_dma));
- device_set_desc_copy(dev, buffer);
- ctlr->chip = idx;
+ ata_set_desc(dev);
ctlr->chipinit = ata_acard_chipinit;
return 0;
}
@@ -1091,27 +1151,22 @@
ata_ali_ident(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(dev);
- struct ata_chip_id *idx;
static struct ata_chip_id ids[] =
{{ ATA_ALI_5289, 0x00, 2, ALISATA, ATA_SA150, "M5289" },
+ { ATA_ALI_5288, 0x00, 4, ALISATA, ATA_SA300, "M5288" },
{ ATA_ALI_5287, 0x00, 4, ALISATA, ATA_SA150, "M5287" },
{ ATA_ALI_5281, 0x00, 2, ALISATA, ATA_SA150, "M5281" },
- { ATA_ALI_5288, 0x00, 4, ALISATA, ATA_SA300, "M5288" },
{ ATA_ALI_5229, 0xc5, 0, ALINEW, ATA_UDMA6, "M5229" },
{ ATA_ALI_5229, 0xc4, 0, ALINEW, ATA_UDMA5, "M5229" },
{ ATA_ALI_5229, 0xc2, 0, ALINEW, ATA_UDMA4, "M5229" },
{ ATA_ALI_5229, 0x20, 0, ALIOLD, ATA_UDMA2, "M5229" },
{ ATA_ALI_5229, 0x00, 0, ALIOLD, ATA_WDMA2, "M5229" },
{ 0, 0, 0, 0, 0, 0}};
- char buffer[64];
- if (!(idx = ata_match_chip(dev, ids)))
+ if (!(ctlr->chip = ata_match_chip(dev, ids)))
return ENXIO;
- sprintf(buffer, "AcerLabs %s %s controller",
- idx->text, ata_mode2str(idx->max_dma));
- device_set_desc_copy(dev, buffer);
- ctlr->chip = idx;
+ ata_set_desc(dev);
ctlr->chipinit = ata_ali_chipinit;
return 0;
}
@@ -1130,12 +1185,10 @@
ctlr->allocate = ata_ali_sata_allocate;
ctlr->setmode = ata_sata_setmode;
- /* if we have a memory resource we can likely do AHCI */
- 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 ata_ahci_chipinit(dev);
+ /* AHCI mode is correctly supported only on the ALi 5288. */
+ if ((ctlr->chip->chipid == ATA_ALI_5288) &&
+ (ata_ahci_chipinit(dev) != ENXIO))
+ return 0;
/* enable PCI interrupt */
pci_write_config(dev, PCIR_COMMAND,
@@ -1335,7 +1388,6 @@
ata_amd_ident(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(dev);
- struct ata_chip_id *idx;
static struct ata_chip_id ids[] =
{{ ATA_AMD756, 0x00, AMDNVIDIA, 0x00, ATA_UDMA4, "756" },
{ ATA_AMD766, 0x00, AMDNVIDIA, AMDCABLE|AMDBUG, ATA_UDMA5, "766" },
@@ -1343,15 +1395,11 @@
{ ATA_AMD8111, 0x00, AMDNVIDIA, AMDCABLE, ATA_UDMA6, "8111" },
{ ATA_AMD5536, 0x00, AMDNVIDIA, 0x00, ATA_UDMA5, "CS5536" },
{ 0, 0, 0, 0, 0, 0}};
- char buffer[64];
- if (!(idx = ata_match_chip(dev, ids)))
+ if (!(ctlr->chip = ata_match_chip(dev, ids)))
return ENXIO;
- sprintf(buffer, "AMD %s %s controller",
- idx->text, ata_mode2str(idx->max_dma));
- device_set_desc_copy(dev, buffer);
- ctlr->chip = idx;
+ ata_set_desc(dev);
ctlr->chipinit = ata_amd_chipinit;
return 0;
}
@@ -1382,7 +1430,6 @@
ata_ati_ident(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(dev);
- struct ata_chip_id *idx;
static struct ata_chip_id ids[] =
{{ ATA_ATI_IXP200, 0x00, 0, 0, ATA_UDMA5, "IXP200" },
{ ATA_ATI_IXP300, 0x00, 0, 0, ATA_UDMA6, "IXP300" },
@@ -1395,15 +1442,11 @@
{ ATA_ATI_IXP600_S1, 0x00, 0, AHCI, ATA_SA300, "IXP600" },
{ ATA_ATI_IXP700_S1, 0x00, 0, AHCI, ATA_SA300, "IXP700" },
{ 0, 0, 0, 0, 0, 0}};
- char buffer[64];
- if (!(idx = ata_match_chip(dev, ids)))
+ if (!(ctlr->chip = ata_match_chip(dev, ids)))
return ENXIO;
- sprintf(buffer, "ATI %s %s controller",
- idx->text, ata_mode2str(idx->max_dma));
- device_set_desc_copy(dev, buffer);
- ctlr->chip = idx;
+ ata_set_desc(dev);
/* the ATI SATA controller is actually a SiI 3112 controller*/
if (ctlr->chip->cfg1 & SIIMEMIO)
@@ -1421,17 +1464,10 @@
if (ata_setup_interrupt(dev))
return ENXIO;
- if (ctlr->chip->cfg2 & AHCI) {
- ctlr->r_rid2 = PCIR_BAR(5);
- ctlr->r_type2 = SYS_RES_MEMORY;
- if ((ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2,
- &ctlr->r_rid2,
- RF_ACTIVE)))
- return ata_ahci_chipinit(dev);
- }
-
- if (ctlr->chip->cfg2 & ATISINGLE)
- ctlr->channels = 1;
+ /* IXP600 & IXP700 only have 1 PATA channel */
+ if ((ctlr->chip->chipid == ATA_ATI_IXP600) ||
+ (ctlr->chip->chipid == ATA_ATI_IXP700))
+ ctlr->channels = 1;
ctlr->setmode = ata_ati_setmode;
return 0;
@@ -1501,6 +1537,7 @@
}
}
+
/*
* Cyrix chipset support functions
*/
@@ -1806,7 +1843,6 @@
ata_intel_ident(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(dev);
- struct ata_chip_id *idx;
static struct ata_chip_id ids[] =
{{ ATA_I82371FB, 0, 0, 0x00, ATA_WDMA2, "PIIX" },
{ ATA_I82371SB, 0, 0, 0x00, ATA_WDMA2, "PIIX3" },
@@ -1860,15 +1896,11 @@
{ ATA_I82801IB_AH6, 0, AHCI, 0x00, ATA_SA300, "ICH9" },
{ ATA_I31244, 0, 0, 0x00, ATA_SA150, "31244" },
{ 0, 0, 0, 0, 0, 0}};
- char buffer[64];
- if (!(idx = ata_match_chip(dev, ids)))
+ if (!(ctlr->chip = ata_match_chip(dev, ids)))
return ENXIO;
- sprintf(buffer, "Intel %s %s controller",
- idx->text, ata_mode2str(idx->max_dma));
- device_set_desc_copy(dev, buffer);
- ctlr->chip = idx;
+ ata_set_desc(dev);
ctlr->chipinit = ata_intel_chipinit;
return 0;
}
@@ -1911,25 +1943,28 @@
/* SATA parts can be either compat or AHCI */
else {
/* force all ports active "the legacy way" */
- pci_write_config(dev, 0x92, pci_read_config(dev, 0x92, 2) | 0x0f,2);
+ pci_write_config(dev, 0x92, pci_read_config(dev, 0x92, 2) | 0x0f, 2);
ctlr->allocate = ata_intel_allocate;
ctlr->reset = ata_intel_reset;
/*
- * if we have AHCI capability and BAR(5) as a memory resource
- * and AHCI or RAID mode enabled in BIOS we go for AHCI mode
+ * if we have AHCI capability and AHCI or RAID mode enabled
+ * in BIOS we try for AHCI mode
*/
if ((ctlr->chip->cfg1 == AHCI) &&
- (pci_read_config(dev, 0x90, 1) & 0xc0)) {
- 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 ata_ahci_chipinit(dev);
- }
- ctlr->setmode = ata_sata_setmode;
+ (pci_read_config(dev, 0x90, 1) & 0xc0) &&
+ (ata_ahci_chipinit(dev) != ENXIO))
+ return 0;
+
+ /* if BAR(5) is IO it should point to SATA interface registers */
+ ctlr->r_type2 = SYS_RES_IOPORT;
+ ctlr->r_rid2 = PCIR_BAR(5);
+ if ((ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2,
+ &ctlr->r_rid2, RF_ACTIVE)))
+ ctlr->setmode = ata_intel_sata_setmode;
+ else
+ ctlr->setmode = ata_sata_setmode;
/* enable PCI interrupt */
pci_write_config(dev, PCIR_COMMAND,
@@ -1941,12 +1976,21 @@
static int
ata_intel_allocate(device_t dev)
{
+ struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
/* setup the usual register normal pci style */
if (ata_pci_allocate(dev))
return ENXIO;
+ /* if r_res2 is valid it points to SATA interface registers */
+ if (ctlr->r_res2) {
+ ch->r_io[ATA_IDX_ADDR].res = ctlr->r_res2;
+ ch->r_io[ATA_IDX_ADDR].offset = 0x00;
+ ch->r_io[ATA_IDX_DATA].res = ctlr->r_res2;
+ ch->r_io[ATA_IDX_DATA].offset = 0x04;
+ }
+
ch->flags |= ATA_ALWAYS_DMASTAT;
return 0;
}
@@ -2073,6 +2117,38 @@
atadev->mode = mode;
}
+static void
+ata_intel_sata_setmode(device_t dev, int mode)
+{
+ struct ata_device *atadev = device_get_softc(dev);
+
+ if (atadev->param.satacapabilities != 0x0000 &&
+ atadev->param.satacapabilities != 0xffff) {
+
+ struct ata_channel *ch = device_get_softc(device_get_parent(dev));
+ int devno = (ch->unit << 1) + ATA_DEV(atadev->unit);
+
+ /* on some drives we need to set the transfer mode */
+ ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0,
+ ata_limit_mode(dev, mode, ATA_UDMA6));
+
+ /* set ATA_SSTATUS register offset */
+ ATA_IDX_OUTL(ch, ATA_IDX_ADDR, devno * 0x100);
+
+ /* query SATA STATUS for the speed */
+ if ((ATA_IDX_INL(ch, ATA_IDX_DATA) & ATA_SS_CONWELL_MASK) ==
+ ATA_SS_CONWELL_GEN2)
+ atadev->mode = ATA_SA300;
+ else
+ atadev->mode = ATA_SA150;
+ }
+ else {
+ mode = ata_limit_mode(dev, mode, ATA_UDMA5);
+ if (!ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode))
+ atadev->mode = mode;
+ }
+}
+
static int
ata_intel_31244_allocate(device_t dev)
{
@@ -2113,7 +2189,7 @@
ch->flags |= ATA_NO_SLAVE;
ata_pci_hw(dev);
ch->hw.status = ata_intel_31244_status;
- ch->hw.command = ata_intel_31244_command;
+ ch->hw.tf_write = ata_intel_31244_tf_write;
/* enable PHY state change interrupt */
ATA_OUTL(ctlr->r_res2, 0x4,
@@ -2124,76 +2200,69 @@
static int
ata_intel_31244_status(device_t dev)
{
- struct ata_channel *ch = device_get_softc(dev);
- u_int32_t status = ATA_IDX_INL(ch, ATA_SSTATUS);
- u_int32_t error = ATA_IDX_INL(ch, ATA_SERROR);
- struct ata_connect_task *tp;
+ /* do we have any PHY events ? */
+ ata_sata_phy_check_events(dev);
- /* check for PHY related interrupts on SATA capable HW */
- if (error) {
- /* clear error bits/interrupt */
- ATA_IDX_OUTL(ch, ATA_SERROR, error);
+ /* any drive action to take care of ? */
+ return ata_pci_status(dev);
+}
- /* if we have a connection event deal with it */
- if ((error & ATA_SE_PHY_CHANGED) &&
- (tp = (struct ata_connect_task *)
- malloc(sizeof(struct ata_connect_task),
- M_ATA, M_NOWAIT | M_ZERO))) {
+static void
+ata_intel_31244_tf_write(struct ata_request *request)
+{
+ struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
+ struct ata_device *atadev = device_get_softc(request->dev);
- if ((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN1) {
- if (bootverbose)
- device_printf(ch->dev, "CONNECT requested\n");
- tp->action = ATA_C_ATTACH;
+ if (atadev->flags & ATA_D_48BIT_ACTIVE) {
+ ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature);
+ ATA_IDX_OUTW(ch, ATA_COUNT, request->u.ata.count);
+ ATA_IDX_OUTW(ch, ATA_SECTOR, ((request->u.ata.lba >> 16) & 0xff00) |
+ (request->u.ata.lba & 0x00ff));
+ ATA_IDX_OUTW(ch, ATA_CYL_LSB, ((request->u.ata.lba >> 24) & 0xff00) |
+ ((request->u.ata.lba >> 8) & 0x00ff));
+ ATA_IDX_OUTW(ch, ATA_CYL_MSB, ((request->u.ata.lba >> 32) & 0xff00) |
+ ((request->u.ata.lba >> 16) & 0x00ff));
+ ATA_IDX_OUTW(ch, ATA_DRIVE, ATA_D_LBA | atadev->unit);
+ }
+ else {
+ ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature);
+ ATA_IDX_OUTB(ch, ATA_COUNT, request->u.ata.count);
+ if (atadev->flags & ATA_D_USE_CHS) {
+ int heads, sectors;
+
+ if (atadev->param.atavalid & ATA_FLAG_54_58) {
+ heads = atadev->param.current_heads;
+ sectors = atadev->param.current_sectors;
}
else {
- if (bootverbose)
- device_printf(ch->dev, "DISCONNECT requested\n");
- tp->action = ATA_C_DETACH;
+ heads = atadev->param.heads;
+ sectors = atadev->param.sectors;
}
- tp->dev = ch->dev;
- TASK_INIT(&tp->task, 0, ata_sata_phy_event, tp);
- taskqueue_enqueue(taskqueue_thread, &tp->task);
+ ATA_IDX_OUTB(ch, ATA_SECTOR, (request->u.ata.lba % sectors)+1);
+ ATA_IDX_OUTB(ch, ATA_CYL_LSB,
+ (request->u.ata.lba / (sectors * heads)));
+ ATA_IDX_OUTB(ch, ATA_CYL_MSB,
+ (request->u.ata.lba / (sectors * heads)) >> 8);
+ ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | atadev->unit |
+ (((request->u.ata.lba% (sectors * heads)) /
+ sectors) & 0xf));
+ }
+ else {
+ ATA_IDX_OUTB(ch, ATA_SECTOR, request->u.ata.lba);
+ ATA_IDX_OUTB(ch, ATA_CYL_LSB, request->u.ata.lba >> 8);
+ ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 16);
+ ATA_IDX_OUTB(ch, ATA_DRIVE,
+ ATA_D_IBM | ATA_D_LBA | atadev->unit |
+ ((request->u.ata.lba >> 24) & 0x0f));
}
}
-
- /* any drive action to take care of ? */
- return ata_pci_status(dev);
-}
-
-static int
-ata_intel_31244_command(struct ata_request *request)
-{
- struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
- struct ata_device *atadev = device_get_softc(request->dev);
- u_int64_t lba;
-
- if (!(atadev->flags & ATA_D_48BIT_ACTIVE))
- return (ata_generic_command(request));
-
- lba = request->u.ata.lba;
- ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | atadev->unit);
- /* enable interrupt */
- ATA_IDX_OUTB(ch, ATA_CONTROL, ATA_A_4BIT);
- ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature);
- ATA_IDX_OUTW(ch, ATA_COUNT, request->u.ata.count);
- ATA_IDX_OUTW(ch, ATA_SECTOR, ((lba >> 16) & 0xff00) | (lba & 0x00ff));
- ATA_IDX_OUTW(ch, ATA_CYL_LSB, ((lba >> 24) & 0xff00) |
- ((lba >> 8) & 0x00ff));
- ATA_IDX_OUTW(ch, ATA_CYL_MSB, ((lba >> 32) & 0xff00) |
- ((lba >> 16) & 0x00ff));
-
- /* issue command to controller */
- ATA_IDX_OUTB(ch, ATA_COMMAND, request->u.ata.command);
-
- return 0;
}
static void
ata_intel_31244_reset(device_t dev)
{
- struct ata_channel *ch = device_get_softc(dev);
-
- ata_sata_phy_enable(ch);
+ if (ata_sata_phy_reset(dev))
+ ata_generic_reset(dev);
}
@@ -2204,20 +2273,15 @@
ata_ite_ident(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(dev);
- struct ata_chip_id *idx;
static struct ata_chip_id ids[] =
{{ ATA_IT8212F, 0x00, 0x00, 0x00, ATA_UDMA6, "IT8212F" },
{ ATA_IT8211F, 0x00, 0x00, 0x00, ATA_UDMA6, "IT8211F" },
{ 0, 0, 0, 0, 0, 0}};
- char buffer[64];
- if (!(idx = ata_match_chip(dev, ids)))
+ if (!(ctlr->chip = ata_match_chip(dev, ids)))
return ENXIO;
- sprintf(buffer, "ITE %s %s controller",
- idx->text, ata_mode2str(idx->max_dma));
- device_set_desc_copy(dev, buffer);
- ctlr->chip = idx;
+ ata_set_desc(dev);
ctlr->chipinit = ata_ite_chipinit;
return 0;
}
@@ -2348,12 +2412,9 @@
/* do we have multiple PCI functions ? */
if (pci_read_config(dev, 0xdf, 1) & 0x40) {
- /* if we have a memory BAR(5) we are on the 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 ata_ahci_chipinit(dev);
+ /* are we on the AHCI part ? */
+ if (ata_ahci_chipinit(dev) != ENXIO)
+ return 0;
/* otherwise we are on the PATA part */
ctlr->allocate = ata_pci_allocate;
@@ -2367,13 +2428,8 @@
pci_write_config(dev, 0x40, 0x80c0a131, 4);
pci_write_config(dev, 0x80, 0x01200000, 4);
- 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))){
- if ((error = ata_ahci_chipinit(dev)))
- return error;
- }
+ if (ctlr->chip->cfg1 && (error = ata_ahci_chipinit(dev)))
+ return error;
ctlr->allocate = ata_jmicron_allocate;
ctlr->reset = ata_jmicron_reset;
@@ -2476,7 +2532,6 @@
ata_marvell_ident(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(dev);
- struct ata_chip_id *idx;
static struct ata_chip_id ids[] =
{{ ATA_M88SX5040, 0, 4, MV50XX, ATA_SA150, "88SX5040" },
{ ATA_M88SX5041, 0, 4, MV50XX, ATA_SA150, "88SX5041" },
@@ -2487,23 +2542,20 @@
{ ATA_M88SX6101, 0, 1, MV61XX, ATA_UDMA6, "88SX6101" },
{ ATA_M88SX6145, 0, 2, MV61XX, ATA_UDMA6, "88SX6145" },
{ 0, 0, 0, 0, 0, 0}};
- char buffer[64];
- if (!(idx = ata_match_chip(dev, ids)))
+ if (!(ctlr->chip = ata_match_chip(dev, ids)))
return ENXIO;
- sprintf(buffer, "Marvell %s %s controller",
- idx->text, ata_mode2str(idx->max_dma));
- device_set_desc_copy(dev, buffer);
- ctlr->chip = idx;
+ ata_set_desc(dev);
+
switch (ctlr->chip->cfg2) {
- case MV50XX:
- case MV60XX:
- ctlr->chipinit = ata_marvell_edma_chipinit;
- break;
- case MV61XX:
- ctlr->chipinit = ata_marvell_pata_chipinit;
- break;
+ case MV50XX:
+ case MV60XX:
+ ctlr->chipinit = ata_marvell_edma_chipinit;
+ break;
+ case MV61XX:
+ ctlr->chipinit = ata_marvell_pata_chipinit;
+ break;
}
return 0;
}
@@ -2512,8 +2564,9 @@
ata_marvell_pata_chipinit(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(dev);
+
if (ata_setup_interrupt(dev))
- return ENXIO;
+ return ENXIO;
ctlr->allocate = ata_marvell_pata_allocate;
ctlr->setmode = ata_marvell_pata_setmode;
@@ -2525,13 +2578,13 @@
ata_marvell_pata_allocate(device_t dev)
{
struct ata_channel *ch = device_get_softc(dev);
-
+
/* setup the usual register normal pci style */
if (ata_pci_allocate(dev))
- return ENXIO;
-
+ return ENXIO;
+
/* dont use 32 bit PIO transfers */
- ch->flags |= ATA_USE_16BIT;
+ ch->flags |= ATA_USE_16BIT;
return 0;
}
@@ -2546,7 +2599,7 @@
mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma);
mode = ata_check_80pin(dev, mode);
if (!ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode))
- atadev->mode = mode;
+ atadev->mode = mode;
}
static int
@@ -2601,7 +2654,7 @@
{
struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
- bus_addr_t work = ch->dma->work_bus;
+ u_int64_t work = ch->dma->work_bus;
int i;
/* clear work area */
@@ -2654,7 +2707,7 @@
ATA_OUTL(ctlr->r_res1, 0x02000 + ATA_MV_EDMA_BASE(ch), (1<<11) | (1<<13));
/* request queue base high */
- ATA_OUTL(ctlr->r_res1, 0x02010 + ATA_MV_EDMA_BASE(ch), (work >> 16) >> 16);
+ ATA_OUTL(ctlr->r_res1, 0x02010 + ATA_MV_EDMA_BASE(ch), work >> 32);
/* request queue in ptr */
ATA_OUTL(ctlr->r_res1, 0x02014 + ATA_MV_EDMA_BASE(ch), work & 0xffffffff);
@@ -2664,7 +2717,7 @@
/* response queue base high */
work += 1024;
- ATA_OUTL(ctlr->r_res1, 0x0201c + ATA_MV_EDMA_BASE(ch), (work >> 16) >> 16);
+ ATA_OUTL(ctlr->r_res1, 0x0201c + ATA_MV_EDMA_BASE(ch), work >> 32);
/* response queue in ptr */
ATA_OUTL(ctlr->r_res1, 0x02020 + ATA_MV_EDMA_BASE(ch), 0x0);
@@ -2694,45 +2747,13 @@
u_int32_t cause = ATA_INL(ctlr->r_res1, 0x01d60);
int shift = (ch->unit << 1) + (ch->unit > 3);
- /* do we have any errors flagged ? */
if (cause & (1 << shift)) {
- struct ata_connect_task *tp;
- u_int32_t error =
- ATA_INL(ctlr->r_res1, 0x02008 + ATA_MV_EDMA_BASE(ch));
-
- /* check for and handle disconnect events */
- if ((error & 0x00000008) &&
- (tp = (struct ata_connect_task *)
- malloc(sizeof(struct ata_connect_task),
- M_ATA, M_NOWAIT | M_ZERO))) {
-
- if (bootverbose)
- device_printf(ch->dev, "DISCONNECT requested\n");
- tp->action = ATA_C_DETACH;
- tp->dev = ch->dev;
- TASK_INIT(&tp->task, 0, ata_sata_phy_event, tp);
- taskqueue_enqueue(taskqueue_thread, &tp->task);
- }
-
- /* check for and handle connect events */
- if ((error & 0x00000010) &&
- (tp = (struct ata_connect_task *)
- malloc(sizeof(struct ata_connect_task),
- M_ATA, M_NOWAIT | M_ZERO))) {
-
- if (bootverbose)
- device_printf(ch->dev, "CONNECT requested\n");
- tp->action = ATA_C_ATTACH;
- tp->dev = ch->dev;
- TASK_INIT(&tp->task, 0, ata_sata_phy_event, tp);
- taskqueue_enqueue(taskqueue_thread, &tp->task);
- }
-
- /* clear SATA error register */
- ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR));
- /* clear any outstanding error interrupts */
+ /* clear interrupt(s) */
ATA_OUTL(ctlr->r_res1, 0x02008 + ATA_MV_EDMA_BASE(ch), 0x0);
+
+ /* do we have any PHY events ? */
+ ata_sata_phy_check_events(dev);
}
/* do we have any device action ? */
@@ -2784,7 +2805,7 @@
/* fill in this request */
quadp[0] = (long)ch->dma->sg_bus & 0xffffffff;
- quadp[1] = (ch->dma->sg_bus & 0xffffffff00000000ull) >> 32;
+ quadp[1] = (u_int64_t)ch->dma->sg_bus >> 32;
wordp[4] = (request->flags & ATA_R_READ ? 0x01 : 0x00) | (tag<<1);
i = 10;
@@ -2847,9 +2868,6 @@
u_int32_t rsp_in, rsp_out;
int slot;
- /* unload SG list */
- ch->dma->unload(ch->dev);
-
/* stop timeout */
callout_stop(&request->callout);
@@ -2873,6 +2891,10 @@
if (!(request->status & ATA_S_ERROR) &&
!(request->flags & ATA_R_TIMEOUT))
request->donecount = request->bytecount;
+
+ /* unload SG list */
+ ch->dma->unload(ch->dev);
+
res = ATA_OP_FINISHED;
}
@@ -2907,15 +2929,16 @@
ATA_OUTL(ctlr->r_res1, 0x0200c + ATA_MV_EDMA_BASE(ch), ~0x0);
/* enable channel and test for devices */
- ata_sata_phy_enable(ch);
+ if (ata_sata_phy_reset(dev))
+ ata_generic_reset(dev);
/* enable EDMA machinery */
ATA_OUTL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch), 0x00000001);
}
static void
-ata_marvell_edma_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs,
- int error)
+ata_marvell_edma_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs,
+ int error)
{
struct ata_dmasetprd_args *args = xsc;
struct ata_marvell_dma_prdentry *prd = args->dmatab;
@@ -2926,24 +2949,35 @@
for (i = 0; i < nsegs; i++) {
prd[i].addrlo = htole32(segs[i].ds_addr);
- prd[i].addrhi = 0;
prd[i].count = htole32(segs[i].ds_len);
+ prd[i].addrhi = htole32((u_int64_t)segs[i].ds_addr >> 32);
}
prd[i - 1].count |= htole32(ATA_DMA_EOT);
+ KASSERT(nsegs <= ATA_DMA_ENTRIES, ("too many DMA segment entries\n"));
+ args->nsegs = nsegs;
}
static void
ata_marvell_edma_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);
if (ch->dma) {
/* note start and stop are not used here */
ch->dma->setprd = ata_marvell_edma_dmasetprd;
+
+ /* if 64bit support present adjust max address used */
+ if (ATA_INL(ctlr->r_res1, 0x00d00) & 0x00000004)
+ ch->dma->max_address = BUS_SPACE_MAXADDR;
+
+ /* chip does not reliably do 64K DMA transfers */
+ ch->dma->max_iosize = 126 * DEV_BSIZE;
}
}
+
/*
* National chipset support functions
*/
@@ -2960,12 +2994,12 @@
}
return ENXIO;
}
-
+
static int
ata_national_chipinit(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(dev);
-
+
if (ata_setup_interrupt(dev))
return ENXIO;
@@ -3020,13 +3054,56 @@
/*
+ * NetCell chipset support functions
+ */
+int
+ata_netcell_ident(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+
+ if (pci_get_devid(dev) == ATA_NETCELL_SR) {
+ device_set_desc(dev, "Netcell SyncRAID SR3000/5000 RAID Controller");
+ ctlr->chipinit = ata_netcell_chipinit;
+ return 0;
+ }
+ return ENXIO;
+}
+
+static int
+ata_netcell_chipinit(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+
+ if (ata_generic_chipinit(dev))
+ return ENXIO;
+
+ ctlr->allocate = ata_netcell_allocate;
+ return 0;
+}
+
+static int
+ata_netcell_allocate(device_t dev)
+{
+ struct ata_channel *ch = device_get_softc(dev);
+
+ /* setup the usual register normal pci style */
+ if (ata_pci_allocate(dev))
+ return ENXIO;
+
+ /* the NetCell only supports 16 bit PIO transfers */
+ ch->flags |= ATA_USE_16BIT;
+
+ return 0;
+}
+
+
+/*
* nVidia chipset support functions
*/
int
ata_nvidia_ident(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(dev);
- struct ata_chip_id *idx;
static struct ata_chip_id ids[] =
{{ ATA_NFORCE1, 0, AMDNVIDIA, NVIDIA, ATA_UDMA5, "nForce" },
{ ATA_NFORCE2, 0, AMDNVIDIA, NVIDIA, ATA_UDMA6, "nForce2" },
@@ -3057,15 +3134,11 @@
{ ATA_NFORCE_MCP73, 0, AMDNVIDIA, NVIDIA, ATA_UDMA6, "nForce MCP73" },
{ ATA_NFORCE_MCP77, 0, AMDNVIDIA, NVIDIA, ATA_UDMA6, "nForce MCP77" },
{ 0, 0, 0, 0, 0, 0}} ;
- char buffer[64] ;
- if (!(idx = ata_match_chip(dev, ids)))
+ if (!(ctlr->chip = ata_match_chip(dev, ids)))
return ENXIO;
- sprintf(buffer, "nVidia %s %s controller",
- idx->text, ata_mode2str(idx->max_dma));
- device_set_desc_copy(dev, buffer);
- ctlr->chip = idx;
+ ata_set_desc(dev);
ctlr->chipinit = ata_nvidia_chipinit;
return 0;
}
@@ -3157,59 +3230,26 @@
struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
int offset = ctlr->chip->cfg2 & NV4 ? 0x0440 : 0x0010;
- struct ata_connect_task *tp;
int shift = ch->unit << (ctlr->chip->cfg2 & NVQ ? 4 : 2);
- u_int32_t status;
-
- /* get and clear interrupt status */
- if (ctlr->chip->cfg2 & NVQ) {
- status = ATA_INL(ctlr->r_res2, offset);
- ATA_OUTL(ctlr->r_res2, offset, (0x0f << shift) | 0x00f000f0);
- }
- else {
- status = ATA_INB(ctlr->r_res2, offset);
- ATA_OUTB(ctlr->r_res2, offset, (0x0f << shift));
- }
-
- /* check for and handle connect events */
- if (((status & (0x0c << shift)) == (0x04 << shift)) &&
- (tp = (struct ata_connect_task *)
- malloc(sizeof(struct ata_connect_task),
- M_ATA, M_NOWAIT | M_ZERO))) {
-
- if (bootverbose)
- device_printf(ch->dev, "CONNECT requested\n");
- tp->action = ATA_C_ATTACH;
- tp->dev = ch->dev;
- TASK_INIT(&tp->task, 0, ata_sata_phy_event, tp);
- taskqueue_enqueue(taskqueue_thread, &tp->task);
- }
-
- /* check for and handle disconnect events */
- if ((status & (0x08 << shift)) &&
- !((status & (0x04 << shift) && ATA_IDX_INL(ch, ATA_SSTATUS))) &&
- (tp = (struct ata_connect_task *)
- malloc(sizeof(struct ata_connect_task),
- M_ATA, M_NOWAIT | M_ZERO))) {
+ u_int32_t istatus = ATA_INL(ctlr->r_res2, offset);
- if (bootverbose)
- device_printf(ch->dev, "DISCONNECT requested\n");
- tp->action = ATA_C_DETACH;
- tp->dev = ch->dev;
- TASK_INIT(&tp->task, 0, ata_sata_phy_event, tp);
- taskqueue_enqueue(taskqueue_thread, &tp->task);
- }
+ /* do we have any PHY events ? */
+ if (istatus & (0x0c << shift))
+ ata_sata_phy_check_events(dev);
+
+ /* clear interrupt(s) */
+ ATA_OUTB(ctlr->r_res2, offset,
+ (0x0f << shift) | (ctlr->chip->cfg2 & NVQ ? 0x00f000f0 : 0));
/* do we have any device action ? */
- return (status & (0x01 << shift));
+ return (istatus & (0x01 << shift));
}
static void
ata_nvidia_reset(device_t dev)
{
- struct ata_channel *ch = device_get_softc(dev);
-
- ata_sata_phy_enable(ch);
+ if (ata_sata_phy_reset(dev))
+ ata_generic_reset(dev);
}
@@ -3376,7 +3416,7 @@
u_int32_t dimm = ATA_INL(ctlr->r_res2, 0x000c0080);
if (bus_teardown_intr(dev, ctlr->r_irq, ctlr->handle) ||
- bus_setup_intr(dev, ctlr->r_irq, ATA_INTR_FLAGS,
+ bus_setup_intr(dev, ctlr->r_irq, ATA_INTR_FLAGS, NULL,
ata_promise_sx4_intr, ctlr, &ctlr->handle)) {
device_printf(dev, "unable to setup interrupt\n");
goto failnfree;
@@ -3410,7 +3450,7 @@
/* mio type controllers need an interrupt intercept */
if (bus_teardown_intr(dev, ctlr->r_irq, ctlr->handle) ||
- bus_setup_intr(dev, ctlr->r_irq, ATA_INTR_FLAGS,
+ bus_setup_intr(dev, ctlr->r_irq, ATA_INTR_FLAGS, NULL,
ata_promise_mio_intr, ctlr, &ctlr->handle)) {
device_printf(dev, "unable to setup interrupt\n");
goto failnfree;
@@ -3446,9 +3486,13 @@
/* prime fake interrupt register */
ATA_OUTL(ctlr->r_res2, fake_reg, 0xffffffff);
- /* clear SATA status */
+ /* clear SATA status and unmask interrupts */
ATA_OUTL(ctlr->r_res2, stat_reg, 0x000000ff);
+ /* enable "long burst lenght" on gen2 chips */
+ if ((ctlr->chip->cfg2 == PRSATA2) || (ctlr->chip->cfg2 == PRCMBO2))
+ ATA_OUTL(ctlr->r_res2, 0x44, ATA_INL(ctlr->r_res2, 0x44) | 0x2000);
+
ctlr->allocate = ata_promise_mio_allocate;
ctlr->reset = ata_promise_mio_reset;
ctlr->dmainit = ata_promise_mio_dmainit;
@@ -3881,7 +3925,8 @@
if ((ctlr->chip->cfg2 == PRSATA) ||
((ctlr->chip->cfg2 == PRCMBO) && (ch->unit < 2))) {
- ata_sata_phy_enable(ch);
+ if (ata_sata_phy_reset(dev))
+ ata_generic_reset(dev);
/* reset and enable plug/unplug intr */
ATA_OUTL(ctlr->r_res2, 0x06c, (0x00000011 << ch->unit));
@@ -3916,7 +3961,8 @@
(ATA_INL(ctlr->r_res2, 0x414 + (ch->unit << 8)) &
~0x00000003) | 0x00000001);
- ata_sata_phy_enable(ch);
+ if (ata_sata_phy_reset(dev))
+ ata_generic_reset(dev);
/* reset and enable plug/unplug intr */
ATA_OUTL(ctlr->r_res2, 0x060, (0x00000011 << ch->unit));
@@ -3934,8 +3980,42 @@
static void
ata_promise_mio_dmainit(device_t dev)
{
+ struct ata_channel *ch = device_get_softc(dev);
+
/* note start and stop are not used here */
ata_dmainit(dev);
+ if (ch->dma)
+ ch->dma->setprd = ata_promise_mio_setprd;
+}
+
+
+#define MAXLASTSGSIZE (32 * sizeof(u_int32_t))
+static void
+ata_promise_mio_setprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error)
+{
+ struct ata_dmasetprd_args *args = xsc;
+ struct ata_dma_prdentry *prd = args->dmatab;
+ int i;
+
+ if ((args->error = error))
+ return;
+
+ for (i = 0; i < nsegs; i++) {
+ prd[i].addr = htole32(segs[i].ds_addr);
+ prd[i].count = htole32(segs[i].ds_len);
+ }
+ if (segs[i - 1].ds_len > MAXLASTSGSIZE) {
+ //printf("split last SG element of %u\n", segs[i - 1].ds_len);
+ prd[i - 1].count = htole32(segs[i - 1].ds_len - MAXLASTSGSIZE);
+ prd[i].count = htole32(MAXLASTSGSIZE);
+ prd[i].addr = htole32(segs[i - 1].ds_addr +
+ (segs[i - 1].ds_len - MAXLASTSGSIZE));
+ nsegs++;
+ i++;
+ }
+ prd[i - 1].count |= htole32(ATA_DMA_EOT);
+ KASSERT(nsegs <= ATA_DMA_ENTRIES, ("too many DMA segment entries\n"));
+ args->nsegs = nsegs;
}
static void
@@ -4186,7 +4266,6 @@
ata_serverworks_ident(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(dev);
- struct ata_chip_id *idx;
static struct ata_chip_id ids[] =
{{ ATA_ROSB4, 0x00, SWKS33, 0, ATA_UDMA2, "ROSB4" },
{ ATA_CSB5, 0x92, SWKS100, 0, ATA_UDMA5, "CSB5" },
@@ -4200,15 +4279,11 @@
{ ATA_FRODO4, 0x00, SWKSMIO, 4, ATA_SA150, "Frodo4" },
{ ATA_FRODO8, 0x00, SWKSMIO, 8, ATA_SA150, "Frodo8" },
{ 0, 0, 0, 0, 0, 0}};
- char buffer[64];
- if (!(idx = ata_match_chip(dev, ids)))
+ if (!(ctlr->chip = ata_match_chip(dev, ids)))
return ENXIO;
- sprintf(buffer, "ServerWorks %s %s controller",
- idx->text, ata_mode2str(idx->max_dma));
- device_set_desc_copy(dev, buffer);
- ctlr->chip = idx;
+ ata_set_desc(dev);
ctlr->chipinit = ata_serverworks_chipinit;
return 0;
}
@@ -4296,10 +4371,97 @@
ch->flags |= ATA_NO_SLAVE;
ata_pci_hw(dev);
+ ch->hw.tf_read = ata_serverworks_tf_read;
+ ch->hw.tf_write = ata_serverworks_tf_write;
+
+ /* chip does not reliably do 64K DMA transfers */
+ if (ch->dma)
+ ch->dma->max_iosize = 126 * DEV_BSIZE;
+
return 0;
}
static void
+ata_serverworks_tf_read(struct ata_request *request)
+{
+ struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
+ struct ata_device *atadev = device_get_softc(request->dev);
+
+ if (atadev->flags & ATA_D_48BIT_ACTIVE) {
+ u_int16_t temp;
+
+ request->u.ata.count = ATA_IDX_INW(ch, ATA_COUNT);
+ temp = ATA_IDX_INW(ch, ATA_SECTOR);
+ request->u.ata.lba = (u_int64_t)(temp & 0x00ff) |
+ ((u_int64_t)(temp & 0xff00) << 24);
+ temp = ATA_IDX_INW(ch, ATA_CYL_LSB);
+ request->u.ata.lba |= ((u_int64_t)(temp & 0x00ff) << 8) |
+ ((u_int64_t)(temp & 0xff00) << 32);
+ temp = ATA_IDX_INW(ch, ATA_CYL_MSB);
+ request->u.ata.lba |= ((u_int64_t)(temp & 0x00ff) << 16) |
+ ((u_int64_t)(temp & 0xff00) << 40);
+ }
+ else {
+ request->u.ata.count = ATA_IDX_INW(ch, ATA_COUNT) & 0x00ff;
+ request->u.ata.lba = (ATA_IDX_INW(ch, ATA_SECTOR) & 0x00ff) |
+ ((ATA_IDX_INW(ch, ATA_CYL_LSB) & 0x00ff) << 8) |
+ ((ATA_IDX_INW(ch, ATA_CYL_MSB) & 0x00ff) << 16) |
+ ((ATA_IDX_INW(ch, ATA_DRIVE) & 0xf) << 24);
+ }
+}
+
+static void
+ata_serverworks_tf_write(struct ata_request *request)
+{
+ struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
+ struct ata_device *atadev = device_get_softc(request->dev);
+
+ if (atadev->flags & ATA_D_48BIT_ACTIVE) {
+ ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature);
+ ATA_IDX_OUTW(ch, ATA_COUNT, request->u.ata.count);
+ ATA_IDX_OUTW(ch, ATA_SECTOR, ((request->u.ata.lba >> 16) & 0xff00) |
+ (request->u.ata.lba & 0x00ff));
+ ATA_IDX_OUTW(ch, ATA_CYL_LSB, ((request->u.ata.lba >> 24) & 0xff00) |
+ ((request->u.ata.lba >> 8) & 0x00ff));
+ ATA_IDX_OUTW(ch, ATA_CYL_MSB, ((request->u.ata.lba >> 32) & 0xff00) |
+ ((request->u.ata.lba >> 16) & 0x00ff));
+ ATA_IDX_OUTW(ch, ATA_DRIVE, ATA_D_LBA | atadev->unit);
+ }
+ else {
+ ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature);
+ ATA_IDX_OUTW(ch, ATA_COUNT, request->u.ata.count);
+ if (atadev->flags & ATA_D_USE_CHS) {
+ int heads, sectors;
+
+ if (atadev->param.atavalid & ATA_FLAG_54_58) {
+ heads = atadev->param.current_heads;
+ sectors = atadev->param.current_sectors;
+ }
+ else {
+ heads = atadev->param.heads;
+ sectors = atadev->param.sectors;
+ }
+ ATA_IDX_OUTW(ch, ATA_SECTOR, (request->u.ata.lba % sectors)+1);
+ ATA_IDX_OUTW(ch, ATA_CYL_LSB,
+ (request->u.ata.lba / (sectors * heads)));
+ ATA_IDX_OUTW(ch, ATA_CYL_MSB,
+ (request->u.ata.lba / (sectors * heads)) >> 8);
+ ATA_IDX_OUTW(ch, ATA_DRIVE, ATA_D_IBM | atadev->unit |
+ (((request->u.ata.lba% (sectors * heads)) /
+ sectors) & 0xf));
+ }
+ else {
+ ATA_IDX_OUTW(ch, ATA_SECTOR, request->u.ata.lba);
+ ATA_IDX_OUTW(ch, ATA_CYL_LSB, request->u.ata.lba >> 8);
+ ATA_IDX_OUTW(ch, ATA_CYL_MSB, request->u.ata.lba >> 16);
+ ATA_IDX_OUTW(ch, ATA_DRIVE,
+ ATA_D_IBM | ATA_D_LBA | atadev->unit |
+ ((request->u.ata.lba >> 24) & 0x0f));
+ }
+ }
+}
+
+static void
ata_serverworks_setmode(device_t dev, int mode)
{
device_t gparent = GRANDPARENT(dev);
@@ -4367,7 +4529,6 @@
ata_sii_ident(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(dev);
- struct ata_chip_id *idx;
static struct ata_chip_id ids[] =
{{ ATA_SII3114, 0x00, SIIMEMIO, SII4CH, ATA_SA150, "SiI 3114" },
{ ATA_SII3512, 0x02, SIIMEMIO, 0, ATA_SA150, "SiI 3512" },
@@ -4376,20 +4537,19 @@
{ ATA_SII3512, 0x00, SIIMEMIO, SIIBUG, ATA_SA150, "SiI 3512" },
{ ATA_SII3112, 0x00, SIIMEMIO, SIIBUG, ATA_SA150, "SiI 3112" },
{ ATA_SII3112_1, 0x00, SIIMEMIO, SIIBUG, ATA_SA150, "SiI 3112" },
+ { ATA_SII3124, 0x00, SIIPRBIO, SII4CH, ATA_SA300, "SiI 3124" },
+ { ATA_SII3132, 0x00, SIIPRBIO, 0, ATA_SA300, "SiI 3132" },
{ ATA_SII0680, 0x00, SIIMEMIO, SIISETCLK, ATA_UDMA6, "SiI 0680" },
{ ATA_CMD649, 0x00, 0, SIIINTR, ATA_UDMA5, "CMD 649" },
{ ATA_CMD648, 0x00, 0, SIIINTR, ATA_UDMA4, "CMD 648" },
{ ATA_CMD646, 0x07, 0, 0, ATA_UDMA2, "CMD 646U2" },
{ ATA_CMD646, 0x00, 0, 0, ATA_WDMA2, "CMD 646" },
{ 0, 0, 0, 0, 0, 0}};
- char buffer[64];
- if (!(idx = ata_match_chip(dev, ids)))
+ if (!(ctlr->chip = ata_match_chip(dev, ids)))
return ENXIO;
- sprintf(buffer, "%s %s controller", idx->text, ata_mode2str(idx->max_dma));
- device_set_desc_copy(dev, buffer);
- ctlr->chip = idx;
+ ata_set_desc(dev);
ctlr->chipinit = ata_sii_chipinit;
return 0;
}
@@ -4402,7 +4562,38 @@
if (ata_setup_interrupt(dev))
return ENXIO;
- if (ctlr->chip->cfg1 == SIIMEMIO) {
+ switch (ctlr->chip->cfg1) {
+ case SIIPRBIO:
+ ctlr->r_type1 = SYS_RES_MEMORY;
+ ctlr->r_rid1 = PCIR_BAR(0);
+ if (!(ctlr->r_res1 = bus_alloc_resource_any(dev, ctlr->r_type1,
+ &ctlr->r_rid1, RF_ACTIVE)))
+ return ENXIO;
+
+ ctlr->r_rid2 = PCIR_BAR(2);
+ ctlr->r_type2 = SYS_RES_MEMORY;
+ if (!(ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2,
+ &ctlr->r_rid2, RF_ACTIVE))){
+ bus_release_resource(dev, ctlr->r_type1, ctlr->r_rid1,ctlr->r_res1);
+ return ENXIO;
+ }
+ ctlr->allocate = ata_siiprb_allocate;
+ ctlr->reset = ata_siiprb_reset;
+ ctlr->dmainit = ata_siiprb_dmainit;
+ ctlr->setmode = ata_sata_setmode;
+ ctlr->channels = (ctlr->chip->cfg2 == SII4CH) ? 4 : 2;
+
+ /* reset controller */
+ ATA_OUTL(ctlr->r_res1, 0x0040, 0x80000000);
+ DELAY(10000);
+ ATA_OUTL(ctlr->r_res1, 0x0040, 0x0000000f);
+
+ /* enable PCI interrupt */
+ pci_write_config(dev, PCIR_COMMAND,
+ pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400, 2);
+ break;
+
+ case SIIMEMIO:
ctlr->r_type2 = SYS_RES_MEMORY;
ctlr->r_rid2 = PCIR_BAR(5);
if (!(ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2,
@@ -4424,13 +4615,13 @@
ctlr->channels = 4;
}
- /* enable PCI interrupt as BIOS might not */
- pci_write_config(dev, 0x8a, (pci_read_config(dev, 0x8a, 1) & 0x3f), 1);
-
/* dont block interrupts from any channel */
pci_write_config(dev, 0x48,
(pci_read_config(dev, 0x48, 4) & ~0x03c00000), 4);
+ /* enable PCI interrupt as BIOS might not */
+ pci_write_config(dev, 0x8a, (pci_read_config(dev, 0x8a, 1) & 0x3f), 1);
+
ctlr->allocate = ata_sii_allocate;
if (ctlr->chip->max_dma >= ATA_SA150) {
ctlr->reset = ata_sii_reset;
@@ -4438,8 +4629,9 @@
}
else
ctlr->setmode = ata_sii_setmode;
- }
- else {
+ break;
+
+ default:
if ((pci_read_config(dev, 0x51, 1) & 0x08) != 0x08) {
device_printf(dev, "HW has secondary channel disabled\n");
ctlr->channels = 1;
@@ -4450,6 +4642,7 @@
ctlr->allocate = ata_cmd_allocate;
ctlr->setmode = ata_cmd_setmode;
+ break;
}
return 0;
}
@@ -4563,8 +4756,6 @@
ch->r_io[ATA_BMSTAT_PORT].offset = 0x02 + (unit01 << 3) + (unit10 << 8);
ch->r_io[ATA_BMDTP_PORT].res = ctlr->r_res2;
ch->r_io[ATA_BMDTP_PORT].offset = 0x04 + (unit01 << 3) + (unit10 << 8);
- ch->r_io[ATA_BMDEVSPEC_0].res = ctlr->r_res2;
- ch->r_io[ATA_BMDEVSPEC_0].offset = 0xa1 + (unit01 << 6) + (unit10 << 8);
if (ctlr->chip->max_dma >= ATA_SA150) {
ch->r_io[ATA_SSTATUS].res = ctlr->r_res2;
@@ -4581,7 +4772,7 @@
if ((ctlr->chip->cfg2 & SIIBUG) && ch->dma) {
/* work around errata in early chips */
- ch->dma->boundary = 16 * DEV_BSIZE;
+ ch->dma->boundary = 8192;
ch->dma->segsize = 15 * DEV_BSIZE;
}
@@ -4595,68 +4786,25 @@
{
struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
+ int offset0 = ((ch->unit & 1) << 3) + ((ch->unit & 2) << 8);
+ int offset1 = ((ch->unit & 1) << 6) + ((ch->unit & 2) << 8);
- /* check for PHY related interrupts on SATA capable HW */
- if (ctlr->chip->max_dma >= ATA_SA150) {
- u_int32_t status = ATA_IDX_INL(ch, ATA_SSTATUS);
- u_int32_t error = ATA_IDX_INL(ch, ATA_SERROR);
- struct ata_connect_task *tp;
-
- if (error) {
- /* clear error bits/interrupt */
- ATA_IDX_OUTL(ch, ATA_SERROR, error);
-
- /* if we have a connection event deal with it */
- if ((error & ATA_SE_PHY_CHANGED) &&
- (tp = (struct ata_connect_task *)
- malloc(sizeof(struct ata_connect_task),
- M_ATA, M_NOWAIT | M_ZERO))) {
-
- if ((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN1) {
- if (bootverbose)
- device_printf(ch->dev, "CONNECT requested\n");
- tp->action = ATA_C_ATTACH;
- }
- else {
- if (bootverbose)
- device_printf(ch->dev, "DISCONNECT requested\n");
- tp->action = ATA_C_DETACH;
- }
- tp->dev = ch->dev;
- TASK_INIT(&tp->task, 0, ata_sata_phy_event, tp);
- taskqueue_enqueue(taskqueue_thread, &tp->task);
- }
- }
- }
+ /* do we have any PHY events ? */
+ if (ctlr->chip->max_dma >= ATA_SA150 &&
+ (ATA_INL(ctlr->r_res2, 0x10 + offset0) & 0x00000010))
+ ata_sata_phy_check_events(dev);
- /* any drive action to take care of ? */
- if (ATA_IDX_INB(ch, ATA_BMDEVSPEC_0) & 0x08)
+ if (ATA_INL(ctlr->r_res2, 0xa0 + offset1) & 0x00000800)
return ata_pci_status(dev);
- else
+ else
return 0;
}
static void
ata_sii_reset(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 & 1) << 7) + ((ch->unit & 2) << 8);
-
- /* disable PHY state change interrupt */
- ATA_OUTL(ctlr->r_res2, 0x148 + offset, ~(1 << 16));
-
- /* reset controller part for this channel */
- ATA_OUTL(ctlr->r_res2, 0x48,
- ATA_INL(ctlr->r_res2, 0x48) | (0xc0 >> ch->unit));
- DELAY(1000);
- ATA_OUTL(ctlr->r_res2, 0x48,
- ATA_INL(ctlr->r_res2, 0x48) & ~(0xc0 >> ch->unit));
-
- ata_sata_phy_enable(ch);
-
- /* enable PHY state change interrupt */
- ATA_OUTL(ctlr->r_res2, 0x148 + offset, (1 << 16));
+ if (ata_sata_phy_reset(dev))
+ ata_generic_reset(dev);
}
static void
@@ -4725,6 +4873,355 @@
}
+struct ata_siiprb_dma_prdentry {
+ u_int64_t addr;
+ u_int32_t count;
+ u_int32_t control;
+} __packed;
+
+struct ata_siiprb_ata_command {
+ struct ata_siiprb_dma_prdentry prd[126];
+} __packed;
+
+struct ata_siiprb_atapi_command {
+ u_int8_t ccb[16];
+ struct ata_siiprb_dma_prdentry prd[125];
+} __packed;
+
+struct ata_siiprb_command {
+ u_int16_t control;
+ u_int16_t protocol_override;
+ u_int32_t transfer_count;
+ u_int8_t fis[24];
+ union {
+ struct ata_siiprb_ata_command ata;
+ struct ata_siiprb_atapi_command atapi;
+ } u;
+} __packed;
+
+static int
+ata_siiprb_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 * 0x2000;
+
+ /* set the SATA resources */
+ ch->r_io[ATA_SSTATUS].res = ctlr->r_res2;
+ ch->r_io[ATA_SSTATUS].offset = 0x1f04 + offset;
+ ch->r_io[ATA_SERROR].res = ctlr->r_res2;
+ ch->r_io[ATA_SERROR].offset = 0x1f08 + offset;
+ ch->r_io[ATA_SCONTROL].res = ctlr->r_res2;
+ ch->r_io[ATA_SCONTROL].offset = 0x1f00 + offset;
+ ch->r_io[ATA_SACTIVE].res = ctlr->r_res2;
+ ch->r_io[ATA_SACTIVE].offset = 0x1f0c + offset;
+
+ ch->hw.begin_transaction = ata_siiprb_begin_transaction;
+ ch->hw.end_transaction = ata_siiprb_end_transaction;
+ ch->hw.status = ata_siiprb_status;
+ ch->hw.command = NULL; /* not used here */
+ return 0;
+}
+
+static int
+ata_siiprb_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_res1, 0x0044);
+ int offset = ch->unit * 0x2000;
+
+ if (action & (1 << ch->unit)) {
+ u_int32_t istatus = ATA_INL(ctlr->r_res2, 0x1008 + offset);
+
+ /* do we have any PHY events ? */
+ ata_sata_phy_check_events(dev);
+
+ /* clear interrupt(s) */
+ ATA_OUTL(ctlr->r_res2, 0x1008 + offset, istatus);
+
+ /* do we have any device action ? */
+ return (istatus & 0x00000003);
+ }
+ return 0;
+}
+
+static int
+ata_siiprb_begin_transaction(struct ata_request *request)
+{
+ struct ata_pci_controller *ctlr=device_get_softc(GRANDPARENT(request->dev));
+ struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
+ struct ata_siiprb_command *prb;
+ struct ata_siiprb_dma_prdentry *prd;
+ int offset = ch->unit * 0x2000;
+ u_int64_t prb_bus;
+ int tag = 0, dummy;
+
+ /* SOS XXX */
+ if (request->u.ata.command == ATA_DEVICE_RESET) {
+ request->result = 0;
+ return ATA_OP_FINISHED;
+ }
+
+ /* check for 48 bit access and convert if needed */
+ ata_modify_if_48bit(request);
+
+ /* get a piece of the workspace for this request */
+ prb = (struct ata_siiprb_command *)
+ (ch->dma->work + (sizeof(struct ata_siiprb_command) * tag));
+
+ /* set basic prd options ata/atapi etc etc */
+ bzero(prb, sizeof(struct ata_siiprb_command));
+
+ /* setup the FIS for this request */
+ if (!ata_request2fis_h2d(request, &prb->fis[0])) {
+ device_printf(request->dev, "setting up SATA FIS failed\n");
+ request->result = EIO;
+ return ATA_OP_FINISHED;
+ }
+
+ /* setup transfer type */
+ if (request->flags & ATA_R_ATAPI) {
+ struct ata_device *atadev = device_get_softc(request->dev);
+
+ bcopy(request->u.atapi.ccb, prb->u.atapi.ccb, 16);
+ if ((atadev->param.config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12)
+ ATA_OUTL(ctlr->r_res2, 0x1004 + offset, 0x00000020);
+ else
+ ATA_OUTL(ctlr->r_res2, 0x1000 + offset, 0x00000020);
+ if (request->flags & ATA_R_READ)
+ prb->control = htole16(0x0010);
+ if (request->flags & ATA_R_WRITE)
+ prb->control = htole16(0x0020);
+ prd = &prb->u.atapi.prd[0];
+ }
+ else
+ prd = &prb->u.ata.prd[0];
+
+ /* if request moves data setup and load SG list */
+ if (request->flags & (ATA_R_READ | ATA_R_WRITE)) {
+ if (ch->dma->load(ch->dev, request->data, request->bytecount,
+ request->flags & ATA_R_READ, prd, &dummy)) {
+ device_printf(request->dev, "setting up DMA failed\n");
+ request->result = EIO;
+ return ATA_OP_FINISHED;
+ }
+ }
+
+ /* activate the prb */
+ prb_bus = ch->dma->work_bus + (sizeof(struct ata_siiprb_command) * tag);
+ ATA_OUTL(ctlr->r_res2,
+ 0x1c00 + offset + (tag * sizeof(u_int64_t)), prb_bus);
+ ATA_OUTL(ctlr->r_res2,
+ 0x1c04 + offset + (tag * sizeof(u_int64_t)), prb_bus>>32);
+
+ /* start the timeout */
+ callout_reset(&request->callout, request->timeout * hz,
+ (timeout_t*)ata_timeout, request);
+ return ATA_OP_CONTINUES;
+}
+
+static int
+ata_siiprb_end_transaction(struct ata_request *request)
+{
+ struct ata_pci_controller *ctlr=device_get_softc(GRANDPARENT(request->dev));
+ struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
+ struct ata_siiprb_command *prb;
+ int offset = ch->unit * 0x2000;
+ int error, timeout, tag = 0;
+
+ /* kill the timeout */
+ callout_stop(&request->callout);
+
+ prb = (struct ata_siiprb_command *)
+ ((u_int8_t *)rman_get_virtual(ctlr->r_res2) + (tag << 7) + offset);
+
+ /* any controller errors flagged ? */
+ if ((error = ATA_INL(ctlr->r_res2, 0x1024 + offset))) {
+ if (bootverbose)
+ printf("ata_siiprb_end_transaction %s error=%08x\n",
+ ata_cmd2str(request), error);
+
+ /* if device error status get details */
+ if (error == 1 || error == 2) {
+ request->status = prb->fis[2];
+ if (request->status & ATA_S_ERROR)
+ request->error = prb->fis[3];
+ }
+
+ /* SOS XXX handle other controller errors here */
+
+ /* initialize port */
+ ATA_OUTL(ctlr->r_res2, 0x1000 + offset, 0x00000004);
+
+ /* poll for port ready */
+ for (timeout = 0; timeout < 1000; timeout++) {
+ DELAY(1000);
+ if (ATA_INL(ctlr->r_res2, 0x1008 + offset) & 0x00040000)
+ break;
+ }
+ if (bootverbose) {
+ if (timeout >= 1000)
+ device_printf(ch->dev, "port initialize timeout\n");
+ else
+ device_printf(ch->dev, "port initialize time=%dms\n", timeout);
+ }
+ }
+
+ /* update progress */
+ if (!(request->status & ATA_S_ERROR) && !(request->flags & ATA_R_TIMEOUT)) {
+ if (request->flags & ATA_R_READ)
+ request->donecount = prb->transfer_count;
+ else
+ request->donecount = request->bytecount;
+ }
+
+ /* release SG list etc */
+ ch->dma->unload(ch->dev);
+
+ return ATA_OP_FINISHED;
+}
+
+static void
+ata_siiprb_reset(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 * 0x2000;
+ struct ata_siiprb_command *prb;
+ u_int64_t prb_bus;
+ u_int32_t status, signature;
+ int timeout, tag = 0;
+
+ /* reset channel HW */
+ ATA_OUTL(ctlr->r_res2, 0x1000 + offset, 0x00000001);
+ DELAY(1000);
+ ATA_OUTL(ctlr->r_res2, 0x1004 + offset, 0x00000001);
+ DELAY(10000);
+
+ /* poll for channel ready */
+ for (timeout = 0; timeout < 1000; timeout++) {
+ if ((status = ATA_INL(ctlr->r_res2, 0x1008 + offset)) & 0x00040000)
+ break;
+ DELAY(1000);
+ }
+
+ if (bootverbose) {
+ if (timeout >= 1000)
+ device_printf(ch->dev, "channel HW reset timeout\n");
+ else
+ device_printf(ch->dev, "channel HW reset time=%dms\n", timeout);
+ }
+
+ /* reset phy */
+ if (!ata_sata_phy_reset(dev)) {
+ if (bootverbose)
+ device_printf(ch->dev, "phy reset found no device\n");
+ ch->devices = 0;
+ goto finish;
+ }
+
+ /* get a piece of the workspace for a soft reset request */
+ prb = (struct ata_siiprb_command *)
+ (ch->dma->work + (sizeof(struct ata_siiprb_command) * tag));
+ bzero(prb, sizeof(struct ata_siiprb_command));
+ prb->control = htole16(0x0080);
+
+ /* activate the soft reset prb */
+ prb_bus = ch->dma->work_bus + (sizeof(struct ata_siiprb_command) * tag);
+ ATA_OUTL(ctlr->r_res2,
+ 0x1c00 + offset + (tag * sizeof(u_int64_t)), prb_bus);
+ ATA_OUTL(ctlr->r_res2,
+ 0x1c04 + offset + (tag * sizeof(u_int64_t)), prb_bus>>32);
+
+ /* poll for command finished */
+ for (timeout = 0; timeout < 10000; timeout++) {
+ DELAY(1000);
+ if ((status = ATA_INL(ctlr->r_res2, 0x1008 + offset)) & 0x00010000)
+ break;
+ }
+ if (timeout >= 1000) {
+ device_printf(ch->dev, "reset timeout - no device found\n");
+ ch->devices = 0;
+ goto finish;
+ }
+ if (bootverbose)
+ device_printf(ch->dev, "soft reset exec time=%dms status=%08x\n",
+ timeout, status);
+
+ /* find out whats there */
+ prb = (struct ata_siiprb_command *)
+ ((u_int8_t *)rman_get_virtual(ctlr->r_res2) + (tag << 7) + offset);
+ signature =
+ prb->fis[12]|(prb->fis[4]<<8)|(prb->fis[5]<<16)|(prb->fis[6]<<24);
+ if (bootverbose)
+ device_printf(ch->dev, "SIGNATURE=%08x\n", signature);
+ switch (signature) {
+ case 0x00000101:
+ ch->devices = ATA_ATA_MASTER;
+ break;
+ case 0x96690101:
+ ch->devices = ATA_PORTMULTIPLIER;
+ device_printf(ch->dev, "Portmultipliers not supported yet\n");
+ ch->devices = 0;
+ break;
+ case 0xeb140101:
+ ch->devices = ATA_ATAPI_MASTER;
+ break;
+ default:
+ ch->devices = 0;
+ }
+ if (bootverbose)
+ device_printf(dev, "siiprb_reset devices=0x%b\n", ch->devices,
+ "\20\4ATAPI_SLAVE\3ATAPI_MASTER\2ATA_SLAVE\1ATA_MASTER");
+
+finish:
+ /* clear interrupt(s) */
+ ATA_OUTL(ctlr->r_res2, 0x1008 + offset, 0x000008ff);
+
+ /* require explicit interrupt ack */
+ ATA_OUTL(ctlr->r_res2, 0x1000 + offset, 0x00000008);
+
+ /* 64bit mode */
+ ATA_OUTL(ctlr->r_res2, 0x1004 + offset, 0x00000400);
+
+ /* enable interrupts wanted */
+ ATA_OUTL(ctlr->r_res2, 0x1010 + offset, 0x000000ff);
+}
+
+static void
+ata_siiprb_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error)
+{
+ struct ata_dmasetprd_args *args = xsc;
+ struct ata_siiprb_dma_prdentry *prd = args->dmatab;
+ int i;
+
+ if ((args->error = error))
+ return;
+
+ for (i = 0; i < nsegs; i++) {
+ prd[i].addr = htole64(segs[i].ds_addr);
+ prd[i].count = htole32(segs[i].ds_len);
+ }
+ prd[i - 1].control = htole32(ATA_DMA_EOT);
+ KASSERT(nsegs <= ATA_DMA_ENTRIES, ("too many DMA segment entries\n"));
+ args->nsegs = nsegs;
+}
+
+static void
+ata_siiprb_dmainit(device_t dev)
+{
+ struct ata_channel *ch = device_get_softc(dev);
+
+ ata_dmainit(dev);
+ if (ch->dma) {
+ /* note start and stop are not used here */
+ ch->dma->setprd = ata_siiprb_dmasetprd;
+ ch->dma->max_address = BUS_SPACE_MAXADDR;
+ }
+}
+
+
/*
* Silicon Integrated Systems Corp. (SiS) chipset support functions
*/
@@ -4881,12 +5378,10 @@
static void
ata_sis_reset(device_t dev)
{
- struct ata_channel *ch = device_get_softc(dev);
-
- ata_sata_phy_enable(ch);
+ if (ata_sata_phy_reset(dev))
+ ata_generic_reset(dev);
}
-
static void
ata_sis_setmode(device_t dev, int mode)
{
@@ -4974,7 +5469,6 @@
ata_via_ident(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(dev);
- struct ata_chip_id *idx;
static struct ata_chip_id ids[] =
{{ ATA_VIA82C586, 0x02, VIA33, 0x00, ATA_UDMA2, "82C586B" },
{ ATA_VIA82C586, 0x00, VIA33, 0x00, ATA_WDMA2, "82C586" },
@@ -4990,30 +5484,28 @@
{ ATA_VIA8235, 0x00, VIA133, 0x00, ATA_UDMA6, "8235" },
{ ATA_VIA8237, 0x00, VIA133, 0x00, ATA_UDMA6, "8237" },
{ ATA_VIA8237A, 0x00, VIA133, 0x00, ATA_UDMA6, "8237A" },
+ { ATA_VIA8237S, 0x00, VIA133, 0x00, ATA_UDMA6, "8237S" },
{ ATA_VIA8251, 0x00, VIA133, 0x00, ATA_UDMA6, "8251" },
{ 0, 0, 0, 0, 0, 0 }};
static struct ata_chip_id new_ids[] =
{{ ATA_VIA6410, 0x00, 0, 0x00, ATA_UDMA6, "6410" },
{ ATA_VIA6420, 0x00, 7, 0x00, ATA_SA150, "6420" },
{ ATA_VIA6421, 0x00, 6, VIABAR, ATA_SA150, "6421" },
- { ATA_VIA8237A, 0x00, 0, 0x00, ATA_SA150, "8237A" },
+ { ATA_VIA8237A, 0x00, 7, 0x00, ATA_SA150, "8237A" },
+ { ATA_VIA8237S, 0x00, 7, 0x00, ATA_SA150, "8237S" },
{ ATA_VIA8251, 0x00, 0, VIAAHCI, ATA_SA300, "8251" },
{ 0, 0, 0, 0, 0, 0 }};
- char buffer[64];
if (pci_get_devid(dev) == ATA_VIA82C571) {
- if (!(idx = ata_find_chip(dev, ids, -99)))
+ if (!(ctlr->chip = ata_find_chip(dev, ids, -99)))
return ENXIO;
}
else {
- if (!(idx = ata_match_chip(dev, new_ids)))
+ if (!(ctlr->chip = ata_match_chip(dev, new_ids)))
return ENXIO;
}
- sprintf(buffer, "VIA %s %s controller",
- idx->text, ata_mode2str(idx->max_dma));
- device_set_desc_copy(dev, buffer);
- ctlr->chip = idx;
+ ata_set_desc(dev);
ctlr->chipinit = ata_via_chipinit;
return 0;
}
@@ -5027,15 +5519,10 @@
return ENXIO;
if (ctlr->chip->max_dma >= ATA_SA150) {
- if (ctlr->chip->cfg2 == VIAAHCI) {
- 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 ata_ahci_chipinit(dev);
- }
- }
+ /* do we have AHCI capability ? */
+ if ((ctlr->chip->cfg2 == VIAAHCI) && ata_ahci_chipinit(dev) != ENXIO)
+ return 0;
+
ctlr->r_type2 = SYS_RES_IOPORT;
ctlr->r_rid2 = PCIR_BAR(5);
if ((ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2,
@@ -5047,7 +5534,13 @@
pci_write_config(dev, PCIR_COMMAND,
pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400,2);
}
- ctlr->setmode = ata_sata_setmode;
+
+ if (ctlr->chip->cfg2 & VIABAR) {
+ ctlr->channels = 3;
+ ctlr->setmode = ata_via_setmode;
+ }
+ else
+ ctlr->setmode = ata_sata_setmode;
return 0;
}
@@ -5108,6 +5601,8 @@
ch->r_io[i].offset = (i - ATA_BMCMD_PORT)+(ch->unit * ATA_BMIOSIZE);
}
ata_pci_hw(dev);
+ if (ch->unit >= 2)
+ return 0;
}
else {
/* setup the usual register normal pci style */
@@ -5131,9 +5626,47 @@
static void
ata_via_reset(device_t dev)
{
+ struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
- ata_sata_phy_enable(ch);
+ if ((ctlr->chip->cfg2 & VIABAR) && (ch->unit > 1))
+ ata_generic_reset(dev);
+ else
+ if (ata_sata_phy_reset(dev))
+ ata_generic_reset(dev);
+}
+
+static void
+ata_via_setmode(device_t dev, int mode)
+{
+ device_t gparent = GRANDPARENT(dev);
+ struct ata_pci_controller *ctlr = device_get_softc(gparent);
+ struct ata_channel *ch = device_get_softc(device_get_parent(dev));
+ struct ata_device *atadev = device_get_softc(dev);
+ int error;
+
+ if ((ctlr->chip->cfg2 & VIABAR) && (ch->unit > 1)) {
+ u_int8_t pio_timings[] = { 0xa8, 0x65, 0x65, 0x32, 0x20,
+ 0x65, 0x32, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
+ u_int8_t dma_timings[] = { 0xee, 0xe8, 0xe6, 0xe4, 0xe2, 0xe1, 0xe0 };
+
+ mode = ata_check_80pin(dev, ata_limit_mode(dev, mode, ATA_UDMA6));
+ error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode);
+ if (bootverbose)
+ device_printf(dev, "%ssetting %s on %s chip\n",
+ (error) ? "FAILURE " : "", ata_mode2str(mode),
+ ctlr->chip->text);
+ if (!error) {
+ pci_write_config(gparent, 0xab, pio_timings[ata_mode2idx(mode)], 1);
+ if (mode >= ATA_UDMA0)
+ pci_write_config(gparent, 0xb3,
+ dma_timings[mode & ATA_MODE_MASK], 1);
+ atadev->mode = mode;
+ }
+ }
+ else
+ ata_sata_setmode(dev, mode);
}
static void
@@ -5174,7 +5707,7 @@
struct ata_channel *ch = device_get_softc(device_get_parent(dev));
struct ata_device *atadev = device_get_softc(dev);
u_int8_t timings[] = { 0xa8, 0x65, 0x42, 0x22, 0x20, 0x42, 0x22, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
int modes[][7] = {
{ 0xc2, 0xc1, 0xc0, 0x00, 0x00, 0x00, 0x00 }, /* VIA ATA33 */
{ 0xee, 0xec, 0xea, 0xe9, 0xe8, 0x00, 0x00 }, /* VIA ATA66 */
@@ -5221,6 +5754,18 @@
/* misc functions */
+static void
+ata_set_desc(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+ char buffer[128];
+
+ sprintf(buffer, "%s %s %s controller",
+ ata_pcivendor2str(dev), ctlr->chip->text,
+ ata_mode2str(ctlr->chip->max_dma));
+ device_set_desc_copy(dev, buffer);
+}
+
static struct ata_chip_id *
ata_match_chip(device_t dev, struct ata_chip_id *index)
{
@@ -5270,8 +5815,9 @@
device_printf(dev, "unable to map interrupt\n");
return ENXIO;
}
- if ((bus_setup_intr(dev, ctlr->r_irq, ATA_INTR_FLAGS,
+ if ((bus_setup_intr(dev, ctlr->r_irq, ATA_INTR_FLAGS, NULL,
ata_generic_intr, ctlr, &ctlr->handle))) {
+ /* SOS XXX release r_irq */
device_printf(dev, "unable to setup interrupt\n");
return ENXIO;
}
Index: atapi-cd.c
===================================================================
RCS file: /home/cvs/src/sys/dev/ata/atapi-cd.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -L sys/dev/ata/atapi-cd.c -L sys/dev/ata/atapi-cd.c -u -r1.4 -r1.5
--- sys/dev/ata/atapi-cd.c
+++ sys/dev/ata/atapi-cd.c
@@ -34,6 +34,7 @@
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/malloc.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/bio.h>
#include <sys/bus.h>
@@ -257,8 +258,11 @@
cdp->flags |= F_LOCKED;
break;
+ /*
+ * XXXRW: Why does this require privilege?
+ */
case CDIOCRESET:
- error = suser(td);
+ error = priv_check(td, PRIV_DRIVER);
if (error)
break;
error = acd_test_ready(dev);
@@ -709,7 +713,7 @@
request->u.atapi.sense.key == 7) &&
request->u.atapi.sense.asc == 4 &&
request->u.atapi.sense.ascq == 1)
- tsleep(&timeout, PRIBIO, "acdld", hz / 2);
+ pause("acdld", hz / 2);
else
break;
}
@@ -1094,7 +1098,7 @@
/* some drives just return ready, wait for the expected fixate time */
if ((error = acd_test_ready(dev)) != EBUSY) {
timeout = timeout / (cdp->cap.cur_write_speed / 177);
- tsleep(&error, PRIBIO, "acdfix", timeout * hz / 2);
+ pause("acdfix", timeout * hz / 2);
return acd_test_ready(dev);
}
@@ -1103,7 +1107,7 @@
return error;
if ((error = acd_test_ready(dev)) != EBUSY)
return error;
- tsleep(&error, PRIBIO, "acdcld", hz / 2);
+ pause("acdcld", hz / 2);
}
return EIO;
}
@@ -1237,10 +1241,8 @@
request->flags = ATA_R_ATAPI | ATA_R_READ;
request->timeout = 30;
ata_queue_request(request);
-/* rgb - fix for pr 109270 from Martin Birgmeier
- if (!request->error && request->u.atapi.sense.error & ATA_SENSE_VALID)
-*/
- if (!request->error && request->u.atapi.sense.specific & ATA_SENSE_SPEC_VALID)
+ if (!request->error &&
+ request->u.atapi.sense.specific & ATA_SENSE_SPEC_VALID)
*finished = ((request->u.atapi.sense.specific2 |
(request->u.atapi.sense.specific1<<8))*100)/65535;
else
@@ -1341,7 +1343,8 @@
error = ata_atapicmd(dev, ccb, (caddr_t)d, length,
ai->format == DVD_INVALIDATE_AGID ? 0 : ATA_R_READ,10);
if (error) {
- free(d, M_ACD);
+ if (length)
+ free(d, M_ACD);
return error;
}
@@ -1383,7 +1386,8 @@
default:
error = EINVAL;
}
- free(d, M_ACD);
+ if (length)
+ free(d, M_ACD);
return error;
}
@@ -1639,13 +1643,15 @@
acd_get_cap(device_t dev)
{
struct acd_softc *cdp = device_get_ivars(dev);
+ int8_t ccb[16] = { ATAPI_MODE_SENSE_BIG, 0, ATAPI_CDROM_CAP_PAGE,
+ 0, 0, 0, 0, sizeof(cdp->cap)>>8, sizeof(cdp->cap),
+ 0, 0, 0, 0, 0, 0, 0 };
int count;
/* get drive capabilities, some bugridden drives needs this repeated */
for (count = 0 ; count < 5 ; count++) {
- if (!acd_mode_sense(dev, ATAPI_CDROM_CAP_PAGE,
- (caddr_t)&cdp->cap, sizeof(cdp->cap)) &&
- cdp->cap.page_code == ATAPI_CDROM_CAP_PAGE) {
+ if (!ata_atapicmd(dev, ccb, (caddr_t)&cdp->cap, sizeof(cdp->cap),
+ ATA_R_READ | ATA_R_QUIET, 5)) {
cdp->cap.max_read_speed = ntohs(cdp->cap.max_read_speed);
cdp->cap.cur_read_speed = ntohs(cdp->cap.cur_read_speed);
cdp->cap.max_write_speed = ntohs(cdp->cap.max_write_speed);
@@ -1824,6 +1830,8 @@
printf("CD-R "); break;
case MST_CDRW:
printf("CD-RW "); break;
+ case MST_DVD:
+ printf("DVD "); break;
case MST_DOOR_OPEN:
printf("door open"); break;
case MST_NO_DISC:
More information about the Midnightbsd-cvs
mailing list