Re: [PATCH][MMC][2/6] Secure Digital (SD) support : init

2005-03-05 Thread Pierre Ossman
SD card initialisation.
This patch contains the central parts of the SD support.
The system first tries to detect MMC cards, and if none are found then 
it procedes to look for an SD card. This is incorrect acording to SD 
specifications but I find it odd that MMC is supposed to cope with SD 
commands and not the other way around (since MMC is the older of the 
two). This behaviour is the one Windows uses and has posed no problems 
with any cards tested so far.

It provides flags for the card and host to mark them as SD. The host 
needs to be marked because the MMC layer needs to determine if it should 
send MMC or SD commands at points where no specific card is involved.

A new helper function called mmc_wait_for_app_cmd() is added to handle 
the APP commands which are used frequently with SD.

CID and CSD parsing are extended to handle SD formats.
Index: linux-sd/include/linux/mmc/card.h
===
--- linux-sd/include/linux/mmc/card.h	(revision 135)
+++ linux-sd/include/linux/mmc/card.h	(working copy)
@@ -47,6 +47,7 @@
 #define MMC_STATE_PRESENT	(1<<0)		/* present in sysfs */
 #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 */
 	u32			raw_cid[4];	/* raw card CID */
 	u32			raw_csd[4];	/* raw card CSD */
 	struct mmc_cid		cid;		/* card identification */
@@ -56,10 +57,12 @@
 #define mmc_card_present(c)	((c)->state & MMC_STATE_PRESENT)
 #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_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_name(c)	((c)->cid.prod_name)
 #define mmc_card_id(c)		((c)->dev.bus_id)
Index: linux-sd/include/linux/mmc/mmc.h
===
--- linux-sd/include/linux/mmc/mmc.h	(revision 136)
+++ linux-sd/include/linux/mmc/mmc.h	(working copy)
@@ -88,6 +88,8 @@
 
 extern int mmc_wait_for_req(struct mmc_host *, struct mmc_request *);
 extern int mmc_wait_for_cmd(struct mmc_host *, struct mmc_command *, int);
+extern int mmc_wait_for_app_cmd(struct mmc_host *, unsigned int,
+	struct mmc_command *, int);
 
 extern int __mmc_claim_host(struct mmc_host *host, struct mmc_card *card);
 
Index: linux-sd/include/linux/mmc/host.h
===
--- linux-sd/include/linux/mmc/host.h	(revision 135)
+++ linux-sd/include/linux/mmc/host.h	(working copy)
@@ -79,6 +79,10 @@
 	/* private data */
 	struct mmc_ios		ios;		/* current io bus settings */
 	u32			ocr;		/* the current OCR setting */
+	
+	unsigned int		mode;		/* current card mode of host */
+#define MMC_MODE_MMC		0
+#define MMC_MODE_SD		1
 
 	struct list_head	cards;		/* devices attached to this host */
 
Index: linux-sd/drivers/mmc/mmc.c
===
--- linux-sd/drivers/mmc/mmc.c	(revision 135)
+++ linux-sd/drivers/mmc/mmc.c	(working copy)
@@ -172,8 +172,80 @@
 
 EXPORT_SYMBOL(mmc_wait_for_cmd);
 
