git-svn-id: svn://localhost/Users/andi/Downloads/code/DML@30 be6c1b03-d731-4111-a574-e37d80d43941
This commit is contained in:
0xD15EA5E@gmail.com 2012-09-25 11:48:20 +00:00
parent 206dff56e5
commit 82602a7ff0
24 changed files with 2576 additions and 343 deletions

22
Card.c
View File

@ -1,12 +1,16 @@
#include "Card.h" #include "Card.h"
FIL CardStat; FIL CardStat;
extern u32 FSTMode;
extern FIL GameFile;
void CardInit( void ) void CardInit( void )
{ {
FILINFO f; FILINFO f;
u32 i,wrote; u32 i,wrote;
CARDStat CStat; CARDStat CStat;
char GameID[0x20];
memset32( (void*)CARD_BASE, 0xdeadbeef, 0x20 ); memset32( (void*)CARD_BASE, 0xdeadbeef, 0x20 );
memset32( (void*)CARD_SHADOW, 0, 0x20 ); memset32( (void*)CARD_SHADOW, 0, 0x20 );
@ -18,10 +22,20 @@ void CardInit( void )
f_chdir("/saves"); f_chdir("/saves");
} }
if( f_chdir((const TCHAR*)0) != FR_OK ) if( FSTMode )
{ {
f_mkdir((const TCHAR*)0); FSTRead( (char*)GameID, 0x20, 0 );
f_chdir((const TCHAR*)0);
} else {
f_lseek( &GameFile, 0 );
f_read( &GameFile, (char*)GameID, 0x20, &wrote );
}
if( f_chdir(GameID) != FR_OK )
{
f_mkdir(GameID);
f_chdir(GameID);
} }
switch( f_stat( "stats.bin", &f ) ) switch( f_stat( "stats.bin", &f ) )
@ -90,7 +104,7 @@ s32 CardFindEntryByName( char *Filename )
f_lseek( &CardStat, sizeof(CARDStat) * i ); f_lseek( &CardStat, sizeof(CARDStat) * i );
f_read( &CardStat, &CStat, sizeof(CARDStat), &read ); f_read( &CardStat, &CStat, sizeof(CARDStat), &read );
if( memcmp( Filename, CStat.fileName, strlen(Filename) ) == 0 ) if( strcmp( Filename, CStat.fileName ) == 0 )
{ {
//dbgprintf("CardFindEntryByName(%d,%s,%s)\n", i, Filename, CStat.fileName ); //dbgprintf("CardFindEntryByName(%d,%s,%s)\n", i, Filename, CStat.fileName );
return i; return i;

View File

@ -9,13 +9,13 @@ void ConfigInit( DML_CFG *Cfg )
memset32( DMLCfg, 0, sizeof(DML_CFG) ); memset32( DMLCfg, 0, sizeof(DML_CFG) );
//If a loader supplied any options we use them otherwise use the code defines //If a loader supplied any options we use them otherwise use the code defines
if( Cfg->Magicbytes == 0xD1050CF6 && Cfg->Version == CONFIG_VERSION ) if( Cfg->Magicbytes == 0xD1050CF6 )
{ {
memcpy( DMLCfg, Cfg, sizeof( DML_CFG ) ); memcpy( DMLCfg, Cfg, sizeof( DML_CFG ) );
} else { } else {
dbgprintf("No valid found in RAM\n"); dbgprintf("No valid config found in RAM\n");
dbgprintf("Version:%08X\n", DMLCfg->Version ); dbgprintf("Version:%08X\n", DMLCfg->Version );
dbgprintf("Config :%08X\n", DMLCfg->Config ); dbgprintf("Config :%08X\n", DMLCfg->Config );
@ -41,9 +41,9 @@ void ConfigInit( DML_CFG *Cfg )
#ifdef PADHOOK #ifdef PADHOOK
DMLCfg->Config |= DML_CFG_PADHOOK; DMLCfg->Config |= DML_CFG_PADHOOK;
#endif #endif
DMLCfg->VideoMode = DML_VID_DML_AUTO;
DMLCfg->Version = CONFIG_VERSION;
DMLCfg->Magicbytes = 0xD1050CF6; DMLCfg->Magicbytes = 0xD1050CF6;
DMLCfg->Version = CONFIG_VERSION;
DMLCfg->VideoMode = DML_VID_DML_AUTO;
} }
//Check if a memcard is inserted in Slot A //Check if a memcard is inserted in Slot A

View File

@ -3,7 +3,6 @@
#include "string.h" #include "string.h"
#include "global.h" #include "global.h"
#include "ipc.h"
#include "alloc.h" #include "alloc.h"
#include "vsprintf.h" #include "vsprintf.h"
#include "HW.h" #include "HW.h"

View File

@ -3,26 +3,8 @@
#include "global.h" #include "global.h"
#include "asm\DVDRead.h"
#include "asm\DVDReadAsync.h"
#include "asm\DVDReadAbsAsyncPrioAsync.h"
#include "asm\mDVDReadAbsAsyncPrio.h"
#include "asm\DVDReadAbsAsyncPrio.h"
#include "asm\LDVDReadAbsAsyncPrio.h"
#include "asm\DVDReadAbsAsyncPrioForBS.h"
#include "asm\mDVDReadAbsAsyncPrioShift.h"
#include "asm\DVDReadDiscIDAsync.h"
#include "asm\DVDInquiryAsync.h" #include "asm\DVDInquiryAsync.h"
#include "asm\__DVDInterruptHandler.h"
#include "asm\DVDLowReadShift.h"
#include "asm\DVDWaitReady.h"
#include "asm\dDVDReadAbs.h"
#include "asm\DVDSeekAbsAsyncPrio.h" #include "asm\DVDSeekAbsAsyncPrio.h"
#include "asm\DVDPrepareStreamAbsAsync.h"
#include "asm\DVDStopStreamAtEndAsync.h"
#include "asm\DVDCancelStreamAsync.h"
#include "asm\DVDGetStreamPlayAddrAsync.h"
#include "asm\DVDLowRead.h"
#include "asm\padipc.h" #include "asm\padipc.h"
#endif #endif

1
HW.h
View File

@ -4,7 +4,6 @@
#include "string.h" #include "string.h"
#include "global.h" #include "global.h"
#include "memory.h" #include "memory.h"
#include "ipc.h"
#include "alloc.h" #include "alloc.h"
#include "dip.h" #include "dip.h"

View File

@ -890,8 +890,11 @@ void DoPatches( char *ptr, u32 size, u32 SectionOffset )
if( FPatterns[j].Patch == (u8*)DVDGetDriveStatus ) if( FPatterns[j].Patch == (u8*)DVDGetDriveStatus )
{ {
if( !ConfigGetConfig( DML_CFG_NODISC ) ) if( (read32(0) >> 8) != 0x474754 && // Chibi-Robo!
(read32(0) >> 8) != 0x475041 ) // Pokémon Channel
break; break;
dbgprintf("Patch:DVDGetDriveStatus\n");
} }
if( (FPatterns[j].Length >> 16) == 0xdead ) if( (FPatterns[j].Length >> 16) == 0xdead )

View File

@ -3,7 +3,6 @@
#include "string.h" #include "string.h"
#include "global.h" #include "global.h"
#include "ipc.h"
#include "alloc.h" #include "alloc.h"
#include "ff.h" #include "ff.h"
#include "vsprintf.h" #include "vsprintf.h"

View File

@ -2,7 +2,11 @@
#define __BSDTYPES_H__ #define __BSDTYPES_H__
#include "global.h" #include "global.h"
#include "errno.h"
#define ENXIO 6
#define EINVAL 22
#define WSAETIMEDOUT 10060L
#define ETIMEDOUT WSAETIMEDOUT
typedef u32 u_int; typedef u32 u_int;
//typedef u32 u_int32_t; //typedef u32 u_int32_t;

6
dip.c
View File

@ -155,7 +155,8 @@ u32 DIUpdateRegisters( void )
switch( Offset ) switch( Offset )
{ {
case 0x56B8E7E0: // AppSwitcher [EUR] case 0x56B8E7E0: // AppSwitcher [EUR]
case 0x56C49600: // [USA] case 0x56C49600: // [USA] v1.1
case 0x56C4C980: // [USA] v1.0
{ {
DMLCfg->Config &= ~(DML_CFG_CHEATS|DML_CFG_PADHOOK|DML_CFG_DEBUGGER|DML_CFG_DEBUGWAIT); DMLCfg->Config &= ~(DML_CFG_CHEATS|DML_CFG_PADHOOK|DML_CFG_DEBUGGER|DML_CFG_DEBUGWAIT);
@ -163,7 +164,8 @@ u32 DIUpdateRegisters( void )
} break; } break;
case 0x5668FE20: // psov3.dol [EUR] case 0x5668FE20: // psov3.dol [EUR]
case 0x56750660: // [USA] case 0x56750660: // [USA] v1.1
case 0x56753EC0: // [USA] v1.0
{ {
PSOHack = 1; PSOHack = 1;
} break; } break;

View File

@ -15,7 +15,7 @@
#define PADHOOK 1 #define PADHOOK 1
#define CONFIG_VERSION 0x00000002 #define CONFIG_VERSION 0x00000002
#define DML_VERSION 0x00020002 #define DML_VERSION 0x00020003
#define DI_SUCCESS 1 #define DI_SUCCESS 1
#define DI_ERROR 2 #define DI_ERROR 2

67
ipc.h
View File

@ -1,67 +0,0 @@
#ifndef __IPC_H__
#define __IPC_H__ 1
struct ioctl_vector {
void *data;
unsigned int len;
} __attribute__((packed));
struct ipcmessage
{
unsigned int command; // 0
unsigned int result; // 4
union
{
unsigned int fd; // 8
};
union
{
struct
{
char *device; // 12
unsigned int mode; // 16
unsigned int resultfd; // 20
} open;
struct
{
void *data;
unsigned int length;
} read, write;
struct
{
int offset;
int origin;
} seek;
struct
{
unsigned int command;
unsigned int *buffer_in;
unsigned int length_in;
unsigned int *buffer_io;
unsigned int length_io;
} ioctl;
struct
{
unsigned int command; // C
unsigned int argc_in; // 10
unsigned int argc_io; // 14
struct ioctl_vector *argv; // 18
} ioctlv;
};
} __attribute__((packed)) ipcmessage;
#define IOS_OPEN 0x01
#define IOS_CLOSE 0x02
#define IOS_READ 0x03
#define IOS_WRITE 0x04
#define IOS_SEEK 0x05
#define IOS_IOCTL 0x06
#define IOS_IOCTLV 0x07
#endif

1
main.c
View File

@ -7,7 +7,6 @@ Copyright (C) 2010-2012 crediar
*/ */
#include "string.h" #include "string.h"
#include "global.h" #include "global.h"
#include "ipc.h"
#include "alloc.h" #include "alloc.h"
#include "ff.h" #include "ff.h"
#include "diskio.h" #include "diskio.h"

View File

@ -3,7 +3,6 @@
#include "string.h" #include "string.h"
#include "global.h" #include "global.h"
#include "ipc.h"
#include "utils.h" #include "utils.h"
#include "hollywood.h" #include "hollywood.h"
#include "vsprintf.h" #include "vsprintf.h"

854
sdhc.c Normal file
View File

@ -0,0 +1,854 @@
/*
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
* Copyright (c) 2009 Sven Peter <svenpeter@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* SD Host Controller driver based on the SD Host Controller Standard
* Simplified Specification Version 1.00 (www.sdcard.com).
*/
#include "bsdtypes.h"
#include "sdmmc.h"
#include "sdhc.h"
#include "string.h"
#include "utils.h"
#include "memory.h"
struct sdhc_host sc_host;
//#define SDHC_DEBUG
#define SDHC_COMMAND_TIMEOUT 500
#define SDHC_TRANSFER_TIMEOUT 5000
#define sdhc_wait_intr(a,b,c) sdhc_wait_intr_debug(__func__, __LINE__, a, b, c)
static inline u32 bus_space_read_4(bus_space_handle_t ioh, u32 reg)
{
return read32(ioh + reg);
}
static inline u16 bus_space_read_2(bus_space_handle_t ioh, u32 reg)
{
u32 val;
if(reg & 3)
val = (read32((ioh + reg) & ~3) & 0xffff0000) >> 16;
else
val = (read32(ioh + reg) & 0xffff);
return val;
}
static inline u8 bus_space_read_1(bus_space_handle_t ioh, u32 reg)
{
u32 mask;
u32 addr;
u8 shift;
shift = (reg & 3) * 8;
mask = (0xFF << shift);
addr = ioh + reg;
return (read32(addr & ~3) & mask) >> shift;
}
static inline void bus_space_write_4(bus_space_handle_t ioh, u32 r, u32 v)
{
write32(ioh + r, v);
}
static inline void bus_space_write_2(bus_space_handle_t ioh, u32 r, u16 v)
{
if(r & 3)
mask32((ioh + r) & ~3, 0xffff0000, v << 16);
else
mask32((ioh + r), 0xffff, ((u32)v));
}
static inline void bus_space_write_1(bus_space_handle_t ioh, u32 r, u8 v)
{
u32 mask;
u32 addr;
u8 shift;
shift = (r & 3) * 8;
mask = (0xFF << shift);
addr = ioh + r;
mask32(addr & ~3, mask, v << shift);
}
/* flag values */
#define SHF_USE_DMA 0x0001
#define HREAD1(hp, reg) \
(bus_space_read_1((hp)->ioh, (reg)))
#define HREAD2(hp, reg) \
(bus_space_read_2((hp)->ioh, (reg)))
#define HREAD4(hp, reg) \
(bus_space_read_4((hp)->ioh, (reg)))
#define HWRITE1(hp, reg, val) \
bus_space_write_1((hp)->ioh, (reg), (val))
#define HWRITE2(hp, reg, val) \
bus_space_write_2((hp)->ioh, (reg), (val))
#define HWRITE4(hp, reg, val) \
bus_space_write_4((hp)->ioh, (reg), (val))
#define HCLR1(hp, reg, bits) \
HWRITE1((hp), (reg), HREAD1((hp), (reg)) & ~(bits))
#define HCLR2(hp, reg, bits) \
HWRITE2((hp), (reg), HREAD2((hp), (reg)) & ~(bits))
#define HSET1(hp, reg, bits) \
HWRITE1((hp), (reg), HREAD1((hp), (reg)) | (bits))
#define HSET2(hp, reg, bits) \
HWRITE2((hp), (reg), HREAD2((hp), (reg)) | (bits))
int sdhc_start_command(struct sdhc_host *, struct sdmmc_command *);
int sdhc_wait_state(struct sdhc_host *, u_int32_t, u_int32_t);
int sdhc_soft_reset(struct sdhc_host *, int);
void sdhc_reset_intr_status(struct sdhc_host *hp);
int sdhc_wait_intr_debug(const char *func, int line, struct sdhc_host *, int, int);
void sdhc_transfer_data(struct sdhc_host *, struct sdmmc_command *);
void sdhc_read_data(struct sdhc_host *, u_char *, int);
void sdhc_write_data(struct sdhc_host *, u_char *, int);
//#define SDHC_DEBUG 1
#ifdef SDHC_DEBUG
int sdhcdebug = 0;
#define DPRINTF(n,s) do { if ((n) <= sdhcdebug) dbgprintf s; } while (0)
void sdhc_dump_regs(struct sdhc_host *);
#else
#define DPRINTF(n,s) do {} while(0)
#endif
/*
* Called by attachment driver. For each SD card slot there is one SD
* host controller standard register set. (1.3)
*/
int
sdhc_host_found(bus_space_tag_t iot, bus_space_handle_t ioh, int usedma)
{
u_int32_t caps;
int error = 1;
#ifdef SDHC_DEBUG
u_int16_t version;
version = bus_space_read_2(ioh, SDHC_HOST_CTL_VERSION);
dbgprintf("sdhc: SD Host Specification/Vendor Version ");
switch(SDHC_SPEC_VERSION(version)) {
case 0x00:
dbgprintf("1.0/%u\n", SDHC_VENDOR_VERSION(version));
break;
default:
dbgprintf(">1.0/%u\n", SDHC_VENDOR_VERSION(version));
break;
}
#endif
memset8(&sc_host, 0, sizeof(sc_host));
/* Fill in the new host structure. */
sc_host.iot = iot;
sc_host.ioh = ioh;
sc_host.data_command = 0;
/*
* Reset the host controller and enable interrupts.
*/
error = sdhc_host_reset(&sc_host);
/* Determine host capabilities. */
caps = HREAD4(&sc_host, SDHC_CAPABILITIES);
/* Use DMA if the host system and the controller support it. */
if (usedma && ISSET(caps, SDHC_DMA_SUPPORT))
SET(sc_host.flags, SHF_USE_DMA);
/*
* Determine the base clock frequency. (2.2.24)
*/
if (SDHC_BASE_FREQ_KHZ(caps) != 0)
sc_host.clkbase = SDHC_BASE_FREQ_KHZ(caps);
if (sc_host.clkbase == 0) {
/* The attachment driver must tell us. */
//dbgprintf("sdhc: base clock frequency unknown\n");
goto err;
} else if (sc_host.clkbase < 10000 || sc_host.clkbase > 63000) {
/* SDHC 1.0 supports only 10-63 MHz. */
//dbgprintf("sdhc: base clock frequency out of range: %u MHz\n", sc_host.clkbase / 1000);
goto err;
}
/*
* XXX Set the data timeout counter value according to
* capabilities. (2.2.15)
*/
if (ISSET(caps, SDHC_VOLTAGE_SUPP_1_8V))
SET(sc_host.ocr, MMC_OCR_1_7V_1_8V | MMC_OCR_1_8V_1_9V);
if (ISSET(caps, SDHC_VOLTAGE_SUPP_3_0V))
SET(sc_host.ocr, MMC_OCR_2_9V_3_0V | MMC_OCR_3_0V_3_1V);
if (ISSET(caps, SDHC_VOLTAGE_SUPP_3_3V))
SET(sc_host.ocr, MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V);
/*
* Determine the maximum block length supported by the host
* controller. (2.2.24)
*/
//switch((caps >> SDHC_MAX_BLK_LEN_SHIFT) & SDHC_MAX_BLK_LEN_MASK)
//{
// case SDHC_MAX_BLK_LEN_512:
// hp->maxblklen = 512;
// break;
// case SDHC_MAX_BLK_LEN_1024:
// hp->maxblklen = 1024;
// break;
// case SDHC_MAX_BLK_LEN_2048:
// hp->maxblklen = 2048;
// break;
// default:
// hp->maxblklen = 1;
// break;
//}
/*
* Attach the generic SD/MMC bus driver. (The bus driver must
* not invoke any chipset functions before it is attached.)
*/
sdmmc_attach(&sc_host);
return 0;
err:
return (error);
}
#ifndef LOADER
/*
* Shutdown hook established by or called from attachment driver.
*/
void
sdhc_shutdown(void)
{
/* XXX chip locks up if we don't disable it before reboot. */
(void)sdhc_host_reset(&sc_host);
}
#endif
/*
* Reset the host controller. Called during initialization, when
* cards are removed, upon resume, and during error recovery.
*/
int
sdhc_host_reset(struct sdhc_host *hp)
{
u_int16_t imask;
int error;
/* Disable all interrupts. */
HWRITE2(hp, SDHC_NINTR_SIGNAL_EN, 0);
/*
* Reset the entire host controller and wait up to 100ms for
* the controller to clear the reset bit.
*/
if ((error = sdhc_soft_reset(hp, SDHC_RESET_ALL)) != 0)
{
return (error);
}
/* Set data timeout counter value to max for now. */
HWRITE1(hp, SDHC_TIMEOUT_CTL, SDHC_TIMEOUT_MAX);
/* Enable interrupts. */
imask =
#ifndef LOADER
SDHC_CARD_REMOVAL | SDHC_CARD_INSERTION |
#endif
SDHC_BUFFER_READ_READY | SDHC_BUFFER_WRITE_READY |
SDHC_DMA_INTERRUPT | SDHC_BLOCK_GAP_EVENT |
SDHC_TRANSFER_COMPLETE | SDHC_COMMAND_COMPLETE;
HWRITE2(hp, SDHC_NINTR_STATUS_EN, imask);
HWRITE2(hp, SDHC_EINTR_STATUS_EN, SDHC_EINTR_STATUS_MASK);
HWRITE2(hp, SDHC_NINTR_SIGNAL_EN, imask);
HWRITE2(hp, SDHC_EINTR_SIGNAL_EN, SDHC_EINTR_SIGNAL_MASK);
return 0;
}
/*
* Return non-zero if the card is currently inserted.
*/
int
sdhc_card_detect(struct sdhc_host *hp)
{
return ISSET(HREAD4(hp, SDHC_PRESENT_STATE), SDHC_CARD_INSERTED) ?
1 : 0;
}
/*
* Set or change SD bus voltage and enable or disable SD bus power.
* Return zero on success.
*/
int
sdhc_bus_power(struct sdhc_host *hp, u_int32_t ocr)
{
//dbgprintf("sdhc_bus_power(%u)\n", ocr);
/* Disable bus power before voltage change. */
HWRITE1(hp, SDHC_POWER_CTL, 0);
/* If power is disabled, reset the host and return now. */
if (ocr == 0) {
(void)sdhc_host_reset(hp);
return 0;
}
/*
* Enable bus power. Wait at least 1 ms (or 74 clocks) plus
* voltage ramp until power rises.
*/
HWRITE1(hp, SDHC_POWER_CTL, (SDHC_VOLTAGE_3_3V << SDHC_VOLTAGE_SHIFT) |
SDHC_BUS_POWER);
udelay(10000);
/*
* The host system may not power the bus due to battery low,
* etc. In that case, the host controller should clear the
* bus power bit.
*/
if (!ISSET(HREAD1(hp, SDHC_POWER_CTL), SDHC_BUS_POWER))
{
//dbgprintf("Host controller failed to enable bus power\n");
return ENXIO;
}
return 0;
}
/*
* Return the smallest possible base clock frequency divisor value
* for the CLOCK_CTL register to produce `freq' (KHz).
*/
static int
sdhc_clock_divisor(struct sdhc_host *hp, u_int freq)
{
int div;
for (div = 1; div <= 256; div *= 2)
if ((hp->clkbase / div) <= freq)
return (div / 2);
/* No divisor found. */
return -1;
}
/*
* Set or change SDCLK frequency or disable the SD clock.
* Return zero on success.
*/
int
sdhc_bus_clock(struct sdhc_host *hp, int freq)
{
int div;
int timo;
//dbgprintf("%s(%d)\n", __FUNCTION__, freq);
#ifdef DIAGNOSTIC
/* Must not stop the clock if commands are in progress. */
if (ISSET(HREAD4(hp, SDHC_PRESENT_STATE), SDHC_CMD_INHIBIT_MASK) &&
sdhc_card_detect(hp))
dbgprintf("sdhc_sdclk_frequency_select: command in progress\n");
#endif
/* Stop SD clock before changing the frequency. */
HWRITE2(hp, SDHC_CLOCK_CTL, 0);
if (freq == SDMMC_SDCLK_OFF)
return 0;
/* Set the minimum base clock frequency divisor. */
if ((div = sdhc_clock_divisor(hp, freq)) < 0) {
/* Invalid base clock frequency or `freq' value. */
return EINVAL;
}
HWRITE2(hp, SDHC_CLOCK_CTL, div << SDHC_SDCLK_DIV_SHIFT);
/* Start internal clock. Wait 10ms for stabilization. */
HSET2(hp, SDHC_CLOCK_CTL, SDHC_INTCLK_ENABLE);
for (timo = 1000; timo > 0; timo--) {
if (ISSET(HREAD2(hp, SDHC_CLOCK_CTL), SDHC_INTCLK_STABLE))
break;
udelay(10);
}
if (timo == 0) {
//dbgprintf("sdhc: internal clock never stabilized\n");
return ETIMEDOUT;
}
/* Enable SD clock. */
HSET2(hp, SDHC_CLOCK_CTL, SDHC_SDCLK_ENABLE);
return 0;
}
void
sdhc_card_intr_mask(struct sdhc_host *hp, int enable)
{
if (enable) {
HSET2(hp, SDHC_NINTR_STATUS_EN, SDHC_CARD_INTERRUPT);
HSET2(hp, SDHC_NINTR_SIGNAL_EN, SDHC_CARD_INTERRUPT);
} else {
HCLR2(hp, SDHC_NINTR_SIGNAL_EN, SDHC_CARD_INTERRUPT);
HCLR2(hp, SDHC_NINTR_STATUS_EN, SDHC_CARD_INTERRUPT);
}
}
void
sdhc_card_intr_ack(struct sdhc_host *hp)
{
HSET2(hp, SDHC_NINTR_STATUS_EN, SDHC_CARD_INTERRUPT);
}
int
sdhc_wait_state(struct sdhc_host *hp, u_int32_t mask, u_int32_t value)
{
u_int32_t state;
int timeout;
for (timeout = 500; timeout > 0; timeout--) {
if (((state = HREAD4(hp, SDHC_PRESENT_STATE)) & mask) == value)
return 0;
udelay(10000);
}
return ETIMEDOUT;
}
void
sdhc_exec_command(struct sdhc_host *hp, struct sdmmc_command *cmd)
{
int error;
if (cmd->c_datalen > 0)
hp->data_command = 1;
if (cmd->c_timeout == 0) {
if (cmd->c_datalen > 0)
cmd->c_timeout = SDHC_TRANSFER_TIMEOUT;
else
cmd->c_timeout = SDHC_COMMAND_TIMEOUT;
}
hp->intr_status = 0;
/*
* Start the MMC command, or mark `cmd' as failed and return.
*/
error = sdhc_start_command(hp, cmd);
if (error != 0) {
cmd->c_error = error;
SET(cmd->c_flags, SCF_ITSDONE);
hp->data_command = 0;
return;
}
/*
* Wait until the command phase is done, or until the command
* is marked done for any other reason.
*/
int status = sdhc_wait_intr(hp, SDHC_COMMAND_COMPLETE, cmd->c_timeout);
if (!ISSET(status, SDHC_COMMAND_COMPLETE)) {
cmd->c_error = ETIMEDOUT;
//dbgprintf("timeout dump: error_intr: 0x%x intr: 0x%x\n", hp->intr_error_status, hp->intr_status);
//sdhc_dump_regs(hp);
SET(cmd->c_flags, SCF_ITSDONE);
hp->data_command = 0;
return;
}
//dbgprintf("command_complete, continuing...\n");
/*
* The host controller removes bits [0:7] from the response
* data (CRC) and we pass the data up unchanged to the bus
* driver (without padding).
*/
if (cmd->c_error == 0 && ISSET(cmd->c_flags, SCF_RSP_PRESENT)) {
if (ISSET(cmd->c_flags, SCF_RSP_136)) {
u_char *p = (u_char *)cmd->c_resp;
int i;
for (i = 0; i < 15; i++)
*p++ = HREAD1(hp, SDHC_RESPONSE + i);
} else
cmd->c_resp[0] = HREAD4(hp, SDHC_RESPONSE);
}
/*
* If the command has data to transfer in any direction,
* execute the transfer now.
*/
if (cmd->c_error == 0 && cmd->c_datalen > 0)
sdhc_transfer_data(hp, cmd);
SET(cmd->c_flags, SCF_ITSDONE);
hp->data_command = 0;
}
int
sdhc_start_command(struct sdhc_host *hp, struct sdmmc_command *cmd)
{
u_int16_t blksize = 0;
u_int16_t blkcount = 0;
u_int16_t mode;
u_int16_t command;
int error;
/*
* The maximum block length for commands should be the minimum
* of the host buffer size and the card buffer size. (1.7.2)
*/
/* Fragment the data into proper blocks. */
if (cmd->c_datalen > 0) {
blksize = MIN(cmd->c_datalen, cmd->c_blklen);
blkcount = cmd->c_datalen / blksize;
if (cmd->c_datalen % blksize > 0) {
/* XXX: Split this command. (1.7.4) */
//dbgprintf("sdhc: data not a multiple of %d bytes\n", blksize);
return EINVAL;
}
}
/* Check limit imposed by 9-bit block count. (1.7.2) */
if (blkcount > SDHC_BLOCK_COUNT_MAX) {
//dbgprintf("sdhc: too much data\n");
return EINVAL;
}
/* Prepare transfer mode register value. (2.2.5) */
mode = 0;
if (ISSET(cmd->c_flags, SCF_CMD_READ))
mode |= SDHC_READ_MODE;
if (blkcount > 0) {
mode |= SDHC_BLOCK_COUNT_ENABLE;
// if (blkcount > 1) {
mode |= SDHC_MULTI_BLOCK_MODE;
/* XXX only for memory commands? */
mode |= SDHC_AUTO_CMD12_ENABLE;
// }
}
if (ISSET(hp->flags, SHF_USE_DMA))
mode |= SDHC_DMA_ENABLE;
/*
* Prepare command register value. (2.2.6)
*/
command = (cmd->c_opcode & SDHC_COMMAND_INDEX_MASK) <<
SDHC_COMMAND_INDEX_SHIFT;
if (ISSET(cmd->c_flags, SCF_RSP_CRC))
command |= SDHC_CRC_CHECK_ENABLE;
if (ISSET(cmd->c_flags, SCF_RSP_IDX))
command |= SDHC_INDEX_CHECK_ENABLE;
if (cmd->c_data != NULL)
command |= SDHC_DATA_PRESENT_SELECT;
if (!ISSET(cmd->c_flags, SCF_RSP_PRESENT))
command |= SDHC_NO_RESPONSE;
else if (ISSET(cmd->c_flags, SCF_RSP_136))
command |= SDHC_RESP_LEN_136;
else if (ISSET(cmd->c_flags, SCF_RSP_BSY))
command |= SDHC_RESP_LEN_48_CHK_BUSY;
else
command |= SDHC_RESP_LEN_48;
/* Wait until command and data inhibit bits are clear. (1.5) */
if ((error = sdhc_wait_state(hp, SDHC_CMD_INHIBIT_MASK, 0)) != 0)
return error;
if( ISSET( hp->flags, SHF_USE_DMA) && cmd->c_datalen > 0 )
{
cmd->c_resid = blkcount;
cmd->c_buf = cmd->c_data;
if( ISSET(cmd->c_flags, SCF_CMD_READ) )
{
dc_invalidaterange(cmd->c_data, cmd->c_datalen);
} else {
dc_flushrange(cmd->c_data, cmd->c_datalen);
ahb_flush_to(AHB_SDHC);
}
HWRITE4(hp, SDHC_DMA_ADDR, (u32)cmd->c_data);
}
/*
* Start a CPU data transfer. Writing to the high order byte
* of the SDHC_COMMAND register triggers the SD command. (1.5)
*/
HWRITE2(hp, SDHC_BLOCK_SIZE, blksize | 7<<12);
if (blkcount > 0)
HWRITE2(hp, SDHC_BLOCK_COUNT, blkcount);
HWRITE4(hp, SDHC_ARGUMENT, cmd->c_arg);
HWRITE4(hp, SDHC_TRANSFER_MODE, ((u32)command<<16)|mode);
// HWRITE2(hp, SDHC_COMMAND, command);
// HWRITE2(hp, SDHC_TRANSFER_MODE, mode);
return 0;
}
void
sdhc_transfer_data(struct sdhc_host *hp, struct sdmmc_command *cmd)
{
int error;
int status;
error = 0;
if (ISSET(hp->flags, SHF_USE_DMA)) {
for(;;) {
status = sdhc_wait_intr(hp, SDHC_TRANSFER_COMPLETE |
SDHC_DMA_INTERRUPT,
SDHC_TRANSFER_TIMEOUT);
if (!status) {
error = ETIMEDOUT;
break;
}
if (ISSET(status, SDHC_TRANSFER_COMPLETE))
{
//dbgprintf("got a TRANSFER_COMPLETE: %08x\n", status);
break;
}
if (ISSET(status, SDHC_DMA_INTERRUPT)) {
// this works because our virtual memory
// addresses are equal to the physical memory
// addresses and because we require the target
// buffer to be contiguous
HWRITE4(hp, SDHC_DMA_ADDR,
HREAD4(hp, SDHC_DMA_ADDR));
continue;
}
}
}
#ifdef SDHC_DEBUG
/* XXX I forgot why I wanted to know when this happens :-( */
if ((cmd->c_opcode == 52 || cmd->c_opcode == 53) &&
ISSET(MMC_R1(cmd->c_resp), 0xcb00))
dbgprintf("sdhc: CMD52/53 error response flags %#x\n",
MMC_R1(cmd->c_resp) & 0xff00);
#endif
if (ISSET(cmd->c_flags, SCF_CMD_READ))
ahb_flush_from( AHB_SDHC );
if (error != 0)
cmd->c_error = error;
SET(cmd->c_flags, SCF_ITSDONE);
return;
}
/* Prepare for another command. */
int
sdhc_soft_reset(struct sdhc_host *hp, int mask)
{
int timo;
HWRITE1(hp, SDHC_SOFTWARE_RESET, mask);
for (timo = 10; timo > 0; timo--) {
if (!ISSET(HREAD1(hp, SDHC_SOFTWARE_RESET), mask))
break;
udelay(10000);
HWRITE1(hp, SDHC_SOFTWARE_RESET, 0);
}
if (timo == 0) {
HWRITE1(hp, SDHC_SOFTWARE_RESET, 0);
return (ETIMEDOUT);
}
return (0);
}
int
sdhc_wait_intr_debug(const char *funcname, int line, struct sdhc_host *hp, int mask, int timo)
{
int status;
mask |= SDHC_ERROR_INTERRUPT;
mask |= SDHC_ERROR_TIMEOUT;
status = hp->intr_status & mask;
for (; timo > 0; timo--)
{
sdhc_irq(); // seems backwards but ok
if (hp->intr_status != 0) {
status = hp->intr_status & mask;
break;
}
udelay(1000);
}
if (timo == 0) {
status |= SDHC_ERROR_TIMEOUT;
}
hp->intr_status &= ~status;
//DPRINTF(2,("sdhc: funcname=%s, line=%d, timo=%d status=%#x intr status=%#x error %#x\n",
// funcname, line, timo, status, hp->intr_status, hp->intr_error_status));
/* Command timeout has higher priority than command complete. */
if (ISSET(status, SDHC_ERROR_INTERRUPT)) {
//dbgprintf("resetting due to error interrupt\n");
//sdhc_dump_regs(hp);
hp->intr_error_status = 0;
(void)sdhc_soft_reset(hp, SDHC_RESET_DAT|SDHC_RESET_CMD);
status = 0;
}
/* Command timeout has higher priority than command complete. */
if (ISSET(status, SDHC_ERROR_TIMEOUT)) {
//dbgprintf("not resetting due to timeout\n");
//sdhc_dump_regs(hp);
hp->intr_error_status = 0;
// (void)sdhc_soft_reset(hp, SDHC_RESET_DAT|SDHC_RESET_CMD);
status = 0;
}
return status;
}
/*
* Established by attachment driver at interrupt priority IPL_SDMMC.
*/
int
sdhc_intr(void)
{
u_int16_t status;
//DPRINTF(1,("shdc_intr():\n"));
//sdhc_dump_regs(&sc_host);
/* Find out which interrupts are pending. */
status = HREAD2(&sc_host, SDHC_NINTR_STATUS);
if (!ISSET(status, SDHC_NINTR_STATUS_MASK)) {
//DPRINTF(1, ("unknown interrupt\n"));
return 0;
}
/* Acknowledge the interrupts we are about to handle. */
HWRITE2(&sc_host, SDHC_NINTR_STATUS, status);
//DPRINTF(2,("sdhc: interrupt status=%d\n", status));
/* Service error interrupts. */
if (ISSET(status, SDHC_ERROR_INTERRUPT)) {
u_int16_t error;
u_int16_t signal;
/* Acknowledge error interrupts. */
error = HREAD2(&sc_host, SDHC_EINTR_STATUS);
signal = HREAD2(&sc_host, SDHC_EINTR_SIGNAL_EN);
HWRITE2(&sc_host, SDHC_EINTR_SIGNAL_EN, 0);
(void)sdhc_soft_reset(&sc_host, SDHC_RESET_DAT|SDHC_RESET_CMD);
if (sc_host.data_command == 1) {
sc_host.data_command = 0;
// TODO: add a way to send commands from irq
// context and uncomment this
// sdmmc_abort();
}
HWRITE2(&sc_host, SDHC_EINTR_STATUS, error);
HWRITE2(&sc_host, SDHC_EINTR_SIGNAL_EN, signal);
//DPRINTF(2,("sdhc: error interrupt, status=%d\n", error));
if (ISSET(error, SDHC_CMD_TIMEOUT_ERROR|
SDHC_DATA_TIMEOUT_ERROR)) {
sc_host.intr_error_status |= error;
sc_host.intr_status |= status;
}
}
/*
* Wake up the blocking process to service command
* related interrupt(s).
*/
if (ISSET(status, SDHC_BUFFER_READ_READY|
SDHC_BUFFER_WRITE_READY|SDHC_COMMAND_COMPLETE|
SDHC_TRANSFER_COMPLETE|SDHC_DMA_INTERRUPT)) {
sc_host.intr_status |= status;
}
/* Service SD card interrupts. */
if (ISSET(status, SDHC_CARD_INTERRUPT)) {
//DPRINTF(0,("sdhc: card interrupt\n"));
HCLR2(&sc_host, SDHC_NINTR_STATUS_EN, SDHC_CARD_INTERRUPT);
}
return 1;
}
#ifdef SDHC_DEBUG
void
sdhc_dump_regs(struct sdhc_host *hp)
{
dbgprintf("0x%02x PRESENT_STATE: %x\n", SDHC_PRESENT_STATE,
HREAD4(hp, SDHC_PRESENT_STATE));
dbgprintf("0x%02x POWER_CTL: %x\n", SDHC_POWER_CTL,
HREAD1(hp, SDHC_POWER_CTL));
dbgprintf("0x%02x NINTR_STATUS: %x\n", SDHC_NINTR_STATUS,
HREAD2(hp, SDHC_NINTR_STATUS));
dbgprintf("0x%02x EINTR_STATUS: %x\n", SDHC_EINTR_STATUS,
HREAD2(hp, SDHC_EINTR_STATUS));
dbgprintf("0x%02x NINTR_STATUS_EN: %x\n", SDHC_NINTR_STATUS_EN,
HREAD2(hp, SDHC_NINTR_STATUS_EN));
dbgprintf("0x%02x EINTR_STATUS_EN: %x\n", SDHC_EINTR_STATUS_EN,
HREAD2(hp, SDHC_EINTR_STATUS_EN));
dbgprintf("0x%02x NINTR_SIGNAL_EN: %x\n", SDHC_NINTR_SIGNAL_EN,
HREAD2(hp, SDHC_NINTR_SIGNAL_EN));
dbgprintf("0x%02x EINTR_SIGNAL_EN: %x\n", SDHC_EINTR_SIGNAL_EN,
HREAD2(hp, SDHC_EINTR_SIGNAL_EN));
dbgprintf("0x%02x CAPABILITIES: %x\n", SDHC_CAPABILITIES,
HREAD4(hp, SDHC_CAPABILITIES));
dbgprintf("0x%02x MAX_CAPABILITIES: %x\n", SDHC_MAX_CAPABILITIES,
HREAD4(hp, SDHC_MAX_CAPABILITIES));
}
#endif
#include "hollywood.h"
void sdhc_irq(void)
{
sdhc_intr();
}
void sdhc_init(void)
{
sdhc_host_found(0, SDHC_REG_BASE, 1);
//sdhc_host_found(0, SDHC_REG_BASE + 0x100, 1);
//sdhc_host_found(0, 0x0d080000, 1);
}
void sdhc_exit(void)
{
sdhc_shutdown();
}

210
sdhc.h Normal file
View File

@ -0,0 +1,210 @@
/* $OpenBSD: sdhcvar.h,v 1.3 2007/09/06 08:01:01 jsg Exp $ */
/*
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
* Copyright (c) 2009 Sven Peter <svenpeter@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _SDHCVAR_H_
#define _SDHCVAR_H_
#include "bsdtypes.h"
#ifdef CAN_HAZ_IPC
#include "ipc.h"
#endif
#include "sdmmc.h"
struct sdhc_host {
bus_space_tag_t iot; /* host register set tag */
bus_space_handle_t ioh; /* host register set handle */
u_int clkbase; /* base clock frequency in KHz */
int flags; /* flags for this host */
u_int32_t ocr; /* OCR value from capabilities */
u_int8_t regs[14]; /* host controller state */
u_int16_t intr_status; /* soft interrupt status */
u_int16_t intr_error_status; /* soft error status */
int data_command;
};
extern struct sdhc_host sc_host;
/* Host controller functions called by the attachment driver. */
int sdhc_host_found(bus_space_tag_t, bus_space_handle_t, int);
void sdhc_power(int, void *);
void sdhc_shutdown(void);
int sdhc_intr(void);
void sdhc_init(void);
void sdhc_exit(void);
void sdhc_irq(void);
#ifdef CAN_HAZ_IPC
void sdhc_ipc(volatile ipc_request *req);
#endif
/* Host standard register set */
#define SDHC_DMA_ADDR 0x00
#define SDHC_BLOCK_SIZE 0x04
#define SDHC_BLOCK_COUNT 0x06
#define SDHC_BLOCK_COUNT_MAX 512
#define SDHC_ARGUMENT 0x08
#define SDHC_TRANSFER_MODE 0x0c
#define SDHC_MULTI_BLOCK_MODE (1<<5)
#define SDHC_READ_MODE (1<<4)
#define SDHC_AUTO_CMD12_ENABLE (1<<2)
#define SDHC_BLOCK_COUNT_ENABLE (1<<1)
#define SDHC_DMA_ENABLE (1<<0)
#define SDHC_COMMAND 0x0e
/* 14-15 reserved */
#define SDHC_COMMAND_INDEX_SHIFT 8
#define SDHC_COMMAND_INDEX_MASK 0x3f
#define SDHC_COMMAND_TYPE_ABORT (3<<6)
#define SDHC_COMMAND_TYPE_RESUME (2<<6)
#define SDHC_COMMAND_TYPE_SUSPEND (1<<6)
#define SDHC_COMMAND_TYPE_NORMAL (0<<6)
#define SDHC_DATA_PRESENT_SELECT (1<<5)
#define SDHC_INDEX_CHECK_ENABLE (1<<4)
#define SDHC_CRC_CHECK_ENABLE (1<<3)
/* 2 reserved */
#define SDHC_RESP_LEN_48_CHK_BUSY (3<<0)
#define SDHC_RESP_LEN_48 (2<<0)
#define SDHC_RESP_LEN_136 (1<<0)
#define SDHC_NO_RESPONSE (0<<0)
#define SDHC_RESPONSE 0x10 /* - 0x1f */
#define SDHC_DATA 0x20
#define SDHC_PRESENT_STATE 0x24
/* 25-31 reserved */
#define SDHC_CMD_LINE_SIGNAL_LEVEL (1<<24)
#define SDHC_DAT3_LINE_LEVEL (1<<23)
#define SDHC_DAT2_LINE_LEVEL (1<<22)
#define SDHC_DAT1_LINE_LEVEL (1<<21)
#define SDHC_DAT0_LINE_LEVEL (1<<20)
#define SDHC_WRITE_PROTECT_SWITCH (1<<19)
#define SDHC_CARD_DETECT_PIN_LEVEL (1<<18)
#define SDHC_CARD_STATE_STABLE (1<<17)
#define SDHC_CARD_INSERTED (1<<16)
/* 12-15 reserved */
#define SDHC_BUFFER_READ_ENABLE (1<<11)
#define SDHC_BUFFER_WRITE_ENABLE (1<<10)
#define SDHC_READ_TRANSFER_ACTIVE (1<<9)
#define SDHC_WRITE_TRANSFER_ACTIVE (1<<8)
/* 3-7 reserved */
#define SDHC_DAT_ACTIVE (1<<2)
#define SDHC_CMD_INHIBIT_DAT (1<<1)
#define SDHC_CMD_INHIBIT_CMD (1<<0)
#define SDHC_CMD_INHIBIT_MASK 0x0003
#define SDHC_HOST_CTL 0x28
#define SDHC_HIGH_SPEED (1<<2)
#define SDHC_4BIT_MODE (1<<1)
#define SDHC_LED_ON (1<<0)
#define SDHC_POWER_CTL 0x29
#define SDHC_VOLTAGE_SHIFT 1
#define SDHC_VOLTAGE_MASK 0x07
#define SDHC_VOLTAGE_3_3V 0x07
#define SDHC_VOLTAGE_3_0V 0x06
#define SDHC_VOLTAGE_1_8V 0x05
#define SDHC_BUS_POWER (1<<0)
#define SDHC_BLOCK_GAP_CTL 0x2a
#define SDHC_WAKEUP_CTL 0x2b
#define SDHC_CLOCK_CTL 0x2c
#define SDHC_SDCLK_DIV_SHIFT 8
#define SDHC_SDCLK_DIV_MASK 0xff
#define SDHC_SDCLK_ENABLE (1<<2)
#define SDHC_INTCLK_STABLE (1<<1)
#define SDHC_INTCLK_ENABLE (1<<0)
#define SDHC_TIMEOUT_CTL 0x2e
#define SDHC_TIMEOUT_MAX 0x0e
#define SDHC_SOFTWARE_RESET 0x2f
#define SDHC_RESET_MASK 0x5
#define SDHC_RESET_DAT (1<<2)
#define SDHC_RESET_CMD (1<<1)
#define SDHC_RESET_ALL (1<<0)
#define SDHC_NINTR_STATUS 0x30
#define SDHC_ERROR_INTERRUPT (1<<15)
#define SDHC_ERROR_TIMEOUT (1<<14)
#define SDHC_CARD_INTERRUPT (1<<8)
#define SDHC_CARD_REMOVAL (1<<7)
#define SDHC_CARD_INSERTION (1<<6)
#define SDHC_BUFFER_READ_READY (1<<5)
#define SDHC_BUFFER_WRITE_READY (1<<4)
#define SDHC_DMA_INTERRUPT (1<<3)
#define SDHC_BLOCK_GAP_EVENT (1<<2)
#define SDHC_TRANSFER_COMPLETE (1<<1)
#define SDHC_COMMAND_COMPLETE (1<<0)
#define SDHC_NINTR_STATUS_MASK 0x81ff
#define SDHC_EINTR_STATUS 0x32
#define SDHC_ADMA_ERROR (1<<9)
#define SDHC_AUTO_CMD12_ERROR (1<<8)
#define SDHC_CURRENT_LIMIT_ERROR (1<<7)
#define SDHC_DATA_END_BIT_ERROR (1<<6)
#define SDHC_DATA_CRC_ERROR (1<<5)
#define SDHC_DATA_TIMEOUT_ERROR (1<<4)
#define SDHC_DATA_ERROR 0x70
#define SDHC_CMD_INDEX_ERROR (1<<3)
#define SDHC_CMD_END_BIT_ERROR (1<<2)
#define SDHC_CMD_CRC_ERROR (1<<1)
#define SDHC_CMD_TIMEOUT_ERROR (1<<0)
#define SDHC_CMD_ERROR 0x0f
#define SDHC_EINTR_STATUS_MASK 0x03ff /* excluding vendor signals */
#define SDHC_NINTR_STATUS_EN 0x34
#define SDHC_EINTR_STATUS_EN 0x36
#define SDHC_NINTR_SIGNAL_EN 0x38
#define SDHC_NINTR_SIGNAL_MASK 0x01ff
#define SDHC_EINTR_SIGNAL_EN 0x3a
#define SDHC_EINTR_SIGNAL_MASK 0x03ff /* excluding vendor signals */
#define SDHC_CMD12_ERROR_STATUS 0x3c
#define SDHC_CAPABILITIES 0x40
#define SDHC_VOLTAGE_SUPP_1_8V (1<<26)
#define SDHC_VOLTAGE_SUPP_3_0V (1<<25)
#define SDHC_VOLTAGE_SUPP_3_3V (1<<24)
#define SDHC_DMA_SUPPORT (1<<22)
#define SDHC_HIGH_SPEED_SUPP (1<<21)
#define SDHC_BASE_FREQ_SHIFT 8
#define SDHC_BASE_FREQ_MASK 0x3f
#define SDHC_TIMEOUT_FREQ_UNIT (1<<7) /* 0=KHz, 1=MHz */
#define SDHC_TIMEOUT_FREQ_SHIFT 0
#define SDHC_TIMEOUT_FREQ_MASK 0x1f
#define SDHC_MAX_CAPABILITIES 0x48
#define SDHC_SLOT_INTR_STATUS 0xfc
#define SDHC_HOST_CTL_VERSION 0xfe
#define SDHC_SPEC_VERS_SHIFT 0
#define SDHC_SPEC_VERS_MASK 0xff
#define SDHC_VENDOR_VERS_SHIFT 8
#define SDHC_VENDOR_VERS_MASK 0xff
/* SDHC_CAPABILITIES decoding */
#define SDHC_BASE_FREQ_KHZ(cap) \
((((cap) >> SDHC_BASE_FREQ_SHIFT) & SDHC_BASE_FREQ_MASK) * 1000)
#define SDHC_TIMEOUT_FREQ(cap) \
(((cap) >> SDHC_TIMEOUT_FREQ_SHIFT) & SDHC_TIMEOUT_FREQ_MASK)
#define SDHC_TIMEOUT_FREQ_KHZ(cap) \
(((cap) & SDHC_TIMEOUT_FREQ_UNIT) ? \
SDHC_TIMEOUT_FREQ(cap) * 1000: \
SDHC_TIMEOUT_FREQ(cap))
/* SDHC_HOST_CTL_VERSION decoding */
#define SDHC_SPEC_VERSION(hcv) \
(((hcv) >> SDHC_SPEC_VERS_SHIFT) & SDHC_SPEC_VERS_MASK)
#define SDHC_VENDOR_VERSION(hcv) \
(((hcv) >> SDHC_VENDOR_VERS_SHIFT) & SDHC_VENDOR_VERS_MASK)
struct sdmmc_command;
int sdhc_host_reset(struct sdhc_host *hp);
int sdhc_card_detect(struct sdhc_host *hp);
int sdhc_bus_power(struct sdhc_host *hp, u_int32_t);
int sdhc_bus_clock(struct sdhc_host *hp, int);
void sdhc_card_intr_mask(struct sdhc_host *hp, int);
void sdhc_card_intr_ack(struct sdhc_host *hp);
void sdhc_exec_command(struct sdhc_host *hp, struct sdmmc_command *);
#endif

172
sdhcreg.h Normal file
View File

@ -0,0 +1,172 @@
/* $OpenBSD: sdhcreg.h,v 1.4 2006/07/30 17:20:40 fgsch Exp $ */
/*
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _SDHCREG_H_
#define _SDHCREG_H_
/* Host standard register set */
#define SDHC_DMA_ADDR 0x00
#define SDHC_BLOCK_SIZE 0x04
#define SDHC_BLOCK_COUNT 0x06
#define SDHC_BLOCK_COUNT_MAX 512
#define SDHC_ARGUMENT 0x08
#define SDHC_TRANSFER_MODE 0x0c
#define SDHC_MULTI_BLOCK_MODE (1<<5)
#define SDHC_READ_MODE (1<<4)
#define SDHC_AUTO_CMD12_ENABLE (1<<2)
#define SDHC_BLOCK_COUNT_ENABLE (1<<1)
#define SDHC_DMA_ENABLE (1<<0)
#define SDHC_COMMAND 0x0e
/* 14-15 reserved */
#define SDHC_COMMAND_INDEX_SHIFT 8
#define SDHC_COMMAND_INDEX_MASK 0x3f
#define SDHC_COMMAND_TYPE_ABORT (3<<6)
#define SDHC_COMMAND_TYPE_RESUME (2<<6)
#define SDHC_COMMAND_TYPE_SUSPEND (1<<6)
#define SDHC_COMMAND_TYPE_NORMAL (0<<6)
#define SDHC_DATA_PRESENT_SELECT (1<<5)
#define SDHC_INDEX_CHECK_ENABLE (1<<4)
#define SDHC_CRC_CHECK_ENABLE (1<<3)
/* 2 reserved */
#define SDHC_RESP_LEN_48_CHK_BUSY (3<<0)
#define SDHC_RESP_LEN_48 (2<<0)
#define SDHC_RESP_LEN_136 (1<<0)
#define SDHC_NO_RESPONSE (0<<0)
#define SDHC_RESPONSE 0x10 /* - 0x1f */
#define SDHC_DATA 0x20
#define SDHC_PRESENT_STATE 0x24
/* 25-31 reserved */
#define SDHC_CMD_LINE_SIGNAL_LEVEL (1<<24)
#define SDHC_DAT3_LINE_LEVEL (1<<23)
#define SDHC_DAT2_LINE_LEVEL (1<<22)
#define SDHC_DAT1_LINE_LEVEL (1<<21)
#define SDHC_DAT0_LINE_LEVEL (1<<20)
#define SDHC_WRITE_PROTECT_SWITCH (1<<19)
#define SDHC_CARD_DETECT_PIN_LEVEL (1<<18)
#define SDHC_CARD_STATE_STABLE (1<<17)
#define SDHC_CARD_INSERTED (1<<16)
/* 12-15 reserved */
#define SDHC_BUFFER_READ_ENABLE (1<<11)
#define SDHC_BUFFER_WRITE_ENABLE (1<<10)
#define SDHC_READ_TRANSFER_ACTIVE (1<<9)
#define SDHC_WRITE_TRANSFER_ACTIVE (1<<8)
/* 3-7 reserved */
#define SDHC_DAT_ACTIVE (1<<2)
#define SDHC_CMD_INHIBIT_DAT (1<<1)
#define SDHC_CMD_INHIBIT_CMD (1<<0)
#define SDHC_CMD_INHIBIT_MASK 0x0003
#define SDHC_HOST_CTL 0x28
#define SDHC_HIGH_SPEED (1<<2)
#define SDHC_4BIT_MODE (1<<1)
#define SDHC_LED_ON (1<<0)
#define SDHC_POWER_CTL 0x29
#define SDHC_VOLTAGE_SHIFT 1
#define SDHC_VOLTAGE_MASK 0x07
#define SDHC_VOLTAGE_3_3V 0x07
#define SDHC_VOLTAGE_3_0V 0x06
#define SDHC_VOLTAGE_1_8V 0x05
#define SDHC_BUS_POWER (1<<0)
#define SDHC_BLOCK_GAP_CTL 0x2a
#define SDHC_WAKEUP_CTL 0x2b
#define SDHC_CLOCK_CTL 0x2c
#define SDHC_SDCLK_DIV_SHIFT 8
#define SDHC_SDCLK_DIV_MASK 0xff
#define SDHC_SDCLK_ENABLE (1<<2)
#define SDHC_INTCLK_STABLE (1<<1)
#define SDHC_INTCLK_ENABLE (1<<0)
#define SDHC_TIMEOUT_CTL 0x2e
#define SDHC_TIMEOUT_MAX 0x0e
#define SDHC_SOFTWARE_RESET 0x2f
#define SDHC_RESET_MASK 0x5
#define SDHC_RESET_DAT (1<<2)
#define SDHC_RESET_CMD (1<<1)
#define SDHC_RESET_ALL (1<<0)
#define SDHC_NINTR_STATUS 0x30
#define SDHC_ERROR_INTERRUPT (1<<15)
#define SDHC_CARD_INTERRUPT (1<<8)
#define SDHC_CARD_REMOVAL (1<<7)
#define SDHC_CARD_INSERTION (1<<6)
#define SDHC_BUFFER_READ_READY (1<<5)
#define SDHC_BUFFER_WRITE_READY (1<<4)
#define SDHC_DMA_INTERRUPT (1<<3)
#define SDHC_BLOCK_GAP_EVENT (1<<2)
#define SDHC_TRANSFER_COMPLETE (1<<1)
#define SDHC_COMMAND_COMPLETE (1<<0)
#define SDHC_NINTR_STATUS_MASK 0x81ff
#define SDHC_EINTR_STATUS 0x32
#define SDHC_ADMA_ERROR (1<<9)
#define SDHC_AUTO_CMD12_ERROR (1<<8)
#define SDHC_CURRENT_LIMIT_ERROR (1<<7)
#define SDHC_DATA_END_BIT_ERROR (1<<6)
#define SDHC_DATA_CRC_ERROR (1<<5)
#define SDHC_DATA_TIMEOUT_ERROR (1<<4)
#define SDHC_DATA_ERROR 0x70
#define SDHC_CMD_INDEX_ERROR (1<<3)
#define SDHC_CMD_END_BIT_ERROR (1<<2)
#define SDHC_CMD_CRC_ERROR (1<<1)
#define SDHC_CMD_TIMEOUT_ERROR (1<<0)
#define SDHC_CMD_ERROR 0x0f
#define SDHC_EINTR_STATUS_MASK 0x03ff /* excluding vendor signals */
#define SDHC_NINTR_STATUS_EN 0x34
#define SDHC_EINTR_STATUS_EN 0x36
#define SDHC_NINTR_SIGNAL_EN 0x38
#define SDHC_NINTR_SIGNAL_MASK 0x01ff
#define SDHC_EINTR_SIGNAL_EN 0x3a
#define SDHC_EINTR_SIGNAL_MASK 0x03ff /* excluding vendor signals */
#define SDHC_CMD12_ERROR_STATUS 0x3c
#define SDHC_CAPABILITIES 0x40
#define SDHC_VOLTAGE_SUPP_1_8V (1<<26)
#define SDHC_VOLTAGE_SUPP_3_0V (1<<25)
#define SDHC_VOLTAGE_SUPP_3_3V (1<<24)
#define SDHC_DMA_SUPPORT (1<<22)
#define SDHC_HIGH_SPEED_SUPP (1<<21)
#define SDHC_MAX_BLK_LEN_512 0
#define SDHC_MAX_BLK_LEN_1024 1
#define SDHC_MAX_BLK_LEN_2048 2
#define SDHC_MAX_BLK_LEN_SHIFT 16
#define SDHC_MAX_BLK_LEN_MASK 0x3
#define SDHC_BASE_FREQ_SHIFT 8
#define SDHC_BASE_FREQ_MASK 0x3f
#define SDHC_TIMEOUT_FREQ_UNIT (1<<7) /* 0=KHz, 1=MHz */
#define SDHC_TIMEOUT_FREQ_SHIFT 0
#define SDHC_TIMEOUT_FREQ_MASK 0x1f
#define SDHC_MAX_CAPABILITIES 0x48
#define SDHC_SLOT_INTR_STATUS 0xfc
#define SDHC_HOST_CTL_VERSION 0xfe
#define SDHC_SPEC_VERS_SHIFT 0
#define SDHC_SPEC_VERS_MASK 0xff
#define SDHC_VENDOR_VERS_SHIFT 8
#define SDHC_VENDOR_VERS_MASK 0xff
/* SDHC_CAPABILITIES decoding */
#define SDHC_BASE_FREQ_KHZ(cap) \
((((cap) >> SDHC_BASE_FREQ_SHIFT) & SDHC_BASE_FREQ_MASK) * 1000)
#define SDHC_TIMEOUT_FREQ(cap) \
(((cap) >> SDHC_TIMEOUT_FREQ_SHIFT) & SDHC_TIMEOUT_FREQ_MASK)
#define SDHC_TIMEOUT_FREQ_KHZ(cap) \
(((cap) & SDHC_TIMEOUT_FREQ_UNIT) ? \
SDHC_TIMEOUT_FREQ(cap) * 1000: \
SDHC_TIMEOUT_FREQ(cap))
/* SDHC_HOST_CTL_VERSION decoding */
#define SDHC_SPEC_VERSION(hcv) \
(((hcv) >> SDHC_SPEC_VERS_SHIFT) & SDHC_SPEC_VERS_MASK)
#define SDHC_VENDOR_VERSION(hcv) \
(((hcv) >> SDHC_VENDOR_VERS_SHIFT) & SDHC_VENDOR_VERS_MASK)
#endif

62
sdhcvar.h Normal file
View File

@ -0,0 +1,62 @@
/* $OpenBSD: sdhcvar.h,v 1.3 2007/09/06 08:01:01 jsg Exp $ */
/*
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
* Copyright (c) 2009 Sven Peter <svenpeter@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _SDHCVAR_H_
#define _SDHCVAR_H_
#include "bsdtypes.h"
#define SDHC_MAX_HOSTS 4
struct sdhc_host {
struct sdhc_softc *sc; /* host controller device */
struct device *sdmmc; /* generic SD/MMC device */
bus_space_tag_t iot; /* host register set tag */
bus_space_handle_t ioh; /* host register set handle */
u_int clkbase; /* base clock frequency in KHz */
int maxblklen; /* maximum block length */
int flags; /* flags for this host */
u_int32_t ocr; /* OCR value from capabilities */
u_int8_t regs[14]; /* host controller state */
u_int16_t intr_status; /* soft interrupt status */
u_int16_t intr_error_status; /* soft error status */
int data_command;
};
struct sdhc_softc {
struct device sc_dev;
struct sdhc_host sc_host[SDHC_MAX_HOSTS];
int sc_nhosts;
u_int sc_flags;
};
/* Host controller functions called by the attachment driver. */
int sdhc_host_found(struct sdhc_softc *, bus_space_tag_t,
bus_space_handle_t, int);
void sdhc_power(int, void *);
void sdhc_shutdown(void *);
int sdhc_intr(void *);
void SDHCInit(void);
void sdhc_irq(void);
/* flag values */
#define SDHC_F_NOPWR0 (1 << 0)
#endif

373
sdmmc.c Normal file
View File

@ -0,0 +1,373 @@
/*
mini - a Free Software replacement for the Nintendo/BroadOn IOS.
SD/MMC interface
Copyright (C) 2008, 2009 Sven Peter <svenpeter@gmail.com>
# This code is licensed to you under the terms of the GNU GPL, version 2;
# see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
*/
#include "bsdtypes.h"
#include "sdhc.h"
#include "string.h"
#include "utils.h"
//#define SDMMC_DEBUG
#ifdef SDMMC_DEBUG
static int sdmmcdebug = 0;
#define DPRINTF(n,s) do { if ((n) <= sdmmcdebug) dbgprintf s; } while (0)
#else
#define DPRINTF(n,s) do {} while(0)
#endif
struct sdmmc_card {
sdmmc_chipset_handle_t handle;
int inserted;
int sdhc_blockmode;
int selected;
int new_card; // set to 1 everytime a new card is inserted
u32 timeout;
u32 num_sectors;
u32 cid;
u16 rca;
};
#ifdef LOADER
static struct sdmmc_card card;
#else
static struct sdmmc_card card;
#endif
void sdmmc_attach(sdmmc_chipset_handle_t handle)
{
memset8(&card, 0, sizeof(card));
card.handle = handle;
//DPRINTF(0, ("sdmmc: attached new SD/MMC card\n"));
sdhc_host_reset(card.handle);
if (sdhc_card_detect(card.handle)) {
//DPRINTF(1, ("card is inserted. starting init sequence.\n"));
sdmmc_needs_discover();
}
}
void sdmmc_abort(void) {
struct sdmmc_command cmd;
//dbgprintf("abortion kthx\n");
memset8(&cmd, 0, sizeof(cmd));
cmd.c_opcode = MMC_STOP_TRANSMISSION;
cmd.c_arg = 0;
cmd.c_flags = SCF_RSP_R1B;
sdhc_exec_command(card.handle, &cmd);
}
void sdmmc_needs_discover(void)
{
struct sdmmc_command cmd;
u32 ocr;
//DPRINTF(0, ("sdmmc: card needs discovery.\n"));
sdhc_host_reset(card.handle);
card.new_card = 1;
if (!sdhc_card_detect(card.handle)) {
//DPRINTF(1, ("sdmmc: card (no longer?) inserted.\n"));
card.inserted = 0;
return;
}
if (sdhc_bus_power(card.handle, 1) != 0) {
//dbgprintf("sdmmc: powerup failed for card\n");
goto out;
}
if (sdhc_bus_clock(card.handle, SDMMC_DEFAULT_CLOCK) != 0) {
//dbgprintf("sdmmc: could not enable clock for card\n");
goto out_power;
}
memset8(&cmd, 0, sizeof(cmd));
cmd.c_opcode = MMC_GO_IDLE_STATE;
cmd.c_flags = SCF_RSP_R0;
sdhc_exec_command(card.handle, &cmd);
if (cmd.c_error) {
//dbgprintf("sdmmc: GO_IDLE_STATE failed with %d\n", cmd.c_error);
goto out_clock;
}
memset8(&cmd, 0, sizeof(cmd));
cmd.c_opcode = SD_SEND_IF_COND;
cmd.c_arg = 0x1aa;
cmd.c_flags = SCF_RSP_R7;
cmd.c_timeout = 100;
sdhc_exec_command(card.handle, &cmd);
ocr = card.handle->ocr;
if (cmd.c_error || (cmd.c_resp[0] & 0xff) != 0xaa)
ocr &= ~SD_OCR_SDHC_CAP;
else
ocr |= SD_OCR_SDHC_CAP;
int tries;
for (tries = 100; tries > 0; tries--) {
udelay(100000);
memset8(&cmd, 0, sizeof(cmd));
cmd.c_opcode = MMC_APP_CMD;
cmd.c_arg = 0;
cmd.c_flags = SCF_RSP_R1;
sdhc_exec_command(card.handle, &cmd);
if (cmd.c_error)
continue;
memset8(&cmd, 0, sizeof(cmd));
cmd.c_opcode = SD_APP_OP_COND;
cmd.c_arg = ocr;
cmd.c_flags = SCF_RSP_R3;
sdhc_exec_command(card.handle, &cmd);
if (cmd.c_error)
continue;
if (ISSET(MMC_R1(cmd.c_resp), MMC_OCR_MEM_READY))
break;
}
if (!ISSET(cmd.c_resp[0], MMC_OCR_MEM_READY)) {
//dbgprintf("sdmmc: card failed to powerup.\n");
goto out_power;
}
if (ISSET(MMC_R1(cmd.c_resp), SD_OCR_SDHC_CAP))
card.sdhc_blockmode = 1;
else
card.sdhc_blockmode = 0;
u8 *resp;
memset8(&cmd, 0, sizeof(cmd));
cmd.c_opcode = MMC_ALL_SEND_CID;
cmd.c_arg = 0;
cmd.c_flags = SCF_RSP_R2;
sdhc_exec_command(card.handle, &cmd);
if (cmd.c_error) {
goto out_clock;
}
card.cid = MMC_R1(cmd.c_resp);
resp = (u8 *)cmd.c_resp;
memset8(&cmd, 0, sizeof(cmd));
cmd.c_opcode = SD_SEND_RELATIVE_ADDR;
cmd.c_arg = 0;
cmd.c_flags = SCF_RSP_R6;
sdhc_exec_command(card.handle, &cmd);
if (cmd.c_error) {
//dbgprintf("sdmmc: SD_SEND_RCA failed with %d\n", cmd.c_error);
goto out_clock;
}
card.rca = MMC_R1(cmd.c_resp)>>16;
card.selected = 0;
card.inserted = 1;
memset8(&cmd, 0, sizeof(cmd));
cmd.c_opcode = MMC_SEND_CSD;
cmd.c_arg = ((u32)card.rca)<<16;
cmd.c_flags = SCF_RSP_R2;
sdhc_exec_command(card.handle, &cmd);
if (cmd.c_error) {
//dbgprintf("sdmmc: MMC_SEND_CSD failed with %d\n", cmd.c_error);
goto out_power;
}
resp = (u8 *)cmd.c_resp;
if (resp[13] == 0xe) { // sdhc
unsigned int c_size = resp[7] << 16 | resp[6] << 8 | resp[5];
//dbgprintf("sdmmc: sdhc mode, c_size=%u, card size = %uk\n", c_size, (c_size + 1)* 512);
card.timeout = 250 * 1000000; // spec says read timeout is 100ms and write/erase timeout is 250ms
card.num_sectors = (c_size + 1) * 1024; // number of 512-byte sectors
}
else {
unsigned int taac, nsac, read_bl_len, c_size, c_size_mult;
taac = resp[13];
nsac = resp[12];
read_bl_len = resp[9] & 0xF;
c_size = (resp[8] & 3) << 10;
c_size |= (resp[7] << 2);
c_size |= (resp[6] >> 6);
c_size_mult = (resp[5] & 3) << 1;
c_size_mult |= resp[4] >> 7;
//dbgprintf("taac=%u nsac=%u read_bl_len=%u c_size=%u c_size_mult=%u card size=%u bytes\n",
// taac, nsac, read_bl_len, c_size, c_size_mult, (c_size + 1) * (4 << c_size_mult) * (1 << read_bl_len));
static const unsigned int time_unit[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000};
static const unsigned int time_value[] = {1, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80}; // must div by 10
card.timeout = time_unit[taac & 7] * time_value[(taac >> 3) & 0xf] / 10;
//dbgprintf("calculated timeout = %uns\n", card.timeout);
card.num_sectors = (c_size + 1) * (4 << c_size_mult) * (1 << read_bl_len) / 512;
}
sdmmc_select();
memset8(&cmd, 0, sizeof(cmd));
cmd.c_opcode = MMC_SET_BLOCKLEN;
cmd.c_arg = SDMMC_DEFAULT_BLOCKLEN;
cmd.c_flags = SCF_RSP_R1;
sdhc_exec_command(card.handle, &cmd);
if (cmd.c_error) {
//dbgprintf("sdmmc: MMC_SET_BLOCKLEN failed with %d\n", cmd.c_error);
card.inserted = card.selected = 0;
goto out_clock;
}
return;
out_clock:
sdhc_bus_clock(card.handle, SDMMC_SDCLK_OFF);
out_power:
sdhc_bus_power(card.handle, 0);
out:
return;
}
int sdmmc_select(void)
{
struct sdmmc_command cmd;
memset8(&cmd, 0, sizeof(cmd));
cmd.c_opcode = MMC_SELECT_CARD;
cmd.c_arg = ((u32)card.rca)<<16;
cmd.c_flags = SCF_RSP_R1B;
sdhc_exec_command(card.handle, &cmd);
if (cmd.c_error)
{
return -1;
}
card.selected = 1;
return 0;
}
int sdmmc_check_card(void)
{
if (card.inserted == 0)
return SDMMC_NO_CARD;
if (card.new_card == 1)
return SDMMC_NEW_CARD;
return SDMMC_INSERTED;
}
int sdmmc_ack_card(void)
{
if (card.new_card == 1) {
card.new_card = 0;
return 0;
}
return -1;
}
int sdmmc_read(u32 blk_start, u32 blk_count, void *data)
{
struct sdmmc_command cmd;
if (card.inserted == 0)
{
return -1;
}
if (card.selected == 0) {
if (sdmmc_select() < 0) {
return -1;
}
}
if (card.new_card == 1) {
return -1;
}
memset8(&cmd, 0, sizeof(cmd));
cmd.c_opcode = MMC_READ_BLOCK_MULTIPLE;
if (card.sdhc_blockmode)
cmd.c_arg = blk_start;
else
cmd.c_arg = blk_start * SDMMC_DEFAULT_BLOCKLEN;
cmd.c_data = data;
cmd.c_datalen = blk_count * SDMMC_DEFAULT_BLOCKLEN;
cmd.c_blklen = SDMMC_DEFAULT_BLOCKLEN;
cmd.c_flags = SCF_RSP_R1 | SCF_CMD_READ;
sdhc_exec_command(card.handle, &cmd);
if (cmd.c_error)
{
return -1;
}
return 0;
}
int sdmmc_write(u32 blk_start, u32 blk_count, void *data)
{
struct sdmmc_command cmd;
if (card.inserted == 0) {
return -1;
}
if (card.selected == 0) {
if (sdmmc_select() < 0) {
return -1;
}
}
if (card.new_card == 1) {
return -1;
}
memset8(&cmd, 0, sizeof(cmd));
cmd.c_opcode = MMC_WRITE_BLOCK_MULTIPLE;
if (card.sdhc_blockmode)
cmd.c_arg = blk_start;
else
cmd.c_arg = blk_start * SDMMC_DEFAULT_BLOCKLEN;
cmd.c_data = data;
cmd.c_datalen = blk_count * SDMMC_DEFAULT_BLOCKLEN;
cmd.c_blklen = SDMMC_DEFAULT_BLOCKLEN;
cmd.c_flags = SCF_RSP_R1;
sdhc_exec_command(card.handle, &cmd);
if (cmd.c_error)
{
return -1;
}
return 0;
}
int sdmmc_get_sectors(void)
{
if (card.inserted == 0) {
return -1;
}
if (card.new_card == 1) {
return -1;
}
// sdhc_error(sdhci->reg_base, "num sectors = %u", sdhci->num_sectors);
return card.num_sectors;
}

370
sdmmc.h Normal file
View File

@ -0,0 +1,370 @@
#ifndef __SDMMC_H__
#define __SDMMC_H__
#include "bsdtypes.h"
struct sdmmc_command;
typedef struct sdhc_host * sdmmc_chipset_handle_t;
/* clock frequencies for sdmmc_chip_bus_clock() */
#define SDMMC_SDCLK_OFF 0
#define SDMMC_SDCLK_400KHZ 400
#define SDMMC_SDCLK_25MHZ 25000
struct sdmmc_csd {
int csdver; /* CSD structure format */
int mmcver; /* MMC version (for CID format) */
int capacity; /* total number of sectors */
int sector_size; /* sector size in bytes */
int read_bl_len; /* block length for reads */
/* ... */
};
struct sdmmc_cid {
int mid; /* manufacturer identification number */
int oid; /* OEM/product identification number */
char pnm[8]; /* product name (MMC v1 has the longest) */
int rev; /* product revision */
int psn; /* product serial number */
int mdt; /* manufacturing date */
};
typedef u_int32_t sdmmc_response[4];
struct sdmmc_softc;
struct sdmmc_task {
void (*func)(void *arg);
void *arg;
int onqueue;
struct sdmmc_softc *sc;
};
#define sdmmc_init_task(xtask, xfunc, xarg) do { \
(xtask)->func = (xfunc); \
(xtask)->arg = (xarg); \
(xtask)->onqueue = 0; \
(xtask)->sc = NULL; \
} while (0)
#define sdmmc_task_pending(xtask) ((xtask)->onqueue)
struct sdmmc_command {
// struct sdmmc_task c_task; /* task queue entry */
u_int16_t c_opcode; /* SD or MMC command index */
u_int32_t c_arg; /* SD/MMC command argument */
sdmmc_response c_resp; /* response buffer */
void *c_data; /* buffer to send or read into */
int c_datalen; /* length of data buffer */
int c_blklen; /* block length */
int c_flags; /* see below */
#define SCF_ITSDONE 0x0001 /* command is complete */
#define SCF_CMD(flags) ((flags) & 0x00f0)
#define SCF_CMD_AC 0x0000
#define SCF_CMD_ADTC 0x0010
#define SCF_CMD_BC 0x0020
#define SCF_CMD_BCR 0x0030
#define SCF_CMD_READ 0x0040 /* read command (data expected) */
#define SCF_RSP_BSY 0x0100
#define SCF_RSP_136 0x0200
#define SCF_RSP_CRC 0x0400
#define SCF_RSP_IDX 0x0800
#define SCF_RSP_PRESENT 0x1000
/* response types */
#define SCF_RSP_R0 0 /* none */
#define SCF_RSP_R1 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
#define SCF_RSP_R1B (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX|SCF_RSP_BSY)
#define SCF_RSP_R2 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_136)
#define SCF_RSP_R3 (SCF_RSP_PRESENT)
#define SCF_RSP_R4 (SCF_RSP_PRESENT)
#define SCF_RSP_R5 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
#define SCF_RSP_R5B (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX|SCF_RSP_BSY)
#define SCF_RSP_R6 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
#define SCF_RSP_R7 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
int c_error; /* errno value on completion */
int c_timeout;
/* Host controller owned fields for data xfer in progress */
int c_resid; /* remaining I/O */
u_char *c_buf; /* remaining data */
};
/*
* Decoded PC Card 16 based Card Information Structure (CIS),
* per card (function 0) and per function (1 and greater).
*/
struct sdmmc_cis {
u_int16_t manufacturer;
#define SDMMC_VENDOR_INVALID 0xffff
u_int16_t product;
#define SDMMC_PRODUCT_INVALID 0xffff
u_int8_t function;
#define SDMMC_FUNCTION_INVALID 0xff
u_char cis1_major;
u_char cis1_minor;
char cis1_info_buf[256];
char *cis1_info[4];
};
/*
* Structure describing either an SD card I/O function or a SD/MMC
* memory card from a "stack of cards" that responded to CMD2. For a
* combo card with one I/O function and one memory card, there will be
* two of these structures allocated. Each card slot has such a list
* of sdmmc_function structures.
*/
struct sdmmc_function {
/* common members */
u_int16_t rca; /* relative card address */
int flags;
#define SFF_ERROR 0x0001 /* function is poo; ignore it */
#define SFF_SDHC 0x0002 /* SD High Capacity card */
/* SD card I/O function members */
int number; /* I/O function number or -1 */
struct sdmmc_cis cis; /* decoded CIS */
/* SD/MMC memory card members */
struct sdmmc_csd csd; /* decoded CSD value */
struct sdmmc_cid cid; /* decoded CID value */
sdmmc_response raw_cid; /* temp. storage for decoding */
};
#define SDMMC_LOCK(sc) lockmgr(&(sc)->sc_lock, LK_EXCLUSIVE, NULL)
#define SDMMC_UNLOCK(sc) lockmgr(&(sc)->sc_lock, LK_RELEASE, NULL)
#define SDMMC_ASSERT_LOCKED(sc) \
KASSERT(lockstatus(&((sc))->sc_lock) == LK_EXCLUSIVE)
#ifdef CAN_HAZ_IPC
#include "ipc.h"
#endif
#define SDMMC_DEFAULT_CLOCK 25000
#define SDMMC_DEFAULT_BLOCKLEN 512
#define SDMMC_NO_CARD 1
#define SDMMC_NEW_CARD 2
#define SDMMC_INSERTED 3
int sdmmc_write(u32 blk_start, u32 blk_count, void *data);
void sdmmc_attach(sdmmc_chipset_handle_t handle);
void sdmmc_needs_discover(void);
int sdmmc_select(void);
int sdmmc_check_card(void);
int sdmmc_ack_card(void);
int sdmmc_read(u32 blk_start, u32 blk_count, void *data);
#ifdef CAN_HAZ_IPC
void sdmmc_ipc(volatile ipc_request *req);
#endif
/* MMC commands */ /* response type */
#define MMC_GO_IDLE_STATE 0 /* R0 */
#define MMC_SEND_OP_COND 1 /* R3 */
#define MMC_ALL_SEND_CID 2 /* R2 */
#define MMC_SET_RELATIVE_ADDR 3 /* R1 */
#define MMC_SELECT_CARD 7 /* R1 */
#define MMC_SEND_CSD 9 /* R2 */
#define MMC_STOP_TRANSMISSION 12 /* R1B */
#define MMC_SEND_STATUS 13 /* R1 */
#define MMC_SET_BLOCKLEN 16 /* R1 */
#define MMC_READ_BLOCK_SINGLE 17 /* R1 */
#define MMC_READ_BLOCK_MULTIPLE 18 /* R1 */
#define MMC_SET_BLOCK_COUNT 23 /* R1 */
#define MMC_WRITE_BLOCK_SINGLE 24 /* R1 */
#define MMC_WRITE_BLOCK_MULTIPLE 25 /* R1 */
#define MMC_APP_CMD 55 /* R1 */
/* SD commands */ /* response type */
#define SD_SEND_RELATIVE_ADDR 3 /* R6 */
#define SD_SEND_IF_COND 8 /* R7 */
/* SD application commands */ /* response type */
#define SD_APP_SET_BUS_WIDTH 6 /* R1 */
#define SD_APP_OP_COND 41 /* R3 */
/* OCR bits */
#define MMC_OCR_MEM_READY (1<<31) /* memory power-up status bit */
#define MMC_OCR_3_5V_3_6V (1<<23)
#define MMC_OCR_3_4V_3_5V (1<<22)
#define MMC_OCR_3_3V_3_4V (1<<21)
#define MMC_OCR_3_2V_3_3V (1<<20)
#define MMC_OCR_3_1V_3_2V (1<<19)
#define MMC_OCR_3_0V_3_1V (1<<18)
#define MMC_OCR_2_9V_3_0V (1<<17)
#define MMC_OCR_2_8V_2_9V (1<<16)
#define MMC_OCR_2_7V_2_8V (1<<15)
#define MMC_OCR_2_6V_2_7V (1<<14)
#define MMC_OCR_2_5V_2_6V (1<<13)
#define MMC_OCR_2_4V_2_5V (1<<12)
#define MMC_OCR_2_3V_2_4V (1<<11)
#define MMC_OCR_2_2V_2_3V (1<<10)
#define MMC_OCR_2_1V_2_2V (1<<9)
#define MMC_OCR_2_0V_2_1V (1<<8)
#define MMC_OCR_1_9V_2_0V (1<<7)
#define MMC_OCR_1_8V_1_9V (1<<6)
#define MMC_OCR_1_7V_1_8V (1<<5)
#define MMC_OCR_1_6V_1_7V (1<<4)
#define SD_OCR_SDHC_CAP (1<<30)
#define SD_OCR_VOL_MASK 0xFF8000 /* bits 23:15 */
/* R1 response type bits */
#define MMC_R1_READY_FOR_DATA (1<<8) /* ready for next transfer */
#define MMC_R1_APP_CMD (1<<5) /* app. commands supported */
/* 48-bit response decoding (32 bits w/o CRC) */
#define MMC_R1(resp) ((resp)[0])
#define MMC_R3(resp) ((resp)[0])
#define SD_R6(resp) ((resp)[0])
/* RCA argument and response */
#define MMC_ARG_RCA(rca) ((rca) << 16)
#define SD_R6_RCA(resp) (SD_R6((resp)) >> 16)
/* bus width argument */
#define SD_ARG_BUS_WIDTH_1 0
#define SD_ARG_BUS_WIDTH_4 2
/* MMC R2 response (CSD) */
#define MMC_CSD_CSDVER(resp) MMC_RSP_BITS((resp), 126, 2)
#define MMC_CSD_CSDVER_1_0 1
#define MMC_CSD_CSDVER_2_0 2
#define MMC_CSD_MMCVER(resp) MMC_RSP_BITS((resp), 122, 4)
#define MMC_CSD_MMCVER_1_0 0 /* MMC 1.0 - 1.2 */
#define MMC_CSD_MMCVER_1_4 1 /* MMC 1.4 */
#define MMC_CSD_MMCVER_2_0 2 /* MMC 2.0 - 2.2 */
#define MMC_CSD_MMCVER_3_1 3 /* MMC 3.1 - 3.3 */
#define MMC_CSD_MMCVER_4_0 4 /* MMC 4 */
#define MMC_CSD_READ_BL_LEN(resp) MMC_RSP_BITS((resp), 80, 4)
#define MMC_CSD_C_SIZE(resp) MMC_RSP_BITS((resp), 62, 12)
#define MMC_CSD_CAPACITY(resp) ((MMC_CSD_C_SIZE((resp))+1) << \
(MMC_CSD_C_SIZE_MULT((resp))+2))
#define MMC_CSD_C_SIZE_MULT(resp) MMC_RSP_BITS((resp), 47, 3)
/* MMC v1 R2 response (CID) */
#define MMC_CID_MID_V1(resp) MMC_RSP_BITS((resp), 104, 24)
#define MMC_CID_PNM_V1_CPY(resp, pnm) \
do { \
(pnm)[0] = MMC_RSP_BITS((resp), 96, 8); \
(pnm)[1] = MMC_RSP_BITS((resp), 88, 8); \
(pnm)[2] = MMC_RSP_BITS((resp), 80, 8); \
(pnm)[3] = MMC_RSP_BITS((resp), 72, 8); \
(pnm)[4] = MMC_RSP_BITS((resp), 64, 8); \
(pnm)[5] = MMC_RSP_BITS((resp), 56, 8); \
(pnm)[6] = MMC_RSP_BITS((resp), 48, 8); \
(pnm)[7] = '\0'; \
} while (0)
#define MMC_CID_REV_V1(resp) MMC_RSP_BITS((resp), 40, 8)
#define MMC_CID_PSN_V1(resp) MMC_RSP_BITS((resp), 16, 24)
#define MMC_CID_MDT_V1(resp) MMC_RSP_BITS((resp), 8, 8)
/* MMC v2 R2 response (CID) */
#define MMC_CID_MID_V2(resp) MMC_RSP_BITS((resp), 120, 8)
#define MMC_CID_OID_V2(resp) MMC_RSP_BITS((resp), 104, 16)
#define MMC_CID_PNM_V2_CPY(resp, pnm) \
do { \
(pnm)[0] = MMC_RSP_BITS((resp), 96, 8); \
(pnm)[1] = MMC_RSP_BITS((resp), 88, 8); \
(pnm)[2] = MMC_RSP_BITS((resp), 80, 8); \
(pnm)[3] = MMC_RSP_BITS((resp), 72, 8); \
(pnm)[4] = MMC_RSP_BITS((resp), 64, 8); \
(pnm)[5] = MMC_RSP_BITS((resp), 56, 8); \
(pnm)[6] = '\0'; \
} while (0)
#define MMC_CID_PSN_V2(resp) MMC_RSP_BITS((resp), 16, 32)
/* SD R2 response (CSD) */
#define SD_CSD_CSDVER(resp) MMC_RSP_BITS((resp), 126, 2)
#define SD_CSD_CSDVER_1_0 0
#define SD_CSD_CSDVER_2_0 1
#define SD_CSD_TAAC(resp) MMC_RSP_BITS((resp), 112, 8)
#define SD_CSD_TAAC_1_5_MSEC 0x26
#define SD_CSD_NSAC(resp) MMC_RSP_BITS((resp), 104, 8)
#define SD_CSD_SPEED(resp) MMC_RSP_BITS((resp), 96, 8)
#define SD_CSD_SPEED_25_MHZ 0x32
#define SD_CSD_SPEED_50_MHZ 0x5a
#define SD_CSD_CCC(resp) MMC_RSP_BITS((resp), 84, 12)
#define SD_CSD_CCC_ALL 0x5f5
#define SD_CSD_READ_BL_LEN(resp) MMC_RSP_BITS((resp), 80, 4)
#define SD_CSD_READ_BL_PARTIAL(resp) MMC_RSP_BITS((resp), 79, 1)
#define SD_CSD_WRITE_BLK_MISALIGN(resp) MMC_RSP_BITS((resp), 78, 1)
#define SD_CSD_READ_BLK_MISALIGN(resp) MMC_RSP_BITS((resp), 77, 1)
#define SD_CSD_DSR_IMP(resp) MMC_RSP_BITS((resp), 76, 1)
#define SD_CSD_C_SIZE(resp) MMC_RSP_BITS((resp), 62, 12)
#define SD_CSD_CAPACITY(resp) ((SD_CSD_C_SIZE((resp))+1) << \
(SD_CSD_C_SIZE_MULT((resp))+2))
#define SD_CSD_V2_C_SIZE(resp) MMC_RSP_BITS((resp), 48, 22)
#define SD_CSD_V2_CAPACITY(resp) ((SD_CSD_V2_C_SIZE((resp))+1) << 10)
#define SD_CSD_V2_BL_LEN 0x9 /* 512 */
#define SD_CSD_VDD_R_CURR_MIN(resp) MMC_RSP_BITS((resp), 59, 3)
#define SD_CSD_VDD_R_CURR_MAX(resp) MMC_RSP_BITS((resp), 56, 3)
#define SD_CSD_VDD_W_CURR_MIN(resp) MMC_RSP_BITS((resp), 53, 3)
#define SD_CSD_VDD_W_CURR_MAX(resp) MMC_RSP_BITS((resp), 50, 3)
#define SD_CSD_VDD_RW_CURR_100mA 0x7
#define SD_CSD_VDD_RW_CURR_80mA 0x6
#define SD_CSD_C_SIZE_MULT(resp) MMC_RSP_BITS((resp), 47, 3)
#define SD_CSD_ERASE_BLK_EN(resp) MMC_RSP_BITS((resp), 46, 1)
#define SD_CSD_SECTOR_SIZE(resp) MMC_RSP_BITS((resp), 39, 7) /* +1 */
#define SD_CSD_WP_GRP_SIZE(resp) MMC_RSP_BITS((resp), 32, 7) /* +1 */
#define SD_CSD_WP_GRP_ENABLE(resp) MMC_RSP_BITS((resp), 31, 1)
#define SD_CSD_R2W_FACTOR(resp) MMC_RSP_BITS((resp), 26, 3)
#define SD_CSD_WRITE_BL_LEN(resp) MMC_RSP_BITS((resp), 22, 4)
#define SD_CSD_RW_BL_LEN_2G 0xa
#define SD_CSD_RW_BL_LEN_1G 0x9
#define SD_CSD_WRITE_BL_PARTIAL(resp) MMC_RSP_BITS((resp), 21, 1)
#define SD_CSD_FILE_FORMAT_GRP(resp) MMC_RSP_BITS((resp), 15, 1)
#define SD_CSD_COPY(resp) MMC_RSP_BITS((resp), 14, 1)
#define SD_CSD_PERM_WRITE_PROTECT(resp) MMC_RSP_BITS((resp), 13, 1)
#define SD_CSD_TMP_WRITE_PROTECT(resp) MMC_RSP_BITS((resp), 12, 1)
#define SD_CSD_FILE_FORMAT(resp) MMC_RSP_BITS((resp), 10, 2)
/* SD R2 response (CID) */
#define SD_CID_MID(resp) MMC_RSP_BITS((resp), 120, 8)
#define SD_CID_OID(resp) MMC_RSP_BITS((resp), 104, 16)
#define SD_CID_PNM_CPY(resp, pnm) \
do { \
(pnm)[0] = MMC_RSP_BITS((resp), 96, 8); \
(pnm)[1] = MMC_RSP_BITS((resp), 88, 8); \
(pnm)[2] = MMC_RSP_BITS((resp), 80, 8); \
(pnm)[3] = MMC_RSP_BITS((resp), 72, 8); \
(pnm)[4] = MMC_RSP_BITS((resp), 64, 8); \
(pnm)[5] = '\0'; \
} while (0)
#define SD_CID_REV(resp) MMC_RSP_BITS((resp), 56, 8)
#define SD_CID_PSN(resp) MMC_RSP_BITS((resp), 24, 32)
#define SD_CID_MDT(resp) MMC_RSP_BITS((resp), 8, 12)
/* Might be slow, but it should work on big and little endian systems. */
#define MMC_RSP_BITS(resp, start, len) __bitfield((resp), (start)-8, (len))
static __inline int
__bitfield(u_int32_t *src, int start, int len)
{
u_int8_t *sp;
u_int32_t dst, mask;
int shift, bs, bc;
if (start < 0 || len < 0 || len > 32)
return 0;
dst = 0;
mask = len % 32 ? UINT_MAX >> (32 - (len % 32)) : UINT_MAX;
shift = 0;
while (len > 0) {
sp = (u_int8_t *)src + start / 8;
bs = start % 8;
bc = 8 - bs;
if (bc > len)
bc = len;
dst |= (*sp++ >> bs) << shift;
shift += bc;
start += bc;
len -= bc;
}
dst &= mask;
return (int)dst;
}
#endif

