To have our Inferno to communicate with external world we need to have the USB supported as most important parts including ethernet controller and keyboard are behind the USB subsystem. I had a look what parts the Inferno already had for usb support and what was implemented in 9pi. So I decided just to compile-in the Plan9 usb support as devusb.c and usbdwc.c from 9pi. Fortunately due to sharing almost same API of syscalls, the devusb is compiled perfectly and usbdwc needed just two fixes.

Still we need some additions to have the sources compatible:

  1. There is a reference to ISAConf, add to dat.h from Plan9:
 1#define NISAOPT     8
 2
 3struct ISAConf {
 4   char    *type;
 5   ulong   port;
 6   int     irq;
 7   ulong   dma;
 8   ulong   mem;
 9   ulong   size;
10   ulong   freq;
11   int     nopt;
12   char    *opt[NISAOPT];
13};
  1. Several delays are required for USB functioning, clock.c:
 1ulong
 2µs(void)
 3{
 4   if(SystimerFreq != 1*Mhz)
 5       return fastticks2us(fastticks(nil));
 6   return fastticks(nil);
 7}
 8
 9void
10microdelay(int n)
11{
12   Systimers *tn;
13   u32int now, diff;
14
15   tn = (Systimers*)SYSTIMERS;
16   diff = n + 1;
17   now = tn->clo;
18   while(tn->clo - now < diff)
19       ;
20}
21
22void
23delay(int n)
24{
25   while(--n >= 0)
26       microdelay(1000);
27}
  1. Also ARMtimers are now in use, clock.c:
 1void
 2armtimerset(int n)
 3{
 4   Armtimer *tm;
 5
 6   tm = (Armtimer*)ARMTIMER;
 7   if(n > 0){
 8       tm->ctl |= TmrEnable|TmrIntEnable;
 9       tm->load = n;
10   }else{
11       tm->load = 0;
12       tm->ctl &= ~(TmrEnable|TmrIntEnable);
13       tm->irq = 1;
14   }
15}
  1. port/error.h needs several error defines:
1extern char Estalled[];        /* endpoint stalled */
2extern char Enotconf[];        /* endpoint not configured */
3extern char Edetach[];         /* device is detached */
  1. port/usb.h is copied from Plan9
  2. ASM splfhi() is needed:
1TEXT splfhi(SB), 1, $-4
2   MOVW    $(MACHADDR), R2     /* save caller pc in Mach */
3   MOVW    R14, 0(R2)
4   MOVW    CPSR, R0            /* turn off irqs and fiqs */
5   ORR $(PsrDirq|PsrDfiq), R0, R1
6   MOVW    R1, CPSR
7   RET
  1. Later on attempts of tracing some USB I found that we actually haven’t implemented Firq support, so also copy codes from 9pi and adjust intr.s:
 1/*
 2 * called direct from intr.s to handle fiq interrupt.
 3 */
 4void
 5fiq(Ureg *ureg)
 6{
 7   Vctl *v;
 8
 9   v = vfiq;
10   if(v == nil)
11       panic("unexpected item in bagging area");
12   m->intr++;
13   ureg->pc -= 4;
14   coherence();
15   v->f(ureg, v->a);
16   coherence();
17}
  1. To link usbdwc module with actually /dev/usb we need to add a link section to rpi file:
link
   usbdwc

Looks almost complete, what is needed as second step: implement Usbd in Limbo which give us fun expectations… ;)

Stay tuned!

FILES: