dslinux/linux-2.6.x/drivers/mmc scsd_c.c scsd_s.S

amadeus dslinux_amadeus at user.in-berlin.de
Wed Aug 30 14:05:28 CEST 2006


Update of /cvsroot/dslinux/dslinux/linux-2.6.x/drivers/mmc
In directory antilope:/tmp/cvs-serv4723/linux-2.6.x/drivers/mmc

Modified Files:
	scsd_c.c scsd_s.S 
Log Message:
Optimizing switched SD driver

Index: scsd_c.c
===================================================================
RCS file: /cvsroot/dslinux/dslinux/linux-2.6.x/drivers/mmc/scsd_c.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- scsd_c.c	27 Aug 2006 16:31:27 -0000	1.5
+++ scsd_c.c	30 Aug 2006 12:05:26 -0000	1.6
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/mmc/scsd_c.c - Nintendo DS SD driver
+ *  linux/drivers/mmc/scsd_c.c - Supercard SD driver
  *
  *  Copyright (C) 2006 Amadeus, All Rights Reserved.
  *  Based on the old non-mmc driver by by Jean-Pierre Thomasset.
@@ -48,7 +48,7 @@
 #define BLOCKSIZE 	512
 
 #define DRIVER_NAME	"scsd"
-#define DRIVER_VERSION	"1.1.2"
+#define DRIVER_VERSION	"1.1.3"
 
 /*****************************************************************************/
 
@@ -58,66 +58,56 @@
 };
 
 /*****************************************************************************/
-/* Structure for device-specific functions in assembler.
-*/
-struct sd_functions {
-	/* Test if the card is present.
-	   Return != 0 if present. */
-	int  	(*detect_card) (void);
-
-	/* Say if the data transfer is 1 or 4 bit.
-	   Return != 0 if 4 bit. */
-	int     (*transfer_nibbles) (void);
-
-	/* Write at minimum 8 clock cycles to the card.
-	   Wait max. 1ms for the CMD line to become HIGH.
-	   Send a command to the card. Skip 2 Z bits.
-           data = pointer to start of command. 32bit aligned.
-           len  = length of the command (including CRC7).
-	   Return != 0 if OK, 0 if timeout. */
-	int 	(*send_command)	(u8 *data, int len);
+/* 
+ * Low-level assembler stuff in scsd_s.S 
+ */
 
-	/* Wait max. 1ms for the CMD line to become LOW.
- 	   Read a response from the device and skip 2 Z bits. 
-           data = pointer to start of response buffer. 32bit aligned.
-           len  = number of bytes to read(including CRC).
-	   Return != 0 if OK, 0 if timeout. */
-	int	(*read_response) (u8* data, int len);
+/* Test if the card is present.
+   Return != 0 if present. */
+extern int scsd_detect_card(void);
 
-	/* Wait for the DATA line to become HIGH.
-	   Return != 0 if OK, 0 if timeout.
-	   Maximum length of testing is 1ms. */
-	int 	(*wait_ready) (void);
+/* Write at minimum 8 clock cycles to the card.
+   Wait max. 1ms for the CMD line to become HIGH.
+   Send a command to the card. Skip 2 Z bits.
+   if reslen > 0:
+   Wait max. 1ms for the CMD line to become LOW.
+   Read a response from the device and skip 2 Z bits. 
+   data = pointer to start of command & response. 32bit aligned.
+   len  = length of the command (including CRC7).
+   reslen = length of response.
+   Return 0 if OK, 1 if timeout waiting for CMD HIGH,
+                   2 if timeout waiting for CMD LOW */
+extern int scsd_send_command_resp(u8 *data, int len, int reslen);
 
-	/* Write a start bit, send a Data block incl. CRC.
-	   Write the end bit. Skip 2 Z bits.
-           Wait max. 1ms for the start of the CRC response.
-	   Check the CRC response.
-	   data = pointer to start of data. 32bit aligned.
-	   len  = number of bytes to send.
-	   Return != 0 if OK, 0 if CRC missing or error. */
-	int     (*send_data) (u8 *data, int len);
+/* Wait for the DATA line to become HIGH.
+   Return != 0 if OK, 0 if timeout.
+   Maximum length of testing is 1ms. */
+extern int scsd_wait_ready(void);
 
-	/* Wait max 1ms for the DATA line to become LOW.
-	   Receive a Data block and CRC, skip the end bit.
-	   data = pointer to start of data. 32bit aligned.
-	   len  = number of bytes to receive (incl. CRC) 
-	   Return != 0 if OK, 0 if timeout. */
-	int     (*read_data) (u8 *data, int len);
+/* Write a start bit, send a Data block incl. CRC.
+   Write the end bit. Skip 2 Z bits.
+   Wait max. 1ms for the start of the CRC response.
+   Check the CRC response.
+   data = pointer to start of data. 32bit aligned.
+   len  = number of bytes to send.
+   Return != 0 if OK, 0 if CRC missing or error. */
+extern int scsd_send_data(u8 *data, int len);
 
-	/* Read the write protect switch.
-	   Return != 0 if readonly, 0 if r/w.
-	   When in doubt, return 0. */
-	int	(*read_only) (void);
+/* Wait max 1ms for the DATA line to become LOW.
+   Receive a Data block and CRC, skip the end bit.
+   data = pointer to start of data. 32bit aligned.
+   len  = number of bytes to receive (incl. CRC) 
+   Return != 0 if OK, 0 if timeout. */
+extern int scsd_read_data(u8 *data, int len);
 
-	/* Write at minimum 8 clock cycles to the card. */
-	void	(*send_clocks) (void);
-};
+/* Write at minimum 8 clock cycles to the card. */
+extern void scsd_send_clocks(void);
 
