summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authorsos <sos@FreeBSD.org>2000-01-27 19:00:51 +0000
committersos <sos@FreeBSD.org>2000-01-27 19:00:51 +0000
commit0dd4bc7de09574eabc665f10d8394e9cbca4ece9 (patch)
treef4ee033f09cc623d33566a89d435ed0ad2ac4a2b /sys/dev
parenteaf345be5e3f645bf013076336123beb85da201d (diff)
downloadFreeBSD-src-0dd4bc7de09574eabc665f10d8394e9cbca4ece9.zip
FreeBSD-src-0dd4bc7de09574eabc665f10d8394e9cbca4ece9.tar.gz
Add sysctl oid hw.atamodes to set the transfermodes online.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ata/ata-all.c72
-rw-r--r--sys/dev/ata/ata-all.h10
-rw-r--r--sys/dev/ata/ata-disk.c22
-rw-r--r--sys/dev/ata/ata-disk.h3
-rw-r--r--sys/dev/ata/ata-dma.c27
-rw-r--r--sys/dev/ata/atapi-all.c3
-rw-r--r--sys/dev/ata/atapi-all.h7
7 files changed, 101 insertions, 43 deletions
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c
index a1abee5..f1d534e 100644
--- a/sys/dev/ata/ata-all.c
+++ b/sys/dev/ata/ata-all.c
@@ -47,6 +47,7 @@
#include <sys/buf.h>
#include <sys/malloc.h>
#include <sys/devicestat.h>
+#include <sys/sysctl.h>
#include <machine/stdarg.h>
#include <vm/vm.h>
#include <vm/pmap.h>
@@ -784,7 +785,6 @@ ataintr(void *data)
intr_count, scp->status);
}
#endif
- /* return; SOS XXX */
}
scp->active = ATA_IDLE;
scp->running = NULL;
@@ -799,6 +799,7 @@ ata_start(struct ata_softc *scp)
if (scp->active != ATA_IDLE)
return;
+ scp->active = ATA_ACTIVE;
#if NATADISK > 0
/* find & call the responsible driver if anything on the ATA queue */
@@ -853,6 +854,7 @@ ata_start(struct ata_softc *scp)
return;
}
#endif
+ scp->active = ATA_IDLE;
}
void
@@ -1062,6 +1064,7 @@ int8_t *
ata_mode2str(int32_t mode)
{
switch (mode) {
+ case ATA_PIO: return "BIOSPIO";
case ATA_PIO0: return "PIO0";
case ATA_PIO1: return "PIO1";
case ATA_PIO2: return "PIO2";
@@ -1070,7 +1073,7 @@ ata_mode2str(int32_t mode)
case ATA_WDMA2: return "WDMA2";
case ATA_UDMA2: return "UDMA33";
case ATA_UDMA4: return "UDMA66";
- case ATA_DMA: return "DMA";
+ case ATA_DMA: return "BIOSDMA";
default: return "???";
}
}
@@ -1205,3 +1208,68 @@ ata_printf(struct ata_softc *scp, int32_t device, const char * fmt, ...)
va_end(ap);
return ret;
}
+
+static char ata_conf[1024];
+
+static void
+ata_change_mode(struct ata_softc *scp, int32_t device, int32_t mode)
+{
+ int32_t s = splbio();
+
+ while (scp->active != ATA_IDLE)
+ tsleep((caddr_t)&s, PRIBIO, "atachm", hz/4);
+ scp->active = ATA_REINITING;
+ ata_dmainit(scp, device, ata_pmode(ATA_PARAM(scp, device)),
+ mode < ATA_DMA ? -1 : ata_wmode(ATA_PARAM(scp, device)),
+ mode < ATA_DMA ? -1 : ata_umode(ATA_PARAM(scp, device)));
+ scp->active = ATA_IDLE;
+ ata_start(scp);
+ splx(s);
+}
+
+static int
+sysctl_hw_ata SYSCTL_HANDLER_ARGS
+{
+ int error, i;
+
+ /* readout internal state */
+ bzero(ata_conf, sizeof(ata_conf));
+ for (i = 0; i < (atanlun << 1); i++) {
+ if (!atadevices[i >> 1] || !atadevices[ i >> 1]->dev_softc[i & 1])
+ strcat(ata_conf, "---,");
+ else if (atadevices[i >> 1]->mode[i & 1] >= ATA_DMA)
+ strcat(ata_conf, "dma,");
+ else
+ strcat(ata_conf, "pio,");
+ }
+ error = sysctl_handle_string(oidp, ata_conf, sizeof(ata_conf), req);
+ if (error == 0 && req->newptr != NULL) {
+ char *ptr = ata_conf;
+
+ /* update internal state */
+ i = 0;
+ while (*ptr) {
+ if (!strncmp(ptr, "pio", 3) || !strncmp(ptr, "PIO", 3)) {
+ if (atadevices[i >> 1]->dev_softc[i & 1] &&
+ atadevices[i >>1 ]->mode[i & 1] >= ATA_DMA)
+ ata_change_mode(atadevices[i >> 1],
+ (i & 1) ? ATA_SLAVE : ATA_MASTER, ATA_PIO);
+ }
+ else if (!strncmp(ptr, "dma", 3) || !strncmp(ptr, "DMA", 3)) {
+ if (atadevices[i >> 1]->dev_softc[i & 1] &&
+ atadevices[i >> 1]->mode[i & 1] < ATA_DMA)
+ ata_change_mode(atadevices[i >> 1],
+ (i & 1) ? ATA_SLAVE : ATA_MASTER, ATA_DMA);
+ }
+ else if (strncmp(ptr, "---", 3))
+ break;
+ ptr+=3;
+ if (*ptr++ != ',' || ++i > (atanlun << 1))
+ break;
+ }
+ }
+ return error;
+}
+
+SYSCTL_PROC(_hw, OID_AUTO, atamodes, CTLTYPE_STRING | CTLFLAG_RW,
+ 0, sizeof(ata_conf), sysctl_hw_ata, "A", "");
diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h
index 66de7f1..ff6c640 100644
--- a/sys/dev/ata/ata-all.h
+++ b/sys/dev/ata/ata-all.h
@@ -260,15 +260,16 @@ struct ata_softc {
void *dev_softc[2]; /* ptr to devices softc's */
struct ata_dmaentry *dmatab[2]; /* DMA transfer tables */
int32_t mode[2]; /* transfer mode for devices */
+#define ATA_PIO 0x00
#define ATA_PIO0 0x08
#define ATA_PIO1 0x09
#define ATA_PIO2 0x0a
#define ATA_PIO3 0x0b
#define ATA_PIO4 0x0c
+#define ATA_DMA 0x10
#define ATA_WDMA2 0x22
#define ATA_UDMA2 0x42
#define ATA_UDMA4 0x44
-#define ATA_DMA 0xff
int32_t flags; /* controller flags */
#define ATA_DMA_ACTIVE 0x01
@@ -288,9 +289,10 @@ struct ata_softc {
#define ATA_IMMEDIATE 0x1
#define ATA_WAIT_INTR 0x2
#define ATA_WAIT_READY 0x3
-#define ATA_ACTIVE_ATA 0x4
-#define ATA_ACTIVE_ATAPI 0x5
-#define ATA_REINITING 0x6
+#define ATA_ACTIVE 0x4
+#define ATA_ACTIVE_ATA 0x5
+#define ATA_ACTIVE_ATAPI 0x6
+#define ATA_REINITING 0x7
TAILQ_HEAD(, ad_request) ata_queue; /* head of ATA queue */
TAILQ_HEAD(, atapi_request) atapi_queue; /* head of ATAPI queue */
diff --git a/sys/dev/ata/ata-disk.c b/sys/dev/ata/ata-disk.c
index c21be76..f7d596c 100644
--- a/sys/dev/ata/ata-disk.c
+++ b/sys/dev/ata/ata-disk.c
@@ -152,9 +152,8 @@ ad_attach(struct ata_softc *scp, int32_t device)
printf("ad%d: enabling write cache failed\n", adp->lun);
/* use DMA if drive & controller supports it */
- if (!ata_dmainit(adp->controller, adp->unit, ata_pmode(AD_PARAM),
- ata_wmode(AD_PARAM), ata_umode(AD_PARAM)))
- adp->flags |= AD_F_DMA_ENABLED;
+ ata_dmainit(adp->controller, adp->unit, ata_pmode(AD_PARAM),
+ ata_wmode(AD_PARAM), ata_umode(AD_PARAM));
/* use tagged queueing if supported (not yet) */
if ((adp->num_tags = (AD_PARAM->queuelen & 0x1f) + 1))
@@ -257,8 +256,9 @@ addump(dev_t dev)
if (!adp)
return ENXIO;
+ /* force PIO mode for dumps */
+ adp->controller->mode[ATA_DEV(adp->unit)] = ATA_PIO;
ata_reinit(adp->controller);
- adp->flags &= ~AD_F_DMA_ENABLED;
while (count > 0) {
DELAY(1000);
@@ -386,7 +386,7 @@ ad_transfer(struct ad_request *request)
/* does this drive & transfer work with DMA ? */
request->flags &= ~AR_F_DMA_USED;
- if ((adp->flags & AD_F_DMA_ENABLED) &&
+ if ((adp->controller->mode[ATA_DEV(adp->unit)] >= ATA_DMA) &&
!ata_dmasetup(adp->controller, adp->unit,
(void *)request->data, request->bytecount,
(request->flags & AR_F_READ))) {
@@ -394,23 +394,26 @@ ad_transfer(struct ad_request *request)
cmd = request->flags & AR_F_READ ? ATA_C_READ_DMA : ATA_C_WRITE_DMA;
request->currentsize = request->bytecount;
}
+
/* does this drive support multi sector transfers ? */
else if (request->currentsize > DEV_BSIZE)
cmd = request->flags & AR_F_READ?ATA_C_READ_MULTI:ATA_C_WRITE_MULTI;
+
/* just plain old single sector transfer */
else
cmd = request->flags & AR_F_READ ? ATA_C_READ : ATA_C_WRITE;
if (ata_command(adp->controller, adp->unit, cmd,
- cylinder, head, sector, count, 0, ATA_IMMEDIATE))
+ cylinder, head, sector, count, 0, ATA_IMMEDIATE)) {
printf("ad%d: wouldn't take transfer command\n", adp->lun);
+ return;
+ }
/* if this is a DMA transfer, start it, return and wait for interrupt */
if (request->flags & AR_F_DMA_USED) {
ata_dmastart(adp->controller);
return;
}
-
}
/* calculate this transfer length */
@@ -473,7 +476,6 @@ oops:
else {
ata_dmainit(adp->controller, adp->unit,
ata_pmode(AD_PARAM), -1, -1);
- adp->flags &= ~AD_F_DMA_ENABLED;
printf(" falling back to PIO mode\n");
}
TAILQ_INSERT_HEAD(&adp->controller->ata_queue, request, chain);
@@ -485,7 +487,6 @@ oops:
untimeout((timeout_t *)ad_timeout, request,request->timeout_handle);
ata_dmainit(adp->controller, adp->unit, ata_pmode(AD_PARAM), -1,-1);
request->flags |= AR_F_FORCE_PIO;
- adp->flags &= ~AD_F_DMA_ENABLED;
TAILQ_INSERT_HEAD(&adp->controller->ata_queue, request, chain);
return ATA_OP_FINISHED;
}
@@ -558,7 +559,7 @@ ad_reinit(struct ad_softc *adp)
/* reinit disk parameters */
ata_command(adp->controller, adp->unit, ATA_C_SET_MULTI, 0, 0, 0,
adp->transfersize / DEV_BSIZE, 0, ATA_WAIT_READY);
- if (adp->flags & AD_F_DMA_ENABLED)
+ if (adp->controller->mode[ATA_DEV(adp->unit)] >= ATA_DMA)
ata_dmainit(adp->controller, adp->unit, ata_pmode(AD_PARAM),
ata_wmode(AD_PARAM), ata_umode(AD_PARAM));
else
@@ -578,7 +579,6 @@ ad_timeout(struct ad_request *request)
ata_dmadone(adp->controller);
if (request->retries == AD_MAX_RETRIES) {
ata_dmainit(adp->controller, adp->unit, ata_pmode(AD_PARAM), -1,-1);
- adp->flags &= ~AD_F_DMA_ENABLED;
printf("ad%d: ad_timeout: trying fallback to PIO mode\n", adp->lun);
request->retries = 0;
}
diff --git a/sys/dev/ata/ata-disk.h b/sys/dev/ata/ata-disk.h
index 63fb4c7..eadfeb12 100644
--- a/sys/dev/ata/ata-disk.h
+++ b/sys/dev/ata/ata-disk.h
@@ -42,8 +42,7 @@ struct ad_softc {
#define AD_F_LABELLING 0x0001
#define AD_F_LBA_ENABLED 0x0002
#define AD_F_32B_ENABLED 0x0004
-#define AD_F_DMA_ENABLED 0x0008
-#define AD_F_TAG_ENABLED 0x0010
+#define AD_F_TAG_ENABLED 0x0008
struct buf_queue_head queue; /* head of request queue */
struct devstat stats; /* devstat entry */
diff --git a/sys/dev/ata/ata-dma.c b/sys/dev/ata/ata-dma.c
index 82a1afb..56de719 100644
--- a/sys/dev/ata/ata-dma.c
+++ b/sys/dev/ata/ata-dma.c
@@ -260,7 +260,8 @@ ata_dmainit(struct ata_softc *scp, int32_t device,
error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY);
if (bootverbose)
- ata_printf(scp, device, "%s setting up UDMA4 mode on VIA chip\n",
+ ata_printf(scp, device,
+ "%s setting up UDMA4 mode on VIA chip\n",
(error) ? "failed" : "success");
if (!error) {
pci_write_config(scp->dev, 0x53 - devno, 0xe8, 1);
@@ -418,11 +419,9 @@ ata_dmainit(struct ata_softc *scp, int32_t device,
"%s setting up PIO%d mode on Promise chip\n",
(error) ? "failed" : "success",
(apiomode >= 0) ? apiomode : 0);
- if (!error) {
- promise_timing(scp, devno, ata_pio2mode(apiomode));
- return 0;
- }
- break;
+ promise_timing(scp, devno, ata_pio2mode(apiomode));
+ scp->mode[ATA_DEV(device)] = ata_pio2mode(apiomode);
+ return -1;
case 0x00041103: /* HighPoint HPT366 controller */
/* no ATAPI devices for now */
@@ -476,11 +475,9 @@ ata_dmainit(struct ata_softc *scp, int32_t device,
ata_printf(scp, device, "%s setting up PIO%d mode on HPT366 chip\n",
(error) ? "failed" : "success",
(apiomode >= 0) ? apiomode : 0);
- if (!error) {
- hpt366_timing(scp, devno, ata_pio2mode(apiomode));
- return 0;
- }
- break;
+ hpt366_timing(scp, devno, ata_pio2mode(apiomode));
+ scp->mode[ATA_DEV(device)] = ata_pio2mode(apiomode);
+ return -1;
default: /* unknown controller chip */
/* better not try generic DMA on ATAPI devices it almost never works */
@@ -490,11 +487,6 @@ ata_dmainit(struct ata_softc *scp, int32_t device,
/* well, we have no support for this, but try anyways */
if ((wdmamode >= 2 && apiomode >= 4) && scp->bmaddr) {
-#if MAYBE_NOT
- && (inb(scp->bmaddr + ATA_BMSTAT_PORT) &
- ((device == ATA_MASTER) ?
- ATA_BMSTAT_DMA_MASTER : ATA_BMSTAT_DMA_SLAVE))) {
-#endif
error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
if (bootverbose)
@@ -512,8 +504,7 @@ ata_dmainit(struct ata_softc *scp, int32_t device,
if (bootverbose)
ata_printf(scp, device, "%s setting up PIO%d mode on generic chip\n",
(error) ? "failed" : "success",(apiomode>=0) ? apiomode : 0);
- if (!error)
- scp->mode[ATA_DEV(device)] = ata_pio2mode(apiomode);
+ scp->mode[ATA_DEV(device)] = ata_pio2mode(apiomode);
return -1;
}
diff --git a/sys/dev/ata/atapi-all.c b/sys/dev/ata/atapi-all.c
index fecbe3a..2f37f2c 100644
--- a/sys/dev/ata/atapi-all.c
+++ b/sys/dev/ata/atapi-all.c
@@ -93,7 +93,6 @@ atapi_attach(struct ata_softc *scp, int32_t device)
(ata_wmode(ATP_PARAM) < 0) ?
(ATP_PARAM->dmaflag ? 2 : 0) : ata_wmode(ATP_PARAM),
ata_umode(ATP_PARAM)))
- atp->flags |= ATAPI_F_DMA_ENABLED;
}
else
#endif
@@ -208,7 +207,7 @@ atapi_transfer(struct atapi_request *request)
atp->flags &= ~ATAPI_F_DSC_USED;
/* if DMA enabled setup DMA hardware */
- if ((atp->flags & ATAPI_F_DMA_ENABLED) &&
+ if ((atp->controller->mode[ATA_DEV(atp->unit)] >= ATA_DMA) &&
(request->ccb[0] == ATAPI_READ ||
request->ccb[0] == ATAPI_READ_BIG ||
((request->ccb[0] == ATAPI_WRITE ||
diff --git a/sys/dev/ata/atapi-all.h b/sys/dev/ata/atapi-all.h
index 36e84b6..26cf7ad 100644
--- a/sys/dev/ata/atapi-all.h
+++ b/sys/dev/ata/atapi-all.h
@@ -139,10 +139,9 @@ struct atapi_softc {
int8_t *devname; /* this devices name */
int8_t cmd; /* last cmd executed */
u_int32_t flags; /* drive flags */
-#define ATAPI_F_DMA_ENABLED 0x0001
-#define ATAPI_F_DMA_USED 0x0002
-#define ATAPI_F_DSC_USED 0x0004
-#define ATAPI_F_MEDIA_CHANGED 0x0008
+#define ATAPI_F_DMA_USED 0x0001
+#define ATAPI_F_DSC_USED 0x0002
+#define ATAPI_F_MEDIA_CHANGED 0x0004
};
OpenPOWER on IntegriCloud