summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsos <sos@FreeBSD.org>2008-04-10 13:05:05 +0000
committersos <sos@FreeBSD.org>2008-04-10 13:05:05 +0000
commit34ad2308146bd2683968373b3f427e50e7dbe7c6 (patch)
treef3e7a479de8c6c0f0f0f4fe2f5fd2f056d3b80be
parent8f080cfa2b4b4a38cdc320c3d842360c2a61f1c3 (diff)
downloadFreeBSD-src-34ad2308146bd2683968373b3f427e50e7dbe7c6.zip
FreeBSD-src-34ad2308146bd2683968373b3f427e50e7dbe7c6.tar.gz
Add experimental support for SATA Port Multipliers
Support is working on the Silicon Image SiI3124/3132. Support is working on some AHCI chips but far from all. Remember this is WIP, so test reports and (constructive) suggestions are welcome!
-rw-r--r--sys/dev/ata/ata-all.c130
-rw-r--r--sys/dev/ata/ata-all.h67
-rw-r--r--sys/dev/ata/ata-card.c2
-rw-r--r--sys/dev/ata/ata-cbus.c2
-rw-r--r--sys/dev/ata/ata-chipset.c1063
-rw-r--r--sys/dev/ata/ata-disk.c165
-rw-r--r--sys/dev/ata/ata-disk.h2
-rw-r--r--sys/dev/ata/ata-dma.c288
-rw-r--r--sys/dev/ata/ata-isa.c2
-rw-r--r--sys/dev/ata/ata-lowlevel.c64
-rw-r--r--sys/dev/ata/ata-pci.c81
-rw-r--r--sys/dev/ata/ata-pci.h3
-rw-r--r--sys/dev/ata/ata-queue.c11
-rw-r--r--sys/dev/ata/ata-raid.c2
-rw-r--r--sys/dev/ata/ata-raid.h2
-rw-r--r--sys/dev/ata/ata-usb.c3
-rw-r--r--sys/dev/ata/ata_if.m2
-rw-r--r--sys/dev/ata/atapi-cd.c13
-rw-r--r--sys/dev/ata/atapi-cd.h2
-rw-r--r--sys/dev/ata/atapi-fd.c10
-rw-r--r--sys/dev/ata/atapi-fd.h2
-rw-r--r--sys/dev/ata/atapi-tape.c18
-rw-r--r--sys/dev/ata/atapi-tape.h2
-rw-r--r--sys/sys/ata.h8
24 files changed, 1296 insertions, 648 deletions
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c
index e275b6a..2f1f317 100644
--- a/sys/dev/ata/ata-all.c
+++ b/sys/dev/ata/ata-all.c
@@ -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;
/* local vars */
static int ata_dma = 1;
@@ -91,6 +91,9 @@ SYSCTL_INT(_hw_ata, OID_AUTO, atapi_dma, CTLFLAG_RDTUN, &atapi_dma, 0,
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
@@ -404,13 +407,13 @@ ata_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
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],
@@ -569,7 +572,7 @@ ata_add_child(device_t parent, struct ata_device *atadev, int unit)
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));
@@ -577,11 +580,9 @@ ata_getparam(struct ata_device *atadev, int init)
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;
@@ -631,7 +632,7 @@ ata_getparam(struct ata_device *atadev, int init)
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)),
@@ -643,13 +644,13 @@ ata_getparam(struct ata_device *atadev, int init)
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;
@@ -667,52 +668,39 @@ 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, unit = -1;
+ 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))) {
+ 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;
+ 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);
@@ -810,8 +798,23 @@ ata_modify_if_48bit(struct ata_request *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;
@@ -834,6 +837,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) {
diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h
index 28adac9..6470e35 100644
--- a/sys/dev/ata/ata-all.h
+++ b/sys/dev/ata/ata-all.h
@@ -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,11 +221,13 @@
#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_OFFSET 1024+4096
#define ATA_AHCI_CT_SG_OFFSET 128
#define ATA_AHCI_CT_SIZE 256
@@ -245,6 +248,13 @@ struct ata_ahci_cmd_tab {
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 == ATA_ATA_SLAVE) ? 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
@@ -364,7 +375,16 @@ struct ata_request {
u_int8_t status; /* ATA status */
u_int8_t error; /* ATA error */
- u_int8_t dmastat; /* DMA status */
+ struct {
+ 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 */
+ u_int32_t cur_iosize; /* DMA data current IO size */
+ } dma;
u_int32_t donecount; /* bytes transferred */
int result; /* result error code */
void (*callback)(struct ata_request *request);
@@ -398,6 +418,7 @@ struct ata_device {
device_t dev; /* device handle */
int unit; /* physical unit */
#define ATA_MASTER 0x00
+#define ATA_PM 0x0f
#define ATA_SLAVE 0x10
struct ata_params param; /* ata param structure */
@@ -429,40 +450,33 @@ struct ata_dmasetprd_args {
/* structure holding DMA related information */
struct ata_dma {
bus_dma_tag_t dmatag; /* parent DMA tag */
- 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 */
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 */
-
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 +499,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 +508,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 +538,7 @@ extern int (*ata_raid_ioctl_func)(u_long cmd, caddr_t data);
extern struct intr_config_hook *ata_delayed_attach;
extern devclass_t ata_devclass;
extern int ata_wc;
+extern int ata_setmax;
/* public prototypes */
/* ata-all.c: */
@@ -535,10 +550,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);
diff --git a/sys/dev/ata/ata-card.c b/sys/dev/ata/ata-card.c
index dcd43e7..9a66419 100644
--- a/sys/dev/ata/ata-card.c
+++ b/sys/dev/ata/ata-card.c
@@ -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
diff --git a/sys/dev/ata/ata-cbus.c b/sys/dev/ata/ata-cbus.c
index c978dc3..3ca86a3 100644
--- a/sys/dev/ata/ata-cbus.c
+++ b/sys/dev/ata/ata-cbus.c
@@ -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
diff --git a/sys/dev/ata/ata-chipset.c b/sys/dev/ata/ata-chipset.c
index 29a6117..d6ff0ac 100644
--- a/sys/dev/ata/ata-chipset.c
+++ b/sys/dev/ata/ata-chipset.c
@@ -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
@@ -66,6 +66,9 @@ 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);
@@ -130,8 +133,8 @@ static void ata_nvidia_reset(device_t dev);
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 +145,9 @@ static void ata_promise_mio_intr(void *data);
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 +173,9 @@ static int ata_siiprb_allocate(device_t dev);
static int ata_siiprb_status(device_t dev);
static int ata_siiprb_begin_transaction(struct ata_request *request);
static int ata_siiprb_end_transaction(struct ata_request *request);
+static 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 +277,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 +416,109 @@ 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);
+ }
+
+ /* 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 +526,22 @@ ata_request2fis_h2d(struct ata_request *request, u_int8_t *fis)
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;
@@ -534,10 +638,12 @@ ata_ahci_chipinit(device_t 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",
+ "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_NPMASK) + 1,
+ (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_SPM) ?
+ "supported" : "not supported");
return 0;
}
@@ -563,13 +669,16 @@ 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;
+ 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;
+ 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);
@@ -581,6 +690,9 @@ ata_ahci_allocate(device_t dev)
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));
+ /* enable FIS based switching */
+ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBS + offset, 0x00000003);
+
/* 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 |
@@ -595,7 +707,6 @@ 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;
if (action & (1 << ch->unit)) {
u_int32_t istatus = ATA_INL(ctlr->r_res2, ATA_AHCI_P_IS + offset);
@@ -610,7 +721,8 @@ ata_ahci_status(device_t dev)
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 & 0x78400050) && (cstatus & 1)) {
u_int32_t cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset);
int timeout = 0;
@@ -622,7 +734,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 +748,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 +759,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 +781,7 @@ ata_ahci_begin_transaction(struct ata_request *request)
/* 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 +790,21 @@ ata_ahci_begin_transaction(struct ata_request *request)
/* 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 +816,11 @@ ata_ahci_begin_transaction(struct ata_request *request)
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 +853,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 +869,140 @@ ata_ahci_end_transaction(struct ata_request *request)
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;
+ }
+
+ *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;
}
- ch->devices = 0;
+
+ 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 +1013,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 +1028,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 +1036,119 @@ 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 */
+ 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)
+ | (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);
+ struct ata_ahci_cmd_tab *ctp =
+ (struct ata_ahci_cmd_tab *)(ch->dma.work + ATA_AHCI_CT_OFFSET);
+ int offset = ch->unit << 7;
+ int timeout = 0;
- /* 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));
+ /* kick controller into sane state if needed */
+ ata_ahci_restart(dev);
- /* clear SATA error register */
- ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR));
+ /* 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);
- /* 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));
+ if (ata_ahci_issue_cmd(dev, ATA_AHCI_CMD_RESET | ATA_AHCI_CMD_CLR_BUSY,100))
+ device_printf(dev, "setting SRST failed ??\n");
+ //return -1;
+
+ ata_udelay(5000);
+
+ /* pull reset inactive -> device softreset */
+ bzero(ctp->cfis, 64);
+ ctp->cfis[0] = 0x27;
+ ctp->cfis[1] = port & 0x0f;
+ //ctp->cfis[7] = ATA_D_LBA | ATA_D_IBM;
+ ctp->cfis[15] = ATA_A_4BIT;
+ if (ata_ahci_issue_cmd(dev, 0, 0))
+ return -1;
+
+ ata_udelay(150000);
+
+ timeout = 0;
+ 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);
+
+ 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_int32_t signature;
+
+ if (!(ATA_INL(ctlr->r_res2, ATA_AHCI_PI) & (1 << ch->unit))) {
+ device_printf(dev, "port not implemented\n");
+ return;
+ }
+
+ ata_ahci_restart(dev);
- signature = ATA_INL(ctlr->r_res2, ATA_AHCI_P_SIG + offset);
+ if (!ata_sata_phy_reset(dev)) {
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, "phy reset found no device\n");
+ ch->devices = 0;
+ 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);
+
+ switch (signature) {
+ case 0x00000101:
+ ch->devices = ATA_ATA_MASTER;
+ break;
+ case 0x96690101:
+ ch->devices = ATA_PORTMULTIPLIER;
+ ata_pm_identify(dev);
+ break;
+ case 0xeb140101:
+ ch->devices = ATA_ATAPI_MASTER;
+ break;
+ default: /* SOS XXX */
+ if (bootverbose)
+ device_printf(dev, "No signature, asuming disk device\n");
+ ch->devices = ATA_ATA_MASTER;
}
if (bootverbose)
- device_printf(dev, "ahci_reset devices=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 +1164,9 @@ ata_ahci_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error)
prd[i].dbc = htole32((segs[i].ds_len - 1) & ATA_AHCI_PRD_MASK);
}
}
- KASSERT(nsegs <= ATA_DMA_ENTRIES, ("too many DMA segment entries\n"));
+
+ /* we only have space for 16 entries in a slot */
+ KASSERT(nsegs <= 16, ("too many DMA segment entries\n"));
args->nsegs = nsegs;
}
@@ -874,13 +1177,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 +1257,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 +1286,7 @@ ata_acard_850_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,
@@ -1021,7 +1322,7 @@ ata_acard_86X_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;
@@ -1234,7 +1535,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);
@@ -1398,7 +1699,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 +1793,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 +1982,7 @@ ata_highpoint_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;
u_int32_t timings33[][4] = {
/* HPT366 HPT370 HPT372 HPT374 mode */
@@ -1960,7 +2261,7 @@ ata_intel_new_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;
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);
@@ -2042,7 +2343,7 @@ ata_intel_sata_setmode(device_t dev, int mode)
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,
@@ -2116,11 +2417,13 @@ ata_intel_31244_allocate(device_t dev)
static int
ata_intel_31244_status(device_t dev)
{
+ struct ata_channel *ch = device_get_softc(dev);
+
/* do we have any PHY events ? */
ata_sata_phy_check_events(dev);
/* any drive action to take care of ? */
- return ata_pci_status(dev);
+ return ch->hw.status(dev);
}
static void
@@ -2138,7 +2441,7 @@ ata_intel_31244_tf_write(struct ata_request *request)
((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);
@@ -2159,7 +2462,7 @@ ata_intel_31244_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));
}
@@ -2168,7 +2471,7 @@ ata_intel_31244_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));
}
}
@@ -2227,7 +2530,7 @@ ata_ite_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 */
@@ -2260,7 +2563,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 {
@@ -2570,11 +2873,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++) {
@@ -2681,13 +2984,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 &&
@@ -2703,9 +3006,7 @@ ata_marvell_edma_begin_transaction(struct ata_request *request)
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;
@@ -2714,15 +3015,15 @@ ata_marvell_edma_begin_transaction(struct ata_request *request)
/* 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;
@@ -2773,7 +3074,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;
@@ -2794,7 +3095,7 @@ ata_marvell_edma_end_transaction(struct ata_request *request)
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;
@@ -2809,7 +3110,7 @@ ata_marvell_edma_end_transaction(struct ata_request *request)
request->donecount = request->bytecount;
/* unload SG list */
- ch->dma->unload(ch->dev);
+ ch->dma.unload(request);
res = ATA_OP_FINISHED;
}
@@ -2880,17 +3181,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;
}
@@ -2929,7 +3228,7 @@ ata_national_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;
u_int32_t piotiming[] =
{ 0x9172d132, 0x21717121, 0x00803020, 0x20102010, 0x00100010,
0x00803020, 0x20102010, 0x00100010,
@@ -2938,8 +3237,8 @@ ata_national_setmode(device_t dev, int mode)
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);
@@ -3405,7 +3704,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);
@@ -3444,41 +3743,41 @@ ata_promise_status(device_t dev)
struct ata_channel *ch = device_get_softc(dev);
if (ATA_INL(ctlr->r_res1, 0x1c) & (ch->unit ? 0x00004000 : 0x00000400)) {
- return ata_pci_status(dev);
+ return ch->hw.status(dev);
}
return 0;
}
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->dma.cur_iosize >> 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) {
@@ -3490,7 +3789,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;
}
@@ -3511,11 +3810,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
@@ -3525,7 +3822,7 @@ ata_promise_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;
u_int32_t timings[][2] = {
/* PROLD PRNEW mode */
@@ -3613,7 +3910,7 @@ ata_promise_tx2_status(device_t dev)
ATA_IDX_OUTB(ch, ATA_BMDEVSPEC_0, 0x0b);
if (ATA_IDX_INB(ch, ATA_BMDEVSPEC_1) & 0x20) {
- return ata_pci_status(dev);
+ return ch->hw.status(dev);
}
return 0;
}
@@ -3653,6 +3950,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;
}
@@ -3734,9 +4034,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);
}
@@ -3748,9 +4048,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);
}
@@ -3763,11 +4063,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:
@@ -3783,11 +4088,11 @@ ata_promise_mio_command(struct ata_request *request)
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;
}
@@ -3856,7 +4161,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));
@@ -3877,13 +4182,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
@@ -3893,15 +4224,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_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;
}
@@ -3987,8 +4430,8 @@ ata_promise_sx4_command(struct ata_request *request)
{
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;
@@ -4095,7 +4538,7 @@ ata_promise_apkt(u_int8_t *bytep, struct ata_request *request)
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;
@@ -4116,7 +4559,7 @@ ata_promise_apkt(u_int8_t *bytep, struct ata_request *request)
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;
@@ -4131,7 +4574,8 @@ ata_promise_apkt(u_int8_t *bytep, struct ata_request *request)
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;
@@ -4291,8 +4735,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;
}
@@ -4300,7 +4743,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) {
@@ -4329,7 +4772,7 @@ ata_serverworks_tf_read(struct ata_request *request)
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) {
@@ -4341,7 +4784,7 @@ ata_serverworks_tf_write(struct ata_request *request)
((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);
@@ -4362,7 +4805,7 @@ ata_serverworks_tf_write(struct ata_request *request)
(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));
}
@@ -4371,7 +4814,7 @@ ata_serverworks_tf_write(struct ata_request *request)
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));
}
}
@@ -4384,7 +4827,7 @@ ata_serverworks_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,
@@ -4585,11 +5028,11 @@ 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);
+ return ch->hw.status(dev);
}
return 0;
}
@@ -4601,7 +5044,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);
@@ -4626,7 +5069,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) {
@@ -4686,10 +5129,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);
@@ -4711,7 +5154,7 @@ ata_sii_status(device_t dev)
ata_sata_phy_check_events(dev);
if (ATA_INL(ctlr->r_res2, 0xa0 + offset1) & 0x00000800)
- return ata_pci_status(dev);
+ return ch->hw.status(dev);
else
return 0;
}
@@ -4730,9 +5173,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;
@@ -4762,7 +5205,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);
@@ -4773,7 +5216,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);
}
@@ -4782,7 +5225,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;
@@ -4832,10 +5275,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;
}
@@ -4866,12 +5313,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) {
@@ -4879,12 +5325,9 @@ ata_siiprb_begin_transaction(struct ata_request *request)
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));
@@ -4916,8 +5359,7 @@ ata_siiprb_begin_transaction(struct ata_request *request)
/* 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;
@@ -4925,11 +5367,12 @@ ata_siiprb_begin_transaction(struct ata_request *request)
}
/* 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,
@@ -4941,16 +5384,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))) {
@@ -4984,6 +5427,21 @@ ata_siiprb_end_transaction(struct ata_request *request)
}
}
+ /* 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)
@@ -4993,21 +5451,126 @@ ata_siiprb_end_transaction(struct ata_request *request)
}
/* 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);
@@ -5024,62 +5587,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;
@@ -5088,8 +5622,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) */
@@ -5130,11 +5663,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;
}
@@ -5305,7 +5836,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);
@@ -5630,7 +6161,7 @@ ata_via_family_setmode(device_t dev, int mode)
{ 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;
@@ -5784,7 +6315,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;
}
}
diff --git a/sys/dev/ata/ata-disk.c b/sys/dev/ata/ata-disk.c
index 1ed4c20..a4d7959 100644
--- a/sys/dev/ata/ata-disk.c
+++ b/sys/dev/ata/ata-disk.c
@@ -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$");
#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$");
#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;
-
- /* 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;
+ /* get device geometry into internal structs */
+ ad_get_geometry(dev);
- /* 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;
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;
@@ -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) {
diff --git a/sys/dev/ata/ata-disk.h b/sys/dev/ata/ata-disk.h
index 562b32f..3a091b4 100644
--- a/sys/dev/ata/ata-disk.h
+++ b/sys/dev/ata/ata-disk.h
@@ -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
diff --git a/sys/dev/ata/ata-dma.c b/sys/dev/ata/ata-dma.c
index e6cdff5..10db9aa 100644
--- a/sys/dev/ata/ata-dma.c
+++ b/sys/dev/ata/ata-dma.c
@@ -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,11 @@ __FBSDID("$FreeBSD$");
#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_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");
@@ -68,93 +68,63 @@ ata_dmainit(device_t dev)
{
struct ata_channel *ch = device_get_softc(dev);
- 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;
}
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;
+ struct ata_dc_cb_args dcba;
- if (bus_dmamap_create(ch->dma->data_tag, 0, &ch->dma->data_map))
+ 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,
+ 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))
+ 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))
+ 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, &ccba, 0) || ccba.error) {
- bus_dmamem_free(ch->dma->work_tag,ch->dma->work, ch->dma->work_map);
+ if (bus_dmamap_load(ch->dma.work_tag, ch->dma.work_map ,ch->dma.work,
+ MAXWSPCSZ, ata_dmasetupc_cb, &dcba, BUS_DMA_NOWAIT) ||
+ dcba.error) {
+ bus_dmamem_free(ch->dma.work_tag, ch->dma.work, ch->dma.work_map);
goto error;
}
- ch->dma->work_bus = ccba.maddr;
+ ch->dma.work_bus = dcba.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
@@ -162,39 +132,20 @@ ata_dmafree(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->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.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->data_tag) {
- bus_dma_tag_destroy(ch->dma->data_tag);
- ch->dma->data_tag = 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;
+ if (ch->dma.dmatag) {
+ bus_dma_tag_destroy(ch->dma.dmatag);
+ ch->dma.dmatag = NULL;
}
}
@@ -218,67 +169,144 @@ ata_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error)
}
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_dc_cb_args dcba;
+ 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.cur_iosize) {
+ 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 (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, &request->dma.sg_tag)) {
+ device_printf(request->dev, "FAILURE - create sg_tag\n");
+ goto error;
+ }
+
+ if (bus_dmamem_alloc(request->dma.sg_tag, (void **)&request->dma.sg, 0,
+ &request->dma.sg_map)) {
+ device_printf(request->dev, "FAILURE - alloc sg_map\n");
+ goto error;
+ }
+
+ if (bus_dmamap_load(request->dma.sg_tag, request->dma.sg_map,
+ request->dma.sg, MAXTABSZ,
+ ata_dmasetupc_cb, &dcba, BUS_DMA_NOWAIT) || dcba.error){
+ bus_dmamem_free(request->dma.sg_tag,
+ request->dma.sg, request->dma.sg_map);
+ device_printf(request->dev, "FAILURE - load sg\n");
+ goto error;
+ }
+ request->dma.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,
+ &request->dma.data_tag)) {
+ device_printf(request->dev, "FAILURE - create data_tag\n");
+ goto error;
+ }
+
+ if (bus_dmamap_create(request->dma.data_tag, 0, &request->dma.data_map)) {
+ device_printf(request->dev, "FAILURE - create data_map\n");
+ goto error;
+ }
+
+ 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;
+ }
- 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;
+ if (entries)
+ *entries = dspa.nsegs;
- *entries = cba.nsegs;
+ bus_dmamap_sync(request->dma.sg_tag, request->dma.sg_map,
+ BUS_DMASYNC_PREWRITE);
- bus_dmamap_sync(ch->dma->sg_tag, ch->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);
- bus_dmamap_sync(ch->dma->data_tag, ch->dma->data_map,
- dir ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
+ request->dma.cur_iosize = request->bytecount;
- ch->dma->cur_iosize = count;
- ch->dma->flags = dir ? (ATA_DMA_LOADED | ATA_DMA_READ) : ATA_DMA_LOADED;
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.cur_iosize) {
+ 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);
+ bus_dmamap_unload(request->dma.data_tag, request->dma.data_map);
- ch->dma->cur_iosize = 0;
- ch->dma->flags &= ~ATA_DMA_LOADED;
+ request->dma.cur_iosize = 0;
+ }
+ if (request->dma.data_map) {
+ bus_dmamap_destroy(request->dma.data_tag, request->dma.data_map);
+ request->dma.data_map = NULL;
+ }
+ if (request->dma.data_tag) {
+ bus_dma_tag_destroy(request->dma.data_tag);
+ request->dma.data_tag = NULL;
+ }
+ if (request->dma.sg_bus) {
+ bus_dmamap_unload(request->dma.sg_tag, request->dma.sg_map);
+ bus_dmamem_free(request->dma.sg_tag, request->dma.sg,
+ request->dma.sg_map);
+ request->dma.sg = NULL;
+ request->dma.sg_bus = 0;
+ request->dma.sg_map = NULL;
+ }
+ if (request->dma.sg_tag) {
+ bus_dma_tag_destroy(request->dma.sg_tag);
+ request->dma.sg_tag = NULL;
}
return 0;
}
diff --git a/sys/dev/ata/ata-isa.c b/sys/dev/ata/ata-isa.c
index 038e2d9..3b7d86d 100644
--- a/sys/dev/ata/ata-isa.c
+++ b/sys/dev/ata/ata-isa.c
@@ -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
diff --git a/sys/dev/ata/ata-lowlevel.c b/sys/dev/ata/ata-lowlevel.c
index af08b1a..62a5f0a 100644
--- a/sys/dev/ata/ata-lowlevel.c
+++ b/sys/dev/ata/ata-lowlevel.c
@@ -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 *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 *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 *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 *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 *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 *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,7 @@ ata_begin_transaction(struct ata_request *request)
printf("ata_begin_transaction OOPS!!!\n");
begin_finished:
- if (ch->dma && ch->dma->flags & ATA_DMA_LOADED)
- ch->dma->unload(ch->dev);
+ ch->dma.unload(request);
return ATA_OP_FINISHED;
begin_continue:
@@ -228,7 +226,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 +312,19 @@ ata_end_transaction(struct ata_request *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 +424,19 @@ ata_end_transaction(struct ata_request *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;
@@ -617,7 +615,7 @@ ata_wait(struct ata_channel *ch, struct ata_device *atadev, u_int8_t mask)
/* 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 +655,11 @@ ata_wait(struct ata_channel *ch, struct ata_device *atadev, u_int8_t mask)
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 +726,7 @@ ata_generic_command(struct ata_request *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 +756,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 +770,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 +792,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 +801,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 +810,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 +835,7 @@ ata_pio_read(struct ata_request *request, int length)
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;
diff --git a/sys/dev/ata/ata-pci.c b/sys/dev/ata/ata-pci.c
index 6d493e2..daee8e5 100644
--- a/sys/dev/ata/ata-pci.c
+++ b/sys/dev/ata/ata-pci.c
@@ -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
@@ -422,23 +422,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
+static 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 +446,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 +493,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 +511,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 *
@@ -603,14 +609,13 @@ ata_pcichannel_attach(device_t dev)
struct ata_channel *ch = device_get_softc(dev);
int error;
- if (ctlr->dmainit)
+ if (ctlr->dmainit) {
ctlr->dmainit(dev);
- if (ch->dma)
- ch->dma->alloc(dev);
+ ch->dma.alloc(dev);
+ }
if ((error = ctlr->allocate(dev))) {
- if (ch->dma)
- ch->dma->free(dev);
+ ch->dma.free(dev);
return error;
}
@@ -626,8 +631,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 +657,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)
diff --git a/sys/dev/ata/ata-pci.h b/sys/dev/ata/ata-pci.h
index f514af8..314b333 100644
--- a/sys/dev/ata/ata-pci.h
+++ b/sys/dev/ata/ata-pci.h
@@ -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
@@ -460,7 +460,6 @@ int ata_pci_setup_intr(device_t dev, device_t child, struct resource *irq, int f
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_dmainit(device_t dev);
char *ata_pcivendor2str(device_t dev);
diff --git a/sys/dev/ata/ata-queue.c b/sys/dev/ata/ata-queue.c
index 9849443..763058c 100644
--- a/sys/dev/ata/ata-queue.c
+++ b/sys/dev/ata/ata-queue.c
@@ -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
@@ -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");
@@ -694,11 +694,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 +729,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);
diff --git a/sys/dev/ata/ata-raid.c b/sys/dev/ata/ata-raid.c
index 74c849c..50a872b 100644
--- a/sys/dev/ata/ata-raid.c
+++ b/sys/dev/ata/ata-raid.c
@@ -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
diff --git a/sys/dev/ata/ata-raid.h b/sys/dev/ata/ata-raid.h
index 17d38e4..f8cc2b9 100644
--- a/sys/dev/ata/ata-raid.h
+++ b/sys/dev/ata/ata-raid.h
@@ -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
diff --git a/sys/dev/ata/ata-usb.c b/sys/dev/ata/ata-usb.c
index cc449e0..2cc25d6 100644
--- a/sys/dev/ata/ata-usb.c
+++ b/sys/dev/ata/ata-usb.c
@@ -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$");
#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>
diff --git a/sys/dev/ata/ata_if.m b/sys/dev/ata/ata_if.m
index 2621fef..8fcc3f2 100644
--- a/sys/dev/ata/ata_if.m
+++ b/sys/dev/ata/ata_if.m
@@ -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
diff --git a/sys/dev/ata/atapi-cd.c b/sys/dev/ata/atapi-cd.c
index df63fe1..a64cfeb 100644
--- a/sys/dev/ata/atapi-cd.c
+++ b/sys/dev/ata/atapi-cd.c
@@ -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
@@ -908,10 +908,7 @@ 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);
- if (ch->dma)
- cdp->iomax = min(ch->dma->max_iosize, 65534);
- else
- cdp->iomax = min(DFLTPHYS, 65534);
+ cdp->iomax = min(ch->dma.max_iosize, 65534);
}
static void
@@ -1706,8 +1703,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 +1875,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) );
}
}
diff --git a/sys/dev/ata/atapi-cd.h b/sys/dev/ata/atapi-cd.h
index 3358870..d78771a 100644
--- a/sys/dev/ata/atapi-cd.h
+++ b/sys/dev/ata/atapi-cd.h
@@ -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
diff --git a/sys/dev/ata/atapi-fd.c b/sys/dev/ata/atapi-fd.c
index 0f98913..9a26399 100644
--- a/sys/dev/ata/atapi-fd.c
+++ b/sys/dev/ata/atapi-fd.c
@@ -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;
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",
diff --git a/sys/dev/ata/atapi-fd.h b/sys/dev/ata/atapi-fd.h
index fdad69b..e44ad66 100644
--- a/sys/dev/ata/atapi-fd.h
+++ b/sys/dev/ata/atapi-fd.h
@@ -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
diff --git a/sys/dev/ata/atapi-tape.c b/sys/dev/ata/atapi-tape.c
index f12f4b4..3304907 100644
--- a/sys/dev/ata/atapi-tape.c
+++ b/sys/dev/ata/atapi-tape.c
@@ -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;
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 */
@@ -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));
}
}
diff --git a/sys/dev/ata/atapi-tape.h b/sys/dev/ata/atapi-tape.h
index af3ea23..0d4dedf 100644
--- a/sys/dev/ata/atapi-tape.h
+++ b/sys/dev/ata/atapi-tape.h
@@ -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
diff --git a/sys/sys/ata.h b/sys/sys/ata.h
index d951ceb..a42932c 100644
--- a/sys/sys/ata.h
+++ b/sys/sys/ata.h
@@ -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 */
OpenPOWER on IntegriCloud