83
sdmmcchip.h Normal file
View File

@ -0,0 +1,83 @@
/* $OpenBSD: sdmmcchip.h,v 1.4 2009/02/20 19:16:35 miod Exp $ */
/*
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _SDMMC_CHIP_H_
#define _SDMMC_CHIP_H_
struct sdmmc_command;
typedef struct sdmmc_chip_functions *sdmmc_chipset_tag_t;
typedef void *sdmmc_chipset_handle_t;
struct sdmmc_chip_functions {
/* host controller reset */
int (*host_reset)(sdmmc_chipset_handle_t);
/* host capabilities */
u_int32_t (*host_ocr)(sdmmc_chipset_handle_t);
int (*host_maxblklen)(sdmmc_chipset_handle_t);
/* card detection */
int (*card_detect)(sdmmc_chipset_handle_t);
/* bus power and clock frequency */
int (*bus_power)(sdmmc_chipset_handle_t, u_int32_t);
int (*bus_clock)(sdmmc_chipset_handle_t, int);
/* command execution */
void (*exec_command)(sdmmc_chipset_handle_t,
struct sdmmc_command *);
/* bus width */
void (*set_bus_width)(sdmmc_chipset_handle_t, int);
};
/* host controller reset */
#define sdmmc_chip_host_reset(tag, handle) \
((tag)->host_reset((handle)))
/* host capabilities */
#define sdmmc_chip_host_ocr(tag, handle) \
((tag)->host_ocr((handle)))
#define sdmmc_chip_host_maxblklen(tag, handle) \
((tag)->host_maxblklen((handle)))
/* card detection */
#define sdmmc_chip_card_detect(tag, handle) \
((tag)->card_detect((handle)))
/* bus power and clock frequency */
#define sdmmc_chip_bus_power(tag, handle, ocr) \
((tag)->bus_power((handle), (ocr)))
#define sdmmc_chip_bus_clock(tag, handle, freq) \
((tag)->bus_clock((handle), (freq)))
/* command execution */
#define sdmmc_chip_exec_command(tag, handle, cmdp) \
((tag)->exec_command((handle), (cmdp)))
/* bus widht */
#define sdmmc_chip_set_bus_width(tag, handle, enable) \
((tag)->set_bus_width((handle), (enable)))
/* clock frequencies for sdmmc_chip_bus_clock() */
#define SDMMC_SDCLK_OFF 0
#define SDMMC_SDCLK_400KHZ 400
#define SDMMC_SDCLK_25MHZ 25000
struct sdmmcbus_attach_args {
const char *saa_busname;
sdmmc_chipset_tag_t sct;
sdmmc_chipset_handle_t sch;
int flags;
long max_xfer;
};
void sdmmc_delay(u_int);
#endif

