/* USBlinuz * Copyright (C) 2002-2004 USBlinuz Team * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <stdlib.h> #include <string.h> #include <errno.h> #include "USB.h" const unsigned char version = PS2E_USB_VERSION; const unsigned char revision = 0; const unsigned char build = 4; // increase that with each version static char *libraryName = "USBlinuz Driver"; u32 CALLBACK PS2EgetLibType() { return PS2E_LT_USB; } char* CALLBACK PS2EgetLibName() { return libraryName; } u32 CALLBACK PS2EgetLibVersion2(u32 type) { return (version<<16) | (revision<<8) | build; } void __Log(char *fmt, ...) { va_list list; if (!conf.Log) return; va_start(list, fmt); vfprintf(usbLog, fmt, list); va_end(list); } s32 CALLBACK USBinit() { LoadConfig(); #ifdef USB_LOG usbLog = fopen("logs/usbLog.txt", "w"); setvbuf(usbLog, NULL, _IONBF, 0); USB_LOG("usblinuz plugin version %d,%d\n",revision,build); USB_LOG("USBinit\n"); #endif usbR = (s8*)malloc(0x10000); if (usbR == NULL) { SysMessage("Error allocating memory"); return -1; } memset(usbR, 0, 0x10000); ohci = (struct ohci_regs*)usbR; ohci->revision = 0x10; ohci->roothub.a = 0x2; return 0; } void CALLBACK USBshutdown() { free(usbR); #ifdef USB_LOG fclose(usbLog); #endif } s32 CALLBACK USBopen(void *pDsp) { #ifdef USB_LOG USB_LOG("USBopen\n"); #endif return 0; } void CALLBACK USBclose() { } u8 CALLBACK USBread8(u32 addr) { u8 hard; switch (addr) { default: hard = usbRu8(addr); #ifdef USB_LOG USB_LOG("*Unknown 8bit read at address %lx value %x\n", addr, hard); #endif return hard; } #ifdef USB_LOG USB_LOG("*Known 8bit read at address %lx value %x\n", addr, hard); #endif return hard; } u16 CALLBACK USBread16(u32 addr) { u16 hard; switch (addr) { default: hard = usbRu16(addr); #ifdef USB_LOG USB_LOG("*Unknown 16bit read at address %lx value %x\n", addr, hard); #endif return hard; } #ifdef USB_LOG USB_LOG("*Known 16bit read at address %lx value %x\n", addr, hard); #endif return hard; } u32 CALLBACK USBread32(u32 addr) { u32 hard; int i; if (addr >= 0x1f801654 && addr < 0x1f801690) { i = (addr - 0x1f801654) / 4; hard = ohci->roothub.portstatus[i]; #ifdef USB_LOG USB_LOG("ohci->roothub.portstatus[%d] read32 %x\n", i, hard); #endif return hard; } switch (addr) { #ifdef USB_LOG case 0x1f801600: hard = ohci->revision; USB_LOG("ohci->revision read32 %x\n", hard); return hard; #endif #ifdef USB_LOG case 0x1f801604: hard = ohci->control; USB_LOG("ohci->control read32 %x\n", hard); return hard; #endif case 0x1f801608: hard = 0; #ifdef USB_LOG USB_LOG("ohci->cmdstatus read32 %x\n", hard); #endif return hard; #ifdef USB_LOG case 0x1f80160c: hard = ohci->intrstatus; USB_LOG("ohci->intrstatus read32 %x\n", hard); return hard; case 0x1f801610: hard = ohci->intrenable; USB_LOG("ohci->intrenable read32 %x\n", hard); return hard; case 0x1f801648: hard = ohci->roothub.a; USB_LOG("ohci->roothub.a read32 %x\n", hard); return hard; case 0x1f80164C: hard = ohci->roothub.b; USB_LOG("ohci->roothub.b read32 %x\n", hard); return hard; case 0x1f801650: hard = ohci->roothub.status; USB_LOG("ohci->roothub.status read32 %x\n", hard); return hard; #endif default: hard = usbRu32(addr); #ifdef USB_LOG USB_LOG("*Unkwnown 32bit read at address %lx: %lx\n", addr, hard); #endif return hard; } #ifdef USB_LOG USB_LOG("*Known 32bit read at address %lx: %lx\n", addr, hard); #endif return hard; } void CALLBACK USBwrite8(u32 addr, u8 value) { switch (addr) { default: usbRu8(addr) = value; #ifdef USB_LOG USB_LOG("*Unknown 8bit write at address %lx value %x\n", addr, value); #endif return; } usbRu8(addr) = value; #ifdef USB_LOG USB_LOG("*Known 8bit write at address %lx value %x\n", addr, value); #endif } void CALLBACK USBwrite16(u32 addr, u16 value) { switch (addr) { default: usbRu16(addr) = value; #ifdef USB_LOG USB_LOG("*Unknown 16bit write at address %lx value %x\n", addr, value); #endif return; } usbRu16(addr) = value; #ifdef USB_LOG USB_LOG("*Known 16bit write at address %lx value %x\n", addr, value); #endif } void CALLBACK USBwrite32(u32 addr, u32 value) { int i; if (addr >= 0x1f801654 && addr < 0x1f801690) { i = (addr - 0x1f801654) / 4; // ohci->roothub.portstatus[i] = value; ohci->intrstatus|= OHCI_INTR_SF; #ifdef USB_LOG USB_LOG("ohci->roothub.portstatus[%d] write32 %x\n", i, value); #endif return; } switch (addr) { case 0x1f801600: // ohci->revision (read only) return; case 0x1f801604: #ifdef USB_LOG USB_LOG("ohci->control write32 %x\n", value); #endif ohci->control = value; if ((ohci->control & OHCI_CTRL_HCFS) == OHCI_USB_OPER) { USBirq(PSXCLK / 1000000); ohci->roothub.portstatus[0] = 0x1; ohci->intrstatus|= OHCI_INTR_RHSC; } return; case 0x1f80160c: #ifdef USB_LOG USB_LOG("ohci->intrstatus write32 %x\n", value); #endif ohci->intrstatus&= ~value; return; case 0x1f801610: #ifdef USB_LOG USB_LOG("ohci->intrenable write32 %x\n", value); #endif for (i=0; i<32; i++) { if (value & (1<<i)) { ohci->intrenable|= 1<<i; } } return; case 0x1f801614: #ifdef USB_LOG USB_LOG("ohci->intrdisable write32 %x\n", value); #endif for (i=0; i<32; i++) { if (value & (1<<i)) { ohci->intrenable&= ~(1<<i); } } return; case 0x1f801618: ohci->hcca = value; hcca = (struct ohci_hcca*)&ram[ohci->hcca]; ohci->intrstatus|= OHCI_INTR_SF; #ifdef USB_LOG USB_LOG("ohci->hcca write32 %x\n", value); #endif return; #ifdef USB_LOG case 0x1f801608: ohci->cmdstatus = value; USB_LOG("ohci->cmdstatus write32 %x\n", value); return; case 0x1f801630: ohci->donehead = value; USB_LOG("ohci->donehead write32 %x\n", value); return; case 0x1f801634: ohci->fminterval = value; USB_LOG("ohci->fminterval write32 %x\n", value); return; case 0x1f801640: ohci->periodicstart = value; USB_LOG("ohci->periodicstart write32 %x\n", value); return; case 0x1f801644: ohci->lsthresh = value; USB_LOG("ohci->lsthresh write32 %x\n", value); return; case 0x1f801648: ohci->roothub.a = value; USB_LOG("ohci->roothub.a write32 %x\n", value); return; case 0x1f80164C: ohci->roothub.b = value; USB_LOG("ohci->roothub.b write32 %x\n", value); return; case 0x1f801650: ohci->roothub.status = value; USB_LOG("ohci->roothub.status write32 %x\n", value); return; #endif default: usbRu32(addr) = value; #ifdef USB_LOG USB_LOG("*Unknown 32bit write at address %lx write %x\n", addr, value); #endif return; } usbRu32(addr) = value; #ifdef USB_LOG USB_LOG("*Known 32bit write at address %lx value %lx\n", addr, value); #endif } void CALLBACK USBirqCallback(USBcallback callback) { USBirq = callback; } int CALLBACK _USBirqHandler(void) { if ((ohci->control & OHCI_CTRL_HCFS) == OHCI_USB_OPER) { USBirq(PSXCLK / 1000000); } #ifdef USB_LOG // USB_LOG("_USBirqHandler: %x\n", ohci->intrenable); #endif if (ohci->fmnumber == 0xffff) { ohci->fmnumber = 0; ohci->intrstatus|= OHCI_INTR_FNO; } else { ohci->fmnumber++; } if (ohci->intrenable & OHCI_INTR_MIE && ohci->intrenable & OHCI_INTR_SF && ohci->intrstatus & OHCI_INTR_SF) { #ifdef USB_LOG USB_LOG("_USBirqHandler: SOF\n"); #endif return 1; } if (ohci->intrenable & OHCI_INTR_MIE && ohci->intrenable & OHCI_INTR_FNO && ohci->intrstatus & OHCI_INTR_FNO) { #ifdef USB_LOG USB_LOG("_USBirqHandler: FNO\n"); #endif return 1; } return 0; } USBhandler CALLBACK USBirqHandler(void) { return (USBhandler)_USBirqHandler; } void CALLBACK USBsetRAM(void *mem) { ram = mem; } // extended funcs char USBfreezeID[] = "USB STv0"; typedef struct { u8 id[32]; u8 usbR[0x10000]; usbStruct usb; } USBfreezeData; s32 CALLBACK USBfreeze(int mode, freezeData *data) { USBfreezeData *usbd; if (mode == FREEZE_LOAD) { usbd = (USBfreezeData*)data->data; if (data->size != sizeof(USBfreezeData)) return -1; if (strcmp(usbd->id, USBfreezeID)) return -1; memcpy(usbR, usbd->usbR, 0x10000); memcpy(&usb, &usbd->usb, sizeof(usbStruct)); } else if (mode == FREEZE_SAVE) { data->size = sizeof(USBfreezeData); data->data = malloc(data->size); if (data->data == NULL) return -1; usbd = (USBfreezeData*)data->data; strcpy(usbd->id, USBfreezeID); memcpy(usbd->usbR, usbR, 0x10000); memcpy(&usbd->usb, &usb, sizeof(usbStruct)); } return 0; } s32 CALLBACK USBtest() { return 0; }