Date: Sat, 04 Oct 2008 19:38:09 +0400 From: "Andrey V. Elsukov" <bu7cher@yandex.ru> To: freebsd-stable@freebsd.org Cc: kib@freebsd.org, sos@freebsd.org Subject: Request for testing: ata(4) MFC Message-ID: <676151223134689@webmail38.yandex.ru>
index | next in thread | raw e-mail
[-- Attachment #1 --]
Hi, All.
I prepared patch to make MFC of ata(4) driver into RELENG_7
before 7.1-RELEASE. Depending on results of the testing patch
will be commited or not (if some regressions will be detected).
So if you want or just can test it, please try and report here.
--
WBR, Andrey V. Elsukov
[-- Attachment #2 --]
--- src/sys/dev/ata/ata-all.c 2008-09-29 23:54:38.000000000 +0400
+++ src/sys/dev/ata/ata-all.c 2008-08-15 14:55:11.000000000 +0400
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -62,7 +62,6 @@ static struct cdevsw ata_cdevsw = {
/* prototypes */
static void ata_boot_attach(void);
static device_t ata_add_child(device_t, struct ata_device *, int);
-static int ata_getparam(struct ata_device *, int);
static void bswap(int8_t *, int);
static void btrim(int8_t *, int);
static void bpack(int8_t *, int8_t *, int);
@@ -75,6 +74,7 @@ devclass_t ata_devclass;
uma_zone_t ata_request_zone;
uma_zone_t ata_composite_zone;
int ata_wc = 1;
+int ata_setmax = 0;
int ata_dma_check_80pin = 1;
/* local vars */
@@ -96,6 +96,9 @@ SYSCTL_INT(_hw_ata, OID_AUTO, atapi_dma,
TUNABLE_INT("hw.ata.wc", &ata_wc);
SYSCTL_INT(_hw_ata, OID_AUTO, wc, CTLFLAG_RDTUN, &ata_wc, 0,
"ATA disk write caching");
+TUNABLE_INT("hw.ata.setmax", &ata_setmax);
+SYSCTL_INT(_hw_ata, OID_AUTO, setmax, CTLFLAG_RDTUN, &ata_setmax, 0,
+ "ATA disk set max native address");
/*
* newbus device interface related functions
@@ -131,6 +134,10 @@ ata_attach(device_t dev)
ATA_RESET(dev);
ATA_LOCKING(dev, ATA_LF_UNLOCK);
+ /* allocate DMA resources if DMA HW present*/
+ if (ch->dma.alloc)
+ ch->dma.alloc(dev);
+
/* setup interrupt delivery */
rid = ATA_IRQ_RID;
ch->r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
@@ -409,13 +416,13 @@ ata_ioctl(struct cdev *dev, u_long cmd,
if (children[i] && device_is_attached(children[i])) {
struct ata_device *atadev = device_get_softc(children[i]);
- if (atadev->unit == ATA_MASTER) {
+ if (atadev->unit == ATA_MASTER) { /* XXX SOS PM */
strncpy(devices->name[0],
device_get_nameunit(children[i]), 32);
bcopy(&atadev->param, &devices->params[0],
sizeof(struct ata_params));
}
- if (atadev->unit == ATA_SLAVE) {
+ if (atadev->unit == ATA_SLAVE) { /* XXX SOS PM */
strncpy(devices->name[1],
device_get_nameunit(children[i]), 32);
bcopy(&atadev->param, &devices->params[1],
@@ -457,6 +464,7 @@ ata_device_ioctl(device_t dev, u_long cm
free(buf, M_ATA);
return ENOMEM;
}
+ request->dev = atadev->dev;
if (ioc_request->flags & ATA_CMD_WRITE) {
error = copyin(ioc_request->data, buf, ioc_request->count);
if (error) {
@@ -465,7 +473,6 @@ ata_device_ioctl(device_t dev, u_long cm
return error;
}
}
- request->dev = dev;
if (ioc_request->flags & ATA_CMD_ATAPI) {
request->flags = ATA_R_ATAPI;
bcopy(ioc_request->u.atapi.ccb, request->u.atapi.ccb, 16);
@@ -574,7 +581,7 @@ ata_add_child(device_t parent, struct at
return child;
}
-static int
+int
ata_getparam(struct ata_device *atadev, int init)
{
struct ata_channel *ch = device_get_softc(device_get_parent(atadev->dev));
@@ -582,11 +589,9 @@ ata_getparam(struct ata_device *atadev,
u_int8_t command = 0;
int error = ENOMEM, retries = 2;
- if (ch->devices &
- (atadev->unit == ATA_MASTER ? ATA_ATA_MASTER : ATA_ATA_SLAVE))
+ if (ch->devices & (ATA_ATA_MASTER << atadev->unit))
command = ATA_ATA_IDENTIFY;
- if (ch->devices &
- (atadev->unit == ATA_MASTER ? ATA_ATAPI_MASTER : ATA_ATAPI_SLAVE))
+ if (ch->devices & (ATA_ATAPI_MASTER << atadev->unit))
command = ATA_ATAPI_IDENTIFY;
if (!command)
return ENXIO;
@@ -636,7 +641,7 @@ ata_getparam(struct ata_device *atadev,
if (bootverbose)
printf("ata%d-%s: pio=%s wdma=%s udma=%s cable=%s wire\n",
device_get_unit(ch->dev),
- atadev->unit == ATA_MASTER ? "master" : "slave",
+ ata_unit2str(atadev),
ata_mode2str(ata_pmode(atacap)),
ata_mode2str(ata_wmode(atacap)),
ata_mode2str(ata_umode(atacap)),
@@ -648,13 +653,13 @@ ata_getparam(struct ata_device *atadev,
if ((atadev->param.config & ATA_PROTO_ATAPI) &&
(atadev->param.config != ATA_CFA_MAGIC1) &&
(atadev->param.config != ATA_CFA_MAGIC2)) {
- if (atapi_dma && ch->dma &&
+ if (atapi_dma &&
(atadev->param.config & ATA_DRQ_MASK) != ATA_DRQ_INTR &&
ata_umode(&atadev->param) >= ATA_UDMA2)
atadev->mode = ATA_DMA_MAX;
}
else {
- if (ata_dma && ch->dma &&
+ if (ata_dma &&
(ata_umode(&atadev->param) > 0 ||
ata_wmode(&atadev->param) > 0))
atadev->mode = ATA_DMA_MAX;
@@ -672,52 +677,42 @@ int
ata_identify(device_t dev)
{
struct ata_channel *ch = device_get_softc(dev);
- struct ata_device *master = NULL, *slave = NULL;
- device_t master_child = NULL, slave_child = NULL;
- int master_unit = -1, slave_unit = -1;
-
- if (ch->devices & (ATA_ATA_MASTER | ATA_ATAPI_MASTER)) {
- if (!(master = malloc(sizeof(struct ata_device),
- M_ATA, M_NOWAIT | M_ZERO))) {
- device_printf(dev, "out of memory\n");
- return ENOMEM;
- }
- master->unit = ATA_MASTER;
- }
- if (ch->devices & (ATA_ATA_SLAVE | ATA_ATAPI_SLAVE)) {
- if (!(slave = malloc(sizeof(struct ata_device),
- M_ATA, M_NOWAIT | M_ZERO))) {
- free(master, M_ATA);
- device_printf(dev, "out of memory\n");
- return ENOMEM;
- }
- slave->unit = ATA_SLAVE;
- }
+ struct ata_device *devices[ATA_PM];
+ device_t childdevs[ATA_PM];
+ int i;
+ if (bootverbose)
+ device_printf(dev, "identify ch->devices=%08x\n", ch->devices);
+
+ for (i = 0; i < ATA_PM; ++i) {
+ if (ch->devices & (((ATA_ATA_MASTER | ATA_ATAPI_MASTER) << i))) {
+ int unit = -1;
+
+ if (!(devices[i] = malloc(sizeof(struct ata_device),
+ M_ATA, M_NOWAIT | M_ZERO))) {
+ device_printf(dev, "out of memory\n");
+ return ENOMEM;
+ }
+ devices[i]->unit = i;
#ifdef ATA_STATIC_ID
- if (ch->devices & ATA_ATA_MASTER)
- master_unit = (device_get_unit(dev) << 1);
-#endif
- if (master && !(master_child = ata_add_child(dev, master, master_unit))) {
- free(master, M_ATA);
- master = NULL;
- }
-#ifdef ATA_STATIC_ID
- if (ch->devices & ATA_ATA_SLAVE)
- slave_unit = (device_get_unit(dev) << 1) + 1;
+ if (ch->devices & ((ATA_ATA_MASTER << i)))
+ unit = (device_get_unit(dev) << 1) + i;
#endif
- if (slave && !(slave_child = ata_add_child(dev, slave, slave_unit))) {
- free(slave, M_ATA);
- slave = NULL;
- }
-
- if (slave && ata_getparam(slave, 1)) {
- device_delete_child(dev, slave_child);
- free(slave, M_ATA);
- }
- if (master && ata_getparam(master, 1)) {
- device_delete_child(dev, master_child);
- free(master, M_ATA);
+ if (!(childdevs[i] = ata_add_child(dev, devices[i], unit))) {
+ free(devices[i], M_ATA);
+ devices[i]=NULL;
+ }
+ else {
+ if (ata_getparam(devices[i], 1)) {
+ device_delete_child(dev, childdevs[i]);
+ free(devices[i], M_ATA);
+ childdevs[i] = NULL;
+ devices[i] = NULL;
+ }
+ }
+ }
+ devices[i] = NULL;
+ childdevs[i] = NULL;
}
bus_generic_probe(dev);
@@ -815,8 +810,23 @@ ata_modify_if_48bit(struct ata_request *
case ATA_FLUSHCACHE:
request->u.ata.command = ATA_FLUSHCACHE48;
break;
- case ATA_READ_NATIVE_MAX_ADDDRESS:
- request->u.ata.command = ATA_READ_NATIVE_MAX_ADDDRESS48;
+ case ATA_SET_MAX_ADDRESS:
+ request->u.ata.command = ATA_SET_MAX_ADDRESS48;
+ break;
+ default:
+ return;
+ }
+ atadev->flags |= ATA_D_48BIT_ACTIVE;
+ }
+ else if (atadev->param.support.command2 & ATA_SUPPORT_ADDRESS48) {
+
+ /* translate command into 48bit version */
+ switch (request->u.ata.command) {
+ case ATA_FLUSHCACHE:
+ request->u.ata.command = ATA_FLUSHCACHE48;
+ break;
+ case ATA_READ_NATIVE_MAX_ADDRESS:
+ request->u.ata.command = ATA_READ_NATIVE_MAX_ADDRESS48;
break;
case ATA_SET_MAX_ADDRESS:
request->u.ata.command = ATA_SET_MAX_ADDRESS48;
@@ -839,6 +849,19 @@ ata_udelay(int interval)
}
char *
+ata_unit2str(struct ata_device *atadev)
+{
+ struct ata_channel *ch = device_get_softc(device_get_parent(atadev->dev));
+ static char str[8];
+
+ if (ch->devices & ATA_PORTMULTIPLIER)
+ sprintf(str, "port%d", atadev->unit);
+ else
+ sprintf(str, "%s", atadev->unit == ATA_MASTER ? "master" : "slave");
+ return str;
+}
+
+char *
ata_mode2str(int mode)
{
switch (mode) {
--- src/sys/dev/ata/ata-all.h 2008-08-22 12:09:13.000000000 +0400
+++ src/sys/dev/ata/ata-all.h 2008-08-15 14:55:11.000000000 +0400
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -149,6 +149,7 @@
/* SATA AHCI v1.0 register defines */
#define ATA_AHCI_CAP 0x00
#define ATA_AHCI_NPMASK 0x1f
+#define ATA_AHCI_CAP_SPM 0x00020000
#define ATA_AHCI_CAP_CLO 0x01000000
#define ATA_AHCI_CAP_64BIT 0x80000000
@@ -220,13 +221,14 @@
#define ATA_AHCI_P_SERR 0x130
#define ATA_AHCI_P_SACT 0x134
#define ATA_AHCI_P_CI 0x138
+#define ATA_AHCI_P_SNTF 0x13C
+#define ATA_AHCI_P_FBS 0x140
#define ATA_AHCI_CL_SIZE 32
#define ATA_AHCI_CL_OFFSET 0
-#define ATA_AHCI_FB_OFFSET 1024
-#define ATA_AHCI_CT_OFFSET 1024+256
-#define ATA_AHCI_CT_SG_OFFSET 128
-#define ATA_AHCI_CT_SIZE 256
+#define ATA_AHCI_FB_OFFSET (ATA_AHCI_CL_SIZE * 32)
+#define ATA_AHCI_CT_OFFSET (ATA_AHCI_FB_OFFSET + 4096)
+#define ATA_AHCI_CT_SIZE (1024 + 128)
struct ata_ahci_dma_prd {
u_int64_t dba;
@@ -240,11 +242,19 @@ 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];
+#define ATA_AHCI_DMA_ENTRIES 64
+ struct ata_ahci_dma_prd prd_tab[ATA_AHCI_DMA_ENTRIES];
} __packed;
struct ata_ahci_cmd_list {
u_int16_t cmd_flags;
+#define ATA_AHCI_CMD_ATAPI 0x0020
+#define ATA_AHCI_CMD_WRITE 0x0040
+#define ATA_AHCI_CMD_PREFETCH 0x0080
+#define ATA_AHCI_CMD_RESET 0x0100
+#define ATA_AHCI_CMD_BIST 0x0200
+#define ATA_AHCI_CMD_CLR_BUSY 0x0400
+
u_int16_t prd_length; /* PRD entries */
u_int32_t bytecount;
u_int64_t cmd_table_phys; /* 128byte aligned */
@@ -291,7 +301,7 @@ struct ata_ahci_cmd_list {
#define ATA_PC98_CTLADDR_RID 8
#define ATA_PC98_BANKADDR_RID 9
#define ATA_IRQ_RID 0
-#define ATA_DEV(device) ((device == ATA_MASTER) ? 0 : 1)
+#define ATA_DEV(unit) ((unit > 0) ? 0x10 : 0)
#define ATA_CFA_MAGIC1 0x844A
#define ATA_CFA_MAGIC2 0x848A
#define ATA_CFA_MAGIC3 0x8400
@@ -343,6 +353,7 @@ struct ata_request {
u_int32_t bytecount; /* bytes to transfer */
u_int32_t transfersize; /* bytes pr transfer */
caddr_t data; /* pointer to data buf */
+ u_int32_t tag; /* HW tag of this request */
int flags;
#define ATA_R_CONTROL 0x00000001
#define ATA_R_READ 0x00000002
@@ -362,9 +373,9 @@ struct ata_request {
#define ATA_R_DANGER1 0x20000000
#define ATA_R_DANGER2 0x40000000
+ struct ata_dmaslot *dma; /* DMA slot of this request */
u_int8_t status; /* ATA status */
u_int8_t error; /* ATA error */
- u_int8_t dmastat; /* DMA status */
u_int32_t donecount; /* bytes transferred */
int result; /* result error code */
void (*callback)(struct ata_request *request);
@@ -398,7 +409,8 @@ struct ata_device {
device_t dev; /* device handle */
int unit; /* physical unit */
#define ATA_MASTER 0x00
-#define ATA_SLAVE 0x10
+#define ATA_SLAVE 0x01
+#define ATA_PM 0x0f
struct ata_params param; /* ata param structure */
int mode; /* current transfermode */
@@ -426,43 +438,50 @@ struct ata_dmasetprd_args {
int error;
};
-/* structure holding DMA related information */
-struct ata_dma {
- bus_dma_tag_t dmatag; /* parent DMA tag */
+struct ata_dmaslot {
+ u_int8_t status; /* DMA status */
bus_dma_tag_t sg_tag; /* SG list DMA tag */
bus_dmamap_t sg_map; /* SG list DMA map */
void *sg; /* DMA transfer table */
bus_addr_t sg_bus; /* bus address of dmatab */
bus_dma_tag_t data_tag; /* data DMA tag */
bus_dmamap_t data_map; /* data DMA map */
+};
+
+/* structure holding DMA related information */
+struct ata_dma {
+ bus_dma_tag_t dmatag; /* parent DMA tag */
bus_dma_tag_t work_tag; /* workspace DMA tag */
bus_dmamap_t work_map; /* workspace DMA map */
u_int8_t *work; /* workspace */
bus_addr_t work_bus; /* bus address of dmatab */
+#define ATA_DMA_SLOTS 32
+ int dma_slots; /* DMA slots allocated */
+ struct ata_dmaslot slot[ATA_DMA_SLOTS];
u_int32_t alignment; /* DMA SG list alignment */
u_int32_t boundary; /* DMA SG list boundary */
u_int32_t segsize; /* DMA SG list segment size */
u_int32_t max_iosize; /* DMA data max IO size */
- u_int32_t cur_iosize; /* DMA data current IO size */
u_int64_t max_address; /* highest DMA'able address */
int flags;
-#define ATA_DMA_READ 0x01 /* transaction is a read */
-#define ATA_DMA_LOADED 0x02 /* DMA tables etc loaded */
-#define ATA_DMA_ACTIVE 0x04 /* DMA transfer in progress */
+#define ATA_DMA_ACTIVE 0x01 /* DMA transfer in progress */
void (*alloc)(device_t dev);
void (*free)(device_t dev);
void (*setprd)(void *xsc, bus_dma_segment_t *segs, int nsegs, int error);
- int (*load)(device_t dev, caddr_t data, int32_t count, int dir, void *addr, int *nsegs);
- int (*unload)(device_t dev);
- int (*start)(device_t dev);
- int (*stop)(device_t dev);
+ int (*load)(struct ata_request *request, void *addr, int *nsegs);
+ int (*unload)(struct ata_request *request);
+ int (*start)(struct ata_request *request);
+ int (*stop)(struct ata_request *request);
void (*reset)(device_t dev);
};
/* structure holding lowlevel functions */
struct ata_lowlevel {
+ u_int32_t (*softreset)(device_t dev, int pmport);
+ int (*pm_read)(device_t dev, int port, int reg, u_int32_t *result);
+ int (*pm_write)(device_t dev, int port, int reg, u_int32_t value);
int (*status)(device_t dev);
int (*begin_transaction)(struct ata_request *request);
int (*end_transaction)(struct ata_request *request);
@@ -485,7 +504,7 @@ struct ata_channel {
struct resource *r_irq; /* interrupt of this channel */
void *ih; /* interrupt handle */
struct ata_lowlevel hw; /* lowlevel HW functions */
- struct ata_dma *dma; /* DMA data / functions */
+ struct ata_dma dma; /* DMA data / functions */
int flags; /* channel flags */
#define ATA_NO_SLAVE 0x01
#define ATA_USE_16BIT 0x02
@@ -494,11 +513,11 @@ struct ata_channel {
#define ATA_ALWAYS_DMASTAT 0x10
int devices; /* what is present */
-#define ATA_ATA_MASTER 0x01
-#define ATA_ATA_SLAVE 0x02
-#define ATA_ATAPI_MASTER 0x04
-#define ATA_ATAPI_SLAVE 0x08
-#define ATA_PORTMULTIPLIER 0x10
+#define ATA_ATA_MASTER 0x00000001
+#define ATA_ATA_SLAVE 0x00000002
+#define ATA_PORTMULTIPLIER 0x00008000
+#define ATA_ATAPI_MASTER 0x00010000
+#define ATA_ATAPI_SLAVE 0x00020000
struct mtx state_mtx; /* state lock */
int state; /* ATA channel state */
@@ -524,6 +543,7 @@ extern int (*ata_raid_ioctl_func)(u_long
extern struct intr_config_hook *ata_delayed_attach;
extern devclass_t ata_devclass;
extern int ata_wc;
+extern int ata_setmax;
extern int ata_dma_check_80pin;
/* public prototypes */
@@ -536,10 +556,12 @@ int ata_suspend(device_t dev);
int ata_resume(device_t dev);
int ata_interrupt(void *data);
int ata_device_ioctl(device_t dev, u_long cmd, caddr_t data);
+int ata_getparam(struct ata_device *atadev, int init);
int ata_identify(device_t dev);
void ata_default_registers(device_t dev);
void ata_modify_if_48bit(struct ata_request *request);
void ata_udelay(int interval);
+char *ata_unit2str(struct ata_device *atadev);
char *ata_mode2str(int mode);
int ata_pmode(struct ata_params *ap);
int ata_wmode(struct ata_params *ap);
@@ -571,6 +593,7 @@ extern uma_zone_t ata_request_zone;
if (!(request->flags & ATA_R_DANGER2)) \
uma_zfree(ata_request_zone, request); \
}
+
/* macros for alloc/free of struct ata_composite */
extern uma_zone_t ata_composite_zone;
#define ata_alloc_composite() uma_zalloc(ata_composite_zone, M_NOWAIT | M_ZERO)
--- src/sys/dev/ata/ata-card.c 2007-02-21 22:07:18.000000000 +0300
+++ src/sys/dev/ata/ata-card.c 2008-04-10 17:05:04.000000000 +0400
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
--- src/sys/dev/ata/ata-cbus.c 2007-02-23 15:18:32.000000000 +0300
+++ src/sys/dev/ata/ata-cbus.c 2008-04-10 17:05:05.000000000 +0400
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2002 - 2007 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 2002 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
--- src/sys/dev/ata/ata-chipset.c 2008-09-13 11:36:16.000000000 +0400
+++ src/sys/dev/ata/ata-chipset.c 2008-09-26 11:29:48.000000000 +0400
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -62,10 +62,15 @@ static int ata_sata_connect(struct ata_c
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_ctlr_reset(device_t dev);
+static int ata_ahci_suspend(device_t dev);
static int ata_ahci_allocate(device_t dev);
static int ata_ahci_status(device_t dev);
static int ata_ahci_begin_transaction(struct ata_request *request);
static int ata_ahci_end_transaction(struct ata_request *request);
+static int ata_ahci_pm_read(device_t dev, int port, int reg, u_int32_t *result);
+static int ata_ahci_pm_write(device_t dev, int port, int reg, u_int32_t result);
+static u_int32_t ata_ahci_softreset(device_t dev, int port);
static void ata_ahci_reset(device_t dev);
static void ata_ahci_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error);
static void ata_ahci_dmainit(device_t dev);
@@ -102,7 +107,8 @@ static int ata_intel_31244_status(device
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);
+static void ata_ite_8213_setmode(device_t dev, int mode);
+static void ata_ite_821x_setmode(device_t dev, int mode);
static int ata_jmicron_chipinit(device_t dev);
static int ata_jmicron_allocate(device_t dev);
static void ata_jmicron_reset(device_t dev);
@@ -130,8 +136,8 @@ static void ata_nvidia_reset(device_t de
static int ata_promise_chipinit(device_t dev);
static int ata_promise_allocate(device_t dev);
static int ata_promise_status(device_t dev);
-static int ata_promise_dmastart(device_t dev);
-static int ata_promise_dmastop(device_t dev);
+static int ata_promise_dmastart(struct ata_request *request);
+static int ata_promise_dmastop(struct ata_request *request);
static void ata_promise_dmareset(device_t dev);
static void ata_promise_dmainit(device_t dev);
static void ata_promise_setmode(device_t dev, int mode);
@@ -142,6 +148,9 @@ static void ata_promise_mio_intr(void *d
static int ata_promise_mio_status(device_t dev);
static int ata_promise_mio_command(struct ata_request *request);
static void ata_promise_mio_reset(device_t dev);
+static int ata_promise_mio_pm_read(device_t dev, int port, int reg, u_int32_t *result);
+static int ata_promise_mio_pm_write(device_t dev, int port, int reg, u_int32_t result);
+static u_int32_t ata_promise_mio_softreset(device_t dev, int port);
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);
@@ -167,6 +176,9 @@ static int ata_siiprb_allocate(device_t
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 int ata_siiprb_pm_read(device_t dev, int port, int reg, u_int32_t *result);
+static int ata_siiprb_pm_write(device_t dev, int port, int reg, u_int32_t result);
+static u_int32_t ata_siiprb_softreset(device_t dev, int port);
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);
@@ -268,15 +280,15 @@ ata_sata_phy_check_events(device_t dev)
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");
+ device_printf(dev, "CONNECT requested\n");
tp->action = ATA_C_ATTACH;
}
else {
if (bootverbose)
- device_printf(ch->dev, "DISCONNECT requested\n");
+ device_printf(dev, "DISCONNECT requested\n");
tp->action = ATA_C_DETACH;
}
- tp->dev = ch->dev;
+ tp->dev = dev;
TASK_INIT(&tp->task, 0, ata_sata_phy_event, tp);
taskqueue_enqueue(taskqueue_thread, &tp->task);
}
@@ -407,14 +419,112 @@ ata_sata_setmode(device_t dev, int mode)
}
}
+static void
+ata_pm_identify(device_t dev)
+{
+ struct ata_channel *ch = device_get_softc(dev);
+ u_int32_t pm_chipid, pm_revision, pm_ports;
+ int port;
+
+ /* get PM vendor & product data */
+ if (ch->hw.pm_read(dev, ATA_PM, 0, &pm_chipid)) {
+ device_printf(dev, "error getting PM vendor data\n");
+ return;
+ }
+
+ /* get PM revision data */
+ if (ch->hw.pm_read(dev, ATA_PM, 1, &pm_revision)) {
+ device_printf(dev, "error getting PM revison data\n");
+ return;
+ }
+
+ /* get number of HW ports on the PM */
+ if (ch->hw.pm_read(dev, ATA_PM, 2, &pm_ports)) {
+ device_printf(dev, "error getting PM port info\n");
+ return;
+ }
+ pm_ports &= 0x0000000f;
+
+ /* chip specific quirks */
+ switch (pm_chipid) {
+ case 0x37261095:
+ /* Some of these bogusly reports 6 ports */
+ pm_ports = 5;
+ device_printf(dev, "SiI 3726 r%x Portmultiplier with %d ports\n",
+ pm_revision, pm_ports);
+ break;
+
+ default:
+ device_printf(dev, "Portmultiplier (id=%08x rev=%x) with %d ports\n",
+ pm_chipid, pm_revision, pm_ports);
+ }
+
+ /* inform dma.alloc() about needed DMA slots */
+ ch->dma.dma_slots = pm_ports;
+
+ /* reset all ports and register if anything connected */
+ for (port=0; port < pm_ports; port++) {
+ u_int32_t signature, status;
+ int timeout;
+
+ if (ch->hw.pm_write(dev, port, 2, ATA_SC_DET_RESET)) {
+ device_printf(dev, "p%d: writing ATA_SC_DET_RESET failed\n", port);
+ continue;
+ }
+
+ ata_udelay(5000);
+
+ if (ch->hw.pm_write(dev, port, 2, ATA_SC_DET_IDLE)) {
+ device_printf(dev, "p%d: writing ATA_SC_DET_idle failed\n", port);
+ continue;
+ }
+
+ ata_udelay(5000);
+
+ /* wait up to 1 second for "connect well" */
+ for (timeout = 0; timeout < 100 ; timeout++) {
+ ch->hw.pm_read(dev, port, 0, &status);
+ if ((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN1 ||
+ (status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN2)
+ break;
+ ata_udelay(10000);
+ }
+ if (timeout >= 100) {
+ if (bootverbose)
+ device_printf(dev, "p%d: connect status=%08x\n", port, status);
+ continue;
+ }
+ if (bootverbose)
+ device_printf(dev, "p%d: connect time %dms\n", port, timeout * 10);
+
+ /* clear SERROR register */
+ ch->hw.pm_write(dev, port, 1, 0xffffffff);
+
+ signature = ch->hw.softreset(dev, port);
+
+ if (bootverbose)
+ device_printf(dev, "p%d: SIGNATURE=%08x\n", port, signature);
+
+ /* figure out whats there */
+ switch (signature) {
+ case 0x00000101:
+ ch->devices |= (ATA_ATA_MASTER << port);
+ continue;
+ case 0xeb140101:
+ ch->devices |= (ATA_ATAPI_MASTER << port);
+ continue;
+ }
+ }
+}
+
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[0] = 0x27; /* host to device */
+ fis[1] = 0x80 | (atadev->unit & 0x0f);
fis[2] = ATA_PACKET_CMD;
if (request->flags & (ATA_R_READ | ATA_R_WRITE))
fis[3] = ATA_F_DMA;
@@ -422,22 +532,22 @@ ata_request2fis_h2d(struct ata_request *
fis[5] = request->transfersize;
fis[6] = request->transfersize >> 8;
}
- fis[7] = ATA_D_LBA | atadev->unit;
+ fis[7] = ATA_D_LBA;
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[0] = 0x27; /* host to device */
+ fis[1] = 0x80 | (atadev->unit & 0x0f);
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;
+ fis[7] = ATA_D_LBA;
if (!(atadev->flags & ATA_D_48BIT_ACTIVE))
- fis[7] |= (request->u.ata.lba >> 24 & 0x0f);
+ fis[7] |= (ATA_D_IBM | (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;
@@ -495,6 +605,42 @@ ata_ahci_chipinit(device_t dev)
else
device_printf(dev, "AHCI called from vendor specific driver\n");
+ /* reset controller */
+ ata_ahci_ctlr_reset(dev);
+
+ /* get the number of HW channels */
+ ctlr->channels =
+ MAX(flsl(ATA_INL(ctlr->r_res2, ATA_AHCI_PI)),
+ (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_NPMASK) + 1);
+
+ ctlr->reset = ata_ahci_reset;
+ ctlr->dmainit = ata_ahci_dmainit;
+ ctlr->allocate = ata_ahci_allocate;
+ ctlr->setmode = ata_sata_setmode;
+ ctlr->suspend = ata_ahci_suspend;
+ ctlr->resume = ata_ahci_ctlr_reset;
+
+ /* enable PCI interrupt */
+ pci_write_config(dev, PCIR_COMMAND,
+ pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400, 2);
+
+ /* announce we support the HW */
+ version = ATA_INL(ctlr->r_res2, ATA_AHCI_VS);
+ device_printf(dev,
+ "AHCI Version %x%x.%x%x controller with %d ports PM %s\n",
+ (version >> 24) & 0xff, (version >> 16) & 0xff,
+ (version >> 8) & 0xff, version & 0xff,
+ (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_NPMASK) + 1,
+ (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_SPM) ?
+ "supported" : "not supported");
+ return 0;
+}
+
+static int
+ata_ahci_ctlr_reset(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+
/* enable AHCI mode */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, ATA_AHCI_GHC_AE);
@@ -510,11 +656,6 @@ ata_ahci_chipinit(device_t dev)
/* reenable AHCI mode */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, ATA_AHCI_GHC_AE);
- /* get the number of HW channels */
- ctlr->channels =
- MAX(flsl(ATA_INL(ctlr->r_res2, ATA_AHCI_PI)),
- (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_NPMASK) + 1);
-
/* clear interrupts */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_IS, ATA_INL(ctlr->r_res2, ATA_AHCI_IS));
@@ -522,31 +663,26 @@ ata_ahci_chipinit(device_t dev)
ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC,
ATA_INL(ctlr->r_res2, ATA_AHCI_GHC) | ATA_AHCI_GHC_IE);
- ctlr->reset = ata_ahci_reset;
- ctlr->dmainit = ata_ahci_dmainit;
- ctlr->allocate = ata_ahci_allocate;
- ctlr->setmode = ata_sata_setmode;
+ return 0;
+}
- /* enable PCI interrupt */
- pci_write_config(dev, PCIR_COMMAND,
- pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400, 2);
+static int
+ata_ahci_suspend(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
- /* announce we support the HW */
- version = ATA_INL(ctlr->r_res2, ATA_AHCI_VS);
- device_printf(dev,
- "AHCI Version %x%x.%x%x controller with %d ports detected\n",
- (version >> 24) & 0xff, (version >> 16) & 0xff,
- (version >> 8) & 0xff, version & 0xff,
- (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_NPMASK) + 1);
+ /* disable interupts so the state change(s) doesn't trigger */
+ ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC,
+ ATA_INL(ctlr->r_res2, ATA_AHCI_GHC) & (~ATA_AHCI_GHC_IE));
return 0;
}
+
static int
ata_ahci_allocate(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
- u_int64_t work;
int offset = ch->unit << 7;
/* set the SATA resources */
@@ -563,28 +699,10 @@ ata_ahci_allocate(device_t dev)
ch->hw.begin_transaction = ata_ahci_begin_transaction;
ch->hw.end_transaction = ata_ahci_end_transaction;
ch->hw.command = NULL; /* not used here */
+ ch->hw.softreset = ata_ahci_softreset;
+ ch->hw.pm_read = ata_ahci_pm_read;
+ ch->hw.pm_write = ata_ahci_pm_write;
- /* 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,
- (ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_TFE | ATA_AHCI_P_IX_HBF |
- ATA_AHCI_P_IX_HBD | ATA_AHCI_P_IX_IF | ATA_AHCI_P_IX_OF |
- ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC | ATA_AHCI_P_IX_DP |
- ATA_AHCI_P_IX_UF | ATA_AHCI_P_IX_SDB | ATA_AHCI_P_IX_DS |
- ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DHR));
-
- /* 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));
return 0;
}
@@ -595,22 +713,25 @@ ata_ahci_status(device_t dev)
struct ata_channel *ch = device_get_softc(dev);
u_int32_t action = ATA_INL(ctlr->r_res2, ATA_AHCI_IS);
int offset = ch->unit << 7;
- int tag = 0;
+
+#define ATA_AHCI_STATBITS \
+ (ATA_AHCI_P_IX_IF|ATA_AHCI_P_IX_HBD|ATA_AHCI_P_IX_HBF|ATA_AHCI_P_IX_TFE)
if (action & (1 << ch->unit)) {
u_int32_t istatus = ATA_INL(ctlr->r_res2, ATA_AHCI_P_IS + offset);
u_int32_t cstatus = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CI + offset);
/* clear interrupt(s) */
- ATA_OUTL(ctlr->r_res2, ATA_AHCI_IS, action & (1 << ch->unit));
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IS + offset, istatus);
+ ATA_OUTL(ctlr->r_res2, ATA_AHCI_IS, action & (1 << ch->unit));
/* do we have any PHY events ? */
- /* XXX SOS check istatus phy bits */
- ata_sata_phy_check_events(dev);
+ if (istatus & (ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC))
+ ata_sata_phy_check_events(dev);
/* do we have a potentially hanging engine to take care of? */
- if ((istatus & 0x78400050) && (cstatus & (1 << tag))) {
+ /* XXX SOS what todo on NCQ */
+ if ((istatus & ATA_AHCI_STATBITS) && (cstatus & 1)) {
u_int32_t cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset);
int timeout = 0;
@@ -622,7 +743,7 @@ ata_ahci_status(device_t dev)
/* XXX SOS this is not entirely wrong */
do {
DELAY(1000);
- if (timeout++ > 500) {
+ if (timeout++ > 1000) {
device_printf(dev, "stopping AHCI engine failed\n");
break;
}
@@ -636,7 +757,8 @@ ata_ahci_status(device_t dev)
return 1;
}
else
- return (!(cstatus & (1 << tag)));
+ /* XXX SOS what todo on NCQ */
+ return (!(cstatus & 1));
}
return 0;
}
@@ -646,16 +768,18 @@ static int
ata_ahci_begin_transaction(struct ata_request *request)
{
struct ata_pci_controller *ctlr=device_get_softc(GRANDPARENT(request->dev));
- struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
+ struct ata_channel *ch = device_get_softc(request->parent);
+ struct ata_device *atadev = device_get_softc(request->dev);
struct ata_ahci_cmd_tab *ctp;
struct ata_ahci_cmd_list *clp;
int offset = ch->unit << 7;
- int tag = 0, entries = 0;
+ int port = atadev->unit & 0x0f;
+ int entries = 0;
int fis_size;
/* get a piece of the workspace for this request */
ctp = (struct ata_ahci_cmd_tab *)
- (ch->dma->work + ATA_AHCI_CT_OFFSET + (ATA_AHCI_CT_SIZE * tag));
+ (ch->dma.work + ATA_AHCI_CT_OFFSET + (ATA_AHCI_CT_SIZE*request->tag));
/* setup the FIS for this request */
if (!(fis_size = ata_ahci_setup_fis(ctp, request))) {
@@ -666,9 +790,7 @@ ata_ahci_begin_transaction(struct ata_re
/* 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,
- ctp->prd_tab, &entries)) {
+ if (ch->dma.load(request, ctp->prd_tab, &entries)) {
device_printf(request->dev, "setting up DMA failed\n");
request->result = EIO;
return ATA_OP_FINISHED;
@@ -677,18 +799,21 @@ ata_ahci_begin_transaction(struct ata_re
/* setup the command list entry */
clp = (struct ata_ahci_cmd_list *)
- (ch->dma->work + ATA_AHCI_CL_OFFSET + (ATA_AHCI_CL_SIZE * tag));
+ (ch->dma.work + ATA_AHCI_CL_OFFSET + (ATA_AHCI_CL_SIZE*request->tag));
clp->prd_length = entries;
- clp->cmd_flags = (request->flags & ATA_R_WRITE ? (1<<6) : 0) |
- (request->flags & ATA_R_ATAPI ? ((1<<5) | (1<<7)) : 0) |
- (fis_size / sizeof(u_int32_t));
+ clp->cmd_flags = (request->flags & ATA_R_WRITE ? ATA_AHCI_CMD_WRITE : 0) |
+ (request->flags & ATA_R_ATAPI ?
+ (ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH) : 0) |
+ (fis_size / sizeof(u_int32_t)) |
+ (port << 12);
clp->bytecount = 0;
- clp->cmd_table_phys = htole64(ch->dma->work_bus + ATA_AHCI_CT_OFFSET +
- (ATA_AHCI_CT_SIZE * tag));
+ clp->cmd_table_phys = htole64(ch->dma.work_bus + ATA_AHCI_CT_OFFSET +
+ (ATA_AHCI_CT_SIZE * request->tag));
/* clear eventual ACTIVE bit */
- ATA_IDX_OUTL(ch, ATA_SACTIVE, ATA_IDX_INL(ch, ATA_SACTIVE) & (1 << tag));
+ ATA_IDX_OUTL(ch, ATA_SACTIVE,
+ ATA_IDX_INL(ch, ATA_SACTIVE) & (1 << request->tag));
/* set command type bit */
if (request->flags & ATA_R_ATAPI)
@@ -700,8 +825,11 @@ ata_ahci_begin_transaction(struct ata_re
ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset) &
~ATA_AHCI_P_CMD_ATAPI);
+ /* set PM port to address */
+ //ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBS + offset, (port << 8) | 0x00000001);
+
/* issue command to controller */
- ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CI + offset, (1 << tag));
+ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CI + offset, (1 << request->tag));
if (!(request->flags & ATA_R_ATAPI)) {
/* device reset doesn't interrupt */
@@ -734,11 +862,10 @@ static int
ata_ahci_end_transaction(struct ata_request *request)
{
struct ata_pci_controller *ctlr=device_get_softc(GRANDPARENT(request->dev));
- struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
+ struct ata_channel *ch = device_get_softc(request->parent);
struct ata_ahci_cmd_list *clp;
u_int32_t tf_data;
int offset = ch->unit << 7;
- int tag = 0;
/* kill the timeout */
callout_stop(&request->callout);
@@ -751,31 +878,140 @@ ata_ahci_end_transaction(struct ata_requ
if (request->status & ATA_S_ERROR)
request->error = tf_data >> 8;
+ /* on control commands read back registers to the request struct */
+ if (request->flags & ATA_R_CONTROL) {
+ struct ata_device *atadev = device_get_softc(request->dev);
+ u_int8_t *fis = ch->dma.work + ATA_AHCI_FB_OFFSET + 0x40;
+
+ request->u.ata.count = fis[12] | ((u_int16_t)fis[13] << 8);
+ request->u.ata.lba = fis[4] | ((u_int64_t)fis[5] << 8) |
+ ((u_int64_t)fis[6] << 16);
+ if (atadev->flags & ATA_D_48BIT_ACTIVE)
+ request->u.ata.lba |= ((u_int64_t)fis[8] << 24) |
+ ((u_int64_t)fis[9] << 32) |
+ ((u_int64_t)fis[10] << 40);
+ else
+ request->u.ata.lba |= ((u_int64_t)(fis[7] & 0x0f) << 24);
+ }
+
/* record how much data we actually moved */
clp = (struct ata_ahci_cmd_list *)
- (ch->dma->work + ATA_AHCI_CL_OFFSET + (ATA_AHCI_CL_SIZE * tag));
+ (ch->dma.work + ATA_AHCI_CL_OFFSET + (ATA_AHCI_CL_SIZE*request->tag));
request->donecount = clp->bytecount;
/* release SG list etc */
- ch->dma->unload(ch->dev);
+ ch->dma.unload(request);
return ATA_OP_FINISHED;
}
-static void
-ata_ahci_reset(device_t dev)
+static int
+ata_ahci_issue_cmd(device_t dev, u_int16_t flags, int timeout)
{
struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
- u_int32_t cmd, signature;
+ struct ata_ahci_cmd_list *clp =
+ (struct ata_ahci_cmd_list *)(ch->dma.work + ATA_AHCI_CL_OFFSET);
+ struct ata_ahci_cmd_tab *ctp =
+ (struct ata_ahci_cmd_tab *)(ch->dma.work + ATA_AHCI_CT_OFFSET);
+ u_int32_t status = 0;
int offset = ch->unit << 7;
- int timeout;
+ int port = (ctp->cfis[1] & 0x0f);
+ int count;
- if (!(ATA_INL(ctlr->r_res2, ATA_AHCI_PI) & (1 << ch->unit))) {
- device_printf(dev, "port not implemented\n");
- return;
+ clp->prd_length = 0;
+ clp->cmd_flags = (20 / sizeof(u_int32_t)) | flags | (port << 12);
+ clp->bytecount = 0;
+ clp->cmd_table_phys = htole64(ch->dma.work_bus + ATA_AHCI_CT_OFFSET);
+
+ /* set PM port */
+ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBS + offset, (port << 8) | 0x00000001);
+
+ /* issue command to controller */
+ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CI + offset, 1);
+
+ /* poll for command finished */
+ for (count = 0; count < timeout; count++) {
+ DELAY(1000);
+ if (!((status = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CI + offset)) & 1))
+ break;
+ }
+
+ /* clear interrupts */
+ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IS + offset,
+ ATA_INL(ctlr->r_res2, ATA_AHCI_P_IS + offset));
+
+ if (bootverbose)
+ device_printf(dev, "ahci_issue_cmd time=%dms cnt=%dms status=%08x\n",
+ timeout, count, status);
+ if (timeout && (count >= timeout))
+ return EIO;
+
+ return 0;
+}
+
+static int
+ata_ahci_pm_read(device_t dev, int port, int reg, u_int32_t *result)
+{
+ struct ata_channel *ch = device_get_softc(dev);
+ struct ata_ahci_cmd_tab *ctp =
+ (struct ata_ahci_cmd_tab *)(ch->dma.work + ATA_AHCI_CT_OFFSET);
+ u_int8_t *fis = ch->dma.work + ATA_AHCI_FB_OFFSET + 0x40;
+
+ bzero(ctp->cfis, 64);
+ ctp->cfis[0] = 0x27; /* host to device */
+ ctp->cfis[1] = 0x8f; /* command FIS to PM port */
+ ctp->cfis[2] = ATA_READ_PM;
+ ctp->cfis[3] = reg;
+ ctp->cfis[7] = port | ATA_D_LBA;
+ ctp->cfis[15] = ATA_A_4BIT;
+
+ if (ata_ahci_issue_cmd(dev, 0, 10)) {
+ device_printf(dev, "error reading PM port\n");
+ return EIO;
}
- ch->devices = 0;
+
+ *result = fis[12] | (fis[4] << 8) | (fis[5] << 16) | (fis[6] << 24);
+ return 0;
+}
+
+static int
+ata_ahci_pm_write(device_t dev, int port, int reg, u_int32_t value)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
+ struct ata_channel *ch = device_get_softc(dev);
+ struct ata_ahci_cmd_tab *ctp =
+ (struct ata_ahci_cmd_tab *)(ch->dma.work + ATA_AHCI_CT_OFFSET);
+ int offset = ch->unit << 7;
+
+ bzero(ctp->cfis, 64);
+ ctp->cfis[0] = 0x27; /* host to device */
+ ctp->cfis[1] = 0x8f; /* command FIS to PM port */
+ ctp->cfis[2] = ATA_WRITE_PM;
+ ctp->cfis[3] = reg;
+ ctp->cfis[7] = port | ATA_D_LBA;
+ ctp->cfis[12] = value & 0xff;
+ ctp->cfis[4] = (value >> 8) & 0xff;;
+ ctp->cfis[5] = (value >> 16) & 0xff;;
+ ctp->cfis[6] = (value >> 24) & 0xff;;
+ ctp->cfis[15] = ATA_A_4BIT;
+
+ if (ata_ahci_issue_cmd(dev, 0, 100)) {
+ device_printf(dev, "error writing PM port\n");
+ return ATA_E_ABORT;
+ }
+
+ return (ATA_INL(ctlr->r_res2, ATA_AHCI_P_TFD + offset) >> 8) & 0xff;
+}
+
+static void
+ata_ahci_restart(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
+ struct ata_channel *ch = device_get_softc(dev);
+ u_int32_t cmd;
+ int offset = ch->unit << 7;
+ int timeout;
/* kill off all activity on this channel */
cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset);
@@ -786,7 +1022,7 @@ ata_ahci_reset(device_t dev)
timeout = 0;
do {
DELAY(1000);
- if (timeout++ > 500) {
+ if (timeout++ > 1000) {
device_printf(dev, "stopping AHCI engine failed\n");
break;
}
@@ -801,7 +1037,7 @@ ata_ahci_reset(device_t dev)
timeout = 0;
do {
DELAY(1000);
- if (timeout++ > 500) {
+ if (timeout++ > 1000) {
device_printf(dev, "executing CLO failed\n");
break;
}
@@ -809,45 +1045,151 @@ ata_ahci_reset(device_t dev)
while (ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD+offset)&ATA_AHCI_P_CMD_CLO);
}
- /* reset PHY and decide what is present */
- if (ata_sata_phy_reset(dev)) {
+ /* clear SATA error register */
+ ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR));
+
+ /* clear any interrupts pending on this channel */
+ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IS + offset,
+ ATA_INL(ctlr->r_res2, ATA_AHCI_P_IS + offset));
+
+ /* start operations on this channel */
+ cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset);
+ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset,
+ cmd | (ATA_AHCI_P_CMD_FRE | ATA_AHCI_P_CMD_ST) |
+ (ch->devices & ATA_PORTMULTIPLIER ? ATA_AHCI_P_CMD_PMA : 0));
+}
+
+static u_int32_t
+ata_ahci_softreset(device_t dev, int port)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
+ struct ata_channel *ch = device_get_softc(dev);
+ int offset = ch->unit << 7;
+ int timeout = 0;
+#ifdef AHCI_PM
+ struct ata_ahci_cmd_tab *ctp =
+ (struct ata_ahci_cmd_tab *)(ch->dma.work + ATA_AHCI_CT_OFFSET);
+
+ /* kick controller into sane state if needed */
+ ata_ahci_restart(dev);
+
+ /* pull reset active */
+ bzero(ctp->cfis, 64);
+ ctp->cfis[0] = 0x27;
+ ctp->cfis[1] = port & 0x0f;
+ //ctp->cfis[7] = ATA_D_LBA | ATA_D_IBM;
+ ctp->cfis[15] = (ATA_A_4BIT | ATA_A_RESET);
+
+ if (ata_ahci_issue_cmd(dev, ATA_AHCI_CMD_RESET | ATA_AHCI_CMD_CLR_BUSY,100))
+ device_printf(dev, "setting SRST failed ??\n");
+ //return -1;
- /* 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));
+ ata_udelay(5000);
- /* clear SATA error register */
- ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR));
+ /* pull reset inactive -> device softreset */
+ bzero(ctp->cfis, 64);
+ ctp->cfis[0] = 0x27;
+ ctp->cfis[1] = port & 0x0f;
+ //ctp->cfis[7] = ATA_D_LBA | ATA_D_IBM;
+ ctp->cfis[15] = ATA_A_4BIT;
+ if (ata_ahci_issue_cmd(dev, 0, 0))
+ return -1;
+
+ ata_udelay(150000);
+
+#endif
+ do {
+ DELAY(1000);
+ if (timeout++ > 1000) {
+ device_printf(dev, "still BUSY after softreset\n");
+ break;
+ }
+ } while (ATA_INL(ctlr->r_res2, ATA_AHCI_P_TFD + offset) & ATA_S_BUSY);
+ if (bootverbose)
+ device_printf(dev, "BUSY wait time=%dms\n", timeout);
- /* start operations on this channel */
+ return ATA_INL(ctlr->r_res2, ATA_AHCI_P_SIG + offset);
+}
+
+static void
+ata_ahci_reset(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
+ struct ata_channel *ch = device_get_softc(dev);
+ u_int64_t work;
+ u_int32_t cmd, signature;
+ int offset = ch->unit << 7;
+
+ if (!(ATA_INL(ctlr->r_res2, ATA_AHCI_PI) & (1 << ch->unit))) {
+ device_printf(dev, "port not implemented\n");
+ return;
+ }
+
+ /* setup work areas */
+ work = ch->dma.work_bus + ATA_AHCI_CL_OFFSET;
+ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLB + offset, work & 0xffffffff);
+ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLBU + offset, work >> 32);
+
+ work = ch->dma.work_bus + ATA_AHCI_FB_OFFSET;
+ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FB + offset, work & 0xffffffff);
+ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBU + offset, work >> 32);
+
+ /* enable wanted port interrupts */
+ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IE + offset,
+ (ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_TFE | ATA_AHCI_P_IX_HBF |
+ ATA_AHCI_P_IX_HBD | ATA_AHCI_P_IX_IF | ATA_AHCI_P_IX_OF |
+ ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC | ATA_AHCI_P_IX_DP |
+ ATA_AHCI_P_IX_UF | ATA_AHCI_P_IX_SDB | ATA_AHCI_P_IX_DS |
+ ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DHR));
+
+ /* activate the channel and power/spin up device */
+ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset,
+ (ATA_AHCI_P_CMD_ACTIVE | ATA_AHCI_P_CMD_POD | ATA_AHCI_P_CMD_SUD));
+
+ ata_ahci_restart(dev);
+
+ /* enable FIS based switching */
+ //ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBS + offset, 0x00000003);
+
+ if (!ata_sata_phy_reset(dev)) {
+ if (bootverbose)
+ device_printf(dev, "phy reset found no device\n");
+ ch->devices = 0;
+
+ /* kill off all activity on this channel */
+ cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset);
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset,
- (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));
+ cmd & ~(ATA_AHCI_P_CMD_FRE | ATA_AHCI_P_CMD_ST));
+ return;
+ }
+
+ /* only probe for PortMultiplier if HW has support */
+ if (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_SPM)
+ signature = ata_ahci_softreset(dev, ATA_PM);
+ else {
+ signature = ata_ahci_softreset(dev, 0);
+ }
+ if (bootverbose)
+ device_printf(dev, "SIGNATURE: %08x\n", signature);
- signature = ATA_INL(ctlr->r_res2, ATA_AHCI_P_SIG + offset);
+ switch (signature) {
+ case 0x00000101:
+ ch->devices = ATA_ATA_MASTER;
+ break;
+ case 0x96690101:
+ ch->devices = ATA_PORTMULTIPLIER;
+ ata_pm_identify(dev);
+ break;
+ case 0xeb140101:
+ ch->devices = ATA_ATAPI_MASTER;
+ break;
+ default: /* SOS XXX */
if (bootverbose)
- device_printf(dev, "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;
- }
+ device_printf(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");
+ device_printf(dev, "ahci_reset devices=%08x\n", ch->devices);
}
static void
@@ -863,7 +1205,8 @@ ata_ahci_dmasetprd(void *xsc, bus_dma_se
prd[i].dbc = htole32((segs[i].ds_len - 1) & ATA_AHCI_PRD_MASK);
}
}
- KASSERT(nsegs <= ATA_DMA_ENTRIES, ("too many DMA segment entries\n"));
+
+ KASSERT(nsegs <= ATA_AHCI_DMA_ENTRIES, ("too many DMA segment entries\n"));
args->nsegs = nsegs;
}
@@ -874,13 +1217,11 @@ ata_ahci_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_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;
- }
+ /* 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
@@ -956,9 +1297,9 @@ ata_acard_status(device_t dev)
struct ata_channel *ch = device_get_softc(dev);
if (ctlr->chip->cfg1 == ATPOLD &&
- ATA_LOCKING(ch->dev, ATA_LF_WHICH) != ch->unit)
+ ATA_LOCKING(dev, ATA_LF_WHICH) != ch->unit)
return 0;
- if (ch->dma && (ch->dma->flags & ATA_DMA_ACTIVE)) {
+ if (ch->dma.flags & ATA_DMA_ACTIVE) {
int bmstat = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
if ((bmstat & (ATA_BMSTAT_ACTIVE | ATA_BMSTAT_INTERRUPT)) !=
@@ -985,7 +1326,7 @@ ata_acard_850_setmode(device_t dev, int
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 devno = (ch->unit << 1) + ATA_DEV(atadev->unit);
+ int devno = (ch->unit << 1) + atadev->unit;
int error;
mode = ata_limit_mode(dev, mode,
@@ -1021,7 +1362,7 @@ ata_acard_86X_setmode(device_t dev, int
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 devno = (ch->unit << 1) + ATA_DEV(atadev->unit);
+ int devno = (ch->unit << 1) + atadev->unit;
int error;
@@ -1234,7 +1575,7 @@ ata_ali_setmode(device_t dev, int mode)
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 devno = (ch->unit << 1) + ATA_DEV(atadev->unit);
+ int devno = (ch->unit << 1) + atadev->unit;
int error;
mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma);
@@ -1322,13 +1663,34 @@ ata_amd_chipinit(device_t dev)
if (ata_setup_interrupt(dev))
return ENXIO;
- /* disable/set prefetch, postwrite */
- if (ctlr->chip->cfg2 & AMDBUG)
- pci_write_config(dev, 0x41, pci_read_config(dev, 0x41, 1) & 0x0f, 1);
- else
- pci_write_config(dev, 0x41, pci_read_config(dev, 0x41, 1) | 0xf0, 1);
+ /* disable/set prefetch, postwrite */
+ if (ctlr->chip->cfg2 & AMDBUG)
+ pci_write_config(dev, 0x41, pci_read_config(dev, 0x41, 1) & 0x0f, 1);
+ else
+ pci_write_config(dev, 0x41, pci_read_config(dev, 0x41, 1) | 0xf0, 1);
+
+ ctlr->setmode = ata_via_family_setmode;
+ return 0;
+}
+
+
+/*
+ * Adaptec chipset support functions
+ */
+int
+ata_adaptec_ident(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+ static struct ata_chip_id ids[] =
+ {{ ATA_ADAPTEC_1420, 0, 4, MV60XX, ATA_SA300, "1420SA" },
+ { 0, 0, 0, 0, 0, 0}};
+
+ if (!(ctlr->chip = ata_match_chip(dev, ids)))
+ return ENXIO;
+
+ ata_set_desc(dev);
+ ctlr->chipinit = ata_marvell_edma_chipinit;
- ctlr->setmode = ata_via_family_setmode;
return 0;
}
@@ -1398,7 +1760,7 @@ ata_ati_setmode(device_t dev, int mode)
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 devno = (ch->unit << 1) + ATA_DEV(atadev->unit);
+ int devno = (ch->unit << 1) + atadev->unit;
int offset = (devno ^ 0x01) << 3;
int error;
u_int8_t piotimings[] = { 0x5d, 0x47, 0x34, 0x22, 0x20, 0x34, 0x22, 0x20,
@@ -1492,15 +1854,15 @@ ata_cyrix_setmode(device_t dev, int mode
{
struct ata_channel *ch = device_get_softc(device_get_parent(dev));
struct ata_device *atadev = device_get_softc(dev);
- int devno = (ch->unit << 1) + ATA_DEV(atadev->unit);
+ int devno = (ch->unit << 1) + atadev->unit;
u_int32_t piotiming[] =
{ 0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010 };
u_int32_t dmatiming[] = { 0x00077771, 0x00012121, 0x00002020 };
u_int32_t udmatiming[] = { 0x00921250, 0x00911140, 0x00911030 };
int error;
- ch->dma->alignment = 16;
- ch->dma->max_iosize = 126 * DEV_BSIZE;
+ ch->dma.alignment = 16;
+ ch->dma.max_iosize = 126 * DEV_BSIZE;
mode = ata_limit_mode(dev, mode, ATA_UDMA2);
@@ -1681,7 +2043,7 @@ ata_highpoint_setmode(device_t dev, int
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 devno = (ch->unit << 1) + ATA_DEV(atadev->unit);
+ int devno = (ch->unit << 1) + atadev->unit;
int error;
u_int32_t timings33[][4] = {
/* HPT366 HPT370 HPT372 HPT374 mode */
@@ -1800,6 +2162,7 @@ ata_intel_ident(device_t dev)
{ ATA_I63XXESB2_R2, 0, AHCI, 0x00, ATA_SA300, "63XXESB2" },
{ ATA_I82801HB_S1, 0, AHCI, 0x00, ATA_SA300, "ICH8" },
{ ATA_I82801HB_S2, 0, AHCI, 0x00, ATA_SA300, "ICH8" },
+ { ATA_I82801HB_R1, 2, AHCI, 0x00, ATA_SA300, "ICH9R" },
{ ATA_I82801HB_R1, 0, AHCI, 0x00, ATA_SA300, "ICH8" },
{ ATA_I82801HB_AH4, 0, AHCI, 0x00, ATA_SA300, "ICH8" },
{ ATA_I82801HB_AH6, 0, AHCI, 0x00, ATA_SA300, "ICH8" },
@@ -1963,7 +2326,7 @@ ata_intel_new_setmode(device_t dev, int
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 devno = (ch->unit << 1) + ATA_DEV(atadev->unit);
+ int devno = (ch->unit << 1) + atadev->unit;
u_int32_t reg40 = pci_read_config(gparent, 0x40, 4);
u_int8_t reg44 = pci_read_config(gparent, 0x44, 1);
u_int8_t reg48 = pci_read_config(gparent, 0x48, 1);
@@ -1988,52 +2351,54 @@ ata_intel_new_setmode(device_t dev, int
device_printf(dev, "%ssetting %s on %s chip\n",
(error) ? "FAILURE " : "",
ata_mode2str(mode), ctlr->chip->text);
- if (error)
- return;
+ if (!error) {
+ if (mode >= ATA_UDMA0) {
+ u_int8_t utimings[] = { 0x00, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10 };
- if (mode >= ATA_UDMA0) {
- pci_write_config(gparent, 0x48, reg48 | (0x0001 << devno), 2);
- pci_write_config(gparent, 0x4a,
- (reg4a & ~(0x3 << (devno << 2))) |
- ((0x01 + !(mode & 0x01)) << (devno << 2)), 2);
- }
- else {
- pci_write_config(gparent, 0x48, reg48 & ~(0x0001 << devno), 2);
- pci_write_config(gparent, 0x4a, (reg4a & ~(0x3 << (devno << 2))), 2);
- }
- reg54 |= 0x0400;
- if (mode >= ATA_UDMA2)
- pci_write_config(gparent, 0x54, reg54 | (0x1 << devno), 2);
- else
- pci_write_config(gparent, 0x54, reg54 & ~(0x1 << devno), 2);
+ pci_write_config(gparent, 0x48, reg48 | (0x0001 << devno), 2);
+ pci_write_config(gparent, 0x4a,
+ (reg4a & ~(0x3 << (devno << 2))) |
+ (utimings[mode & ATA_MODE_MASK] << (devno<<2)), 2);
+ }
+ else {
+ pci_write_config(gparent, 0x48, reg48 & ~(0x0001 << devno), 2);
+ pci_write_config(gparent, 0x4a, (reg4a & ~(0x3 << (devno << 2))),2);
+ }
+ reg54 |= 0x0400;
+ if (mode >= ATA_UDMA2)
+ reg54 |= (0x1 << devno);
+ else
+ reg54 &= ~(0x1 << devno);
+ if (mode >= ATA_UDMA5)
+ reg54 |= (0x1000 << devno);
+ else
+ reg54 &= ~(0x1000 << devno);
- if (mode >= ATA_UDMA5)
- pci_write_config(gparent, 0x54, reg54 | (0x1000 << devno), 2);
- else
- pci_write_config(gparent, 0x54, reg54 & ~(0x1000 << devno), 2);
+ pci_write_config(gparent, 0x54, reg54, 2);
- reg40 &= ~0x00ff00ff;
- reg40 |= 0x40774077;
+ reg40 &= ~0x00ff00ff;
+ reg40 |= 0x40774077;
- if (atadev->unit == ATA_MASTER) {
- mask40 = 0x3300;
- new40 = timings[ata_mode2idx(mode)] << 8;
- }
- else {
- mask44 = 0x0f;
- new44 = ((timings[ata_mode2idx(mode)] & 0x30) >> 2) |
- (timings[ata_mode2idx(mode)] & 0x03);
- }
- if (ch->unit) {
- mask40 <<= 16;
- new40 <<= 16;
- mask44 <<= 4;
- new44 <<= 4;
- }
- pci_write_config(gparent, 0x40, (reg40 & ~mask40) | new40, 4);
- pci_write_config(gparent, 0x44, (reg44 & ~mask44) | new44, 1);
+ if (atadev->unit == ATA_MASTER) {
+ mask40 = 0x3300;
+ new40 = timings[ata_mode2idx(mode)] << 8;
+ }
+ else {
+ mask44 = 0x0f;
+ new44 = ((timings[ata_mode2idx(mode)] & 0x30) >> 2) |
+ (timings[ata_mode2idx(mode)] & 0x03);
+ }
+ if (ch->unit) {
+ mask40 <<= 16;
+ new40 <<= 16;
+ mask44 <<= 4;
+ new44 <<= 4;
+ }
+ pci_write_config(gparent, 0x40, (reg40 & ~mask40) | new40, 4);
+ pci_write_config(gparent, 0x44, (reg44 & ~mask44) | new44, 1);
- atadev->mode = mode;
+ atadev->mode = mode;
+ }
}
static void
@@ -2045,7 +2410,7 @@ ata_intel_sata_setmode(device_t dev, int
atadev->param.satacapabilities != 0xffff) {
struct ata_channel *ch = device_get_softc(device_get_parent(dev));
- int devno = (ch->unit << 1) + ATA_DEV(atadev->unit);
+ int devno = (ch->unit << 1) + atadev->unit;
/* on some drives we need to set the transfer mode */
ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0,
@@ -2141,7 +2506,7 @@ ata_intel_31244_tf_write(struct ata_requ
((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);
+ ATA_IDX_OUTW(ch, ATA_DRIVE, ATA_D_LBA | ATA_DEV(atadev->unit));
}
else {
ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature);
@@ -2162,7 +2527,7 @@ ata_intel_31244_tf_write(struct ata_requ
(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 |
+ ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(atadev->unit) |
(((request->u.ata.lba% (sectors * heads)) /
sectors) & 0xf));
}
@@ -2171,7 +2536,7 @@ ata_intel_31244_tf_write(struct ata_requ
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 |
+ ATA_D_IBM | ATA_D_LBA | ATA_DEV(atadev->unit) |
((request->u.ata.lba >> 24) & 0x0f));
}
}
@@ -2193,7 +2558,8 @@ ata_ite_ident(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(dev);
static struct ata_chip_id ids[] =
- {{ ATA_IT8212F, 0x00, 0x00, 0x00, ATA_UDMA6, "IT8212F" },
+ {{ ATA_IT8213F, 0x00, 0x00, 0x00, ATA_UDMA6, "IT8213F" },
+ { ATA_IT8212F, 0x00, 0x00, 0x00, ATA_UDMA6, "IT8212F" },
{ ATA_IT8211F, 0x00, 0x00, 0x00, ATA_UDMA6, "IT8211F" },
{ 0, 0, 0, 0, 0, 0}};
@@ -2213,24 +2579,33 @@ ata_ite_chipinit(device_t dev)
if (ata_setup_interrupt(dev))
return ENXIO;
- ctlr->setmode = ata_ite_setmode;
+ if (ctlr->chip->chipid == ATA_IT8213F) {
+ /* the ITE 8213F only has one channel */
+ ctlr->channels = 1;
+
+ ctlr->setmode = ata_ite_8213_setmode;
+ }
+ else {
+ /* set PCI mode and 66Mhz reference clock */
+ pci_write_config(dev, 0x50, pci_read_config(dev, 0x50, 1) & ~0x83, 1);
- /* set PCI mode and 66Mhz reference clock */
- pci_write_config(dev, 0x50, pci_read_config(dev, 0x50, 1) & ~0x83, 1);
+ /* set default active & recover timings */
+ pci_write_config(dev, 0x54, 0x31, 1);
+ pci_write_config(dev, 0x56, 0x31, 1);
+
+ ctlr->setmode = ata_ite_821x_setmode;
+ }
- /* set default active & recover timings */
- pci_write_config(dev, 0x54, 0x31, 1);
- pci_write_config(dev, 0x56, 0x31, 1);
return 0;
}
static void
-ata_ite_setmode(device_t dev, int mode)
+ata_ite_821x_setmode(device_t dev, int mode)
{
device_t gparent = GRANDPARENT(dev);
struct ata_channel *ch = device_get_softc(device_get_parent(dev));
struct ata_device *atadev = device_get_softc(dev);
- int devno = (ch->unit << 1) + ATA_DEV(atadev->unit);
+ int devno = (ch->unit << 1) + atadev->unit;
int error;
/* correct the mode for what the HW supports */
@@ -2263,7 +2638,7 @@ ata_ite_setmode(device_t dev, int mode)
/* set UDMA timing */
pci_write_config(gparent,
- 0x56 + (ch->unit << 2) + ATA_DEV(atadev->unit),
+ 0x56 + (ch->unit << 2) + atadev->unit,
udmatiming[mode & ATA_MODE_MASK], 1);
}
else {
@@ -2285,6 +2660,80 @@ ata_ite_setmode(device_t dev, int mode)
}
}
+static void
+ata_ite_8213_setmode(device_t dev, int mode)
+{
+ device_t gparent = GRANDPARENT(dev);
+ struct ata_pci_controller *ctlr = device_get_softc(gparent);
+ struct ata_device *atadev = device_get_softc(dev);
+ u_int16_t reg40 = pci_read_config(gparent, 0x40, 2);
+ u_int8_t reg44 = pci_read_config(gparent, 0x44, 1);
+ u_int8_t reg48 = pci_read_config(gparent, 0x48, 1);
+ u_int16_t reg4a = pci_read_config(gparent, 0x4a, 2);
+ u_int16_t reg54 = pci_read_config(gparent, 0x54, 2);
+ u_int16_t mask40 = 0, new40 = 0;
+ u_int8_t mask44 = 0, new44 = 0;
+ int devno = atadev->unit;
+ int error;
+ u_int8_t timings[] = { 0x00, 0x00, 0x10, 0x21, 0x23, 0x10, 0x21, 0x23,
+ 0x23, 0x23, 0x23, 0x23, 0x23, 0x23 };
+
+ mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma);
+
+ if (mode > ATA_UDMA2 && !(reg54 & (0x10 << devno))) {
+ ata_print_cable(dev, "controller");
+ mode = ATA_UDMA2;
+ }
+
+ 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) {
+ if (mode >= ATA_UDMA0) {
+ u_int8_t utimings[] = { 0x00, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10 };
+
+ pci_write_config(gparent, 0x48, reg48 | (0x0001 << devno), 2);
+ pci_write_config(gparent, 0x4a,
+ (reg4a & ~(0x3 << (devno << 2))) |
+ (utimings[mode & ATA_MODE_MASK] << (devno<<2)), 2);
+ }
+ else {
+ pci_write_config(gparent, 0x48, reg48 & ~(0x0001 << devno), 2);
+ pci_write_config(gparent, 0x4a, (reg4a & ~(0x3 << (devno << 2))),2);
+ }
+ if (mode >= ATA_UDMA2)
+ reg54 |= (0x1 << devno);
+ else
+ reg54 &= ~(0x1 << devno);
+ if (mode >= ATA_UDMA5)
+ reg54 |= (0x1000 << devno);
+ else
+ reg54 &= ~(0x1000 << devno);
+ pci_write_config(gparent, 0x54, reg54, 2);
+
+ reg40 &= 0xff00;
+ reg40 |= 0x4033;
+ if (atadev->unit == ATA_MASTER) {
+ reg40 |= (ata_atapi(dev) ? 0x04 : 0x00);
+ mask40 = 0x3300;
+ new40 = timings[ata_mode2idx(mode)] << 8;
+ }
+ else {
+ reg40 |= (ata_atapi(dev) ? 0x40 : 0x00);
+ mask44 = 0x0f;
+ new44 = ((timings[ata_mode2idx(mode)] & 0x30) >> 2) |
+ (timings[ata_mode2idx(mode)] & 0x03);
+ }
+ pci_write_config(gparent, 0x40, (reg40 & ~mask40) | new40, 4);
+ pci_write_config(gparent, 0x44, (reg44 & ~mask44) | new44, 1);
+
+ atadev->mode = mode;
+ }
+}
+
/*
* JMicron chipset support functions
@@ -2573,11 +3022,11 @@ ata_marvell_edma_allocate(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
- u_int64_t work = ch->dma->work_bus;
+ u_int64_t work = ch->dma.work_bus;
int i;
/* clear work area */
- bzero(ch->dma->work, 1024+256);
+ bzero(ch->dma.work, 1024+256);
/* set legacy ATA resources */
for (i = ATA_DATA; i <= ATA_COMMAND; i++) {
@@ -2684,13 +3133,13 @@ static int
ata_marvell_edma_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_channel *ch = device_get_softc(request->parent);
u_int32_t req_in;
u_int8_t *bytep;
u_int16_t *wordp;
u_int32_t *quadp;
- int i, tag = 0x07;
- int dummy, error, slot;
+ int i;
+ int error, slot;
/* only DMA R/W goes through the EMDA machine */
if (request->u.ata.command != ATA_READ_DMA &&
@@ -2706,9 +3155,7 @@ ata_marvell_edma_begin_transaction(struc
ata_modify_if_48bit(request);
/* check sanity, setup SG list and DMA engine */
- if ((error = ch->dma->load(ch->dev, request->data, request->bytecount,
- request->flags & ATA_R_READ, ch->dma->sg,
- &dummy))) {
+ if ((error = ch->dma.load(request, NULL, NULL))) {
device_printf(request->dev, "setting up DMA failed\n");
request->result = error;
return ATA_OP_FINISHED;
@@ -2717,15 +3164,15 @@ ata_marvell_edma_begin_transaction(struc
/* get next free request queue slot */
req_in = ATA_INL(ctlr->r_res1, 0x02014 + ATA_MV_EDMA_BASE(ch));
slot = (((req_in & ~0xfffffc00) >> 5) + 0) & 0x1f;
- bytep = (u_int8_t *)(ch->dma->work);
+ bytep = (u_int8_t *)(ch->dma.work);
bytep += (slot << 5);
wordp = (u_int16_t *)bytep;
quadp = (u_int32_t *)bytep;
/* fill in this request */
- quadp[0] = (long)ch->dma->sg_bus & 0xffffffff;
- quadp[1] = (u_int64_t)ch->dma->sg_bus >> 32;
- wordp[4] = (request->flags & ATA_R_READ ? 0x01 : 0x00) | (tag<<1);
+ quadp[0] = (long)request->dma->sg_bus & 0xffffffff;
+ quadp[1] = (u_int64_t)request->dma->sg_bus >> 32;
+ wordp[4] = (request->flags & ATA_R_READ ? 0x01 : 0x00) | (request->tag<<1);
i = 10;
bytep[i++] = (request->u.ata.count >> 8) & 0xff;
@@ -2776,7 +3223,7 @@ static int
ata_marvell_edma_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_channel *ch = device_get_softc(request->parent);
int offset = (ch->unit > 3 ? 0x30014 : 0x20014);
u_int32_t icr = ATA_INL(ctlr->r_res1, offset);
int res;
@@ -2797,7 +3244,7 @@ ata_marvell_edma_end_transaction(struct
rsp_out &= 0xffffff00;
rsp_out += (slot << 3);
response = (struct ata_marvell_response *)
- (ch->dma->work + 1024 + (slot << 3));
+ (ch->dma.work + 1024 + (slot << 3));
/* record status for this request */
request->status = response->dev_status;
@@ -2812,7 +3259,7 @@ ata_marvell_edma_end_transaction(struct
request->donecount = request->bytecount;
/* unload SG list */
- ch->dma->unload(ch->dev);
+ ch->dma.unload(request);
res = ATA_OP_FINISHED;
}
@@ -2883,17 +3330,15 @@ ata_marvell_edma_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_marvell_edma_dmasetprd;
+ /* 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;
+ /* 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;
- }
+ /* chip does not reliably do 64K DMA transfers */
+ ch->dma.max_iosize = 126 * DEV_BSIZE;
}
@@ -2932,7 +3377,7 @@ ata_national_setmode(device_t dev, int m
device_t gparent = GRANDPARENT(dev);
struct ata_channel *ch = device_get_softc(device_get_parent(dev));
struct ata_device *atadev = device_get_softc(dev);
- int devno = (ch->unit << 1) + ATA_DEV(atadev->unit);
+ int devno = (ch->unit << 1) + atadev->unit;
u_int32_t piotiming[] =
{ 0x9172d132, 0x21717121, 0x00803020, 0x20102010, 0x00100010,
0x00803020, 0x20102010, 0x00100010,
@@ -2941,8 +3386,8 @@ ata_national_setmode(device_t dev, int m
u_int32_t udmatiming[] = { 0x80921250, 0x80911140, 0x80911030 };
int error;
- ch->dma->alignment = 16;
- ch->dma->max_iosize = 126 * DEV_BSIZE;
+ ch->dma.alignment = 16;
+ ch->dma.max_iosize = 126 * DEV_BSIZE;
mode = ata_limit_mode(dev, mode, ATA_UDMA2);
@@ -3150,15 +3595,23 @@ ata_nvidia_status(device_t dev)
struct ata_channel *ch = device_get_softc(dev);
int offset = ctlr->chip->cfg2 & NV4 ? 0x0440 : 0x0010;
int shift = ch->unit << (ctlr->chip->cfg2 & NVQ ? 4 : 2);
- u_int32_t istatus = ATA_INL(ctlr->r_res2, offset);
+ u_int32_t istatus;
+
+ /* get interrupt status */
+ if (ctlr->chip->cfg2 & NVQ)
+ istatus = ATA_INL(ctlr->r_res2, offset);
+ else
+ istatus = ATA_INB(ctlr->r_res2, offset);
/* 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));
+ if (ctlr->chip->cfg2 & NVQ)
+ ATA_OUTL(ctlr->r_res2, offset, (0x0f << shift) | 0x00f000f0);
+ else
+ ATA_OUTB(ctlr->r_res2, offset, (0x0f << shift));
/* do we have any device action ? */
return (istatus & (0x01 << shift));
@@ -3408,7 +3861,7 @@ sataii:
/* clear SATA status and unmask interrupts */
ATA_OUTL(ctlr->r_res2, stat_reg, 0x000000ff);
- /* enable "long burst lenght" on gen2 chips */
+ /* enable "long burst length" 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);
@@ -3453,35 +3906,35 @@ ata_promise_status(device_t dev)
}
static int
-ata_promise_dmastart(device_t dev)
+ata_promise_dmastart(struct ata_request *request)
{
- struct ata_pci_controller *ctlr = device_get_softc(GRANDPARENT(dev));
- struct ata_channel *ch = device_get_softc(device_get_parent(dev));
- struct ata_device *atadev = device_get_softc(dev);
+ struct ata_pci_controller *ctlr=device_get_softc(GRANDPARENT(request->dev));
+ struct ata_channel *ch = device_get_softc(request->parent);
+ struct ata_device *atadev = device_get_softc(request->dev);
if (atadev->flags & ATA_D_48BIT_ACTIVE) {
ATA_OUTB(ctlr->r_res1, 0x11,
ATA_INB(ctlr->r_res1, 0x11) | (ch->unit ? 0x08 : 0x02));
ATA_OUTL(ctlr->r_res1, ch->unit ? 0x24 : 0x20,
- ((ch->dma->flags & ATA_DMA_READ) ? 0x05000000 : 0x06000000) |
- (ch->dma->cur_iosize >> 1));
+ ((request->flags & ATA_R_READ) ? 0x05000000 : 0x06000000) |
+ (request->bytecount >> 1));
}
ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, (ATA_IDX_INB(ch, ATA_BMSTAT_PORT) |
(ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR)));
- ATA_IDX_OUTL(ch, ATA_BMDTP_PORT, ch->dma->sg_bus);
+ ATA_IDX_OUTL(ch, ATA_BMDTP_PORT, request->dma->sg_bus);
ATA_IDX_OUTB(ch, ATA_BMCMD_PORT,
- ((ch->dma->flags & ATA_DMA_READ) ? ATA_BMCMD_WRITE_READ : 0) |
+ ((request->flags & ATA_R_READ) ? ATA_BMCMD_WRITE_READ : 0) |
ATA_BMCMD_START_STOP);
- ch->flags |= ATA_DMA_ACTIVE;
+ ch->dma.flags |= ATA_DMA_ACTIVE;
return 0;
}
static int
-ata_promise_dmastop(device_t dev)
+ata_promise_dmastop(struct ata_request *request)
{
- struct ata_pci_controller *ctlr = device_get_softc(GRANDPARENT(dev));
- struct ata_channel *ch = device_get_softc(device_get_parent(dev));
- struct ata_device *atadev = device_get_softc(dev);
+ struct ata_pci_controller *ctlr=device_get_softc(GRANDPARENT(request->dev));
+ struct ata_channel *ch = device_get_softc(request->parent);
+ struct ata_device *atadev = device_get_softc(request->dev);
int error;
if (atadev->flags & ATA_D_48BIT_ACTIVE) {
@@ -3493,7 +3946,7 @@ ata_promise_dmastop(device_t dev)
ATA_IDX_OUTB(ch, ATA_BMCMD_PORT,
ATA_IDX_INB(ch, ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP);
ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR);
- ch->flags &= ~ATA_DMA_ACTIVE;
+ ch->dma.flags &= ~ATA_DMA_ACTIVE;
return error;
}
@@ -3514,11 +3967,9 @@ ata_promise_dmainit(device_t dev)
struct ata_channel *ch = device_get_softc(dev);
ata_dmainit(dev);
- if (ch->dma) {
- ch->dma->start = ata_promise_dmastart;
- ch->dma->stop = ata_promise_dmastop;
- ch->dma->reset = ata_promise_dmareset;
- }
+ ch->dma.start = ata_promise_dmastart;
+ ch->dma.stop = ata_promise_dmastop;
+ ch->dma.reset = ata_promise_dmareset;
}
static void
@@ -3528,7 +3979,7 @@ ata_promise_setmode(device_t dev, int mo
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 devno = (ch->unit << 1) + ATA_DEV(atadev->unit);
+ int devno = (ch->unit << 1) + atadev->unit;
int error;
u_int32_t timings[][2] = {
/* PROLD PRNEW mode */
@@ -3656,6 +4107,9 @@ ata_promise_mio_allocate(device_t dev)
else {
ch->hw.command = ata_promise_mio_command;
ch->hw.status = ata_promise_mio_status;
+ ch->hw.softreset = ata_promise_mio_softreset;
+ ch->hw.pm_read = ata_promise_mio_pm_read;
+ ch->hw.pm_write = ata_promise_mio_pm_write;
}
return 0;
}
@@ -3737,9 +4191,9 @@ ata_promise_mio_status(device_t dev)
M_ATA, M_NOWAIT | M_ZERO))) {
if (bootverbose)
- device_printf(ch->dev, "DISCONNECT requested\n");
+ device_printf(dev, "DISCONNECT requested\n");
tp->action = ATA_C_DETACH;
- tp->dev = ch->dev;
+ tp->dev = dev;
TASK_INIT(&tp->task, 0, ata_sata_phy_event, tp);
taskqueue_enqueue(taskqueue_thread, &tp->task);
}
@@ -3751,9 +4205,9 @@ ata_promise_mio_status(device_t dev)
M_ATA, M_NOWAIT | M_ZERO))) {
if (bootverbose)
- device_printf(ch->dev, "CONNECT requested\n");
+ device_printf(dev, "CONNECT requested\n");
tp->action = ATA_C_ATTACH;
- tp->dev = ch->dev;
+ tp->dev = dev;
TASK_INIT(&tp->task, 0, ata_sata_phy_event, tp);
taskqueue_enqueue(taskqueue_thread, &tp->task);
}
@@ -3766,11 +4220,16 @@ static int
ata_promise_mio_command(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));
- u_int32_t *wordp = (u_int32_t *)ch->dma->work;
+ struct ata_channel *ch = device_get_softc(request->parent);
+ struct ata_device *atadev = device_get_softc(request->dev);
+
+ u_int32_t *wordp = (u_int32_t *)ch->dma.work;
ATA_OUTL(ctlr->r_res2, (ch->unit + 1) << 2, 0x00000001);
+ /* set portmultiplier port */
+ ATA_OUTB(ctlr->r_res2, 0x4e8 + (ch->unit << 8), atadev->unit & 0x0f);
+
/* XXX SOS add ATAPI commands support later */
switch (request->u.ata.command) {
default:
@@ -3786,11 +4245,11 @@ ata_promise_mio_command(struct ata_reque
wordp[0] = htole32(0x00 | ((ch->unit + 1) << 16) | (0x00 << 24));
break;
}
- wordp[1] = htole32(ch->dma->sg_bus);
+ wordp[1] = htole32(request->dma->sg_bus);
wordp[2] = 0;
ata_promise_apkt((u_int8_t*)wordp, request);
- ATA_OUTL(ctlr->r_res2, 0x0240 + (ch->unit << 7), ch->dma->work_bus);
+ ATA_OUTL(ctlr->r_res2, 0x0240 + (ch->unit << 7), ch->dma.work_bus);
return 0;
}
@@ -3859,7 +4318,7 @@ ata_promise_mio_reset(device_t dev)
if ((ctlr->chip->cfg2 == PRSATA2) ||
((ctlr->chip->cfg2 == PRCMBO2) && (ch->unit < 2))) {
/* set portmultiplier port */
- ATA_OUTL(ctlr->r_res2, 0x4e8 + (ch->unit << 8), 0x0f);
+ //ATA_OUTL(ctlr->r_res2, 0x4e8 + (ch->unit << 8), 0x0f);
/* mask plug/unplug intr */
ATA_OUTL(ctlr->r_res2, 0x060, (0x00110000 << ch->unit));
@@ -3880,13 +4339,39 @@ ata_promise_mio_reset(device_t dev)
(ATA_INL(ctlr->r_res2, 0x414 + (ch->unit << 8)) &
~0x00000003) | 0x00000001);
- if (ata_sata_phy_reset(dev))
- ata_generic_reset(dev);
+ if (ata_sata_phy_reset(dev)) {
+ u_int32_t signature = ch->hw.softreset(dev, ATA_PM);
+
+ if (1 | bootverbose)
+ device_printf(dev, "SIGNATURE: %08x\n", signature);
+
+ switch (signature) {
+ case 0x00000101:
+ ch->devices = ATA_ATA_MASTER;
+ break;
+ case 0x96690101:
+ ch->devices = ATA_PORTMULTIPLIER;
+ ata_pm_identify(dev);
+ break;
+ case 0xeb140101:
+ ch->devices = ATA_ATAPI_MASTER;
+ break;
+ default: /* SOS XXX */
+ if (bootverbose)
+ device_printf(dev,
+ "No signature, asuming disk device\n");
+ ch->devices = ATA_ATA_MASTER;
+ }
+ if (bootverbose)
+ device_printf(dev, "promise_mio_reset devices=%08x\n",
+ ch->devices);
+
+ }
/* reset and enable plug/unplug intr */
ATA_OUTL(ctlr->r_res2, 0x060, (0x00000011 << ch->unit));
- /* set portmultiplier port */
+ ///* set portmultiplier port */
ATA_OUTL(ctlr->r_res2, 0x4e8 + (ch->unit << 8), 0x00);
}
else
@@ -3896,15 +4381,127 @@ ata_promise_mio_reset(device_t dev)
}
}
+static int
+ata_promise_mio_pm_read(device_t dev, int port, int reg, u_int32_t *result)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
+ struct ata_channel *ch = device_get_softc(dev);
+ int timeout = 0;
+
+ /* set portmultiplier port */
+ ATA_OUTB(ctlr->r_res2, 0x4e8 + (ch->unit << 8), 0x0f);
+
+ ATA_IDX_OUTB(ch, ATA_FEATURE, reg);
+ ATA_IDX_OUTB(ch, ATA_DRIVE, port);
+
+ ATA_IDX_OUTB(ch, ATA_COMMAND, ATA_READ_PM);
+
+ while (timeout < 1000000) {
+ u_int8_t status = ATA_IDX_INB(ch, ATA_STATUS);
+ if (!(status & ATA_S_BUSY))
+ break;
+ timeout += 1000;
+ DELAY(1000);
+ }
+ if (timeout >= 1000000)
+ return ATA_E_ABORT;
+
+ *result = ATA_IDX_INB(ch, ATA_COUNT) |
+ (ATA_IDX_INB(ch, ATA_SECTOR) << 8) |
+ (ATA_IDX_INB(ch, ATA_CYL_LSB) << 16) |
+ (ATA_IDX_INB(ch, ATA_CYL_MSB) << 24);
+ return 0;
+}
+
+static int
+ata_promise_mio_pm_write(device_t dev, int port, int reg, u_int32_t value)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
+ struct ata_channel *ch = device_get_softc(dev);
+ int timeout = 0;
+
+ /* set portmultiplier port */
+ ATA_OUTB(ctlr->r_res2, 0x4e8 + (ch->unit << 8), 0x0f);
+
+ ATA_IDX_OUTB(ch, ATA_FEATURE, reg);
+ ATA_IDX_OUTB(ch, ATA_DRIVE, port);
+ ATA_IDX_OUTB(ch, ATA_COUNT, value & 0xff);
+ ATA_IDX_OUTB(ch, ATA_SECTOR, (value >> 8) & 0xff);
+ ATA_IDX_OUTB(ch, ATA_CYL_LSB, (value >> 16) & 0xff);
+ ATA_IDX_OUTB(ch, ATA_CYL_MSB, (value >> 24) & 0xff);
+
+ ATA_IDX_OUTB(ch, ATA_COMMAND, ATA_WRITE_PM);
+
+ while (timeout < 1000000) {
+ u_int8_t status = ATA_IDX_INB(ch, ATA_STATUS);
+ if (!(status & ATA_S_BUSY))
+ break;
+ timeout += 1000;
+ DELAY(1000);
+ }
+ if (timeout >= 1000000)
+ return ATA_E_ABORT;
+
+ return ATA_IDX_INB(ch, ATA_ERROR);
+}
+
+/* must be called with ATA channel locked and state_mtx held */
+static u_int32_t
+ata_promise_mio_softreset(device_t dev, int port)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
+ struct ata_channel *ch = device_get_softc(dev);
+ int timeout;
+
+ /* set portmultiplier port */
+ ATA_OUTB(ctlr->r_res2, 0x4e8 + (ch->unit << 8), port & 0x0f);
+
+ /* softreset device on this channel */
+ ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | ATA_DEV(ATA_MASTER));
+ DELAY(10);
+ ATA_IDX_OUTB(ch, ATA_CONTROL, ATA_A_IDS | ATA_A_RESET);
+ ata_udelay(10000);
+ ATA_IDX_OUTB(ch, ATA_CONTROL, ATA_A_IDS);
+ ata_udelay(150000);
+ ATA_IDX_INB(ch, ATA_ERROR);
+
+ /* wait for BUSY to go inactive */
+ for (timeout = 0; timeout < 100; timeout++) {
+ u_int8_t err, stat;
+
+ err = ATA_IDX_INB(ch, ATA_ERROR);
+ stat = ATA_IDX_INB(ch, ATA_STATUS);
+
+ //if (stat == err && timeout > (stat & ATA_S_BUSY ? 100 : 10))
+ //break;
+
+ if (!(stat & ATA_S_BUSY)) {
+ //if ((err & 0x7f) == ATA_E_ILI) {
+ return ATA_IDX_INB(ch, ATA_COUNT) |
+ (ATA_IDX_INB(ch, ATA_SECTOR) << 8) |
+ (ATA_IDX_INB(ch, ATA_CYL_LSB) << 16) |
+ (ATA_IDX_INB(ch, ATA_CYL_MSB) << 24);
+ //}
+ //else if (stat & 0x0f) {
+ //stat |= ATA_S_BUSY;
+ //}
+ }
+
+ if (!(stat & ATA_S_BUSY) || (stat == 0xff && timeout > 10))
+ break;
+ ata_udelay(100000);
+ }
+ return -1;
+}
+
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;
+ /* note start and stop are not used here */
+ ch->dma.setprd = ata_promise_mio_setprd;
}
@@ -3990,8 +4587,8 @@ ata_promise_sx4_command(struct ata_reque
{
device_t gparent = GRANDPARENT(request->dev);
struct ata_pci_controller *ctlr = device_get_softc(gparent);
- struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
- struct ata_dma_prdentry *prd = ch->dma->sg;
+ struct ata_channel *ch = device_get_softc(request->parent);
+ struct ata_dma_prdentry *prd = request->dma->sg;
caddr_t window = rman_get_virtual(ctlr->r_res1);
u_int32_t *wordp;
int i, idx, length = 0;
@@ -4098,7 +4695,7 @@ ata_promise_apkt(u_int8_t *bytep, struct
int i = 12;
bytep[i++] = ATA_PDC_1B | ATA_PDC_WRITE_REG | ATA_PDC_WAIT_NBUSY|ATA_DRIVE;
- bytep[i++] = ATA_D_IBM | ATA_D_LBA | atadev->unit;
+ bytep[i++] = ATA_D_IBM | ATA_D_LBA | ATA_DEV(atadev->unit);
bytep[i++] = ATA_PDC_1B | ATA_PDC_WRITE_CTL;
bytep[i++] = ATA_A_4BIT;
@@ -4119,7 +4716,7 @@ ata_promise_apkt(u_int8_t *bytep, struct
bytep[i++] = request->u.ata.lba >> 40;
bytep[i++] = request->u.ata.lba >> 16;
bytep[i++] = ATA_PDC_1B | ATA_PDC_WRITE_REG | ATA_DRIVE;
- bytep[i++] = ATA_D_LBA | atadev->unit;
+ bytep[i++] = ATA_D_LBA | ATA_DEV(atadev->unit);
}
else {
bytep[i++] = ATA_PDC_1B | ATA_PDC_WRITE_REG | ATA_FEATURE;
@@ -4134,7 +4731,8 @@ ata_promise_apkt(u_int8_t *bytep, struct
bytep[i++] = request->u.ata.lba >> 16;
bytep[i++] = ATA_PDC_1B | ATA_PDC_WRITE_REG | ATA_DRIVE;
bytep[i++] = (atadev->flags & ATA_D_USE_CHS ? 0 : ATA_D_LBA) |
- ATA_D_IBM | atadev->unit | ((request->u.ata.lba >> 24)&0xf);
+ ATA_D_IBM | ATA_DEV(atadev->unit) |
+ ((request->u.ata.lba >> 24)&0xf);
}
bytep[i++] = ATA_PDC_1B | ATA_PDC_WRITE_END | ATA_COMMAND;
bytep[i++] = request->u.ata.command;
@@ -4294,8 +4892,7 @@ ata_serverworks_allocate(device_t dev)
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;
+ ch->dma.max_iosize = 126 * DEV_BSIZE;
return 0;
}
@@ -4303,7 +4900,7 @@ ata_serverworks_allocate(device_t dev)
static void
ata_serverworks_tf_read(struct ata_request *request)
{
- struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
+ struct ata_channel *ch = device_get_softc(request->parent);
struct ata_device *atadev = device_get_softc(request->dev);
if (atadev->flags & ATA_D_48BIT_ACTIVE) {
@@ -4332,7 +4929,7 @@ ata_serverworks_tf_read(struct ata_reque
static void
ata_serverworks_tf_write(struct ata_request *request)
{
- struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
+ struct ata_channel *ch = device_get_softc(request->parent);
struct ata_device *atadev = device_get_softc(request->dev);
if (atadev->flags & ATA_D_48BIT_ACTIVE) {
@@ -4344,7 +4941,7 @@ ata_serverworks_tf_write(struct ata_requ
((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);
+ ATA_IDX_OUTW(ch, ATA_DRIVE, ATA_D_LBA | ATA_DEV(atadev->unit));
}
else {
ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature);
@@ -4365,7 +4962,7 @@ ata_serverworks_tf_write(struct ata_requ
(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 |
+ ATA_IDX_OUTW(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(atadev->unit) |
(((request->u.ata.lba% (sectors * heads)) /
sectors) & 0xf));
}
@@ -4374,7 +4971,7 @@ ata_serverworks_tf_write(struct ata_requ
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 |
+ ATA_D_IBM | ATA_D_LBA | ATA_DEV(atadev->unit) |
((request->u.ata.lba >> 24) & 0x0f));
}
}
@@ -4387,7 +4984,7 @@ ata_serverworks_setmode(device_t dev, in
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 devno = (ch->unit << 1) + ATA_DEV(atadev->unit);
+ int devno = (ch->unit << 1) + atadev->unit;
int offset = (devno ^ 0x01) << 3;
int error;
u_int8_t piotimings[] = { 0x5d, 0x47, 0x34, 0x22, 0x20, 0x34, 0x22, 0x20,
@@ -4449,21 +5046,21 @@ ata_sii_ident(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(dev);
static struct ata_chip_id ids[] =
- {{ ATA_SII3114, 0x00, SIIMEMIO, SII4CH, ATA_SA150, "SiI 3114" },
- { ATA_SII3512, 0x02, SIIMEMIO, 0, ATA_SA150, "SiI 3512" },
- { ATA_SII3112, 0x02, SIIMEMIO, 0, ATA_SA150, "SiI 3112" },
- { ATA_SII3112_1, 0x02, SIIMEMIO, 0, ATA_SA150, "SiI 3112" },
- { 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_SII3132_1, 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" },
+ {{ ATA_SII3114, 0x00, SIIMEMIO, SII4CH, ATA_SA150, "3114" },
+ { ATA_SII3512, 0x02, SIIMEMIO, 0, ATA_SA150, "3512" },
+ { ATA_SII3112, 0x02, SIIMEMIO, 0, ATA_SA150, "3112" },
+ { ATA_SII3112_1, 0x02, SIIMEMIO, 0, ATA_SA150, "3112" },
+ { ATA_SII3512, 0x00, SIIMEMIO, SIIBUG, ATA_SA150, "3512" },
+ { ATA_SII3112, 0x00, SIIMEMIO, SIIBUG, ATA_SA150, "3112" },
+ { ATA_SII3112_1, 0x00, SIIMEMIO, SIIBUG, ATA_SA150, "3112" },
+ { ATA_SII3124, 0x00, SIIPRBIO, SII4CH, ATA_SA300, "3124" },
+ { ATA_SII3132, 0x00, SIIPRBIO, 0, ATA_SA300, "3132" },
+ { ATA_SII3132_1, 0x00, SIIPRBIO, 0, ATA_SA300, "3132" },
+ { ATA_SII0680, 0x00, SIIMEMIO, SIISETCLK, ATA_UDMA6, "680" },
+ { 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}};
if (!(ctlr->chip = ata_match_chip(dev, ids)))
@@ -4517,7 +5114,7 @@ ata_sii_chipinit(device_t dev)
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))) {
+ &ctlr->r_rid2, RF_ACTIVE))){
if (ctlr->chip->chipid != ATA_SII0680 ||
(pci_read_config(dev, 0x8a, 1) & 1))
return ENXIO;
@@ -4594,9 +5191,9 @@ ata_cmd_status(device_t dev)
struct ata_channel *ch = device_get_softc(dev);
u_int8_t reg71;
- if (((reg71 = pci_read_config(device_get_parent(ch->dev), 0x71, 1)) &
+ if (((reg71 = pci_read_config(device_get_parent(dev), 0x71, 1)) &
(ch->unit ? 0x08 : 0x04))) {
- pci_write_config(device_get_parent(ch->dev), 0x71,
+ pci_write_config(device_get_parent(dev), 0x71,
reg71 & ~(ch->unit ? 0x04 : 0x08), 1);
return ata_pci_status(dev);
}
@@ -4610,7 +5207,7 @@ ata_cmd_setmode(device_t dev, int mode)
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 devno = (ch->unit << 1) + ATA_DEV(atadev->unit);
+ int devno = (ch->unit << 1) + atadev->unit;
int error;
mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma);
@@ -4635,7 +5232,7 @@ ata_cmd_setmode(device_t dev, int mode)
u_int8_t umode = pci_read_config(gparent, ureg, 1);
umode &= ~(atadev->unit == ATA_MASTER ? 0x35 : 0xca);
- umode |= udmatimings[mode & ATA_MODE_MASK][ATA_DEV(atadev->unit)];
+ umode |= udmatimings[mode & ATA_MODE_MASK][atadev->unit];
pci_write_config(gparent, ureg, umode, 1);
}
else if (mode >= ATA_WDMA0) {
@@ -4695,10 +5292,10 @@ ata_sii_allocate(device_t dev)
ATA_OUTL(ctlr->r_res2, 0x148 + (unit01 << 7) + (unit10 << 8),(1 << 16));
}
- if ((ctlr->chip->cfg2 & SIIBUG) && ch->dma) {
+ if (ctlr->chip->cfg2 & SIIBUG) {
/* work around errata in early chips */
- ch->dma->boundary = 8192;
- ch->dma->segsize = 15 * DEV_BSIZE;
+ ch->dma.boundary = 8192;
+ ch->dma.segsize = 15 * DEV_BSIZE;
}
ata_pci_hw(dev);
@@ -4739,9 +5336,9 @@ ata_sii_setmode(device_t dev, int mode)
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 rego = (ch->unit << 4) + (ATA_DEV(atadev->unit) << 1);
+ int rego = (ch->unit << 4) + (atadev->unit << 1);
int mreg = ch->unit ? 0x84 : 0x80;
- int mask = 0x03 << (ATA_DEV(atadev->unit) << 2);
+ int mask = 0x03 << (atadev->unit << 2);
int mval = pci_read_config(gparent, mreg, 1) & ~mask;
int error;
@@ -4771,7 +5368,7 @@ ata_sii_setmode(device_t dev, int mode)
u_int8_t ureg = 0xac + rego;
pci_write_config(gparent, mreg,
- mval | (0x03 << (ATA_DEV(atadev->unit) << 2)), 1);
+ mval | (0x03 << (atadev->unit << 2)), 1);
pci_write_config(gparent, ureg,
(pci_read_config(gparent, ureg, 1) & ~0x3f) |
udmatimings[mode & ATA_MODE_MASK], 1);
@@ -4782,7 +5379,7 @@ ata_sii_setmode(device_t dev, int mode)
u_int16_t dmatimings[] = { 0x2208, 0x10c2, 0x10c1 };
pci_write_config(gparent, mreg,
- mval | (0x02 << (ATA_DEV(atadev->unit) << 2)), 1);
+ mval | (0x02 << (atadev->unit << 2)), 1);
pci_write_config(gparent, dreg, dmatimings[mode & ATA_MODE_MASK], 2);
}
@@ -4791,7 +5388,7 @@ ata_sii_setmode(device_t dev, int mode)
u_int16_t piotimings[] = { 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1 };
pci_write_config(gparent, mreg,
- mval | (0x01 << (ATA_DEV(atadev->unit) << 2)), 1);
+ mval | (0x01 << (atadev->unit << 2)), 1);
pci_write_config(gparent, preg, piotimings[mode & ATA_MODE_MASK], 2);
}
atadev->mode = mode;
@@ -4804,13 +5401,14 @@ struct ata_siiprb_dma_prdentry {
u_int32_t control;
} __packed;
+#define ATA_SIIPRB_DMA_ENTRIES 125
struct ata_siiprb_ata_command {
- struct ata_siiprb_dma_prdentry prd[126];
+ struct ata_siiprb_dma_prdentry prd[ATA_SIIPRB_DMA_ENTRIES];
} __packed;
struct ata_siiprb_atapi_command {
u_int8_t ccb[16];
- struct ata_siiprb_dma_prdentry prd[125];
+ struct ata_siiprb_dma_prdentry prd[ATA_SIIPRB_DMA_ENTRIES];
} __packed;
struct ata_siiprb_command {
@@ -4841,10 +5439,14 @@ ata_siiprb_allocate(device_t dev)
ch->r_io[ATA_SACTIVE].res = ctlr->r_res2;
ch->r_io[ATA_SACTIVE].offset = 0x1f0c + offset;
+ ch->hw.status = ata_siiprb_status;
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 */
+ ch->hw.softreset = ata_siiprb_softreset;
+ ch->hw.pm_read = ata_siiprb_pm_read;
+ ch->hw.pm_write = ata_siiprb_pm_write;
+
return 0;
}
@@ -4875,12 +5477,11 @@ 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_channel *ch = device_get_softc(request->parent);
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) {
@@ -4888,12 +5489,9 @@ ata_siiprb_begin_transaction(struct ata_
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));
+ (ch->dma.work + (sizeof(struct ata_siiprb_command) * request->tag));
/* set basic prd options ata/atapi etc etc */
bzero(prb, sizeof(struct ata_siiprb_command));
@@ -4925,8 +5523,7 @@ ata_siiprb_begin_transaction(struct ata_
/* 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)) {
+ if (ch->dma.load(request, prd, NULL)) {
device_printf(request->dev, "setting up DMA failed\n");
request->result = EIO;
return ATA_OP_FINISHED;
@@ -4934,11 +5531,12 @@ ata_siiprb_begin_transaction(struct ata_
}
/* activate the prb */
- prb_bus = ch->dma->work_bus + (sizeof(struct ata_siiprb_command) * tag);
+ prb_bus = ch->dma.work_bus +
+ (sizeof(struct ata_siiprb_command) * request->tag);
ATA_OUTL(ctlr->r_res2,
- 0x1c00 + offset + (tag * sizeof(u_int64_t)), prb_bus);
+ 0x1c00 + offset + (request->tag * sizeof(u_int64_t)), prb_bus);
ATA_OUTL(ctlr->r_res2,
- 0x1c04 + offset + (tag * sizeof(u_int64_t)), prb_bus>>32);
+ 0x1c04 + offset + (request->tag * sizeof(u_int64_t)), prb_bus>>32);
/* start the timeout */
callout_reset(&request->callout, request->timeout * hz,
@@ -4950,16 +5548,16 @@ 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_channel *ch = device_get_softc(request->parent);
struct ata_siiprb_command *prb;
int offset = ch->unit * 0x2000;
- int error, timeout, tag = 0;
+ int error, timeout;
/* kill the timeout */
callout_stop(&request->callout);
prb = (struct ata_siiprb_command *)
- ((u_int8_t *)rman_get_virtual(ctlr->r_res2) + (tag << 7) + offset);
+ ((u_int8_t *)rman_get_virtual(ctlr->r_res2)+(request->tag << 7)+offset);
/* any controller errors flagged ? */
if ((error = ATA_INL(ctlr->r_res2, 0x1024 + offset))) {
@@ -4993,6 +5591,21 @@ ata_siiprb_end_transaction(struct ata_re
}
}
+ /* on control commands read back registers to the request struct */
+ if (request->flags & ATA_R_CONTROL) {
+ struct ata_device *atadev = device_get_softc(request->dev);
+
+ request->u.ata.count = prb->fis[12] | ((u_int16_t)prb->fis[13] << 8);
+ request->u.ata.lba = prb->fis[4] | ((u_int64_t)prb->fis[5] << 8) |
+ ((u_int64_t)prb->fis[6] << 16);
+ if (atadev->flags & ATA_D_48BIT_ACTIVE)
+ request->u.ata.lba |= ((u_int64_t)prb->fis[8] << 24) |
+ ((u_int64_t)prb->fis[9] << 32) |
+ ((u_int64_t)prb->fis[10] << 40);
+ else
+ request->u.ata.lba |= ((u_int64_t)(prb->fis[7] & 0x0f) << 24);
+ }
+
/* update progress */
if (!(request->status & ATA_S_ERROR) && !(request->flags & ATA_R_TIMEOUT)) {
if (request->flags & ATA_R_READ)
@@ -5002,21 +5615,126 @@ ata_siiprb_end_transaction(struct ata_re
}
/* release SG list etc */
- ch->dma->unload(ch->dev);
+ ch->dma.unload(request);
return ATA_OP_FINISHED;
}
+static int
+ata_siiprb_issue_cmd(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
+ struct ata_channel *ch = device_get_softc(dev);
+ u_int64_t prb_bus = ch->dma.work_bus;
+ u_int32_t status;
+ int offset = ch->unit * 0x2000;
+ int timeout;
+
+ /* issue command to chip */
+ ATA_OUTL(ctlr->r_res2, 0x1c00 + offset, prb_bus);
+ ATA_OUTL(ctlr->r_res2, 0x1c04 + offset, 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;
+ }
+ ATA_OUTL(ctlr->r_res2, 0x1008 + offset, 0x00010000);
+
+ if (timeout >= 1000)
+ return EIO;
+
+ if (bootverbose)
+ device_printf(dev, "siiprb_issue_cmd time=%dms status=%08x\n",
+ timeout, status);
+ return 0;
+}
+
+static int
+ata_siiprb_pm_read(device_t dev, int port, int reg, u_int32_t *result)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
+ struct ata_channel *ch = device_get_softc(dev);
+ struct ata_siiprb_command *prb = (struct ata_siiprb_command *)ch->dma.work;
+ int offset = ch->unit * 0x2000;
+
+ bzero(prb, sizeof(struct ata_siiprb_command));
+ prb->fis[0] = 0x27; /* host to device */
+ prb->fis[1] = 0x8f; /* command FIS to PM port */
+ prb->fis[2] = ATA_READ_PM;
+ prb->fis[3] = reg;
+ prb->fis[7] = port;
+ if (ata_siiprb_issue_cmd(dev)) {
+ device_printf(dev, "error reading PM port\n");
+ return EIO;
+ }
+ prb = (struct ata_siiprb_command *)
+ ((u_int8_t *)rman_get_virtual(ctlr->r_res2) + offset);
+ *result = prb->fis[12]|(prb->fis[4]<<8)|(prb->fis[5]<<16)|(prb->fis[6]<<24);
+ return 0;
+}
+
+static int
+ata_siiprb_pm_write(device_t dev, int port, int reg, u_int32_t value)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
+ struct ata_channel *ch = device_get_softc(dev);
+ struct ata_siiprb_command *prb = (struct ata_siiprb_command *)ch->dma.work;
+ int offset = ch->unit * 0x2000;
+
+ bzero(prb, sizeof(struct ata_siiprb_command));
+ prb->fis[0] = 0x27; /* host to device */
+ prb->fis[1] = 0x8f; /* command FIS to PM port */
+ prb->fis[2] = ATA_WRITE_PM;
+ prb->fis[3] = reg;
+ prb->fis[7] = port;
+ prb->fis[12] = value & 0xff;
+ prb->fis[4] = (value >> 8) & 0xff;;
+ prb->fis[5] = (value >> 16) & 0xff;;
+ prb->fis[6] = (value >> 24) & 0xff;;
+ if (ata_siiprb_issue_cmd(dev)) {
+ device_printf(dev, "error writing PM port\n");
+ return ATA_E_ABORT;
+ }
+ prb = (struct ata_siiprb_command *)
+ ((u_int8_t *)rman_get_virtual(ctlr->r_res2) + offset);
+ return prb->fis[3];
+}
+
+static u_int32_t
+ata_siiprb_softreset(device_t dev, int port)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
+ struct ata_channel *ch = device_get_softc(dev);
+ struct ata_siiprb_command *prb = (struct ata_siiprb_command *)ch->dma.work;
+ int offset = ch->unit * 0x2000;
+
+ /* setup the workspace for a soft reset command */
+ bzero(prb, sizeof(struct ata_siiprb_command));
+ prb->control = htole16(0x0080);
+ prb->fis[1] = port & 0x0f;
+
+ /* issue soft reset */
+ if (ata_siiprb_issue_cmd(dev))
+ return -1;
+
+ ata_udelay(150000);
+
+ /* return possible signature */
+ prb = (struct ata_siiprb_command *)
+ ((u_int8_t *)rman_get_virtual(ctlr->r_res2) + offset);
+ return prb->fis[12]|(prb->fis[4]<<8)|(prb->fis[5]<<16)|(prb->fis[6]<<24);
+}
+
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;
+ int timeout;
/* reset channel HW */
ATA_OUTL(ctlr->r_res2, 0x1000 + offset, 0x00000001);
@@ -5033,62 +5751,33 @@ ata_siiprb_reset(device_t dev)
if (bootverbose) {
if (timeout >= 1000)
- device_printf(ch->dev, "channel HW reset timeout\n");
+ device_printf(dev, "channel HW reset timeout\n");
else
- device_printf(ch->dev, "channel HW reset time=%dms\n", timeout);
+ device_printf(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");
+ device_printf(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;
- }
+ /* issue soft reset */
+ signature = ata_siiprb_softreset(dev, ATA_PM);
if (bootverbose)
- device_printf(ch->dev, "soft reset exec time=%dms status=%08x\n",
- timeout, status);
+ device_printf(dev, "SIGNATURE=%08x\n", signature);
- /* 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);
+ /* figure out whats there */
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;
+ ATA_OUTL(ctlr->r_res2, 0x1000 + offset, 0x2000); /* enable PM support */
+ ata_pm_identify(dev);
break;
case 0xeb140101:
ch->devices = ATA_ATAPI_MASTER;
@@ -5097,8 +5786,7 @@ ata_siiprb_reset(device_t dev)
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");
+ device_printf(dev, "siiprb_reset devices=%08x\n", ch->devices);
finish:
/* clear interrupt(s) */
@@ -5129,7 +5817,7 @@ ata_siiprb_dmasetprd(void *xsc, bus_dma_
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"));
+ KASSERT(nsegs <= ATA_SIIPRB_DMA_ENTRIES,("too many DMA segment entries\n"));
args->nsegs = nsegs;
}
@@ -5139,11 +5827,9 @@ 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;
- }
+ /* note start and stop are not used here */
+ ch->dma.setprd = ata_siiprb_dmasetprd;
+ ch->dma.max_address = BUS_SPACE_MAXADDR;
}
@@ -5314,7 +6000,7 @@ ata_sis_setmode(device_t dev, int mode)
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 devno = (ch->unit << 1) + ATA_DEV(atadev->unit);
+ int devno = (ch->unit << 1) + atadev->unit;
int error;
mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma);
@@ -5639,7 +6325,7 @@ ata_via_family_setmode(device_t dev, int
{ 0xf7, 0xf6, 0xf4, 0xf2, 0xf1, 0xf0, 0x00 }, /* VIA ATA100 */
{ 0xf7, 0xf7, 0xf6, 0xf4, 0xf2, 0xf1, 0xf0 }, /* VIA ATA133 */
{ 0xc2, 0xc1, 0xc0, 0xc4, 0xc5, 0xc6, 0xc7 }}; /* AMD/nVIDIA */
- int devno = (ch->unit << 1) + ATA_DEV(atadev->unit);
+ int devno = (ch->unit << 1) + atadev->unit;
int reg = 0x53 - devno;
int error;
@@ -5793,7 +6479,7 @@ ata_serialize(device_t dev, int flags)
if ((ch = ctlr->interrupt[serial->restart_ch].argument)) {
serial->restart_ch = -1;
mtx_unlock(&serial->locked_mtx);
- ata_start(ch->dev);
+ ata_start(dev);
return -1;
}
}
--- src/sys/dev/ata/ata-disk.c 2008-04-08 14:48:21.000000000 +0400
+++ src/sys/dev/ata/ata-disk.c 2008-05-08 21:55:44.000000000 +0400
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -39,7 +39,6 @@ __FBSDID("$FreeBSD: src/sys/dev/ata/ata-
#include <sys/conf.h>
#include <sys/disk.h>
#include <sys/cons.h>
-#include <sys/sysctl.h>
#include <sys/sema.h>
#include <sys/taskqueue.h>
#include <vm/uma.h>
@@ -54,10 +53,12 @@ __FBSDID("$FreeBSD: src/sys/dev/ata/ata-
#include <ata_if.h>
/* prototypes */
-static void ad_init(device_t);
-static void ad_done(struct ata_request *);
+static void ad_init(device_t dev);
+static void ad_get_geometry(device_t dev);
+static void ad_set_geometry(device_t dev);
+static void ad_done(struct ata_request *request);
static void ad_describe(device_t dev);
-static int ad_version(u_int16_t);
+static int ad_version(u_int16_t version);
static disk_strategy_t ad_strategy;
static disk_ioctl_t ad_ioctl;
static dumper_t ad_dump;
@@ -93,8 +94,6 @@ ad_attach(device_t dev)
struct ata_channel *ch = device_get_softc(device_get_parent(dev));
struct ata_device *atadev = device_get_softc(dev);
struct ad_softc *adp;
- u_int32_t lbasize;
- u_int64_t lbasize48;
/* check that we have a virgin disk to attach */
if (device_get_ivars(dev))
@@ -106,37 +105,12 @@ ad_attach(device_t dev)
}
device_set_ivars(dev, adp);
- if ((atadev->param.atavalid & ATA_FLAG_54_58) &&
- atadev->param.current_heads && atadev->param.current_sectors) {
- adp->heads = atadev->param.current_heads;
- adp->sectors = atadev->param.current_sectors;
- adp->total_secs = (u_int32_t)atadev->param.current_size_1 |
- ((u_int32_t)atadev->param.current_size_2 << 16);
- }
- else {
- adp->heads = atadev->param.heads;
- adp->sectors = atadev->param.sectors;
- adp->total_secs = atadev->param.cylinders * adp->heads * adp->sectors;
- }
- lbasize = (u_int32_t)atadev->param.lba_size_1 |
- ((u_int32_t)atadev->param.lba_size_2 << 16);
-
- /* does this device need oldstyle CHS addressing */
- if (!ad_version(atadev->param.version_major) || !lbasize)
- atadev->flags |= ATA_D_USE_CHS;
+ /* get device geometry into internal structs */
+ ad_get_geometry(dev);
- /* use the 28bit LBA size if valid or bigger than the CHS mapping */
- if (atadev->param.cylinders == 16383 || adp->total_secs < lbasize)
- adp->total_secs = lbasize;
-
- /* use the 48bit LBA size if valid */
- lbasize48 = ((u_int64_t)atadev->param.lba_size48_1) |
- ((u_int64_t)atadev->param.lba_size48_2 << 16) |
- ((u_int64_t)atadev->param.lba_size48_3 << 32) |
- ((u_int64_t)atadev->param.lba_size48_4 << 48);
- if ((atadev->param.support.command2 & ATA_SUPPORT_ADDRESS48) &&
- lbasize48 > ATA_MAX_28BIT_LBA)
- adp->total_secs = lbasize48;
+ /* set the max size if configured */
+ if (ata_setmax)
+ ad_set_geometry(dev);
/* init device parameters */
ad_init(dev);
@@ -151,10 +125,7 @@ ad_attach(device_t dev)
adp->disk->d_dump = ad_dump;
adp->disk->d_name = "ad";
adp->disk->d_drv1 = dev;
- if (ch->dma)
- adp->disk->d_maxsize = ch->dma->max_iosize;
- else
- adp->disk->d_maxsize = DFLTPHYS;
+ adp->disk->d_maxsize = ch->dma.max_iosize ? ch->dma.max_iosize : DFLTPHYS;
adp->disk->d_sectorsize = DEV_BSIZE;
adp->disk->d_mediasize = DEV_BSIZE * (off_t)adp->total_secs;
adp->disk->d_fwsectors = adp->sectors;
@@ -249,7 +220,7 @@ ad_spindown(void *priv)
struct ata_device *atadev = device_get_softc(dev);
struct ata_request *request;
- if(atadev->spindown == 0)
+ if (!atadev->spindown)
return;
device_printf(dev, "Idle, spin down\n");
atadev->spindown_state = 1;
@@ -257,8 +228,8 @@ ad_spindown(void *priv)
device_printf(dev, "FAILURE - out of memory in ad_spindown\n");
return;
}
- request->flags = ATA_R_CONTROL;
request->dev = dev;
+ request->flags = ATA_R_CONTROL;
request->timeout = 5;
request->retries = 1;
request->callback = ad_power_callback;
@@ -274,9 +245,9 @@ ad_strategy(struct bio *bp)
struct ata_device *atadev = device_get_softc(dev);
struct ata_request *request;
- if (atadev->spindown != 0)
+ if (atadev->spindown)
callout_reset(&atadev->spindown_timer, hz * atadev->spindown,
- ad_spindown, dev);
+ ad_spindown, dev);
if (!(request = ata_alloc_request())) {
device_printf(dev, "FAILURE - out of memory in start\n");
@@ -292,7 +263,8 @@ ad_strategy(struct bio *bp)
device_printf(dev, "request while spun down, starting.\n");
atadev->spindown_state = 0;
request->timeout = 31;
- } else {
+ }
+ else {
request->timeout = 5;
}
request->retries = 2;
@@ -426,7 +398,105 @@ ad_init(device_t dev)
atadev->max_iosize = DEV_BSIZE;
}
-void
+static void
+ad_get_geometry(device_t dev)
+{
+ struct ata_device *atadev = device_get_softc(dev);
+ struct ad_softc *adp = device_get_ivars(dev);
+ u_int64_t lbasize48;
+ u_int32_t lbasize;
+
+ if ((atadev->param.atavalid & ATA_FLAG_54_58) &&
+ atadev->param.current_heads && atadev->param.current_sectors) {
+ adp->heads = atadev->param.current_heads;
+ adp->sectors = atadev->param.current_sectors;
+ adp->total_secs = (u_int32_t)atadev->param.current_size_1 |
+ ((u_int32_t)atadev->param.current_size_2 << 16);
+ }
+ else {
+ adp->heads = atadev->param.heads;
+ adp->sectors = atadev->param.sectors;
+ adp->total_secs = atadev->param.cylinders * adp->heads * adp->sectors;
+ }
+ lbasize = (u_int32_t)atadev->param.lba_size_1 |
+ ((u_int32_t)atadev->param.lba_size_2 << 16);
+
+ /* does this device need oldstyle CHS addressing */
+ if (!ad_version(atadev->param.version_major) || !lbasize)
+ atadev->flags |= ATA_D_USE_CHS;
+
+ /* use the 28bit LBA size if valid or bigger than the CHS mapping */
+ if (atadev->param.cylinders == 16383 || adp->total_secs < lbasize)
+ adp->total_secs = lbasize;
+
+ /* use the 48bit LBA size if valid */
+ lbasize48 = ((u_int64_t)atadev->param.lba_size48_1) |
+ ((u_int64_t)atadev->param.lba_size48_2 << 16) |
+ ((u_int64_t)atadev->param.lba_size48_3 << 32) |
+ ((u_int64_t)atadev->param.lba_size48_4 << 48);
+ if ((atadev->param.support.command2 & ATA_SUPPORT_ADDRESS48) &&
+ lbasize48 > ATA_MAX_28BIT_LBA)
+ adp->total_secs = lbasize48;
+}
+
+static void
+ad_set_geometry(device_t dev)
+{
+ struct ad_softc *adp = device_get_ivars(dev);
+ struct ata_request *request;
+
+ if (1 | bootverbose)
+ device_printf(dev, "ORG %ju sectors [%juC/%dH/%dS]\n", adp->total_secs,
+ adp->total_secs / (adp->heads * adp->sectors),
+ adp->heads, adp->sectors);
+
+ if (!(request = ata_alloc_request()))
+ return;
+
+ /* get the max native size the device supports */
+ request->dev = dev;
+ request->u.ata.command = ATA_READ_NATIVE_MAX_ADDRESS;
+ request->u.ata.lba = 0;
+ request->u.ata.count = 0;
+ request->u.ata.feature = 0;
+ request->flags = ATA_R_CONTROL | ATA_R_QUIET;
+ request->timeout = 5;
+ request->retries = 0;
+ ata_queue_request(request);
+ if (request->status & ATA_S_ERROR)
+ goto out;
+
+ if (1 | bootverbose)
+ device_printf(dev, "MAX %ju sectors\n", request->u.ata.lba + 1);
+
+ /* if original size equals max size nothing more todo */
+ if (adp->total_secs >= request->u.ata.lba)
+ goto out;
+
+ /* set the max native size to its max */
+ request->dev = dev;
+ request->u.ata.command = ATA_SET_MAX_ADDRESS;
+ request->u.ata.count = 1;
+ request->u.ata.feature = 0;
+ request->flags = ATA_R_CONTROL;
+ request->timeout = 5;
+ request->retries = 0;
+ ata_queue_request(request);
+ if (request->status & ATA_S_ERROR)
+ goto out;
+
+ /* refresh geometry from drive */
+ ata_getparam(device_get_softc(dev), 0);
+ ad_get_geometry(dev);
+ if (1 | bootverbose)
+ device_printf(dev, "NEW %ju sectors [%juC/%dH/%dS]\n", adp->total_secs,
+ adp->total_secs / (adp->heads * adp->sectors),
+ adp->heads, adp->sectors);
+out:
+ ata_free_request(request);
+}
+
+static void
ad_describe(device_t dev)
{
struct ata_channel *ch = device_get_softc(device_get_parent(dev));
@@ -458,8 +528,7 @@ ad_describe(device_t dev)
device_printf(dev, "%juMB <%s%s %.8s> at ata%d-%s %s%s\n",
adp->total_secs / (1048576 / DEV_BSIZE),
vendor, product, atadev->param.revision,
- device_get_unit(ch->dev),
- (atadev->unit == ATA_MASTER) ? "master" : "slave",
+ device_get_unit(ch->dev), ata_unit2str(atadev),
(adp->flags & AD_F_TAG_ENABLED) ? "tagged " : "",
ata_mode2str(atadev->mode));
if (bootverbose) {
--- src/sys/dev/ata/ata-disk.h 2007-02-21 22:07:18.000000000 +0300
+++ src/sys/dev/ata/ata-disk.h 2008-04-10 17:05:05.000000000 +0400
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,7 +34,7 @@ struct ad_softc {
u_int32_t transfersize; /* size of each transfer */
int num_tags; /* number of tags supported */
int flags; /* drive flags */
-#define AD_F_LABELLING 0x0001
+#define AD_F_LABELLING 0x0001
#define AD_F_CHS_USED 0x0002
#define AD_F_32B_ENABLED 0x0004
#define AD_F_TAG_ENABLED 0x0008
--- src/sys/dev/ata/ata-dma.c 2008-01-09 11:54:47.000000000 +0300
+++ src/sys/dev/ata/ata-dma.c 2008-04-18 19:15:04.000000000 +0400
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -45,11 +45,13 @@ __FBSDID("$FreeBSD: src/sys/dev/ata/ata-
#include <dev/ata/ata-pci.h>
/* prototypes */
-static void ata_dmaalloc(device_t);
-static void ata_dmafree(device_t);
-static void ata_dmasetprd(void *, bus_dma_segment_t *, int, int);
-static int ata_dmaload(device_t, caddr_t, int32_t, int, void *, int *);
-static int ata_dmaunload(device_t);
+static void ata_dmafini(device_t dev);
+static void ata_dmasetupc_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error);
+static void ata_dmaalloc(device_t dev);
+static void ata_dmafree(device_t dev);
+static void ata_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error);
+static int ata_dmaload(struct ata_request *request, void *addr, int *nsegs);
+static int ata_dmaunload(struct ata_request *request);
/* local vars */
static MALLOC_DEFINE(M_ATADMA, "ata_dma", "ATA driver DMA");
@@ -67,134 +69,170 @@ void
ata_dmainit(device_t dev)
{
struct ata_channel *ch = device_get_softc(dev);
+ struct ata_dc_cb_args dcba;
- if ((ch->dma = malloc(sizeof(struct ata_dma), M_ATADMA, M_NOWAIT|M_ZERO))) {
- ch->dma->alloc = ata_dmaalloc;
- ch->dma->free = ata_dmafree;
- ch->dma->setprd = ata_dmasetprd;
- ch->dma->load = ata_dmaload;
- ch->dma->unload = ata_dmaunload;
- ch->dma->alignment = 2;
- ch->dma->boundary = 65536;
- ch->dma->segsize = 128 * DEV_BSIZE;
- ch->dma->max_iosize = 128 * DEV_BSIZE;
- ch->dma->max_address = BUS_SPACE_MAXADDR_32BIT;
+ ch->dma.alloc = ata_dmaalloc;
+ ch->dma.free = ata_dmafree;
+ ch->dma.setprd = ata_dmasetprd;
+ ch->dma.load = ata_dmaload;
+ ch->dma.unload = ata_dmaunload;
+ ch->dma.alignment = 2;
+ ch->dma.boundary = 65536;
+ ch->dma.segsize = 63536;
+ ch->dma.max_iosize = 128 * DEV_BSIZE;
+ ch->dma.max_address = BUS_SPACE_MAXADDR_32BIT;
+ ch->dma.dma_slots = 2;
+
+ if (bus_dma_tag_create(bus_get_dma_tag(dev), ch->dma.alignment, 0,
+ ch->dma.max_address, BUS_SPACE_MAXADDR,
+ NULL, NULL, ch->dma.max_iosize,
+ ATA_DMA_ENTRIES, ch->dma.segsize,
+ 0, NULL, NULL, &ch->dma.dmatag))
+ goto error;
+
+ if (bus_dma_tag_create(ch->dma.dmatag, PAGE_SIZE, 64 * 1024,
+ ch->dma.max_address, BUS_SPACE_MAXADDR,
+ NULL, NULL, MAXWSPCSZ, 1, MAXWSPCSZ,
+ 0, NULL, NULL, &ch->dma.work_tag))
+ goto error;
+
+ if (bus_dmamem_alloc(ch->dma.work_tag, (void **)&ch->dma.work, 0,
+ &ch->dma.work_map))
+ goto error;
+
+ if (bus_dmamap_load(ch->dma.work_tag, ch->dma.work_map, ch->dma.work,
+ MAXWSPCSZ, ata_dmasetupc_cb, &dcba, 0) ||
+ dcba.error) {
+ bus_dmamem_free(ch->dma.work_tag, ch->dma.work, ch->dma.work_map);
+ goto error;
+ }
+ ch->dma.work_bus = dcba.maddr;
+ return;
+
+error:
+ device_printf(dev, "WARNING - DMA initialization failed, disabling DMA\n");
+ ata_dmafini(dev);
+}
+
+void
+ata_dmafini(device_t dev)
+{
+ struct ata_channel *ch = device_get_softc(dev);
+
+ if (ch->dma.work_bus) {
+ bus_dmamap_unload(ch->dma.work_tag, ch->dma.work_map);
+ bus_dmamem_free(ch->dma.work_tag, ch->dma.work, ch->dma.work_map);
+ ch->dma.work_bus = 0;
+ ch->dma.work_map = NULL;
+ ch->dma.work = NULL;
+ }
+ if (ch->dma.work_tag) {
+ bus_dma_tag_destroy(ch->dma.work_tag);
+ ch->dma.work_tag = NULL;
+ }
+ if (ch->dma.dmatag) {
+ bus_dma_tag_destroy(ch->dma.dmatag);
+ ch->dma.dmatag = NULL;
}
}
static void
ata_dmasetupc_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error)
{
- struct ata_dc_cb_args *cba = (struct ata_dc_cb_args *)xsc;
+ struct ata_dc_cb_args *dcba = (struct ata_dc_cb_args *)xsc;
- if (!(cba->error = error))
- cba->maddr = segs[0].ds_addr;
+ if (!(dcba->error = error))
+ dcba->maddr = segs[0].ds_addr;
}
static void
ata_dmaalloc(device_t dev)
{
struct ata_channel *ch = device_get_softc(dev);
- struct ata_dc_cb_args ccba;
-
- if (bus_dma_tag_create(bus_get_dma_tag(dev), ch->dma->alignment, 0,
- ch->dma->max_address, BUS_SPACE_MAXADDR,
- NULL, NULL, ch->dma->max_iosize,
- ATA_DMA_ENTRIES, ch->dma->segsize,
- 0, NULL, NULL, &ch->dma->dmatag))
- goto error;
-
- if (bus_dma_tag_create(ch->dma->dmatag, PAGE_SIZE, PAGE_SIZE,
- ch->dma->max_address, BUS_SPACE_MAXADDR,
- NULL, NULL, MAXTABSZ, 1, MAXTABSZ,
- 0, NULL, NULL, &ch->dma->sg_tag))
- goto error;
-
- if (bus_dma_tag_create(ch->dma->dmatag,ch->dma->alignment,ch->dma->boundary,
- ch->dma->max_address, BUS_SPACE_MAXADDR,
- NULL, NULL, ch->dma->max_iosize,
- ATA_DMA_ENTRIES, ch->dma->segsize,
- 0, NULL, NULL, &ch->dma->data_tag))
- goto error;
-
- if (bus_dmamem_alloc(ch->dma->sg_tag, (void **)&ch->dma->sg, 0,
- &ch->dma->sg_map))
- goto error;
-
- if (bus_dmamap_load(ch->dma->sg_tag, ch->dma->sg_map, ch->dma->sg,
- MAXTABSZ, ata_dmasetupc_cb, &ccba, 0) || ccba.error) {
- bus_dmamem_free(ch->dma->sg_tag, ch->dma->sg, ch->dma->sg_map);
- goto error;
- }
- ch->dma->sg_bus = ccba.maddr;
-
- if (bus_dmamap_create(ch->dma->data_tag, 0, &ch->dma->data_map))
- goto error;
-
- if (bus_dma_tag_create(ch->dma->dmatag, PAGE_SIZE, 64 * 1024,
- ch->dma->max_address, BUS_SPACE_MAXADDR,
- NULL, NULL, MAXWSPCSZ, 1, MAXWSPCSZ,
- 0, NULL, NULL, &ch->dma->work_tag))
- goto error;
-
- if (bus_dmamem_alloc(ch->dma->work_tag, (void **)&ch->dma->work, 0,
- &ch->dma->work_map))
- goto error;
+ struct ata_dc_cb_args dcba;
+ int i;
- if (bus_dmamap_load(ch->dma->work_tag, ch->dma->work_map,ch->dma->work,
- MAXWSPCSZ, ata_dmasetupc_cb, &ccba, 0) || ccba.error) {
- bus_dmamem_free(ch->dma->work_tag,ch->dma->work, ch->dma->work_map);
- goto error;
+ /* alloc and setup needed dma slots */
+ bzero(ch->dma.slot, sizeof(struct ata_dmaslot) * ATA_DMA_SLOTS);
+ for (i = 0; i < ch->dma.dma_slots; i++) {
+ struct ata_dmaslot *slot = &ch->dma.slot[i];
+
+ if (bus_dma_tag_create(ch->dma.dmatag, PAGE_SIZE, PAGE_SIZE,
+ ch->dma.max_address, BUS_SPACE_MAXADDR,
+ NULL, NULL, PAGE_SIZE, 1, PAGE_SIZE,
+ 0, NULL, NULL, &slot->sg_tag)) {
+ device_printf(ch->dev, "FAILURE - create sg_tag\n");
+ goto error;
+ }
+
+ if (bus_dmamem_alloc(slot->sg_tag, (void **)&slot->sg,
+ 0, &slot->sg_map)) {
+ device_printf(ch->dev, "FAILURE - alloc sg_map\n");
+ goto error;
+ }
+
+ if (bus_dmamap_load(slot->sg_tag, slot->sg_map, slot->sg, MAXTABSZ,
+ ata_dmasetupc_cb, &dcba, 0) || dcba.error) {
+ device_printf(ch->dev, "FAILURE - load sg\n");
+ goto error;
+ }
+ slot->sg_bus = dcba.maddr;
+
+ if (bus_dma_tag_create(ch->dma.dmatag,
+ ch->dma.alignment, ch->dma.boundary,
+ ch->dma.max_address, BUS_SPACE_MAXADDR,
+ NULL, NULL, ch->dma.max_iosize,
+ ATA_DMA_ENTRIES, ch->dma.segsize,
+ BUS_DMA_ALLOCNOW, NULL, NULL, &slot->data_tag)) {
+ device_printf(ch->dev, "FAILURE - create data_tag\n");
+ goto error;
+ }
+
+ if (bus_dmamap_create(slot->data_tag, 0, &slot->data_map)) {
+ device_printf(ch->dev, "FAILURE - create data_map\n");
+ goto error;
+ }
}
- ch->dma->work_bus = ccba.maddr;
return;
error:
device_printf(dev, "WARNING - DMA allocation failed, disabling DMA\n");
ata_dmafree(dev);
- free(ch->dma, M_ATADMA);
- ch->dma = NULL;
}
static void
ata_dmafree(device_t dev)
{
struct ata_channel *ch = device_get_softc(dev);
+ int i;
- if (ch->dma->work_bus) {
- bus_dmamap_unload(ch->dma->work_tag, ch->dma->work_map);
- bus_dmamem_free(ch->dma->work_tag, ch->dma->work, ch->dma->work_map);
- ch->dma->work_bus = 0;
- ch->dma->work_map = NULL;
- ch->dma->work = NULL;
- }
- if (ch->dma->work_tag) {
- bus_dma_tag_destroy(ch->dma->work_tag);
- ch->dma->work_tag = NULL;
- }
- if (ch->dma->sg_bus) {
- bus_dmamap_unload(ch->dma->sg_tag, ch->dma->sg_map);
- bus_dmamem_free(ch->dma->sg_tag, ch->dma->sg, ch->dma->sg_map);
- ch->dma->sg_bus = 0;
- ch->dma->sg_map = NULL;
- ch->dma->sg = NULL;
- }
- if (ch->dma->data_map) {
- bus_dmamap_destroy(ch->dma->data_tag, ch->dma->data_map);
- ch->dma->data_map = NULL;
- }
- if (ch->dma->sg_tag) {
- bus_dma_tag_destroy(ch->dma->sg_tag);
- ch->dma->sg_tag = NULL;
- }
- if (ch->dma->data_tag) {
- bus_dma_tag_destroy(ch->dma->data_tag);
- ch->dma->data_tag = NULL;
- }
- if (ch->dma->dmatag) {
- bus_dma_tag_destroy(ch->dma->dmatag);
- ch->dma->dmatag = NULL;
+ /* free all dma slots */
+ for (i = 0; i < ATA_DMA_SLOTS; i++) {
+ struct ata_dmaslot *slot = &ch->dma.slot[i];
+
+ if (slot->sg_bus) {
+ bus_dmamap_unload(slot->sg_tag, slot->sg_map);
+ slot->sg_bus = 0;
+ }
+ if (slot->sg_map) {
+ bus_dmamem_free(slot->sg_tag, slot->sg, slot->sg_map);
+ bus_dmamap_destroy(slot->sg_tag, slot->sg_map);
+ slot->sg = NULL;
+ slot->sg_map = NULL;
+ }
+ if (slot->data_map) {
+ bus_dmamap_destroy(slot->data_tag, slot->data_map);
+ slot->data_map = NULL;
+ }
+ if (slot->sg_tag) {
+ bus_dma_tag_destroy(slot->sg_tag);
+ slot->sg_tag = NULL;
+ }
+ if (slot->data_tag) {
+ bus_dma_tag_destroy(slot->data_tag);
+ slot->data_tag = NULL;
+ }
}
}
@@ -218,67 +256,83 @@ ata_dmasetprd(void *xsc, bus_dma_segment
}
static int
-ata_dmaload(device_t dev, caddr_t data, int32_t count, int dir,
- void *addr, int *entries)
+ata_dmaload(struct ata_request *request, void *addr, int *entries)
{
- struct ata_channel *ch = device_get_softc(dev);
- struct ata_dmasetprd_args cba;
+ struct ata_channel *ch = device_get_softc(request->parent);
+ struct ata_device *atadev = device_get_softc(request->dev);
+ struct ata_dmasetprd_args dspa;
int error;
- if (ch->dma->flags & ATA_DMA_LOADED) {
- device_printf(dev, "FAILURE - already active DMA on this device\n");
+ ATA_DEBUG_RQ(request, "dmaload");
+
+ if (request->dma) {
+ device_printf(request->dev,
+ "FAILURE - already active DMA on this device\n");
return EIO;
}
- if (!count) {
- device_printf(dev, "FAILURE - zero length DMA transfer attempted\n");
+ if (!request->bytecount) {
+ device_printf(request->dev,
+ "FAILURE - zero length DMA transfer attempted\n");
return EIO;
}
- if (((uintptr_t)data & (ch->dma->alignment - 1)) ||
- (count & (ch->dma->alignment - 1))) {
- device_printf(dev, "FAILURE - non aligned DMA transfer attempted\n");
+ if (((uintptr_t)(request->data) & (ch->dma.alignment - 1)) ||
+ (request->bytecount & (ch->dma.alignment - 1))) {
+ device_printf(request->dev,
+ "FAILURE - non aligned DMA transfer attempted\n");
return EIO;
}
- if (count > ch->dma->max_iosize) {
- device_printf(dev, "FAILURE - oversized DMA transfer attempt %d > %d\n",
- count, ch->dma->max_iosize);
+ if (request->bytecount > ch->dma.max_iosize) {
+ device_printf(request->dev,
+ "FAILURE - oversized DMA transfer attempt %d > %d\n",
+ request->bytecount, ch->dma.max_iosize);
return EIO;
}
- cba.dmatab = addr;
-
- if ((error = bus_dmamap_load(ch->dma->data_tag, ch->dma->data_map,
- data, count, ch->dma->setprd, &cba,
- BUS_DMA_NOWAIT)) || (error = cba.error))
- return error;
-
- *entries = cba.nsegs;
+ /* set our slot, unit for simplicity XXX SOS NCQ will change that */
+ request->dma = &ch->dma.slot[atadev->unit];
- bus_dmamap_sync(ch->dma->sg_tag, ch->dma->sg_map, BUS_DMASYNC_PREWRITE);
+ if (addr)
+ dspa.dmatab = addr;
+ else
+ dspa.dmatab = request->dma->sg;
+
+ if ((error = bus_dmamap_load(request->dma->data_tag, request->dma->data_map,
+ request->data, request->bytecount,
+ ch->dma.setprd, &dspa, BUS_DMA_NOWAIT)) ||
+ (error = dspa.error)) {
+ device_printf(request->dev, "FAILURE - load data\n");
+ goto error;
+ }
- bus_dmamap_sync(ch->dma->data_tag, ch->dma->data_map,
- dir ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
+ if (entries)
+ *entries = dspa.nsegs;
- ch->dma->cur_iosize = count;
- ch->dma->flags = dir ? (ATA_DMA_LOADED | ATA_DMA_READ) : ATA_DMA_LOADED;
+ bus_dmamap_sync(request->dma->sg_tag, request->dma->sg_map,
+ BUS_DMASYNC_PREWRITE);
+ bus_dmamap_sync(request->dma->data_tag, request->dma->data_map,
+ (request->flags & ATA_R_READ) ?
+ BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
return 0;
+
+error:
+ ata_dmaunload(request);
+ return EIO;
}
int
-ata_dmaunload(device_t dev)
+ata_dmaunload(struct ata_request *request)
{
- struct ata_channel *ch = device_get_softc(dev);
+ ATA_DEBUG_RQ(request, "dmaunload");
- if (ch->dma->flags & ATA_DMA_LOADED) {
- bus_dmamap_sync(ch->dma->sg_tag, ch->dma->sg_map,
+ if (request->dma) {
+ bus_dmamap_sync(request->dma->sg_tag, request->dma->sg_map,
BUS_DMASYNC_POSTWRITE);
-
- bus_dmamap_sync(ch->dma->data_tag, ch->dma->data_map,
- (ch->dma->flags & ATA_DMA_READ) ?
+ bus_dmamap_sync(request->dma->data_tag, request->dma->data_map,
+ (request->flags & ATA_R_READ) ?
BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
- bus_dmamap_unload(ch->dma->data_tag, ch->dma->data_map);
- ch->dma->cur_iosize = 0;
- ch->dma->flags &= ~ATA_DMA_LOADED;
+ bus_dmamap_unload(request->dma->data_tag, request->dma->data_map);
+ request->dma = NULL;
}
return 0;
}
--- src/sys/dev/ata/ata-isa.c 2007-02-21 22:07:18.000000000 +0300
+++ src/sys/dev/ata/ata-isa.c 2008-04-10 17:05:05.000000000 +0400
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
--- src/sys/dev/ata/ata-lowlevel.c 2008-01-09 11:54:48.000000000 +0300
+++ src/sys/dev/ata/ata-lowlevel.c 2008-05-08 21:55:44.000000000 +0400
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -64,16 +64,19 @@ ata_generic_hw(device_t dev)
ch->hw.begin_transaction = ata_begin_transaction;
ch->hw.end_transaction = ata_end_transaction;
ch->hw.status = ata_generic_status;
+ ch->hw.softreset = NULL;
ch->hw.command = ata_generic_command;
ch->hw.tf_read = ata_tf_read;
ch->hw.tf_write = ata_tf_write;
+ ch->hw.pm_read = NULL;
+ ch->hw.pm_write = NULL;
}
/* must be called with ATA channel locked and state_mtx held */
int
ata_begin_transaction(struct ata_request *request)
{
- struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
+ struct ata_channel *ch = device_get_softc(request->parent);
struct ata_device *atadev = device_get_softc(request->dev);
int dummy, error;
@@ -133,9 +136,7 @@ ata_begin_transaction(struct ata_request
/* ATA DMA data transfer commands */
case ATA_R_DMA:
/* check sanity, setup SG list and DMA engine */
- if ((error = ch->dma->load(ch->dev, request->data, request->bytecount,
- request->flags & ATA_R_READ, ch->dma->sg,
- &dummy))) {
+ if ((error = ch->dma.load(request, NULL, &dummy))) {
device_printf(request->dev, "setting up DMA failed\n");
request->result = error;
goto begin_finished;
@@ -150,7 +151,7 @@ ata_begin_transaction(struct ata_request
}
/* start DMA engine */
- if (ch->dma->start && ch->dma->start(request->dev)) {
+ if (ch->dma.start && ch->dma.start(request)) {
device_printf(request->dev, "error starting DMA\n");
request->result = EIO;
goto begin_finished;
@@ -161,7 +162,7 @@ ata_begin_transaction(struct ata_request
case ATA_R_ATAPI:
/* is this just a POLL DSC command ? */
if (request->u.atapi.ccb[0] == ATAPI_POLL_DSC) {
- ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | atadev->unit);
+ ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(atadev->unit));
DELAY(10);
if (!(ATA_IDX_INB(ch, ATA_ALTSTAT) & ATA_S_DSC))
request->result = EBUSY;
@@ -180,7 +181,7 @@ ata_begin_transaction(struct ata_request
case ATA_R_ATAPI|ATA_R_DMA:
/* is this just a POLL DSC command ? */
if (request->u.atapi.ccb[0] == ATAPI_POLL_DSC) {
- ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | atadev->unit);
+ ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(atadev->unit));
DELAY(10);
if (!(ATA_IDX_INB(ch, ATA_ALTSTAT) & ATA_S_DSC))
request->result = EBUSY;
@@ -188,9 +189,7 @@ ata_begin_transaction(struct ata_request
}
/* check sanity, setup SG list and DMA engine */
- if ((error = ch->dma->load(ch->dev, request->data, request->bytecount,
- request->flags & ATA_R_READ, ch->dma->sg,
- &dummy))) {
+ if ((error = ch->dma.load(request, NULL, &dummy))) {
device_printf(request->dev, "setting up DMA failed\n");
request->result = error;
goto begin_finished;
@@ -204,7 +203,7 @@ ata_begin_transaction(struct ata_request
}
/* start DMA engine */
- if (ch->dma->start && ch->dma->start(request->dev)) {
+ if (ch->dma.start && ch->dma.start(request)) {
request->result = EIO;
goto begin_finished;
}
@@ -214,8 +213,9 @@ ata_begin_transaction(struct ata_request
printf("ata_begin_transaction OOPS!!!\n");
begin_finished:
- if (ch->dma && ch->dma->flags & ATA_DMA_LOADED)
- ch->dma->unload(ch->dev);
+ if (ch->dma.unload) {
+ ch->dma.unload(request);
+ }
return ATA_OP_FINISHED;
begin_continue:
@@ -228,7 +228,7 @@ begin_continue:
int
ata_end_transaction(struct ata_request *request)
{
- struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
+ struct ata_channel *ch = device_get_softc(request->parent);
struct ata_device *atadev = device_get_softc(request->dev);
int length;
@@ -314,19 +314,19 @@ ata_end_transaction(struct ata_request *
case ATA_R_DMA:
/* stop DMA engine and get status */
- if (ch->dma->stop)
- request->dmastat = ch->dma->stop(request->dev);
+ if (ch->dma.stop)
+ request->dma->status = ch->dma.stop(request);
/* did we get error or data */
if (request->status & ATA_S_ERROR)
request->error = ATA_IDX_INB(ch, ATA_ERROR);
- else if (request->dmastat & ATA_BMSTAT_ERROR)
+ else if (request->dma->status & ATA_BMSTAT_ERROR)
request->status |= ATA_S_ERROR;
else if (!(request->flags & ATA_R_TIMEOUT))
request->donecount = request->bytecount;
/* release SG list etc */
- ch->dma->unload(ch->dev);
+ ch->dma.unload(request);
/* done with HW */
goto end_finished;
@@ -426,19 +426,19 @@ ata_end_transaction(struct ata_request *
case ATA_R_ATAPI|ATA_R_DMA:
/* stop DMA engine and get status */
- if (ch->dma->stop)
- request->dmastat = ch->dma->stop(request->dev);
+ if (ch->dma.stop)
+ request->dma->status = ch->dma.stop(request);
/* did we get error or data */
if (request->status & (ATA_S_ERROR | ATA_S_DWF))
request->error = ATA_IDX_INB(ch, ATA_ERROR);
- else if (request->dmastat & ATA_BMSTAT_ERROR)
+ else if (request->dma->status & ATA_BMSTAT_ERROR)
request->status |= ATA_S_ERROR;
else if (!(request->flags & ATA_R_TIMEOUT))
request->donecount = request->bytecount;
/* release SG list etc */
- ch->dma->unload(ch->dev);
+ ch->dma.unload(request);
/* done with HW */
goto end_finished;
@@ -465,7 +465,7 @@ ata_generic_reset(device_t dev)
int mask = 0, timeout;
/* do we have any signs of ATA/ATAPI HW being present ? */
- ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | ATA_MASTER);
+ ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | ATA_DEV(ATA_MASTER));
DELAY(10);
ostat0 = ATA_IDX_INB(ch, ATA_STATUS);
if ((ostat0 & 0xf8) != 0xf8 && ostat0 != 0xa5) {
@@ -475,7 +475,7 @@ ata_generic_reset(device_t dev)
/* in some setups we dont want to test for a slave */
if (!(ch->flags & ATA_NO_SLAVE)) {
- ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | ATA_SLAVE);
+ ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | ATA_DEV(ATA_SLAVE));
DELAY(10);
ostat1 = ATA_IDX_INB(ch, ATA_STATUS);
if ((ostat1 & 0xf8) != 0xf8 && ostat1 != 0xa5) {
@@ -495,7 +495,7 @@ ata_generic_reset(device_t dev)
return;
/* reset (both) devices on this channel */
- ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | ATA_MASTER);
+ ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | ATA_DEV(ATA_MASTER));
DELAY(10);
ATA_IDX_OUTB(ch, ATA_CONTROL, ATA_A_IDS | ATA_A_RESET);
ata_udelay(10000);
@@ -506,7 +506,7 @@ ata_generic_reset(device_t dev)
/* wait for BUSY to go inactive */
for (timeout = 0; timeout < 310; timeout++) {
if ((mask & 0x01) && (stat0 & ATA_S_BUSY)) {
- ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_MASTER);
+ ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(ATA_MASTER));
DELAY(10);
err = ATA_IDX_INB(ch, ATA_ERROR);
lsb = ATA_IDX_INB(ch, ATA_CYL_LSB);
@@ -536,7 +536,7 @@ ata_generic_reset(device_t dev)
if ((mask & 0x02) && (stat1 & ATA_S_BUSY) &&
!((mask & 0x01) && (stat0 & ATA_S_BUSY))) {
- ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_SLAVE);
+ ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(ATA_SLAVE));
DELAY(10);
err = ATA_IDX_INB(ch, ATA_ERROR);
lsb = ATA_IDX_INB(ch, ATA_CYL_LSB);
@@ -584,9 +584,8 @@ ata_generic_reset(device_t dev)
}
if (bootverbose)
- device_printf(dev, "reset tp2 stat0=%02x stat1=%02x devices=0x%b\n",
- stat0, stat1, ch->devices,
- "\20\4ATAPI_SLAVE\3ATAPI_MASTER\2ATA_SLAVE\1ATA_MASTER");
+ device_printf(dev, "reset tp2 stat0=%02x stat1=%02x devices=0x%x\n",
+ stat0, stat1, ch->devices);
}
/* must be called with ATA channel locked and state_mtx held */
@@ -617,7 +616,7 @@ ata_wait(struct ata_channel *ch, struct
/* if drive fails status, reselect the drive and try again */
if (status == 0xff) {
- ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | atadev->unit);
+ ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(atadev->unit));
timeout += 1000;
DELAY(1000);
continue;
@@ -657,11 +656,11 @@ ata_wait(struct ata_channel *ch, struct
int
ata_generic_command(struct ata_request *request)
{
- struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
+ struct ata_channel *ch = device_get_softc(request->parent);
struct ata_device *atadev = device_get_softc(request->dev);
/* select device */
- ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | atadev->unit);
+ ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | ATA_DEV(atadev->unit));
/* ready to issue command ? */
if (ata_wait(ch, atadev, 0) < 0) {
@@ -728,7 +727,7 @@ ata_generic_command(struct ata_request *
static void
ata_tf_read(struct ata_request *request)
{
- struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
+ struct ata_channel *ch = device_get_softc(request->parent);
struct ata_device *atadev = device_get_softc(request->dev);
if (atadev->flags & ATA_D_48BIT_ACTIVE) {
@@ -758,7 +757,7 @@ ata_tf_read(struct ata_request *request)
static void
ata_tf_write(struct ata_request *request)
{
- struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
+ struct ata_channel *ch = device_get_softc(request->parent);
struct ata_device *atadev = device_get_softc(request->dev);
if (atadev->flags & ATA_D_48BIT_ACTIVE) {
@@ -772,7 +771,7 @@ ata_tf_write(struct ata_request *request
ATA_IDX_OUTB(ch, ATA_CYL_LSB, request->u.ata.lba >> 8);
ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 40);
ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 16);
- ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_LBA | atadev->unit);
+ ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_LBA | ATA_DEV(atadev->unit));
}
else {
ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature);
@@ -794,7 +793,7 @@ ata_tf_write(struct ata_request *request
(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 |
+ ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(atadev->unit) |
(((request->u.ata.lba% (sectors * heads)) /
sectors) & 0xf));
}
@@ -803,7 +802,7 @@ ata_tf_write(struct ata_request *request
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 |
+ ATA_D_IBM | ATA_D_LBA | ATA_DEV(atadev->unit) |
((request->u.ata.lba >> 24) & 0x0f));
}
}
@@ -812,7 +811,7 @@ ata_tf_write(struct ata_request *request
static void
ata_pio_read(struct ata_request *request, int length)
{
- struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
+ struct ata_channel *ch = device_get_softc(request->parent);
int size = min(request->transfersize, length);
int resid;
@@ -837,7 +836,7 @@ ata_pio_read(struct ata_request *request
static void
ata_pio_write(struct ata_request *request, int length)
{
- struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
+ struct ata_channel *ch = device_get_softc(request->parent);
int size = min(request->transfersize, length);
int resid;
--- src/sys/dev/ata/ata-pci.c 2007-11-22 00:15:00.000000000 +0300
+++ src/sys/dev/ata/ata-pci.c 2008-09-18 16:12:34.000000000 +0400
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -96,6 +96,10 @@ ata_pci_probe(device_t dev)
if (!ata_amd_ident(dev))
return ATA_PROBE_OK;
break;
+ case ATA_ADAPTEC_ID:
+ if (!ata_adaptec_ident(dev))
+ return ATA_PROBE_OK;
+ break;
case ATA_ATI_ID:
if (!ata_ati_ident(dev))
return ATA_PROBE_OK;
@@ -258,6 +262,31 @@ ata_pci_detach(device_t dev)
return 0;
}
+int
+ata_pci_suspend(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+ int error = 0;
+
+ bus_generic_suspend(dev);
+ if (ctlr->suspend)
+ error = ctlr->suspend(dev);
+ return error;
+}
+
+int
+ata_pci_resume(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+ int error = 0;
+
+ if (ctlr->resume)
+ error = ctlr->resume(dev);
+ bus_generic_resume(dev);
+ return error;
+}
+
+
struct resource *
ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags)
@@ -422,23 +451,14 @@ ata_pci_allocate(device_t dev)
return 0;
}
-void
-ata_pci_hw(device_t dev)
-{
- struct ata_channel *ch = device_get_softc(dev);
-
- ata_generic_hw(dev);
- ch->hw.status = ata_pci_status;
-}
-
int
ata_pci_status(device_t dev)
{
struct ata_channel *ch = device_get_softc(dev);
if ((dumping || !ata_legacy(device_get_parent(dev))) &&
- ch->dma && ((ch->flags & ATA_ALWAYS_DMASTAT) ||
- (ch->dma->flags & ATA_DMA_ACTIVE))) {
+ ((ch->flags & ATA_ALWAYS_DMASTAT) ||
+ (ch->dma.flags & ATA_DMA_ACTIVE))) {
int bmstat = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
if ((bmstat & (ATA_BMSTAT_ACTIVE | ATA_BMSTAT_INTERRUPT)) !=
@@ -455,31 +475,44 @@ ata_pci_status(device_t dev)
return 1;
}
+void
+ata_pci_hw(device_t dev)
+{
+ struct ata_channel *ch = device_get_softc(dev);
+
+ ata_generic_hw(dev);
+ ch->hw.status = ata_pci_status;
+}
+
static int
-ata_pci_dmastart(device_t dev)
+ata_pci_dmastart(struct ata_request *request)
{
- struct ata_channel *ch = device_get_softc(device_get_parent(dev));
+ struct ata_channel *ch = device_get_softc(request->parent);
+
+ ATA_DEBUG_RQ(request, "dmastart");
ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, (ATA_IDX_INB(ch, ATA_BMSTAT_PORT) |
(ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR)));
- ATA_IDX_OUTL(ch, ATA_BMDTP_PORT, ch->dma->sg_bus);
- ch->dma->flags |= ATA_DMA_ACTIVE;
+ ATA_IDX_OUTL(ch, ATA_BMDTP_PORT, request->dma->sg_bus);
+ ch->dma.flags |= ATA_DMA_ACTIVE;
ATA_IDX_OUTB(ch, ATA_BMCMD_PORT,
(ATA_IDX_INB(ch, ATA_BMCMD_PORT) & ~ATA_BMCMD_WRITE_READ) |
- ((ch->dma->flags & ATA_DMA_READ) ? ATA_BMCMD_WRITE_READ : 0) |
+ ((request->flags & ATA_R_READ) ? ATA_BMCMD_WRITE_READ : 0)|
ATA_BMCMD_START_STOP);
return 0;
}
static int
-ata_pci_dmastop(device_t dev)
+ata_pci_dmastop(struct ata_request *request)
{
- struct ata_channel *ch = device_get_softc(device_get_parent(dev));
+ struct ata_channel *ch = device_get_softc(request->parent);
int error;
+ ATA_DEBUG_RQ(request, "dmastop");
+
ATA_IDX_OUTB(ch, ATA_BMCMD_PORT,
ATA_IDX_INB(ch, ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP);
- ch->dma->flags &= ~ATA_DMA_ACTIVE;
+ ch->dma.flags &= ~ATA_DMA_ACTIVE;
error = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR);
return error;
@@ -489,12 +522,16 @@ static void
ata_pci_dmareset(device_t dev)
{
struct ata_channel *ch = device_get_softc(dev);
+ struct ata_request *request;
ATA_IDX_OUTB(ch, ATA_BMCMD_PORT,
ATA_IDX_INB(ch, ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP);
- ch->dma->flags &= ~ATA_DMA_ACTIVE;
+ ch->dma.flags &= ~ATA_DMA_ACTIVE;
ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR);
- ch->dma->unload(dev);
+ if ((request = ch->running)) {
+ device_printf(request->dev, "DMA reset calling unload\n");
+ ch->dma.unload(request);
+ }
}
void
@@ -503,11 +540,9 @@ ata_pci_dmainit(device_t dev)
struct ata_channel *ch = device_get_softc(dev);
ata_dmainit(dev);
- if (ch->dma) {
- ch->dma->start = ata_pci_dmastart;
- ch->dma->stop = ata_pci_dmastop;
- ch->dma->reset = ata_pci_dmareset;
- }
+ ch->dma.start = ata_pci_dmastart;
+ ch->dma.stop = ata_pci_dmastop;
+ ch->dma.reset = ata_pci_dmareset;
}
char *
@@ -517,6 +552,7 @@ ata_pcivendor2str(device_t dev)
case ATA_ACARD_ID: return "Acard";
case ATA_ACER_LABS_ID: return "AcerLabs";
case ATA_AMD_ID: return "AMD";
+ case ATA_ADAPTEC_ID: return "Adaptec";
case ATA_ATI_ID: return "ATI";
case ATA_CYRIX_ID: return "Cyrix";
case ATA_CYPRESS_ID: return "Cypress";
@@ -544,9 +580,9 @@ static device_method_t ata_pci_methods[]
DEVMETHOD(device_probe, ata_pci_probe),
DEVMETHOD(device_attach, ata_pci_attach),
DEVMETHOD(device_detach, ata_pci_detach),
+ DEVMETHOD(device_suspend, ata_pci_suspend),
+ DEVMETHOD(device_resume, ata_pci_resume),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
- DEVMETHOD(device_suspend, bus_generic_suspend),
- DEVMETHOD(device_resume, bus_generic_resume),
/* bus methods */
DEVMETHOD(bus_alloc_resource, ata_pci_alloc_resource),
@@ -600,19 +636,13 @@ static int
ata_pcichannel_attach(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
- struct ata_channel *ch = device_get_softc(dev);
int error;
if (ctlr->dmainit)
ctlr->dmainit(dev);
- if (ch->dma)
- ch->dma->alloc(dev);
- if ((error = ctlr->allocate(dev))) {
- if (ch->dma)
- ch->dma->free(dev);
+ if ((error = ctlr->allocate(dev)))
return error;
- }
return ata_attach(dev);
}
@@ -626,8 +656,7 @@ ata_pcichannel_detach(device_t dev)
if ((error = ata_detach(dev)))
return error;
- if (ch->dma)
- ch->dma->free(dev);
+ ch->dma.free(dev);
/* XXX SOS free resources for io and ctlio ?? */
@@ -653,11 +682,8 @@ ata_pcichannel_reset(device_t dev)
struct ata_channel *ch = device_get_softc(dev);
/* if DMA engine present reset it */
- if (ch->dma) {
- if (ch->dma->reset)
- ch->dma->reset(dev);
- ch->dma->unload(dev);
- }
+ if (ch->dma.reset)
+ ch->dma.reset(dev);
/* reset the controller HW */
if (ctlr->reset)
--- src/sys/dev/ata/ata-pci.h 2008-09-13 11:36:16.000000000 +0400
+++ src/sys/dev/ata/ata-pci.h 2008-09-26 11:29:48.000000000 +0400
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2003 - 2007 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 2003 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -50,6 +50,8 @@ struct ata_pci_controller {
struct ata_chip_id *chip;
int channels;
int (*chipinit)(device_t);
+ int (*suspend)(device_t);
+ int (*resume)(device_t);
int (*allocate)(device_t);
int (*locking)(device_t, int);
void (*reset)(device_t);
@@ -80,6 +82,14 @@ struct ata_connect_task {
#define ATA_ATP865A 0x00081191
#define ATA_ATP865R 0x00091191
+#define ATA_ACER_LABS_ID 0x10b9
+#define ATA_ALI_1533 0x153310b9
+#define ATA_ALI_5229 0x522910b9
+#define ATA_ALI_5281 0x528110b9
+#define ATA_ALI_5287 0x528710b9
+#define ATA_ALI_5288 0x528810b9
+#define ATA_ALI_5289 0x528910b9
+
#define ATA_AMD_ID 0x1022
#define ATA_AMD755 0x74011022
#define ATA_AMD756 0x74091022
@@ -88,13 +98,8 @@ struct ata_connect_task {
#define ATA_AMD8111 0x74691022
#define ATA_AMD5536 0x209a1022
-#define ATA_ACER_LABS_ID 0x10b9
-#define ATA_ALI_1533 0x153310b9
-#define ATA_ALI_5229 0x522910b9
-#define ATA_ALI_5281 0x528110b9
-#define ATA_ALI_5287 0x528710b9
-#define ATA_ALI_5288 0x528810b9
-#define ATA_ALI_5289 0x528910b9
+#define ATA_ADAPTEC_ID 0x9005
+#define ATA_ADAPTEC_1420 0x02419005
#define ATA_ATI_ID 0x1002
#define ATA_ATI_IXP200 0x43491002
@@ -185,6 +190,7 @@ struct ata_connect_task {
#define ATA_ITE_ID 0x1283
#define ATA_IT8211F 0x82111283
#define ATA_IT8212F 0x82121283
+#define ATA_IT8213F 0x82131283
#define ATA_JMICRON_ID 0x197b
#define ATA_JMB360 0x2360197b
@@ -458,13 +464,15 @@ struct ata_connect_task {
int ata_pci_probe(device_t dev);
int ata_pci_attach(device_t dev);
int ata_pci_detach(device_t dev);
+int ata_pci_suspend(device_t dev);
+int ata_pci_resume(device_t dev);
struct resource * ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags);
int ata_pci_release_resource(device_t dev, device_t child, int type, int rid, struct resource *r);
int ata_pci_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 ata_pci_teardown_intr(device_t dev, device_t child, struct resource *irq, void *cookie);
int ata_pci_allocate(device_t dev);
-void ata_pci_hw(device_t dev);
int ata_pci_status(device_t dev);
+void ata_pci_hw(device_t dev);
void ata_pci_dmainit(device_t dev);
char *ata_pcivendor2str(device_t dev);
@@ -475,6 +483,7 @@ int ata_ahci_ident(device_t);
int ata_acard_ident(device_t);
int ata_ali_ident(device_t);
int ata_amd_ident(device_t);
+int ata_adaptec_ident(device_t);
int ata_ati_ident(device_t);
int ata_cyrix_ident(device_t);
int ata_cypress_ident(device_t);
--- src/sys/dev/ata/ata-queue.c 2007-03-13 23:31:56.000000000 +0300
+++ src/sys/dev/ata/ata-queue.c 2008-04-21 14:35:19.000000000 +0400
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -56,7 +56,7 @@ ata_queue_request(struct ata_request *re
/* treat request as virgin (this might be an ATA_R_REQUEUE) */
request->result = request->status = request->error = 0;
- /* check that that the device is still valid */
+ /* check that the device is still valid */
if (!(request->parent = device_get_parent(request->dev))) {
request->result = ENXIO;
if (request->callback)
@@ -358,8 +358,8 @@ ata_completed(void *context, int dummy)
"\4MEDIA_CHANGE_REQEST"
"\3ABORTED\2NO_MEDIA\1ILLEGAL_LENGTH");
if ((request->flags & ATA_R_DMA) &&
- (request->dmastat & ATA_BMSTAT_ERROR))
- printf(" dma=0x%02x", request->dmastat);
+ (request->dma->status & ATA_BMSTAT_ERROR))
+ printf(" dma=0x%02x", request->dma->status);
if (!(request->flags & (ATA_R_ATAPI | ATA_R_CONTROL)))
printf(" LBA=%ju", request->u.ata.lba);
printf("\n");
@@ -503,6 +503,7 @@ ata_timeout(struct ata_request *request)
request->flags |= ATA_R_TIMEOUT;
mtx_unlock(&ch->state_mtx);
ATA_LOCKING(ch->dev, ATA_LF_UNLOCK);
+ ch->dma.unload(request);
ata_finish(request);
}
else {
@@ -694,11 +695,13 @@ ata_cmd2str(struct ata_request *request)
case 0x24: return ("READ48");
case 0x25: return ("READ_DMA48");
case 0x26: return ("READ_DMA_QUEUED48");
+ case 0x27: return ("READ_NATIVE_MAX_ADDRESS48");
case 0x29: return ("READ_MUL48");
case 0x30: return ("WRITE");
case 0x34: return ("WRITE48");
case 0x35: return ("WRITE_DMA48");
case 0x36: return ("WRITE_DMA_QUEUED48");
+ case 0x37: return ("SET_MAX_ADDRESS48");
case 0x39: return ("WRITE_MUL48");
case 0x70: return ("SEEK");
case 0xa0: return ("PACKET_CMD");
@@ -727,6 +730,9 @@ ata_cmd2str(struct ata_request *request)
}
sprintf(buffer, "SETFEATURES 0x%02x", request->u.ata.feature);
return buffer;
+ case 0xf5: return ("SECURITY_FREE_LOCK");
+ case 0xf8: return ("READ_NATIVE_MAX_ADDRESS");
+ case 0xf9: return ("SET_MAX_ADDRESS");
}
}
sprintf(buffer, "unknown CMD (0x%02x)", request->u.ata.command);
--- src/sys/dev/ata/ata-raid.c 2007-08-13 22:46:31.000000000 +0400
+++ src/sys/dev/ata/ata-raid.c 2008-04-17 16:29:35.000000000 +0400
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2000 - 2007 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 2000 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -83,7 +83,7 @@ static int ata_raid_sis_read_meta(device
static int ata_raid_sis_write_meta(struct ar_softc *rdp);
static int ata_raid_via_read_meta(device_t dev, struct ar_softc **raidp);
static int ata_raid_via_write_meta(struct ar_softc *rdp);
-static struct ata_request *ata_raid_init_request(struct ar_softc *rdp, struct bio *bio);
+static struct ata_request *ata_raid_init_request(device_t dev, struct ar_softc *rdp, struct bio *bio);
static int ata_raid_send_request(struct ata_request *request);
static int ata_raid_rw(device_t dev, u_int64_t lba, void *data, u_int bcount, int flags);
static char * ata_raid_format(struct ar_softc *rdp);
@@ -263,7 +263,7 @@ ata_raid_flush(struct bio *bp)
for (disk = 0; disk < rdp->total_disks; disk++) {
if ((dev = rdp->disks[disk].dev) == NULL)
continue;
- if (!(request = ata_raid_init_request(rdp, bp)))
+ if (!(request = ata_raid_init_request(dev, rdp, bp)))
return ENOMEM;
request->dev = dev;
request->u.ata.command = ATA_FLUSHCACHE;
@@ -353,7 +353,7 @@ ata_raid_strategy(struct bio *bp)
if (!(drv == 0 && rdp->format == AR_F_HPTV2_RAID))
lba += rdp->offset_sectors;
- if (!(request = ata_raid_init_request(rdp, bp))) {
+ if (!(request = ata_raid_init_request(rdp->disks[drv].dev, rdp, bp))) {
biofinish(bp, NULL, EIO);
return;
}
@@ -375,7 +375,7 @@ ata_raid_strategy(struct bio *bp)
return;
}
request->this = drv;
- request->dev = rdp->disks[request->this].dev;
+ request->dev = rdp->disks[drv].dev;
ata_raid_send_request(request);
break;
@@ -457,12 +457,14 @@ ata_raid_strategy(struct bio *bp)
/* do we have a spare to rebuild on ? */
if (rdp->disks[this].flags & AR_DF_SPARE) {
if ((composite = ata_alloc_composite())) {
- if ((rebuild = ata_alloc_request())) {
+ if ((rebuild = ata_raid_init_request(
+ rdp->disks[this].dev, rdp, bp))) {
rdp->rebuild_lba = blk + chunk;
- bcopy(request, rebuild,
- sizeof(struct ata_request));
+ rebuild->data = request->data;
+ rebuild->bytecount = request->bytecount;
+ rebuild->u.ata.lba = request->u.ata.lba;
+ rebuild->u.ata.count = request->u.ata.count;
rebuild->this = this;
- rebuild->dev = rdp->disks[this].dev;
rebuild->flags &= ~ATA_R_READ;
rebuild->flags |= ATA_R_WRITE;
mtx_init(&composite->lock,
@@ -518,14 +520,16 @@ ata_raid_strategy(struct bio *bp)
int this = drv + rdp->width;
if ((composite = ata_alloc_composite())) {
- if ((mirror = ata_alloc_request())) {
+ if ((mirror = ata_raid_init_request(
+ rdp->disks[this].dev, rdp, bp))) {
if ((blk <= rdp->rebuild_lba) &&
((blk + chunk) > rdp->rebuild_lba))
rdp->rebuild_lba = blk + chunk;
- bcopy(request, mirror,
- sizeof(struct ata_request));
+ mirror->data = request->data;
+ mirror->bytecount = request->bytecount;
+ mirror->u.ata.lba = request->u.ata.lba;
+ mirror->u.ata.count = request->u.ata.count;
mirror->this = this;
- mirror->dev = rdp->disks[this].dev;
mtx_init(&composite->lock,
"ATA PseudoRAID mirror lock",
NULL, MTX_DEF);
@@ -856,6 +860,7 @@ ata_raid_config_changed(struct ar_softc
int disk, count, status;
mtx_lock(&rdp->lock);
+
/* set default all working mode */
status = rdp->status;
rdp->status &= ~AR_S_DEGRADED;
@@ -910,6 +915,11 @@ ata_raid_config_changed(struct ar_softc
}
if (rdp->status != status) {
+
+ /* raid status has changed, update metadata */
+ writeback = 1;
+
+ /* announce we have trouble ahead */
if (!(rdp->status & AR_S_READY)) {
printf("ar%d: FAILURE - %s array broken\n",
rdp->lun, ata_raid_type(rdp));
@@ -1659,9 +1669,8 @@ ata_raid_adaptec_read_meta(device_t dev,
if (be32toh(meta->generation) >= raid->generation) {
struct ata_device *atadev = device_get_softc(parent);
struct ata_channel *ch = device_get_softc(GRANDPARENT(dev));
- int disk_number = (ch->unit << !(ch->flags & ATA_NO_SLAVE)) +
- ATA_DEV(atadev->unit);
-
+ int disk_number =
+ (ch->unit << !(ch->flags & ATA_NO_SLAVE)) + atadev->unit;
raid->disks[disk_number].dev = parent;
raid->disks[disk_number].sectors =
be32toh(meta->configs[disk_number + 1].sectors);
@@ -2272,11 +2281,14 @@ ata_raid_intel_write_meta(struct ar_soft
}
rdp->generation++;
- microtime(×tamp);
+ if (!rdp->magic_0) {
+ microtime(×tamp);
+ rdp->magic_0 = timestamp.tv_sec ^ timestamp.tv_usec;
+ }
bcopy(INTEL_MAGIC, meta->intel_id, sizeof(meta->intel_id));
bcopy(INTEL_VERSION_1100, meta->version, sizeof(meta->version));
- meta->config_id = timestamp.tv_sec;
+ meta->config_id = rdp->magic_0;
meta->generation = rdp->generation;
meta->total_disks = rdp->total_disks;
meta->total_volumes = 1; /* XXX SOS */
@@ -2290,7 +2302,7 @@ ata_raid_intel_write_meta(struct ar_soft
bcopy(atadev->param.serial, meta->disk[disk].serial,
sizeof(rdp->disks[disk].serial));
meta->disk[disk].sectors = rdp->disks[disk].sectors;
- meta->disk[disk].id = (ch->unit << 16) | ATA_DEV(atadev->unit);
+ meta->disk[disk].id = (ch->unit << 16) | atadev->unit;
}
else
meta->disk[disk].sectors = rdp->total_sectors / rdp->width;
@@ -3315,7 +3327,7 @@ ata_raid_promise_write_meta(struct ar_so
device_get_softc(device_get_parent(rdp->disks[disk].dev));
meta->raid.channel = ch->unit;
- meta->raid.device = ATA_DEV(atadev->unit);
+ meta->raid.device = atadev->unit;
meta->raid.disk_sectors = rdp->disks[disk].sectors;
meta->raid.disk_offset = rdp->offset_sectors;
}
@@ -3403,7 +3415,7 @@ ata_raid_promise_write_meta(struct ar_so
device_get_softc(rdp->disks[drive].dev);
meta->raid.disk[drive].channel = ch->unit;
- meta->raid.disk[drive].device = ATA_DEV(atadev->unit);
+ meta->raid.disk[drive].device = atadev->unit;
}
meta->raid.disk[drive].magic_0 =
PR_MAGIC0(meta->raid.disk[drive]) | timestamp.tv_sec;
@@ -3729,7 +3741,7 @@ ata_raid_sis_write_meta(struct ar_softc
struct ata_channel *ch =
device_get_softc(device_get_parent(rdp->disks[disk].dev));
struct ata_device *atadev = device_get_softc(rdp->disks[disk].dev);
- int disk_number = 1 + ATA_DEV(atadev->unit) + (ch->unit << 1);
+ int disk_number = 1 + atadev->unit + (ch->unit << 1);
meta->disks |= disk_number << ((1 - disk) << 2);
}
@@ -3767,7 +3779,7 @@ ata_raid_sis_write_meta(struct ar_softc
bcopy(atadev->param.model, meta->model, sizeof(meta->model));
/* XXX SOS if total_disks > 2 this may not float */
- meta->disk_number = 1 + ATA_DEV(atadev->unit) + (ch->unit << 1);
+ meta->disk_number = 1 + atadev->unit + (ch->unit << 1);
if (testing || bootverbose)
ata_raid_sis_print_meta(meta);
@@ -4011,7 +4023,7 @@ ata_raid_via_write_meta(struct ar_softc
}
static struct ata_request *
-ata_raid_init_request(struct ar_softc *rdp, struct bio *bio)
+ata_raid_init_request(device_t dev, struct ar_softc *rdp, struct bio *bio)
{
struct ata_request *request;
@@ -4019,6 +4031,7 @@ ata_raid_init_request(struct ar_softc *r
printf("FAILURE - out of memory in ata_raid_init_request\n");
return NULL;
}
+ request->dev = dev;
request->timeout = 5;
request->retries = 2;
request->callback = ata_raid_done;
--- src/sys/dev/ata/ata-raid.h 2007-02-21 22:07:18.000000000 +0300
+++ src/sys/dev/ata/ata-raid.h 2008-04-10 17:05:05.000000000 +0400
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2000 - 2007 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 2000 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
--- src/sys/dev/ata/ata-usb.c 2007-06-24 01:52:05.000000000 +0400
+++ src/sys/dev/ata/ata-usb.c 2008-04-10 17:05:05.000000000 +0400
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2006 - 2007 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 2006 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,7 +36,6 @@ __FBSDID("$FreeBSD: src/sys/dev/ata/ata-
#include <sys/ata.h>
#include <sys/bus.h>
#include <sys/endian.h>
-#include <sys/sysctl.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/sema.h>
--- src/sys/dev/ata/ata_if.m 2007-04-06 20:18:59.000000000 +0400
+++ src/sys/dev/ata/ata_if.m 2008-04-10 17:05:05.000000000 +0400
@@ -1,4 +1,4 @@
-# Copyright (c) 2004 - 2007 Søren Schmidt <sos@FreeBSD.org>
+# Copyright (c) 2004 - 2008 Søren Schmidt <sos@FreeBSD.org>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
--- src/sys/dev/ata/atapi-cd.c 2007-11-22 00:15:00.000000000 +0300
+++ src/sys/dev/ata/atapi-cd.c 2008-05-08 21:55:44.000000000 +0400
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -696,7 +696,6 @@ acd_geom_access(struct g_provider *pp, i
/* wait if drive is not finished loading the medium */
while (timeout--) {
- bzero(request, sizeof(struct ata_request));
request->dev = dev;
bcopy(ccb, request->u.atapi.ccb, 16);
request->flags = ATA_R_ATAPI;
@@ -907,11 +906,11 @@ acd_set_ioparm(device_t dev)
{
struct ata_channel *ch = device_get_softc(device_get_parent(dev));
struct acd_softc *cdp = device_get_ivars(dev);
+ uint32_t max_iosize;
- if (ch->dma)
- cdp->iomax = min(ch->dma->max_iosize, 65534);
- else
- cdp->iomax = min(DFLTPHYS, 65534);
+ max_iosize = ch->dma.max_iosize ? ch->dma.max_iosize : DFLTPHYS;
+
+ cdp->iomax = min(max_iosize, 65534);
}
static void
@@ -1706,8 +1705,7 @@ acd_describe(device_t dev)
(cdp->cap.media & MST_WRITE_CDRW) ? "CDRW" :
(cdp->cap.media & MST_WRITE_CDR) ? "CDR" :
(cdp->cap.media & MST_READ_DVDROM) ? "DVDROM":"CDROM",
- device_get_unit(ch->dev),
- (atadev->unit == ATA_MASTER) ? "master" : "slave");
+ device_get_unit(ch->dev), ata_unit2str(atadev));
device_printf(dev, "%s", "");
if (cdp->cap.cur_read_speed) {
@@ -1879,8 +1877,7 @@ acd_describe(device_t dev)
printf("with %d CD changer ", cdp->changer_info->slots);
printf("<%.40s/%.8s> at ata%d-%s %s\n",
atadev->param.model, atadev->param.revision,
- device_get_unit(ch->dev),
- (atadev->unit == ATA_MASTER) ? "master" : "slave",
+ device_get_unit(ch->dev), ata_unit2str(atadev),
ata_mode2str(atadev->mode) );
}
}
--- src/sys/dev/ata/atapi-cd.h 2007-10-31 22:59:53.000000000 +0300
+++ src/sys/dev/ata/atapi-cd.h 2008-04-10 17:05:05.000000000 +0400
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
--- src/sys/dev/ata/atapi-fd.c 2007-11-22 00:15:00.000000000 +0300
+++ src/sys/dev/ata/atapi-fd.c 2008-05-08 21:55:44.000000000 +0400
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -105,10 +105,7 @@ afd_attach(device_t dev)
fdp->disk->d_ioctl = afd_ioctl;
fdp->disk->d_name = "afd";
fdp->disk->d_drv1 = dev;
- if (ch->dma)
- fdp->disk->d_maxsize = ch->dma->max_iosize;
- else
- fdp->disk->d_maxsize = DFLTPHYS;
+ fdp->disk->d_maxsize = ch->dma.max_iosize ? ch->dma.max_iosize : DFLTPHYS;
fdp->disk->d_unit = device_get_unit(dev);
disk_create(fdp->disk, DISK_VERSION);
return 0;
@@ -406,8 +403,7 @@ afd_describe(device_t dev)
device_printf(dev, "%s <%.40s %.8s> at ata%d-%s %s\n",
sizestring, atadev->param.model, atadev->param.revision,
- device_get_unit(ch->dev),
- (atadev->unit == ATA_MASTER) ? "master" : "slave",
+ device_get_unit(ch->dev), ata_unit2str(atadev),
ata_mode2str(atadev->mode));
if (bootverbose) {
device_printf(dev, "%ju sectors [%juC/%dH/%dS]\n",
--- src/sys/dev/ata/atapi-fd.h 2007-02-21 22:07:19.000000000 +0300
+++ src/sys/dev/ata/atapi-fd.h 2008-04-10 17:05:05.000000000 +0400
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
--- src/sys/dev/ata/atapi-tape.c 2007-11-22 00:15:00.000000000 +0300
+++ src/sys/dev/ata/atapi-tape.c 2008-09-27 12:51:18.000000000 +0400
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -142,19 +142,13 @@ ast_attach(device_t dev)
UID_ROOT, GID_OPERATOR, 0640, "ast%d",
device_get_unit(dev));
device->si_drv1 = dev;
- if (ch->dma)
- device->si_iosize_max = ch->dma->max_iosize;
- else
- device->si_iosize_max = DFLTPHYS;
+ device->si_iosize_max = ch->dma.max_iosize ? ch->dma.max_iosize : DFLTPHYS;
stp->dev1 = device;
device = make_dev(&ast_cdevsw, 2 * device_get_unit(dev) + 1,
UID_ROOT, GID_OPERATOR, 0640, "nast%d",
device_get_unit(dev));
device->si_drv1 = dev;
- if (ch->dma)
- device->si_iosize_max = ch->dma->max_iosize;
- else
- device->si_iosize_max = DFLTPHYS;
+ device->si_iosize_max = ch->dma.max_iosize;
stp->dev2 = device;
/* announce we are here and ready */
@@ -244,7 +238,7 @@ ast_close(struct cdev *cdev, int flags,
ast_write_filemark(dev, ATAPI_WF_WRITE);
/* if minor is even rewind on close */
- if (!(minor(cdev) & 0x01))
+ if (!(dev2unit(cdev) & 0x01))
ast_rewind(dev);
if (stp->cap.lock && count_dev(cdev) == 1)
@@ -678,8 +672,7 @@ ast_describe(device_t dev)
if (bootverbose) {
device_printf(dev, "<%.40s/%.8s> tape drive at ata%d as %s\n",
atadev->param.model, atadev->param.revision,
- device_get_unit(ch->dev),
- (atadev->unit == ATA_MASTER) ? "master" : "slave");
+ device_get_unit(ch->dev), ata_unit2str(atadev));
device_printf(dev, "%dKB/s, ", stp->cap.max_speed);
printf("transfer limit %d blk%s, ",
stp->cap.ctl, (stp->cap.ctl > 1) ? "s" : "");
@@ -717,8 +710,7 @@ ast_describe(device_t dev)
else {
device_printf(dev, "TAPE <%.40s/%.8s> at ata%d-%s %s\n",
atadev->param.model, atadev->param.revision,
- device_get_unit(ch->dev),
- (atadev->unit == ATA_MASTER) ? "master" : "slave",
+ device_get_unit(ch->dev), ata_unit2str(atadev),
ata_mode2str(atadev->mode));
}
}
--- src/sys/dev/ata/atapi-tape.h 2007-02-21 22:07:19.000000000 +0300
+++ src/sys/dev/ata/atapi-tape.h 2008-04-10 17:05:05.000000000 +0400
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
--- src/sys/sys/ata.h 2008-04-08 10:48:21.000000000 +0000
+++ src/sys/sys/ata.h 2008-04-10 13:01:17.000000000 +0000
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2000 - 2006 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 2000 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -239,7 +239,7 @@ struct ata_params {
#define ATA_READ48 0x24 /* read 48bit LBA */
#define ATA_READ_DMA48 0x25 /* read DMA 48bit LBA */
#define ATA_READ_DMA_QUEUED48 0x26 /* read DMA QUEUED 48bit LBA */
-#define ATA_READ_NATIVE_MAX_ADDDRESS48 0x27 /* read native max addr 48bit */
+#define ATA_READ_NATIVE_MAX_ADDRESS48 0x27 /* read native max addr 48bit */
#define ATA_READ_MUL48 0x29 /* read multi 48bit LBA */
#define ATA_WRITE 0x30 /* write */
#define ATA_WRITE48 0x34 /* write 48bit LBA */
@@ -267,8 +267,10 @@ struct ata_params {
#define ATA_STANDBY_CMD 0xe2 /* standby */
#define ATA_IDLE_CMD 0xe3 /* idle */
#define ATA_READ_BUFFER 0xe4 /* read buffer */
+#define ATA_READ_PM 0xe4 /* read portmultiplier */
#define ATA_SLEEP 0xe6 /* sleep */
#define ATA_FLUSHCACHE 0xe7 /* flush cache to disk */
+#define ATA_WRITE_PM 0xe8 /* write portmultiplier */
#define ATA_FLUSHCACHE48 0xea /* flush cache to disk */
#define ATA_ATA_IDENTIFY 0xec /* get ATA params */
#define ATA_SETFEATURES 0xef /* features command */
@@ -282,7 +284,7 @@ struct ata_params {
#define ATA_SF_ENAB_SRVIRQ 0x5e /* enable service interrupt */
#define ATA_SF_DIS_SRVIRQ 0xde /* disable service interrupt */
#define ATA_SECURITY_FREEE_LOCK 0xf5 /* freeze security config */
-#define ATA_READ_NATIVE_MAX_ADDDRESS 0xf8 /* read native max address */
+#define ATA_READ_NATIVE_MAX_ADDRESS 0xf8 /* read native max address */
#define ATA_SET_MAX_ADDRESS 0xf9 /* set max address */
help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?676151223134689>