232
sdmmcreg.h Normal file
View File

@ -0,0 +1,232 @@
/* $OpenBSD: sdmmcreg.h,v 1.4 2009/01/09 10:55:22 jsg Exp $ */
/*
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _SDMMCREG_H_
#define _SDMMCREG_H_
/* MMC commands */ /* response type */
#define MMC_GO_IDLE_STATE 0 /* R0 */
#define MMC_SEND_OP_COND 1 /* R3 */
#define MMC_ALL_SEND_CID 2 /* R2 */
#define MMC_SET_RELATIVE_ADDR 3 /* R1 */
#define MMC_SELECT_CARD 7 /* R1 */
#define MMC_SEND_CSD 9 /* R2 */
#define MMC_STOP_TRANSMISSION 12 /* R1B */
#define MMC_SEND_STATUS 13 /* R1 */
#define MMC_SET_BLOCKLEN 16 /* R1 */
#define MMC_READ_BLOCK_SINGLE 17 /* R1 */
#define MMC_READ_BLOCK_MULTIPLE 18 /* R1 */
#define MMC_SET_BLOCK_COUNT 23 /* R1 */
#define MMC_WRITE_BLOCK_SINGLE 24 /* R1 */
#define MMC_WRITE_BLOCK_MULTIPLE 25 /* R1 */
#define MMC_APP_CMD 55 /* R1 */
/* SD commands */ /* response type */
#define SD_SEND_RELATIVE_ADDR 3 /* R6 */
#define SD_SEND_IF_COND 8 /* R7 */
/* SD application commands */ /* response type */
#define SD_APP_SET_BUS_WIDTH 6 /* R1 */
#define SD_APP_OP_COND 41 /* R3 */
/* OCR bits */
#define MMC_OCR_MEM_READY (1<<31) /* memory power-up status bit */
#define MMC_OCR_3_5V_3_6V (1<<23)
#define MMC_OCR_3_4V_3_5V (1<<22)
#define MMC_OCR_3_3V_3_4V (1<<21)
#define MMC_OCR_3_2V_3_3V (1<<20)
#define MMC_OCR_3_1V_3_2V (1<<19)
#define MMC_OCR_3_0V_3_1V (1<<18)
#define MMC_OCR_2_9V_3_0V (1<<17)
#define MMC_OCR_2_8V_2_9V (1<<16)
#define MMC_OCR_2_7V_2_8V (1<<15)
#define MMC_OCR_2_6V_2_7V (1<<14)
#define MMC_OCR_2_5V_2_6V (1<<13)
#define MMC_OCR_2_4V_2_5V (1<<12)
#define MMC_OCR_2_3V_2_4V (1<<11)
#define MMC_OCR_2_2V_2_3V (1<<10)
#define MMC_OCR_2_1V_2_2V (1<<9)
#define MMC_OCR_2_0V_2_1V (1<<8)
#define MMC_OCR_1_9V_2_0V (1<<7)
#define MMC_OCR_1_8V_1_9V (1<<6)
#define MMC_OCR_1_7V_1_8V (1<<5)
#define MMC_OCR_1_6V_1_7V (1<<4)
#define SD_OCR_SDHC_CAP (1<<30)
#define SD_OCR_VOL_MASK 0xFF8000 /* bits 23:15 */
/* R1 response type bits */
#define MMC_R1_READY_FOR_DATA (1<<8) /* ready for next transfer */
#define MMC_R1_APP_CMD (1<<5) /* app. commands supported */
/* 48-bit response decoding (32 bits w/o CRC) */
#define MMC_R1(resp) ((resp)[0])
#define MMC_R3(resp) ((resp)[0])
#define SD_R6(resp) ((resp)[0])
/* RCA argument and response */
#define MMC_ARG_RCA(rca) ((rca) << 16)
#define SD_R6_RCA(resp) (SD_R6((resp)) >> 16)
/* bus width argument */
#define SD_ARG_BUS_WIDTH_1 0
#define SD_ARG_BUS_WIDTH_4 2
/* MMC R2 response (CSD) */
#define MMC_CSD_CSDVER(resp) MMC_RSP_BITS((resp), 126, 2)
#define MMC_CSD_CSDVER_1_0 1
#define MMC_CSD_CSDVER_2_0 2
#define MMC_CSD_MMCVER(resp) MMC_RSP_BITS((resp), 122, 4)
#define MMC_CSD_MMCVER_1_0 0 /* MMC 1.0 - 1.2 */
#define MMC_CSD_MMCVER_1_4 1 /* MMC 1.4 */
#define MMC_CSD_MMCVER_2_0 2 /* MMC 2.0 - 2.2 */
#define MMC_CSD_MMCVER_3_1 3 /* MMC 3.1 - 3.3 */
#define MMC_CSD_MMCVER_4_0 4 /* MMC 4 */
#define MMC_CSD_READ_BL_LEN(resp) MMC_RSP_BITS((resp), 80, 4)
#define MMC_CSD_C_SIZE(resp) MMC_RSP_BITS((resp), 62, 12)
#define MMC_CSD_CAPACITY(resp) ((MMC_CSD_C_SIZE((resp))+1) << \
(MMC_CSD_C_SIZE_MULT((resp))+2))
#define MMC_CSD_C_SIZE_MULT(resp) MMC_RSP_BITS((resp), 47, 3)
/* MMC v1 R2 response (CID) */
#define MMC_CID_MID_V1(resp) MMC_RSP_BITS((resp), 104, 24)
#define MMC_CID_PNM_V1_CPY(resp, pnm) \
do { \
(pnm)[0] = MMC_RSP_BITS((resp), 96, 8); \
(pnm)[1] = MMC_RSP_BITS((resp), 88, 8); \
(pnm)[2] = MMC_RSP_BITS((resp), 80, 8); \
(pnm)[3] = MMC_RSP_BITS((resp), 72, 8); \
(pnm)[4] = MMC_RSP_BITS((resp), 64, 8); \
(pnm)[5] = MMC_RSP_BITS((resp), 56, 8); \
(pnm)[6] = MMC_RSP_BITS((resp), 48, 8); \
(pnm)[7] = '\0'; \
} while (0)
#define MMC_CID_REV_V1(resp) MMC_RSP_BITS((resp), 40, 8)
#define MMC_CID_PSN_V1(resp) MMC_RSP_BITS((resp), 16, 24)
#define MMC_CID_MDT_V1(resp) MMC_RSP_BITS((resp), 8, 8)
/* MMC v2 R2 response (CID) */
#define MMC_CID_MID_V2(resp) MMC_RSP_BITS((resp), 120, 8)
#define MMC_CID_OID_V2(resp) MMC_RSP_BITS((resp), 104, 16)
#define MMC_CID_PNM_V2_CPY(resp, pnm) \
do { \
(pnm)[0] = MMC_RSP_BITS((resp), 96, 8); \
(pnm)[1] = MMC_RSP_BITS((resp), 88, 8); \
(pnm)[2] = MMC_RSP_BITS((resp), 80, 8); \
(pnm)[3] = MMC_RSP_BITS((resp), 72, 8); \
(pnm)[4] = MMC_RSP_BITS((resp), 64, 8); \
(pnm)[5] = MMC_RSP_BITS((resp), 56, 8); \
(pnm)[6] = '\0'; \
} while (0)
#define MMC_CID_PSN_V2(resp) MMC_RSP_BITS((resp), 16, 32)
/* SD R2 response (CSD) */
#define SD_CSD_CSDVER(resp) MMC_RSP_BITS((resp), 126, 2)
#define SD_CSD_CSDVER_1_0 0
#define SD_CSD_CSDVER_2_0 1
#define SD_CSD_TAAC(resp) MMC_RSP_BITS((resp), 112, 8)
#define SD_CSD_TAAC_1_5_MSEC 0x26
#define SD_CSD_NSAC(resp) MMC_RSP_BITS((resp), 104, 8)
#define SD_CSD_SPEED(resp) MMC_RSP_BITS((resp), 96, 8)
#define SD_CSD_SPEED_25_MHZ 0x32
#define SD_CSD_SPEED_50_MHZ 0x5a
#define SD_CSD_CCC(resp) MMC_RSP_BITS((resp), 84, 12)
#define SD_CSD_CCC_ALL 0x5f5
#define SD_CSD_READ_BL_LEN(resp) MMC_RSP_BITS((resp), 80, 4)
#define SD_CSD_READ_BL_PARTIAL(resp) MMC_RSP_BITS((resp), 79, 1)
#define SD_CSD_WRITE_BLK_MISALIGN(resp) MMC_RSP_BITS((resp), 78, 1)
#define SD_CSD_READ_BLK_MISALIGN(resp) MMC_RSP_BITS((resp), 77, 1)
#define SD_CSD_DSR_IMP(resp) MMC_RSP_BITS((resp), 76, 1)
#define SD_CSD_C_SIZE(resp) MMC_RSP_BITS((resp), 62, 12)
#define SD_CSD_CAPACITY(resp) ((SD_CSD_C_SIZE((resp))+1) << \
(SD_CSD_C_SIZE_MULT((resp))+2))
#define SD_CSD_V2_C_SIZE(resp) MMC_RSP_BITS((resp), 48, 22)
#define SD_CSD_V2_CAPACITY(resp) ((SD_CSD_V2_C_SIZE((resp))+1) << 10)
#define SD_CSD_V2_BL_LEN 0x9 /* 512 */
#define SD_CSD_VDD_R_CURR_MIN(resp) MMC_RSP_BITS((resp), 59, 3)
#define SD_CSD_VDD_R_CURR_MAX(resp) MMC_RSP_BITS((resp), 56, 3)
#define SD_CSD_VDD_W_CURR_MIN(resp) MMC_RSP_BITS((resp), 53, 3)
#define SD_CSD_VDD_W_CURR_MAX(resp) MMC_RSP_BITS((resp), 50, 3)
#define SD_CSD_VDD_RW_CURR_100mA 0x7
#define SD_CSD_VDD_RW_CURR_80mA 0x6
#define SD_CSD_C_SIZE_MULT(resp) MMC_RSP_BITS((resp), 47, 3)
#define SD_CSD_ERASE_BLK_EN(resp) MMC_RSP_BITS((resp), 46, 1)
#define SD_CSD_SECTOR_SIZE(resp) MMC_RSP_BITS((resp), 39, 7) /* +1 */
#define SD_CSD_WP_GRP_SIZE(resp) MMC_RSP_BITS((resp), 32, 7) /* +1 */
#define SD_CSD_WP_GRP_ENABLE(resp) MMC_RSP_BITS((resp), 31, 1)
#define SD_CSD_R2W_FACTOR(resp) MMC_RSP_BITS((resp), 26, 3)
#define SD_CSD_WRITE_BL_LEN(resp) MMC_RSP_BITS((resp), 22, 4)
#define SD_CSD_RW_BL_LEN_2G 0xa
#define SD_CSD_RW_BL_LEN_1G 0x9
#define SD_CSD_WRITE_BL_PARTIAL(resp) MMC_RSP_BITS((resp), 21, 1)
#define SD_CSD_FILE_FORMAT_GRP(resp) MMC_RSP_BITS((resp), 15, 1)
#define SD_CSD_COPY(resp) MMC_RSP_BITS((resp), 14, 1)
#define SD_CSD_PERM_WRITE_PROTECT(resp) MMC_RSP_BITS((resp), 13, 1)
#define SD_CSD_TMP_WRITE_PROTECT(resp) MMC_RSP_BITS((resp), 12, 1)
#define SD_CSD_FILE_FORMAT(resp) MMC_RSP_BITS((resp), 10, 2)
/* SD R2 response (CID) */
#define SD_CID_MID(resp) MMC_RSP_BITS((resp), 120, 8)
#define SD_CID_OID(resp) MMC_RSP_BITS((resp), 104, 16)
#define SD_CID_PNM_CPY(resp, pnm) \
do { \
(pnm)[0] = MMC_RSP_BITS((resp), 96, 8); \
(pnm)[1] = MMC_RSP_BITS((resp), 88, 8); \
(pnm)[2] = MMC_RSP_BITS((resp), 80, 8); \
(pnm)[3] = MMC_RSP_BITS((resp), 72, 8); \
(pnm)[4] = MMC_RSP_BITS((resp), 64, 8); \
(pnm)[5] = '\0'; \
} while (0)
#define SD_CID_REV(resp) MMC_RSP_BITS((resp), 56, 8)
#define SD_CID_PSN(resp) MMC_RSP_BITS((resp), 24, 32)
#define SD_CID_MDT(resp) MMC_RSP_BITS((resp), 8, 12)
/* Might be slow, but it should work on big and little endian systems. */
#define MMC_RSP_BITS(resp, start, len) __bitfield((resp), (start)-8, (len))
static __inline int
__bitfield(u_int32_t *src, int start, int len)
{
u_int8_t *sp;
u_int32_t dst, mask;
int shift, bs, bc;
if (start < 0 || len < 0 || len > 32)
return 0;
dst = 0;
mask = len % 32 ? UINT_MAX >> (32 - (len % 32)) : UINT_MAX;
shift = 0;
while (len > 0) {
sp = (u_int8_t *)src + start / 8;
bs = start % 8;
bc = 8 - bs;
if (bc > len)
bc = len;
dst |= (*sp++ >> bs) << shift;
shift += bc;
start += bc;
len -= bc;
}
dst &= mask;
return (int)dst;
}
#endif