-/*****************************************************************************/
-/* Active link to device-specific functions.
-*/
-static struct sd_functions *sd_dev;
+/* Calculate the data crc.
+   data = pointer to start of data. 32bit aligned.
+   len  = number of bytes of CRC calculation.
+   crc  = pointer to start of CRC. */
+extern void scsd_calc_crc(u8 *data, int len, u8* crc);
 
 /*****************************************************************************/
 /* Timer delayed execution of last clocks */
@@ -132,14 +122,6 @@
 static u8 sd_databuf[BLOCKSIZE+16] __attribute__ ((aligned (4)));
 
 /*****************************************************************************/
-/* Device-specific functions.
-*/
-#ifdef CONFIG_MMC_SCSD
-/* Supercard SD(mini,lite) */
-extern struct sd_functions supercard_functions;
-#endif
-
-/*****************************************************************************/
 
 /* Improved CRC7 function provided by cory1492 */
 inline static u8 scsd_crc7(u8* data, int cnt)
@@ -162,85 +144,6 @@
     return(crc);
 } 
 
-/* Calculate the data crc.
-   data = pointer to start of data. 32bit aligned.
-   len  = number of bytes of CRC calculation.
-   crc  = pointer to start of CRC. 
-*/
-/* non-static */ void scsd_calc_crc(u8 *data, int len, u8* crc)
-{
-	__asm__ __volatile__(					
-"	mov	r9,%2		\n"
-"                               \n"
-"	mov	r3,#0           \n"
-"	mov	r4,#0           \n"          
-"	mov	r5,#0           \n"          
-"	mov	r6,#0           \n"          
-"                               \n"
-"	ldr	r7,=0x80808080  \n"
-"	ldr	r8,=0x1021      \n"          
-"	mov	%1,%1,lsl #3    \n"          
-"1:                             \n"
-"	tst	r7,#0x80        \n"          
-"	ldrneb	%2,[%0],#1      \n"       
-"                               \n"
-"	mov	r3,r3,lsl #1    \n"
-"	tst	r3,#0x10000     \n"          
-"	eorne	r3,r3,r8        \n"        
-"	tst	%2,r7,lsr #24   \n"          
-"	eorne	r3,r3,r8        \n"        
-"	                        \n"      
-"	mov	r4,r4,lsl #1    \n"          
-"	tst	r4,#0x10000     \n"          
-"	eorne	r4,r4,r8        \n"        
-"	tst	%2,r7,lsr #25   \n"          
-"	eorne	r4,r4,r8        \n"        
-"	                        \n"      
-"	mov	r5,r5,lsl #1    \n"          
-"	tst	r5,#0x10000     \n"          
-"	eorne	r5,r5,r8        \n"        
-"	tst	%2,r7,lsr #26   \n"          
-"	eorne	r5,r5,r8        \n"        
-"	                        \n"      
-"	mov	r6,r6,lsl #1    \n"          
-"	tst	r6,#0x10000     \n"          
-"	eorne	r6,r6,r8        \n"        
-"	tst	%2,r7,lsr #27   \n"          
-"	eorne	r6,r6,r8        \n"        
-"                               \n"
-"	mov	r7,r7,ror #4    \n"
-"	subs	%1,%1,#4        \n"         
-"       bne     1b              \n"
-"                               \n"
-"	mov	%2,r9           \n"
-"	mov	r8,#16          \n"          
-"2:                             \n"
-"	mov	r7,r7,lsl #4    \n"          
-"	tst	r3,#0x8000      \n"          
-"	orrne	r7,r7,#8        \n"        
-"	tst	r4,#0x8000      \n"          
-"	orrne	r7,r7,#4        \n"        
-"	tst	r5,#0x8000      \n"          
-"	orrne	r7,r7,#2        \n"        
-"	tst	r6,#0x8000      \n"          
-"	orrne	r7,r7,#1        \n"        
-"                               \n"
-"	mov	r3,r3,lsl #1    \n"
-"	mov	r4,r4,lsl #1    \n"          
-"	mov	r5,r5,lsl #1    \n"          
-"	mov	r6,r6,lsl #1    \n"          
-"                               \n"
-"	sub	r8,r8,#1        \n"
-"	tst	r8,#1           \n"          
-"	streqb	r7,[%2],#1	\n"
-"	cmp	r8,#0           \n"          
-"	bne	2b              \n"          
-"                               \n"
-	: /* no output registers */					
-	: "r" (data), "r" (len), "r" (crc)
-	: "r3", "r4", "r5", "r6", "r7", "r8", "r9", "cc");
-}
-
 
 /* Wait until ready on the data lines */
 /* return 0 if ready, 1 if busy */
