Commit e7c1e36d authored by Kevin Bracey's avatar Kevin Bracey
Browse files

Latest stuff from John - mainly Rhenium improvements.

Version 0.26. Tagged as 'NetBSD-0_26'
parent 833bc3d0
/* (0.25)
/* (0.26)
*
* This file is automatically maintained by srccommit, do not edit manually.
* Last processed by srccommit version: 1.2.
* Last processed by srccommit version: 1.68.
*
*/
#define Module_MajorVersion_CMHG 0.25
#define Module_MajorVersion_CMHG 0.26
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 06 May 2004
#define Module_Date_CMHG 30 Jun 2004
#define Module_MajorVersion "0.25"
#define Module_Version 25
#define Module_MajorVersion "0.26"
#define Module_Version 26
#define Module_MinorVersion ""
#define Module_Date "06 May 2004"
#define Module_Date "30 Jun 2004"
#define Module_ApplicationDate "06-May-04"
#define Module_ApplicationDate "30-Jun-04"
#define Module_ComponentName "NetBSD"
#define Module_ComponentPath "RiscOS/Sources/HWSupport/USB/NetBSD"
#define Module_FullVersion "0.25"
#define Module_HelpVersion "0.25 (06 May 2004)"
#define Module_LibraryVersionInfo "0:25"
#define Module_FullVersion "0.26"
#define Module_HelpVersion "0.26 (30 Jun 2004)"
#define Module_LibraryVersionInfo "0:26"
......@@ -17,6 +17,3 @@ echo starting build
amu_machine all rom COMPONENT=USBDriver CFLAGS="-ff -DSTANDALONE" THROWBACK=-throwback
amu_machine all rom COMPONENT=OHCIDriver CFLAGS="-ff -DSTANDALONE" THROWBACK=-throwback
amu_machine all rom COMPONENT=EHCIDriver CFLAGS="-ff -DSTANDALONE" THROWBACK=-throwback
|amu_machine -f MakeEHCID all
|amu_machine -f MakeHUB all
|amu_machine -f MakeHID all
| Copyright 2004 Castle Technology Ltd
|
| Licensed under the Apache License, Version 2.0 (the "License");
| you may not use this file except in compliance with the License.
| You may obtain a copy of the License at
|
| http://www.apache.org/licenses/LICENSE-2.0
|
| Unless required by applicable law or agreed to in writing, software
| distributed under the License is distributed on an "AS IS" BASIS,
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
| See the License for the specific language governing permissions and
| limitations under the License.
|
dir <obey$dir>
echo starting build
amu_machine all rom COMPONENT=USBDriver CFLAGS="-ff -DSTANDALONE -DRHENIUM -DRHENIUM_NO_ISOC -DRHENIUM_NO_BULK " THROWBACK=-throwback
amu_machine all rom COMPONENT=OHCIDriver CFLAGS="-ff -DSTANDALONE -DRHENIUM -DRHENIUM_NO_ISOC -DRHENIUM_NO_BULK " CMHGFLAGS="-DRHENIUM " THROWBACK=-throwback
|amu_machine all rom COMPONENT=EHCIDriver CFLAGS="-ff -DSTANDALONE -DRHENIUM -DRHENIUM_NO_ISOC -DRHENIUM_NO_BULK " THROWBACK=-throwback
\ No newline at end of file
......@@ -13,4 +13,5 @@ usbkboard.o \
hid.o \
bufman.o \
triggercbs.o \
call_veneer.o \
usbmsgs.o
No preview for this file type
......@@ -2,11 +2,11 @@
VersionNum file really,as a work around define them here so the CMHG
file remains unaltered */
#define OHCIDriverModule_Module_Date_CMHG 26 Apr 2004
#define OHCIDriverModule_MajorVersion_CMHG 0.17
#define OHCIDriverModule_Module_Date_CMHG 12 Jun 2004
#define OHCIDriverModule_MajorVersion_CMHG 0.18
#define EHCIDriverModule_Module_Date_CMHG 26 Apr 2004
#define EHCIDriverModule_MajorVersion_CMHG 0.02
#define USBDriverModule_Module_Date_CMHG 26 Apr 2004
#define USBDriverModule_MajorVersion_CMHG 0.29
#define USBDriverModule_Module_Date_CMHG 06 Jun 2004
#define USBDriverModule_MajorVersion_CMHG 0.30
......@@ -52,6 +52,8 @@
#define OHCIEmulator_ReadWord 0x054a83
#define OHCIEmulator_WriteWord 0x054a84
#define OHCIVendorUnknownRootName "Built-in"
MessagesFD mod_messages;
/* for debugging */
......@@ -124,6 +126,150 @@ int irqs;
unsigned int irq_min = INT_MAX, irq_max = 0;
unsigned long long irq_tot;
#ifdef RHENIUM
#define REPOWER_DELAY 10
void (*ohci_ppower)(int port, int state); //(used with rhenium)
int (*ohci_error)(int port); //(used with rhenium)
int (*ohci_pirq)(int port, int mode); //(used with rhenium)
int hal_pirq_device; // device to use for power IRQ, or -1
int hal_error_irq_claimed;
typedef enum {P_none,P_on,P_off,P_going_on,P_going_on2,P_ready,P_retry}P_Phase;
typedef struct p_err_chk{
int unit;
P_Phase state;
}p_err_chk;
p_err_chk pchk;
// 0 if OK, 1 if overcurrent
int do_hal_perror(int port)
{
int r;
_swix(OS_Hardware, _INR(0,1)|_INR(8,9)|_OUT(0),
0, port-1,
0, EntryNo_HAL_USBPortStatus,
&r);
return r;
}
// mode=0 .. turn off irq .. report irq device number
// mode=1 .. turn irq source on and acknowledge the IRQ
// mode=2 .. read irq status and acknowledge the IRQ
int do_hal_pirq (int port, int mode)
{
int r=0;
_swix(OS_Hardware, _INR(0,1)|_INR(8,9)|_OUT(0),
port-1,mode,
0, EntryNo_HAL_USBPortIRQ,
&r);
return r;
}
void do_hal_ppower(int port, int state);
//_kernel_oserror * _hal_powercheck (_kernel_swi_regs * r, void* pw, void* v);
_kernel_oserror * _hal_powercheck (_kernel_swi_regs * r, void* pw, void* v)
{
p_err_chk *p = (p_err_chk*)v;
switch(p->state)
{
case P_going_on:
if(do_hal_perror(1)) // power is not yet good
{
p->state=P_going_on2; // wait a little longer
callx_add_callafter(2, _hal_powercheck, p);
break;
} // else fall through
case P_going_on2:
if(do_hal_perror(1)) // power is still not good
{
p->state=P_off;
do_hal_ppower(p->unit,0);
break;
} // else fall through
case P_ready:
{
_swix (OS_ClaimDeviceVector, _INR(0,4),
hal_pirq_device | (1u<<31),
usb_irq_port_error_entry, private_word, 0, 0);
hal_error_irq_claimed = 1;
p->state=P_on;
do_hal_pirq(1,1); // force the irq source on again
}
break;
case P_retry:
do_hal_ppower(p->unit,1); // try turning on again
break;
}
return NULL;
}
/* Note OHCI numbers ports from 1, the HAL from 0 */
void do_hal_ppower(int port, int state)
{
_swix(OS_Hardware, _INR(0,2)|_INR(8,9), 0, port-1, state,
0, EntryNo_HAL_USBPortPower);
// only allowed to monitor overcurrent status if port is on
if(hal_pirq_device!=-1)
{
if (state && !hal_error_irq_claimed)
{
pchk.state=P_going_on;
pchk.unit = port;
callx_add_callafter(2,_hal_powercheck,(void*)&pchk); // delay monitoring
}
else
if (!state )
{
do_hal_pirq(1,0);
pchk.state=P_retry;
pchk.unit = port;
callx_add_callafter(100*REPOWER_DELAY,
_hal_powercheck,(void*)&pchk); // try again
if(hal_error_irq_claimed)
_swix (OS_ReleaseDeviceVector, _INR(0,4),
hal_pirq_device | (1u<<31),
usb_irq_port_error_entry, private_word, 0, 0);
hal_error_irq_claimed = 0;
}
}
}
// designed to turn off root port power if overcurrent detected
int usb_irq_port_error_handler(_kernel_swi_regs *r, void *pw)
{
int ret;
ret=do_hal_pirq(1,2); // my IRQ?
if(ret)
{
do_hal_pirq(1,0); // else ack the irq and force irq off..back on
do_hal_ppower(1,0); // if irq .. power off please
}
return ret?0:1; // claim.. or pass on
}
int do_ohci_pirq (int port, int mode)
{
return !mode?-1:0; // not implemented..
}
void do_ohci_ppower(int port, int state)
{
ohci_base[OHCI_RH_PORT_STATUS(port)/4] =
state ? UPS_PORT_POWER : UPS_LOW_SPEED;
}
int do_ohci_perror(int port)
{
return ohci_base[OHCI_RH_PORT_STATUS(port)/4] & UPS_OVERCURRENT_INDICATOR
? 1 : 0;
}
#endif /* RHENIUM */
_kernel_oserror* new_instance (_kernel_swi_regs* r, void* pw, void* h)
{
_kernel_oserror * e;
......@@ -135,10 +281,22 @@ _kernel_oserror* new_instance (_kernel_swi_regs* r, void* pw, void* h)
/* fill in the device name in the callback so that our service call handler
is threaded and there to respond to PCI calls */
_swix (PCI_ReadInfo, _INR(0,3), (1<<16), &v, 4, pci_device);
if (v == 0) v = (char *)"";
strncpy (ohci_soft.sc_vendor, v, sizeof ohci_soft.sc_vendor)
[sizeof ohci_soft.sc_vendor - 1] = '\0';
#ifdef RHENIUM
if (pci_device == -1)
{
strcpy (ohci_soft.sc_vendor, OHCIVendorUnknownRootName);
return NULL;
}
else
{
#endif /* RHENIUM */
_swix (PCI_ReadInfo, _INR(0,3), (1<<16), &v, 4, pci_device);
if (v == 0) v = (char *)"";
strncpy (ohci_soft.sc_vendor, v, sizeof ohci_soft.sc_vendor)
[sizeof ohci_soft.sc_vendor - 1] = '\0';
#ifdef RHENIUM
}
#endif /* RHENIUM */
/* allow enough space for name, % and number, then space, and
another number */
......@@ -216,6 +374,59 @@ _kernel_oserror *module_init(const char *cmd_tail, int podule_base, void *pw) {
0xFFFFFF,
pci_device,
&pci_device);
#ifdef RHENIUM
if (e || pci_device == 0)
{
struct
{
int type;
int flags;
void *hw;
int devno;
} usbinfo;
size_t usbinfolen;
e = _swix(OS_Hardware, _INR(0,2)|_INR(8,9)|_OUT(0),
0, &usbinfo, sizeof usbinfo,
0, EntryNo_HAL_USBControllerInfo,
&usbinfolen);
if (!e && (usbinfolen >= sizeof(usbinfo)) && usbinfo.type == 0)
{
device_number = usbinfo.devno;
ohci_base = usbinfo.hw;
if(usbinfo.flags & 1)
{
ohci_ppower = do_hal_ppower;
}
else
{
ohci_ppower = do_ohci_ppower;
}
if(usbinfo.flags & 2)
{
ohci_error = do_hal_perror;
}
else
{
ohci_error = do_ohci_perror;
}
if(usbinfo.flags & 4)
{
ohci_pirq = do_hal_pirq;
hal_pirq_device=(ohci_pirq)(1,0); // irq off .. read devicenum
hal_error_irq_claimed=0;
}
else
{
ohci_pirq = do_ohci_pirq;
hal_pirq_device=-1; // not implemented
}
pci_device = -1;
(ohci_ppower)(1,0); // ensure port power off
}
}
#endif /* RHENIUM */
if (e) goto error;
} while (0);//pci_device == 2 || pci_device == 3);
......@@ -232,44 +443,63 @@ _kernel_oserror *module_init(const char *cmd_tail, int podule_base, void *pw) {
dprintf (("Main_0", "Found OHCI controller on device %d\n", pci_device));
/* now establish our interrupt and address */
#ifdef RHENIUM
e = _swix(PCI_ReadInfo, _INR(0,3),
PCI_ReadInfo_IntDeviceVector,
&device_number,
sizeof device_number,
pci_device);
if (e) goto error;
if (pci_device != -1)
{
#endif /* RHENIUM */
/* now establish our interrupt and address */
dprintf (("Main_0", "interrupt device %d\n", device_number));
e = _swix(PCI_ReadInfo, _INR(0,3),
PCI_ReadInfo_IntDeviceVector,
&device_number,
sizeof device_number,
pci_device);
if (e) goto error;
e = _swix(PCI_HardwareAddress, _INR(0,1)|_IN(3)|_OUT(4),
0, 0, pci_device, &ohci_base);
if (e) goto error;
dprintf (("Main_0", "interrupt device %d\n", device_number));
dprintf (("Main_0", "hardware address %p\n", ohci_base));
e = _swix(PCI_HardwareAddress, _INR(0,1)|_IN(3)|_OUT(4),
0, 0, pci_device, &ohci_base);
if (e) goto error;
dprintf (("Main_0", "hardware address %p\n", ohci_base));
#ifdef RHENIUM
}
#endif /* RHENIUM */
memset (&ohci_soft, 0, sizeof ohci_soft);
sprintf (ohci_soft.sc_bus.bdev.dv_xname, "OHCI%d", instance);
_swix (PCI_ReadInfo, _INR(0,3), (1<<16), &v, 4, pci_device);
strncpy (ohci_soft.sc_vendor, v, sizeof ohci_soft.sc_vendor)
[sizeof ohci_soft.sc_vendor - 1] = '\0';
_swix (PCI_ReadInfo, _INR(0,3), (1<<16), &v, 4, pci_device);
strncpy (ohci_soft.sc_vendor, v, sizeof ohci_soft.sc_vendor)
#ifdef RHENIUM
if (pci_device == -1)
strcpy(ohci_soft.sc_vendor, OHCIVendorUnknownRootName);
else
{
#endif /* RHENIUM */
_swix (PCI_ReadInfo, _INR(0,3), (1<<16), &v, 4, pci_device);
strncpy (ohci_soft.sc_vendor, v, sizeof ohci_soft.sc_vendor)
[sizeof ohci_soft.sc_vendor - 1] = '\0';
#ifdef RHENIUM
}
#endif /* RHENIUM */
private_word = pw;
#ifdef OHCI_DEBUG
usbdebug = ohcidebug = atoi (getenv ("ohcidebug"));
#endif
_swix (OS_ClaimDeviceVector, _INR(0,4),
device_number| (1u<<31), usb_irq_entry, pw, 0, 0);
device_number | ((pci_device == -1)?0:(1u<<31)),
usb_irq_entry, pw, 0, 0);
_swix (OS_Hardware, _IN(0) | _INR(8,9),
device_number, 0, EntryNo_HAL_IRQEnable);
#ifdef RHENIUM
#endif /* RHENIUM */
if ((magic = init_veneer ()) == NULL)
{
......@@ -287,7 +517,7 @@ _kernel_oserror *module_init(const char *cmd_tail, int podule_base, void *pw) {
_swix (USBDriver_RegisterBus, _IN(0)|_OUT(0),
&ohci_soft, &usb_soft);
dprintf (("Main_0", "Finished module initialisation\n"));
dprintf (("", "Finished module initialisation\n"));
#ifdef OHCI_DEBUG
/* if we're sharing an interrupt with the video card */
......@@ -337,6 +567,17 @@ _kernel_oserror *module_final(int fatal, int podule, void *pw)
v = ob[OHCI_CONTROL / 4]; // flush the write
#ifdef RHENIUM
if(hal_error_irq_claimed)
{
(ohci_pirq)(1,0);
_swix (OS_ReleaseDeviceVector, _INR(0,4),
hal_pirq_device | (1u<<31),
usb_irq_port_error_entry, private_word, 0, 0);
}
#endif /*RHENIUM*/
callx_remove_all_callbacks ();
callx_remove_all_callafters ();
callx_remove_all_calleverys ();
......@@ -345,7 +586,8 @@ _kernel_oserror *module_final(int fatal, int podule, void *pw)
when noone is left responding */
_swix (OS_ReleaseDeviceVector, _INR(0,4),
device_number | (1u<<31), usb_irq_entry, pw, 0, 0);
device_number | ((pci_device == -1)?0:(1u<<31)),
usb_irq_entry, pw, 0, 0);
if (magic) _swix (OS_Module, _IN(0)|_IN(2), 7, magic);
......@@ -437,9 +679,18 @@ void module_services(int service_number, _kernel_swi_regs *r, void *pw)
usb_soft = NULL;
memset (&ohci_soft, 0, sizeof ohci_soft);
sprintf (ohci_soft.sc_bus.bdev.dv_xname, "OHCI%d", instance);
_swix (PCI_ReadInfo, _INR(0,3), (1<<16), &v, 4, pci_device);
strncpy (ohci_soft.sc_vendor, v, sizeof ohci_soft.sc_vendor)
[sizeof ohci_soft.sc_vendor - 1] = '\0';
#ifdef RHENIUM
if (pci_device == -1)
strcpy(ohci_soft.sc_vendor, OHCIVendorUnknownRootName);
else
{
#endif /* RHENIUM */
_swix (PCI_ReadInfo, _INR(0,3), (1<<16), &v, 4, pci_device);
strncpy (ohci_soft.sc_vendor, v, sizeof ohci_soft.sc_vendor)
[sizeof ohci_soft.sc_vendor - 1] = '\0';
#ifdef RHENIUM
}
#endif /* RHENIUM */
ohci_init (&ohci_soft);
break;
}
......@@ -644,7 +895,13 @@ int usb_irq_handler(_kernel_swi_regs *r, void *pw)
/* interrupts must be left off for the duration of this call, otherwise
it hangs */
ret = !ohci_intr (&ohci_soft);
ret = !ohci_intr (&ohci_soft);
#ifdef RHENIUM
// the chip requires its interrupts cleared
if (pci_device == -1)
_swix(OS_Hardware, _IN(0)|_INR(8,9), device_number,
0, EntryNo_HAL_IRQClear);
#endif /* RHENIUM */
#ifdef OHCI_DEBUG
if (ret)
......
......@@ -36,6 +36,8 @@ int total_sleep;
extern void detach_hub (struct device*);
extern void detach_device (struct device*);
extern uint32_t hal_veneer2(uint32_t (*)(void), void*, ...);
extern uint64_t gettime (void);
uint64_t gettime (void)
......@@ -65,7 +67,7 @@ uint64_t gettime (void)
}
_swix (OS_ReadMonotonicTime, _OUT(0), &cs);
return (uint64_t) (max_count - (readcode) ()) * ns_factor +
return (uint64_t) (max_count - hal_veneer2(readcode,ws)) * ns_factor +
((uint64_t) cs) * 10000000 /* 1e7 */;
}
......
......@@ -238,6 +238,12 @@ struct device* attach_keyboard (struct device* parent, void* aux)
int detach_keyboard (struct device* kb)
{
struct ukbd_softc* sc = (struct ukbd_softc*) kb;
if(!sc || !sc->sc_intrpipe)
{
dprintf (("", "attempt to detach a NULL keyboard 'sc'\n"));
return 0;
}
uint32_t * status = sc->status;
/* release any keys held down */
for (int w = 0; w < sizeof sc->status / sizeof (int); ++w)
......
......@@ -49,6 +49,7 @@
#include "usbkboard.h"
#include "service.h"
/*---------------------------------------------------------------------------*/
/* structure definitions */
/*---------------------------------------------------------------------------*/
......@@ -165,11 +166,15 @@ _kernel_oserror* uerror (char* e)
void riscos_failed_device (void* p)
{
//#ifdef STANDALONE
#ifndef RHENIUM
_kernel_oserror* e;
(void) p;
e = uerror (E_BadDevice);
_swix (OS_UpCall, _INR(0,6), UpCall_MediaNotPresent, fsnumber_DeviceFS,
-1, -1, 0, 0x7fffffff, e->errmess);
-1, -1, 0, 0x7f/*ffffff*/, e->errmess);
#endif /*RHENIUM*/
//#endif /*STANDALONE*/
}
_kernel_oserror* messages_update (messages* mess)
......@@ -391,6 +396,7 @@ _kernel_oserror *module_final(int fatal, int podule, void *pw)
}
/*---------------------------------------------------------------------------*/
extern int Image__RO_Base;
void module_services(int service_number, _kernel_swi_regs *r, void *pw)
{
......@@ -1080,6 +1086,7 @@ struct device* attach_hub (struct device* parent, void* aux)
softc->dv_cfdata = (void*) 1; // hub
(*uhub_uhub_ca.ca_attach) (parent, softc, aux);
dprintf (("", "Matched hub\n"));
return softc;
......@@ -1184,7 +1191,7 @@ char* service_call (usbd_device_handle dev, int unit, int link)
serv->dev.ifcs = idescs;
for (epn = 0, iface = 0; iface < nifs; ++iface)
{
{
int ifcepn = dev->ifaces[iface].idesc->bNumEndpoints;
dprintf(("", "iface %d, num endpoints = %d, at %p\n", iface, ifcepn, idescs[iface]));
memcpy (idescs[iface], dev->ifaces[iface].idesc,
......@@ -2110,7 +2117,8 @@ static void read_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
{
struct devstream* str = priv;
if (status != USBD_NORMAL_COMPLETION)
if ( (status != USBD_NORMAL_COMPLETION)
&&(status != USBD_SHORT_XFER_DONE))
{
dprintf (("", "Bad completion code: %d (%s) %d bytes read\n",
status, ccodes[status], xfer->actlen));
......@@ -2126,7 +2134,23 @@ static void read_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
/* only start another transfer if we haven't finished the transfer and
this is not a interrupt endpoint (the BSD framework restarts
repeating transfers) */
if (str->count != str->totalcount && !xfer->pipe->repeat)
/* if we've got a number of bytes including a part packet, then
transfer must have ended.. else.. try more */
// if (!(xfer->actlen/UGETW(xfer->pipe->endpoint->edesc->wMaxPacketSize)) &&
// str->count != str->totalcount)
if(status == USBD_SHORT_XFER_DONE)
{
char zero[ UGETW(xfer->pipe->endpoint->edesc->wMaxPacketSize)];
memset (zero, 0, sizeof zero);
// fill up the rest of the request with garbage!
_kernel_swi_regs r;
r.r[0] = BM_InsertBlock;
r.r[1] = (int) str->buffer_id;
r.r[2] = (int) zero;
r.r[3] = str->totalcount - str->count;
CallBufMan (&r);
}
else if (str->count != str->totalcount && !xfer->pipe->repeat)
{
dprintf (("", "Starting read from callback\n"));
start_read (str);
......@@ -2295,7 +2319,7 @@ void terminate_stream (struct ugen_softc* ugen, struct devstream * str, int kill
if (kill)
{
int status;
if (str->dying) return;
if (str->dying || !str->pipe) return;
str->dying = 1;
/* only close these when the device is removed */
status = usbd_abort_pipe(str->pipe);
......@@ -2673,7 +2697,7 @@ _kernel_oserror* driver (_kernel_swi_regs* r, void* pw)
&mod_messages, cc, 0, &cp);
return _swix (MessageTrans_ErrorLookup, _INR(0,4),
errtoken, &mod_messages, &err, sizeof err, cp);
}
return NULL; }
break;
case DeviceFSCallDevice_USBRequest:
{
......
......@@ -129,6 +129,7 @@ static int match_mouse (struct usb_attach_arg *uaa)
}
nrepid = uhidev_maxrepid(desc, size);
ret = UMATCH_NONE;
for (repid = 0; repid <= nrepid; repid++)
......@@ -200,6 +201,7 @@ static void do_attach_mouse (struct ums_softc* sc, struct usb_attach_arg *uaa)
USB_ATTACH_ERROR_RETURN;
nrepid = uhidev_maxrepid(desc, size);
for (repid = 0; repid <= nrepid; repid++)
{
if (hid_is_collection(desc, size, repid,
......@@ -268,6 +270,8 @@ static void do_attach_mouse (struct ums_softc* sc, struct usb_attach_arg *uaa)
sc->sc_iid, hid_input, &sc->sc_loc_btn[i-1], 0);
sc->sc_isize = hid_report_size(desc, size, hid_input, sc->sc_iid);
sc->sc_isize += (nrepid != 0);
sc->sc_ibuf = malloc(sc->sc_isize);
if (sc->sc_ibuf == NULL) {
logprintf("%s: no memory\n", USBDEVNAME(sc->sc_dev));
......@@ -337,6 +341,11 @@ struct device* attach_mouse (struct device* parent, void* aux)
/* set idle rate to 0 */
usbd_set_idle (sc->sc_iface, 0, 0);
/* make sure we're using the report protocol */
usbd_set_protocol(sc->sc_iface, 1);
int err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr,
USBD_SHORT_XFER_OK, &sc->sc_intrpipe, sc,
sc->sc_ibuf, sc->sc_isize, ums_intr, USBD_DEFAULT_INTERVAL);
......@@ -357,6 +366,11 @@ struct device* attach_mouse (struct device* parent, void* aux)
int detach_mouse (struct device* ms)
{
struct ums_softc* sc= (struct ums_softc*) ms;
if(!sc || !sc->sc_intrpipe)
{
dprintf (("", "attempt to detach a NULL mouse 'sc'\n"));
return 0;
}
dprintf (("", "detaching mouse, buttons = %x\n", sc->sc_buttons));
usbd_abort_pipe(sc->sc_intrpipe);
usbd_close_pipe(sc->sc_intrpipe);
......
......@@ -70,5 +70,8 @@ event-handler: vsync_entry/vsync Event_VSync
#endif
vector-handlers: usb_irq_entry/usb_irq_handler,
#ifdef RHENIUM
usb_irq_port_error_entry/usb_irq_port_error_handler,
#endif /*RHENIUM*/
softintr_entry/softintr
generic-veneers: callout_entry/callout_handler
......@@ -23,7 +23,6 @@ service-call-handler: module_services Service_ResourceFSStarted,
Service_ResourceFSStarting,
Service_PCI,
Service_USB
title-string: USBDriver
help-string: USBDriver USBDriverModule_MajorVersion_CMHG
......
......@@ -69,4 +69,17 @@ common STMFD sp!, {v1,v2,fp,lr}
LDMFD sp!, {v1,v2,fp,pc}
magic_end
; hal_veneer(code, ws) up to 2 arguments supported
EXPORT hal_veneer2
hal_veneer2
STMFD sp!,{r9,lr}
MOV ip, a1
MOV r9, a2
MOV a1, a3
MOV a2, a4
MOV lr, pc
MOV pc, ip
LDMFD sp!,{r9,pc}
END
/* $NetBSD: ehci.c,v 1.40 2002/11/19 19:18:09 martin Exp $ */
/*
* TODO
* hold off explorations by companion controllers until ehci has started.
*/
/* $NetBSD: ehci.c,v 1.54 2004/01/17 13:15:05 jdolecek Exp $ */
/*
* Copyright (c) 2001 The NetBSD Foundation, Inc.
......@@ -48,11 +43,31 @@
* http://developer.intel.com/technology/usb/download/ehci-r10.pdf
* and the USB 2.0 spec at
* http://www.usb.org/developers/data/usb_20.zip
/*
* TODO:
* 1) hold off explorations by companion controllers until ehci has started.
*
* 2) The EHCI driver lacks support for interrupt isochronous transfers, so
* devices using them don't work.
* Interrupt transfers are not difficult, it's just not done.
*
* 3) There might also be some issues with the data toggle, it was not
* completely tested to work properly under all condistions. If wrong
* toggle would be sent/recvd, bulk data transfers would stop working.
*
* 4) The meaty part to implement is the support for USB 2.0 hubs.
* They are quite compolicated since the need to be able to do
* "transaction translation", i.e., converting to/from USB 2 and USB 1.
* So the hub driver needs to handle and schedule these things, to
* assign place in frame where different devices get to go. See chapter
* on hubs in USB 2.0 for details.
*
* 5) command failures are not recovered correctly
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.40 2002/11/19 19:18:09 martin Exp $");
__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.54 2004/01/17 13:15:05 jdolecek Exp $");
#include <sys/param.h>
#include <sys/systm.h>
......@@ -221,7 +236,11 @@ Static void ehci_dump_exfer(struct ehci_xfer *);
#define ehci_add_intr_list(sc, ex) \
LIST_INSERT_HEAD(&(sc)->sc_intrhead, (ex), inext);
#define ehci_del_intr_list(ex) \
LIST_REMOVE((ex), inext)
do { \
LIST_REMOVE((ex), inext); \
(ex)->inext.le_prev = NULL; \
} while (0)
#define ehci_active_intr_list(ex) ((ex)->inext.le_prev != NULL)
Static struct usbd_bus_methods ehci_bus_methods = {
ehci_open,
......@@ -655,7 +674,7 @@ void
ehci_softintr(void *v)
{
ehci_softc_t *sc = v;
struct ehci_xfer *ex;
struct ehci_xfer *ex, *nextex;
DPRINTFN(10,("%s: ehci_softintr (%d)\n", USBDEVNAME(sc->sc_bus.bdev),
sc->sc_bus.intr_context));
......@@ -668,8 +687,10 @@ ehci_softintr(void *v)
* An interrupt just tells us that something is done, we have no
* clue what, so we need to scan through all active transfers. :-(
*/
for (ex = LIST_FIRST(&sc->sc_intrhead); ex; ex = LIST_NEXT(ex, inext))
for (ex = LIST_FIRST(&sc->sc_intrhead); ex; ex = nextex) {
nextex = LIST_NEXT(ex, inext);
ehci_check_intr(sc, ex);
}
if (sc->sc_softwake) {
sc->sc_softwake = 0;
......@@ -778,6 +799,10 @@ ehci_idone(struct ehci_xfer *ex)
break;
status = nstatus;
/* halt is ok if descriptor is last, and complete */
if (sqtd->qtd.qtd_next == EHCI_NULL &&
EHCI_QTD_GET_BYTES(status) == 0)
status &= ~EHCI_QTD_HALTED;
if (EHCI_QTD_GET_PID(status) != EHCI_QTD_PID_SETUP)
actlen += sqtd->len - EHCI_QTD_GET_BYTES(status);
}
......@@ -1831,7 +1856,7 @@ ehci_root_ctrl_start(usbd_xfer_handle xfer)
#endif
break;
case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE):
if (value & 0xff != 0) {
if ((value & 0xff) != 0) {
err = USBD_IOERROR;
goto ret;
}
......@@ -2292,6 +2317,7 @@ ehci_alloc_sqtd_chain(struct ehci_pipe *epipe, ehci_softc_t *sc,
if (i != 0) /* use offset only in first buffer */
a = EHCI_PAGE(a);
cur->qtd.qtd_buffer[i] = htole32(a);
cur->qtd.qtd_buffer_hi[i] = 0;
#ifdef DIAGNOSTIC
if (i >= EHCI_QTD_NBUFFERS) {
logprintf("ehci_alloc_sqtd_chain: i=%d\n", i);
......@@ -2576,7 +2602,7 @@ ehci_device_ctrl_done(usbd_xfer_handle xfer)
}
#endif
if (xfer->status != USBD_NOMEM) {
if (xfer->status != USBD_NOMEM && ehci_active_intr_list(ex)) {
ehci_del_intr_list(ex); /* remove from active list */
ehci_free_sqtd_chain(sc, ex->sqtdstart, NULL);
}
......@@ -2699,6 +2725,7 @@ ehci_device_request(usbd_xfer_handle xfer)
EHCI_QTD_SET_BYTES(sizeof *req)
);
setup->qtd.qtd_buffer[0] = htole32(DMAADDR(&epipe->u.ctl.reqdma, 0));
setup->qtd.qtd_buffer_hi[0] = 0;
setup->nextqtd = next;
setup->qtd.qtd_next = setup->qtd.qtd_altnext = htole32(next->physaddr);
setup->xfer = xfer;
......@@ -2711,6 +2738,7 @@ ehci_device_request(usbd_xfer_handle xfer)
EHCI_QTD_IOC
);
stat->qtd.qtd_buffer[0] = 0; /* XXX not needed? */
stat->qtd.qtd_buffer_hi[0] = 0; /* XXX not needed? */
stat->nextqtd = NULL;
stat->qtd.qtd_next = stat->qtd.qtd_altnext = EHCI_NULL;
stat->xfer = xfer;
......@@ -2906,9 +2934,9 @@ ehci_device_bulk_done(usbd_xfer_handle xfer)
DPRINTFN(10,("ehci_bulk_done: xfer=%p, actlen=%d\n",
xfer, xfer->actlen));
if (xfer->status != USBD_NOMEM) {
if (xfer->status != USBD_NOMEM && ehci_active_intr_list(ex)) {
ehci_del_intr_list(ex); /* remove from active list */
ehci_free_sqtd_chain(sc, ex->sqtdstart, 0);
ehci_free_sqtd_chain(sc, ex->sqtdstart, NULL);
}
DPRINTFN(5, ("ehci_bulk_done: length=%d\n", xfer->actlen));
......
......@@ -138,6 +138,10 @@ Static usbd_status ohci_alloc_std_chain(struct ohci_pipe *,
Static void ohci_shutdown(void *v);
Static void ohci_power(int, void *);
#ifdef RHENIUM
extern void (*ohci_ppower)(int port, int state); //(used with rhenium)
extern int (*ohci_error)(int port); //(used with rhenium)
#endif /*RHENIUM*/
Static usbd_status ohci_open(usbd_pipe_handle);
Static void ohci_poll(struct usbd_bus *);
Static void ohci_softintr(void *);
......@@ -904,6 +908,9 @@ ohci_init(ohci_softc_t *sc)
desca = OREAD4(sc, OHCI_RH_DESCRIPTOR_A);
OWRITE4(sc, OHCI_RH_DESCRIPTOR_A, desca | OHCI_NOCP);
OWRITE4(sc, OHCI_RH_STATUS, OHCI_LPSC); /* Enable port power */
#ifdef RHENIUM
(*ohci_ppower)(1, 1); // port power on
#endif /*RHENIUM*/
usb_delay_ms(&sc->sc_bus, OHCI_ENABLE_POWER_DELAY);
OWRITE4(sc, OHCI_RH_DESCRIPTOR_A, desca);
......@@ -1163,7 +1170,7 @@ ohci_intr1(ohci_softc_t *sc)
int temp_debug;
#endif
DPRINTFN(14,("ohci_intr1: enter\n"));
DPRINTFN(10,("ohci_intr1: enter\n"));
/* In case the interrupt occurs before initialization has completed. */
if (sc == NULL || sc->sc_hcca == NULL) {
......@@ -2767,6 +2774,9 @@ ohci_root_ctrl_start(usbd_xfer_handle xfer)
case UHF_PORT_POWER:
/* Yes, writing to the LOW_SPEED bit clears power. */
OWRITE4(sc, port, UPS_LOW_SPEED);
#ifdef RHENIUM
(*ohci_ppower)(1, 0); // port power off
#endif /*RHENIUM*/
break;
case UHF_C_PORT_CONNECTION:
OWRITE4(sc, port, UPS_C_CONNECT_STATUS << 16);
......@@ -2889,6 +2899,9 @@ ohci_root_ctrl_start(usbd_xfer_handle xfer)
case UHF_PORT_POWER:
DPRINTFN(2,("ohci_root_ctrl_transfer: set port power "
"%d\n", index));
#ifdef RHENIUM
(*ohci_ppower)(1, 1); // port power on
#endif /*RHENIUM*/
OWRITE4(sc, port, UPS_PORT_POWER);
break;
default:
......@@ -3057,6 +3070,35 @@ ohci_noop(usbd_pipe_handle pipe)
{
}
#ifdef RHENIUM_NO_BULK /* Bulk transfers dis-allowed */
Static usbd_status
ohci_device_bulk_transfer(usbd_xfer_handle xfer)
{
return (USBD_IOERROR);
}
Static usbd_status
ohci_device_bulk_start(usbd_xfer_handle xfer)
{
return (USBD_IOERROR);
}
Static void
ohci_device_bulk_abort(usbd_xfer_handle xfer)
{
}
/*
* Close a device bulk pipe.
*/
Static void
ohci_device_bulk_close(usbd_pipe_handle pipe)
{
}
#else /*RHENIUM_NO_BULK*/
Static usbd_status
ohci_device_bulk_transfer(usbd_xfer_handle xfer)
{
......@@ -3194,6 +3236,7 @@ ohci_device_bulk_close(usbd_pipe_handle pipe)
ohci_close_pipe(pipe, sc->sc_bulk_head);
ohci_free_std(sc, opipe->tail.td);
}
#endif /*RHENIUM_NO_BULK*/
/************************/
......@@ -3405,6 +3448,49 @@ ohci_device_setintr(ohci_softc_t *sc, struct ohci_pipe *opipe, int ival)
/***********************/
#ifdef RHENIUM_NO_ISOC
usbd_status
ohci_device_isoc_transfer(usbd_xfer_handle xfer)
{
return (USBD_IOERROR);
}
void
ohci_device_isoc_enter(usbd_xfer_handle xfer)
{
}
usbd_status
ohci_device_isoc_start(usbd_xfer_handle xfer)
{
return (USBD_IOERROR);
}
void
ohci_device_isoc_abort(usbd_xfer_handle xfer)
{
}
void
ohci_device_isoc_done(usbd_xfer_handle xfer)
{
DPRINTFN(1,("ohci_device_isoc_done: xfer=%p\n", xfer));
// xfer->hcpriv = NULL;
}
usbd_status
ohci_setup_isoc(usbd_pipe_handle pipe)
{
return (USBD_IOERROR);
}
void
ohci_device_isoc_close(usbd_pipe_handle pipe)
{
}
#else /*RHENIUM_NO_ISOC*/
usbd_status
ohci_device_isoc_transfer(usbd_xfer_handle xfer)
{
......@@ -3683,3 +3769,4 @@ ohci_device_isoc_close(usbd_pipe_handle pipe)
#endif
ohci_free_sitd(sc, opipe->tail.itd);
}
#endif /*RHENIUM_NO_ISOC*/
......@@ -556,7 +556,7 @@ USB_DETACH(uhub)
DPRINTF(("uhub_detach: sc=%port\n", sc));
#endif
if (hub == NULL) /* Must be partially working */
if (hub == NULL || !sc->sc_ipipe) /* Must be partially working */
return (0);
usbd_abort_pipe(sc->sc_ipipe);
......
......@@ -151,12 +151,13 @@ void
usbd_dump_queue(usbd_pipe_handle pipe)
{
usbd_xfer_handle xfer;
logprintf("usbd_dump_queue: pipe=%p\n", pipe);
if(pipe)
{
SIMPLEQ_FOREACH(xfer, &pipe->queue, next) {
logprintf(" xfer=%p\n", xfer);
}
if(pipe)
{
SIMPLEQ_FOREACH(xfer, &pipe->queue, next) {
logprintf(" xfer=%p\n", xfer);
}
}
}
......@@ -265,19 +266,17 @@ usbd_close_pipe(usbd_pipe_handle pipe)
return (USBD_NORMAL_COMPLETION);
}
#endif
if(pipe)
{
if (--pipe->refcnt != 0)
return (USBD_NORMAL_COMPLETION);
if (! SIMPLEQ_EMPTY(&pipe->queue))
return (USBD_PENDING_REQUESTS);
LIST_REMOVE(pipe, next);
pipe->endpoint->refcnt--;
pipe->methods->close(pipe);
if (pipe->intrxfer != NULL)
usbd_free_xfer(pipe->intrxfer);
free(pipe, M_USB);
}
if (--pipe->refcnt != 0)
return (USBD_NORMAL_COMPLETION);
if (! SIMPLEQ_EMPTY(&pipe->queue))
return (USBD_PENDING_REQUESTS);
LIST_REMOVE(pipe, next);
pipe->endpoint->refcnt--;
pipe->methods->close(pipe);
if (pipe->intrxfer != NULL)
usbd_free_xfer(pipe->intrxfer);
free(pipe, M_USB);
return (USBD_NORMAL_COMPLETION);
}
......@@ -291,7 +290,7 @@ usbd_transfer(usbd_xfer_handle xfer)
int s;
DPRINTFN(5,("usbd_transfer: xfer=%p, flags=%d, pipe=%p, running=%d\n",
xfer, xfer->flags, pipe, pipe?pipe->running:0));
xfer, xfer->flags, pipe, pipe->running));
#ifdef USB_DEBUG
if (usbdebug > 5)
usbd_dump_queue(pipe);
......@@ -757,33 +756,34 @@ usbd_ar_pipe(usbd_pipe_handle pipe)
SPLUSBCHECK;
DPRINTFN(2,("usbd_ar_pipe: pipe=%p\n", pipe));
if(!pipe)
{
return (USBD_NORMAL_COMPLETION);
}
#ifdef USB_DEBUG
if (usbdebug > 5)
usbd_dump_queue(pipe);
#endif
if (pipe)
{
pipe->repeat = 0;
pipe->aborting = 1;
while ((xfer = SIMPLEQ_FIRST(&pipe->queue)) != NULL) {
DPRINTFN(2,("usbd_ar_pipe: pipe=%p xfer=%p (methods=%p)\n",
pipe, xfer, 0/*pipe->methods*/));
if (xfer == oxfer)
{
DPRINTF(("xfer hasn't changed: %p\n", SIMPLEQ_FIRST(&pipe->queue)));
break;
}
oxfer = xfer;
// usbdebug = 10;
/* Make the HC abort it (and invoke the callback). */
DPRINTF(("pipe %p\n", pipe));
pipe->methods->abort(xfer);
DPRINTF(("first now: %p\n", SIMPLEQ_FIRST(&pipe->queue)));
// usbdebug = 5;
/* XXX only for non-0 usbd_clear_endpoint_stall(pipe); */
}
pipe->aborting = 0;
}
pipe->repeat = 0;
pipe->aborting = 1;
while ((xfer = SIMPLEQ_FIRST(&pipe->queue)) != NULL) {
DPRINTFN(2,("usbd_ar_pipe: pipe=%p xfer=%p (methods=%p)\n",
pipe, xfer, pipe->methods));
if (xfer == oxfer)
{
DPRINTF(("xfer hasn't changed: %p\n", SIMPLEQ_FIRST(&pipe->queue)));
break;
}
oxfer = xfer;
// usbdebug = 10;
/* Make the HC abort it (and invoke the callback). */
pipe->methods->abort(xfer);
DPRINTF(("first now: %p\n", SIMPLEQ_FIRST(&pipe->queue)));
// usbdebug = 5;
/* XXX only for non-0 usbd_clear_endpoint_stall(pipe); */
}
pipe->aborting = 0;
return (USBD_NORMAL_COMPLETION);
}
......@@ -866,12 +866,16 @@ usb_transfer_complete(usbd_xfer_handle xfer)
[pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE];
xfer->done = 1;
if (!xfer->status && xfer->actlen < xfer->length &&
!(xfer->flags & USBD_SHORT_XFER_OK)) {
if (!xfer->status && xfer->actlen < xfer->length)
{
if (!(xfer->flags & USBD_SHORT_XFER_OK)) {
DPRINTFN(-1,("usbd_transfer_cb: short transfer %d<%d\n",
xfer->actlen, xfer->length));
xfer->status = USBD_SHORT_XFER;
}
else
xfer->status = USBD_SHORT_XFER_DONE;
}
if (xfer->callback)
xfer->callback(xfer, xfer->priv, xfer->status);
......@@ -966,7 +970,9 @@ usbd_start_next(usbd_pipe_handle pipe)
usbd_status
usbd_do_request(usbd_device_handle dev, usb_device_request_t *req, void *data)
{
return (usbd_do_request_flags(dev, req, data, 0, 0,
/* set flags to allow a short transfer, since some devices requires
this */
return (usbd_do_request_flags(dev, req, data, USBD_SHORT_XFER_OK /*0*/, 0,
USBD_DEFAULT_TIMEOUT));
}
......
/* $NetBSD: ehcireg.h,v 1.13 2001/11/23 01:16:27 augustss Exp $ */
/* $NetBSD: ehcireg.h,v 1.14 2003/10/13 00:05:10 enami Exp $ */
/*
* Copyright (c) 2001 The NetBSD Foundation, Inc.
......@@ -231,6 +231,7 @@ typedef struct {
#define EHCI_QTD_GET_TOGGLE(x) (((x) >> 31) & 0x1)
#define EHCI_QTD_TOGGLE 0x80000000
ehci_physaddr_t qtd_buffer[EHCI_QTD_NBUFFERS];
ehci_physaddr_t qtd_buffer_hi[EHCI_QTD_NBUFFERS];
} ehci_qtd_t;
#define EHCI_QTD_ALIGN 32
......
......@@ -522,7 +522,12 @@ typedef struct {
#define USB_EXTRA_POWER_UP_TIME 0 /* ms */
#else
/* Allow for marginal (i.e. non-conforming) devices. */
#define USB_PORT_RESET_DELAY 50 /* ms */
/* MUST allow sufficient time for power to really die! */
#ifdef RHENIUM
#define USB_PORT_RESET_DELAY 200 /* ms */
#else /*RHENIUM*/
#define USB_PORT_RESET_DELAY 100 /* ms */
#endif /*RHENIUM*/
#define USB_PORT_ROOT_RESET_DELAY 50 /* ms */
#define USB_PORT_RESET_RECOVERY 50 /* ms */
#define USB_PORT_POWERUP_DELAY 300 /* ms */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment