M carrera/trap.c => carrera/trap.c +21 -7
@@ 296,9 296,28 @@ seteisadma(int ch, void (*func)(void))
}
void
-intr(Ureg *ur)
+eisadmaintr(void)
{
int i;
+ uchar isr;
+ void (*f)(void);
+
+ isr = EISAINB(Eisadmaintr) & ~(1<<4);
+ for(i = 0; i < 8; i++) {
+ if(isr & 1) {
+ f = eisadma[i];
+ if(f == 0)
+ print("EISAdma%d: stray intr %.2ux\n", i, isr);
+ else
+ f();
+ }
+ isr >>= 1;
+ }
+}
+
+void
+intr(Ureg *ur)
+{
static uchar devint;
ulong cause = ur->cause;
ulong isr, vec;
@@ 368,12 387,7 @@ intr(Ureg *ur)
mpegintr();
break;
case 13:
- isr = EISAINB(Eisadmaintr) & ~(1<<4);
- for(i = 0; i < 8; i++) {
- if(isr & 1)
- eisadma[i]();
- isr >>= 1;
- }
+ eisadmaintr();
break;
}
cause &= ~INTR4;
M port/qio.c => port/qio.c +15 -3
@@ 375,15 375,26 @@ long
qread(Queue *q, void *vp, int len)
{
Block *b;
- int n, dowakeup;
+ int n, dowakeup, syncwait;
uchar *p = vp;
qlock(&q->rlock);
+ syncwait = 0;
if(waserror()){
/* can't let go if the buffer is in use */
- if(q->syncbuf){
+ if(syncwait){
qlock(&q->wlock);
ilock(q);
+ if(q->syncbuf == 0){
+ /* we got some data before the interrupt, queue it */
+ b = allocb(q->synclen);
+ memmove(b->wp, vp, q->synclen);
+ b->wp += q->synclen;
+ if(q->bfirst == 0)
+ q->blast = b;
+ q->bfirst = b;
+ q->len += q->synclen;
+ }
q->syncbuf = 0;
iunlock(q);
qunlock(&q->wlock);
@@ 415,10 426,11 @@ qread(Queue *q, void *vp, int len)
q->synclen = len;
q->syncbuf = vp;
iunlock(q);
+ syncwait = 1; USED(syncwait);
sleep(&q->rr, filled, q);
len = q->synclen;
- poperror();
qunlock(&q->rlock);
+ poperror();
return len;
} else {
q->state |= Qstarve;