@@ -249,7 +152,7 @@
 	int i;
 
 	for (i = 1000; i; i--) {
-		if (sd_dev->wait_ready())
+		if (scsd_wait_ready())
 			return 0;
 	}
 	return 1;
@@ -261,6 +164,7 @@
 {
 	u8 *p = sd_databuf;
 	int i;
+	int reslen;
 
 	/* stop the clock timer, we will send a command */
 	del_timer(&clock_timer);
@@ -276,10 +180,29 @@
 	*p++ = cmd->arg; 
 	*p   = scsd_crc7(sd_databuf, 5);
 	
-	/* waiting for CMD line high, write command to card */
+	/* calculate length of response */
+	reslen = 0;
+	if ((cmd->flags & MMC_RSP_MASK) == MMC_RSP_LONG)
+		reslen = 18;
+	if ((cmd->flags & MMC_RSP_MASK) == MMC_RSP_SHORT)
+		reslen = 6;
+	if ((cmd->opcode == MMC_READ_SINGLE_BLOCK)
+         || (cmd->opcode == MMC_READ_MULTIPLE_BLOCK)
+	 || (cmd->opcode == SD_APP_SEND_SCR))
+		reslen = 0;
+	/* waiting for CMD line high, write command to card, read response */
 	for (i = 250; i; i--) {
-		if (sd_dev->send_command(sd_databuf, 6))
+		int ret = scsd_send_command_resp(sd_databuf, 6, reslen);
+		if (!ret)	/* all OK */
 			break;
+		if (ret == 1)	/* Card busy, try again */
+			continue;
+		if (ret == 2) {	/* Timeout waiting for response */
+			/* Timeout error */
+			printk(KERN_ERR "CMD:Timeout after command\n");
+			cmd->error = MMC_ERR_TIMEOUT;
+			return -1;
+		}
 	}
 	if (!i) {
 		printk( KERN_ERR "CMD:Timeout before command\n");
@@ -307,17 +230,6 @@
 			return 0;
 		}  
 
-		/* Read the response */
-		if ((cmd->flags & MMC_RSP_MASK) == MMC_RSP_LONG)
-			i = 18;
-		else
-			i = 6;
-		if (!sd_dev->read_response(sd_databuf, i)) {
-			/* Timeout error */
-			printk(KERN_ERR "CMD:Timeout after command\n");
-			cmd->error = MMC_ERR_TIMEOUT;
-			return -1;
-		}
 		p = sd_databuf;
 		p++; /* skip command byte */
 		cmd->resp[0]  = *p++ << 24;
@@ -361,7 +273,6 @@
 	}
 
 	/* success */
-	cmd->error = MMC_ERR_NONE;
 	return 0;
 }
 
@@ -404,7 +315,7 @@
 
 				/* wait max. 100ms for start bit, read the data+crc+end bit */
 				for( i=100; i; i--) {
-					if (sd_dev->read_data(sd_databuf, length+8))
+					if (scsd_read_data(sd_databuf, length+8))
 						break;
 				}
 				if (!i) {
@@ -447,7 +358,7 @@
 				}
 
 				/* Write data, check CRC response */
