/* midi.c */ #define VPIX 1 #include #include #include #include #include #include #include #include #include #include #include #ifdef VPIX #include "sys/immu.h" #include "sys/region.h" #include "sys/proc.h" #include "sys/tss.h" #include "sys/v86.h" #include static struct proc *ectproc; static int vpix; #endif /* VPIX */ /* BUFSIZ is the size of the buffers obtained from geteblk(). Is there */ /* a #define elsewhere that gives this value? (besides stdio.h) */ #define BUFSIZ 1024 #define CIRCLESIZE (BUFSIZ*MIDI_BUFS) #define controller(dev) (minor(dev)) #define DATA_READY 0x40 #define DATA_AVAILABLE 0x80 #define RESET 0xff #define UART 0x3f /* note that active sensing and ACK from controller are the same */ #define ACK 0xfe #define ACTIVE 0xfe #define TRUE 1 #define FALSE 0 #define midi_putdata(ctlr,c) (outb(ctlr_to_data_port[ctlr],(c))) #define midi_putcmd(ctlr,c) (outb(ctlr_to_status_port[ctlr],(c))) #define midi_getdata(ctlr) (inb(ctlr_to_data_port[ctlr])) #define midi_getstatus(ctlr) (inb(ctlr_to_status_port[ctlr])) #define data_is_available(ctlr) (!(midi_getstatus(ctlr)&DATA_AVAILABLE)) #define ready_for_data(ctlr) (!(midi_getstatus(ctlr)&DATA_READY)) void midiinit() { register int n; /* create an irq_to_ctlr array so that midiintr() can */ /* get the ctlr number quickly. */ for ( n=0; nbuf[(int)((off/BUFSIZ)%MIDI_BUFS)]; if ( ! b ) return NULL; a = (unsigned char *)(b->b_un.b_addr); if ( ! a ) return NULL; return (a + (int)(off%BUFSIZ)); } void midiqput(q,c) register struct midi_queue *q; int c; { register unsigned char *p = midiqchr(q,q->high); if ( p ) { *p = c; q->high++; /* if we wrap around in the circular buffer, */ /* make sure the low offset keeps up (ie. this */ /* throws away the oldest unread data) */ if ( (q->high - q->low) >= CIRCLESIZE ) q->low = q->high - CIRCLESIZE + 1; } } midiqget(q) struct midi_queue *q; { register unsigned char *p; register int c; if ( q->low == q->high ) return -1; p = midiqchr(q,q->low); if ( ! p ) return -1; c = *p; q->low++; return c; } void midireset(ctlr,uart) { register struct midi_ctlr *m = &midi_ctlr[ ctlr ]; register time_t etime; int n; while ( data_is_available(ctlr) ) (void) midi_getdata(ctlr); /* try reset twice if ACK not received */ for ( n=0; n<2; n++ ) { midi_putcmd(ctlr,RESET); /* probably shouldn't busy loop */ etime = lbolt + HZ / 40; /* for 25 milliseconds */ while ( lbolt >= etime ) { if ( midiqget(&(m->in)) == ACK ) break; } if ( lbolt < etime ) break; } if ( n >= 2 ) printf("midireset didn't get ACK?\n"); if ( uart ) midi_putcmd(ctlr,UART); /* doesn't send an ACK back */ } void midiopen(dev) { register struct midi_ctlr *m; register int ctlr = controller(dev); register int n; if ( ctlr >= midi_nctlr ) { u.u_error = ENXIO; return; } m = &midi_ctlr[ctlr]; if ( ((m->flags)&ISOPEN) == 0 ) { /* opened for the first time */ for ( n=0; nin.buf[n] = geteblk(); m->in.low = m->in.high = 0; } m->flags |= ISOPEN; m->flags &= (~ACTSENSE);/* default is to ignore active sensing*/ m->clockoffset = lbolt; /* TIME starts out at 0 */ #ifdef VPIX ectproc = u.u_procp; if (ectproc && ectproc->p_v86) { vpix = TRUE; } else vpix = FALSE; #endif /* VPIX */ } midireset(ctlr,RESET); } void midiioctl(dev, cmd, arg, mode) int dev; int cmd; caddr_t arg; { register int ctlr = controller(dev); register struct midi_ctlr *m; time_t *t; off_t n; m = &midi_ctlr[ ctlr ]; switch(cmd) { case MIDIACTIVE: if ( arg ) m->flags |= ACTSENSE; else m->flags &= (~ACTSENSE); break; case MIDIRESET: midireset(ctlr,1); /* default is UART mode */ break; case MIDITHRU: midireset(ctlr,RESET); break; case MIDITIMERESET: m->clockoffset = lbolt; break; case MIDITIME: t = (time_t *)arg; #define MILLIPERHZ (1000/HZ) if ( t ) suword(t,(long)(MILLIPERHZ*(lbolt - m->clockoffset))); break; default: u.u_error = EINVAL; break; } } midi_wait_for_ready(ctlr) { register struct midi_ctlr *m; int tmout; register int c; for ( tmout=50000; tmout>0; tmout-- ) { if ( ready_for_data(ctlr) ) break; } if ( tmout <= 0 ) { printf("/dev/midi timed out waiting for data ready\n"); return 0; } return 1; } void midiclose(dev) { register struct midi_ctlr *m; register int n; register int ctlr = controller(dev); m = &midi_ctlr[ ctlr ]; if ( ((m->flags)&ISOPEN) != 0 ) { /* paranoia */ m->flags &= (~ISOPEN); for ( n=0; nin.buf[n]); } midireset(ctlr,RESET); } void midiread(dev) { register struct midi_ctlr *m; register int ctlr = controller(dev); register int c; m = &midi_ctlr[ ctlr ]; while ( u.u_count ) { c = midiqget(&(m->in)); if ( c < 0 ) break; /* active sensing may be ignored */ if ( c == ACTIVE && ((m->flags&ACTSENSE)==0) ) break; subyte(u.u_base,c); u.u_base++; u.u_count--; } } void midiwrite(dev) { register int ctlr = controller(dev); while ( u.u_count ) { if ( midi_wait_for_ready(ctlr) ) midi_putdata(ctlr,fubyte(u.u_base)); u.u_base++; u.u_count--; } } void midiintr(irq) { register struct midi_ctlr *m; register int ctlr; register int c; #ifdef VPIX register int v86intr = (1 << irq); #endif /* VPIX */ ctlr = irq_to_ctlr[irq]; #ifdef VPIX if(vpix) { /* send a pseudorupt if this is an ECT */ ectproc->p_v86->vp_xtss->xt_viurgent |= v86intr; ectproc->p_v86->vp_xtss->xt_viflag |= v86intr; /* v86setint(ectproc->p_v86, v86intr); */ } else { #endif /* VPIX */ if ( data_is_available(ctlr) ) { c = midi_getdata(ctlr); m = &midi_ctlr[ ctlr ]; if ( (m->flags & ISOPEN) != 0 ) midiqput(&(m->in),c); } #ifdef VPIX } #endif /* VPIX */ }