0,0 → 1,232 |
|
|
#include "types.h" |
#include "link.h" |
|
#include <stdio.h> |
#include <malloc.h> |
#include <memory.h> |
|
#include "pci.h" |
|
#include "syscall.h" |
#include "usb.h" |
|
static Bool FindPciDevice(); |
|
int __stdcall srv_usb(ioctl_t *io); |
|
Bool init_hc(hc_t *hc); |
|
static slab_t qh_slab; |
static slab_t td_slab; |
|
static link_t hc_list; |
static link_t newdev_list; |
static link_t rq_list; |
|
u32_t __stdcall drvEntry(int action) |
{ |
u32_t retval; |
hc_t *hc; |
udev_t *dev; |
|
int i; |
|
if(action != 1) |
return 0; |
|
if(!dbg_open("/rd/1/drivers/usb.log")) |
{ |
printf("Can't open /rd/1/drivers/usb.log\nExit\n"); |
return 0; |
} |
|
list_initialize(&hc_list); |
list_initialize(&newdev_list); |
list_initialize(&rq_list); |
|
if( !FindPciDevice() ) { |
dbgprintf("no uhci devices found\n"); |
return 0; |
}; |
|
qh_slab.available = 256; |
qh_slab.start = KernelAlloc(4096); |
qh_slab.nextavail = (addr_t)qh_slab.start; |
qh_slab.dma = GetPgAddr(qh_slab.start); |
|
qh_t *p; |
addr_t dma; |
|
for (i = 0, p = (qh_t*)qh_slab.start, dma = qh_slab.dma; |
i < 256; i++, p++, dma+= sizeof(qh_t)) |
{ |
p->qlink = (addr_t)(p+1); |
p->qelem = 1; |
p->dma = dma; |
p->r1 = 0; |
}; |
|
td_slab.available = 128; |
td_slab.start = KernelAlloc(4096); |
td_slab.nextavail = (addr_t)td_slab.start; |
td_slab.dma = GetPgAddr(td_slab.start); |
|
td_t *td; |
for (i = 0, td = (td_t*)td_slab.start, dma = td_slab.dma; |
i < 128; i++, td++, dma+= sizeof(td_t)) |
{ |
td->link = (addr_t)(td+1); |
td->status = 0; |
td->token = 0; |
td->buffer = 0; |
td->dma = dma; |
}; |
|
|
hc = (hc_t*)hc_list.next; |
|
while( &hc->link != &hc_list) |
{ |
init_hc(hc); |
hc = (hc_t*)hc->link.next; |
} |
|
dbgprintf("\n"); |
|
dev = (udev_t*)newdev_list.next; |
while( &dev->link != &newdev_list) |
{ |
udev_t *tmp = dev; |
dev = (udev_t*)dev->link.next; |
|
if(tmp->id != 0) |
init_device(tmp); |
} |
|
while(1) |
{ |
udev_t *dev; |
request_t *rq; |
|
rq = (request_t*)rq_list.next; |
while( &rq->link != &rq_list) |
{ |
qh_t *qh; |
td_t *td; |
|
td = rq->td_head; |
dev = rq->dev; |
qh = dev->host->qh1; |
|
qh->qelem = td->dma; |
|
__asm__ __volatile__ ("":::"memory"); |
rq = (request_t*)rq->link.next; |
}; |
|
delay(10/10); |
|
rq = (request_t*)rq_list.next; |
while( &rq->link != &rq_list) |
{ |
request_t *tmp; |
td_t *td; |
|
tmp = rq; |
rq = (request_t*)rq->link.next; |
|
td = tmp->td_head; |
|
if( td->status & TD_CTRL_ACTIVE) |
continue; |
|
tmp->handler(tmp->dev, tmp); |
}; |
}; |
|
retval = RegService("USB", srv_usb); |
dbgprintf("reg service USB as: %x\n", retval); |
|
return retval; |
}; |
|
|
#define API_VERSION 0x01000100 |
|
#define SRV_GETVERSION 0 |
|
|
int __stdcall srv_usb(ioctl_t *io) |
{ |
u32_t *inp; |
u32_t *outp; |
|
inp = io->input; |
outp = io->output; |
|
switch(io->io_code) |
{ |
case SRV_GETVERSION: |
if(io->out_size==4) |
{ |
*outp = API_VERSION; |
return 0; |
} |
break; |
|
|
default: |
return ERR_PARAM; |
}; |
return ERR_PARAM; |
} |
|
|
static qh_t* alloc_qh() |
{ |
if( qh_slab.available ) |
{ |
qh_t *qh; |
|
qh_slab.available--; |
qh = (qh_t*)qh_slab.nextavail; |
qh_slab.nextavail = qh->qlink; |
return qh; |
} |
return NULL; |
}; |
|
static void free_qh(qh_t *qh) |
{ |
qh->qlink = qh_slab.nextavail; |
qh_slab.nextavail = (addr_t)qh; |
qh_slab.available++; |
}; |
|
static td_t* alloc_td() |
{ |
if( td_slab.available ) |
{ |
td_t *td; |
|
td_slab.available--; |
td = (td_t*)td_slab.nextavail; |
td_slab.nextavail = td->link; |
return td; |
} |
return NULL; |
}; |
|
static void free_td(td_t *td) |
{ |
td->link = td_slab.nextavail; |
td_slab.nextavail = (addr_t)td; |
td_slab.available++; |
}; |
|
#include "pci.inc" |
#include "detect.inc" |
#include "hcd.inc" |
#include "hid.inc" |