Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/jdolecek-ncq]: src/sys/dev pass also ata_command via ata_xfer, callers o...
details: https://anonhg.NetBSD.org/src/rev/f066562aba11
branches: jdolecek-ncq
changeset: 352625:f066562aba11
user: jdolecek <jdolecek%NetBSD.org@localhost>
date: Sat Apr 15 17:14:11 2017 +0000
description:
pass also ata_command via ata_xfer, callers of ata_exec_command() is now
responsible for allocation/disposal of the structure
change code to allocate ata_xfer for commands on stack same way as previously
the ata_command were, using c_slot 0; adjust asserts so that it would allow
several xfers with same c_slot, as long as only one such transfer is active
at a time
diffstat:
sys/dev/ata/ata.c | 81 +++++++++++---------
sys/dev/ata/atavar.h | 125 ++++++++++++++++---------------
sys/dev/ata/satapmp_subr.c | 72 +++++++++---------
sys/dev/ata/wd.c | 175 +++++++++++++++++++++++---------------------
sys/dev/ic/ahcisata_core.c | 32 +++----
sys/dev/ic/mvsata.c | 54 ++++++-------
sys/dev/ic/siisata.c | 39 ++++-----
sys/dev/ic/wdc.c | 25 ++----
sys/dev/ic/wdcvar.h | 4 +-
sys/dev/scsipi/atapi_wdc.c | 40 +++++-----
10 files changed, 322 insertions(+), 325 deletions(-)
diffs (truncated from 1622 to 300 lines):
diff -r 3841969bc5c3 -r f066562aba11 sys/dev/ata/ata.c
--- a/sys/dev/ata/ata.c Sat Apr 15 12:01:23 2017 +0000
+++ b/sys/dev/ata/ata.c Sat Apr 15 17:14:11 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ata.c,v 1.132.8.3 2017/04/15 12:01:23 jdolecek Exp $ */
+/* $NetBSD: ata.c,v 1.132.8.4 2017/04/15 17:14:11 jdolecek Exp $ */
/*
* Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved.
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.132.8.3 2017/04/15 12:01:23 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.132.8.4 2017/04/15 17:14:11 jdolecek Exp $");
#include "opt_ata.h"
@@ -192,10 +192,18 @@
struct ata_xfer *
ata_queue_hwslot_to_xfer(struct ata_queue *chq, int hwslot)
{
+ struct ata_xfer *xfer;
+
KASSERT(hwslot < chq->queue_openings);
- KASSERT((chq->queue_xfers_avail & __BIT(hwslot)) == 0);
+ KASSERT(hwslot == 0 || (chq->queue_xfers_avail & __BIT(hwslot)) == 0);
- return &chq->queue_xfers[hwslot];
+ /* Usually the first entry will be the one */
+ TAILQ_FOREACH(xfer, &chq->active_xfers, c_activechain) {
+ if (xfer->c_slot == hwslot)
+ return xfer;
+ }
+
+ panic("%s: xfer with slot %d not found", __func__, hwslot);
}
struct ata_queue *
@@ -204,7 +212,7 @@
if (openings == 0)
openings = 1;
struct ata_queue *chq = malloc(offsetof(struct ata_queue, queue_xfers[openings]),
- M_DEVBUF, M_WAITOK);
+ M_DEVBUF, M_WAITOK | M_ZERO);
if (chq != NULL) {
chq->queue_openings = openings;
chq->queue_xfers_avail = (1 << openings) - 1;
@@ -768,7 +776,7 @@
ata_get_params(struct ata_drive_datas *drvp, uint8_t flags,
struct ataparams *prms)
{
- struct ata_command ata_c;
+ struct ata_xfer xfer;
struct ata_channel *chp = drvp->chnl_softc;
struct atac_softc *atac = chp->ch_atac;
char *tb;
@@ -779,42 +787,42 @@
tb = kmem_zalloc(DEV_BSIZE, KM_SLEEP);
memset(prms, 0, sizeof(struct ataparams));
- memset(&ata_c, 0, sizeof(struct ata_command));
+ memset(&xfer, 0, sizeof(xfer));
if (drvp->drive_type == ATA_DRIVET_ATA) {
- ata_c.r_command = WDCC_IDENTIFY;
- ata_c.r_st_bmask = WDCS_DRDY;
- ata_c.r_st_pmask = WDCS_DRQ;
- ata_c.timeout = 3000; /* 3s */
+ xfer.c_ata_c.r_command = WDCC_IDENTIFY;
+ xfer.c_ata_c.r_st_bmask = WDCS_DRDY;
+ xfer.c_ata_c.r_st_pmask = WDCS_DRQ;
+ xfer.c_ata_c.timeout = 3000; /* 3s */
} else if (drvp->drive_type == ATA_DRIVET_ATAPI) {
- ata_c.r_command = ATAPI_IDENTIFY_DEVICE;
- ata_c.r_st_bmask = 0;
- ata_c.r_st_pmask = WDCS_DRQ;
- ata_c.timeout = 10000; /* 10s */
+ xfer.c_ata_c.r_command = ATAPI_IDENTIFY_DEVICE;
+ xfer.c_ata_c.r_st_bmask = 0;
+ xfer.c_ata_c.r_st_pmask = WDCS_DRQ;
+ xfer.c_ata_c.timeout = 10000; /* 10s */
} else {
ATADEBUG_PRINT(("ata_get_parms: no disks\n"),
DEBUG_FUNCS|DEBUG_PROBE);
rv = CMD_ERR;
goto out;
}
- ata_c.flags = AT_READ | flags;
- ata_c.data = tb;
- ata_c.bcount = DEV_BSIZE;
+ xfer.c_ata_c.flags = AT_READ | flags;
+ xfer.c_ata_c.data = tb;
+ xfer.c_ata_c.bcount = DEV_BSIZE;
if ((*atac->atac_bustype_ata->ata_exec_command)(drvp,
- &ata_c) != ATACMD_COMPLETE) {
+ &xfer) != ATACMD_COMPLETE) {
ATADEBUG_PRINT(("ata_get_parms: wdc_exec_command failed\n"),
DEBUG_FUNCS|DEBUG_PROBE);
rv = CMD_AGAIN;
goto out;
}
- if (ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
+ if (xfer.c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
ATADEBUG_PRINT(("ata_get_parms: ata_c.flags=0x%x\n",
- ata_c.flags), DEBUG_FUNCS|DEBUG_PROBE);
+ xfer.c_ata_c.flags), DEBUG_FUNCS|DEBUG_PROBE);
rv = CMD_ERR;
goto out;
}
/* if we didn't read any data something is wrong */
- if ((ata_c.flags & AT_XFDONE) == 0) {
+ if ((xfer.c_ata_c.flags & AT_XFDONE) == 0) {
rv = CMD_ERR;
goto out;
}
@@ -868,24 +876,24 @@
int
ata_set_mode(struct ata_drive_datas *drvp, uint8_t mode, uint8_t flags)
{
- struct ata_command ata_c;
+ struct ata_xfer xfer;
struct ata_channel *chp = drvp->chnl_softc;
struct atac_softc *atac = chp->ch_atac;
ATADEBUG_PRINT(("ata_set_mode=0x%x\n", mode), DEBUG_FUNCS);
- memset(&ata_c, 0, sizeof(struct ata_command));
+ memset(&xfer, 0, sizeof(xfer));
- ata_c.r_command = SET_FEATURES;
- ata_c.r_st_bmask = 0;
- ata_c.r_st_pmask = 0;
- ata_c.r_features = WDSF_SET_MODE;
- ata_c.r_count = mode;
- ata_c.flags = flags;
- ata_c.timeout = 1000; /* 1s */
+ xfer.c_ata_c.r_command = SET_FEATURES;
+ xfer.c_ata_c.r_st_bmask = 0;
+ xfer.c_ata_c.r_st_pmask = 0;
+ xfer.c_ata_c.r_features = WDSF_SET_MODE;
+ xfer.c_ata_c.r_count = mode;
+ xfer.c_ata_c.flags = flags;
+ xfer.c_ata_c.timeout = 1000; /* 1s */
if ((*atac->atac_bustype_ata->ata_exec_command)(drvp,
- &ata_c) != ATACMD_COMPLETE)
+ &xfer) != ATACMD_COMPLETE)
return CMD_AGAIN;
- if (ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
+ if (xfer.c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
return CMD_ERR;
}
return CMD_OK;
@@ -1113,11 +1121,11 @@
struct ata_queue * const chq = chp->ch_queue;
KASSERT(chq->queue_active < chq->queue_openings);
- KASSERT((chq->queue_xfers_avail & __BIT(xfer->c_slot)) == 0);
+ KASSERT((chq->active_xfers_used & __BIT(xfer->c_slot)) == 0);
TAILQ_REMOVE(&chq->queue_xfer, xfer, c_xferchain);
TAILQ_INSERT_TAIL(&chq->active_xfers, xfer, c_activechain);
-
+ chq->active_xfers_used |= __BIT(xfer->c_slot);
chq->queue_active++;
}
@@ -1127,12 +1135,13 @@
struct ata_queue * const chq = chp->ch_queue;
KASSERT(chq->queue_active > 0);
- KASSERT((chq->queue_xfers_avail & __BIT(xfer->c_slot)) == 0);
+ KASSERT((chq->active_xfers_used & __BIT(xfer->c_slot)) != 0);
//if ((xfer->c_flags & C_TIMEOU) == 0)
callout_stop(&chp->ch_callout);
TAILQ_REMOVE(&chq->active_xfers, xfer, c_activechain);
+ chq->active_xfers_used &= ~__BIT(xfer->c_slot);
chq->queue_active--;
}
diff -r 3841969bc5c3 -r f066562aba11 sys/dev/ata/atavar.h
--- a/sys/dev/ata/atavar.h Sat Apr 15 12:01:23 2017 +0000
+++ b/sys/dev/ata/atavar.h Sat Apr 15 17:14:11 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: atavar.h,v 1.92.8.3 2017/04/15 12:01:23 jdolecek Exp $ */
+/* $NetBSD: atavar.h,v 1.92.8.4 2017/04/15 17:14:11 jdolecek Exp $ */
/*
* Copyright (c) 1998, 2001 Manuel Bouyer.
@@ -69,6 +69,64 @@
};
/*
+ * ATA/ATAPI commands description
+ *
+ * This structure defines the interface between the ATA/ATAPI device driver
+ * and the controller for short commands. It contains the command's parameter,
+ * the length of data to read/write (if any), and a function to call upon
+ * completion.
+ * If no sleep is allowed, the driver can poll for command completion.
+ * Once the command completed, if the error registered is valid, the flag
+ * AT_ERROR is set and the error register value is copied to r_error .
+ * A separate interface is needed for read/write or ATAPI packet commands
+ * (which need multiple interrupts per commands).
+ */
+struct ata_command {
+ /* ATA parameters */
+ uint64_t r_lba; /* before & after */
+ uint16_t r_count; /* before & after */
+ union {
+ uint16_t r_features; /* before */
+ uint8_t r_error; /* after */
+ };
+ union {
+ uint8_t r_command; /* before */
+ uint8_t r_status; /* after */
+ };
+ uint8_t r_device; /* before & after */
+
+ uint8_t r_st_bmask; /* status register mask to wait for before
+ command */
+ uint8_t r_st_pmask; /* status register mask to wait for after
+ command */
+ volatile uint16_t flags;
+
+#define AT_READ 0x0001 /* There is data to read */
+#define AT_WRITE 0x0002 /* There is data to write (excl. with AT_READ) */
+#define AT_WAIT 0x0008 /* wait in controller code for command completion */
+#define AT_POLL 0x0010 /* poll for command completion (no interrupts) */
+#define AT_DONE 0x0020 /* command is done */
+#define AT_XFDONE 0x0040 /* data xfer is done */
+#define AT_ERROR 0x0080 /* command is done with error */
+#define AT_TIMEOU 0x0100 /* command timed out */
+#define AT_DF 0x0200 /* Drive fault */
+#define AT_RESET 0x0400 /* command terminated by channel reset */
+#define AT_GONE 0x0800 /* command terminated because device is gone */
+#define AT_READREG 0x1000 /* Read registers on completion */
+#define AT_LBA 0x2000 /* LBA28 */
+#define AT_LBA48 0x4000 /* LBA48 */
+
+ int timeout; /* timeout (in ms) */
+ void *data; /* Data buffer address */
+ int bcount; /* number of bytes to transfer */
+ void (*callback)(void *); /* command to call once command completed */
+ void *callback_arg; /* argument passed to *callback() */
+};
+
+/* Forward declaration for ata_xfer */
+struct scsipi_xfer;
+
+/*
* Description of a command to be handled by an ATA controller. These
* commands are queued in a list.
*/
@@ -80,7 +138,6 @@
uint16_t c_drive;
int8_t c_slot; /* queue slot # */
- void *c_cmd; /* private request structure pointer */
void *c_databuf; /* pointer to data buffer */
int c_bcount; /* byte count left */
int c_skip; /* bytes already transferred */
@@ -88,9 +145,13 @@
int c_lenoff; /* offset to c_bcount (ATAPI) */
union {
- struct ata_bio c_bio; /* block I/O context */
+ struct ata_bio c_bio; /* ATA transfer */
+ struct ata_command c_ata_c; /* ATA command */
+ struct scsipi_xfer *c_scsipi; /* SCSI transfer */
} u;
#define c_bio u.c_bio
+#define c_ata_c u.c_ata_c
+#define c_scsipi u.c_scsipi
/* Link on the command queue. */
TAILQ_ENTRY(ata_xfer) c_xferchain;
@@ -127,6 +188,7 @@
int queue_openings; /* max number of active transfers */
#ifdef ATABUS_PRIVATE
TAILQ_HEAD(, ata_xfer) active_xfers; /* active commands */
+ uint32_t active_xfers_used; /* mask of active commands */
uint32_t queue_xfers_avail; /* available xfers mask */
struct ata_xfer queue_xfers[0]; /* xfers */
#endif
@@ -240,61 +302,6 @@
#define ATA_CONFIG_UDMA_OFF 8
/*
- * ATA/ATAPI commands description
- *
- * This structure defines the interface between the ATA/ATAPI device driver
- * and the controller for short commands. It contains the command's parameter,
- * the length of data to read/write (if any), and a function to call upon
- * completion.
- * If no sleep is allowed, the driver can poll for command completion.
- * Once the command completed, if the error registered is valid, the flag
- * AT_ERROR is set and the error register value is copied to r_error .
- * A separate interface is needed for read/write or ATAPI packet commands
Home |
Main Index |
Thread Index |
Old Index