static void uartsetup(ulong port, char *name) { Uart *p; if(nuart >= Nuart) return; p = xalloc(sizeof(Uart)); uart[nuart++] = p; strcpy(p->name, name); p->reg = &UARTREG[port]; p->bps = 9600; p->bits = 8; p->parity = 'n'; p->stop = 1; p->kickme = 0; p->port = port; p->iq = qopen(4*1024, 0, 0 , p); p->oq = qopen(4*1024, 0, uartkick, p); p->ip = p->istage; p->ie = &p->istage[Stagesize]; p->op = p->ostage; p->oe = p->ostage; intrenable(UARTTXbit(port), uarttxintr, p, 0); intrenable(UARTRXbit(port), uartrxintr, p, 0); }
static SDev* viopnp(void) { SDev *s, *h, *t; Vdev *vd; int id; id = 'F'; h = t = nil; for(vd = viopnpdevs(2); vd; vd = vd->next){ if(vd->nqueue != 1) continue; intrenable(vd->pci->intl, viointerrupt, vd, vd->pci->tbdf, "virtio"); outb(vd->port+Status, inb(vd->port+Status) | DriverOk); if((s = malloc(sizeof(*s))) == nil) break; s->ctlr = vd; s->idno = id++; s->ifc = &sdvirtioifc; s->nunit = 1; if(h) t->next = s; else h = s; t = s; } return h; }
static void oxenable(Uart *uart, int) { Ctlr *ctlr; Port *port; port = uart->regs; ctlr = port->ctlr; ilock(ctlr); if(ctlr->im == 0) intrenable(ctlr->pcidev->intl, oxinterrupt, ctlr, ctlr->pcidev->tbdf, ctlr->name); ctlr->im |= MASK(port); iunlock(ctlr); /* Enable 950 Mode */ port->mem[Lcr] |= 1<<7; /* Divisor latch access */ port->mem[Efr] = 1<<4; /* Enhanced mode */ port->mem[Lcr] &= ~(1<<7); port->mem[Ier] = 1<<2|1<<1|1<<0; /* Rx Stat, THRE, RxRDY */ (*uart->phys->dtr)(uart, 1); (*uart->phys->rts)(uart, 1); /* Enable FIFO */ (*uart->phys->fifo)(uart, ~0); }
static void i8250enable(Uart* uart, int ie) { Ctlr *ctlr; /* * Enable interrupts and turn on DTR and RTS. * Be careful if this is called to set up a polled serial line * early on not to try to enable interrupts as interrupt- * -enabling mechanisms might not be set up yet. */ ctlr = uart->regs; if(ie){ if(ctlr->iena == 0){ intrenable(ctlr->irq, i8250interrupt, uart, ctlr->tbdf, uart->name); ctlr->iena = 1; } ctlr->sticky[Ier] = Ethre|Erda; ctlr->sticky[Mcr] |= Ie; } else{ ctlr->sticky[Ier] = 0; ctlr->sticky[Mcr] = 0; } csr8w(ctlr, Ier, ctlr->sticky[Ier]); csr8w(ctlr, Mcr, ctlr->sticky[Mcr]); (*uart->phys->dtr)(uart, 1); (*uart->phys->rts)(uart, 1); }
void i8042auxenable(void (*putc)(int, int)) { char *err = "i8042: aux init failed\n"; /* enable kbd/aux xfers and interrupts */ ccc &= ~Cauxdis; ccc |= Cauxint; ilock(&i8042lock); if(outready() < 0) print(err); outb(Cmd, 0x60); /* write control register */ if(outready() < 0) print(err); outb(Data, ccc); if(outready() < 0) print(err); outb(Cmd, 0xA8); /* auxilliary device enable */ if(outready() < 0){ iunlock(&i8042lock); return; } auxputc = putc; intrenable(IrqAUX, i8042intr, 0, BUSUNKNOWN, "kbdaux"); iunlock(&i8042lock); }
void clockinit(void) { Systimers *tn; Armtimer *tm; u32int t0, t1, tstart, tend; tn = (Systimers*)SYSTIMERS; tm = (Armtimer*)ARMTIMER; tm->load = 0; tm->ctl = TmrPrescale1|CntEnable|CntWidth32; tstart = tn->clo; do{ t0 = lcycles(); }while(tn->clo == tstart); tend = tstart + 10000; do{ t1 = lcycles(); }while(tn->clo != tend); t1 -= t0; m->cpuhz = 100 * t1; m->cpumhz = (m->cpuhz + Mhz/2 - 1) / Mhz; m->cyclefreq = m->cpuhz; tn->c3 = tn->clo - 1; intrenable(IRQtimer3, clockintr, nil, 0, "clock"); }
void gpioinit(void) { boardrev = getboardrev() & 0xff; pinscheme = Qboard; intrenable(49, interrupt, nil, 0, "gpio1"); }
void clockinit(void) { TimerReg *tr; IntrReg *ir; ulong l, u; m->ticks = 0; tr = TIMERREG; tr->enable = 0; tr->pulse1 = 1; /* first tune the delay loop parameter (using a search because the counter doesn't decrement) */ ir = INTRREG; tr->count1 = Mclk/1000 - tr->pulse1; /* millisecond */ u = m->cpuhz/(2*1000); /* over-large estimate for a millisecond */ l = 10000; while(l+1 < u){ m->delayloop = l + (u-l)/2; ir->st = 1<<IRQtm1; /* reset edge */ tr->enable = 1<<1; delay(1); tr->enable = 0; if(ir->st & (1<<IRQtm1)) u = m->delayloop; else l = m->delayloop; } intrenable(IRQ, IRQtm1, clockintr, nil, "timer.1"); tr->count1 = Mclk/HZ - tr->pulse1; tr->enable = 1<<1; /* enable only Timer 1 */ }
void mathinit(void) { trapenable(VectorCERR, matherror, 0, "matherror"); if(X86FAMILY(m->cpuidax) == 3) intrenable(IrqIRQ13, matherror, 0, BUSUNKNOWN, "matherror"); trapenable(VectorCNA, mathemu, 0, "mathemu"); trapenable(VectorCSO, mathover, 0, "mathover"); }
void timerenable( int timer, int Hz, void (*f)(Ureg *, void*), void* a) { TimerReg *t = TIMERREG; if ((timer < 0) || (timer > 1)) return; timerdisable(timer); timer_incr[timer] = TIMER_HZ/Hz; /* set up freq */ t->data[timer] = timer_incr[timer]; ENABLE(t, timer); intrenable(TIMERbit(timer), f, a, 0); }
void llfifoinit(Ether *ether) { llether = ether; frp->ier = 0; frp->isr = frp->isr; /* extinguish intr source */ coherence(); intrenable(Intllfifo, llfifointr); coherence(); frp->ier = Rc | Tc; coherence(); }
static void i2cinit(void) { i2c.regs = (Bsc*)I2CREGS; i2c.regs->clkdiv = 2500; gpiosel(SDA0Pin, Alt0); gpiosel(SCL0Pin, Alt0); gpiopullup(SDA0Pin); gpiopullup(SCL0Pin); intrenable(IRQi2c, i2cinterrupt, 0, 0, "i2c"); }
void clockinit(void) { Systimers *tn; Armtimer *tm; u32int t0, t1, tstart, tend; if(((cprdsc(0, CpID, CpIDfeat, 1) >> 16) & 0xF) != 0) { /* generic timer supported */ if(m->machno == 0){ *(ulong*)(ARMLOCAL + Localctl) = 0; /* magic */ *(ulong*)(ARMLOCAL + Prescaler) = 0x06aaaaab; /* magic for 1 Mhz */ } cpwrsc(0, CpTIMER, CpTIMERphys, CpTIMERphysctl, Imask); } tn = (Systimers*)SYSTIMERS; tstart = tn->clo; do{ t0 = lcycles(); }while(tn->clo == tstart); tend = tstart + 10000; do{ t1 = lcycles(); }while(tn->clo != tend); t1 -= t0; m->cpuhz = 100 * t1; m->cpumhz = (m->cpuhz + Mhz/2 - 1) / Mhz; m->cyclefreq = m->cpuhz; if(m->machno == 0){ tn->c3 = tn->clo - 1; tm = (Armtimer*)ARMTIMER; tm->load = 0; tm->ctl = TmrPrescale1|CntEnable|CntWidth32; intrenable(IRQtimer3, clockintr, nil, 0, "clock"); }else intrenable(IRQcntpns, localclockintr, nil, 0, "clock"); }
void timerinit(void) { *(ushort*)Timer_ctrl = 0; *(ulong*)Timer0_load = m->bushz / HZ; *(ulong*)Timer0_cnt = m->bushz / HZ; *(ulong*)Timer1_load = m->bushz; *(ulong*)Timer1_cnt = m->bushz; intrenable(Vectimer0, saturntimerintr, nil, "timer"); timer_ctl = T0_cen|T0_ie|T1_cen; *(ushort*)Timer_ctrl = timer_ctl; }
static void pitreset(void) { IMM *io; io = ioplock(); io->piscrk = KEEP_ALIVE_KEY; io->piscr = (PITlevel<<8) | PS | PITF; if(0) io->piscrk = ~KEEP_ALIVE_KEY; /* piscrk is left unlocked for interrupt routine */ iopunlock(); intrenable(PITlevel, pitinterrupt, nil, BUSUNKNOWN, "pit"); }
void kbdenable(void) { if(kbdq == nil){ kbdq = qopen(4*1024, 0, 0, 0); if(kbdq == nil) panic("kbdinit"); qnoblock(kbdq, 1); } ioalloc(Data, 1, 0, "kbd"); ioalloc(Cmd, 1, 0, "kbd"); intrenable(IrqKBD, i8042intr, 0, BUSUNKNOWN, "kbd"); }
static void ks8695_enable(Uart* uart, int ie) { Ctlr *ctlr; ctlr = uart->regs; /* * Enable interrupts and turn on DTR and RTS. * Be careful if this is called to set up a polled serial line * early on not to try to enable interrupts as interrupt- * -enabling mechanisms might not be set up yet. */ if(ctlr->iena == 0 && ie){ intrenable(IRQ, ctlr->irq, ks8695_txintr, uart, uart->name); intrenable(IRQ, ctlr->irq+1, ks8695_rxintr, uart, uart->name); intrenable(IRQ, ctlr->irq+2, ks8695_rxintr, uart, uart->name); intrenable(IRQ, ctlr->irq+3, ks8695_modemintr, uart, uart->name); ctlr->iena = 1; } (*uart->phys->dtr)(uart, 1); (*uart->phys->rts)(uart, 1); }
void timerenable( int timer, int Hz, void (*f)(Ureg *, void*), void* a) { OstmrReg *ost = OSTMRREG; char name[KNAMELEN]; if(timer < 0 || timer > 3) return; timer_incr[timer] = CLOCKFREQ/Hz; /* set up freq */ ost->osmr[timer] = ost->oscr+timer_incr[timer]; snprint(name, sizeof(name), "timer%d", timer); intrenable(IRQ, IRQtimer0+timer, f, a, name); ost->ossr = (1 << timer); /* clear any pending interrupt */ ost->oier |= (1 << timer); /* enable interrupt */ }
static void sdioenable(void) { u32int *r; r = (u32int*)AddrSdio; WR(Clockdiv, clkdiv(Clkfreq/Initfreq - 1)); delay(10); WR(Clockctl, r[Clockctl] & ~Sdclken); WR(Hostctl, Pushpullen|Bigendian|Cardtypemem); WR(Irpten, 0); WR(Interrupt, ~0); WR(ErrIntr, ~0); WR(Irptmask, ~0); WR(ErrIrptmask, ~Dtoerr); intrenable(Irqlo, IRQ0sdio, sdiointerrupt, &ctlr, "sdio"); }
static Chan* acpiattach(char *spec) { int i; /* * This was written for the stock kernel. * This code must use 64 registers to be acpi ready in nix. */ if(1 || acpiinit() < 0) error("no acpi"); /* * should use fadt->xpm* and fadt->xgpe* registers for 64 bits. * We are not ready in this kernel for that. */ DBG("acpi io alloc\n"); acpiioalloc(fadt.smicmd, 1); acpiioalloc(fadt.pm1aevtblk, fadt.pm1evtlen); acpiioalloc(fadt.pm1bevtblk, fadt.pm1evtlen ); acpiioalloc(fadt.pm1acntblk, fadt.pm1cntlen); acpiioalloc(fadt.pm1bcntblk, fadt.pm1cntlen); acpiioalloc(fadt.pm2cntblk, fadt.pm2cntlen); acpiioalloc(fadt.pmtmrblk, fadt.pmtmrlen); acpiioalloc(fadt.gpe0blk, fadt.gpe0blklen); acpiioalloc(fadt.gpe1blk, fadt.gpe1blklen); DBG("acpi init gpes\n"); initgpes(); /* * This starts ACPI, which may require we handle * power mgmt events ourselves. Use with care. */ DBG("acpi starting\n"); outb(fadt.smicmd, fadt.acpienable); for(i = 0; i < 10; i++) if(getpm1ctl() & Pm1SciEn) break; if(i == 10) error("acpi: failed to enable\n"); if(fadt.sciint != 0) intrenable(fadt.sciint, acpiintr, 0, BUSUNKNOWN, "acpi"); return devattach(L'α', spec); }
static void gtimerinit(int i, ushort *tmr, ushort *ter) { GTimer *t; char name[KNAMELEN]; snprint(name, sizeof(name), "timer.%d", i); t = &cpmtimers.t[i]; t->x = i*4; /* field in tgcr */ t->inuse = 0; t->interrupt = nil; t->tmr = tmr; t->trr = tmr+2; t->tcr = tmr+4; t->tcn = tmr+6; t->ter = ter; intrenable(VectorCPIC+timerirq[i], gtimerintr, t, BUSUNKNOWN, name); }
void dmainit(void) { int n; char name[16]; Dchan *cp; Regs *regs = (Regs *)PHYSSDMA; if (probeaddr((uintptr)®s->syssts) < 0) panic("dmainit: no syssts reg"); regs->syssts = 0; coherence(); regs->syscfg |= 1<<1; /* Softreset */ coherence(); while(!(regs->syssts & (1<<0))) /* Resetdone? */ ; for (n = 0; n < Nchan; n++) { cp = regs->chan + n; cp->ccr = 0; cp->clnkctrl = 0; cp->cicr = 0; cp->csr = 0; cp->csdp = 0; cp->cen = cp->cfn = 0; cp->cssa = cp->cdsa = 0; cp->csei = cp->csfi = 0; cp->cdei = cp->cdfi = 0; // cp->csac = cp->cdac = 0; // ro cp->ccen = cp->ccfn = 0; cp->color = 0; } zerowds((void *)regs->irqsts, sizeof regs->irqsts / sizeof(ulong)); zerowds((void *)regs->irqen, sizeof regs->irqen / sizeof(ulong)); coherence(); regs->gcr = 65; /* burst size + 1 */ coherence(); for (n = 0; n < Nirq; n++) { snprint(name, sizeof name, "dma%d", n); intrenable(Baseirq + n, dmaintr, (void *)n, nil, name); } }
void trapinit(void) { /* * Need to set BPT interrupt gate - here or in vsvminit? */ /* * Special traps. * Syscall() is called directly without going through trap(). */ trapenable(VectorBPT, debugbpt, 0, "#BP"); trapenable(VectorPF, faultamd64, 0, "#PF"); trapenable(Vector2F, doublefault, 0, "#DF"); intrenable(IdtIPI, expected, 0, BUSUNKNOWN, "#IPI"); trapenable(Vector15, unexpected, 0, "#15"); nmienable(); addarchfile("irqalloc", 0444, irqallocread, nil); }
/* * called by the reset routine of any driver using the IIC */ void i2csetup(int polling) { IICregs *iic; Ctlr *ctlr; ctlr = iicctlr; ctlr->polling = polling; iic = (IICregs*)KADDR(PHYSIIC); ctlr->regs = iic; if(!polling) { if(ctlr->init == 0) { initialise(iic, Eihe | Eiic | Eita | Eimtc); ctlr->init = 1; intrenable(VectorIIC, interrupt, iicctlr, BUSUNKNOWN, "iic"); } } else initialise(iic, 0); }
static void emmcenable(void) { u32int *r; int i; r = (u32int*)EMMCREGS; WR(Control1, clkdiv(emmc.extclk/Initfreq - 1) | DTO<<Datatoshift | Clkgendiv | Clken | Clkintlen); for(i = 0; i < 1000; i++){ delay(1); if(r[Control1] & Clkstable) break; } if(i == 1000) print("SD clock won't initialise!\n"); WR(Irptmask, ~(Dtoerr|Cardintr)); intrenable(IRQmmc, mmcinterrupt, nil, 0, "mmc"); }
static void axpenable(Uart* uart, int ie) { Cc *cc; Ctlr *ctlr; u16int lp; cc = uart->regs; ctlr = cc->ctlr; /* * Enable interrupts and turn on DTR and RTS. * Be careful if this is called to set up a polled serial line * early on not to try to enable interrupts as interrupt- * -enabling mechanisms might not be set up yet. */ if(ie){ /* * The Uart is qlocked. */ if(ctlr->im == 0){ intrenable(ctlr->pcidev->intl, axpinterrupt, ctlr, ctlr->pcidev->tbdf, ctlr->name); csr32w(ctlr, Ics, 0x00031F00); csr32w(ctlr, Pdb, 1); ctlr->gcb->gcw2 = 1; } ctlr->im |= 1<<cc->uartno; } (*uart->phys->dtr)(uart, 1); (*uart->phys->rts)(uart, 1); /* * Make sure we control RTS, DTR and break. */ lp = cc->ccb->lp; cc->ccb->lp = Emcs|lp; cc->ccb->oblw = 64; axpcc(cc, Et|Er|Ccu); }
/* * called by the reset routine of any driver using the IIC */ void i2csetup(int polling) { I2Cregs *i2c; Ctlr *ctlr; ctlr = i2cctlr; ctlr->polling = polling; i2c = KADDR(PHYSI2C); ctlr->regs = i2c; if(!polling){ if(ctlr->init == 0){ initialise(i2c, 1); ctlr->init = 1; intrenable(IRQ, IRQi2c, interrupt, i2cctlr, "i2c"); if(Chatty) i2cdump("init", i2c); } }else initialise(i2c, 0); }
void kbdinit(void) { int c; kbdq = qopen(4*1024, 0, 0, 0); if(kbdq == nil) panic("kbdinit"); qnoblock(kbdq, 1); ioalloc(Data, 1, 0, "kbd"); ioalloc(Cmd, 1, 0, "kbd"); intrenable(IrqKBD, i8042intr, 0, BUSUNKNOWN, "kbd"); /* wait for a quiescent controller */ while((c = inb(Status)) & (Outbusy | Inready)) if(c & Inready) inb(Data); /* get current controller command byte */ outb(Cmd, 0x20); if(inready() < 0){ print("kbdinit: can't read ccc\n"); ccc = 0; } else ccc = inb(Data); /* enable kbd xfers and interrupts */ /* disable mouse */ ccc &= ~Ckbddis; ccc |= Csf | Ckbdint | Cscs1; if(outready() < 0) print("kbd init failed\n"); outb(Cmd, 0x60); if(outready() < 0) print("kbd init failed\n"); outb(Data, ccc); outready(); }
static void enable(Uart *uart, int ie) { u32int *ap; ap = (u32int*)uart->regs; delay(10); gpiofuncset(TxPin, Alt5); gpiofuncset(RxPin, Alt5); gpiopullset(TxPin, 0); gpiopullset(RxPin, 0); ap[Enables] |= UartEn; ap[MuIir] = 6; ap[MuLcr] = Bits8; ap[MuCntl] = TxEn|RxEn; ap[MuBaud] = uart->freq/(115200*8) - 1; if(ie){ intrenable(IRQaux, interrupt, uart, 0, "uart"); ap[MuIer] = RxIen|TxIen; }else ap[MuIer] = 0; }
void powerinit(void) { extern ulong power_magic; extern ulong power_code; extern ulong doze_code; ulong *p, *q, i; p = (ulong*)(((ulong)&power_magic + 0x1f) & ~0x1f); q = &power_code; for (i = 0; i < 8; i++) *p++ = *q++; p = (ulong*)(((ulong)doze + 0x3f) & ~0x1f); q = &doze_code; for (i = 0; i < 3; i++) *p++ = *q++; *resumeaddr = (ulong) power_resume; addclock0link(blanktimer, 1000/HZ); addclock0link(suspendtimer, 1000/HZ); intrenable(GPIOrising, bitno(GPIO_PWR_ON_i), onoffintr, nil, "on/off"); }