#include <stdbool.h>
#include <blkdev.h>
+/* for platforms with multiple SD card slots, this variable contains
+ * the current operation's drive number */
+uint8_t sd_drive;
+
uint8_t devsd_transfer_sector(void)
{
- uint8_t attempt, drive;
+ uint8_t attempt;
bool success;
- drive = blk_op.blkdev->driver_data & DRIVE_NR_MASK;
+ sd_drive = blk_op.blkdev->driver_data & DRIVE_NR_MASK;
for(attempt=0; attempt<8; attempt++){
- if(sd_send_command(drive, blk_op.is_read ? CMD17 : CMD24,
+ if(sd_send_command(blk_op.is_read ? CMD17 : CMD24,
/* for byte addressed cards, shift LBA to convert to byte address */
(blk_op.blkdev->driver_data & CT_BLOCK) ? blk_op.lba : (blk_op.lba << 9)
) == 0){
if(blk_op.is_read){
- success = (sd_spi_wait(drive, false) == 0xFE);
+ success = (sd_spi_wait(false) == 0xFE);
if(success)
- sd_spi_receive_sector(drive);
+ sd_spi_receive_sector();
}else{
success = false;
- if(sd_spi_wait(drive, true) == 0xFF){
- sd_spi_transmit_byte(drive, 0xFE);
- sd_spi_transmit_sector(drive);
- sd_spi_transmit_byte(drive, 0xFF); /* dummy CRC */
- sd_spi_transmit_byte(drive, 0xFF);
- success = ((sd_spi_wait(drive, false) & 0x1F) == 0x05);
+ if(sd_spi_wait(true) == 0xFF){
+ sd_spi_transmit_byte(0xFE);
+ sd_spi_transmit_sector();
+ sd_spi_transmit_byte(0xFF); /* dummy CRC */
+ sd_spi_transmit_byte(0xFF);
+ success = ((sd_spi_wait(false) & 0x1F) == 0x05);
}
}
}else
success = false;
- sd_spi_release(drive);
+ sd_spi_release();
if(success)
return 1;
return 0;
}
-void sd_spi_release(uint8_t drive)
+void sd_spi_release(void)
{
- sd_spi_raise_cs(drive);
- sd_spi_receive_byte(drive);
+ sd_spi_raise_cs();
+ sd_spi_receive_byte();
}
-uint8_t sd_spi_wait(uint8_t drive, bool want_ff)
+uint8_t sd_spi_wait(bool want_ff)
{
unsigned int timer;
unsigned char b;
timer = set_timer_ms(500);
while(true){
- b = sd_spi_receive_byte(drive);
+ b = sd_spi_receive_byte();
if(want_ff){
if(b == 0xFF)
break;
return b;
}
-int sd_send_command(uint8_t drive, unsigned char cmd, uint32_t arg)
+int sd_send_command(unsigned char cmd, uint32_t arg)
{
unsigned char n, res, *p;
if (cmd & 0x80) { /* ACMD<n> is the command sequense of CMD55-CMD<n> */
cmd &= 0x7F;
- res = sd_send_command(drive, CMD55, 0);
+ res = sd_send_command(CMD55, 0);
if (res > 1)
return res;
}
/* Select the card and wait for ready */
- sd_spi_release(drive); /* raise CS, then sends 8 clocks (some cards require this) */
- sd_spi_lower_cs(drive);
- if(sd_spi_wait(drive, true) != 0xFF)
+ sd_spi_release(); /* raise CS, then sends 8 clocks (some cards require this) */
+ sd_spi_lower_cs();
+ if(sd_spi_wait(true) != 0xFF)
return 0xFF;
/* Send command packet */
- sd_spi_transmit_byte(drive, cmd); /* Start + Command index */
+ sd_spi_transmit_byte(cmd); /* Start + Command index */
#if 0
- sd_spi_transmit_byte(drive, (unsigned char)(arg >> 24)); /* Argument[31..24] */
- sd_spi_transmit_byte(drive, (unsigned char)(arg >> 16)); /* Argument[23..16] */
- sd_spi_transmit_byte(drive, (unsigned char)(arg >> 8)); /* Argument[15..8] */
- sd_spi_transmit_byte(drive, (unsigned char)arg); /* Argument[7..0] */
+ sd_spi_transmit_byte((unsigned char)(arg >> 24)); /* Argument[31..24] */
+ sd_spi_transmit_byte((unsigned char)(arg >> 16)); /* Argument[23..16] */
+ sd_spi_transmit_byte((unsigned char)(arg >> 8)); /* Argument[15..8] */
+ sd_spi_transmit_byte((unsigned char)arg); /* Argument[7..0] */
#else
/* sdcc sadly unable to figure this out for itself yet */
p = ((unsigned char *)&arg)+3;
- sd_spi_transmit_byte(drive, *(p--)); /* Argument[31..24] */
- sd_spi_transmit_byte(drive, *(p--)); /* Argument[23..16] */
- sd_spi_transmit_byte(drive, *(p--)); /* Argument[15..8] */
- sd_spi_transmit_byte(drive, *p); /* Argument[7..0] */
+ sd_spi_transmit_byte(*(p--)); /* Argument[31..24] */
+ sd_spi_transmit_byte(*(p--)); /* Argument[23..16] */
+ sd_spi_transmit_byte(*(p--)); /* Argument[15..8] */
+ sd_spi_transmit_byte(*p); /* Argument[7..0] */
#endif
/* there's only a few commands (in native mode) that need correct CRCs */
n = 0x01; /* Dummy CRC + Stop */
if (cmd == CMD0) n = 0x95; /* Valid CRC for CMD0(0) */
if (cmd == CMD8) n = 0x87; /* Valid CRC for CMD8(0x1AA) */
- sd_spi_transmit_byte(drive, n);
+ sd_spi_transmit_byte(n);
/* Receive command response */
if (cmd == CMD12)
- sd_spi_receive_byte(drive); /* Skip a stuff byte when stop reading */
+ sd_spi_receive_byte(); /* Skip a stuff byte when stop reading */
n = 20; /* Wait for a valid response */
do{
- res = sd_spi_receive_byte(drive);
+ res = sd_spi_receive_byte();
}while ((res & 0x80) && --n);
return res; /* Return with the response value */
void devsd_init(void);
/* platform-specific SPI functions */
-void sd_spi_clock(uint8_t drive, bool go_fast);
-void sd_spi_raise_cs(uint8_t drive);
-void sd_spi_lower_cs(uint8_t drive);
-void sd_spi_transmit_byte(uint8_t drive, uint8_t byte);
-uint8_t sd_spi_receive_byte(uint8_t drive);
-bool sd_spi_receive_sector(uint8_t drive);
-bool sd_spi_transmit_sector(uint8_t drive);
+void sd_spi_clock(bool go_fast);
+void sd_spi_raise_cs(void);
+void sd_spi_lower_cs(void);
+void sd_spi_transmit_byte(uint8_t byte);
+uint8_t sd_spi_receive_byte(void);
+bool sd_spi_receive_sector(void);
+bool sd_spi_transmit_sector(void);
+
+/* for platforms which support multiple SD cards */
+extern uint8_t sd_drive; /* current card/drive number */
#ifdef _SD_PRIVATE
/* internal functions */
-void sd_spi_release(uint8_t drive);
-int sd_send_command(uint8_t drive, unsigned char cmd, uint32_t arg);
-uint8_t sd_spi_wait(uint8_t drive, bool want_ff);
-void sd_init_drive(uint8_t drive);
-int sd_spi_init(uint8_t drive);
+void sd_spi_release(void);
+int sd_send_command(unsigned char cmd, uint32_t arg);
+uint8_t sd_spi_wait(bool want_ff);
+void sd_init_drive(void);
+int sd_spi_init(void);
uint8_t devsd_transfer_sector(void);
/* Definitions for MMC/SDC command */
void devsd_init(void)
{
- uint8_t d;
-
- for(d=0; d<SD_DRIVE_COUNT; d++)
- sd_init_drive(d);
+ for(sd_drive=0; sd_drive<SD_DRIVE_COUNT; sd_drive++)
+ sd_init_drive();
}
-void sd_init_drive(uint8_t drive)
+void sd_init_drive(void)
{
blkdev_t *blk;
unsigned char csd[16], n;
uint8_t card_type;
- kprintf("SD drive %d: ", drive);
- card_type = sd_spi_init(drive);
+ kprintf("SD drive %d: ", sd_drive);
+ card_type = sd_spi_init();
if(!(card_type & (~CT_BLOCK))){
kprintf("no card found\n");
return;
blk->transfer = devsd_transfer_sector;
- blk->driver_data = (drive & DRIVE_NR_MASK) | card_type;
+ blk->driver_data = (sd_drive & DRIVE_NR_MASK) | card_type;
/* read and compute card size */
- if(sd_send_command(drive, CMD9, 0) == 0 && sd_spi_wait(drive, false) == 0xFE){
+ if(sd_send_command(CMD9, 0) == 0 && sd_spi_wait(false) == 0xFE){
for(n=0; n<16; n++)
- csd[n] = sd_spi_receive_byte(drive);
+ csd[n] = sd_spi_receive_byte();
if ((csd[0] >> 6) == 1) {
/* SDC ver 2.00 */
blk->drive_lba_count = ((uint32_t)csd[9]
blk->drive_lba_count <<= (n-9);
}
}
- sd_spi_release(drive);
+ sd_spi_release();
blkdev_scan(blk, 0);
}
-int sd_spi_init(uint8_t drive)
+int sd_spi_init(void)
{
unsigned char n, cmd, card_type, ocr[4];
timer_t timer;
- sd_spi_raise_cs(drive);
+ sd_spi_raise_cs();
- sd_spi_clock(drive, false);
+ sd_spi_clock(false);
for (n = 20; n; n--)
- sd_spi_receive_byte(drive); /* send dummy clocks -- at least 80 required; we send 160 */
+ sd_spi_receive_byte(); /* send dummy clocks -- at least 80 required; we send 160 */
card_type = CT_NONE;
/* Enter Idle state */
- if (sd_send_command(drive, CMD0, 0) == 1) {
+ if (sd_send_command(CMD0, 0) == 1) {
/* initialisation timeout 2 seconds */
timer = set_timer_sec(2);
- if (sd_send_command(drive, CMD8, (uint32_t)0x1AA) == 1) { /* SDHC */
+ if (sd_send_command(CMD8, (uint32_t)0x1AA) == 1) { /* SDHC */
/* Get trailing return value of R7 resp */
- for (n = 0; n < 4; n++) ocr[n] = sd_spi_receive_byte(drive);
+ for (n = 0; n < 4; n++) ocr[n] = sd_spi_receive_byte();
/* The card can work at vdd range of 2.7-3.6V */
if (ocr[2] == 0x01 && ocr[3] == 0xAA) {
/* Wait for leaving idle state (ACMD41 with HCS bit) */
- while(!timer_expired(timer) && sd_send_command(drive, ACMD41, (uint32_t)1 << 30));
+ while(!timer_expired(timer) && sd_send_command(ACMD41, (uint32_t)1 << 30));
/* Check CCS bit in the OCR */
- if (!timer_expired(timer) && sd_send_command(drive, CMD58, 0) == 0) {
- for (n = 0; n < 4; n++) ocr[n] = sd_spi_receive_byte(drive);
+ if (!timer_expired(timer) && sd_send_command(CMD58, 0) == 0) {
+ for (n = 0; n < 4; n++) ocr[n] = sd_spi_receive_byte();
card_type = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* SDv2 */
}
}
} else { /* SDSC or MMC */
- if (sd_send_command(drive, ACMD41, 0) <= 1) {
+ if (sd_send_command(ACMD41, 0) <= 1) {
/* SDv1 */
card_type = CT_SD1;
cmd = ACMD41;
cmd = CMD1;
}
/* Wait for leaving idle state */
- while(!timer_expired(timer) && sd_send_command(drive, cmd, 0));
+ while(!timer_expired(timer) && sd_send_command(cmd, 0));
/* Set R/W block length to 512 */
- if(timer_expired(timer) || sd_send_command(drive, CMD16, 512) != 0)
+ if(timer_expired(timer) || sd_send_command(CMD16, 512) != 0)
card_type = CT_NONE;
}
}
- sd_spi_release(drive);
+ sd_spi_release();
if (card_type) {
- sd_spi_clock(drive, true); /* up to 20MHz should be OK */
+ sd_spi_clock(true); /* up to 20MHz should be OK */
return card_type;
}
mapslot_bank1(slotram);
}
-void sd_spi_clock(uint8_t drive, bool go_fast)
+void sd_spi_clock(bool go_fast)
{
- drive; /* not used */
go_fast;
}
-void sd_spi_raise_cs(uint8_t drive)
+void sd_spi_raise_cs(void)
{
- drive; /* not used */
-
sd_spi_map_interface();
- writeb(drive, MSD_DEVSEL);
+ writeb(0, MSD_DEVSEL);
/* reading from MSD_CS raises CS for all cards */
sd_spi_unmap_interface();
}
-void sd_spi_lower_cs(uint8_t drive)
+void sd_spi_lower_cs(void)
{
- drive; /* not used */
-
/* happens automatically when sending */
}
-void sd_spi_transmit_byte(uint8_t drive, unsigned char byte)
+void sd_spi_transmit_byte(unsigned char byte)
{
- drive; /* not used */
-
sd_spi_map_interface();
writeb(byte, MSD_RDWR);
sd_spi_unmap_interface();
}
-uint8_t sd_spi_receive_byte(uint8_t drive)
+uint8_t sd_spi_receive_byte(void)
{
unsigned char c;
- drive; /* not used */
sd_spi_map_interface();
* Target page is always mapped to slot_page2, and the target address offset accordingly.
*
*/
-bool sd_spi_receive_sector(uint8_t drive) __naked
+bool sd_spi_receive_sector(void) __naked
{
__asm
ld bc,#512
jp looptxrx
__endasm;
-
- drive; /* silence compiler warning */
}
-bool sd_spi_transmit_sector(uint8_t drive) __naked
+bool sd_spi_transmit_sector(void) __naked
{
__asm
ret z
jp _map_kernel
__endasm;
- drive; /* silence compiler warning */
}
#endif
byte; /* squelch compiler warning */
}
-void sd_spi_clock(uint8_t drive, bool go_fast)
+void sd_spi_clock(bool go_fast)
{
unsigned char c;
- drive; /* not used */
c = CSIO_CNTR & 0xf8; /* clear low three bits, gives fastest rate (clk/20) */
if(!go_fast)
CSIO_CNTR = c;
}
-void sd_spi_raise_cs(uint8_t drive)
+void sd_spi_raise_cs(void)
{
- drive; /* not used */
/* wait for idle */
while(CSIO_CNTR & (CSIO_CNTR_TE | CSIO_CNTR_RE));
MARK4_SD = MARK4_SD & (~MARK4_SD_CS);
}
-void sd_spi_lower_cs(uint8_t drive)
+void sd_spi_lower_cs(void)
{
- drive; /* not used */
/* wait for idle */
while(CSIO_CNTR & (CSIO_CNTR_TE | CSIO_CNTR_RE));
MARK4_SD = MARK4_SD | MARK4_SD_CS;
}
-void sd_spi_transmit_byte(uint8_t drive, unsigned char byte)
+void sd_spi_transmit_byte(unsigned char byte)
{
unsigned char c;
- drive; /* not used */
/* reverse the bits before we busywait */
byte = reverse_byte(byte);
CSIO_CNTR = c | CSIO_CNTR_TE;
}
-uint8_t sd_spi_receive_byte(uint8_t drive)
+uint8_t sd_spi_receive_byte(void)
{
unsigned char c;
- drive; /* not used */
/* wait for any current transmit or receive operation to complete */
do{
/* WRS: measured byte transfer time as approx 5.66us with Z180 @ 36.864MHz,
three times faster. Main change is to start the next receive operation
as soon as possible and overlap the loop housekeeping with the receive. */
-bool sd_spi_receive_sector(uint8_t drive) __naked
+bool sd_spi_receive_sector(void) __naked
{
__asm
waitrx:
jr nz, rxnextbyte ; go again if not yet done
jr transferdone ; we are done
__endasm;
- drive; /* squelch compiler warnings */
}
-bool sd_spi_transmit_sector(uint8_t drive) __naked
+bool sd_spi_transmit_sector(void) __naked
{
__asm
; load parameters
ret z ; return if kernel still mapped
jp map_kernel ; else map kernel and return
__endasm;
- drive; /* squelch compiler warnings */
}
#define SD_SPI_TX 0x32
#define SD_SPI_RX 0x33
-void sd_spi_mode0(uint8_t drive)
+void sd_spi_mode0(void)
{
- used(drive);
sd_spi_mode = 0;
}
-void sd_spi_clock(uint8_t drive, bool go_fast)
+void sd_spi_clock(bool go_fast)
{
- used(drive);
-// sd_spi_mode0(drive);
+// sd_spi_mode0();
/* Currently the sd driver just uses 'slow' and 'fast'. That's ok for
sd but mmc really needs to be 16MHz */
if (go_fast)
sd_spi_divisor = 255;
}
-void sd_spi_raise_cs(uint8_t drive)
+void sd_spi_raise_cs(void)
{
- used(drive);
sd_spi_chipselect = 0xFF;
}
-void sd_spi_lower_cs(uint8_t drive)
+void sd_spi_lower_cs(void)
{
- used(drive);
sd_spi_chipselect = 0xFE;
}
-void sd_spi_transmit_byte(uint8_t drive, unsigned char byte)
+void sd_spi_transmit_byte(unsigned char byte)
{
- used(drive);
sd_spi_tx = byte;
}
-uint8_t sd_spi_receive_byte(uint8_t drive)
+uint8_t sd_spi_receive_byte(void)
{
uint8_t r;
- used(drive);
sd_spi_tx = 0xFF;
r = sd_spi_rx;
return r;
COMMON_MEMORY
-bool sd_spi_receive_sector(uint8_t drive) __naked
+bool sd_spi_receive_sector(void) __naked
{
- used(drive);
__asm
ld a, (_blk_op+BLKPARAM_IS_USER_OFFSET);
ld hl, (_blk_op+BLKPARAM_ADDR_OFFSET);
__endasm;
}
-bool sd_spi_transmit_sector(uint8_t drive) __naked
+bool sd_spi_transmit_sector(void) __naked
{
- used(drive);
__asm
ld a, (_blk_op+BLKPARAM_IS_USER_OFFSET)
ld hl, (_blk_op+BLKPARAM_ADDR_OFFSET)