diff options
author | Pierre Ossman <drzeus-list@drzeus.cx> | 2005-09-06 18:18:52 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-07 19:57:50 -0400 |
commit | a00fc09029f02ca833cf90e5d5625f08c4ac4f51 (patch) | |
tree | 02774c6f35623a27fbefbe1fe7f26f4a0f5fdd32 | |
parent | 335eadf2ef6a1122a720aea98e758e5d431da87d (diff) |
[PATCH] sd: read-only switch
Support for the read-only switch on SD cards which must be enforced by the
host.
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Cc: Russell King <rmk@arm.linux.org.uk>
Cc: David Brownell <david-b@pacbell.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | drivers/mmc/mmc.c | 39 | ||||
-rw-r--r-- | drivers/mmc/mmc_block.c | 9 | ||||
-rw-r--r-- | include/linux/mmc/card.h | 3 | ||||
-rw-r--r-- | include/linux/mmc/host.h | 1 |
4 files changed, 34 insertions, 18 deletions
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 294961a102ca..725c6ad3eb64 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c | |||
@@ -413,8 +413,7 @@ static void mmc_decode_cid(struct mmc_card *card) | |||
413 | card->cid.month = UNSTUFF_BITS(resp, 8, 4); | 413 | card->cid.month = UNSTUFF_BITS(resp, 8, 4); |
414 | 414 | ||
415 | card->cid.year += 2000; /* SD cards year offset */ | 415 | card->cid.year += 2000; /* SD cards year offset */ |
416 | } | 416 | } else { |
417 | else { | ||
418 | /* | 417 | /* |
419 | * The selection of the format here is based upon published | 418 | * The selection of the format here is based upon published |
420 | * specs from sandisk and from what people have reported. | 419 | * specs from sandisk and from what people have reported. |
@@ -494,8 +493,7 @@ static void mmc_decode_csd(struct mmc_card *card) | |||
494 | csd->capacity = (1 + m) << (e + 2); | 493 | csd->capacity = (1 + m) << (e + 2); |
495 | 494 | ||
496 | csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4); | 495 | csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4); |
497 | } | 496 | } else { |
498 | else { | ||
499 | /* | 497 | /* |
500 | * We only understand CSD structure v1.1 and v1.2. | 498 | * We only understand CSD structure v1.1 and v1.2. |
501 | * v1.2 has extra information in bits 15, 11 and 10. | 499 | * v1.2 has extra information in bits 15, 11 and 10. |
@@ -738,10 +736,20 @@ static void mmc_discover_cards(struct mmc_host *host) | |||
738 | err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); | 736 | err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); |
739 | if (err != MMC_ERR_NONE) | 737 | if (err != MMC_ERR_NONE) |
740 | mmc_card_set_dead(card); | 738 | mmc_card_set_dead(card); |
741 | else | 739 | else { |
742 | card->rca = cmd.resp[0] >> 16; | 740 | card->rca = cmd.resp[0] >> 16; |
743 | } | 741 | |
744 | else { | 742 | if (!host->ops->get_ro) { |
743 | printk(KERN_WARNING "%s: host does not " | ||
744 | "support reading read-only " | ||
745 | "switch. assuming write-enable.\n", | ||
746 | mmc_hostname(host)); | ||
747 | } else { | ||
748 | if (host->ops->get_ro(host)) | ||
749 | mmc_card_set_readonly(card); | ||
750 | } | ||
751 | } | ||
752 | } else { | ||
745 | cmd.opcode = MMC_SET_RELATIVE_ADDR; | 753 | cmd.opcode = MMC_SET_RELATIVE_ADDR; |
746 | cmd.arg = card->rca << 16; | 754 | cmd.arg = card->rca << 16; |
747 | cmd.flags = MMC_RSP_R1; | 755 | cmd.flags = MMC_RSP_R1; |
@@ -833,24 +841,23 @@ static void mmc_setup(struct mmc_host *host) | |||
833 | int err; | 841 | int err; |
834 | u32 ocr; | 842 | u32 ocr; |
835 | 843 | ||
836 | host->mode = MMC_MODE_MMC; | 844 | host->mode = MMC_MODE_SD; |
837 | 845 | ||
838 | mmc_power_up(host); | 846 | mmc_power_up(host); |
839 | mmc_idle_cards(host); | 847 | mmc_idle_cards(host); |
840 | 848 | ||
841 | err = mmc_send_op_cond(host, 0, &ocr); | 849 | err = mmc_send_app_op_cond(host, 0, &ocr); |
842 | 850 | ||
843 | /* | 851 | /* |
844 | * If we fail to detect any cards then try | 852 | * If we fail to detect any SD cards then try |
845 | * searching for SD cards. | 853 | * searching for MMC cards. |
846 | */ | 854 | */ |
847 | if (err != MMC_ERR_NONE) | 855 | if (err != MMC_ERR_NONE) { |
848 | { | 856 | host->mode = MMC_MODE_MMC; |
849 | err = mmc_send_app_op_cond(host, 0, &ocr); | 857 | |
858 | err = mmc_send_op_cond(host, 0, &ocr); | ||
850 | if (err != MMC_ERR_NONE) | 859 | if (err != MMC_ERR_NONE) |
851 | return; | 860 | return; |
852 | |||
853 | host->mode = MMC_MODE_SD; | ||
854 | } | 861 | } |
855 | 862 | ||
856 | host->ocr = mmc_select_voltage(host, ocr); | 863 | host->ocr = mmc_select_voltage(host, ocr); |
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c index d4eee99c2bf6..fa83f15fdf16 100644 --- a/drivers/mmc/mmc_block.c +++ b/drivers/mmc/mmc_block.c | |||
@@ -95,6 +95,10 @@ static int mmc_blk_open(struct inode *inode, struct file *filp) | |||
95 | if (md->usage == 2) | 95 | if (md->usage == 2) |
96 | check_disk_change(inode->i_bdev); | 96 | check_disk_change(inode->i_bdev); |
97 | ret = 0; | 97 | ret = 0; |
98 | |||
99 | if ((filp->f_mode & FMODE_WRITE) && | ||
100 | mmc_card_readonly(md->queue.card)) | ||
101 | ret = -EROFS; | ||
98 | } | 102 | } |
99 | 103 | ||
100 | return ret; | 104 | return ret; |
@@ -403,9 +407,10 @@ static int mmc_blk_probe(struct mmc_card *card) | |||
403 | if (err) | 407 | if (err) |
404 | goto out; | 408 | goto out; |
405 | 409 | ||
406 | printk(KERN_INFO "%s: %s %s %dKiB\n", | 410 | printk(KERN_INFO "%s: %s %s %dKiB %s\n", |
407 | md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), | 411 | md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), |
408 | (card->csd.capacity << card->csd.read_blkbits) / 1024); | 412 | (card->csd.capacity << card->csd.read_blkbits) / 1024, |
413 | mmc_card_readonly(card)?"(ro)":""); | ||
409 | 414 | ||
410 | mmc_set_drvdata(card, md); | 415 | mmc_set_drvdata(card, md); |
411 | add_disk(md->disk); | 416 | add_disk(md->disk); |
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 538e8c86336c..0e9ec01b9c5b 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h | |||
@@ -48,6 +48,7 @@ struct mmc_card { | |||
48 | #define MMC_STATE_DEAD (1<<1) /* device no longer in stack */ | 48 | #define MMC_STATE_DEAD (1<<1) /* device no longer in stack */ |
49 | #define MMC_STATE_BAD (1<<2) /* unrecognised device */ | 49 | #define MMC_STATE_BAD (1<<2) /* unrecognised device */ |
50 | #define MMC_STATE_SDCARD (1<<3) /* is an SD card */ | 50 | #define MMC_STATE_SDCARD (1<<3) /* is an SD card */ |
51 | #define MMC_STATE_READONLY (1<<4) /* card is read-only */ | ||
51 | u32 raw_cid[4]; /* raw card CID */ | 52 | u32 raw_cid[4]; /* raw card CID */ |
52 | u32 raw_csd[4]; /* raw card CSD */ | 53 | u32 raw_csd[4]; /* raw card CSD */ |
53 | struct mmc_cid cid; /* card identification */ | 54 | struct mmc_cid cid; /* card identification */ |
@@ -58,11 +59,13 @@ struct mmc_card { | |||
58 | #define mmc_card_dead(c) ((c)->state & MMC_STATE_DEAD) | 59 | #define mmc_card_dead(c) ((c)->state & MMC_STATE_DEAD) |
59 | #define mmc_card_bad(c) ((c)->state & MMC_STATE_BAD) | 60 | #define mmc_card_bad(c) ((c)->state & MMC_STATE_BAD) |
60 | #define mmc_card_sd(c) ((c)->state & MMC_STATE_SDCARD) | 61 | #define mmc_card_sd(c) ((c)->state & MMC_STATE_SDCARD) |
62 | #define mmc_card_readonly(c) ((c)->state & MMC_STATE_READONLY) | ||
61 | 63 | ||
62 | #define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT) | 64 | #define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT) |
63 | #define mmc_card_set_dead(c) ((c)->state |= MMC_STATE_DEAD) | 65 | #define mmc_card_set_dead(c) ((c)->state |= MMC_STATE_DEAD) |
64 | #define mmc_card_set_bad(c) ((c)->state |= MMC_STATE_BAD) | 66 | #define mmc_card_set_bad(c) ((c)->state |= MMC_STATE_BAD) |
65 | #define mmc_card_set_sd(c) ((c)->state |= MMC_STATE_SDCARD) | 67 | #define mmc_card_set_sd(c) ((c)->state |= MMC_STATE_SDCARD) |
68 | #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY) | ||
66 | 69 | ||
67 | #define mmc_card_name(c) ((c)->cid.prod_name) | 70 | #define mmc_card_name(c) ((c)->cid.prod_name) |
68 | #define mmc_card_id(c) ((c)->dev.bus_id) | 71 | #define mmc_card_id(c) ((c)->dev.bus_id) |
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 845020d90c60..8c5f71376e41 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h | |||
@@ -62,6 +62,7 @@ struct mmc_ios { | |||
62 | struct mmc_host_ops { | 62 | struct mmc_host_ops { |
63 | void (*request)(struct mmc_host *host, struct mmc_request *req); | 63 | void (*request)(struct mmc_host *host, struct mmc_request *req); |
64 | void (*set_ios)(struct mmc_host *host, struct mmc_ios *ios); | 64 | void (*set_ios)(struct mmc_host *host, struct mmc_ios *ios); |
65 | int (*get_ro)(struct mmc_host *host); | ||
65 | }; | 66 | }; |
66 | 67 | ||
67 | struct mmc_card; | 68 | struct mmc_card; |