M bitsy/devuda1341.c => bitsy/devuda1341.c +40 -18
@@ 132,6 132,7 @@ struct Buf
struct IOstate
{
QLock;
+ Lock ilock;
Rendez vous;
Chan *chan; /* chan of open */
int dma; /* dma chan, alloc on open, free on close */
@@ 435,15 436,17 @@ audioenable(void)
L3_init();
/* Setup the uarts */
- ppcregs->assignment &= ~(1<<18); /* Could be the other way round! */
+ ppcregs->assignment &= (1<<18); /* Could be the other way round! */
gpioregs->altfunc &= ~(GPIO_SSP_TXD_o | GPIO_SSP_RXD_i | GPIO_SSP_SCLK_o | GPIO_SSP_SFRM_o);
gpioregs->altfunc |= (GPIO_SSP_CLK_i);
gpioregs->direction &= ~(GPIO_SSP_CLK_i);
- sspregs->control0 = 0x10<<0 | 0x1<<4 | 1<<7 | 0x8<<8;
+ sspregs->control0 = 0xf<<0 | 0x1<<4 | 0x3<<8;
sspregs->control1 = 0<<3 + 0<<4 + 1<<5;
+ sspregs->control0 |= 1<<7; /* enable */
+
/* Enable the audio power */
audiopower(1);
amplifierpower(1);
@@ 458,12 461,14 @@ audioenable(void)
delay(100);
print("Ser4SSSR=0x%lux\n", sspregs->status);
+ gpioregs->clear = EGPIO_codec_reset;
+ gpioregs->set = EGPIO_codec_reset;
+
/* Reset the chip */
data[0] = 2<<4 /* system clock */ | 1<<1 /* lsb16 */ | 1<<6 /* reset */;
L3_write(UDA1341_L3Addr<<2 | UDA1341_STATUS, data, 1 );
- gpioregs->clear = EGPIO_codec_reset;
- gpioregs->set = EGPIO_codec_reset;
+ delay(10);
data[0] = 2<<4 /* system clock */ | 1<<1 /* lsb16 */;
L3_write( (UDA1341_L3Addr<<2)|UDA1341_STATUS, data, 1 );
@@ 496,22 501,38 @@ audioenable(void)
data[1] = 0xe0 | 0<<2 | 3; /* agc time constant and output level */
L3_write(UDA1341_L3Addr<<2 | UDA1341_DATA0, data, 2 );
+ /* Reset the chip */
+ data[0] = 2<<4 /* system clock */ | 1<<1 /* lsb16 */ | 1<<6 /* reset */;
+ L3_write(UDA1341_L3Addr<<2 | UDA1341_STATUS, data, 1 );
+
+ delay(10);
+
+ data[0] = 2<<4 /* system clock */ | 1<<1 /* lsb16 */;
+ L3_write( (UDA1341_L3Addr<<2)|UDA1341_STATUS, data, 1 );
+ /* Reset done */
+
if (debug) print("#A: audio enabled\n");
}
static void
sendaudio(IOstate *b) {
- /* call this with lock held */
- if (debug) print("#A: sendaudio\n");
+ /* interrupt routine calls this too */
+ if (debug > 1) print("#A: sendaudio\n");
+ ilock(&b->ilock);
while (b->next != b->filling) {
assert(b->next->nbytes);
- if (dmastart(b->dma, b->next->virt, b->next->nbytes) == 0)
- break;
incref(&b->active);
+ if (dmastart(b->dma, b->next->virt, b->next->nbytes) == 0) {
+ decref(&b->active);
+ break;
+ }
+ if (debug > 1) print("#A: dmastart @%p\n", b->next);
+ b->next->nbytes = 0;
b->next++;
if (b->next == &b->buf[Nbuf])
b->next = &b->buf[0];
}
+ iunlock(&b->ilock);
}
static void
@@ 519,16 540,13 @@ audiointr(void *x, ulong) {
IOstate *s = x;
if (s == &audio.o) {
- decref(&s->active);
/* Only interrupt routine touches s->current */
- s->current->nbytes = 0;
+ if (debug > 1) iprint("#A: audio interrupt @%p\n", s->current);
s->current++;
if (s->current == &s->buf[Nbuf])
s->current = &s->buf[0];
- if (canlock((Lock*)s)) {
- sendaudio(s);
- unlock((Lock*)s);
- }
+ decref(&s->active);
+ sendaudio(s);
}
wakeup(&s->vous);
}
@@ 598,8 616,8 @@ audioopen(Chan *c, int omode)
audio.o.chan = c;
audio.o.dma = dmaalloc(0, 0, 8, 2, SSPXmitDMA, Port4SSP, audiointr, (void*)&audio.o);
}
- qunlock(&audio);
// mxvolume();
+ qunlock(&audio);
if (debug) print("#A: open done\n");
break;
}
@@ 626,6 644,7 @@ audioclose(Chan *c)
break;
case Qaudio:
+ if (debug > 1) print("#A: close\n");
if(c->flag & COPEN) {
qlock(&audio);
qlock(&audio.o);
@@ 638,7 657,7 @@ audioclose(Chan *c)
/* closing the write end */
audio.amode &= ~Awrite;
- while (audio.o.filling->nbytes) {
+ if (audio.o.filling->nbytes) {
audio.o.filling++;
if (audio.o.filling == &audio.o.buf[Nbuf])
audio.o.filling = &audio.o.buf[0];
@@ 827,7 846,7 @@ audiowrite(Chan *c, void *vp, long n, vlong)
break;
case Qaudio:
- if (debug) print("#A: write %ld\n", n);
+ if (debug > 1) print("#A: write %ld\n", n);
if((audio.amode & Awrite) == 0)
error(Emode);
a = &audio.o;
@@ 838,8 857,10 @@ audiowrite(Chan *c, void *vp, long n, vlong)
}
while(n > 0) {
/* wait if dma in progress */
- while (a->active.ref && a->filling == a->current)
+ while (a->active.ref && a->filling == a->current) {
+ if (debug > 1) print("#A: sleep\n");
sleep(&a->vous, audioqnotfull, a);
+ }
m = Bufsize - a->filling->nbytes;
if(m > n)
@@ 850,6 871,7 @@ audiowrite(Chan *c, void *vp, long n, vlong)
n -= m;
p += m;
if(a->filling->nbytes >= Bufsize) {
+ if (debug > 1) print("#A: filled @%p\n", a->filling);
a->filling++;
if (a->filling == &a->buf[Nbuf])
a->filling = a->buf;
M bitsy/sa1110dma.c => bitsy/sa1110dma.c +50 -46
@@ 41,7 41,8 @@ enum {
};
typedef struct DMAchan {
- int inuse;
+ int allocated;
+ Ref active;
Rendez r;
void (*intr)(void*, ulong);
void *param;
@@ 71,6 72,8 @@ dmainit(void) {
/* map the lcd regs into the kernel's virtual space */
dmaregs = (struct dmaregs*)mapspecial(DMAREGS, NDMA*sizeof(struct dmaregs));;
+ if (debug) print("dma: dmaalloc registers 0x%ux mapped at 0x%p\n",
+ DMAREGS, dmaregs);
for (i = 0; i < NDMA; i++) {
intrenable(IRQdma0+i, dmaintr, &dmaregs[i], "DMA");
}
@@ 79,23 82,26 @@ dmainit(void) {
int
dmaalloc(int rd, int bigendian, int burstsize, int datumsize, int device, ulong port, void (*intr)(void*, ulong), void *param) {
int i;
+ ulong ddar;
- if (debug) print("dma: dmaalloc\n");
lock(&dma);
for (i = 0; i < NDMA; i++) {
- if (dma.chan[i].inuse)
+ if (dma.chan[i].allocated)
continue;
- dma.chan[i].inuse++;
+ dma.chan[i].allocated++;
unlock(&dma);
- dmaregs[i].ddar =
+ ddar =
(rd?1:0)<<RW |
(bigendian?1:0)<<E |
((burstsize==8)?1:0)<<BS |
((datumsize==2)?1:0)<<DW |
device<<DS |
0x80000000 | ((ulong)port << 6);
+ dmaregs[i].ddar = ddar;
+ if (debug) print("dma: dmaalloc: 0x%lux\n", ddar);
dma.chan[i].intr = intr;
dma.chan[i].param = param;
+ dmaregs[i].dcsr_clr = 0xff;
return i;
}
unlock(&dma);
@@ 104,68 110,58 @@ dmaalloc(int rd, int bigendian, int burstsize, int datumsize, int device, ulong
void
dmafree(int i) {
- dma.chan[i].inuse = 0;
+ dma.chan[i].allocated = 0;
dma.chan[i].intr = nil;
}
-static int
-dmaready(void *dcsr) {
- return *(int*)dcsr & ((1<<DONEA)|(1<<DONEB));
-}
-
ulong
dmastart(int chan, void *addr, int count) {
ulong status;
- if (debug) print("dma: dmastart\n");
- if (((status = dmaregs[chan].dcsr_rd) & ((1<<DONEA)|(1<<DONEB))) == 0)
+ status = dmaregs[chan].dcsr_rd;
+ if (debug > 1) print("dma: dmastart 0x%lux\n", status);
+
+ if (dma.chan[chan].active.ref >= 2) {
+ if (debug > 1) print("\n");
return 0;
+ }
+
+ if ((status & (1<<DONEA|1<<DONEB|1<<RUN)) == 1<<RUN)
+ panic("dmastart called while busy");
cachewbregion((ulong)addr, count);
if ((status & (1<<BIU | 1<<STRTB)) == (1<<BIU | 1<<STRTB) ||
- (status & (1<<BIU | 1<<STRTA)) == (1<<STRTA)) {
- dmaregs[chan].dcsr_clr |= 1<<DONEA | 1<<STRTA;
+ (status & (1<<BIU | 1<<STRTA)) == 0) {
+ dmaregs[chan].dcsr_clr = 1<<DONEA | 1<<STRTA;
dmaregs[chan].dstrtA = addr;
dmaregs[chan].dxcntA = count-1;
- dmaregs[chan].dcsr_set |= 1<<RUN | 1<<IE | 1<<STRTA;
+ incref(&dma.chan[chan].active);
+ dmaregs[chan].dcsr_set = 1<<RUN | 1<<IE | 1<<STRTA;
return 1<<DONEA;
} else {
- dmaregs[chan].dcsr_clr |= 1<<DONEB | 1<<STRTB;
+ dmaregs[chan].dcsr_clr = 1<<DONEB | 1<<STRTB;
dmaregs[chan].dstrtB = addr;
dmaregs[chan].dxcntB = count-1;
- dmaregs[chan].dcsr_set |= 1<<RUN | 1<<IE | 1<<STRTB;
+ incref(&dma.chan[chan].active);
+ dmaregs[chan].dcsr_set = 1<<RUN | 1<<IE | 1<<STRTB;
return 1<<DONEB;
}
}
-ulong
-dmadone(int chan, ulong op) {
- ulong dcsr;
-
- dcsr = dmaregs[chan].dcsr_rd;
- if (dcsr & 1<<ERROR)
- pprint("DMA error, chan %d, status 0x%lux\n", chan, dcsr);
- return dcsr & (op | 1<<ERROR);
-}
-
int
dmaidle(int chan) {
- ulong dcsr;
+ return dma.chan[chan].active.ref == 0;
+}
- dcsr = dmaregs[chan].dcsr_rd;
- if (dcsr & 1<<ERROR)
- pprint("DMA error, chan %d, status 0x%lux\n", chan, dcsr);
- return (dcsr & (1<<DONEA | 1<<DONEB)) == (1<<DONEA | 1<<DONEB);
+static int
+_dmaidle(void* chan) {
+ return dma.chan[(int)chan].active.ref == 0;
}
void
-dmawait(int chan, ulong op) {
- ulong dcsr;
-
- while (((dcsr = dmaregs[chan].dcsr_rd) & (op | 1<<ERROR)) == 0)
- sleep(&dma.chan[chan].r, dmaready, &dmaregs[chan].dcsr_rd);
- if (dcsr & 1<<ERROR)
- pprint("DMA error, chan %d, status 0x%lux\n", chan, dcsr);
+dmawait(int chan) {
+ while (dma.chan[chan].active.ref)
+ sleep(&dma.chan[chan].r, _dmaidle, (void*)chan);
}
/*
@@ 176,14 172,22 @@ dmaintr(Ureg*, void *x)
{
int i;
struct dmaregs *regs = x;
- ulong dcsr;
+ ulong dcsr, donebit;
- if (debug) print("dma: interrupt\n");
i = regs - dmaregs;
- if ((dcsr = regs->dcsr_rd) & (1<<DONEA | 1<<DONEB | 1<<ERROR)) {
- wakeup(&dma.chan[i].r);
+ dcsr = regs->dcsr_rd;
+ if (debug > 1)
+ iprint("dma: interrupt channel %d, status 0x%lux\n", i, dcsr);
+ if (dcsr & 1<<ERROR)
+ iprint("error, channel %d, status 0x%lux\n", i, dcsr);
+ donebit = 1<<((dcsr&1<<BIU)?DONEA:DONEB);
+ if (dcsr & donebit) {
+ regs->dcsr_clr |= donebit;
if (dma.chan[i].intr)
- (*dma.chan[i].intr)(dma.chan[i].param, dcsr);
+ (*dma.chan[i].intr)(dma.chan[i].param, 3-dma.chan[i].active.ref);
+ /* must call interrupt routine before calling decref */
+ decref(&dma.chan[i].active);
+ wakeup(&dma.chan[i].r);
} else
- print("spurious DMA interrupt, channel %d, status 0x%lux\n", i, dcsr);
+ iprint("spurious DMA interrupt, channel %d, status 0x%lux\n", i, dcsr);
}
M bitsy/sa1110dma.h => bitsy/sa1110dma.h +4 -3
@@ 10,7 10,8 @@ enum {
void dmainit(void);
int dmaalloc(int, int, int, int, int, ulong, void (*)(void*, ulong), void*);
void dmafree(int);
+
ulong dmastart(int, void *, int);
-ulong dmadone(int, ulong);
-void dmawait(int, ulong);
-int dmaidle(int chan);
+
+void dmawait(int);
+int dmaidle(int);
M pc/devi82365.c => pc/devi82365.c +2 -2
@@ 661,14 661,14 @@ i82365reset(void)
/* look for controllers if the ports aren't already taken */
if(ioalloc(0x3E0, 2, 0, "i82365.0") >= 0){
- i82365probe(0x3E0, 0x3E1, 0);
+ i82365probe(0x3E0, 0x3E1, 0) ||
i82365probe(0x3E0, 0x3E1, 1);
if(ncontroller == 0)
iofree(0x3E0);
}
if(ioalloc(0x3E2, 2, 0, "i82365.1") >= 0){
i = ncontroller;
- i82365probe(0x3E2, 0x3E3, 0);
+ i82365probe(0x3E2, 0x3E3, 0) ||
i82365probe(0x3E2, 0x3E3, 1);
if(ncontroller == i)
iofree(0x3E2);
M port/latin1.h => port/latin1.h +2 -2
@@ 57,7 57,7 @@
"P", "P", L"ℙ",
"Q", "Q", L"ℚ",
"R", "R", L"ℝ",
- "S", "S", L"§",
+ "S", "123S", L"¹²³§",
"T", "-u", L"Ŧ⊨",
"V", "=", L"⇐",
"Y", "R", L"Ʀ",
@@ 85,7 85,7 @@
"o", "AOUaeiu", L"Å⊚Ůåœƣů",
"p", "Odgrt", L"℗∂¶∏∝",
"r", "\"\'O", L"”’®",
- "s", "()+-0123456789=abnoprstu", L"⁽⁾⁺⁻⁰¹²³⁴⁵⁶⁷⁸⁹⁼ª⊂ⁿº⊃√ß∍∑",
+ "s", "()+-0123456789=abnoprstu", L"⁽⁾⁺⁻⁰ⁱ⁴⁵⁶⁷⁸⁹⁼ª⊂ⁿº⊃√ß∍∑",
"t", "-efmsu", L"ŧ∃∴™ς⊢",
"u", "-AEGIOUaegiou", L"ʉĂĔĞĬŎŬ↑ĕğĭŏŭ",
"v\"", "Uu", L"Ǚǚ",