2011-09-04 01:36:14 +00:00
|
|
|
/* 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 "qemu-usb/vl.h"
|
|
|
|
#include "USB.h"
|
|
|
|
|
|
|
|
const unsigned char version = PS2E_USB_VERSION;
|
|
|
|
const unsigned char revision = 0;
|
|
|
|
const unsigned char build = 1; // increase that with each version
|
|
|
|
|
|
|
|
static char *libraryName = "Qemu USB Driver by Gigaherz"
|
|
|
|
#ifdef _DEBUG
|
|
|
|
" (debug)"
|
|
|
|
#endif
|
|
|
|
;
|
|
|
|
|
|
|
|
OHCIState *qemu_ohci;
|
|
|
|
|
|
|
|
Config conf;
|
|
|
|
|
|
|
|
HWND gsWnd=NULL;
|
|
|
|
|
|
|
|
u8 *usbR;
|
|
|
|
u8 *ram;
|
|
|
|
usbStruct usb;
|
|
|
|
USBcallback _USBirq;
|
|
|
|
FILE *usbLog;
|
2011-09-04 01:53:30 +00:00
|
|
|
int64_t usb_frame_time=0;
|
|
|
|
int64_t usb_bit_time=0;
|
2011-09-04 01:36:14 +00:00
|
|
|
|
2011-09-04 01:53:30 +00:00
|
|
|
s64 clocks=0;
|
|
|
|
s64 remaining=0;
|
2011-09-04 01:36:14 +00:00
|
|
|
|
2011-09-04 01:53:30 +00:00
|
|
|
int64_t get_ticks_per_sec()
|
|
|
|
{
|
|
|
|
return PSXCLK;
|
2011-09-04 01:36:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void __Log(char *fmt, ...) {
|
|
|
|
va_list list;
|
|
|
|
|
|
|
|
if (!conf.Log) return;
|
|
|
|
|
|
|
|
va_start(list, fmt);
|
|
|
|
vfprintf(usbLog, fmt, list);
|
|
|
|
va_end(list);
|
|
|
|
}
|
|
|
|
|
2011-09-04 01:53:30 +00:00
|
|
|
u32 CALLBACK PS2EgetLibType() {
|
|
|
|
return PS2E_LT_USB;
|
|
|
|
}
|
|
|
|
|
|
|
|
char* CALLBACK PS2EgetLibName() {
|
|
|
|
return libraryName;
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 CALLBACK PS2EgetLibVersion2(u32 type) {
|
|
|
|
return (version<<16) | (revision<<8) | build;
|
|
|
|
}
|
|
|
|
|
2011-09-04 01:36:14 +00:00
|
|
|
void USBirq(int cycles)
|
|
|
|
{
|
|
|
|
USB_LOG("USBirq.\n");
|
|
|
|
|
|
|
|
_USBirq(cycles);
|
|
|
|
}
|
|
|
|
|
|
|
|
s32 CALLBACK USBinit() {
|
|
|
|
LoadConfig();
|
|
|
|
if (conf.Log)
|
|
|
|
{
|
|
|
|
usbLog = fopen("logs/usbLog.txt", "w");
|
|
|
|
setvbuf(usbLog, NULL, _IONBF, 0);
|
2011-09-04 01:53:30 +00:00
|
|
|
USB_LOG("USBqemu plugin version %d,%d\n",revision,build);
|
2011-09-04 01:36:14 +00:00
|
|
|
USB_LOG("USBinit\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
qemu_ohci = ohci_create(0x1f801600,2);
|
|
|
|
qemu_ohci->rhport[0].port.attach(&(qemu_ohci->rhport[0].port),usb_keyboard_init());
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CALLBACK USBshutdown() {
|
|
|
|
|
2011-09-04 01:53:30 +00:00
|
|
|
qemu_ohci->rhport[0].port.dev->info->handle_destroy(qemu_ohci->rhport[0].port.dev);
|
2011-09-04 01:36:14 +00:00
|
|
|
|
|
|
|
free(qemu_ohci);
|
|
|
|
|
|
|
|
#ifdef _DEBUG
|
2011-09-04 01:53:30 +00:00
|
|
|
if(usbLog)
|
|
|
|
fclose(usbLog);
|
2011-09-04 01:36:14 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
s32 CALLBACK USBopen(void *pDsp) {
|
|
|
|
USB_LOG("USBopen\n");
|
|
|
|
|
|
|
|
HWND hWnd=(HWND)pDsp;
|
|
|
|
|
|
|
|
if (!IsWindow (hWnd) && !IsBadReadPtr ((u32*)hWnd, 4))
|
|
|
|
hWnd = *(HWND*)hWnd;
|
|
|
|
if (!IsWindow (hWnd))
|
|
|
|
hWnd = NULL;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
while (GetWindowLong (hWnd, GWL_STYLE) & WS_CHILD)
|
|
|
|
hWnd = GetParent (hWnd);
|
|
|
|
}
|
|
|
|
gsWnd = hWnd;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CALLBACK USBclose() {
|
|
|
|
}
|
|
|
|
|
|
|
|
u8 CALLBACK USBread8(u32 addr) {
|
|
|
|
USB_LOG("* Invalid 8bit read at address %lx\n", addr);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
u16 CALLBACK USBread16(u32 addr) {
|
|
|
|
USB_LOG("* Invalid 16bit read at address %lx\n", addr);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 CALLBACK USBread32(u32 addr) {
|
|
|
|
u32 hard;
|
|
|
|
|
2011-09-04 01:53:30 +00:00
|
|
|
hard=ohci_mem_read(qemu_ohci,addr - qemu_ohci->mem);
|
2011-09-04 01:36:14 +00:00
|
|
|
|
|
|
|
USB_LOG("* Known 32bit read at address %lx: %lx\n", addr, hard);
|
|
|
|
|
|
|
|
return hard;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CALLBACK USBwrite8(u32 addr, u8 value) {
|
|
|
|
USB_LOG("* Invalid 8bit write at address %lx value %x\n", addr, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CALLBACK USBwrite16(u32 addr, u16 value) {
|
|
|
|
USB_LOG("* Invalid 16bit write at address %lx value %x\n", addr, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CALLBACK USBwrite32(u32 addr, u32 value) {
|
|
|
|
USB_LOG("* Known 32bit write at address %lx value %lx\n", addr, value);
|
2011-09-04 01:53:30 +00:00
|
|
|
ohci_mem_write(qemu_ohci,addr - qemu_ohci->mem, value);
|
2011-09-04 01:36:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CALLBACK USBirqCallback(USBcallback callback) {
|
|
|
|
_USBirq = callback;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern u32 bits;
|
|
|
|
|
|
|
|
int CALLBACK _USBirqHandler(void)
|
|
|
|
{
|
|
|
|
//fprintf(stderr," * USB: IRQ Acknowledged.\n");
|
|
|
|
//qemu_ohci->intr_status&=~bits;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
USBhandler CALLBACK USBirqHandler(void) {
|
|
|
|
return (USBhandler)_USBirqHandler;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CALLBACK USBsetRAM(void *mem) {
|
|
|
|
ram = (u8*)mem;
|
|
|
|
}
|
|
|
|
|
|
|
|
// extended funcs
|
|
|
|
|
|
|
|
char USBfreezeID[] = "USB STv0";
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
OHCIState t;
|
|
|
|
} 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;
|
|
|
|
|
|
|
|
memcpy(qemu_ohci, usbd, sizeof(OHCIState));
|
|
|
|
} else
|
|
|
|
if (mode == FREEZE_SAVE) {
|
|
|
|
data->size = sizeof(USBfreezeData);
|
|
|
|
data->data = (s8*)malloc(data->size);
|
|
|
|
if (data->data == NULL) return -1;
|
|
|
|
usbd = (USBfreezeData*)data->data;
|
|
|
|
memcpy(usbd, qemu_ohci, sizeof(OHCIState));
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-09-04 01:53:30 +00:00
|
|
|
void CALLBACK USBasync(u32 _cycles)
|
2011-09-04 01:36:14 +00:00
|
|
|
{
|
2011-09-04 01:53:30 +00:00
|
|
|
remaining += _cycles;
|
|
|
|
clocks += remaining;
|
2011-09-04 01:36:14 +00:00
|
|
|
if(qemu_ohci->eof_timer>0)
|
|
|
|
{
|
2011-09-04 01:53:30 +00:00
|
|
|
while(remaining>=qemu_ohci->eof_timer)
|
2011-09-04 01:36:14 +00:00
|
|
|
{
|
2011-09-04 01:53:30 +00:00
|
|
|
remaining-=qemu_ohci->eof_timer;
|
2011-09-04 01:36:14 +00:00
|
|
|
qemu_ohci->eof_timer=0;
|
|
|
|
ohci_frame_boundary(qemu_ohci);
|
|
|
|
}
|
2011-09-04 01:53:30 +00:00
|
|
|
if((remaining>0)&&(qemu_ohci->eof_timer>0))
|
|
|
|
{
|
|
|
|
s64 m = qemu_ohci->eof_timer;
|
|
|
|
if(remaining < m)
|
|
|
|
m = remaining;
|
|
|
|
qemu_ohci->eof_timer -= m;
|
|
|
|
remaining -= m;
|
|
|
|
}
|
2011-09-04 01:36:14 +00:00
|
|
|
}
|
2011-09-04 01:53:30 +00:00
|
|
|
//if(qemu_ohci->eof_timer <= 0)
|
|
|
|
//{
|
|
|
|
// ohci_frame_boundary(qemu_ohci);
|
|
|
|
//}
|
2011-09-04 01:36:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
s32 CALLBACK USBtest() {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void cpu_physical_memory_rw(u32 addr, u8 *buf,
|
|
|
|
int len, int is_write)
|
|
|
|
{
|
|
|
|
if(is_write)
|
|
|
|
memcpy(&(ram[addr]),buf,len);
|
|
|
|
else
|
|
|
|
memcpy(buf,&(ram[addr]),len);
|
|
|
|
}
|
|
|
|
|
|
|
|
s64 get_clock()
|
|
|
|
{
|
|
|
|
return clocks;
|
|
|
|
}
|
|
|
|
|
|
|
|
void *qemu_mallocz(uint32_t size)
|
|
|
|
{
|
|
|
|
void *m=malloc(size);
|
|
|
|
if(!m) return NULL;
|
|
|
|
memset(m,0,size);
|
|
|
|
return m;
|
|
|
|
}
|