182
sdmmcvar.h Normal file
View File

@ -0,0 +1,182 @@
/* $OpenBSD: sdmmcvar.h,v 1.16 2009/04/07 16:35:52 blambert Exp $ */
/*
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
* Copyright (c) 2009 Sven Peter <svenpeter@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _SDMMCVAR_H_
#define _SDMMCVAR_H_
struct sdmmc_csd {
int csdver; /* CSD structure format */
int mmcver; /* MMC version (for CID format) */
int capacity; /* total number of sectors */
int sector_size; /* sector size in bytes */
int read_bl_len; /* block length for reads */
/* ... */
};
struct sdmmc_cid {
int mid; /* manufacturer identification number */
int oid; /* OEM/product identification number */
char pnm[8]; /* product name (MMC v1 has the longest) */
int rev; /* product revision */
int psn; /* product serial number */
int mdt; /* manufacturing date */
};
typedef u_int32_t sdmmc_response[4];
struct sdmmc_softc;
struct sdmmc_task {
void (*func)(void *arg);
void *arg;
int onqueue;
struct sdmmc_softc *sc;
};
#define sdmmc_init_task(xtask, xfunc, xarg) do { \
(xtask)->func = (xfunc); \
(xtask)->arg = (xarg); \
(xtask)->onqueue = 0; \
(xtask)->sc = NULL; \
} while (0)
#define sdmmc_task_pending(xtask) ((xtask)->onqueue)
struct sdmmc_command {
// struct sdmmc_task c_task; /* task queue entry */
u_int16_t c_opcode; /* SD or MMC command index */
u_int32_t c_arg; /* SD/MMC command argument */
sdmmc_response c_resp; /* response buffer */
void *c_data; /* buffer to send or read into */
int c_datalen; /* length of data buffer */
int c_blklen; /* block length */
int c_flags; /* see below */
#define SCF_ITSDONE 0x0001 /* command is complete */
#define SCF_CMD(flags) ((flags) & 0x00f0)
#define SCF_CMD_AC 0x0000
#define SCF_CMD_ADTC 0x0010
#define SCF_CMD_BC 0x0020
#define SCF_CMD_BCR 0x0030
#define SCF_CMD_READ 0x0040 /* read command (data expected) */
#define SCF_RSP_BSY 0x0100
#define SCF_RSP_136 0x0200
#define SCF_RSP_CRC 0x0400
#define SCF_RSP_IDX 0x0800
#define SCF_RSP_PRESENT 0x1000
/* response types */
#define SCF_RSP_R0 0 /* none */
#define SCF_RSP_R1 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
#define SCF_RSP_R1B (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX|SCF_RSP_BSY)
#define SCF_RSP_R2 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_136)
#define SCF_RSP_R3 (SCF_RSP_PRESENT)
#define SCF_RSP_R4 (SCF_RSP_PRESENT)
#define SCF_RSP_R5 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
#define SCF_RSP_R5B (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX|SCF_RSP_BSY)
#define SCF_RSP_R6 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
#define SCF_RSP_R7 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
int c_error; /* errno value on completion */
/* Host controller owned fields for data xfer in progress */
int c_resid; /* remaining I/O */
u_char *c_buf; /* remaining data */
};
/*
* Decoded PC Card 16 based Card Information Structure (CIS),
* per card (function 0) and per function (1 and greater).
*/
struct sdmmc_cis {
u_int16_t manufacturer;
#define SDMMC_VENDOR_INVALID 0xffff
u_int16_t product;
#define SDMMC_PRODUCT_INVALID 0xffff
u_int8_t function;
#define SDMMC_FUNCTION_INVALID 0xff
u_char cis1_major;
u_char cis1_minor;
char cis1_info_buf[256];
char *cis1_info[4];
};
/*
* Structure describing either an SD card I/O function or a SD/MMC
* memory card from a "stack of cards" that responded to CMD2. For a
* combo card with one I/O function and one memory card, there will be
* two of these structures allocated. Each card slot has such a list
* of sdmmc_function structures.
*/
struct sdmmc_function {
/* common members */
struct sdmmc_softc *sc; /* card slot softc */
u_int16_t rca; /* relative card address */
int flags;
#define SFF_ERROR 0x0001 /* function is poo; ignore it */
#define SFF_SDHC 0x0002 /* SD High Capacity card */
/* SD card I/O function members */
int number; /* I/O function number or -1 */
struct device *child; /* function driver */
struct sdmmc_cis cis; /* decoded CIS */
/* SD/MMC memory card members */
struct sdmmc_csd csd; /* decoded CSD value */
struct sdmmc_cid cid; /* decoded CID value */
sdmmc_response raw_cid; /* temp. storage for decoding */
};
/*
* Structure describing a single SD/MMC/SDIO card slot.
*/
struct sdmmc_softc {
struct device sc_dev; /* base device */
#define SDMMCDEVNAME(sc) ((sc)->sc_dev.dv_xname)
sdmmc_chipset_tag_t sct; /* host controller chipset tag */
sdmmc_chipset_handle_t sch; /* host controller chipset handle */
int sc_flags;
#define SMF_SD_MODE 0x0001 /* host in SD mode (MMC otherwise) */
#define SMF_IO_MODE 0x0002 /* host in I/O mode (SD mode only) */
#define SMF_MEM_MODE 0x0004 /* host in memory mode (SD or MMC) */
#define SMF_CARD_PRESENT 0x0010 /* card presence noticed */
#define SMF_CARD_ATTACHED 0x0020 /* card driver(s) attached */
#define SMF_STOP_AFTER_MULTIPLE 0x0040 /* send a stop after a multiple cmd */
int sc_function_count; /* number of I/O functions (SDIO) */
struct sdmmc_function *sc_card; /* selected card */
struct sdmmc_function *sc_fn0; /* function 0, the card itself */
int sc_dying; /* bus driver is shutting down */
struct proc *sc_task_thread; /* asynchronous tasks */
struct sdmmc_task sc_discover_task; /* card attach/detach task */
struct sdmmc_task sc_intr_task; /* card interrupt task */
void *sc_scsibus; /* SCSI bus emulation softc */
long sc_max_xfer; /* maximum transfer size */
};
/*
* Attach devices at the sdmmc bus.
*/
struct sdmmc_attach_args {
struct scsi_link *scsi_link; /* XXX */
struct sdmmc_function *sf;
};
#define IPL_SDMMC IPL_BIO
#define SDMMC_LOCK(sc) lockmgr(&(sc)->sc_lock, LK_EXCLUSIVE, NULL)
#define SDMMC_UNLOCK(sc) lockmgr(&(sc)->sc_lock, LK_RELEASE, NULL)
#define SDMMC_ASSERT_LOCKED(sc) \
KASSERT(lockstatus(&((sc))->sc_lock) == LK_EXCLUSIVE)
#endif