+/**
+ *	mmc_wait_for_app_cmd - start an application command and wait for
+ 			   completion
+ *	@host: MMC host to start command
+ *	@rca: RCA to send MMC_APP_CMD to
+ *	@cmd: MMC command to start
+ *	@retries: maximum number of retries
+ *
+ *	Sends a MMC_APP_CMD, checks the card response, sends the command
+ *	in the parameter and waits for it to complete. Return any error
+ *	that occurred while the command was executing.  Do not attempt to
+ *	parse the response.
+ */
+int mmc_wait_for_app_cmd(struct mmc_host *host, unsigned int rca,
+	struct mmc_command *cmd, int retries)
+{
+	struct mmc_request mrq;
+	struct mmc_command appcmd;
+	
+	int i, err;
 
+	BUG_ON(host->card_busy == NULL);
+	BUG_ON(retries < 0);
+	
+	err = MMC_ERR_INVALID;
+	
+	/*
+	 * We have to resend MMC_APP_CMD for each attempt so
+	 * we cannot use the retries field in mmc_command.
+	 */
+	for (i = 0;i <= retries;i++) {
+		memset(, 0, sizeof(struct mmc_request));
 
+		appcmd.opcode = MMC_APP_CMD;
+		appcmd.arg = rca << 16;
+		appcmd.flags = MMC_RSP_R1;
+		appcmd.retries = 0;
+		memset(appcmd.resp, 0, sizeof(appcmd.resp));
+		appcmd.data = NULL;
+		
+		mrq.cmd = 
+		appcmd.data = NULL;
+		
+		mmc_wait_for_req(host, );
+		
+		if (appcmd.error) {
+			err = appcmd.error;
+			continue;
+		}
+		
+		/* Check that card supported application commands */
+		if (!(appcmd.resp[0] & R1_APP_CMD))
+			return MMC_ERR_FAILED;
+
+		memset(, 0, sizeof(struct mmc_request));
+
+		memset(cmd->resp, 0, sizeof(cmd->resp));
+		cmd->retries = 0;
+
+		mrq.cmd = cmd;
+		cmd->data = NULL;
+
+		mmc_wait_for_req(host, );
+		
+		err = 

Re: [PATCH][MMC][2/6] Secure Digital (SD) support : init

2005-03-05 Thread Pierre Ossman
SD card initialisation.
This patch contains the central parts of the SD support.
The system first tries to detect MMC cards, and if none are found then 
it procedes to look for an SD card. This is incorrect acording to SD 
specifications but I find it odd that MMC is supposed to cope with SD 
commands and not the other way around (since MMC is the older of the 
two). This behaviour is the one Windows uses and has posed no problems 
with any cards tested so far.

It provides flags for the card and host to mark them as SD. The host 
needs to be marked because the MMC layer needs to determine if it should 
send MMC or SD commands at points where no specific card is involved.

A new helper function called mmc_wait_for_app_cmd() is added to handle 
the APP commands which are used frequently with SD.

CID and CSD parsing are extended to handle SD formats.
Index: linux-sd/include/linux/mmc/card.h
===
--- linux-sd/include/linux/mmc/card.h	(revision 135)
+++ linux-sd/include/linux/mmc/card.h	(working copy)
@@ -47,6 +47,7 @@
 #define MMC_STATE_PRESENT	(10)		/* present in sysfs */
 #define MMC_STATE_DEAD		(11)		/* device no longer in stack */
 #define MMC_STATE_BAD		(12)		/* unrecognised device */
+#define MMC_STATE_SDCARD	(13)		/* is an SD card */
 	u32			raw_cid[4];	/* raw card CID */
 	u32			raw_csd[4];	/* raw card CSD */
 	struct mmc_cid		cid;		/* card identification */
@@ -56,10 +57,12 @@
 #define mmc_card_present(c)	((c)-state  MMC_STATE_PRESENT)
 #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_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_name(c)	((c)-cid.prod_name)
 #define mmc_card_id(c)		((c)-dev.bus_id)
Index: linux-sd/include/linux/mmc/mmc.h
===
--- linux-sd/include/linux/mmc/mmc.h	(revision 136)
+++ linux-sd/include/linux/mmc/mmc.h	(working copy)
@@ -88,6 +88,8 @@
 
 extern int mmc_wait_for_req(struct mmc_host *, struct mmc_request *);
 extern int mmc_wait_for_cmd(struct mmc_host *, struct mmc_command *, int);
+extern int mmc_wait_for_app_cmd(struct mmc_host *, unsigned int,
+	struct mmc_command *, int);
 
 extern int __mmc_claim_host(struct mmc_host *host, struct mmc_card *card);
 
Index: linux-sd/include/linux/mmc/host.h
===
--- linux-sd/include/linux/mmc/host.h	(revision 135)
+++ linux-sd/include/linux/mmc/host.h	(working copy)
@@ -79,6 +79,10 @@
 	/* private data */
 	struct mmc_ios		ios;		/* current io bus settings */
 	u32			ocr;		/* the current OCR setting */
+	
+	unsigned int		mode;		/* current card mode of host */
+#define MMC_MODE_MMC		0
+#define MMC_MODE_SD		1
 
 	struct list_head	cards;		/* devices attached to this host */
 
Index: linux-sd/drivers/mmc/mmc.c
===
--- linux-sd/drivers/mmc/mmc.c	(revision 135)
+++ linux-sd/drivers/mmc/mmc.c	(working copy)
@@ -172,8 +172,80 @@
 
 EXPORT_SYMBOL(mmc_wait_for_cmd);
 
+/**
+ *	mmc_wait_for_app_cmd - start an application command and wait for
+ 			   completion
+ *	@host: MMC host to start command
+ *	@rca: RCA to send MMC_APP_CMD to
+ *	@cmd: MMC command to start
+ *	@retries: maximum number of retries
+ *
+ *	Sends a MMC_APP_CMD, checks the card response, sends the command
+ *	in the parameter and waits for it to complete. Return any error
+ *	that occurred while the command was executing.  Do not attempt to
+ *	parse the response.
+ */
+int mmc_wait_for_app_cmd(struct mmc_host *host, unsigned int rca,
+	struct mmc_command *cmd, int retries)
+{
+	struct mmc_request mrq;
+	struct mmc_command appcmd;
+	
+	int i, err;
 
+	BUG_ON(host-card_busy == NULL);
+	BUG_ON(retries  0);
+	
+	err = MMC_ERR_INVALID;
+	
+	/*
+	 * We have to resend MMC_APP_CMD for each attempt so
+	 * we cannot use the retries field in mmc_command.
+	 */
+	for (i = 0;i = retries;i++) {
+		memset(mrq, 0, sizeof(struct mmc_request));
 
+		appcmd.opcode = MMC_APP_CMD;
+		appcmd.arg = rca  16;
+		appcmd.flags = MMC_RSP_R1;
+		appcmd.retries = 0;
+		memset(appcmd.resp, 0, sizeof(appcmd.resp));
+		appcmd.data = NULL;
+		
+		mrq.cmd = appcmd;
+		appcmd.data = NULL;
+		
+		mmc_wait_for_req(host, mrq);
+		
+		if (appcmd.error) {
+			err = appcmd.error;
+			continue;
+		}
+		
+		/* Check that card supported application commands */
+		if (!(appcmd.resp[0]  R1_APP_CMD))
+			return MMC_ERR_FAILED;
+
+		memset(mrq, 0, sizeof(struct mmc_request));
+
+		memset(cmd-resp, 0, sizeof(cmd-resp));
+		cmd-retries = 0;
+
+		mrq.cmd = cmd;
+		cmd-data = NULL;
+
+		mmc_wait_for_req(host, mrq);
+		
+		err = cmd-error;
+		if