mirror of
https://git.rtems.org/rtems-libbsd/
synced 2025-10-15 03:17:56 +08:00
Update to FreeBSD head 2018-06-01
Git mirror commit fb63610a69b0eb7f69a201ba05c4c1a7a2739cf9. Update #3472.
This commit is contained in:
@@ -162,34 +162,35 @@ struct mmc_command {
|
||||
#define R1_STATE_PRG 7
|
||||
#define R1_STATE_DIS 8
|
||||
|
||||
/* R4 response (SDIO) */
|
||||
#define R4_IO_NUM_FUNCTIONS(ocr) (((ocr) >> 28) & 0x3)
|
||||
#define R4_IO_MEM_PRESENT (0x1<<27)
|
||||
#define R4_IO_OCR_MASK 0x00fffff0
|
||||
/* R4 responses (SDIO) */
|
||||
#define R4_IO_NUM_FUNCTIONS(ocr) (((ocr) >> 28) & 0x3)
|
||||
#define R4_IO_MEM_PRESENT (0x1 << 27)
|
||||
#define R4_IO_OCR_MASK 0x00fffff0
|
||||
|
||||
/*
|
||||
* R5 responses
|
||||
*
|
||||
* Types (per SD 2.0 standard)
|
||||
*e : error bit
|
||||
*s : status bit
|
||||
*r : detected and set for the actual command response
|
||||
*x : Detected and set during command execution. The host can get
|
||||
* the status by issuing a command with R1 response.
|
||||
* e : error bit
|
||||
* s : status bit
|
||||
* r : detected and set for the actual command response
|
||||
* x : Detected and set during command execution. The host can get
|
||||
* the status by issuing a command with R1 response.
|
||||
*
|
||||
* Clear Condition (per SD 2.0 standard)
|
||||
*a : according to the card current state.
|
||||
*b : always related to the previous command. reception of a valid
|
||||
* command will clear it (with a delay of one command).
|
||||
*c : clear by read
|
||||
* a : according to the card current state.
|
||||
* b : always related to the previous command. reception of a valid
|
||||
* command will clear it (with a delay of one command).
|
||||
* c : clear by read
|
||||
*/
|
||||
#define R5_COM_CRC_ERROR (1u << 15)/* er, b */
|
||||
#define R5_ILLEGAL_COMMAND (1u << 14)/* er, b */
|
||||
#define R5_IO_CURRENT_STATE_MASK (3u << 12)/* s, b */
|
||||
#define R5_IO_CURRENT_STATE(x) (((x) & R5_IO_CURRENT_STATE_MASK) >> 12)
|
||||
#define R5_ERROR (1u << 11)/* erx, c */
|
||||
#define R5_FUNCTION_NUMBER (1u << 9)/* er, c */
|
||||
#define R5_OUT_OF_RANGE (1u << 8)/* er, c */
|
||||
#define R5_COM_CRC_ERROR (1u << 15) /* er, b */
|
||||
#define R5_ILLEGAL_COMMAND (1u << 14) /* er, b */
|
||||
#define R5_IO_CURRENT_STATE_MASK (3u << 12) /* s, b */
|
||||
#define R5_IO_CURRENT_STATE(x) (((x) & R5_IO_CURRENT_STATE_MASK) >> 12)
|
||||
#define R5_ERROR (1u << 11) /* erx, c */
|
||||
#define R5_FUNCTION_NUMBER (1u << 9) /* er, c */
|
||||
#define R5_OUT_OF_RANGE (1u << 8) /* er, c */
|
||||
|
||||
struct mmc_data {
|
||||
size_t len; /* size of the data */
|
||||
size_t xfer_len;
|
||||
@@ -227,7 +228,7 @@ struct mmc_request {
|
||||
#define SD_SEND_RELATIVE_ADDR 3
|
||||
#define MMC_SET_DSR 4
|
||||
#define MMC_SLEEP_AWAKE 5
|
||||
#define IO_SEND_OP_COND 5
|
||||
#define IO_SEND_OP_COND 5
|
||||
#define MMC_SWITCH_FUNC 6
|
||||
#define MMC_SWITCH_FUNC_CMDS 0
|
||||
#define MMC_SWITCH_FUNC_SET 1
|
||||
@@ -318,30 +319,30 @@ struct mmc_request {
|
||||
/* Class 9: I/O cards (sd) */
|
||||
#define SD_IO_RW_DIRECT 52
|
||||
/* CMD52 arguments */
|
||||
#define SD_ARG_CMD52_READ (0<<31)
|
||||
#define SD_ARG_CMD52_WRITE (1<<31)
|
||||
#define SD_ARG_CMD52_FUNC_SHIFT 28
|
||||
#define SD_ARG_CMD52_FUNC_MASK 0x7
|
||||
#define SD_ARG_CMD52_EXCHANGE (1<<27)
|
||||
#define SD_ARG_CMD52_REG_SHIFT 9
|
||||
#define SD_ARG_CMD52_REG_MASK 0x1ffff
|
||||
#define SD_ARG_CMD52_DATA_SHIFT 0
|
||||
#define SD_ARG_CMD52_DATA_MASK 0xff
|
||||
#define SD_R5_DATA(resp) ((resp)[0] & 0xff)
|
||||
#define SD_ARG_CMD52_READ (0 << 31)
|
||||
#define SD_ARG_CMD52_WRITE (1 << 31)
|
||||
#define SD_ARG_CMD52_FUNC_SHIFT 28
|
||||
#define SD_ARG_CMD52_FUNC_MASK 0x7
|
||||
#define SD_ARG_CMD52_EXCHANGE (1 << 27)
|
||||
#define SD_ARG_CMD52_REG_SHIFT 9
|
||||
#define SD_ARG_CMD52_REG_MASK 0x1ffff
|
||||
#define SD_ARG_CMD52_DATA_SHIFT 0
|
||||
#define SD_ARG_CMD52_DATA_MASK 0xff
|
||||
#define SD_R5_DATA(resp) ((resp)[0] & 0xff)
|
||||
|
||||
#define SD_IO_RW_EXTENDED 53
|
||||
/* CMD53 arguments */
|
||||
#define SD_ARG_CMD53_READ (0<<31)
|
||||
#define SD_ARG_CMD53_WRITE (1<<31)
|
||||
#define SD_ARG_CMD53_FUNC_SHIFT 28
|
||||
#define SD_ARG_CMD53_FUNC_MASK 0x7
|
||||
#define SD_ARG_CMD53_BLOCK_MODE (1<<27)
|
||||
#define SD_ARG_CMD53_INCREMENT (1<<26)
|
||||
#define SD_ARG_CMD53_REG_SHIFT 9
|
||||
#define SD_ARG_CMD53_REG_MASK 0x1ffff
|
||||
#define SD_ARG_CMD53_LENGTH_SHIFT 0
|
||||
#define SD_ARG_CMD53_LENGTH_MASK 0x1ff
|
||||
#define SD_ARG_CMD53_LENGTH_MAX 64 /* XXX should be 511? */
|
||||
#define SD_ARG_CMD53_READ (0 << 31)
|
||||
#define SD_ARG_CMD53_WRITE (1 << 31)
|
||||
#define SD_ARG_CMD53_FUNC_SHIFT 28
|
||||
#define SD_ARG_CMD53_FUNC_MASK 0x7
|
||||
#define SD_ARG_CMD53_BLOCK_MODE (1 << 27)
|
||||
#define SD_ARG_CMD53_INCREMENT (1 << 26)
|
||||
#define SD_ARG_CMD53_REG_SHIFT 9
|
||||
#define SD_ARG_CMD53_REG_MASK 0x1ffff
|
||||
#define SD_ARG_CMD53_LENGTH_SHIFT 0
|
||||
#define SD_ARG_CMD53_LENGTH_MASK 0x1ff
|
||||
#define SD_ARG_CMD53_LENGTH_MAX 64 /* XXX should be 511? */
|
||||
|
||||
/* Class 10: Switch function commands */
|
||||
#define SD_SWITCH_FUNC 6
|
||||
@@ -364,6 +365,8 @@ struct mmc_request {
|
||||
/*
|
||||
* EXT_CSD fields
|
||||
*/
|
||||
#define EXT_CSD_FLUSH_CACHE 32 /* W/E */
|
||||
#define EXT_CSD_CACHE_CTRL 33 /* R/W/E */
|
||||
#define EXT_CSD_EXT_PART_ATTR 52 /* R/W, 2 bytes */
|
||||
#define EXT_CSD_ENH_START_ADDR 136 /* R/W, 4 bytes */
|
||||
#define EXT_CSD_ENH_SIZE_MULT 140 /* R/W, 3 bytes */
|
||||
@@ -397,12 +400,19 @@ struct mmc_request {
|
||||
#define EXT_CSD_PWR_CL_200_360 237 /* RO */
|
||||
#define EXT_CSD_PWR_CL_52_195_DDR 238 /* RO */
|
||||
#define EXT_CSD_PWR_CL_52_360_DDR 239 /* RO */
|
||||
#define EXT_CSD_CACHE_FLUSH_POLICY 249 /* RO */
|
||||
#define EXT_CSD_GEN_CMD6_TIME 248 /* RO */
|
||||
#define EXT_CSD_CACHE_SIZE 249 /* RO, 4 bytes */
|
||||
#define EXT_CSD_PWR_CL_200_360_DDR 253 /* RO */
|
||||
|
||||
/*
|
||||
* EXT_CSD field definitions
|
||||
*/
|
||||
#define EXT_CSD_FLUSH_CACHE_FLUSH 0x01
|
||||
#define EXT_CSD_FLUSH_CACHE_BARRIER 0x02
|
||||
|
||||
#define EXT_CSD_CACHE_CTRL_CACHE_EN 0x01
|
||||
|
||||
#define EXT_CSD_EXT_PART_ATTR_DEFAULT 0x0
|
||||
#define EXT_CSD_EXT_PART_ATTR_SYSTEMCODE 0x1
|
||||
#define EXT_CSD_EXT_PART_ATTR_NPERSISTENT 0x2
|
||||
@@ -482,6 +492,8 @@ struct mmc_request {
|
||||
#define EXT_CSD_SEC_FEATURE_SUPPORT_GB_CL_EN 0x10
|
||||
#define EXT_CSD_SEC_FEATURE_SUPPORT_SANITIZE 0x40
|
||||
|
||||
#define EXT_CSD_CACHE_FLUSH_POLICY_FIFO 0x01
|
||||
|
||||
/*
|
||||
* Vendor specific EXT_CSD fields
|
||||
*/
|
||||
@@ -533,50 +545,50 @@ struct mmc_request {
|
||||
/*
|
||||
* SDIO Direct & Extended I/O
|
||||
*/
|
||||
#define SD_IO_RW_WR (1u << 31)
|
||||
#define SD_IO_RW_FUNC(x) (((x) & 0x7) << 28)
|
||||
#define SD_IO_RW_RAW (1u << 27)
|
||||
#define SD_IO_RW_INCR (1u << 26)
|
||||
#define SD_IO_RW_ADR(x) (((x) & 0x1FFFF) << 9)
|
||||
#define SD_IO_RW_DAT(x) (((x) & 0xFF) << 0)
|
||||
#define SD_IO_RW_LEN(x) (((x) & 0xFF) << 0)
|
||||
#define SD_IO_RW_WR (1u << 31)
|
||||
#define SD_IO_RW_FUNC(x) (((x) & 0x7) << 28)
|
||||
#define SD_IO_RW_RAW (1u << 27)
|
||||
#define SD_IO_RW_INCR (1u << 26)
|
||||
#define SD_IO_RW_ADR(x) (((x) & 0x1FFFF) << 9)
|
||||
#define SD_IO_RW_DAT(x) (((x) & 0xFF) << 0)
|
||||
#define SD_IO_RW_LEN(x) (((x) & 0xFF) << 0)
|
||||
|
||||
#define SD_IOE_RW_LEN(x) (((x) & 0x1FF) << 0)
|
||||
#define SD_IOE_RW_BLK (1u << 27)
|
||||
#define SD_IOE_RW_LEN(x) (((x) & 0x1FF) << 0)
|
||||
#define SD_IOE_RW_BLK (1u << 27)
|
||||
|
||||
/* Card Common Control Registers (CCCR) */
|
||||
#define SD_IO_CCCR_START 0x00000
|
||||
#define SD_IO_CCCR_SIZE 0x100
|
||||
#define SD_IO_CCCR_FN_ENABLE 0x02
|
||||
#define SD_IO_CCCR_FN_READY 0x03
|
||||
#define SD_IO_CCCR_INT_ENABLE 0x04
|
||||
#define SD_IO_CCCR_INT_PENDING 0x05
|
||||
#define SD_IO_CCCR_CTL 0x06
|
||||
#define CCCR_CTL_RES (1<<3)
|
||||
#define SD_IO_CCCR_BUS_WIDTH 0x07
|
||||
#define CCCR_BUS_WIDTH_4 (1<<1)
|
||||
#define CCCR_BUS_WIDTH_1 (1<<0)
|
||||
#define SD_IO_CCCR_CARDCAP 0x08
|
||||
#define SD_IO_CCCR_CISPTR 0x09 /* XXX 9-10, 10-11, or 9-12 */
|
||||
#define SD_IO_CCCR_START 0x00000
|
||||
#define SD_IO_CCCR_SIZE 0x100
|
||||
#define SD_IO_CCCR_FN_ENABLE 0x02
|
||||
#define SD_IO_CCCR_FN_READY 0x03
|
||||
#define SD_IO_CCCR_INT_ENABLE 0x04
|
||||
#define SD_IO_CCCR_INT_PENDING 0x05
|
||||
#define SD_IO_CCCR_CTL 0x06
|
||||
#define CCCR_CTL_RES (1 << 3)
|
||||
#define SD_IO_CCCR_BUS_WIDTH 0x07
|
||||
#define CCCR_BUS_WIDTH_4 (1 << 1)
|
||||
#define CCCR_BUS_WIDTH_1 (1 << 0)
|
||||
#define SD_IO_CCCR_CARDCAP 0x08
|
||||
#define SD_IO_CCCR_CISPTR 0x09 /* XXX 9-10, 10-11, or 9-12 */
|
||||
|
||||
/* Function Basic Registers (FBR) */
|
||||
#define SD_IO_FBR_START 0x00100
|
||||
#define SD_IO_FBR_SIZE 0x00700
|
||||
#define SD_IO_FBR_START 0x00100
|
||||
#define SD_IO_FBR_SIZE 0x00700
|
||||
|
||||
/* Card Information Structure (CIS) */
|
||||
#define SD_IO_CIS_START 0x01000
|
||||
#define SD_IO_CIS_SIZE 0x17000
|
||||
#define SD_IO_CIS_START 0x01000
|
||||
#define SD_IO_CIS_SIZE 0x17000
|
||||
|
||||
/* CIS tuple codes (based on PC Card 16) */
|
||||
#define SD_IO_CISTPL_VERS_1 0x15
|
||||
#define SD_IO_CISTPL_MANFID 0x20
|
||||
#define SD_IO_CISTPL_FUNCID 0x21
|
||||
#define SD_IO_CISTPL_FUNCE 0x22
|
||||
#define SD_IO_CISTPL_END 0xff
|
||||
#define SD_IO_CISTPL_VERS_1 0x15
|
||||
#define SD_IO_CISTPL_MANFID 0x20
|
||||
#define SD_IO_CISTPL_FUNCID 0x21
|
||||
#define SD_IO_CISTPL_FUNCE 0x22
|
||||
#define SD_IO_CISTPL_END 0xff
|
||||
|
||||
/* CISTPL_FUNCID codes */
|
||||
/* OpenBSD incorrectly defines 0x0c as FUNCTION_WLAN */
|
||||
/* #define SDMMC_FUNCTION_WLAN 0x0c */
|
||||
/* #define SDMMC_FUNCTION_WLAN 0x0c */
|
||||
|
||||
/* OCR bits */
|
||||
|
||||
|
@@ -71,7 +71,9 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/priv.h>
|
||||
#include <sys/slicer.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <geom/geom.h>
|
||||
@@ -142,6 +144,8 @@ struct mmcsd_softc {
|
||||
uint32_t flags;
|
||||
#define MMCSD_INAND_CMD38 0x0001
|
||||
#define MMCSD_USE_TRIM 0x0002
|
||||
#define MMCSD_FLUSH_CACHE 0x0004
|
||||
#define MMCSD_DIRTY 0x0008
|
||||
uint32_t cmd6_time; /* Generic switch timeout [us] */
|
||||
uint32_t part_time; /* Partition switch timeout [us] */
|
||||
off_t enh_base; /* Enhanced user data area slice base ... */
|
||||
@@ -166,12 +170,19 @@ static const char * const errmsg[] =
|
||||
"NO MEMORY"
|
||||
};
|
||||
|
||||
static SYSCTL_NODE(_hw, OID_AUTO, mmcsd, CTLFLAG_RD, NULL, "mmcsd driver");
|
||||
|
||||
static int mmcsd_cache = 1;
|
||||
SYSCTL_INT(_hw_mmcsd, OID_AUTO, cache, CTLFLAG_RDTUN, &mmcsd_cache, 0,
|
||||
"Device R/W cache enabled if present");
|
||||
|
||||
#define LOG_PPS 5 /* Log no more than 5 errors per second. */
|
||||
|
||||
/* bus entry points */
|
||||
static int mmcsd_attach(device_t dev);
|
||||
static int mmcsd_detach(device_t dev);
|
||||
static int mmcsd_probe(device_t dev);
|
||||
static int mmcsd_shutdown(device_t dev);
|
||||
|
||||
#ifndef __rtems__
|
||||
/* disk routines */
|
||||
@@ -181,7 +192,6 @@ static int mmcsd_dump(void *arg, void *virtual, vm_offset_t physical,
|
||||
static int mmcsd_getattr(struct bio *);
|
||||
static int mmcsd_ioctl_disk(struct disk *disk, u_long cmd, void *data,
|
||||
int fflag, struct thread *td);
|
||||
static int mmcsd_open(struct disk *dp);
|
||||
static void mmcsd_strategy(struct bio *bp);
|
||||
static void mmcsd_task(void *arg);
|
||||
#endif /* __rtems__ */
|
||||
@@ -197,8 +207,12 @@ static int mmcsd_bus_bit_width(device_t dev);
|
||||
static daddr_t mmcsd_delete(struct mmcsd_part *part, struct bio *bp);
|
||||
#endif /* __rtems__ */
|
||||
static const char *mmcsd_errmsg(int e);
|
||||
#ifndef __rtems__
|
||||
static int mmcsd_flush_cache(struct mmcsd_softc *sc);
|
||||
#endif /* __rtems__ */
|
||||
static const char *mmcsd_errmsg(int e);
|
||||
static int mmcsd_ioctl(struct mmcsd_part *part, u_long cmd, void *data,
|
||||
int fflag);
|
||||
int fflag, struct thread *td);
|
||||
static int mmcsd_ioctl_cmd(struct mmcsd_part *part, struct mmc_ioc_cmd *mic,
|
||||
int fflag);
|
||||
static uintmax_t mmcsd_pretty_size(off_t size, char *unit);
|
||||
@@ -522,6 +536,31 @@ mmcsd_attach(device_t dev)
|
||||
*/
|
||||
rev = ext_csd[EXT_CSD_REV];
|
||||
|
||||
/*
|
||||
* With revision 1.5 (MMC v4.5, EXT_CSD_REV == 6) and later, take
|
||||
* advantage of the device R/W cache if present and useage is not
|
||||
* disabled.
|
||||
*/
|
||||
if (rev >= 6 && mmcsd_cache != 0) {
|
||||
size = ext_csd[EXT_CSD_CACHE_SIZE] |
|
||||
ext_csd[EXT_CSD_CACHE_SIZE + 1] << 8 |
|
||||
ext_csd[EXT_CSD_CACHE_SIZE + 2] << 16 |
|
||||
ext_csd[EXT_CSD_CACHE_SIZE + 3] << 24;
|
||||
if (bootverbose)
|
||||
device_printf(dev, "cache size %juKB\n", size);
|
||||
if (size > 0) {
|
||||
MMCBUS_ACQUIRE_BUS(mmcbus, dev);
|
||||
err = mmc_switch(mmcbus, dev, sc->rca,
|
||||
EXT_CSD_CMD_SET_NORMAL, EXT_CSD_CACHE_CTRL,
|
||||
EXT_CSD_CACHE_CTRL_CACHE_EN, sc->cmd6_time, true);
|
||||
MMCBUS_RELEASE_BUS(mmcbus, dev);
|
||||
if (err != MMC_ERR_NONE)
|
||||
device_printf(dev, "failed to enable cache\n");
|
||||
else
|
||||
sc->flags |= MMCSD_FLUSH_CACHE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Ignore user-creatable enhanced user data area and general purpose
|
||||
* partitions partitions as long as partitioning hasn't been finished.
|
||||
@@ -734,7 +773,6 @@ mmcsd_add_part(struct mmcsd_softc *sc, u_int type, const char *name, u_int cnt,
|
||||
|
||||
#ifndef __rtems__
|
||||
d = part->disk = disk_alloc();
|
||||
d->d_open = mmcsd_open;
|
||||
d->d_close = mmcsd_close;
|
||||
d->d_strategy = mmcsd_strategy;
|
||||
d->d_ioctl = mmcsd_ioctl_disk;
|
||||
@@ -748,6 +786,8 @@ mmcsd_add_part(struct mmcsd_softc *sc, u_int type, const char *name, u_int cnt,
|
||||
d->d_stripesize = sc->erase_sector * d->d_sectorsize;
|
||||
d->d_unit = cnt;
|
||||
d->d_flags = DISKFLAG_CANDELETE;
|
||||
if ((sc->flags & MMCSD_FLUSH_CACHE) != 0)
|
||||
d->d_flags |= DISKFLAG_CANFLUSHCACHE;
|
||||
d->d_delmaxsize = mmc_get_erase_sector(dev) * d->d_sectorsize;
|
||||
strlcpy(d->d_ident, mmc_get_card_sn_string(dev),
|
||||
sizeof(d->d_ident));
|
||||
@@ -908,6 +948,22 @@ mmcsd_detach(device_t dev)
|
||||
free(part, M_DEVBUF);
|
||||
}
|
||||
}
|
||||
if (mmcsd_flush_cache(sc) != MMC_ERR_NONE)
|
||||
device_printf(dev, "failed to flush cache\n");
|
||||
#else /* __rtems__ */
|
||||
BSD_PANIC("FIXME");
|
||||
#endif /* __rtems__ */
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
mmcsd_shutdown(device_t dev)
|
||||
{
|
||||
#ifndef __rtems__
|
||||
struct mmcsd_softc *sc = device_get_softc(dev);
|
||||
|
||||
if (mmcsd_flush_cache(sc) != MMC_ERR_NONE)
|
||||
device_printf(dev, "failed to flush cache\n");
|
||||
#else /* __rtems__ */
|
||||
BSD_PANIC("FIXME");
|
||||
#endif /* __rtems__ */
|
||||
@@ -947,6 +1003,8 @@ mmcsd_suspend(device_t dev)
|
||||
MMCSD_IOCTL_UNLOCK(part);
|
||||
}
|
||||
}
|
||||
if (mmcsd_flush_cache(sc) != MMC_ERR_NONE)
|
||||
device_printf(dev, "failed to flush cache\n");
|
||||
#else /* __rtems__ */
|
||||
BSD_PANIC("FIXME");
|
||||
#endif /* __rtems__ */
|
||||
@@ -989,16 +1047,15 @@ mmcsd_resume(device_t dev)
|
||||
|
||||
#ifndef __rtems__
|
||||
static int
|
||||
mmcsd_open(struct disk *dp __unused)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
mmcsd_close(struct disk *dp __unused)
|
||||
mmcsd_close(struct disk *dp)
|
||||
{
|
||||
struct mmcsd_softc *sc;
|
||||
|
||||
if ((dp->d_flags & DISKFLAG_OPEN) != 0) {
|
||||
sc = ((struct mmcsd_part *)dp->d_drv1)->sc;
|
||||
if (mmcsd_flush_cache(sc) != MMC_ERR_NONE)
|
||||
device_printf(sc->dev, "failed to flush cache\n");
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -1022,24 +1079,25 @@ mmcsd_strategy(struct bio *bp)
|
||||
|
||||
static int
|
||||
mmcsd_ioctl_rpmb(struct cdev *dev, u_long cmd, caddr_t data,
|
||||
int fflag, struct thread *td __unused)
|
||||
int fflag, struct thread *td)
|
||||
{
|
||||
|
||||
return (mmcsd_ioctl(dev->si_drv1, cmd, data, fflag));
|
||||
return (mmcsd_ioctl(dev->si_drv1, cmd, data, fflag, td));
|
||||
}
|
||||
|
||||
#ifndef __rtems__
|
||||
static int
|
||||
mmcsd_ioctl_disk(struct disk *disk, u_long cmd, void *data, int fflag,
|
||||
struct thread *td __unused)
|
||||
struct thread *td)
|
||||
{
|
||||
|
||||
return (mmcsd_ioctl(disk->d_drv1, cmd, data, fflag));
|
||||
return (mmcsd_ioctl(disk->d_drv1, cmd, data, fflag, td));
|
||||
}
|
||||
#endif /* __rtems__ */
|
||||
|
||||
static int
|
||||
mmcsd_ioctl(struct mmcsd_part *part, u_long cmd, void *data, int fflag)
|
||||
mmcsd_ioctl(struct mmcsd_part *part, u_long cmd, void *data, int fflag,
|
||||
struct thread *td)
|
||||
{
|
||||
struct mmc_ioc_cmd *mic;
|
||||
struct mmc_ioc_multi_cmd *mimc;
|
||||
@@ -1049,6 +1107,10 @@ mmcsd_ioctl(struct mmcsd_part *part, u_long cmd, void *data, int fflag)
|
||||
if ((fflag & FREAD) == 0)
|
||||
return (EBADF);
|
||||
|
||||
err = priv_check(td, PRIV_DRIVER);
|
||||
if (err != 0)
|
||||
return (err);
|
||||
|
||||
err = 0;
|
||||
switch (cmd) {
|
||||
case MMC_IOC_CMD:
|
||||
@@ -1190,6 +1252,8 @@ mmcsd_ioctl_cmd(struct mmcsd_part *part, struct mmc_ioc_cmd *mic, int fflag)
|
||||
if (err != MMC_ERR_NONE)
|
||||
goto switch_back;
|
||||
}
|
||||
if (mic->write_flag != 0)
|
||||
sc->flags |= MMCSD_DIRTY;
|
||||
if (mic->is_acmd != 0)
|
||||
(void)mmc_wait_for_app_cmd(mmcbus, dev, rca, &cmd, 0);
|
||||
else
|
||||
@@ -1405,6 +1469,7 @@ mmcsd_rw(struct mmcsd_part *part, struct bio *bp)
|
||||
else
|
||||
cmd.opcode = MMC_READ_SINGLE_BLOCK;
|
||||
} else {
|
||||
sc->flags |= MMCSD_DIRTY;
|
||||
if (numblocks > 1)
|
||||
cmd.opcode = MMC_WRITE_MULTIPLE_BLOCK;
|
||||
else
|
||||
@@ -1590,13 +1655,18 @@ mmcsd_dump(void *arg, void *virtual, vm_offset_t physical, off_t offset,
|
||||
device_t dev, mmcbus;
|
||||
int err;
|
||||
|
||||
/* length zero is special and really means flush buffers to media */
|
||||
if (!length)
|
||||
return (0);
|
||||
|
||||
disk = arg;
|
||||
part = disk->d_drv1;
|
||||
sc = part->sc;
|
||||
|
||||
/* length zero is special and really means flush buffers to media */
|
||||
if (length == 0) {
|
||||
err = mmcsd_flush_cache(sc);
|
||||
if (err != MMC_ERR_NONE)
|
||||
return (EIO);
|
||||
return (0);
|
||||
}
|
||||
|
||||
dev = sc->dev;
|
||||
mmcbus = sc->mmcbus;
|
||||
|
||||
@@ -1646,6 +1716,14 @@ mmcsd_task(void *arg)
|
||||
"mmcsd disk jobqueue", 0);
|
||||
} while (bp == NULL);
|
||||
MMCSD_DISK_UNLOCK(part);
|
||||
if (__predict_false(bp->bio_cmd == BIO_FLUSH)) {
|
||||
if (mmcsd_flush_cache(sc) != MMC_ERR_NONE) {
|
||||
bp->bio_error = EIO;
|
||||
bp->bio_flags |= BIO_ERROR;
|
||||
}
|
||||
biodone(bp);
|
||||
continue;
|
||||
}
|
||||
if (bp->bio_cmd != BIO_READ && part->ro) {
|
||||
bp->bio_error = EROFS;
|
||||
bp->bio_resid = bp->bio_bcount;
|
||||
@@ -1704,10 +1782,37 @@ mmcsd_bus_bit_width(device_t dev)
|
||||
return (8);
|
||||
}
|
||||
|
||||
#ifndef __rtems__
|
||||
static int
|
||||
mmcsd_flush_cache(struct mmcsd_softc *sc)
|
||||
{
|
||||
device_t dev, mmcbus;
|
||||
int err;
|
||||
|
||||
if ((sc->flags & MMCSD_FLUSH_CACHE) == 0)
|
||||
return (MMC_ERR_NONE);
|
||||
|
||||
dev = sc->dev;
|
||||
mmcbus = sc->mmcbus;
|
||||
MMCBUS_ACQUIRE_BUS(mmcbus, dev);
|
||||
if ((sc->flags & MMCSD_DIRTY) == 0) {
|
||||
MMCBUS_RELEASE_BUS(mmcbus, dev);
|
||||
return (MMC_ERR_NONE);
|
||||
}
|
||||
err = mmc_switch(mmcbus, dev, sc->rca, EXT_CSD_CMD_SET_NORMAL,
|
||||
EXT_CSD_FLUSH_CACHE, EXT_CSD_FLUSH_CACHE_FLUSH, 60 * 1000, true);
|
||||
if (err == MMC_ERR_NONE)
|
||||
sc->flags &= ~MMCSD_DIRTY;
|
||||
MMCBUS_RELEASE_BUS(mmcbus, dev);
|
||||
return (err);
|
||||
}
|
||||
#endif /* __rtems__ */
|
||||
|
||||
static device_method_t mmcsd_methods[] = {
|
||||
DEVMETHOD(device_probe, mmcsd_probe),
|
||||
DEVMETHOD(device_attach, mmcsd_attach),
|
||||
DEVMETHOD(device_detach, mmcsd_detach),
|
||||
DEVMETHOD(device_shutdown, mmcsd_shutdown),
|
||||
DEVMETHOD(device_suspend, mmcsd_suspend),
|
||||
DEVMETHOD(device_resume, mmcsd_resume),
|
||||
DEVMETHOD_END
|
||||
|
Reference in New Issue
Block a user