tree 02774c6f35623a27fbefbe1fe7f26f4a0f5fdd32
parent 335eadf2ef6a1122a720aea98e758e5d431da87d
author Pierre Ossman <[EMAIL PROTECTED]> Wed, 07 Sep 2005 05:18:52 -0700
committer Linus Torvalds <[EMAIL PROTECTED]> Thu, 08 Sep 2005 06:57:50 -0700

[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 <[EMAIL PROTECTED]>
Cc: Russell King <[EMAIL PROTECTED]>
Cc: David Brownell <[EMAIL PROTECTED]>
Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>

 drivers/mmc/mmc.c        |   39 +++++++++++++++++++++++----------------
 drivers/mmc/mmc_block.c  |    9 +++++++--
 include/linux/mmc/card.h |    3 +++
 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
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -413,8 +413,7 @@ static void mmc_decode_cid(struct mmc_ca
                card->cid.month                 = UNSTUFF_BITS(resp, 8, 4);
 
                card->cid.year += 2000; /* SD cards year offset */
-       }
-       else {
+       } else {
                /*
                 * The selection of the format here is based upon published
                 * specs from sandisk and from what people have reported.
@@ -494,8 +493,7 @@ static void mmc_decode_csd(struct mmc_ca
                csd->capacity     = (1 + m) << (e + 2);
 
                csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
-       }
-       else {
+       } else {
                /*
                 * We only understand CSD structure v1.1 and v1.2.
                 * v1.2 has extra information in bits 15, 11 and 10.
@@ -738,10 +736,20 @@ static void mmc_discover_cards(struct mm
                        err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
                        if (err != MMC_ERR_NONE)
                                mmc_card_set_dead(card);
-                       else
+                       else {
                                card->rca = cmd.resp[0] >> 16;
-               }
-               else {
+
+                               if (!host->ops->get_ro) {
+                                       printk(KERN_WARNING "%s: host does not "
+                                               "support reading read-only "
+                                               "switch. assuming 
write-enable.\n",
+                                               mmc_hostname(host));
+                               } else {
+                                       if (host->ops->get_ro(host))
+                                               mmc_card_set_readonly(card);
+                               }
+                       }
+               } else {
                        cmd.opcode = MMC_SET_RELATIVE_ADDR;
                        cmd.arg = card->rca << 16;
                        cmd.flags = MMC_RSP_R1;
@@ -833,24 +841,23 @@ static void mmc_setup(struct mmc_host *h
                int err;
                u32 ocr;
 
-               host->mode = MMC_MODE_MMC;
+               host->mode = MMC_MODE_SD;
 
                mmc_power_up(host);
                mmc_idle_cards(host);
 
-               err = mmc_send_op_cond(host, 0, &ocr);
+               err = mmc_send_app_op_cond(host, 0, &ocr);
 
                /*
-                * If we fail to detect any cards then try
-                * searching for SD cards.
+                * If we fail to detect any SD cards then try
+                * searching for MMC cards.
                 */
-               if (err != MMC_ERR_NONE)
-               {
-                       err = mmc_send_app_op_cond(host, 0, &ocr);
+               if (err != MMC_ERR_NONE) {
+                       host->mode = MMC_MODE_MMC;
+
+                       err = mmc_send_op_cond(host, 0, &ocr);
                        if (err != MMC_ERR_NONE)
                                return;
-
-                       host->mode = MMC_MODE_SD;
                }
 
                host->ocr = mmc_select_voltage(host, ocr);
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/mmc_block.c
@@ -95,6 +95,10 @@ static int mmc_blk_open(struct inode *in
                if (md->usage == 2)
                        check_disk_change(inode->i_bdev);
                ret = 0;
+
+               if ((filp->f_mode & FMODE_WRITE) &&
+                       mmc_card_readonly(md->queue.card))
+                       ret = -EROFS;
        }
 
        return ret;
@@ -403,9 +407,10 @@ static int mmc_blk_probe(struct mmc_card
        if (err)
                goto out;
 
-       printk(KERN_INFO "%s: %s %s %dKiB\n",
+       printk(KERN_INFO "%s: %s %s %dKiB %s\n",
                md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
-               (card->csd.capacity << card->csd.read_blkbits) / 1024);
+               (card->csd.capacity << card->csd.read_blkbits) / 1024,
+               mmc_card_readonly(card)?"(ro)":"");
 
        mmc_set_drvdata(card, md);
        add_disk(md->disk);
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -48,6 +48,7 @@ struct mmc_card {
 #define MMC_STATE_DEAD         (1<<1)          /* device no longer in stack */
 #define MMC_STATE_BAD          (1<<2)          /* unrecognised device */
 #define MMC_STATE_SDCARD       (1<<3)          /* is an SD card */
+#define MMC_STATE_READONLY     (1<<4)          /* card is read-only */
        u32                     raw_cid[4];     /* raw card CID */
        u32                     raw_csd[4];     /* raw card CSD */
        struct mmc_cid          cid;            /* card identification */
@@ -58,11 +59,13 @@ struct mmc_card {
 #define mmc_card_dead(c)       ((c)->state & MMC_STATE_DEAD)
 #define mmc_card_bad(c)                ((c)->state & MMC_STATE_BAD)
 #define mmc_card_sd(c)         ((c)->state & MMC_STATE_SDCARD)
+#define mmc_card_readonly(c)   ((c)->state & MMC_STATE_READONLY)
 
 #define mmc_card_set_present(c)        ((c)->state |= MMC_STATE_PRESENT)
 #define mmc_card_set_dead(c)   ((c)->state |= MMC_STATE_DEAD)
 #define mmc_card_set_bad(c)    ((c)->state |= MMC_STATE_BAD)
 #define mmc_card_set_sd(c)     ((c)->state |= MMC_STATE_SDCARD)
+#define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
 
 #define mmc_card_name(c)       ((c)->cid.prod_name)
 #define mmc_card_id(c)         ((c)->dev.bus_id)
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -62,6 +62,7 @@ struct mmc_ios {
 struct mmc_host_ops {
        void    (*request)(struct mmc_host *host, struct mmc_request *req);
        void    (*set_ios)(struct mmc_host *host, struct mmc_ios *ios);
+       int     (*get_ro)(struct mmc_host *host);
 };
 
 struct mmc_card;
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to