1
0
mirror of synced 2026-01-13 07:20:18 +00:00

Modify SDPP driver for XTMax.

This commit is contained in:
Matthieu Bucchianeri 2024-10-19 23:50:24 -07:00
parent 1e54937295
commit c534956ca9
2 changed files with 57 additions and 178 deletions

View File

@ -367,7 +367,7 @@ PUBLIC void Initialize (rh_init_t far *rh)
WORD brkadr, reboot[2]; int status, i; WORD brkadr, reboot[2]; int status, i;
/* The version number is sneakily stored in the device header! */ /* The version number is sneakily stored in the device header! */
cdprintf("SD pport device driver V%c.%c (C) 2014 by Dan Marks\n based on TU58 by Robert Armstrong\n", cdprintf("SD Card driver for XTMax\n based on SD pport device driver V%c.%c (C) 2014 by Dan Marks\n based on TU58 by Robert Armstrong\n",
header.name[6], header.name[7]); header.name[6], header.name[7]);
/* Parse the options from the CONFIG.SYS file, if any... */ /* Parse the options from the CONFIG.SYS file, if any... */

View File

@ -12,15 +12,6 @@
/-------------------------------------------------------------------------/ /-------------------------------------------------------------------------/
Features and Limitations: Features and Limitations:
* Easy to Port Bit-banging SPI
It uses only four GPIO pins. No interrupt, no SPI is needed.
* Platform Independent
You need to modify only a few macros to control GPIO ports.
* Low Speed
The data transfer rate will be several times slower than hardware SPI.
* No Media Change Detection * No Media Change Detection
Application program needs to perform f_mount() after media change. Application program needs to perform f_mount() after media change.
@ -35,34 +26,15 @@
/* Platform dependent macros and functions needed to be modified */ /* Platform dependent macros and functions needed to be modified */
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
#define outportbyte(a,b) outp(a,b)
#define inportbyte(a) inp(a)
static WORD portbases[5] = {0x3BC,0x378,0x278,0x3E8,0x2E8}; static WORD portbases[5] = {0x3BC,0x378,0x278,0x3E8,0x2E8};
BYTE sd_card_check = 0; BYTE sd_card_check = 0;
BYTE portbase = 2; BYTE portbase = 2;
WORD OUTPORT=0x378; WORD DATAPORT=0x378;
WORD STATUSPORT=0x379; WORD CONTROLPORT=0x379;
WORD CONTROLPORT=0x37A;
#define VAR_INIT() {STATUSPORT=OUTPORT+1; CONTROLPORT=OUTPORT+2; outportbyte(CONTROLPORT,inportbyte(CONTROLPORT) & 0xCF); } #define VAR_INIT() {CONTROLPORT=DATAPORT+1;}
/* MISOPIN (SD card DAT0/DO pin 7) is PPORT SELECT (DB-25 pin 13) */
#define MISOPIN (0x01 << 4)
/* Card Detect (N/A) is PPORT BUSY (DB-25 pin 11) */
#define CDDETECTPIN (0x01 << 7)
/* Do not interface 5 to 3.3 volts directly! Use level converter... */
/* MOSI (SD card CMD/DI pin 2) is PPORT D0 (DB-25 pin 2) */
#define MOSIPIN (0x01 << 0)
/* CLOCK (SD card CLK/SCLK pin 5) is PPORT D1 (DB-25 pin 3) */
#define CLOCKPIN (0x01 << 1)
/* Card Select (SD card CAT3/CS pin 1) is PPORT D2 (DB-25 pin 4) */
#define CSPIN (0x01 << 2)
/* Connect ground to one of PPORT pins 18-25 */
#if 1 #if 1
#define TOUTCHR(x) #define TOUTCHR(x)
@ -102,33 +74,10 @@ static BYTE toutword(WORD x)
void setportbase(BYTE val) void setportbase(BYTE val)
{ {
if ((val >= 1) && (val <= (sizeof(portbases)/sizeof(portbases[0])) )) if ((val >= 1) && (val <= (sizeof(portbases)/sizeof(portbases[0])) ))
OUTPORT = portbases[val-1]; DATAPORT = portbases[val-1];
VAR_INIT(); VAR_INIT();
} }
#define DO_INIT()
#define DI_INIT()
#define CK_INIT()
#define CS_INIT()
const int bit_delay_val = 10;
#define BITDLY()
#define DO(statusport) (inportbyte((statusport)) & MISOPIN)
#define CDDETECT(statusport) (inportbyte((statusport)) & CDDETECTPIN)
#define CLOCKBITHIGHMOSIHIGH(outport) outportbyte((outport),MOSIPIN|CLOCKPIN)
#define CLOCKBITHIGHMOSILOW(outport) outportbyte((outport),CLOCKPIN)
#define CLOCKBITLOWMOSIHIGH(outport) outportbyte((outport),MOSIPIN)
#define CLOCKBITLOWMOSILOW(outport) outportbyte((outport),0)
#define CLOCKBITHIGHMOSIHIGHNOCS(outport) outportbyte((outport),MOSIPIN|CLOCKPIN|CSPIN)
#define CLOCKBITLOWMOSIHIGHNOCS(outport) outportbyte((outport),MOSIPIN|CSPIN)
#define CS_L(outport) outportbyte((outport),MOSIPIN)
#define CS_H(outport) outportbyte((outport),MOSIPIN|CSPIN)
#define CK_L(outport)
#define ADJ_VAL 1
static static
void dly_us (UINT n) void dly_us (UINT n)
{ {
@ -238,53 +187,23 @@ void xmit_mmc (
UINT bc /* Number of bytes to send */ UINT bc /* Number of bytes to send */
) )
{ {
#if 1
BYTE d; BYTE d;
WORD outport = OUTPORT;
do { do {
d = *buff++; /* Get a byte to be sent */ d = *buff++; /* Get a byte to be sent */
if (d & 0x80) outp(DATAPORT, d);
{ CLOCKBITLOWMOSIHIGH(outport); BITDLY(); CLOCKBITHIGHMOSIHIGH(outport); BITDLY();
} else
{ CLOCKBITLOWMOSILOW(outport); BITDLY(); CLOCKBITHIGHMOSILOW(outport); BITDLY();
}
if (d & 0x40)
{ CLOCKBITLOWMOSIHIGH(outport); BITDLY(); CLOCKBITHIGHMOSIHIGH(outport); BITDLY();
} else
{ CLOCKBITLOWMOSILOW(outport); BITDLY(); CLOCKBITHIGHMOSILOW(outport); BITDLY();
}
if (d & 0x20)
{ CLOCKBITLOWMOSIHIGH(outport); BITDLY(); CLOCKBITHIGHMOSIHIGH(outport); BITDLY();
} else
{ CLOCKBITLOWMOSILOW(outport); BITDLY(); CLOCKBITHIGHMOSILOW(outport); BITDLY();
}
if (d & 0x10)
{ CLOCKBITLOWMOSIHIGH(outport); BITDLY(); CLOCKBITHIGHMOSIHIGH(outport); BITDLY();
} else
{ CLOCKBITLOWMOSILOW(outport); BITDLY(); CLOCKBITHIGHMOSILOW(outport); BITDLY();
}
if (d & 0x08)
{ CLOCKBITLOWMOSIHIGH(outport); BITDLY(); CLOCKBITHIGHMOSIHIGH(outport); BITDLY();
} else
{ CLOCKBITLOWMOSILOW(outport); BITDLY(); CLOCKBITHIGHMOSILOW(outport); BITDLY();
}
if (d & 0x04)
{ CLOCKBITLOWMOSIHIGH(outport); BITDLY(); CLOCKBITHIGHMOSIHIGH(outport); BITDLY();
} else
{ CLOCKBITLOWMOSILOW(outport); BITDLY(); CLOCKBITHIGHMOSILOW(outport); BITDLY();
}
if (d & 0x02)
{ CLOCKBITLOWMOSIHIGH(outport); BITDLY(); CLOCKBITHIGHMOSIHIGH(outport); BITDLY();
} else
{ CLOCKBITLOWMOSILOW(outport); BITDLY(); CLOCKBITHIGHMOSILOW(outport); BITDLY();
}
if (d & 0x01)
{ CLOCKBITLOWMOSIHIGH(outport); BITDLY(); CLOCKBITHIGHMOSIHIGH(outport); BITDLY();
} else
{ CLOCKBITLOWMOSILOW(outport); BITDLY(); CLOCKBITHIGHMOSILOW(outport); BITDLY();
}
} while (--bc); } while (--bc);
CLOCKBITLOWMOSIHIGH(outport); #else
// Requires to add `-2' in the CC command line in the Makefile.
_asm {
mov cx,bc
mov dx,DATAPORT
push ds
lds si,dword ptr buff
rep outsb
pop ds
}
#endif
} }
@ -299,62 +218,24 @@ void rcvr_mmc (
UINT bc /* Number of bytes to receive */ UINT bc /* Number of bytes to receive */
) )
{ {
#if 1
BYTE r; BYTE r;
WORD outport = OUTPORT;
WORD statusport = STATUSPORT;
do { do {
CLOCKBITHIGHMOSIHIGH(outport); BITDLY(); r = inp(DATAPORT);
r = 0; if (DO(statusport)) r++; /* bit7 */
CLOCKBITLOWMOSIHIGH(outport); BITDLY();
CLOCKBITHIGHMOSIHIGH(outport); BITDLY();
r <<= 1; if (DO(statusport)) r++; /* bit6 */
CLOCKBITLOWMOSIHIGH(outport); BITDLY();
CLOCKBITHIGHMOSIHIGH(outport); BITDLY();
r <<= 1; if (DO(statusport)) r++; /* bit5 */
CLOCKBITLOWMOSIHIGH(outport); BITDLY();
CLOCKBITHIGHMOSIHIGH(outport); BITDLY();
r <<= 1; if (DO(statusport)) r++; /* bit4 */
CLOCKBITLOWMOSIHIGH(outport); BITDLY();
CLOCKBITHIGHMOSIHIGH(outport); BITDLY();
r <<= 1; if (DO(statusport)) r++; /* bit3 */
CLOCKBITLOWMOSIHIGH(outport); BITDLY();
CLOCKBITHIGHMOSIHIGH(outport); BITDLY();
r <<= 1; if (DO(statusport)) r++; /* bit2 */
CLOCKBITLOWMOSIHIGH(outport); BITDLY();
CLOCKBITHIGHMOSIHIGH(outport); BITDLY();
r <<= 1; if (DO(statusport)) r++; /* bit1 */
CLOCKBITLOWMOSIHIGH(outport); BITDLY();
CLOCKBITHIGHMOSIHIGH(outport); BITDLY();
r <<= 1; if (DO(statusport)) r++; /* bit0 */
CLOCKBITLOWMOSIHIGH(outport); BITDLY();
*buff++ = r; /* Store a received byte */ *buff++ = r; /* Store a received byte */
} while (--bc); } while (--bc);
} #else
// Requires to add `-2' in the CC command line in the Makefile.
/*-----------------------------------------------------------------------*/ _asm {
/* Receive bytes from the card (bitbanging) */ mov cx,bc
/*-----------------------------------------------------------------------*/ mov dx,DATAPORT
push es
static les di,dword ptr buff
void dummy_rcvr_mmc (void) rep insb
{ pop es
int i;
WORD outport = OUTPORT;
CLOCKBITLOWMOSIHIGHNOCS(outport); BITDLY();
for (i=0;i<8;i++)
{
CLOCKBITHIGHMOSIHIGHNOCS(outport); BITDLY();
CLOCKBITLOWMOSIHIGHNOCS(outport); BITDLY();
} }
#endif
} }
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@ -369,7 +250,7 @@ int wait_ready (void) /* 1:OK, 0:Timeout */
for (tmr = 5000; tmr; tmr--) { /* Wait for ready in timeout of 500ms */ for (tmr = 5000; tmr; tmr--) { /* Wait for ready in timeout of 500ms */
rcvr_mmc(&d, 1); d = inp(DATAPORT);
if (d == 0xFF) break; if (d == 0xFF) break;
dly_us(100); dly_us(100);
} }
@ -386,10 +267,10 @@ int wait_ready (void) /* 1:OK, 0:Timeout */
static static
void deselect (void) void deselect (void)
{ {
BYTE d; outp(CONTROLPORT, 1); // CS high
#if 0
CS_H(OUTPORT); outp(DATAPORT, 0xFF); /* Dummy clock (force DO hi-z for multiple slave SPI) */
dummy_rcvr_mmc(); /* Dummy clock (force DO hi-z for multiple slave SPI) */ #endif
} }
@ -403,8 +284,10 @@ int select (void) /* 1:OK, 0:Timeout */
{ {
BYTE d; BYTE d;
CS_L(OUTPORT); outp(CONTROLPORT, 0); // CS low
rcvr_mmc(&d, 1); /* Dummy clock (force DO enabled) */ #if 0
(void)inp(DATAPORT); /* Dummy clock (force DO enabled) */
#endif
if (wait_ready()) return 1; /* OK */ if (wait_ready()) return 1; /* OK */
deselect(); deselect();
@ -423,21 +306,21 @@ int rcvr_datablock ( /* 1:OK, 0:Failed */
UINT btr /* Byte count */ UINT btr /* Byte count */
) )
{ {
BYTE d[2]; BYTE d;
UINT tmr; UINT tmr;
for (tmr = 1000; tmr; tmr--) { /* Wait for data packet in timeout of 100ms */ for (tmr = 1000; tmr; tmr--) { /* Wait for data packet in timeout of 100ms */
rcvr_mmc(d, 1); d = inp(DATAPORT);
if (d[0] != 0xFF) break; if (d != 0xFF) break;
dly_us(100); dly_us(100);
} }
if (d[0] != 0xFE) { if (d != 0xFE) {
return 0; /* If not valid data token, return with error */ return 0; /* If not valid data token, return with error */
} }
rcvr_mmc(buff, btr); /* Receive the data block into buffer */ rcvr_mmc(buff, btr); /* Receive the data block into buffer */
rcvr_mmc(d, 2); /* Discard CRC */ (void)inp(DATAPORT); (void)inp(DATAPORT); /* Discard CRC */
return 1; /* Return with success */ return 1; /* Return with success */
} }
@ -454,18 +337,18 @@ int xmit_datablock ( /* 1:OK, 0:Failed */
BYTE token /* Data/Stop token */ BYTE token /* Data/Stop token */
) )
{ {
BYTE d[2]; BYTE d;
if (!wait_ready()) return 0; if (!wait_ready()) return 0;
d[0] = token; d = token;
xmit_mmc(d, 1); /* Xmit a token */ xmit_mmc(&d, 1); /* Xmit a token */
if (token != 0xFD) { /* Is it data token? */ if (token != 0xFD) { /* Is it data token? */
xmit_mmc(buff, 512); /* Xmit the 512 byte data block to MMC */ xmit_mmc(buff, 512); /* Xmit the 512 byte data block to MMC */
rcvr_mmc(d, 2); /* Xmit dummy CRC (0xFF,0xFF) */ (void)inp(DATAPORT); (void)inp(DATAPORT); /* Xmit dummy CRC (0xFF,0xFF) */
rcvr_mmc(d, 1); /* Receive data response */ d = inp(DATAPORT);; /* Receive data response */
if ((d[0] & 0x1F) != 0x05) /* If not accepted, return with error */ if ((d & 0x1F) != 0x05) /* If not accepted, return with error */
{ {
return 0; return 0;
} }
@ -528,11 +411,11 @@ BYTE send_cmd ( /* Returns command response (bit7==1:Send failed)*/
xmit_mmc(buf, 6); xmit_mmc(buf, 6);
/* Receive command response */ /* Receive command response */
if (cmd == CMD12) rcvr_mmc(&d, 1); /* Skip a stuff byte when stop reading */ if (cmd == CMD12) (void)inp(DATAPORT); /* Skip a stuff byte when stop reading */
n = 10; /* Wait for a valid response in timeout of 10 attempts */ n = 10; /* Wait for a valid response in timeout of 10 attempts */
do do
{ {
rcvr_mmc(&d, 1); d = inp(DATAPORT);
} }
while ((d & 0x80) && (--n)); while ((d & 0x80) && (--n));
TOUTCHR('P'); TOUTCHR('P');
@ -558,7 +441,7 @@ DSTATUS disk_status (
) )
{ {
if (drv) return STA_NOINIT; if (drv) return STA_NOINIT;
if ((sd_card_check) && (CDDETECT(STATUSPORT))) if ((sd_card_check) && (inp(CONTROLPORT) & 0x80))
{ {
Stat = STA_NOINIT; Stat = STA_NOINIT;
return STA_NOINIT; return STA_NOINIT;
@ -571,7 +454,7 @@ DRESULT disk_result (
) )
{ {
if (drv) return RES_NOTRDY; if (drv) return RES_NOTRDY;
if ((sd_card_check) && (CDDETECT(STATUSPORT))) if ((sd_card_check) && (inp(CONTROLPORT) & 0x80))
{ {
Stat = STA_NOINIT; Stat = STA_NOINIT;
return RES_NOTRDY; return RES_NOTRDY;
@ -595,18 +478,14 @@ DSTATUS disk_initialize (
setportbase(portbase); setportbase(portbase);
if (drv) return RES_NOTRDY; if (drv) return RES_NOTRDY;
if ((sd_card_check) && (CDDETECT(STATUSPORT))) if ((sd_card_check) && (inp(CONTROLPORT) & 0x80))
return RES_NOTRDY; return RES_NOTRDY;
ty = 0; ty = 0;
for (n = 5; n; n--) { for (n = 5; n; n--) {
CS_INIT(); CS_H(OUTPORT); /* Initialize port pin tied to CS */ outp(CONTROLPORT, 1); // CS high
dly_us(10000); /* 10ms. time for SD card to power up */ dly_us(10000); /* 10ms. time for SD card to power up */
CS_INIT(); CS_H(OUTPORT); /* Initialize port pin tied to CS */ for (tmr = 10; tmr; tmr--) outp(DATAPORT, 0xFF); /* Apply 80 dummy clocks and the card gets ready to receive command */
CK_INIT(); CK_L(OUTPORT); /* Initialize port pin tied to SCLK */
DI_INIT(); /* Initialize port pin tied to DI */
DO_INIT(); /* Initialize port pin tied to DO */
for (tmr = 10; tmr; tmr--) dummy_rcvr_mmc(); /* Apply 80 dummy clocks and the card gets ready to receive command */
if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */ if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */
if (send_cmd(CMD8, 0x1AA) == 1) { /* SDv2? */ if (send_cmd(CMD8, 0x1AA) == 1) { /* SDv2? */
rcvr_mmc(buf, 4); /* Get trailing return value of R7 resp */ rcvr_mmc(buf, 4); /* Get trailing return value of R7 resp */