From 7210addaf27d249679ff17d74d2c75ebd5fd8422 Mon Sep 17 00:00:00 2001 From: dimok321 <15055714+dimok789@users.noreply.github.com> Date: Wed, 22 Jun 2011 17:57:37 +0000 Subject: [PATCH] *Added support for starting .wbfs game files from fat32/ntfs partitions on a sector size > 512 (tested with 4096) *modified libcustomfat and ntfs fragment fetch function to support >512 bytes per sector *Added new ehcmodule (thanks rodries) *Added real support of using both ports simultaniously without shutting down the other (thanks rodries for the ehcmodule works on this). There is no longer the limitation that the settings have to be on SD card for this. (ONLY HERMES CIOS) *Moved a few settings to Feature Settings and added a new Hard Drive Settings *Changed Wiinnertag path to only point to the path and not to the file. You must correct the path manually in custom path settings or reset you configs for this change or Winnertag won't work!! *Removed a few compile warnings for devkitPPC R23 --- ehcmodule/Makefile | 8 +- ehcmodule/bin/convert.bat | 2 + ehcmodule/source/crt0.s | 4 +- ehcmodule/source/ehc_loop.c | 84 +-- ehcmodule/source/main.c | 4 +- ehcmodule/source/wbfs_glue.c | 3 +- test/data/ehcmodule.elf | Bin 25260 -> 27134 bytes test/source/main.c | 794 +++++++++++++--------------- test/source/mload.c | 985 +++++++++++++++++------------------ test/source/mload.h | 473 +++++++++-------- test/source/usbstorage2.c | 344 ++++++++++++ test/source/usbstorage2.h | 31 ++ tinyehci/ehci.c | 85 ++- tinyehci/ehci.h | 5 +- tinyehci/usbstorage.c | 448 ++++++++-------- tinyehci/usbstorage.h | 2 +- 16 files changed, 1786 insertions(+), 1486 deletions(-) create mode 100644 test/source/usbstorage2.c create mode 100644 test/source/usbstorage2.h diff --git a/ehcmodule/Makefile b/ehcmodule/Makefile index 3618ccb9..2d894c15 100644 --- a/ehcmodule/Makefile +++ b/ehcmodule/Makefile @@ -98,13 +98,13 @@ LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) ARCH = -mcpu=arm9tdmi -mtune=arm9tdmi -mthumb -mthumb-interwork -mbig-endian -CFLAGS += -g $(ARCH) $(INCLUDE) -fno-strict-aliasing -Wall -Os -fomit-frame-pointer -ffast-math -fverbose-asm -Wpointer-arith -Winline -Wundef -g -ffunction-sections -fdata-sections -fno-exceptions +CFLAGS += $(ARCH) $(INCLUDE) -fno-strict-aliasing -Wall -Os -fomit-frame-pointer -ffast-math -fverbose-asm -Wpointer-arith -Winline -Wundef -g -ffunction-sections -fdata-sections -fno-exceptions CFLAGS += -Wstrict-prototypes -AFLAGS = -g $(ARCH) -x assembler-with-cpp +AFLAGS = $(ARCH) -x assembler-with-cpp -LDFLAGS = -g $(ARCH) -specs=$(SPECS) -T$(LINKSCRIPT) $(LIBPATHS) $(LIBS) -Wl,--gc-sections -Wl,-static -Wl,-Map,$(TARGET).map -nostartfiles +LDFLAGS = $(ARCH) -specs=$(SPECS) -T$(LINKSCRIPT) $(LIBPATHS) $(LIBS) -Wl,--gc-sections -Wl,-static -Wl,-Map,$(TARGET).map -nostartfiles $(OUTPUT).elf: $(TARGET).elf @@ -114,7 +114,7 @@ $(OUTPUT).elf: $(TARGET).elf %.elf: $(OFILES) @echo linking $(notdir $@) - @$(LD) -g -o $@ $(OFILES) $(LDFLAGS) $(STYLEFIX) + @$(LD) -o $@ $(OFILES) $(LDFLAGS) $(STYLEFIX) %_cpp.o : %.cpp diff --git a/ehcmodule/bin/convert.bat b/ehcmodule/bin/convert.bat index 62e3ef26..0e010c23 100644 --- a/ehcmodule/bin/convert.bat +++ b/ehcmodule/bin/convert.bat @@ -5,6 +5,8 @@ del C:\devkitPro\soft\usbloader\source\mload\modules\ehcmodule_5.c del C:\devkitPro\soft\usbloader\source\mload\modules\ehcmodule_5.h copy ehcmodule_5.c C:\devkitPro\soft\usbloader\source\mload\modules\ copy ehcmodule_5.h C:\devkitPro\soft\usbloader\source\mload\modules\ +touch C:\devkitPro\soft\usbloader\source\mload\modules\ehcmodule_5.c +touch C:\devkitPro\soft\usbloader\source\mload\modules\ehcmodule_5.h diff --git a/ehcmodule/source/crt0.s b/ehcmodule/source/crt0.s index 46b7fc79..ab523f42 100644 --- a/ehcmodule/source/crt0.s +++ b/ehcmodule/source/crt0.s @@ -170,8 +170,8 @@ write_access_perm: .string "EHC_CFG" .long 0x12340001 - .global use_usb_port1 -use_usb_port1: + .global initial_port +initial_port: .byte 0x0 .global use_reset_bulk diff --git a/ehcmodule/source/ehc_loop.c b/ehcmodule/source/ehc_loop.c index eb341661..e1a6aab4 100644 --- a/ehcmodule/source/ehc_loop.c +++ b/ehcmodule/source/ehc_loop.c @@ -113,8 +113,6 @@ int verbose = 0; wbfs_disc_t * wbfs_init_with_partition(u8*discid, int partition); -extern char use_usb_port1; - int USBStorage_DVD_Test(void); @@ -144,6 +142,8 @@ char *parse_hex(char *base,int *val) *val = v; return ptr-1; } + +/* int parse_and_open_device(char *devname,int fd) { char *ptr = devname; @@ -159,7 +159,7 @@ int parse_and_open_device(char *devname,int fd) return -6; return ehci_open_device(vid,pid,fd); } - +*/ int DVD_speed_limit=0; // ingame it can fix x6 speed @@ -345,7 +345,7 @@ extern int is_watchdog_read_sector; extern u32 n_sec,sec_size; -int last_sector=0; +u32 last_sector=0; void direct_os_sync_before_read(void* ptr, int size); @@ -439,11 +439,13 @@ int ehc_loop(void) { ipcmessage* message; int timer2_id=-1; + extern char initial_port; + int init_mode=initial_port; static bool first_read=true; char port; - extern int ums_init_done; - + extern int ums_init_done[2]; + extern u32 current_port; int must_read_sectors=0; @@ -464,7 +466,7 @@ int ehc_loop(void) timer2_id=os_create_timer(WATCHDOG_TIMER, WATCHDOG_TIMER, queuehandle, 0x0); int ums_mode = 0; - int already_discovered = 0; +// int already_discovered = 0; wbfs_disc_t *d = 0; int usb_lock=0; @@ -515,16 +517,16 @@ int ehc_loop(void) if(unplug_device==0) { - if(sec_size!=0 && sec_size<4096) // only support sector size minor to 2048 + if(sec_size!=0 && sec_size<=4096) { - + extern int is_dvd[2]; is_watchdog_read_sector=1; r=USBStorage_Read_Sectors(last_sector, 1, mem_sector); is_watchdog_read_sector=0; - if(r!=0 && sec_size==512) + if(r!=0 && !is_dvd[current_port]) last_sector+=0x1000000/sec_size; // steps of 16MB if(last_sector>=n_sec) last_sector=0; } @@ -645,8 +647,8 @@ int ehc_loop(void) break; case USB_IOCTL_GETDEVLIST: debug_printf("get dev list\n"); - if(dev)result= -6; - else + //if(dev)result= -6; + //else result = ehci_get_device_list(ioctlv_u8(vec[0]),ioctlv_u8(vec[1]), ioctlv_voidp(vec[2]),ioctlv_voidp(vec[3])); break; @@ -658,12 +660,14 @@ int ehc_loop(void) case USB_IOCTL_UMS_INIT: must_read_sectors=0; - if(!already_discovered ) - ehci_discover(); - already_discovered=1; - - result = USBStorage_Init(); - + result = USBStorage_Init(init_mode); + if(result>=0 && result <3) + { + if(result==0 || result==2) + current_port = 0; + else + current_port = 1; + } //result=-os_thread_get_priority(); if(result>=0) {must_read_sectors=1;watchdog_enable=1;} @@ -673,7 +677,7 @@ int ehc_loop(void) case USB_IOCTL_UMS_UMOUNT: must_read_sectors=0; watchdog_enable=0; - // USBStorage_Umount(); + USBStorage_Umount(); result =0; break; case USB_IOCTL_UMS_TESTMODE: @@ -684,19 +688,14 @@ int ehc_loop(void) case USB_IOCTL_SET_PORT: result =0; port=ioctlv_u32(vec[0]); - if(use_usb_port1!=port) + init_mode=port; + //if(ums_init_done==0) init_mode=port; + //else { - if(ums_init_done) - { - USBStorage_Umount(); - ehci_close_devices(); - ehci_release_externals_usb_ports(); - use_usb_port1=port; - ehci_discover(); - result = USBStorage_Init(); - } - } - use_usb_port1=port; + if(port==0 || port==1) current_port=port; + result = current_port; + } + break; case USB_IOCTL_UMS_OFF: @@ -727,6 +726,12 @@ int ehc_loop(void) #ifdef VIGILANTE enable_button=1; #endif + if(watchdog_enable && timer2_id!=-1) + { + os_stop_timer(timer2_id); // stops the timeout timer + os_destroy_timer(timer2_id); + timer2_id=-1; + } result = USBStorage_Read_Sectors(ioctlv_u32(vec[0]),ioctlv_u32(vec[1]), ioctlv_voidp(vec[2])); if(first_read) { @@ -739,6 +744,7 @@ int ehc_loop(void) else s_printf("first read sector (%i) ERROR\n",ioctlv_u32(vec[0])); } + if(watchdog_enable && timer2_id==-1)timer2_id=os_create_timer(WATCHDOG_TIMER, WATCHDOG_TIMER, queuehandle, 0x0); break; case USB_IOCTL_UMS_WRITE_SECTORS: @@ -806,7 +812,14 @@ int ehc_loop(void) case USB_IOCTL_WBFS_READ_DIRECT_DISC: // used to read USB DVD usb_lock=1; watchdog_enable=1; + if(watchdog_enable && timer2_id!=-1) + { + os_stop_timer(timer2_id); // stops the timeout timer + os_destroy_timer(timer2_id); + timer2_id=-1; + } result = WBFS_direct_disc_read(ioctlv_u32(vec[0]),ioctlv_voidp(vec[2]),ioctlv_u32(vec[1])); + if(watchdog_enable)timer2_id=os_create_timer(WATCHDOG_TIMER, WATCHDOG_TIMER, queuehandle, 0x0); usb_lock=0; break; @@ -823,7 +836,14 @@ int ehc_loop(void) usb_lock=1; //os_stop_timer(timer2_id); - result = wbfs_disc_read(d,ioctlv_u32(vec[0]),ioctlv_voidp(vec[2]),ioctlv_u32(vec[1])); + if(watchdog_enable && timer2_id!=-1) + { + os_stop_timer(timer2_id); // stops the timeout timer + os_destroy_timer(timer2_id); + timer2_id=-1; + } + result = wbfs_disc_read(d,ioctlv_u32(vec[0]),ioctlv_voidp(vec[2]),ioctlv_u32(vec[1])); + if(watchdog_enable)timer2_id=os_create_timer(WATCHDOG_TIMER, WATCHDOG_TIMER, queuehandle, 0x0); usb_lock=0; if(result){ //debug_printf("wbfs failed! %d\n",result); diff --git a/ehcmodule/source/main.c b/ehcmodule/source/main.c index 64bf9b0c..233cc579 100644 --- a/ehcmodule/source/main.c +++ b/ehcmodule/source/main.c @@ -256,13 +256,13 @@ int copy_int_vect(u32 ios, u32 none) return 0; } -extern char use_usb_port1; +extern char initial_port; extern u32 current_port; int main(void) { -current_port= ((u32) use_usb_port1)!=0; +current_port=initial_port; // changes IOS vector interrupt to crt0.s routine //swi_mload_led_on(); diff --git a/ehcmodule/source/wbfs_glue.c b/ehcmodule/source/wbfs_glue.c index 4fff5928..06b81e32 100644 --- a/ehcmodule/source/wbfs_glue.c +++ b/ehcmodule/source/wbfs_glue.c @@ -104,7 +104,8 @@ wbfs_disc_t * wbfs_init_with_partition(u8*discid, int partition) // opens the hd only is is not opened if(!p) { - USBStorage_Init(); + extern u32 current_port; + USBStorage_Init(current_port); n_sec = USBStorage_Get_Capacity(&sec_size); //debug_printf("hd found n_sec:%x sec_size %x\n",n_sec,sec_size); if (n_sec==0) diff --git a/test/data/ehcmodule.elf b/test/data/ehcmodule.elf index 24f58176e746a0c385bcc3d00a046a6cf09c9d74..cb6aa68e38ceba0017dd503bca489d463e1b3100 100644 GIT binary patch literal 27134 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 diff --git a/test/source/main.c b/test/source/main.c index aa0a91f9..d7546b89 100644 --- a/test/source/main.c +++ b/test/source/main.c @@ -1,441 +1,353 @@ -/************************************************************/ -/* USB speed test */ -/* */ -/* */ -/************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include "mload.h" -#include "../build/ehcmodule_elf.h" -//#include "../build/fat_elf.h" -data_elf my_data_elf; -int my_thread_id = 0; - - -#include - -#include -#include -#include -#include "usb2storage.h" - - - -const DISC_INTERFACE* sd = &__io_wiisd; -const DISC_INTERFACE* usb = &__io_usbstorage; -//const DISC_INTERFACE* usb1 = &__io_usb1storage; - -static bool reset_pressed = false; -static bool power_pressed = false; - -static void *xfb = NULL; -static GXRModeObj *rmode = NULL; -static const u32 CACHE_PAGES = 8; - -static u8 memsector[4*1024]; - - -void initialise_video() -{ - VIDEO_Init(); - rmode = VIDEO_GetPreferredMode(NULL); - xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode)); - console_init(xfb, 20, 20, rmode->fbWidth, rmode->xfbHeight, rmode->fbWidth * VI_DISPLAY_PIX_SZ); - VIDEO_Configure(rmode); - VIDEO_SetNextFramebuffer(xfb); - VIDEO_SetBlack(FALSE); - VIDEO_Flush(); - VIDEO_WaitVSync(); - - if (rmode->viTVMode & VI_NON_INTERLACE) VIDEO_WaitVSync(); - - printf("\x1b[2;0H"); - - VIDEO_WaitVSync(); -} - -#include -//#define ticks_to_secs(ticks) ((u32)((u64)(ticks)/(u64)(TB_TIMER_CLOCK*1000))) -//#define ticks_to_msecs(ticks) ((u32)((u64)(ticks)/(u64)(TB_TIMER_CLOCK))) - -void showdir(char *path) -{ - char filename[MAXPATHLEN]; - DIR_ITER *dp; - - struct stat fstat; - //chdir("usb:/"); - dp = diropen(path); - - if (dp == NULL) - { - printf("Error diropen\n"); - return ; - } - - else printf("Ok diropen\n"); - - int cnt = 0; - - while ( dirnext( dp, filename, &fstat ) == 0 ) - { - //if(cnt==20) break; - cnt++; - - if ( fstat.st_mode & S_IFDIR ) printf("/"); - - printf("%s\n", filename); - - } - - dirclose(dp); - printf("\nEnd show dirrectory (%d).\n", cnt); -} - -static void reset_cb (void) -{ - reset_pressed = true; -} - -static void power_cb (void) -{ - power_pressed = true; -} - -#include - - -#define VERSION "1.52" - -void save_log() // at now all data is sent to usbgecko, sd log disabled -{ - FILE *fp; - u8 *temp_data = NULL; - u32 level, len; - - temp_data = memalign(32, 256 * 1024); - - mload_seek(0x13750000, SEEK_SET); - mload_read(temp_data, 128*1024); - - //mload_init(); - - //mload_close(); - - for (len = 0;len < 4096 && temp_data[len] != 0;len++); - - fatUnmount("sd"); - - if (fatMount("sd", sd, 0, 128, 2) ) - { - - fp = fopen("sd:/log_usb2.txt", "wb"); - - if (fp != 0) - { - fprintf(fp, "USB2 device test program. v%s\n------------------------------\n", VERSION); - fwrite(temp_data, 1, len , fp); - - fclose(fp); - } - } - - if (usb_isgeckoalive(1)) - { - level = IRQ_Disable(); - usb_sendbuffer(1, temp_data, len); - IRQ_Restore(level); - } - - //printf("\nlog:\n-------\n%s", temp_data); - free(temp_data); -} - -void TryUSBDevice() -{ - printf("Initializing usb device.\n"); - bool s; - - USB2Enable(true); - s = usb->startup(); - usleep(10000); - - if (s > 0) - s = __usb2storage_ReadSectors(0, 1, memsector); - - usleep(10000); - - - if (s > 0) - { - - printf("usb device detected, your device is fully compatible with this usb2 driver\n"); - } - - else - { - //(s==-1) printf("usb device NOT INSERTED, log file not created\n"); - //se - { - printf("usb device NOT detected or not inserted, report 'ubs2 init' value and log file\n"); - printf("Log saved to sd:/log_usb2.txt file\n"); - } - } - - save_log(); -} - -static s32 initialise_network() -{ - s32 result; - - while ((result = net_init()) == -EAGAIN) - { - if (reset_pressed) exit(1); - - usleep(100); - } - - return result; -} - -int wait_for_network_initialisation() -{ - printf("Waiting for network to initialise...\n"); - - if (initialise_network() >= 0) - { - char myIP[16]; - - if (if_config(myIP, NULL, NULL, true) < 0) - { - printf("Error reading IP address\n"); - return 0; - } - - else - { - printf("Network initialised. Wii IP address: %s\n", myIP); - return 1; - } - } - - printf("Unable to initialise network\n"); - return 0; -} - -#define ROUNDDOWN32(v) (((u32)(v)-0x1f)&~0x1f) -static bool usblan_detected(void) -{ - u8 *buffer; - u8 dummy; - u8 i; - u16 vid, pid; - - USB_Initialize(); - - buffer = (u8*)ROUNDDOWN32(((u32)SYS_GetArena2Hi() - (32 * 1024))); - - memset(buffer, 0, 8 << 3); - - if (USB_GetDeviceList("/dev/usb/oh0", buffer, 8, 0, &dummy) < 0) - { - return false; - } - - for (i = 0; i < 8; i++) - { - memcpy(&vid, (buffer + (i << 3) + 4), 2); - memcpy(&pid, (buffer + (i << 3) + 6), 2); - - if ( (vid == 0x0b95) && (pid == 0x7720)) - { - return true; - } - } - - return false; -} - -void init_mload() -{ - int ret; - ret = mload_init(); - - if (ret < 0) - { - printf("fail to get dev/mload, mload cios not detected. Quit\n"); - sleep(3); - exit(0); - //goto out; - } -} - -void loadehcimodule() -{ - u32 addr; - int len; - - mload_get_load_base(&addr, &len); - - if (((u32) ehcmodule_elf) & 3) {printf("Unaligned elf!\n"); return ;} - - mload_elf((void *) ehcmodule_elf, &my_data_elf); - my_thread_id = mload_run_thread(my_data_elf.start, my_data_elf.stack, my_data_elf.size_stack, /*my_data_elf.prio*/0x47); - //my_thread_id=mload_run_thread(my_data_elf.start, my_data_elf.stack, my_data_elf.size_stack, my_data_elf.prio); - - if (my_thread_id < 0) - { - printf("EHCI module can NOT be loaded (%i).. Quit\n", my_thread_id); - sleep(3); - exit(0); - } - - printf("EHCI module loaded (%i).\n", my_thread_id); - VIDEO_WaitVSync(); -} - -int main(int argc, char **argv) -{ - int ret; - bool usblan; - int usblanport; - - initialise_video(); - CON_EnableGecko(1, 0); - - usblan = usblan_detected(); - printf("ios 202 reload\n"); - IOS_ReloadIOS(202); - printf("ios 202 reloaded\n"); - init_mload(); - mload_reset_log(); - loadehcimodule(); - - if (usblan) - { - printf("uslan detected\n"); - usblanport = GetUSB2LanPort(); - printf("usblanport: %i\n", usblanport); - USB2Storage_Close(); - - mload_close(); - IOS_ReloadIOS(202); - init_mload(); - loadehcimodule(); - printf("SetUSBMode(%i)\n", usblanport); - - if (usblanport == 1) - SetUSB2Mode(1); - else - SetUSB2Mode(2); - - } - - else - printf("usblan NOT found\n"); - - SYS_SetResetCallback (reset_cb); - - SYS_SetPowerCallback (power_cb); - - // usleep(10000); - //WIIDVD_Init(false); - // usleep(10000); - - TryUSBDevice(); // init usb2 device - - // usleep(10000); - // save_log(); - // usleep(10000); - /* - if(WIIDVD_DiscPresent()) printf("dvd inserted\n"); - else printf("dvd NOT inserted\n"); - usleep(10000); - save_log(); - - if(fatMount("usb",usb,0,3,128)) - { - showdir("usb:/"); - } - else printf("can't mount usb\n"); - - sleep(6); - return 0; - wait_for_network_initialisation(); // check if lan is working - sleep(1); - */ - printf("Press Home or reset to exit. Press A or power to try to detect usb device again.\n"); - - VIDEO_WaitVSync(); - - VIDEO_WaitVSync(); - - while (1) //wait home press to exit - { - WPAD_ScanPads(); - - if (reset_pressed) break; - - u32 pressed = WPAD_ButtonsDown(0); - - if ( pressed & WPAD_BUTTON_HOME ) - { - mload_close(); - printf ("\n\nExit ..."); - exit(0); - } - - if ( (pressed & WPAD_BUTTON_A) || power_pressed) - { - power_pressed = false; - - TryUSBDevice(); - //usleep(5000); - power_pressed = false; - /* - if(fatMount("usb",usb,0,3,128)) - { - showdir("usb:/"); - } - else printf("can't mount usb\n"); - */ - //TryUSBDevice(); - /* - printf("deinit (5secs)\n"); - sleep(1); - net_deinit(); - sleep(4); - printf("init\n"); - wait_for_network_initialisation(); - */ - //power_pressed=false; - } - - usleep(5000); - VIDEO_WaitVSync(); - } - -out: - mload_close(); - printf ("\n\nExit ..."); - exit(0); -} +/************************************************************/ +/* USB speed test */ +/* */ +/* */ +/************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "mload.h" +#include "../build/ehcmodule_elf.h" +//#include "../build/fat_elf.h" +data_elf my_data_elf; +int my_thread_id=0; + + +#include + +#include +#include +#include +#include "usbstorage2.h" + + + +const DISC_INTERFACE* sd = &__io_wiisd; + +//const DISC_INTERFACE* usb1 = &__io_usb1storage; + +static bool reset_pressed = false; +static bool power_pressed = false; + +static void *xfb = NULL; +static GXRModeObj *rmode = NULL; +static const u32 CACHE_PAGES = 8; + +static u8 memsector[4*1024]; + + +void initialise_video() +{ + VIDEO_Init(); + rmode = VIDEO_GetPreferredMode(NULL); + xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode)); + console_init(xfb, 20, 20, rmode->fbWidth, rmode->xfbHeight, rmode->fbWidth * VI_DISPLAY_PIX_SZ); + VIDEO_Configure(rmode); + VIDEO_SetNextFramebuffer(xfb); + VIDEO_SetBlack(FALSE); + VIDEO_Flush(); + VIDEO_WaitVSync(); + if (rmode->viTVMode & VI_NON_INTERLACE) VIDEO_WaitVSync(); + printf("\x1b[2;0H"); + VIDEO_WaitVSync(); +} + +#include +//#define ticks_to_secs(ticks) ((u32)((u64)(ticks)/(u64)(TB_TIMER_CLOCK*1000))) +//#define ticks_to_msecs(ticks) ((u32)((u64)(ticks)/(u64)(TB_TIMER_CLOCK))) +/* +void showdir(char *path) +{ + char filename[MAXPATHLEN]; + DIR_ITER *dp; + struct stat fstat; + //chdir("usb:/"); + dp = diropen(path); + + if(dp==NULL) + { + printf("Error diropen\n"); + return; + } + else printf("Ok diropen\n"); + + int cnt=0; + while( dirnext( dp, filename, &fstat ) == 0 ) + { + //if(cnt==20) break; + cnt++; + + if( fstat.st_mode & S_IFDIR ) printf("/"); + printf("%s\n",filename); + + } + dirclose(dp); + printf("\nEnd show dirrectory (%d).\n",cnt); +} +*/ +static void reset_cb (void) { + reset_pressed = true; +} +static void power_cb (void) { + power_pressed = true; +} + +#include + + +#define VERSION "2.1" + + +void save_log() // at now all data is sent to usbgecko, sd log disabled +{ + FILE *fp; + u8 *temp_data= NULL; + u32 level,len; + + temp_data=memalign(32,256*1024); + + + mload_init(); + len=mload_get_log(); + + if(len>0) + mload_read(temp_data, len); + + + mload_close(); + + for(len=0;len <2*4096 && temp_data[len]!=0;len++); + /* + fatUnmount("sd"); + if(fatMount("sd",sd,0,128,2) ) + { + + fp=fopen("sd:/log_usb2.txt","wb"); + + if(fp!=0) + { + fprintf(fp,"USB2 device test program. v%s\n------------------------------\n",VERSION); + fwrite(temp_data,1, len ,fp); + + fclose(fp); + } + } + */ + if (usb_isgeckoalive(1)) { + level = IRQ_Disable(); + usb_sendbuffer(1, temp_data, len); + IRQ_Restore(level); + } + + //printf("\nlog:\n-------\n%s", temp_data); + free(temp_data); +} + +void TryUSBDevice(int port) +{ + printf("Initializing usb device port: %i.\n",port); + bool s; + DISC_INTERFACE* usb; + + if(port==0) usb= &__io_usbstorage2_port0; + else usb= &__io_usbstorage2_port1; + + //USB2Enable(true); + s=usb->startup(); + usleep(10000); + /* + if(s) + { + s = __usbstorage_ReadSectors(0, 1, memsector); + } + usleep(10000);*/ + + + if(s>0) + { + + printf("usb device detected, your device is fully compatible with this usb2 driver(%i)\n",s); + } + else + { + //(s==-1) printf("usb device NOT INSERTED, log file not created\n"); + //se + { + printf("usb device NOT detected or not inserted, report log file(%i)\n",s); + printf("Log saved to sd:/log_usb2.txt file\n"); + } + } + save_log(); +} + +void init_mload() +{ + int ret; + ret=mload_init(); + + if(ret<0) + { + printf("fail to get dev/mload, mload cios not detected. Quit\n"); + sleep(3); + exit(0); + //goto out; + } +} +void loadehcimodule() +{ + u32 addr; + int len; + + mload_get_load_base(&addr, &len); + + if(((u32) ehcmodule_elf) & 3) {printf("Unaligned elf!\n"); return;} + mload_elf((void *) ehcmodule_elf, &my_data_elf); + my_thread_id=mload_run_thread(my_data_elf.start, my_data_elf.stack, my_data_elf.size_stack, my_data_elf.prio); + //my_thread_id=mload_run_thread(my_data_elf.start, my_data_elf.stack, my_data_elf.size_stack, my_data_elf.prio); + if(my_thread_id<0) + { + printf("EHCI module can NOT be loaded (%i).. Quit\n",my_thread_id); + sleep(3); + exit(0); + } + + printf("EHCI module loaded (%i).\n",my_thread_id); + VIDEO_WaitVSync(); +} + +int main(int argc, char **argv) +{ + int ret; + bool usblan; + int usblanport; + + initialise_video(); + CON_EnableGecko(1,0); + + + + IOS_ReloadIOS(222); + init_mload(); + //mload_reset_log(); + loadehcimodule(); + + + SYS_SetResetCallback (reset_cb); + SYS_SetPowerCallback (power_cb); + WPAD_Init(); +// usleep(10000); +//WIIDVD_Init(false); +// usleep(10000); + +// TryUSBDevice(); // init usb2 device +// usleep(10000); +// save_log(); +// usleep(10000); +/* + if(WIIDVD_DiscPresent()) printf("dvd inserted\n"); + else printf("dvd NOT inserted\n"); + usleep(10000); + save_log(); + + if(fatMount("usb",usb,0,3,128)) + { + showdir("usb:/"); + } + else printf("can't mount usb\n"); + + sleep(6); + return 0; + wait_for_network_initialisation(); // check if lan is working + sleep(1); +*/ + printf("Press Home or reset to exit. Press A or power to try to detect usb device again.\n"); + + VIDEO_WaitVSync(); + VIDEO_WaitVSync(); + //exit(0); + while(1) //wait home press to exit + { + WPAD_ScanPads(); + if(reset_pressed) break; + u32 pressed = WPAD_ButtonsDown(0); + if ( pressed & WPAD_BUTTON_HOME ) + { + mload_close(); + printf ("\n\nExit ..."); + exit(0); + } + if ( (pressed & WPAD_BUTTON_A) || power_pressed) + { + power_pressed=false; + + TryUSBDevice(0); + //usleep(5000); + power_pressed=false; + /* + if(fatMount("usb",usb,0,3,128)) + { + showdir("usb:/"); + } + else printf("can't mount usb\n"); + */ + //TryUSBDevice(); + /* + printf("deinit (5secs)\n"); + sleep(1); + net_deinit(); + sleep(4); + printf("init\n"); + wait_for_network_initialisation(); + */ + //power_pressed=false; + } + if ( (pressed & WPAD_BUTTON_B) || power_pressed) + { + power_pressed=false; + + TryUSBDevice(1); + //usleep(5000); + power_pressed=false; + /* + if(fatMount("usb",usb,0,3,128)) + { + showdir("usb:/"); + } + else printf("can't mount usb\n"); + */ + //TryUSBDevice(); + /* + printf("deinit (5secs)\n"); + sleep(1); + net_deinit(); + sleep(4); + printf("init\n"); + wait_for_network_initialisation(); + */ + //power_pressed=false; + } + usleep(500); + VIDEO_WaitVSync(); + } +out: + mload_close(); + printf ("\n\nExit ..."); + exit(0); +} diff --git a/test/source/mload.c b/test/source/mload.c index e4fd17af..09ffecb1 100644 --- a/test/source/mload.c +++ b/test/source/mload.c @@ -1,493 +1,492 @@ -/* mload.c (for PPC) (c) 2009, Hermes - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include "mload.h" - -static const char mload_fs[] ATTRIBUTE_ALIGN(32) = "/dev/mload"; - -static s32 mload_fd = -1; -static s32 hid = -1; - -/*--------------------------------------------------------------------------------------------------------------*/ - -// to init/test if the device is running - -int mload_init() -{ - int n; - - if (hid < 0) hid = iosCreateHeap(0x800); - - if (hid < 0) - { - if (mload_fd >= 0) - IOS_Close(mload_fd); - - mload_fd = -1; - - return hid; - } - - if (mload_fd >= 0) - { - return 0; - } - - for (n = 0;n < 20;n++) // try 5 seconds - { - mload_fd = IOS_Open(mload_fs, 0); - - if (mload_fd >= 0) break; - - usleep(250*1000); - } - - if (mload_fd < 0) - { - - if (hid >= 0) - { - iosDestroyHeap(hid); - hid = -1; - } - } - - return mload_fd; -} - -/*--------------------------------------------------------------------------------------------------------------*/ - -// to close the device (remember call it when rebooting the IOS!) - -int mload_close() -{ - int ret; - - if (hid >= 0) - { - iosDestroyHeap(hid); - hid = -1; - } - - if (mload_fd < 0) return -1; - - ret = IOS_Close(mload_fd); - - mload_fd = -1; - - return ret; -} - -/*--------------------------------------------------------------------------------------------------------------*/ - -// to get the thread id of mload - -int mload_get_thread_id() -{ - int ret; - - if (mload_init() < 0) return -1; - - ret = IOS_IoctlvFormat(hid, mload_fd, MLOAD_MLOAD_THREAD_ID, ":"); - - return ret; - -} - -/*--------------------------------------------------------------------------------------------------------------*/ - -// get the base and the size of the memory readable/writable to load modules - -int mload_get_load_base(u32 *starlet_base, int *size) -{ - int ret; - - if (mload_init() < 0) return -1; - - ret = IOS_IoctlvFormat(hid, mload_fd, MLOAD_GET_LOAD_BASE, ":ii", starlet_base, size); - - return ret; - -} - -/*--------------------------------------------------------------------------------------------------------------*/ - -// load and run a module from starlet (it need to allocate MEM2 to send the elf file) -// the module must be a elf made with stripios - -int mload_module(void *addr, int len) -{ - int ret; - void *buf = NULL; - - - if (mload_init() < 0) return -1; - - if (hid >= 0) - { - iosDestroyHeap(hid); - hid = -1; - } - - hid = iosCreateHeap(len + 0x800); - - if (hid < 0) return hid; - - buf = iosAlloc(hid, len); - -if (!buf) {ret = -1;goto out;} - - - memcpy(buf, addr, len); - - ret = IOS_IoctlvFormat(hid, mload_fd, MLOAD_LOAD_MODULE, ":d", buf, len); - - if (ret < 0) goto out; - - ret = IOS_IoctlvFormat(hid, mload_fd, MLOAD_RUN_MODULE, ":"); - -if (ret < 0) {ret = -666;goto out;} - -out: - - if (hid >= 0) - { - iosDestroyHeap(hid); - hid = -1; - } - - return ret; - -} - -/*--------------------------------------------------------------------------------------------------------------*/ - -// load a module from the PPC -// the module must be a elf made with stripios - -int mload_elf(void *my_elf, data_elf *data_elf) -{ - int n, m; - int p; - u8 *adr; - u32 elf = (u32) my_elf; - - if (elf & 3) return -1; // aligned to 4 please! - - elfheader *head = (void *) elf; - - elfphentry *entries; - - if (head->ident0 != 0x7F454C46) return -1; - - if (head->ident1 != 0x01020161) return -1; - - if (head->ident2 != 0x01000000) return -1; - - p = head->phoff; - - data_elf->start = (void *) head->entry; - - for (n = 0; n < head->phnum; n++) - { - entries = (void *) (elf + p); - p += sizeof(elfphentry); - - if (entries->type == 4) - { - adr = (void *) (elf + entries->offset); - - if (getbe32(0) != 0) return -2; // bad info (sure) - - for (m = 4; m < entries->memsz; m += 8) - { - switch (getbe32(m)) - { - case 0x9: - data_elf->start = (void *) getbe32(m + 4); - break; - case 0x7D: - data_elf->prio = getbe32(m + 4); - break; - case 0x7E: - data_elf->size_stack = getbe32(m + 4); - break; - case 0x7F: - data_elf->stack = (void *) (getbe32(m + 4)); - break; - - } - - } - - } - - else - if (entries->type == 1 && entries->memsz != 0 && entries->vaddr != 0) - { - - if (mload_memset((void *) entries->vaddr, 0, entries->memsz) < 0) return -1; - - if (mload_seek(entries->vaddr, SEEK_SET) < 0) return -1; - - if (mload_write((void *) (elf + entries->offset), entries->filesz) < 0) return -1; - - } - } - - return 0; -} - -/*--------------------------------------------------------------------------------------------------------------*/ - -// run one thread (you can use to load modules or binary files) - -int mload_run_thread(void *starlet_addr, void *starlet_top_stack, int stack_size, int priority) -{ - int ret; - - - if (mload_init() < 0) return -1; - - ret = IOS_IoctlvFormat(hid, mload_fd, MLOAD_RUN_THREAD, "iiii:", starlet_addr, starlet_top_stack, stack_size, priority); - - - return ret; -} - -/*--------------------------------------------------------------------------------------------------------------*/ - -// stops one starlet thread - -int mload_stop_thread(int id) -{ - int ret; - - if (mload_init() < 0) return -1; - - ret = IOS_IoctlvFormat(hid, mload_fd, MLOAD_STOP_THREAD, "i:", id); - - return ret; - -} - -/*--------------------------------------------------------------------------------------------------------------*/ - -// continue one stopped starlet thread - -int mload_continue_thread(int id) -{ - int ret; - - if (mload_init() < 0) return -1; - - ret = IOS_IoctlvFormat(hid, mload_fd, MLOAD_CONTINUE_THREAD, "i:", id); - - return ret; - -} - -/*--------------------------------------------------------------------------------------------------------------*/ - -// fix starlet address to read/write (uses SEEK_SET, etc as mode) - -int mload_seek(int offset, int mode) -{ - if (mload_init() < 0) return -1; - - return IOS_Seek(mload_fd, offset, mode); -} - -/*--------------------------------------------------------------------------------------------------------------*/ - -// read bytes from starlet (it update the offset) - -int mload_read(void* buf, u32 size) -{ - if (mload_init() < 0) return -1; - - return IOS_Read(mload_fd, buf, size); -} - -/*--------------------------------------------------------------------------------------------------------------*/ - -// write bytes from starlet (it update the offset) - -int mload_write(const void * buf, u32 size) -{ - if (mload_init() < 0) return -1; - - return IOS_Write(mload_fd, buf, size); -} - -/*--------------------------------------------------------------------------------------------------------------*/ - -// fill a block (similar to memset) - -int mload_memset(void *starlet_addr, int set, int len) -{ - int ret; - - if (mload_init() < 0) return -1; - - ret = IOS_IoctlvFormat(hid, mload_fd, MLOAD_MEMSET, "iii:", starlet_addr, set, len); - - - return ret; -} - -/*--------------------------------------------------------------------------------------------------------------*/ - -// get the ehci datas ( ehcmodule.elf uses this address) - -void * mload_get_ehci_data() -{ - int ret; - - if (mload_init() < 0) return NULL; - - ret = IOS_IoctlvFormat(hid, mload_fd, MLOAD_GET_EHCI_DATA, ":"); - - if (ret < 0) return NULL; - - return (void *) ret; -} - -/*--------------------------------------------------------------------------------------------------------------*/ - -// set the dev/es ioctlv in routine - -int mload_set_ES_ioctlv_vector(void *starlet_addr) -{ - int ret; - - if (mload_init() < 0) return -1; - - ret = IOS_IoctlvFormat(hid, mload_fd, MLOAD_SET_ES_IOCTLV, "i:", starlet_addr); - - return ret; -} - - - -int mload_getw(const void * addr, u32 *dat) -{ - int ret; - - if (mload_init() < 0) return -1; - - ret = IOS_IoctlvFormat(hid, mload_fd, MLOAD_GETW, "i:i", addr, dat); - - return ret; -} - -int mload_geth(const void * addr, u16 *dat) -{ - int ret; - - if (mload_init() < 0) return -1; - - ret = IOS_IoctlvFormat(hid, mload_fd, MLOAD_GETH, "i:h", addr, dat); - - return ret; -} - -int mload_getb(const void * addr, u8 *dat) -{ - int ret; - - if (mload_init() < 0) return -1; - - ret = IOS_IoctlvFormat(hid, mload_fd, MLOAD_GETB, "i:b", addr, dat); - - return ret; -} - -int mload_setw(const void * addr, u32 dat) -{ - int ret; - - if (mload_init() < 0) return -1; - - ret = IOS_IoctlvFormat(hid, mload_fd, MLOAD_SETW, "ii:", addr, dat); - - return ret; -} - -int mload_seth(const void * addr, u16 dat) -{ - int ret; - - if (mload_init() < 0) return -1; - - ret = IOS_IoctlvFormat(hid, mload_fd, MLOAD_SETH, "ih:", addr, dat); - - return ret; -} - -int mload_setb(const void * addr, u8 dat) -{ - int ret; - - if (mload_init() < 0) return -1; - - ret = IOS_IoctlvFormat(hid, mload_fd, MLOAD_SETB, "ib:", addr, dat); - - return ret; -} - -/*--------------------------------------------------------------------------------------------------------------*/ - -// to get log buffer -// this function return the size of the log buffer and prepare it to read with mload_read() the datas - -int mload_get_log() -{ - int ret; - - if (mload_init() < 0) return -1; - - ret = IOS_IoctlvFormat(hid, mload_fd, MLOAD_GET_LOG, ":"); - - return ret; - -} - -void mload_reset_log() -{ - if (mload_init() < 0) return ; - - IOS_IoctlvFormat(hid, mload_fd, MLOAD_RESET_LOG, ":"); -} - -/*--------------------------------------------------------------------------------------------------------------*/ - -// to get IOS base for dev/es to create the cIOS - -int mload_get_IOS_base() -{ - int ret; - - if (mload_init() < 0) return -1; - - ret = IOS_IoctlvFormat(hid, mload_fd, MLOAD_GET_IOS_BASE, ":"); - - return ret; - -} - - +/* mload.c (for PPC) (c) 2009, Hermes + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "mload.h" + +static const char mload_fs[] ATTRIBUTE_ALIGN(32) = "/dev/mload"; + +static s32 mload_fd = -1; +static s32 hid = -1; + +/*--------------------------------------------------------------------------------------------------------------*/ + +// to init/test if the device is running + +int mload_init() +{ + int n; + + if(hid<0) hid = iosCreateHeap(0x10000); + + if(hid<0) + { + if(mload_fd>=0) + IOS_Close(mload_fd); + + mload_fd=-1; + + return hid; + } + + if(mload_fd>=0) + { + return 0; + } + + for(n=0;n<20;n++) // try 5 seconds + { + mload_fd=IOS_Open(mload_fs, 0); + + if(mload_fd>=0) break; + + usleep(250*1000); + } + + return mload_fd; +} + +/*--------------------------------------------------------------------------------------------------------------*/ + +// to close the device (remember call it when rebooting the IOS!) + +int mload_close() +{ + int ret; + + if(mload_fd<0) return -1; + + ret=IOS_Close(mload_fd); + + mload_fd=-1; + + return ret; +} + +/*--------------------------------------------------------------------------------------------------------------*/ + +// to get the thread id of mload + +int mload_get_thread_id() +{ + int ret; + + if(mload_init()<0) return -1; + + ret= IOS_IoctlvFormat(hid, mload_fd, MLOAD_MLOAD_THREAD_ID, ":"); + + return ret; +} + +/*--------------------------------------------------------------------------------------------------------------*/ + +// get the base and the size of the memory readable/writable to load modules + +int mload_get_load_base(u32 *starlet_base, int *size) +{ + int ret; + + if(mload_init()<0) return -1; + + ret= IOS_IoctlvFormat(hid, mload_fd, MLOAD_GET_LOAD_BASE, ":ii",starlet_base, size); + + return ret; +} + +/*--------------------------------------------------------------------------------------------------------------*/ + +// load and run a module from starlet (it need to allocate MEM2 to send the elf file) +// the module must be a elf made with stripios + +int mload_module(void *addr, int len) +{ + int ret; + void *buf=NULL; + + buf= iosAlloc(hid, len); + + if(!buf) + return -1; + + memcpy(buf, addr,len); + + ret = IOS_IoctlvFormat(hid, mload_fd, MLOAD_LOAD_MODULE, ":d", buf, len); + if(ret<0) + return ret; + + ret=IOS_IoctlvFormat(hid, mload_fd, MLOAD_RUN_MODULE, ":"); + + return ret; +} + +/*--------------------------------------------------------------------------------------------------------------*/ + +// load a module from the PPC +// the module must be a elf made with stripios + +int mload_elf(void *my_elf, data_elf *data_elf) +{ + int n,m; + int p; + u8 *adr; + u32 elf=(u32) my_elf; + + if(elf & 3) return -1; // aligned to 4 please! + + elfheader *head=(void *) elf; + elfphentry *entries; + + if(head->ident0!=0x7F454C46) return -1; + if(head->ident1!=0x01020161) return -1; + if(head->ident2!=0x01000000) return -1; + + p=head->phoff; + + data_elf->start=(void *) head->entry; + + for(n=0; nphnum; n++) + { + entries=(void *) (elf+p); + p+=sizeof(elfphentry); + + if(entries->type == 4) + { + adr=(void *) (elf + entries->offset); + + if(getbe32(0)!=0) return -2; // bad info (sure) + + for(m=4; (u32)m < entries->memsz; m+=8) + { + switch(getbe32(m)) + { + case 0x9: + data_elf->start= (void *) getbe32(m+4); + break; + case 0x7D: + data_elf->prio= getbe32(m+4); + break; + case 0x7E: + data_elf->size_stack= getbe32(m+4); + break; + case 0x7F: + data_elf->stack= (void *) (getbe32(m+4)); + break; + + } + + } + + } + else + if(entries->type == 1 && entries->memsz != 0 && entries->vaddr!=0) + { + + if(mload_memset((void *) entries->vaddr, 0, entries->memsz)<0) return -1; + if(mload_seek(entries->vaddr, SEEK_SET)<0) return -1; + if(mload_write((void *) (elf + entries->offset), entries->filesz)<0) return -1; + + } + } + + return 0; +} + +/*--------------------------------------------------------------------------------------------------------------*/ + +// run one thread (you can use to load modules or binary files) + +int mload_run_thread(void *starlet_addr, void *starlet_top_stack, int stack_size, int priority) +{ + int ret; + + if(mload_init()<0) return -1; + + ret= IOS_IoctlvFormat(hid, mload_fd, MLOAD_RUN_THREAD, "iiii:", starlet_addr,starlet_top_stack, stack_size, priority); + + return ret; +} + +/*--------------------------------------------------------------------------------------------------------------*/ + +// stops one starlet thread + +int mload_stop_thread(int id) +{ +int ret; + + if(mload_init()<0) return -1; + + ret= IOS_IoctlvFormat(hid, mload_fd, MLOAD_STOP_THREAD, "i:", id); + +return ret; + +} + +/*--------------------------------------------------------------------------------------------------------------*/ + +// continue one stopped starlet thread + +int mload_continue_thread(int id) +{ + int ret; + + if(mload_init()<0) return -1; + + ret= IOS_IoctlvFormat(hid, mload_fd, MLOAD_CONTINUE_THREAD, "i:", id); + + return ret; +} +/*--------------------------------------------------------------------------------------------------------------*/ + +// fix starlet address to read/write (uses SEEK_SET, etc as mode) + +int mload_seek(int offset, int mode) +{ + if(mload_init()<0) return -1; + + return IOS_Seek(mload_fd, offset, mode); +} + +/*--------------------------------------------------------------------------------------------------------------*/ + +// read bytes from starlet (it update the offset) + +int mload_read(void* buf, u32 size) +{ + if(mload_init()<0) return -1; + + return IOS_Read(mload_fd, buf, size); +} + +/*--------------------------------------------------------------------------------------------------------------*/ + +// write bytes from starlet (it update the offset) + +int mload_write(const void * buf, u32 size) +{ + if(mload_init()<0) return -1; + + return IOS_Write(mload_fd, buf, size); +} + +/*--------------------------------------------------------------------------------------------------------------*/ + +// fill a block (similar to memset) + +int mload_memset(void *starlet_addr, int set, int len) +{ + int ret; + + if(mload_init()<0) return -1; + + ret= IOS_IoctlvFormat(hid, mload_fd, MLOAD_MEMSET, "iii:", starlet_addr, set, len); + + return ret; +} + +/*--------------------------------------------------------------------------------------------------------------*/ + +// get the ehci datas ( ehcmodule.elf uses this address) + +void * mload_get_ehci_data() +{ + int ret; + + if(mload_init()<0) return NULL; + + ret= IOS_IoctlvFormat(hid, mload_fd, MLOAD_GET_EHCI_DATA, ":"); + if(ret<0) return NULL; + + return (void *) ret; +} + +/*--------------------------------------------------------------------------------------------------------------*/ + +// set the dev/es ioctlv in routine + +int mload_set_ES_ioctlv_vector(void *starlet_addr) +{ + int ret; + + if(mload_init()<0) return -1; + + ret= IOS_IoctlvFormat(hid, mload_fd, MLOAD_SET_ES_IOCTLV, "i:", starlet_addr); + + return ret; +} + + + +int mload_getw(const void * addr, u32 *dat) +{ + int ret; + + if(mload_init()<0) return -1; + + ret= IOS_IoctlvFormat(hid, mload_fd, MLOAD_GETW, "i:i", addr, dat); + + return ret; +} + +int mload_geth(const void * addr, u16 *dat) +{ + int ret; + + if(mload_init()<0) return -1; + + ret= IOS_IoctlvFormat(hid, mload_fd, MLOAD_GETH, "i:h", addr, dat); + + return ret; +} + +int mload_getb(const void * addr, u8 *dat) +{ + int ret; + + if(mload_init()<0) return -1; + + ret= IOS_IoctlvFormat(hid, mload_fd, MLOAD_GETB, "i:b", addr, dat); + + return ret; +} + +int mload_setw(const void * addr, u32 dat) +{ + int ret; + + if(mload_init()<0) return -1; + + ret= IOS_IoctlvFormat(hid, mload_fd, MLOAD_SETW, "ii:", addr, dat); + + return ret; +} + +int mload_seth(const void * addr, u16 dat) +{ + int ret; + + if(mload_init()<0) return -1; + + ret= IOS_IoctlvFormat(hid, mload_fd, MLOAD_SETH, "ih:", addr, dat); + + return ret; +} + +int mload_setb(const void * addr, u8 dat) +{ + int ret; + + if(mload_init()<0) return -1; + + ret= IOS_IoctlvFormat(hid, mload_fd, MLOAD_SETB, "ib:", addr, dat); + + return ret; +} + +/*--------------------------------------------------------------------------------------------------------------*/ + +// to get log buffer +// this function return the size of the log buffer and prepare it to read with mload_read() the datas + +int mload_get_log() +{ + int ret; + + if(mload_init()<0) return -1; + + ret= IOS_IoctlvFormat(hid, mload_fd, MLOAD_GET_LOG, ":"); + + return ret; + +} + + +/*--------------------------------------------------------------------------------------------------------------*/ + +// to get IOS base for dev/es to create the cIOS + +int mload_get_IOS_base() +{ + int ret; + + if(mload_init()<0) return -1; + + ret= IOS_IoctlvFormat(hid, mload_fd, MLOAD_GET_IOS_BASE, ":"); + + return ret; + +} + + +int mload_get_version() +{ + int ret; + if(mload_init()<0) return -1; + ret = IOS_IoctlvFormat(hid, mload_fd, MLOAD_GET_MLOAD_VERSION, ":"); + return ret; +} + +/* IOS info structure */ +typedef struct { + /* Syscall base */ + u32 syscall; + + /* Module versions */ + u32 dipVersion; + u32 esVersion; + u32 ffsVersion; + u32 iopVersion; +} iosInfo; + +int wanin_mload_get_IOS_base() +{ + int ret; + iosInfo ios; + memset(&ios, 0, sizeof(ios)); + + if(mload_init()<0) return -1; + + ret= IOS_IoctlvFormat(hid, mload_fd, MLOAD_GET_IOS_BASE, ":d", &ios, sizeof(ios)); + //gprintf("get_ios_base: %d %x\n", ret, ios.dipVersion); + if (ret == 0) { + switch(ios.dipVersion) { + case 0x48776F72: /* DIP: 07/11/08 14:34:26 */ + return 37; + + case 0x4888E14C: /* DIP: 07/24/08 20:08:44 */ + return 38; + + case 0x4A262AF5: /* DIP: 06/03/09 07:49:09 */ + return 57; + + case 0x492ACA9D: /* DIP: 11/24/08 15:39:09 */ + return 60; + } + } + return ret; +} + +int mload_set_gecko_debug() +{ + int ret; + u32 log_mode = 2; // GECKO + if(mload_init()<0) return -1; + + gprintf("Setting debug mode..."); + ret = IOS_IoctlvFormat(hid, mload_fd, MLOAD_SET_LOG_MODE, ":d", &log_mode, sizeof(log_mode)); + gprintf("%d\n", ret); + return ret; +} diff --git a/test/source/mload.h b/test/source/mload.h index ff900fa7..43f21d4c 100644 --- a/test/source/mload.h +++ b/test/source/mload.h @@ -1,240 +1,233 @@ -/* mload.c (for PPC) (c) 2009, Hermes - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef __MLOAD_H__ -#define __MLOAD_H__ - - -#include -#include -#include -#include -#include -#include "unistd.h" - -#define MLOAD_MLOAD_THREAD_ID 0x4D4C4400 -#define MLOAD_GET_IOS_BASE 0x4D4C4401 -#define MLOAD_LOAD_MODULE 0x4D4C4480 -#define MLOAD_RUN_MODULE 0x4D4C4481 -#define MLOAD_RUN_THREAD 0x4D4C4482 - -#define MLOAD_STOP_THREAD 0x4D4C4484 -#define MLOAD_CONTINUE_THREAD 0x4D4C4485 - -#define MLOAD_GET_LOAD_BASE 0x4D4C4490 -#define MLOAD_MEMSET 0x4D4C4491 - -#define MLOAD_GET_EHCI_DATA 0x4D4C44A0 -#define MLOAD_GET_LOG 0x4D4C44A1 -#define MLOAD_RESET_LOG 0x4D4C44A2 - -#define MLOAD_SET_ES_IOCTLV 0x4D4C44B0 - -#define MLOAD_GETW 0x4D4C44C0 -#define MLOAD_GETH 0x4D4C44C1 -#define MLOAD_GETB 0x4D4C44C2 -#define MLOAD_SETW 0x4D4C44C3 -#define MLOAD_SETH 0x4D4C44C4 -#define MLOAD_SETB 0x4D4C44C5 - -#ifdef __cplusplus -extern "C" -{ -#endif - - - // from IOS ELF stripper of neimod - -#define getbe32(x) ((adr[x]<<24) | (adr[x+1]<<16) | (adr[x+2]<<8) | (adr[x+3])) - - typedef struct - { - u32 ident0; - u32 ident1; - u32 ident2; - u32 ident3; - u32 machinetype; - u32 version; - u32 entry; - u32 phoff; - u32 shoff; - u32 flags; - u16 ehsize; - u16 phentsize; - u16 phnum; - u16 shentsize; - u16 shnum; - u16 shtrndx; - } - - elfheader; - - typedef struct - { - u32 type; - u32 offset; - u32 vaddr; - u32 paddr; - u32 filesz; - u32 memsz; - u32 flags; - u32 align; - } - - elfphentry; - - typedef struct - { - void *start; - int prio; - void *stack; - int size_stack; - } - - data_elf; - - /*--------------------------------------------------------------------------------------------------------------*/ - - // to init/test if the device is running - - int mload_init(); - - /*--------------------------------------------------------------------------------------------------------------*/ - - // to close the device (remember call it when rebooting the IOS!) - - int mload_close(); - - /*--------------------------------------------------------------------------------------------------------------*/ - - // to get the thread id of mload - - int mload_get_thread_id(); - - /*--------------------------------------------------------------------------------------------------------------*/ - - // get the base and the size of the memory readable/writable to load modules - - int mload_get_load_base(u32 *starlet_base, int *size); - - /*--------------------------------------------------------------------------------------------------------------*/ - - // load and run a module from starlet (it need to allocate MEM2 to send the elf file) - // the module must be a elf made with stripios - - int mload_module(void *addr, int len); - - /*--------------------------------------------------------------------------------------------------------------*/ - - // load a module from the PPC - // the module must be a elf made with stripios - - int mload_elf(void *my_elf, data_elf *data_elf); - - /*--------------------------------------------------------------------------------------------------------------*/ - - // run one thread (you can use to load modules or binary files) - - int mload_run_thread(void *starlet_addr, void *starlet_top_stack, int stack_size, int priority); - - /*--------------------------------------------------------------------------------------------------------------*/ - - // stops one starlet thread - - int mload_stop_thread(int id); - - /*--------------------------------------------------------------------------------------------------------------*/ - - // continue one stopped starlet thread - - int mload_continue_thread(int id); - - /*--------------------------------------------------------------------------------------------------------------*/ - - // fix starlet address to read/write (uses SEEK_SET, etc as mode) - - int mload_seek(int offset, int mode); - - /*--------------------------------------------------------------------------------------------------------------*/ - - // read bytes from starlet (it update the offset) - - int mload_read(void* buf, u32 size); - - /*--------------------------------------------------------------------------------------------------------------*/ - - // write bytes from starlet (it update the offset) - - int mload_write(const void * buf, u32 size); - - /*--------------------------------------------------------------------------------------------------------------*/ - - // fill a block (similar to memset) - - int mload_memset(void *starlet_addr, int set, int len); - - /*--------------------------------------------------------------------------------------------------------------*/ - - // get the ehci datas ( ehcmodule.elf uses this address) - - void * mload_get_ehci_data(); - - /*--------------------------------------------------------------------------------------------------------------*/ - - // set the dev/es ioctlv in routine - - int mload_set_ES_ioctlv_vector(void *starlet_addr); - - /*--------------------------------------------------------------------------------------------------------------*/ - - - // to get log buffer - // this function return the size of the log buffer and prepare it to read with mload_read() the datas - - int mload_get_log(); - - void mload_reset_log(); - - /*--------------------------------------------------------------------------------------------------------------*/ - - - // to get IOS base for dev/es to create the cIOS - - int mload_get_IOS_base(); - - /*--------------------------------------------------------------------------------------------------------------*/ - - int mload_getw(const void * addr, u32 *dat); - - int mload_geth(const void * addr, u16 *dat); - - int mload_getb(const void * addr, u8 *dat); - - int mload_setw(const void * addr, u32 dat); - - int mload_seth(const void * addr, u16 dat); - - int mload_setb(const void * addr, u8 dat); - -#ifdef __cplusplus - -} - -#endif - - -#endif +/* mload.c (for PPC) (c) 2009, Hermes + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef __MLOAD_H__ +#define __MLOAD_H__ + + +#include +#include +#include +#include +#include +#include "unistd.h" + +#define MLOAD_MLOAD_THREAD_ID 0x4D4C4400 +#define MLOAD_GET_IOS_BASE 0x4D4C4401 +#define MLOAD_GET_MLOAD_VERSION 0x4D4C4402 + +#define MLOAD_LOAD_MODULE 0x4D4C4480 +#define MLOAD_RUN_MODULE 0x4D4C4481 +#define MLOAD_RUN_THREAD 0x4D4C4482 + +#define MLOAD_STOP_THREAD 0x4D4C4484 +#define MLOAD_CONTINUE_THREAD 0x4D4C4485 + +#define MLOAD_GET_LOAD_BASE 0x4D4C4490 +#define MLOAD_MEMSET 0x4D4C4491 + +#define MLOAD_GET_EHCI_DATA 0x4D4C44A0 +#define MLOAD_GET_LOG 0x4D4C44A1 + +#define MLOAD_SET_ES_IOCTLV 0x4D4C44B0 + +#define MLOAD_GETW 0x4D4C44C0 +#define MLOAD_GETH 0x4D4C44C1 +#define MLOAD_GETB 0x4D4C44C2 +#define MLOAD_SETW 0x4D4C44C3 +#define MLOAD_SETH 0x4D4C44C4 +#define MLOAD_SETB 0x4D4C44C5 + +#define MLOAD_SET_LOG_MODE 0x4D4C44D0 +#define MLOAD_GET_LOG_BUFFER 0x4D4C44D1 + +#ifdef __cplusplus +extern "C" { +#endif + +// from IOS ELF stripper of neimod + +#define getbe32(x) ((adr[x]<<24) | (adr[x+1]<<16) | (adr[x+2]<<8) | (adr[x+3])) + +typedef struct +{ + u32 ident0; + u32 ident1; + u32 ident2; + u32 ident3; + u32 machinetype; + u32 version; + u32 entry; + u32 phoff; + u32 shoff; + u32 flags; + u16 ehsize; + u16 phentsize; + u16 phnum; + u16 shentsize; + u16 shnum; + u16 shtrndx; +} elfheader; + +typedef struct +{ + u32 type; + u32 offset; + u32 vaddr; + u32 paddr; + u32 filesz; + u32 memsz; + u32 flags; + u32 align; +} elfphentry; + +typedef struct +{ + void *start; + int prio; + void *stack; + int size_stack; +} data_elf; + +/*--------------------------------------------------------------------------------------------------------------*/ + +// to init/test if the device is running + +int mload_init(); + +/*--------------------------------------------------------------------------------------------------------------*/ + +// to close the device (remember call it when rebooting the IOS!) + +int mload_close(); + +/*--------------------------------------------------------------------------------------------------------------*/ + +// to get the thread id of mload + +int mload_get_thread_id(); + +/*--------------------------------------------------------------------------------------------------------------*/ + +// get the base and the size of the memory readable/writable to load modules + +int mload_get_load_base(u32 *starlet_base, int *size); + +/*--------------------------------------------------------------------------------------------------------------*/ + +// load and run a module from starlet (it need to allocate MEM2 to send the elf file) +// the module must be a elf made with stripios + +int mload_module(void *addr, int len); + +/*--------------------------------------------------------------------------------------------------------------*/ + +// load a module from the PPC +// the module must be a elf made with stripios + +int mload_elf(void *my_elf, data_elf *data_elf); + +/*--------------------------------------------------------------------------------------------------------------*/ + +// run one thread (you can use to load modules or binary files) + +int mload_run_thread(void *starlet_addr, void *starlet_top_stack, int stack_size, int priority); + +/*--------------------------------------------------------------------------------------------------------------*/ + +// stops one starlet thread + +int mload_stop_thread(int id); + +/*--------------------------------------------------------------------------------------------------------------*/ + +// continue one stopped starlet thread + +int mload_continue_thread(int id); + +/*--------------------------------------------------------------------------------------------------------------*/ + +// fix starlet address to read/write (uses SEEK_SET, etc as mode) + +int mload_seek(int offset, int mode); + +/*--------------------------------------------------------------------------------------------------------------*/ + +// read bytes from starlet (it update the offset) + +int mload_read(void* buf, u32 size); + +/*--------------------------------------------------------------------------------------------------------------*/ + +// write bytes from starlet (it update the offset) + +int mload_write(const void * buf, u32 size); + +/*--------------------------------------------------------------------------------------------------------------*/ + +// fill a block (similar to memset) + +int mload_memset(void *starlet_addr, int set, int len); + +/*--------------------------------------------------------------------------------------------------------------*/ + +// get the ehci datas ( ehcmodule.elf uses this address) + +void * mload_get_ehci_data(); + +/*--------------------------------------------------------------------------------------------------------------*/ + +// set the dev/es ioctlv in routine + +int mload_set_ES_ioctlv_vector(void *starlet_addr); + +/*--------------------------------------------------------------------------------------------------------------*/ + + +// to get log buffer +// this function return the size of the log buffer and prepare it to read with mload_read() the datas + +int mload_get_log(); + +/*--------------------------------------------------------------------------------------------------------------*/ + + +// to get IOS base for dev/es to create the cIOS + +int mload_get_IOS_base(); + +int mload_get_version(); + +/*--------------------------------------------------------------------------------------------------------------*/ + +int mload_getw(const void * addr, u32 *dat); +int mload_geth(const void * addr, u16 *dat); +int mload_getb(const void * addr, u8 *dat); + +int mload_setw(const void * addr, u32 dat); +int mload_seth(const void * addr, u16 dat); +int mload_setb(const void * addr, u8 dat); + +int wanin_mload_get_IOS_base(); +int mload_set_gecko_debug(); + +#ifdef __cplusplus + } +#endif + + +#endif diff --git a/test/source/usbstorage2.c b/test/source/usbstorage2.c new file mode 100644 index 00000000..0694fcfb --- /dev/null +++ b/test/source/usbstorage2.c @@ -0,0 +1,344 @@ +/*------------------------------------------------------------- + + usbstorage_starlet.c -- USB mass storage support, inside starlet + Copyright (C) 2011 Dimok + Copyright (C) 2011 Rodries + Copyright (C) 2009 Kwiirk + + If this driver is linked before libogc, this will replace the original + usbstorage driver by svpe from libogc + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any + damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and + redistribute it freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you use + this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + -------------------------------------------------------------*/ + +#include +#include +#include +#include +#include "usbstorage2.h" +//#include "memory/mem2.h" +//#include "gecko.h" + + +/* IOCTL commands */ +#define UMS_BASE (('U'<<24)|('M'<<16)|('S'<<8)) +#define USB_IOCTL_UMS_INIT (UMS_BASE+0x1) +#define USB_IOCTL_UMS_GET_CAPACITY (UMS_BASE+0x2) +#define USB_IOCTL_UMS_READ_SECTORS (UMS_BASE+0x3) +#define USB_IOCTL_UMS_WRITE_SECTORS (UMS_BASE+0x4) +#define USB_IOCTL_UMS_READ_STRESS (UMS_BASE+0x5) +#define USB_IOCTL_UMS_SET_VERBOSE (UMS_BASE+0x6) +#define USB_IOCTL_UMS_UMOUNT (UMS_BASE+0x10) +#define USB_IOCTL_UMS_WATCHDOG (UMS_BASE+0x80) + +#define USB_IOCTL_UMS_TESTMODE (UMS_BASE+0x81) +#define USB_IOCTL_SET_PORT (UMS_BASE+0x83) + +#define WBFS_BASE (('W'<<24)|('F'<<16)|('S'<<8)) +#define USB_IOCTL_WBFS_OPEN_DISC (WBFS_BASE+0x1) +#define USB_IOCTL_WBFS_READ_DISC (WBFS_BASE+0x2) +#define USB_IOCTL_WBFS_SET_DEVICE (WBFS_BASE+0x50) +#define USB_IOCTL_WBFS_SET_FRAGLIST (WBFS_BASE+0x51) + +#define isMEM2Buffer(p) (((u32) p & 0x10000000) != 0) + +#define MAX_SECTOR_SIZE 4096 +#define MAX_BUFFER_SECTORS 128 +#define UMS_HEAPSIZE 2*1024 //it's enoguh, only used for ipc calls, don't waste ios heap + +/* Variables */ +static char fs[] ATTRIBUTE_ALIGN(32) = "/dev/usb2"; +static char fs2[] ATTRIBUTE_ALIGN(32) = "/dev/usb123"; +static char fs3[] ATTRIBUTE_ALIGN(32) = "/dev/usb/ehc"; + +static u8 * mem2_ptr = NULL; +static s32 hid = -1, fd = -1; +static u32 usb2_port = -1; //current USB port +bool hddInUse[2] = { false, false }; +u32 hdd_sector_size[2] = { 512, 512 }; + +s32 USBStorage2_Init(u32 port) +{ + s32 ret; + + /* Create heap */ + if (hid < 0) + { + hid = iosCreateHeap(UMS_HEAPSIZE + 4*1024); //added 4kb for testing, must be deleted because mem2_ptr will be created with mem2 manager + if (hid < 0) return IPC_ENOMEM; + } + + /* Open USB device */ + if (fd < 0) + { + if (fd < 0) fd = IOS_Open(fs, 0); + if (fd < 0) fd = IOS_Open(fs2, 0); + if (fd < 0) fd = IOS_Open(fs3, 0); + if (fd < 0) return fd; + } + USBStorage2_SetPort(port); + + /* Initialize USB storage */ + ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_INIT, ":"); + if(ret!=port) return -1; + + /* Get device capacity */ + if (USBStorage2_GetCapacity(port, &hdd_sector_size[port]) == 0) + return IPC_ENOENT; + + hddInUse[port] = true; + + return 0; // 0->HDD, 1->DVD +} + +void USBStorage2_Deinit(u32 port) +{ + /* Close USB device */ + if (fd >= 0) + { + if(!hddInUse[!port]) + { + IOS_Close(fd); // not sure to close the fd is needed + fd = -1; + } + hddInUse[port] = false; + } + + hdd_sector_size[port] = 512; +} + +s32 USBStorage2_SetPort(u32 port) +{ + //! Port = 2 is handle in the loader, no need to handle it in cIOS + if(port > 1) + return -1; + + if(port == usb2_port) + return 0; + + s32 ret = -1; + usb2_port = port; + + //gprintf("Changing USB port to port %i....\n", port); + //must be called before USBStorage2_Init (default port 0) + if (fd >= 0) + ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_SET_PORT, "i:", usb2_port); + + return ret; +} + +s32 USBStorage2_GetPort() +{ + return usb2_port; +} + +s32 USBStorage2_GetCapacity(u32 port, u32 *_sector_size) +{ + if (fd >= 0) + { + s32 ret; + u32 sector_size = 0; + USBStorage2_SetPort(port); + + ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_GET_CAPACITY, ":i", §or_size); + + if (ret && _sector_size) *_sector_size = sector_size; + + return ret; + } + + return IPC_ENOENT; +} + +s32 USBStorage2_ReadSectors(u32 port, u32 sector, u32 numSectors, void *buffer) +{ + u8 *buf = (u8 *) buffer; + s32 ret = -1; + + /* Device not opened */ + if (fd < 0) return fd; + + if (!mem2_ptr) + //mem2_ptr = (u8 *) MEM2_alloc(MAX_SECTOR_SIZE * MAX_BUFFER_SECTORS); + mem2_ptr = (u8 *) __lwp_heap_allocate(&hid, 4*1024); //patch for testing mem2 manager must be used + + USBStorage2_SetPort(port); + + s32 read_secs, read_size; + + while(numSectors > 0) + { + read_secs = numSectors > MAX_BUFFER_SECTORS ? MAX_BUFFER_SECTORS : numSectors; + read_size = read_secs*hdd_sector_size[port]; + + // Do not read more than MAX_BUFFER_SECTORS sectors at once and create a mem overflow! + if (!isMEM2Buffer(buffer)) + { + ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_READ_SECTORS, "ii:d", sector, read_secs, mem2_ptr, read_size); + if(ret < 0) + return ret; + + memcpy(buf, mem2_ptr, read_size); + } + else + { + /* Read data */ + ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_READ_SECTORS, "ii:d", sector, read_secs, buf, read_size); + if(ret < 0) + return ret; + } + + sector += read_secs; + numSectors -= read_secs; + buf += read_size; + } + + return ret; +} + +s32 USBStorage2_WriteSectors(u32 port, u32 sector, u32 numSectors, const void *buffer) +{ + u8 *buf = (u8 *) buffer; + s32 ret = -1; + + /* Device not opened */ + if (fd < 0) return fd; + + /* Device not opened */ + if (!mem2_ptr) + //mem2_ptr = (u8 *) MEM2_alloc(MAX_SECTOR_SIZE * MAX_BUFFER_SECTORS); + mem2_ptr = (u8 *) __lwp_heap_allocate(&hid, 4*1024); //patch for testing mem2 manager must be used + + USBStorage2_SetPort(port); + + s32 write_size, write_secs; + + while(numSectors > 0) + { + write_secs = numSectors > MAX_BUFFER_SECTORS ? MAX_BUFFER_SECTORS : numSectors; + write_size = write_secs*hdd_sector_size[port]; + + /* MEM1 buffer */ + if (!isMEM2Buffer(buffer)) + { + // Do not read more than MAX_BUFFER_SECTORS sectors at once and create a mem overflow! + memcpy(mem2_ptr, buf, write_size); + + ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_WRITE_SECTORS, "ii:d", sector, write_secs, mem2_ptr, write_size); + if(ret < 0) + return ret; + } + else + { + /* Write data */ + ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_WRITE_SECTORS, "ii:d", sector, write_secs, buf, write_size); + if(ret < 0) + return ret; + } + + sector += write_secs; + numSectors -= write_secs; + buf += write_size; + } + + return ret; +} + +static bool __usbstorage_Startup(void) +{ + return USBStorage2_Init(0) >= 0; +} + +static bool __usbstorage_IsInserted(void) +{ + return (USBStorage2_GetCapacity(0, NULL) != 0); +} + +static bool __usbstorage_ReadSectors(u32 sector, u32 numSectors, void *buffer) +{ + return (USBStorage2_ReadSectors(0, sector, numSectors, buffer) >= 0); +} + +static bool __usbstorage_WriteSectors(u32 sector, u32 numSectors, const void *buffer) +{ + return (USBStorage2_WriteSectors(0, sector, numSectors, buffer) >= 0); +} + +static bool __usbstorage_ClearStatus(void) +{ + return true; +} + +static bool __usbstorage_Shutdown(void) +{ + USBStorage2_Deinit(0); + return true; +} + +const DISC_INTERFACE __io_usbstorage2_port0 = { + DEVICE_TYPE_WII_UMS, FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_USB, + (FN_MEDIUM_STARTUP) &__usbstorage_Startup, + (FN_MEDIUM_ISINSERTED) &__usbstorage_IsInserted, + (FN_MEDIUM_READSECTORS) &__usbstorage_ReadSectors, + (FN_MEDIUM_WRITESECTORS) &__usbstorage_WriteSectors, + (FN_MEDIUM_CLEARSTATUS) &__usbstorage_ClearStatus, + (FN_MEDIUM_SHUTDOWN) &__usbstorage_Shutdown +}; + +static bool __usbstorage_Startup2(void) +{ + return USBStorage2_Init(1) >= 0; +} + +static bool __usbstorage_IsInserted2(void) +{ + return (USBStorage2_GetCapacity(1, NULL) != 0); +} + +static bool __usbstorage_ReadSectors2(u32 sector, u32 numSectors, void *buffer) +{ + return (USBStorage2_ReadSectors(1, sector, numSectors, buffer) >= 0); +} + +static bool __usbstorage_WriteSectors2(u32 sector, u32 numSectors, const void *buffer) +{ + return (USBStorage2_WriteSectors(1, sector, numSectors, buffer) >= 0); +} + +static bool __usbstorage_ClearStatus2(void) +{ + return true; +} + +static bool __usbstorage_Shutdown2(void) +{ + USBStorage2_Deinit(1); + return true; +} + +const DISC_INTERFACE __io_usbstorage2_port1 = { + DEVICE_TYPE_WII_UMS, FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_USB, + (FN_MEDIUM_STARTUP) &__usbstorage_Startup2, + (FN_MEDIUM_ISINSERTED) &__usbstorage_IsInserted2, + (FN_MEDIUM_READSECTORS) &__usbstorage_ReadSectors2, + (FN_MEDIUM_WRITESECTORS) &__usbstorage_WriteSectors2, + (FN_MEDIUM_CLEARSTATUS) &__usbstorage_ClearStatus2, + (FN_MEDIUM_SHUTDOWN) &__usbstorage_Shutdown2 +}; diff --git a/test/source/usbstorage2.h b/test/source/usbstorage2.h new file mode 100644 index 00000000..80687eea --- /dev/null +++ b/test/source/usbstorage2.h @@ -0,0 +1,31 @@ +#ifndef _USBSTORAGE2_H_ +#define _USBSTORAGE2_H_ + +#include "ogc/disc_io.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + /* Prototypes */ + s32 USBStorage2_Init(u32 port); + void USBStorage2_Deinit(u32 port); + s32 USBStorage2_GetCapacity(u32 port, u32 *size); + + s32 USBStorage2_ReadSectors(u32 port, u32 sector, u32 numSectors, void *buffer); + s32 USBStorage2_WriteSectors(u32 port, u32 sector, u32 numSectors, const void *buffer); + + s32 USBStorage2_SetPort(u32 port); + s32 USBStorage2_GetPort(); + +#define DEVICE_TYPE_WII_UMS (('W'<<24)|('U'<<16)|('M'<<8)|'S') + + extern const DISC_INTERFACE __io_usbstorage2_port0; + extern const DISC_INTERFACE __io_usbstorage2_port1; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tinyehci/ehci.c b/tinyehci/ehci.c index caddc158..79bee390 100644 --- a/tinyehci/ehci.c +++ b/tinyehci/ehci.c @@ -25,8 +25,6 @@ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -extern char use_usb_port1; - /* magic numbers that can affect system performance */ #define EHCI_TUNE_CERR 0 /* 0-3 qtd retries; 0 == don't stop */ /* by Hermes: i have replaced 3 by 0 and now it donīt hang when i extract the device*/ #define EHCI_TUNE_RL_HS 4 //4 /* nak throttle; see 4.9 */ @@ -175,7 +173,7 @@ void dump_qh(struct ehci_qh *qh) * bridge shutdown: shutting down the bridge before the devices using it. */ -int unplug_device=0; +int unplug_device[2]={0,0}; #define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT) @@ -535,7 +533,7 @@ cleanup: return NULL; } -u32 usb_timeout=1000*1000; +u32 usb_timeout=500*1000; int mode_int=0; @@ -659,7 +657,7 @@ u32 temp; { if((temp & 1)!=1) // off { - unplug_device=2; + unplug_device[current_port]=2; // *((volatile u32 *)0x0d8000c0) &=~0x20; // LED OFF (you can do it in Interrupt mode) } @@ -752,7 +750,7 @@ u32 temp; { - unplug_device=1; + unplug_device[current_port]=1; // *((volatile u32 *)0x0d8000c0) &=~0x20; // LED OFF (you can do it in Interrupt mode) ret=-ENODEV; @@ -813,7 +811,7 @@ extern int qtd_alt_mem; if(urb->ep==0) //control message { - unplug_device=0; + unplug_device[current_port]=0; urb->setup_dma = ehci_dma_map_to(urb->setup_buffer,sizeof (usbctrlrequest)); } @@ -938,9 +936,9 @@ extern int qtd_alt_mem; }while(retval==-9); mode_int=0; if(enable_urb_debug) s_printf("urb retval: %i\n",retval); - if(retval!=0 || unplug_device!=0) + if(retval!=0 || unplug_device[current_port]!=0) { - if((ehci_readl(&ehci->regs->port_status[current_port]) & 5) !=5) unplug_device=1; + if((ehci_readl(&ehci->regs->port_status[current_port]) & 5) !=5) unplug_device[current_port]=1; //retval=-ETIMEDOUT; } @@ -1503,8 +1501,8 @@ int ehci_adquire_usb_port(int port) ehci_mdelay(60); return 1; } - -int ehci_discover(void) +/* +int ehci_discover(void) //NOT USED { int i,ret,from,to; u32 status; @@ -1551,6 +1549,7 @@ int ehci_discover(void) } return ret; } +*/ int ehci_release_port(int port) { u32 __iomem *status_reg = &ehci->regs->port_status[port]; @@ -1601,15 +1600,12 @@ int ehci_release_externals_usb_ports(void) } return 0; } - +/* int ehci_open_device(int vid,int pid,int fd) { int i; - // for(i=0;inum_port;i++) - // { - - i=use_usb_port1!=0; - + for(i=0;inum_port;i++) + { //ehci_dbg("try device: %d\n",i); if(ehci->devices[i].fd == 0 && le16_to_cpu(ehci->devices[i].desc.idVendor) == vid && @@ -1619,14 +1615,19 @@ int ehci_open_device(int vid,int pid,int fd) ehci->devices[i].fd = fd; return fd; } - //} + } return -6; } +*/ int ehci_close_device(struct ehci_device *dev) { - if (dev) - dev->fd = -1; - return 0; + if (dev) + { + dev->fd = -1; + dev->id=0; + } + + return 0; } void ehci_close_devices() @@ -1641,45 +1642,27 @@ void ehci_close_devices() } - void * ehci_fd_to_dev(int fd) +void * ehci_fd_to_dev(int fd) { - int i; - // for(i=0;inum_port;i++) - current_port=use_usb_port1!=0; - - i=use_usb_port1!=0; - - - { - - struct ehci_device *dev = &ehci->devices[i]; - - return dev; // return always device[0] - - #if 0 - //ehci_dbg ( "device %d:fd:%d %X %X...\n", dev->id,dev->fd,le16_to_cpu(dev->desc.idVendor),le16_to_cpu(dev->desc.idProduct)); - if(dev->fd == fd){ - return dev; - - } - #endif - } - ehci_dbg("unknown fd! %d\n",fd); - return 0; + int i; + for(i=0;inum_port;i++) + { + struct ehci_device *dev = &ehci->devices[i]; + if(dev->fd == fd) return dev; + } + //ehci_dbg("unknown fd! %d\n",fd); + return 0; } #define g_ehci #error int ehci_get_device_list(u8 maxdev,u8 b0,u8*num,u16*buf) { int i,j = 0; - // for(i=0;inum_port && jnum_port && jdevices[i]; if(dev->id != 0){ //ehci_dbg ( "device %d: %X %X...\n", dev->id,le16_to_cpu(dev->desc.idVendor),le16_to_cpu(dev->desc.idProduct)); - buf[j*4] = 0; + buf[j*4] = i; //port buf[j*4+1] = 0; buf[j*4+2] = le16_to_cpu(dev->desc.idVendor); buf[j*4+3] = le16_to_cpu(dev->desc.idProduct); @@ -1688,7 +1671,7 @@ int ehci_get_device_list(u8 maxdev,u8 b0,u8*num,u16*buf) } //ehci_dbg("found %d devices\n",j); *num = j; - return 0; + return j; } diff --git a/tinyehci/ehci.h b/tinyehci/ehci.h index 27412da0..c9300420 100644 --- a/tinyehci/ehci.h +++ b/tinyehci/ehci.h @@ -258,7 +258,7 @@ void create_qtd_dummy(void); s32 ehci_control_message(struct ehci_device *dev,u8 bmRequestType,u8 bmRequest,u16 wValue,u16 wIndex,u16 wLength,void *buf); s32 ehci_bulk_message(struct ehci_device *dev,u8 bEndpoint,u32 wLength,void *rpData); -int ehci_discover(void); +//int ehci_discover(void); int ehci_get_device_list(u8 maxdev,u8 b0,u8*num,u16*buf); int ehci_reset_port2(int port); @@ -266,12 +266,13 @@ int ehci_reset_port2(int port); extern struct ehci_hcd *ehci; /* @todo put ehci as a static global and remove ehci from APIs.. */ extern int ehci_open_device(int vid,int pid,int fd); extern int ehci_close_device(struct ehci_device *dev); +extern void ehci_close_devices(void); extern void * ehci_fd_to_dev(int fd); extern int ehci_release_ports(void); /* UMS API */ -s32 USBStorage_Init(void); +s32 USBStorage_Init(int mode); u32 USBStorage_Get_Capacity(u32*sector_size); s32 USBStorage_Read_Sectors(u32 sector, u32 numSectors, void *buffer); s32 USBStorage_Read_Stress(u32 sector, u32 numSectors, void *buffer); diff --git a/tinyehci/usbstorage.c b/tinyehci/usbstorage.c index 15b5f64d..654caa70 100644 --- a/tinyehci/usbstorage.c +++ b/tinyehci/usbstorage.c @@ -87,16 +87,17 @@ extern char use_reset_bulk; extern char force_flags; extern char use_alternative_timeout; -int is_dvd=0; +int is_dvd[2] = {0,0}; -int ums_init_done = 0; +int ums_init_done[2] = {0,0}; -static usbstorage_handle __usbfd; -static u8 __lun = 16; -static u8 __mounted = 0; -static u16 __vid = 0; -static u16 __pid = 0; +static usbstorage_handle __usbfd[2]; +static u8 __lun[2] = {16,16}; +static u8 __mounted[2] = {0,0}; +static u16 __vid[2] = {0,0}; +static u16 __pid[2] = {0,0}; extern u32 current_port; +static u8* glob_buff =NULL; void reinit_ehci_headers(void); void ehci_stop(void); @@ -433,14 +434,14 @@ static s32 __cycle(usbstorage_handle *dev, u8 lun, u8 *buffer, u32 len, u8 *cb, // s8 retries = USBSTORAGE_CYCLE_RETRIES + 1; - unplug_device=0; + unplug_device[current_port]=0; do { // if(unplug_device) {return -ENODEV;} - if(retval==-ETIMEDOUT || retval==-ENODEV) {unplug_device=1;break;} + if(retval==-ETIMEDOUT || retval==-ENODEV) {unplug_device[current_port]=1;break;} if(retval < 0 /*&& retval!=USBSTORAGE_ESTATUS*/) @@ -455,7 +456,7 @@ static s32 __cycle(usbstorage_handle *dev, u8 lun, u8 *buffer, u32 len, u8 *cb, retries2++; if(retval<0) { - if(retries2>2) {unplug_device=1;break;} else {ehci_msleep(10);continue;} + if(retries2>2) {unplug_device[current_port]=1;break;} else {ehci_msleep(10);continue;} } else retries2=0; ///// @@ -615,10 +616,10 @@ static s32 __cycle(usbstorage_handle *dev, u8 lun, u8 *buffer, u32 len, u8 *cb, } while(retval < 0 && retries > 0); // force unplug - if(retval < 0) {unplug_device=1;} + if(retval < 0) {unplug_device[current_port]=1;} - if(retval>=0) unplug_device=0; + if(retval>=0) unplug_device[current_port]=0; if(_status != NULL) @@ -730,7 +731,7 @@ static s32 __usbstorage_reset(usbstorage_handle *dev,int hard_reset) // device unplugged if (!(PORT_CONNECT & status)) { - unplug_device=1; + unplug_device[current_port]=1; usb_timeout=old_usb_timeout; return -ENODEV; } @@ -812,7 +813,7 @@ end: usb_timeout=old_usb_timeout; - unplug_device=1; // force the unplug method + unplug_device[current_port]=1; // force the unplug method return retval; } @@ -853,7 +854,8 @@ struct _device_data u16 pad2; -} ATTRIBUTE_PACKED _old_device={0}; +} +ATTRIBUTE_PACKED _old_device[2]; s32 USBStorage_Open(usbstorage_handle *dev, struct ehci_device *fd) @@ -867,7 +869,7 @@ s32 USBStorage_Open(usbstorage_handle *dev, struct ehci_device *fd) usb_endpointdesc *ued; - __lun= 16; // select bad LUN + __lun[current_port]= 16; // select bad LUN //max_lun = USB_Alloc(1); //if(max_lun==NULL) return -ENOMEM; @@ -894,15 +896,15 @@ s32 USBStorage_Open(usbstorage_handle *dev, struct ehci_device *fd) goto free_and_return; // test device changed without unmount (prevent device write corruption) - if(ums_init_done) + if(ums_init_done[current_port]) { - if(_old_device.bDeviceClass!=udd.bDeviceClass || - _old_device.bDeviceSubClass!=udd.bDeviceSubClass || - _old_device.idVendor!=udd.idVendor || - _old_device.idProduct!=udd.idProduct || - _old_device.iManufacturer!=udd.iManufacturer || - _old_device.iProduct!=udd.iProduct || - _old_device.iSerialNumber!=udd.iSerialNumber) + if(_old_device[current_port].bDeviceClass!=udd.bDeviceClass || + _old_device[current_port].bDeviceSubClass!=udd.bDeviceSubClass || + _old_device[current_port].idVendor!=udd.idVendor || + _old_device[current_port].idProduct!=udd.idProduct || + _old_device[current_port].iManufacturer!=udd.iManufacturer || + _old_device[current_port].iProduct!=udd.iProduct || + _old_device[current_port].iSerialNumber!=udd.iSerialNumber) { //USB_Free(max_lun); USB_FreeDescriptors(&udd); @@ -914,13 +916,13 @@ s32 USBStorage_Open(usbstorage_handle *dev, struct ehci_device *fd) } } - _old_device.bDeviceClass=udd.bDeviceClass; - _old_device.bDeviceSubClass=udd.bDeviceSubClass; - _old_device.idVendor=udd.idVendor; - _old_device.idProduct=udd.idProduct; - _old_device.iManufacturer=udd.iManufacturer; - _old_device.iProduct=udd.iProduct; - _old_device.iSerialNumber=udd.iSerialNumber; + _old_device[current_port].bDeviceClass=udd.bDeviceClass; + _old_device[current_port].bDeviceSubClass=udd.bDeviceSubClass; + _old_device[current_port].idVendor=udd.idVendor; + _old_device[current_port].idProduct=udd.idProduct; + _old_device[current_port].iManufacturer=udd.iManufacturer; + _old_device[current_port].iProduct=udd.iProduct; + _old_device[current_port].iSerialNumber=udd.iSerialNumber; try_status=-128; @@ -981,12 +983,12 @@ s32 USBStorage_Open(usbstorage_handle *dev, struct ehci_device *fd) s_printf("ep_in %x ep_out %x\n", (u32) dev->ep_in, (u32) dev->ep_out); #endif - _old_device.ep_in=dev->ep_in; - _old_device.ep_out=dev->ep_out; + _old_device[current_port].ep_in=dev->ep_in; + _old_device[current_port].ep_out=dev->ep_out; dev->configuration = ucd->bConfigurationValue; dev->interface = uid->bInterfaceNumber; - _old_device.interface=dev->interface; + _old_device[current_port].interface=dev->interface; dev->altInterface = uid->bAlternateSetting; goto found; @@ -1133,7 +1135,11 @@ usb_timeout=1000*1000; //USB_ClearHalt(dev->usb_fd, dev->ep_out); if(dev->buffer == NULL) - dev->buffer = (void *) ((((u32) USB_Alloc(MAX_TRANSFER_SIZE+32))+31) & ~31); + { + if(glob_buff==NULL) + glob_buff = (void *) ((((u32) USB_Alloc(MAX_TRANSFER_SIZE+32))+31) & ~31); + dev->buffer = glob_buff; + } if(dev->buffer == NULL) {retval = -ENOMEM;try_status=-1205;} else retval = USBSTORAGE_OK; @@ -1271,10 +1277,10 @@ s32 USBStorage_Inquiry(usbstorage_handle *dev, u8 lun) // info from http://en.wikipedia.org/wiki/SCSI_Peripheral_Device_Type case 5: // CDROM case 7: // optical memory device (e.g., some optical disks) - is_dvd=1; + is_dvd[current_port]=1; break; default: - is_dvd=0; + is_dvd[current_port]=0; break; } } @@ -1300,7 +1306,7 @@ s32 USBStorage_ReadCapacity(usbstorage_handle *dev, u8 lun, u32 *sector_size, u3 memcpy(&val, response + 4, 4); if(sector_size != NULL) *sector_size = be32_to_cpu(val); - if(be32_to_cpu(val)==2048)is_dvd=1; + //if(be32_to_cpu(val)==2048)is_dvd[current_port]=1; retval = USBSTORAGE_OK; } // USB_Free(response); @@ -1425,65 +1431,65 @@ s32 USBStorage_Try_Device(struct ehci_device *fd) int maxLun,j,retval; int test_max_lun=1; - __vid=0; - __pid=0; - __mounted = 0; - __lun = 0; + __vid[current_port]=0; + __pid[current_port]=0; + __mounted[current_port] = 0; + __lun[current_port] = 0; try_status=-120; // swi_mload_led_on(); - if(USBStorage_Open(&__usbfd, fd) < 0) + if(USBStorage_Open(&__usbfd[current_port], fd) < 0) return -EINVAL; maxLun= 1; - __usbfd.max_lun = 1; + __usbfd[current_port].max_lun = 1; j=0; // fast re-mount - if(_old_device.mounted) + if(_old_device[current_port].mounted) { - if(_old_device.use_maxlun || (force_flags & 1)) + if(_old_device[current_port].use_maxlun || (force_flags & 1)) { - __usbfd.max_lun = 0; + __usbfd[current_port].max_lun = 0; usb_timeout=10000*1000; - retval = __USB_CtrlMsgTimeout(&__usbfd, (USB_CTRLTYPE_DIR_DEVICE2HOST | USB_CTRLTYPE_TYPE_CLASS | USB_CTRLTYPE_REC_INTERFACE), - USBSTORAGE_GET_MAX_LUN, 0, __usbfd.interface, 1, &__usbfd.max_lun); + retval = __USB_CtrlMsgTimeout(&__usbfd[current_port], (USB_CTRLTYPE_DIR_DEVICE2HOST | USB_CTRLTYPE_TYPE_CLASS | USB_CTRLTYPE_REC_INTERFACE), + USBSTORAGE_GET_MAX_LUN, 0, __usbfd[current_port].interface, 1, &__usbfd[current_port].max_lun); usb_timeout=1000*1000; if(retval < 0) { - __usbfd.max_lun = 1; + __usbfd[current_port].max_lun = 1; goto bad_mount; } - else {__usbfd.max_lun++;} + else {__usbfd[current_port].max_lun++;} } - j=_old_device.lun; + j=_old_device[current_port].lun; #ifdef MEM_PRINT s_printf("Fast USBStorage_MountLUN %i#\n", j); #endif - retval = USBStorage_MountLUN(&__usbfd, j); + retval = USBStorage_MountLUN(&__usbfd[current_port], j); #ifdef MEM_PRINT s_printf("USBStorage_MountLUN: ret %i\n", retval); #endif if(retval == USBSTORAGE_ETIMEDOUT || retval==-ENODEV /*&& test_max_lun==0*/) { - USBStorage_Reset(&__usbfd); + USBStorage_Reset(&__usbfd[current_port]); try_status=-121; - __mounted = 0; - USBStorage_Close(&__usbfd); + __mounted[current_port] = 0; + USBStorage_Close(&__usbfd[current_port]); return -EINVAL; } if(retval < 0) goto bad_mount; - __mounted = 1; - __lun = j; + __mounted[current_port] = 1; + __lun[current_port] = j; usb_timeout=1000*1000; try_status=0; // swi_mload_led_off(); @@ -1491,7 +1497,7 @@ s32 USBStorage_Try_Device(struct ehci_device *fd) return 0; } - _old_device.use_maxlun=0; + _old_device[current_port].use_maxlun=0; //for(j = 0; j < maxLun; j++) while(1) { @@ -1500,7 +1506,7 @@ s32 USBStorage_Try_Device(struct ehci_device *fd) #ifdef MEM_PRINT s_printf("USBStorage_MountLUN %i#\n", j); #endif - retval = USBStorage_MountLUN(&__usbfd, j); + retval = USBStorage_MountLUN(&__usbfd[current_port], j); #ifdef MEM_PRINT s_printf("USBStorage_MountLUN: ret %i\n", retval); #endif @@ -1509,10 +1515,10 @@ s32 USBStorage_Try_Device(struct ehci_device *fd) if((retval == USBSTORAGE_ETIMEDOUT || retval==-ENODEV) && j!=0) { usb_timeout=1000*1000; - USBStorage_Reset(&__usbfd); + USBStorage_Reset(&__usbfd[current_port]); try_status=-121; - __mounted = 0; - USBStorage_Close(&__usbfd); + __mounted[current_port]= 0; + USBStorage_Close(&__usbfd[current_port]); return -EINVAL; // break; } @@ -1524,18 +1530,18 @@ s32 USBStorage_Try_Device(struct ehci_device *fd) { if(test_max_lun) { - unplug_device=0; - __usbfd.max_lun = 0; + unplug_device[current_port]=0; + __usbfd[current_port].max_lun = 0; usb_timeout=10000*1000; - retval = __USB_CtrlMsgTimeout(&__usbfd, + retval = __USB_CtrlMsgTimeout(&__usbfd[current_port], (USB_CTRLTYPE_DIR_DEVICE2HOST | USB_CTRLTYPE_TYPE_CLASS | USB_CTRLTYPE_REC_INTERFACE), - USBSTORAGE_GET_MAX_LUN, 0, __usbfd.interface, 1, &__usbfd.max_lun); + USBSTORAGE_GET_MAX_LUN, 0, __usbfd[current_port].interface, 1, &__usbfd[current_port].max_lun); usb_timeout=1000*1000; if(retval < 0 ) - {__usbfd.max_lun = 1;unplug_device=0;} - else {__usbfd.max_lun++;_old_device.use_maxlun=1;} - maxLun = __usbfd.max_lun; + {__usbfd[current_port].max_lun = 1;unplug_device[current_port]=0;} + else {__usbfd[current_port].max_lun++;_old_device[current_port].use_maxlun=1;} + maxLun = __usbfd[current_port].max_lun; #ifdef MEM_PRINT s_printf("USBSTORAGE_GET_MAX_LUN ret %i maxlun %i\n", retval,maxLun); @@ -1549,13 +1555,13 @@ s32 USBStorage_Try_Device(struct ehci_device *fd) continue; } - _old_device.mounted=1; - _old_device.lun=j; + _old_device[current_port].mounted=1; + _old_device[current_port].lun=j; - __vid=fd->desc.idVendor; - __pid=fd->desc.idProduct; - __mounted = 1; - __lun = j; + __vid[current_port]=fd->desc.idVendor; + __pid[current_port]=fd->desc.idProduct; + __mounted[current_port] = 1; + __lun[current_port] = j; usb_timeout=1000*1000; try_status=0; // swi_mload_led_off(); @@ -1564,9 +1570,9 @@ s32 USBStorage_Try_Device(struct ehci_device *fd) bad_mount: try_status=-122; - USBStorage_Reset(&__usbfd); - __mounted = 0; - USBStorage_Close(&__usbfd); + USBStorage_Reset(&__usbfd[current_port]); + __mounted[current_port] = 0; + USBStorage_Close(&__usbfd[current_port]); #ifdef MEM_PRINT s_printf("USBStorage_MountLUN fail!!!\n"); @@ -1577,7 +1583,7 @@ bad_mount: void USBStorage_Umount(void) { -if(!ums_init_done) return; +if(!ums_init_done[current_port]) return; /* if(__mounted && !unplug_device) { @@ -1585,66 +1591,70 @@ if(!ums_init_done) return; ehci_msleep(1000); } */ - USBStorage_Close(&__usbfd);__lun= 16; - __mounted=0; - ums_init_done=0; - unplug_device=0; - memset(&_old_device,0,sizeof(_old_device)); + if(__mounted[current_port]) + { + USBStorage_Close(&__usbfd[current_port]);__lun[current_port]= 16; + __mounted[current_port]=0; + unplug_device[current_port]=0; + memset(&_old_device[current_port],0,sizeof(_old_device[current_port])); + } + + ums_init_done[current_port]=0; } -s32 USBStorage_Init(void) +s32 USBStorage_Init(int mode) { int i; u32 status; - int ret; + int ret[2]; int from=0,to=0; //debug_printf("usbstorage init %d\n", ums_init_done); - - if(ums_init_done) - return 0; - + if(mode==1)from=to=1; + else if(mode==2) + { + from=0; + to=1; + } + /* + for(i = from;i<=to; i++) + { + if(!ums_init_done[i]) break; + } + if(i==2)//already mounted + return 10; + */ ehci_writel (0, &ehci->regs->intr_enable); ehci_int_passive_callback(NULL); // interrupt port changes detection + //use_alternative_timeout=1; try_status=-100; - unplug_device=1; - __mounted=0; - use_alternative_timeout=1; + #ifdef MEM_PRINT s_printf("\n***************************************************\nRodries ehcmodule 1.0\nUSBStorage_Init()\n***************************************************\n\n"); #endif - -/*if(use_usb_port1!=0) - { - struct ehci_device *dev = &ehci->devices[0]; - - - dev->port=0; - dev->id=0; - ret=ehci_reset_port(0); - } -*/ - if(use_usb_port1==1)from=to=1; - else if(use_usb_port1==2) - { - from=0; - to=1; - } - //current_port=use_usb_port1!=0; - //for(i = use_usb_port1!=0;i<(1+(use_usb_port1!=0))/*ehci->num_port*/; i++){ + ret[0]=-1; + ret[1]=-1; + for(i = from;i<=to; i++){ struct ehci_device *dev = &ehci->devices[i]; + ums_init_done[i]=0; + unplug_device[i]=1; + __mounted[i]=0; + _old_device[i].mounted=0; + + + dev->port=i; current_port=i; @@ -1661,19 +1671,19 @@ s_printf("\n***************************************************\nRodries ehcmodu if(status & 1) { - ret=ehci_reset_port(i); - if(ret==-1119 || ret==-1120) + ret[i]=ehci_reset_port(i); + if(ret[i]==-1119 || ret[i]==-1120) { - try_status=ret; + try_status=ret[i]; try_status=-100; continue; } - ret=ehci_reset_port2(i); + ret[i]=ehci_reset_port2(i); ehci_msleep(20); status=ehci_readl(&ehci->regs->port_status[i]); - if(ret<0 || (status & 0x3905)!=0x1005) - ret=ehci_reset_port(i); + if(ret[i]<0 || (status & 0x3905)!=0x1005) + ret[i]=ehci_reset_port(i); } @@ -1681,7 +1691,7 @@ s_printf("\n***************************************************\nRodries ehcmodu } if(dev->id != 0) { - unplug_device=1; + unplug_device[current_port]=1; /* ret=ehci_reset_port(i); if(ret==-1119 || ret==-1120) @@ -1699,48 +1709,43 @@ s_printf("\n***************************************************\nRodries ehcmodu status=ehci_readl(&ehci->regs->port_status[i]); } */ - unplug_device=1; + unplug_device[current_port]=1; //if(ret>=0 && (status & 0x3105)==0x1005 ) // { - if(USBStorage_Try_Device(dev)==0) - { - ums_init_done = 1;unplug_device=0; - ehci_int_passive_callback(passive_callback_hand); // interrupt port changes detection - ehci_writel (STS_PCD, &ehci->regs->intr_enable); - + { + extern u8 mem_sector[4096]; + ums_init_done[current_port] = 1;unplug_device[current_port]=0; + + if(is_dvd[current_port]) s_printf("Device is a dvd\n"); + else s_printf("Device is a usbhd\n"); s_printf("USBStorage_Init() Ok\n"); ehci_msleep(100); - u8 *buf; - buf = (u8 *) USB_Alloc(2048); usb_timeout=10000*1000; extern bool enable_urb_debug; enable_urb_debug=true; - ehci_writel (0, &ehci->regs->intr_enable); - ehci_int_passive_callback(NULL); s_printf("Reading sector 0\n"); - ret=USBStorage_Read(&__usbfd, __lun, 0, 1, buf); - ehci_int_passive_callback(passive_callback_hand); - ehci_writel (STS_PCD, &ehci->regs->intr_enable); + ret[i]=USBStorage_Read(&__usbfd[current_port], __lun[current_port], 0, 1, mem_sector); enable_urb_debug=false; - usb_timeout=1000*1000; - USB_Free(buf); - if(ret<0) + usb_timeout=500*1000; + if(ret[i]<0) s_printf("Error Reading sector 0\n"); else s_printf("OK Reading sector 0\n"); - if(ret<0) + if(ret[i]<0) { ehci_release_port(i); - return -1118; + ret[i] = -1118; } - if(is_dvd) return i+2; // is DVD medium - return i; + else ret[i]=1; + //if(is_dvd) return i+2; // is DVD medium + //return i; + // 0 -> port0 1 -> port1 2 -> dvdport0 3 -> dvdport1 - } - else ehci_release_port(i); } + else ehci_release_port(i); + } // } /* else @@ -1784,19 +1789,27 @@ s_printf("\n***************************************************\nRodries ehcmodu ehci_int_passive_callback(passive_callback_hand); // interrupt port changes detection ehci_writel (STS_PCD, &ehci->regs->intr_enable); - + if(ret[0]==1) + { + try_status=0; + if(ret[1]==1) try_status=2; + } + else + { + if(ret[1]==1) try_status=1; + } return try_status; } u32 USBStorage_Get_Capacity(u32*sector_size) { if(sector_size) *sector_size = 0; - if(__mounted == 1 && __lun!=16) + if(__mounted[current_port]== 1 && __lun[current_port]!=16) { if(sector_size){ - *sector_size = __usbfd.sector_size[__lun]; + *sector_size = __usbfd[current_port].sector_size[__lun[current_port]]; } - return __usbfd.n_sector[__lun]; + return __usbfd[current_port].n_sector[__lun[current_port]]; } return 0; } @@ -1808,27 +1821,27 @@ int retval; //u8 conf=0; usb_devdesc udd; -if(!ums_init_done) return -1009; +if(!ums_init_done[current_port]) return -1009; // swi_mload_led_on(); retval=0; - __lun=16; + __lun[current_port]=16; if(use_alternative_timeout) usb_timeout=1000*1000; else usb_timeout=200*1000; udd.configurations=NULL; - retval = USB_GetDescriptors(__usbfd.usb_fd, &udd); + retval = USB_GetDescriptors(__usbfd[current_port].usb_fd, &udd); - if(_old_device.bDeviceClass!=udd.bDeviceClass || - _old_device.bDeviceSubClass!=udd.bDeviceSubClass || - _old_device.idVendor!=udd.idVendor || - _old_device.idProduct!=udd.idProduct || - _old_device.iManufacturer!=udd.iManufacturer || - _old_device.iProduct!=udd.iProduct || - _old_device.iSerialNumber!=udd.iSerialNumber) + if(_old_device[current_port].bDeviceClass!=udd.bDeviceClass || + _old_device[current_port].bDeviceSubClass!=udd.bDeviceSubClass || + _old_device[current_port].idVendor!=udd.idVendor || + _old_device[current_port].idProduct!=udd.idProduct || + _old_device[current_port].iManufacturer!=udd.iManufacturer || + _old_device[current_port].iProduct!=udd.iProduct || + _old_device[current_port].iSerialNumber!=udd.iSerialNumber) { USB_FreeDescriptors(&udd); @@ -1844,11 +1857,11 @@ if(!ums_init_done) return -1009; //if(USB_GetConfiguration(__usbfd.usb_fd, &conf) <0) return -1000; - usb_timeout=10000*1000; + usb_timeout=800*1000; - if(USB_SetConfiguration(__usbfd.usb_fd, __usbfd.configuration) < 0) return -1001; + if(USB_SetConfiguration(__usbfd[current_port].usb_fd, __usbfd[current_port].configuration) < 0) return -1001; - if(__usbfd.altInterface != 0 && USB_SetAlternativeInterface(__usbfd.usb_fd, __usbfd.interface, __usbfd.altInterface) < 0) return -1002; + if(__usbfd[current_port].altInterface != 0 && USB_SetAlternativeInterface(__usbfd[current_port].usb_fd, __usbfd[current_port].interface, __usbfd[current_port].altInterface) < 0) return -1002; /* if((conf != __usbfd.configuration || (force_flags & 2)) && USB_SetConfiguration(__usbfd.usb_fd, __usbfd.configuration) < 0) return -1001; @@ -1860,38 +1873,38 @@ if(!ums_init_done) return -1009; //if( __usbstorage_reset(&__usbfd,0)<0) return -1003; - usb_timeout=1000*1000; + //usb_timeout=1000*1000; //if(_old_device.use_maxlun || (force_flags & 1)) { - __usbfd.max_lun = 0; + __usbfd[current_port].max_lun = 0; - usb_timeout=10000*1000; - retval = __USB_CtrlMsgTimeout(&__usbfd, (USB_CTRLTYPE_DIR_DEVICE2HOST | USB_CTRLTYPE_TYPE_CLASS | USB_CTRLTYPE_REC_INTERFACE), - USBSTORAGE_GET_MAX_LUN, 0, __usbfd.interface, 1, &__usbfd.max_lun); - usb_timeout=1000*1000; + //usb_timeout=10000*1000; + retval = __USB_CtrlMsgTimeout(&__usbfd[current_port], (USB_CTRLTYPE_DIR_DEVICE2HOST | USB_CTRLTYPE_TYPE_CLASS | USB_CTRLTYPE_REC_INTERFACE), + USBSTORAGE_GET_MAX_LUN, 0, __usbfd[current_port].interface, 1, &__usbfd[current_port].max_lun); + //usb_timeout=1000*1000; if(retval < 0) { - __usbfd.max_lun = 1; - __usbstorage_reset(&__usbfd,0); + __usbfd[current_port].max_lun = 1; + __usbstorage_reset(&__usbfd[current_port],0); return -1004; } - else {__usbfd.max_lun++;} + else {__usbfd[current_port].max_lun++;} } //retval = USBStorage_MountLUN(&__usbfd, _old_device.lun); - usb_timeout=20000*1000; - retval = __usbstorage_clearerrors(&__usbfd, _old_device.lun); + //usb_timeout=20000*1000; + retval = __usbstorage_clearerrors(&__usbfd[current_port], _old_device[current_port].lun); #ifdef MEM_PRINT // s_printf(" Clear error ret %i\n",retval); #endif - usb_timeout=1000*1000; + //usb_timeout=1000*1000; if(retval<0) return -1005; - retval = USBStorage_Inquiry(&__usbfd, _old_device.lun); + retval = USBStorage_Inquiry(&__usbfd[current_port], _old_device[current_port].lun); #ifdef MEM_PRINT // s_printf(" Inquiry ret %i\n",retval); #endif @@ -1899,8 +1912,8 @@ if(!ums_init_done) return -1009; if(retval<0) return -1006; - __lun=_old_device.lun; - __mounted=1; + __lun[current_port]=_old_device[current_port].lun; + __mounted[current_port]=1; return retval; @@ -1912,8 +1925,7 @@ int unplug_procedure(void) int retval=1; u32 status; -current_port=use_usb_port1!=0; - if(unplug_device!=0 ) + if(unplug_device[current_port]!=0 ) { // unplug detection method @@ -1957,7 +1969,7 @@ current_port=use_usb_port1!=0; #endif - unplug_device=1; + unplug_device[current_port]=1; if(ret>=0 && (status & 0x3105)==0x1005 ) { @@ -1966,12 +1978,12 @@ current_port=use_usb_port1!=0; /*if(__usbfd.buffer != NULL) USB_Free(__usbfd.buffer); __usbfd.buffer= NULL;*/ - __mounted=0;unplug_device=0; - USBStorage_Close(&__usbfd); + __mounted[current_port]=0;unplug_device[current_port]=0; + USBStorage_Close(&__usbfd[current_port]); retval=fast_remount(); - usb_timeout=1000*1000; + //usb_timeout=1000*1000; if(retval>=0) { #ifdef MEM_PRINT @@ -1981,18 +1993,18 @@ current_port=use_usb_port1!=0; #endif // swi_mload_led_off(); - retval=0;unplug_device=0;__mounted=1; + retval=0;unplug_device[current_port]=0;__mounted[current_port]=1; ehci_int_passive_callback(passive_callback_hand); // interrupt port changes detection ehci_writel (STS_PCD, &ehci->regs->intr_enable); } else { - unplug_device=1; + unplug_device[current_port]=1; #ifdef MEM_PRINT s_printf("fast_remount KO ret %i\n", ret); #endif - __mounted=0; + __mounted[current_port]=0; retval=1; //swi_mload_led_off(); ehci_msleep(100); @@ -2014,28 +2026,29 @@ int USBStorage_DVD_Test(void) int retval; - if(!ums_init_done) return 0; + if(!ums_init_done[current_port]) return 0; unplug_procedure(); - if(unplug_device!=0 || __mounted==0) return 0; + if(unplug_device[current_port]!=0 || __mounted[current_port]==0) return 0; // usb_timeout=1000*1000; // retval = __usbstorage_clearerrors(&__usbfd, _old_device.lun); // if(retval<0) return 0; - usb_timeout=1000*1000; - retval = USBStorage_Inquiry(&__usbfd, _old_device.lun); + //usb_timeout=1000*1000; + retval = USBStorage_Inquiry(&__usbfd[current_port], _old_device[current_port].lun); if(retval<0) return 0; - usb_timeout=1000*1000; - retval = USBStorage_ReadCapacity(&__usbfd, _old_device.lun, &__usbfd.sector_size[_old_device.lun], &__usbfd.n_sector[_old_device.lun]); + //usb_timeout=1000*1000; + retval = USBStorage_ReadCapacity(&__usbfd[current_port], _old_device[current_port].lun, + &__usbfd[current_port].sector_size[_old_device[current_port].lun], &__usbfd[current_port].n_sector[_old_device[current_port].lun]); if(retval<0) return 0; // sector size check for USB DVD mode (must be 2048 bytes) - if(retval>=0 && is_dvd) + if(retval>=0 && is_dvd[current_port]) { - if(__usbfd.sector_size[_old_device.lun]!=2048) return 0; + if(__usbfd[current_port].sector_size[_old_device[current_port].lun]!=2048) return 0; } - if(!is_dvd) return 0; + if(!is_dvd[current_port]) return 0; return 1; } @@ -2045,7 +2058,7 @@ int is_watchdog_read_sector=0; extern int test_mode; -extern int last_sector; +extern u32 last_sector; s32 USBStorage_Read_Sectors(u32 sector, u32 numSectors, void *buffer) { @@ -2053,11 +2066,12 @@ s32 USBStorage_Read_Sectors(u32 sector, u32 numSectors, void *buffer) int retry; - if(!is_watchdog_read_sector && is_dvd) last_sector=(int) (sector & 0x7fffffff);//return false; +// if(!is_watchdog_read_sector && is_dvd[current_port]) last_sector=(int) (sector & 0x7fffffff);//return false; + if(!is_watchdog_read_sector && is_dvd[current_port]) last_sector=sector;//return false; - if(test_mode && unplug_device>=2) + if(test_mode && unplug_device[current_port]>=2) { - unplug_device=1; + unplug_device[current_port]=1; return false; } @@ -2072,20 +2086,20 @@ s32 USBStorage_Read_Sectors(u32 sector, u32 numSectors, void *buffer) retval=0; } - if(test_mode && unplug_device==3) break; + if(test_mode && unplug_device[current_port]==3) break; - if(retval<0 || __mounted != 1) + if(retval<0 || __mounted[current_port] != 1) { - unplug_device=1; + unplug_device[current_port]=1; retval=-1; } - if(unplug_device!=0 ) { continue;} + if(unplug_device[current_port]!=0 ) { continue;} - if(is_dvd) + if(is_dvd[current_port]) usb_timeout=10000*1000; else - usb_timeout=3000*1000; + usb_timeout=800*1000; if(retval >= 0) { @@ -2093,20 +2107,20 @@ s32 USBStorage_Read_Sectors(u32 sector, u32 numSectors, void *buffer) ehci_int_passive_callback(NULL); ehci_writel (0, &ehci->regs->intr_enable); - retval = USBStorage_Read(&__usbfd, __lun, sector, numSectors, buffer); + retval = USBStorage_Read(&__usbfd[current_port], __lun[current_port], sector, numSectors, buffer); ehci_int_passive_callback(passive_callback_hand); ehci_writel (STS_PCD, &ehci->regs->intr_enable); } - usb_timeout=1000*1000; + usb_timeout=500*1000; - if(retval<0) unplug_device=1; + if(retval<0) unplug_device[current_port]=1; - if(test_mode && unplug_device!=0 ) {retval=-1;/*__mounted=0;*/break;} + if(test_mode && unplug_device[current_port]!=0 ) {retval=-1;/*__mounted[current_port]=0;*/break;} - if(unplug_device!=0 || __mounted != 1) continue; + if(unplug_device[current_port]!=0 || __mounted[current_port] != 1) continue; if(retval>=0) break; @@ -2122,7 +2136,7 @@ s32 USBStorage_Write_Sectors(u32 sector, u32 numSectors, const void *buffer) { s32 retval=0; - if(is_dvd) return false; // quieto!!! + if(is_dvd[current_port]) return false; // quieto!!! while(1) { @@ -2132,31 +2146,31 @@ s32 USBStorage_Write_Sectors(u32 sector, u32 numSectors, const void *buffer) retval=0; } - if(retval<0 || __mounted != 1) + if(retval<0 || __mounted[current_port] != 1) { - unplug_device=1; + unplug_device[current_port]=1; retval=-1; } - if(unplug_device!=0 ) continue; + if(unplug_device[current_port]!=0 ) continue; - usb_timeout=3000*1000; + usb_timeout=1000*1000; if(retval >=0) { ehci_writel (0, &ehci->regs->intr_enable); ehci_int_passive_callback(NULL); - retval = USBStorage_Write(&__usbfd, __lun, sector, numSectors, buffer); + retval = USBStorage_Write(&__usbfd[current_port], __lun[current_port], sector, numSectors, buffer); ehci_int_passive_callback(passive_callback_hand); ehci_writel (STS_PCD, &ehci->regs->intr_enable); } - usb_timeout=1000*1000; - if(retval<0) unplug_device=1; + usb_timeout=500*1000; + if(retval<0) unplug_device[current_port]=1; - if(unplug_device!=0 ) continue; + if(unplug_device[current_port]!=0 ) continue; if(retval>=0) break; } diff --git a/tinyehci/usbstorage.h b/tinyehci/usbstorage.h index 4ed87ddf..a626d173 100644 --- a/tinyehci/usbstorage.h +++ b/tinyehci/usbstorage.h @@ -46,7 +46,7 @@ typedef struct u8 *buffer; } usbstorage_handle; -s32 USBStorage_Init(void); +s32 USBStorage_Init(int mode); void USBStorage_Umount(void); s32 USBStorage_Open(usbstorage_handle *dev, struct ehci_device *fd);