165
usb.h
View File

@ -1,165 +0,0 @@
#ifndef __USB_H__
#define __USB_H__
#define USB_MAXPATH IPC_MAXPATH_LEN
#define USB_OK 0
#define USB_FAILED 1
/* Descriptor types */
#define USB_DT_DEVICE 0x01
#define USB_DT_CONFIG 0x02
#define USB_DT_STRING 0x03
#define USB_DT_INTERFACE 0x04
#define USB_DT_ENDPOINT 0x05
/* Standard requests */
#define USB_REQ_GETSTATUS 0x00
#define USB_REQ_CLEARFEATURE 0x01
#define USB_REQ_SETFEATURE 0x03
#define USB_REQ_SETADDRESS 0x05
#define USB_REQ_GETDESCRIPTOR 0x06
#define USB_REQ_SETDESCRIPTOR 0x07
#define USB_REQ_GETCONFIG 0x08
#define USB_REQ_SETCONFIG 0x09
#define USB_REQ_GETINTERFACE 0x0a
#define USB_REQ_SETINTERFACE 0x0b
#define USB_REQ_SYNCFRAME 0x0c
/* Descriptor sizes per descriptor type */
#define USB_DT_DEVICE_SIZE 18
#define USB_DT_CONFIG_SIZE 9
#define USB_DT_INTERFACE_SIZE 9
#define USB_DT_ENDPOINT_SIZE 7
#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */
#define USB_DT_HUB_NONVAR_SIZE 7
/* control message request type bitmask */
#define USB_CTRLTYPE_DIR_HOST2DEVICE (0<<7)
#define USB_CTRLTYPE_DIR_DEVICE2HOST (1<<7)
#define USB_CTRLTYPE_TYPE_STANDARD (0<<5)
#define USB_CTRLTYPE_TYPE_CLASS (1<<5)
#define USB_CTRLTYPE_TYPE_VENDOR (2<<5)
#define USB_CTRLTYPE_TYPE_RESERVED (3<<5)
#define USB_CTRLTYPE_REC_DEVICE 0
#define USB_CTRLTYPE_REC_INTERFACE 1
#define USB_CTRLTYPE_REC_ENDPOINT 2
#define USB_CTRLTYPE_REC_OTHER 3
#define USB_FEATURE_ENDPOINT_HALT 0
#define USB_ENDPOINT_IN 0x80
#define USB_ENDPOINT_OUT 0x00
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
# define ATTRIBUTE_PACKED __attribute__((packed))
typedef struct _usbctrlrequest {
u8 bRequestType;
u8 bRequest;
u16 wValue;
u16 wIndex;
u16 wLength;
} ATTRIBUTE_PACKED usbctrlrequest;
typedef struct _usbendpointdesc
{
u8 bLength;
u8 bDescriptorType;
u8 bEndpointAddress;
u8 bmAttributes;
u16 wMaxPacketSize;
u8 bInterval;
} ATTRIBUTE_PACKED usb_endpointdesc;
typedef struct _usbinterfacedesc
{
u8 bLength;
u8 bDescriptorType;
u8 bInterfaceNumber;
u8 bAlternateSetting;
u8 bNumEndpoints;
u8 bInterfaceClass;
u8 bInterfaceSubClass;
u8 bInterfaceProtocol;
u8 iInterface;
struct _usbendpointdesc *endpoints;
} ATTRIBUTE_PACKED usb_interfacedesc;
typedef struct _usbconfdesc
{
u8 bLength;
u8 bDescriptorType;
u16 wTotalLength;
u8 bNumInterfaces;
u8 bConfigurationValue;
u8 iConfiguration;
u8 bmAttributes;
u8 bMaxPower;
struct _usbinterfacedesc *interfaces;
} ATTRIBUTE_PACKED usb_configurationdesc;
typedef struct _usbdevdesc
{
u8 bLength;
u8 bDescriptorType;
u16 bcdUSB;
u8 bDeviceClass;
u8 bDeviceSubClass;
u8 bDeviceProtocol;
u8 bMaxPacketSize0;
u16 idVendor;
u16 idProduct;
u16 bcdDevice;
u8 iManufacturer;
u8 iProduct;
u8 iSerialNumber;
u8 bNumConfigurations;
struct _usbconfdesc *configurations;
} ATTRIBUTE_PACKED usb_devdesc;
struct ehci_device;
s32 USB_OpenDevice(const char *device,u16 vid,u16 pid,struct ehci_device **fd);
s32 USB_CloseDevice(struct ehci_device **fd);
s32 USB_GetDescriptors(struct ehci_device *fd, usb_devdesc *udd);
void USB_FreeDescriptors(usb_devdesc *udd);
s32 USB_GetDeviceDescription(struct ehci_device *fd,usb_devdesc *devdesc);
void USB_SuspendDevice(struct ehci_device *fd);
void USB_ResumeDevice(struct ehci_device *fd);
s32 USB_ReadIntrMsg(struct ehci_device *fd,u8 bEndpoint,u16 wLength,void *rpData);
s32 USB_ReadBlkMsg(struct ehci_device *fd,u8 bEndpoint,u16 wLength,void *rpData);
s32 USB_ReadCtrlMsg(struct ehci_device *fd,u8 bmRequestType,u8 bmRequest,u16 wValue,u16 wIndex,u16 wLength,void *rpData);
s32 USB_WriteIntrMsg(struct ehci_device *fd,u8 bEndpoint,u16 wLength,void *rpData);
s32 USB_WriteBlkMsg(struct ehci_device *fd,u8 bEndpoint,u16 wLength,void *rpData);
s32 USB_WriteCtrlMsg(struct ehci_device *fd,u8 bmRequestType,u8 bmRequest,u16 wValue,u16 wIndex,u16 wLength,void *rpData);
s32 USB_GetConfiguration(struct ehci_device *fd, u8 *configuration);
s32 USB_SetConfiguration(struct ehci_device *fd, u8 configuration);
s32 USB_SetAlternativeInterface(struct ehci_device *fd, u8 interface, u8 alternateSetting);
s32 USB_ClearHalt(struct ehci_device *fd, u8 endpointAddress);
s32 USB_GetDeviceList(const char *devpath,void *descr_buffer,u8 num_descr,u8 b0,u8 *cnt_descr);
/* alloc memory from the USB subsystem */
void * USB_Alloc(int size);
void USB_Free(void *ptr);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif

View File

@ -1,73 +0,0 @@
#ifndef __USBSTORAGE_H__
#define __USBSTORAGE_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include "ehci.h"
#define USBSTORAGE_OK 0
#define USBSTORAGE_ENOINTERFACE -10000
#define USBSTORAGE_ESENSE -10001
#define USBSTORAGE_ESHORTWRITE -10002
#define USBSTORAGE_ESHORTREAD -10003
#define USBSTORAGE_ESIGNATURE -10004
#define USBSTORAGE_ETAG -10005
#define USBSTORAGE_ESTATUS -10006
#define USBSTORAGE_EDATARESIDUE -10007
#define USBSTORAGE_ETIMEDOUT -ETIMEDOUT
#define USBSTORAGE_EINIT -10009
typedef struct
{
u8 configuration;
u32 interface;
u32 altInterface;
u8 ep_in;
u8 ep_out;
u8 max_lun;
u32 sector_size[16];
u32 n_sector[16];
struct ehci_device * usb_fd;
//mutex_t lock;
//cond_t cond;
s32 retval;
u32 tag;
u8 suspended;
u8 *buffer;
} usbstorage_handle;
s32 USBStorage_Initialize(void);
s32 USBStorage_Open(usbstorage_handle *dev, struct ehci_device *fd);
s32 USBStorage_Close(usbstorage_handle *dev);
s32 USBStorage_Reset(usbstorage_handle *dev);
s32 USBStorage_GetMaxLUN(usbstorage_handle *dev);
s32 USBStorage_MountLUN(usbstorage_handle *dev, u8 lun);
s32 USBStorage_Suspend(usbstorage_handle *dev);
s32 USBStorage_ReadCapacity(usbstorage_handle *dev, u8 lun, u32 *sector_size, u32 *n_sectors);
s32 USBStorage_Read(usbstorage_handle *dev, u8 lun, u32 sector, u16 n_sectors, u8 *buffer);
s32 USBStorage_Write(usbstorage_handle *dev, u8 lun, u32 sector, u16 n_sectors, const u8 *buffer);
s32 USBStorage_Inquiry(usbstorage_handle *dev, u8 lun);
#define DEVICE_TYPE_WII_USB (('W'<<24)|('U'<<16)|('S'<<8)|'B')
s32 USBStorage_Try_Device(struct ehci_device *fd);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __USBSTORAGE_H__ */