-				if (!sd_dev->send_data(sd_databuf, length+8)) {
+				if (!scsd_send_data(sd_databuf, length+8)) {
 					/* Timeout error */
 					printk(KERN_ERR "BAD CRC response\n");
 					data->error = MMC_ERR_TIMEOUT;
@@ -493,7 +404,7 @@
 
 	/* Fooling mmc core to only do 4bit data transfers.
 	   if the hardware/the driver can only do 4bit transfers. */
-	if (sd_dev->transfer_nibbles() && mmc->card_selected) {
+	if (mmc->card_selected) {
 		mmc->card_selected->scr.bus_widths |= SD_SCR_BUS_WIDTH_4;
 	}
 
@@ -565,14 +476,14 @@
 		return;	/* nothing to do, next timeout will come */
 	
 	/* send 8 clocks after last command */
-	sd_dev->send_clocks();
+	scsd_send_clocks();
 }
 
 /* read the write protect switch */
 static int scsd_get_ro(struct mmc_host *mmc)
 {
 	DBG("%s\n",__FUNCTION__);
-	return sd_dev->read_only();
+	return 0;
 }
 
 /* set operating conditions for the host */
@@ -612,20 +523,14 @@
 	struct scsd_host *host = NULL;
     	DBG("%s\n",__FUNCTION__);
 
-	/* Pointer to device-specific functions */
-#ifdef CONFIG_MMC_SCSD
-	sd_dev = &supercard_functions;
-	if (sd_dev->detect_card()) {
+	if (scsd_detect_card()) {
 		printk(KERN_INFO "Supercard SD detected\n");
-		goto success;
+	} else {
+		/* device not found */
+		printk(KERN_INFO "No Supercard SD found\n");
+		return -ENODEV;
 	}
-#endif	
 
-	/* device not found */
-	printk(KERN_INFO "No SD device found\n");
-	return -ENODEV;
-
-success:
         /* allocate host data structures */
 	mmc = mmc_alloc_host(sizeof(struct scsd_host), dev);
 	if (!mmc) {
@@ -714,5 +619,5 @@
 module_init(scsd_init);
 module_exit(scsd_exit);
 
-MODULE_DESCRIPTION("Nintendo DS SD Driver");
+MODULE_DESCRIPTION("Supercard SD Driver");
 MODULE_LICENSE("GPL");

Index: scsd_s.S
===================================================================
RCS file: /cvsroot/dslinux/dslinux/linux-2.6.x/drivers/mmc/scsd_s.S,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- scsd_s.S	28 Aug 2006 18:49:08 -0000	1.5
+++ scsd_s.S	30 Aug 2006 12:05:26 -0000	1.6
@@ -9,9 +9,6 @@
  *
  * This driver must be in main memory (or if you are doing XIP) in the
  * lower 16 MBytes of GBA ROM space.
- * 
- * NOTE: this driver destroys the last 2 bytes of RAM in the GBA ROM space.
- *       You don't want to store valuable information here.
  */
 
 /* common macros for all NDS GBA ROM device drivers */
@@ -37,42 +34,29 @@
         @ we are not allowed to destroy contents of GBA ROM space.
 	@ R0: Return != 0 if present. 
 	.ALIGN
-detect_card:	
-	prefix
+	.GLOBAL scsd_detect_card
+scsd_detect_card:	
+	gba_prefix
 	@ read old value @ SC_SD_CMD (in RAM)
 	ldr	r3, =SC_SD_CMD
-	ldrh	r2, [r3]
+	ldrh	r1, [r3]
 	@ store opposite of requested value in SC_SD_CMD (in RAM)
 	mov	r0, #-1
 	strh	r0, [r3]
-	@ read old value @ SC_LOCK (in RAM)
-	ldr	r3, =SC_LOCK
-	ldrh	r1, [r3]
-	@ now switch to IO mode (destroy RAM @ SC_SD_LOCK)
-	sc_setmode SC_MODE_IO
+	@ now switch to IO mode (save old value @SC_LOCK in R2)
+	sc_set_io
 	@ now read SC_SD_CMD (in IO)
 	ldr	r3, =SC_SD_CMD
 	ldrh	r0, [r3]
-	tst	r0, #0x300
+	tst	r0, #0x300		@ both bits must be 0
 	moveq	r0, #1
 	movne	r0, #0
-	@ switch back to RAM
-	sc_setmode SC_MODE_RAM
+	@ switch back to RAM (restore old value @SC_LOCK from R2)
+	sc_set_ram
 	@ restore RAM contents
 	ldr	r3, =SC_SD_CMD
-	strh	r2, [r3]
-	ldr	r3, =SC_LOCK
-	strh	r1, [r3] 
-	suffix
-	mov	pc, lr
-
-/*****************************************************************************/
-
-	@ Say if the data transfer is 1 or 4 bit.
-	@ R0: Return != 0 if 4 bit.
-	.ALIGN
-transfer_nibbles:
-	mov	r0, #1			@ we do only 4 bit data transfers.
+	strh	r1, [r3]
+	gba_suffix
 	mov	pc, lr
 
 /*****************************************************************************/
@@ -80,103 +64,98 @@
 	@ Write at minimum 8 clock cycles to the card.
 	@ Wait max. 1ms for the CMD line to become HIGH.
 	@ Send a command to the card. Skip 2 Z bits.
-        @ R0: pointer to start of command. 32bit aligned.
+	@ if R2 > 0:
+   	@ Wait max. 1ms for the CMD line to become LOW.
+   	@ Read a response from the device and skip 2 Z bits. 
+        @ R0: pointer to start of command & response. 32bit aligned.
 	@ R1: length of the command (including CRC7).
-	@ R0: Return != 0 if OK, 0 if timeout.
+	@ R2: length of response.
+   	@ R0 Return 0 if OK, 1 if timeout waiting for CMD HIGH,
+	@                    2 if timeout waiting for CMD LOW 
 	.ALIGN
-send_command:
-	stmfd   sp!,{r4-r6}		@ use additional registers
-	prefix
-	sc_setmode SC_MODE_IO
-	ldr	r2,=SC_SD_CMD
-	ldmia	r2,{r3-r6}		@ write 8 clocks
+	.GLOBAL scsd_send_command_resp
+scsd_send_command_resp:
+	stmfd   sp!,{r4-r8}		@ use additional registers
+	gba_prefix
+	mov	r8, r2			@ store 3rd parameter in R8
+	sc_set_io			@ switch to IO mode, save @SC_LOCK in R2
+	ldr	r7,=SC_SD_CMD
+	ldmia	r7,{r3-r6}		@ write 8 clocks
 	mov	r4, #1024		@ max. loop count
-send_command_busy:
+scsd_send_command_busy:
 	subs	r4, r4, #1		@ dec. loop count
-	moveq	r0, #0			@ exit R0=0
-	beq	send_command_exit
-	ldrh	r3,[r2]   
+	moveq	r0, #1			@ exit R0=1
+	beq	scsd_send_command_exit
+	ldrh	r3,[r7]   
 	tst	r3,#0x1
-	beq	send_command_busy
-	ldrh	r3,[r2]			@ one additional clock needed here(?)
+	beq	scsd_send_command_busy
+	ldrh	r3,[r7]			@ one additional clock needed here(?)
 	@ supercard lite: write 0 before write command
 	ldrb	r3,[r0]			@ R3 = command byte
 	cmp	r3,#(0x40+24)		@ write single sector
 	cmpne	r3,#(0x40+25)		@ write multiple sectors
 	ldreq 	ip,=SC_SDL_DOWRITE
 	streqh	ip, [ip]
-send_command_loop:
-        ldrb	r3,[r0],#1		@ R3 = byte to send
+	mov	ip, r0
+scsd_send_command_loop:
+        ldrb	r3,[ip],#1		@ R3 = byte to send
 	add	r3,r3,r3,lsl #17	@ some bit stuffing magic for supercard
 	mov	r4,r3,lsl #2
 	mov	r5,r4,lsl #2
 	mov	r6,r5,lsl #2
-        stmia   r2,{r3-r6}  		@ send 8 bit, one bit per 16 bit write
+        stmia   r7,{r3-r6}  		@ send 8 bit, one bit per 16 bit write
         subs    r1, r1, #1                  
-        bne 	send_command_loop
-	ldr	r3,[r2]			@ skip 2 Z bits
-	mov	r0, #1			@ OK
-send_command_exit:
-	sc_setmode SC_MODE_RAM
-	suffix
-	ldmfd   sp!,{r4-r6}		@ restore used registers
-	mov	pc, lr
-
-/*****************************************************************************/
-
-	@ Wait max. 1ms for the CMD line to become LOW.
-	@ Read a response from the device and skip 2 Z bits. 
-        @ R0: pointer to start of response buffer. 32bit aligned.
-        @ R1: number of bytes to read(including CRC).
-	@ R0: Return != 0 if OK, 0 if timeout.
-	.ALIGN
-read_response:
-	prefix
-	sc_setmode SC_MODE_IO
-	ldr	r2, =SC_SD_CMD
+        bne 	scsd_send_command_loop
+	ldr	r3,[r7]			@ skip 2 Z bits
+	@ test if we have to read a response
+	teq	r8, #0			@ reslen = 0?
+	beq	scsd_send_command_ok	@ yes: no response please
+	@ wait for CMD line LOW
 	mov	ip, #1024
-read_response_wait:
+scsd_read_response_wait:
 	subs	ip, ip, #1		@ dec. loop count
-	moveq	r0, #0			@ exit R0=0
-	beq	read_response_exit
-	ldrh	r3,[r2]   
+	moveq	r0, #2			@ exit R0=2
+	beq	scsd_send_command_exit
+	ldrh	r3,[r7]   
 	tst	r3,#0x1
-	bne	read_response_wait
+	bne	scsd_read_response_wait
 	mov	ip, #0			@ the first bit is 0
-	ldrh	r3,[r2]   
+	ldrh	r3,[r7]   
 	tst	r3,#0x1
-	b	read_response_7bit	@ and begin in the middle
-read_response_loop:
+	b	scsd_read_response_7bit	@ and begin in the middle
+scsd_read_response_loop:
 	mov	ip, #0			@ read 8 bit from CMD line
-	ldr	r3,[r2]
+	ldr	r3,[r7]
 	tst	r3, #0x00000001
 	orrne	ip, ip, #0x80
 	tst	r3, #0x00010000
-read_response_7bit:
+scsd_read_response_7bit:
 	orrne	ip, ip, #0x40
-	ldr	r3,[r2]
+	ldr	r3,[r7]
 	tst	r3, #0x00000001
 	orrne	ip, ip, #0x20
 	tst	r3, #0x00010000
 	orrne	ip, ip, #0x10
-	ldr	r3,[r2]
+	ldr	r3,[r7]
 	tst	r3, #0x00000001
 	orrne	ip, ip, #0x08
 	tst	r3, #0x00010000
 	orrne	ip, ip, #0x04
-	ldr	r3,[r2]
+	ldr	r3,[r7]
 	tst	r3, #0x00000001
 	orrne	ip, ip, #0x02
 	tst	r3, #0x00010000
 	orrne	ip, ip, #0x01
 	strb	ip,[r0],#1		@ store byte in buffer (main memory)
-        subs    r1, r1, #1                  
-        bne 	read_response_loop
-	ldr	r3,[r2]			@ skip 2 Z bits
-	mov	r0, #1			@ R0=OK
-read_response_exit:
-	sc_setmode SC_MODE_RAM
-	suffix
+        subs    r8, r8, #1                  
+        bne 	scsd_read_response_loop
+	ldr	r3,[r7]			@ skip 2 Z bits
+scsd_send_command_ok:
+	mov	r0, #0			@ OK
+scsd_send_command_exit:
+	sc_set_ram			@ swith to RAM mode, restore @SC_LOCK from R2
+	gba_suffix
+	ldmfd   sp!,{r4-r8}		@ restore used registers
 	mov	pc, lr
 
 /*****************************************************************************/
@@ -185,27 +164,27 @@
 	@ R0: Return != 0 if OK, 0 if timeout.
 	@ Maximum length of testing is 1ms.
 	.ALIGN
-wait_ready:
-	prefix
-	sc_setmode SC_MODE_IO
+	.GLOBAL scsd_wait_ready
+scsd_wait_ready:
+	gba_prefix
+	sc_set_io			@ switch to IO mode, save @SC_LOCK in R2
 	ldr	r1,=SC_SD_DATAREAD	@ IO address
-	mov	r2, #1024		@ number of tries
-wait_ready_again:
-	mov	r3, #8			@ high counter
-wait_ready_loop:
-	subs	r2, r2, #1		@ dec. loop count
+	mov	ip, #1024		@ number of tries
+scsd_wait_ready_again:
+	mov	r3, #8			@ high times counter
+scsd_wait_ready_loop:
+	subs	ip, ip, #1		@ dec. loop count
 	moveq	r0, #0			@ exit R0=0
-	beq	wait_ready_exit
+	beq	scsd_wait_ready_exit
 	ldrh	r0,[r1]			@ read DATA line
 	tst	r0, #0x100
-	beq	wait_ready_again	@ low: once more
+	beq	scsd_wait_ready_again	@ low: once more
 	subs	r3, r3, #1		@ high: dec high counter
-	bne	wait_ready_loop		@ test again
-	@ 8 times HIGH - OK!
-	mov	r0, #1			@ R0=OK
-wait_ready_exit:
-	sc_setmode SC_MODE_RAM
-	suffix
+	bne	scsd_wait_ready_loop	@ test again
+	mov	r0, #1			@ 8 times HIGH - OK!
+scsd_wait_ready_exit:
+	sc_set_ram			@ swith to RAM mode, restore @SC_LOCK from R2
+	gba_suffix
 	mov	pc, lr
 
 /*****************************************************************************/
@@ -218,45 +197,48 @@
 	@ R1: number of bytes to send.
 	@ R0: Return != 0 if OK, 0 if CRC missing or error. */
 	.ALIGN
-send_data:
-	prefix
-	sc_setmode SC_MODE_IO
+	.GLOBAL scsd_send_data
+scsd_send_data:
+	stmfd   sp!,{r4}		@ use additional registers
+	gba_prefix
+	sc_set_io			@ switch to IO mode, save @SC_LOCK in R2
 	@ write the start bit (0)
 	ldr	ip,=SC_SD_DATAWRITE
 	strh	ip, [ip]
-send_data_loop:
-	ldrh	r2,[r0],#2		@ read 16 bit
-	add	r2,r2,r2,lsl #20
-	mov	r3,r2,lsr #8	
-	stmia   ip,{r2-r3}
+scsd_send_data_loop:
+	ldrh	r3,[r0],#2		@ read 16 bit
+	add	r3,r3,r3,lsl #20
+	mov	r4,r3,lsr #8	
+	stmia   ip,{r3-r4}
 	subs    r1,r1,#2
-	bne     send_data_loop
+	bne     scsd_send_data_loop
 	@ write the end bit
-	ldr	r2,=-1
-	strh	r2,[ip]
+	ldr	r3,=-1
+	strh	r3,[ip]
 	@ switch to read mode
 	ldr	ip,=SC_SD_DATAREAD
 	@ skip 2 Z bits
-	ldr	r2,[ip]
-	mov	r3, #1024
-send_data_wait:
-	subs	r3, r3, #1		@ dec. loop count
+	ldr	r3,[ip]
+	mov	r4, #1024
+scsd_send_data_wait:
+	subs	r4, r4, #1		@ dec. loop count
 	moveq	r0, #0			@ exit R0=0
-	beq	send_data_exit
-	ldrh	r2,[ip]
-	tst	r2, #0x100
-	bne	send_data_wait
+	beq	scsd_send_data_exit
+	ldrh	r3,[ip]
+	tst	r3, #0x100
+	bne	scsd_send_data_wait
 	@ read CRC response and end bit
 	mov	r0, #0			@ failure code
-	ldr	r2,[ip]
-	ldr	r2,[ip]			@ 1=bit28, 2=bit24, 3=bit20, end=bit16
-	tst	r2, #0x10000000
-	bne	send_data_exit
-	tst	r2, #0x01000000
+	ldr	r3,[ip]
+	ldr	r3,[ip]			@ 1=bit28, 2=bit24, 3=bit20, end=bit16
+	tst	r3, #0x10000000
+	bne	scsd_send_data_exit
+	tst	r3, #0x01000000
 	movne	r0, #1			@ R0=OK if CRC code == 2 or 3
-send_data_exit:
-	sc_setmode SC_MODE_RAM
-	suffix
+scsd_send_data_exit:
+	sc_set_ram			@ swith to RAM mode, restore @SC_LOCK from R2
+	gba_suffix
+	ldmfd   sp!,{r4}		@ restore used registers
 	mov	pc, lr
 
 /*****************************************************************************/
@@ -267,86 +249,144 @@
 	@ R1: number of bytes to receive (incl. CRC)
 	@ R0: Return != 0 if OK, 0 if timeout.
 	.ALIGN
-read_data:
-	prefix
-	sc_setmode SC_MODE_IO
+	.GLOBAL scsd_read_data
+scsd_read_data:
+	stmfd   sp!,{r4}		@ use additional registers
+	gba_prefix
+	sc_set_io			@ switch to IO mode, save @SC_LOCK in R2
 	ldr	ip,=SC_SD_DATAREAD
-	mov	r2, #1024
-read_data_wait:
-	subs	r2, r2, #1		@ dec. loop count
+	mov	r3, #1024
+scsd_read_data_wait:
+	subs	r3, r3, #1		@ dec. loop count
 	moveq	r0, #0			@ exit R0=0
-	beq	read_data_exit
-	ldrh	r3,[ip]
-	tst	r3,#0x100
-	bne	read_data_wait
-read_data_loop:
-	ldmia	ip,{r2-r3} 
-	mov	r2,r3,lsr #16
-	strh	r2 ,[r0],#2
+	beq	scsd_read_data_exit
+	ldrh	r4,[ip]
+	tst	r4,#0x100
+	bne	scsd_read_data_wait
+scsd_read_data_loop:
+	ldmia	ip,{r3-r4} 
+	mov	r3,r4,lsr #16
+	strh	r3 ,[r0],#2
 
-	ldmia	ip,{r2-r3} 
-	mov	r2,r3,lsr #16
-	strh	r2 ,[r0],#2
+	ldmia	ip,{r3-r4} 
+	mov	r3,r4,lsr #16
+	strh	r3 ,[r0],#2
 
-	ldmia	ip,{r2-r3} 
-	mov	r2,r3,lsr #16
-	strh	r2 ,[r0],#2
+	ldmia	ip,{r3-r4} 
+	mov	r3,r4,lsr #16
+	strh	r3 ,[r0],#2
 
-	ldmia	ip,{r2-r3} 
-	mov	r2,r3,lsr #16
-	strh	r2 ,[r0],#2
+	ldmia	ip,{r3-r4} 
+	mov	r3,r4,lsr #16
+	strh	r3 ,[r0],#2
 
         subs    r1, r1, #8                
-        bne     read_data_loop 
+        bne     scsd_read_data_loop 
 	
-	ldrh	r2,[ip]		@ read the end bit
-	mov	r0, #1		@ R0=OK
-read_data_exit:
-	sc_setmode SC_MODE_RAM
-	suffix
-	mov	pc, lr
-
-/*****************************************************************************/
-
-	@ Read the write protect switch.
-	@ R0: Return != 0 if readonly, 0 if r/w.
-	@ When in doubt, return 0.
-	.ALIGN
-read_only:
-	mov	r0, #0		@ we cannot read the r/w switch
+	ldrh	r3,[ip]			@ read the end bit
+	mov	r0, #1			@ R0=OK
+scsd_read_data_exit:
+	sc_set_ram			@ swith to RAM mode, restore @SC_LOCK from R2
+	gba_suffix
+	ldmfd   sp!,{r4}		@ restore used registers
 	mov	pc, lr
 
 /*****************************************************************************/
 
 	@ Write at minimum 8 clock cycles to the card.
 	.ALIGN
-send_clocks:
-	prefix
-	sc_setmode SC_MODE_IO
+	.GLOBAL scsd_send_clocks
+scsd_send_clocks:
+	gba_prefix
+	sc_set_io			@ switch to IO mode, save @SC_LOCK in R2
 	ldr	r0,=SC_SD_CMD
 	ldr	r1,[r0]
 	ldr	r1,[r0]
 	ldr	r1,[r0]
 	ldr	r1,[r0]
-	sc_setmode SC_MODE_RAM
-	suffix
+	sc_set_ram		@ switch to RAM mode, restore @SC_LOCK from R2
+	gba_suffix
 	mov	pc, lr
 
 /*****************************************************************************/
 
-	@ Structure for device-specific functions in Assembler.
-	.GLOBAL	supercard_functions
+	@ Calculate the data crc.
+   	@ R0: pointer to start of data. 32bit aligned.
+   	@ R1: number of bytes of CRC calculation.
+   	@ R2: pointer to start of CRC. 
 	.ALIGN
-supercard_functions:
-	.word	detect_card
-	.word	transfer_nibbles
-	.word	send_command
-	.word	read_response
-	.word	wait_ready
-	.word	send_data
-	.word	read_data
-	.word	read_only
-	.word	send_clocks
+	.GLOBAL scsd_calc_crc
+scsd_calc_crc:
+	stmfd   sp!,{r4-r9}
+	mov	r9,r2
+
+	mov	r3,#0  
+	mov	r4,#0  
+	mov	r5,#0  
+	mov	r6,#0  
+
+	ldr	r7,=0x80808080
+	ldr	r8,=0x1021
+	mov	r1,r1,lsl #3
+scsd_calc_crc_loop:
+
+	tst	r7,#0x80
+	ldrneb	r2,[r0],#1
+
+	mov	r3,r3,lsl #1
+	tst	r3,#0x10000
+	eorne	r3,r3,r8
+	tst	r2,r7,lsr #24
+	eorne	r3,r3,r8
+	
+	mov	r4,r4,lsl #1
+	tst	r4,#0x10000
+	eorne	r4,r4,r8
+	tst	r2,r7,lsr #25
+	eorne	r4,r4,r8
+	
+	mov	r5,r5,lsl #1
+	tst	r5,#0x10000
+	eorne	r5,r5,r8
+	tst	r2,r7,lsr #26
+	eorne	r5,r5,r8
+	
+	mov	r6,r6,lsl #1
+	tst	r6,#0x10000
+	eorne	r6,r6,r8
+	tst	r2,r7,lsr #27
+	eorne	r6,r6,r8
+
+	mov	r7,r7,ror #4
+	subs	r1,r1,#4
+        bne     scsd_calc_crc_loop 
+
+	mov	r2,r9
+	mov	r8,#16
+scsd_calc_crc_write_data:
+	mov	r7,r7,lsl #4
+	tst	r3,#0x8000
+	orrne	r7,r7,#8
+	tst	r4,#0x8000
+	orrne	r7,r7,#4
+	tst	r5,#0x8000
+	orrne	r7,r7,#2
+	tst	r6,#0x8000
+	orrne	r7,r7,#1
+
+	mov	r3,r3,lsl #1
+	mov	r4,r4,lsl #1
+	mov	r5,r5,lsl #1
+	mov	r6,r6,lsl #1
+
+	sub	r8,r8,#1
+	tst	r8,#1
+	streqb	r7,[r2], #1
+	cmp	r8,#0
+	bne	scsd_calc_crc_write_data
+
+	ldmfd	sp!,{r4-r9}
+	mov	pc, lr
 
 	.END
 




More information about the dslinux-commit mailing list