Annotation of lucent/sys/src/9/pc/devaudio.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *     SB 16 driver
                      3:  */
                      4: #include       "u.h"
                      5: #include       "../port/lib.h"
                      6: #include       "mem.h"
                      7: #include       "dat.h"
                      8: #include       "fns.h"
                      9: #include       "../port/error.h"
                     10: #include       "devtab.h"
                     11: #include       "io.h"
                     12: #include       "audio.h"
                     13: 
                     14: #define        NPORT           (sizeof audiodir/sizeof(Dirtab))
                     15: 
                     16: typedef struct AQueue  AQueue;
                     17: typedef struct Buf     Buf;
                     18: 
                     19: enum
                     20: {
                     21:        Qdir            = 0,
                     22:        Qaudio,
                     23:        Qvolume,
                     24: 
                     25:        Fmono           = 1,
                     26:        Fin             = 2,
                     27:        Fout            = 4,
                     28: 
                     29:        Aclosed         = 0,
                     30:        Aread,
                     31:        Awrite,
                     32: 
                     33:        Vaudio          = 0,
                     34:        Vsynth,
                     35:        Vcd,
                     36:        Vline,
                     37:        Vmic,
                     38:        Vspeaker,
                     39:        Vtreb,
                     40:        Vbass,
                     41:        Vspeed,
                     42:        Nvol,
                     43: 
                     44:        Speed           = 44100,
                     45:        Ncmd            = 50,           /* max volume command words */
                     46: };
                     47: 
                     48: Dirtab
                     49: audiodir[] =
                     50: {
                     51:        "audio",        {Qaudio},               0,      0666,
                     52:        "volume",       {Qvolume},              0,      0666,
                     53: };
                     54: 
                     55: struct Buf
                     56: {
                     57:        uchar*  virt;
                     58:        ulong   phys;
                     59:        Buf*    next;
                     60: };
                     61: struct AQueue
                     62: {
                     63:        Lock;
                     64:        Buf*    first;
                     65:        Buf*    last;
                     66: };
                     67: static struct
                     68: {
                     69:        QLock;
                     70:        Rendez  vous;
                     71:        int     bufinit;        /* boolean if buffers allocated */
                     72:        int     curcount;       /* how much data in current buffer */
                     73:        int     active;         /* boolean dma running */
                     74:        int     intr;           /* boolean an interrupt has happened */
                     75:        int     amode;          /* Aclosed/Aread/Awrite for /audio */
                     76:        int     rivol[Nvol];            /* right/left input/output volumes */
                     77:        int     livol[Nvol];
                     78:        int     rovol[Nvol];
                     79:        int     lovol[Nvol];
                     80:        int     major;          /* SB16 major version number (sb 4) */
                     81:        int     minor;          /* SB16 minor version number */
                     82: 
                     83:        Buf     buf[Nbuf];      /* buffers and queues */
                     84:        AQueue  empty;
                     85:        AQueue  full;
                     86:        Buf*    current;
                     87:        Buf*    filling;
                     88: } audio;
                     89: 
                     90: static struct
                     91: {
                     92:        char*   name;
                     93:        int     flag;
                     94:        int     ilval;          /* initial values */
                     95:        int     irval;
                     96: } volumes[] =
                     97: {
                     98:        [Vaudio]        "audio",        Fout,           50,     50,
                     99:        [Vsynth]        "synth",        Fin|Fout,       0,      0,
                    100:        [Vcd]           "cd",           Fin|Fout,       0,      0,
                    101:        [Vline]         "line",         Fin|Fout,       0,      0,
                    102:        [Vmic]          "mic",          Fin|Fout|Fmono, 0,      0,
                    103:        [Vspeaker]      "speaker",      Fout|Fmono,     0,      0,
                    104: 
                    105:        [Vtreb]         "treb",         Fout,           50,     50,
                    106:        [Vbass]         "bass",         Fout,           50,     50,
                    107: 
                    108:        [Vspeed]        "speed",        Fin|Fout|Fmono, Speed,  Speed,
                    109:        0
                    110: };
                    111: 
                    112: static struct
                    113: {
                    114:        Lock;
                    115:        int     reset;          /* io ports to the sound blaster */
                    116:        int     read;
                    117:        int     write;
                    118:        int     wstatus;
                    119:        int     rstatus;
                    120:        int     mixaddr;
                    121:        int     mixdata;
                    122:        int     clri8;
                    123:        int     clri16;
                    124:        int     clri401;
                    125:        int     dma;
                    126: } blaster;
                    127: 
                    128: static void    swab(uchar*);
                    129: 
                    130: static char    Emajor[]        = "soundblaster not responding/wrong version";
                    131: static char    Emode[]         = "illegal open mode";
                    132: static char    Evolume[]       = "illegal volume specifier";
                    133: 
                    134: static int
                    135: sbcmd(int val)
                    136: {
                    137:        int i, s;
                    138: 
                    139:        for(i=1<<16; i!=0; i--) {
                    140:                s = inb(blaster.wstatus);
                    141:                if((s & 0x80) == 0) {
                    142:                        outb(blaster.write, val);
                    143:                        return 0;
                    144:                }
                    145:        }
                    146:        return 1;
                    147: }
                    148: 
                    149: static int
                    150: sbread(void)
                    151: {
                    152:        int i, s;
                    153: 
                    154:        for(i=1<<16; i!=0; i--) {
                    155:                s = inb(blaster.rstatus);
                    156:                if((s & 0x80) != 0) {
                    157:                        return inb(blaster.read);
                    158:                }
                    159:        }
                    160:        return 0xbb;
                    161: }
                    162: 
                    163: static int
                    164: mxcmd(int addr, int val)
                    165: {
                    166: 
                    167:        outb(blaster.mixaddr, addr);
                    168:        outb(blaster.mixdata, val);
                    169:        return 1;
                    170: }
                    171: 
                    172: static int
                    173: mxread(int addr)
                    174: {
                    175:        int s;
                    176: 
                    177:        outb(blaster.mixaddr, addr);
                    178:        s = inb(blaster.mixdata);
                    179:        return s;
                    180: }
                    181: 
                    182: static void
                    183: mxcmds(int s, int v)
                    184: {
                    185: 
                    186:        if(v > 100)
                    187:                v = 100;
                    188:        if(v < 0)
                    189:                v = 0;
                    190:        mxcmd(s, (v*255)/100);
                    191: }
                    192: 
                    193: static void
                    194: mxcmdt(int s, int v)
                    195: {
                    196: 
                    197:        if(v > 100)
                    198:                v = 100;
                    199:        if(v <= 0)
                    200:                mxcmd(s, 0);
                    201:        else
                    202:                mxcmd(s, 255-100+v);
                    203: }
                    204: 
                    205: static void
                    206: mxcmdu(int s, int v)
                    207: {
                    208: 
                    209:        if(v > 100)
                    210:                v = 100;
                    211:        if(v <= 0)
                    212:                v = 0;
                    213:        mxcmd(s, 128-50+v);
                    214: }
                    215: 
                    216: static void
                    217: mxvolume(void)
                    218: {
                    219:        int *left, *right;
                    220:        int source;
                    221: 
                    222:        if(audio.amode == Aread){
                    223:                left = audio.livol;
                    224:                right = audio.rivol;
                    225:        }else{
                    226:                left = audio.lovol;
                    227:                right = audio.rovol;
                    228:        }
                    229: 
                    230:        ilock(&blaster);
                    231: 
                    232:        mxcmd(0x30, 255);               /* left master */
                    233:        mxcmd(0x31, 255);               /* right master */
                    234:        mxcmd(0x3f, 0);                 /* left igain */
                    235:        mxcmd(0x40, 0);                 /* right igain */
                    236:        mxcmd(0x41, 0);                 /* left ogain */
                    237:        mxcmd(0x42, 0);                 /* right ogain */
                    238: 
                    239:        mxcmds(0x32, left[Vaudio]);
                    240:        mxcmds(0x33, right[Vaudio]);
                    241: 
                    242:        mxcmds(0x34, left[Vsynth]);
                    243:        mxcmds(0x35, right[Vsynth]);
                    244: 
                    245:        mxcmds(0x36, left[Vcd]);
                    246:        mxcmds(0x37, right[Vcd]);
                    247: 
                    248:        mxcmds(0x38, left[Vline]);
                    249:        mxcmds(0x39, right[Vline]);
                    250: 
                    251:        mxcmds(0x3a, left[Vmic]);
                    252:        mxcmds(0x3b, left[Vspeaker]);
                    253: 
                    254:        mxcmdu(0x44, left[Vtreb]);
                    255:        mxcmdu(0x45, right[Vtreb]);
                    256: 
                    257:        mxcmdu(0x46, left[Vbass]);
                    258:        mxcmdu(0x47, right[Vbass]);
                    259: 
                    260:        source = 0;
                    261:        if(left[Vsynth])
                    262:                source |= 1<<6;
                    263:        if(right[Vsynth])
                    264:                source |= 1<<5;
                    265:        if(left[Vaudio])
                    266:                source |= 1<<4;
                    267:        if(right[Vaudio])
                    268:                source |= 1<<3;
                    269:        if(left[Vcd])
                    270:                source |= 1<<2;
                    271:        if(right[Vcd])
                    272:                source |= 1<<1;
                    273:        if(left[Vmic])
                    274:                source |= 1<<0;
                    275:        if(audio.amode == Aread)
                    276:                mxcmd(0x3c, 0);         /* output switch */
                    277:        else
                    278:                mxcmd(0x3c, source);
                    279:        mxcmd(0x3d, source);            /* input left switch */
                    280:        mxcmd(0x3e, source);            /* input right switch */
                    281:        iunlock(&blaster);
                    282: }
                    283: 
                    284: static Buf*
                    285: getbuf(AQueue *q)
                    286: {
                    287:        Buf *b;
                    288: 
                    289:        ilock(q);
                    290:        b = q->first;
                    291:        if(b)
                    292:                q->first = b->next;
                    293:        iunlock(q);
                    294: 
                    295:        return b;
                    296: }
                    297: 
                    298: static void
                    299: putbuf(AQueue *q, Buf *b)
                    300: {
                    301: 
                    302:        ilock(q);
                    303:        b->next = 0;
                    304:        if(q->first)
                    305:                q->last->next = b;
                    306:        else
                    307:                q->first = b;
                    308:        q->last = b;
                    309:        iunlock(q);
                    310: }
                    311: 
                    312: /*
                    313:  * move the dma to the next buffer
                    314:  */
                    315: static void
                    316: contindma(void)
                    317: {
                    318:        Buf *b;
                    319: 
                    320:        if(!audio.active)
                    321:                goto shutdown;
                    322: 
                    323:        b = audio.current;
                    324:        if(audio.amode == Aread) {
                    325:                if(b)   /* shouldnt happen */
                    326:                        putbuf(&audio.full, b);
                    327:                b = getbuf(&audio.empty);
                    328:        } else {
                    329:                if(b)   /* shouldnt happen */
                    330:                        putbuf(&audio.empty, b);
                    331:                b = getbuf(&audio.full);
                    332:        }
                    333:        audio.current = b;
                    334:        if(b == 0)
                    335:                goto shutdown;
                    336: 
                    337:        dmasetup(blaster.dma, b->virt, Bufsize, audio.amode == Aread);
                    338:        return;
                    339: 
                    340: shutdown:
                    341:        dmaend(blaster.dma);
                    342:        sbcmd(0xd9);                            /* exit at end of count */
                    343:        sbcmd(0xd5);                            /* pause */
                    344:        audio.curcount = 0;
                    345:        audio.active = 0;
                    346: }
                    347: 
                    348: /*
                    349:  * cause sb to get an interrupt per buffer.
                    350:  * start first dma
                    351:  */
                    352: static void
                    353: startdma(void)
                    354: {
                    355:        ulong count;
                    356:        int speed;
                    357: 
                    358:        ilock(&blaster);
                    359:        dmaend(blaster.dma);
                    360:        if(audio.amode == Aread) {
                    361:                sbcmd(0x42);                    /* input sampling rate */
                    362:                speed = audio.livol[Vspeed];
                    363:        } else {
                    364:                sbcmd(0x41);                    /* output sampling rate */
                    365:                speed = audio.lovol[Vspeed];
                    366:        }
                    367:        sbcmd(speed>>8);
                    368:        sbcmd(speed);
                    369: 
                    370:        count = (Bufsize >> 1) - 1;
                    371:        if(audio.amode == Aread)
                    372:                sbcmd(0xbe);                    /* A/D, autoinit */
                    373:        else
                    374:                sbcmd(0xb6);                    /* D/A, autoinit */
                    375:        sbcmd(0x30);                            /* stereo, 16 bit */
                    376:        sbcmd(count);
                    377:        sbcmd(count>>8);
                    378: 
                    379:        audio.active = 1;
                    380:        contindma();
                    381:        iunlock(&blaster);
                    382: }
                    383: 
                    384: /*
                    385:  * if audio is stopped,
                    386:  * start it up again.
                    387:  */
                    388: static void
                    389: pokeaudio(void)
                    390: {
                    391:        if(!audio.active)
                    392:                startdma();
                    393: }
                    394: 
                    395: void
                    396: audiosbintr(void)
                    397: {
                    398:        int stat, dummy;
                    399: 
                    400:        stat = mxread(0x82) & 7;                /* get irq status */
                    401:        if(stat) {
                    402:                dummy = 0;
                    403:                if(stat & 2) {
                    404:                        ilock(&blaster);
                    405:                        dummy = inb(blaster.clri16);
                    406:                        contindma();
                    407:                        iunlock(&blaster);
                    408:                        audio.intr = 1;
                    409:                        wakeup(&audio.vous);
                    410:                }
                    411:                if(stat & 1) {
                    412:                        dummy = inb(blaster.clri8);
                    413:                }
                    414:                if(stat & 4) {
                    415:                        dummy = inb(blaster.clri401);
                    416:                }
                    417:                USED(dummy);
                    418:        }
                    419: }
                    420: 
                    421: void
                    422: pcaudiosbintr(Ureg *ureg, void *rock)
                    423: {
                    424:        USED(ureg, rock);
                    425:        audiosbintr();
                    426: }
                    427: 
                    428: void
                    429: audiodmaintr(void)
                    430: {
                    431: }
                    432: 
                    433: static int
                    434: anybuf(void *p)
                    435: {
                    436:        USED(p);
                    437:        return audio.intr;
                    438: }
                    439: 
                    440: /*
                    441:  * wait for some output to get
                    442:  * empty buffers back.
                    443:  */
                    444: static void
                    445: waitaudio(void)
                    446: {
                    447: 
                    448:        audio.intr = 0;
                    449:        pokeaudio();
                    450:        tsleep(&audio.vous, anybuf, 0, 10*1000);
                    451:        if(audio.intr == 0) {
                    452:                audio.active = 0;
                    453:                pokeaudio();
                    454:        }
                    455: }
                    456: 
                    457: static void
                    458: sbbufinit(void)
                    459: {
                    460:        int i;
                    461:        void *p;
                    462: 
                    463:        for(i=0; i<Nbuf; i++) {
                    464:                p = xspanalloc(Bufsize, CACHELINESZ, 64*1024);
                    465:                audio.buf[i].virt = UNCACHED(uchar, p);
                    466:                audio.buf[i].phys = (ulong)PADDR(p);
                    467:        }
                    468: }
                    469: 
                    470: static void
                    471: setempty(void)
                    472: {
                    473:        int i;
                    474: 
                    475:        ilock(&blaster);
                    476:        audio.empty.first = 0;
                    477:        audio.empty.last = 0;
                    478:        audio.full.first = 0;
                    479:        audio.full.last = 0;
                    480:        audio.current = 0;
                    481:        audio.filling = 0;
                    482:        for(i=0; i<Nbuf; i++)
                    483:                putbuf(&audio.empty, &audio.buf[i]);
                    484:        iunlock(&blaster);
                    485: }
                    486: 
                    487: void
                    488: audioreset(void)
                    489: {
                    490: }
                    491: 
                    492: static void
                    493: resetlevel(void)
                    494: {
                    495:        int i;
                    496: 
                    497:        for(i=0; volumes[i].name; i++) {
                    498:                audio.lovol[i] = volumes[i].ilval;
                    499:                audio.rovol[i] = volumes[i].irval;
                    500:                audio.livol[i] = volumes[i].ilval;
                    501:                audio.rivol[i] = volumes[i].irval;
                    502:        }
                    503: }
                    504: 
                    505: void
                    506: audioinit(void)
                    507: {
                    508:        ISAConf sbconf;
                    509:        int i;
                    510: 
                    511:        sbconf.port = 0x220;
                    512:        sbconf.dma = 5;
                    513:        sbconf.irq = 7;
                    514:        if(isaconfig("audio", 0, &sbconf) == 0)
                    515:                return;
                    516:        if(strcmp(sbconf.type, "sb16") != 0)
                    517:                return;
                    518: 
                    519:        switch(sbconf.port){
                    520:        case 0x220:
                    521:        case 0x240:
                    522:        case 0x260:
                    523:        case 0x280:
                    524:                break;
                    525:        default:
                    526:                print("devaudio: bad sb16 port 0x%x\n", sbconf.port);
                    527:                return;
                    528:        }
                    529:        switch(sbconf.irq){
                    530:        case 2:
                    531:        case 5:
                    532:        case 7:
                    533:        case 10:
                    534:                break;
                    535:        default:
                    536:                print("devaudio: bad sb16 irq %d\n", sbconf.irq);
                    537:                return;
                    538:        }
                    539: 
                    540:        blaster.dma = sbconf.dma;
                    541: 
                    542:        blaster.reset = sbconf.port + 0x6;
                    543:        blaster.read = sbconf.port + 0xa;
                    544:        blaster.write = sbconf.port + 0xc;
                    545:        blaster.wstatus = sbconf.port + 0xc;
                    546:        blaster.rstatus = sbconf.port + 0xe;
                    547:        blaster.mixaddr = sbconf.port + 0x4;
                    548:        blaster.mixdata = sbconf.port + 0x5;
                    549:        blaster.clri8 = sbconf.port + 0xe;
                    550:        blaster.clri16 = sbconf.port + 0xf;
                    551:        blaster.clri401 = sbconf.port + 0x100;
                    552: 
                    553:        seteisadma(blaster.dma, audiodmaintr);
                    554:        setvec(Int0vec+sbconf.irq, pcaudiosbintr, 0);
                    555: 
                    556:        audio.amode = Aclosed;
                    557:        resetlevel();
                    558: 
                    559:        outb(blaster.reset, 1);
                    560:        delay(1);                       /* >3 υs */
                    561:        outb(blaster.reset, 0);
                    562:        delay(1);
                    563: 
                    564:        i = sbread();
                    565:        if(i != 0xaa) {
                    566:                print("sound blaster didnt respond #%.2x\n", i);
                    567:                return;
                    568:        }
                    569: 
                    570:        sbcmd(0xe1);                    /* get version */
                    571:        audio.major = sbread();
                    572:        audio.minor = sbread();
                    573: 
                    574:        if(audio.major != 4) {
                    575:                print("bad soundblaster model #%.2x #%.2x; not SB 16\n", audio.major, audio.minor);
                    576:                return;
                    577:        }
                    578:        /*
                    579:         * initialize the mixer
                    580:         */
                    581:        mxcmd(0x00, 0);                 /* Reset mixer */
                    582:        mxvolume();
                    583: 
                    584:        /*
                    585:         * set up irq/dma chans
                    586:         */
                    587:        mxcmd(0x80,                     /* irq */
                    588:                (sbconf.irq==2)? 1:
                    589:                (sbconf.irq==5)? 2:
                    590:                (sbconf.irq==7)? 4:
                    591:                (sbconf.irq==10)? 8:
                    592:                0);
                    593:        mxcmd(0x81, 1<<blaster.dma);    /* dma */
                    594: }
                    595: 
                    596: Chan*
                    597: audioattach(char *param)
                    598: {
                    599:        return devattach('A', param);
                    600: }
                    601: 
                    602: Chan*
                    603: audioclone(Chan *c, Chan *nc)
                    604: {
                    605:        return devclone(c, nc);
                    606: }
                    607: 
                    608: int
                    609: audiowalk(Chan *c, char *name)
                    610: {
                    611:        return devwalk(c, name, audiodir, NPORT, devgen);
                    612: }
                    613: 
                    614: void
                    615: audiostat(Chan *c, char *db)
                    616: {
                    617:        devstat(c, db, audiodir, NPORT, devgen);
                    618: }
                    619: 
                    620: Chan*
                    621: audioopen(Chan *c, int omode)
                    622: {
                    623:        int amode;
                    624: 
                    625:        if(audio.major != 4)
                    626:                error(Emajor);
                    627: 
                    628:        switch(c->qid.path & ~CHDIR) {
                    629:        default:
                    630:                error(Eperm);
                    631:                break;
                    632: 
                    633:        case Qvolume:
                    634:        case Qdir:
                    635:                break;
                    636: 
                    637:        case Qaudio:
                    638:                amode = Awrite;
                    639:                if((omode&7) == OREAD)
                    640:                        amode = Aread;
                    641:                qlock(&audio);
                    642:                if(audio.amode != Aclosed){
                    643:                        qunlock(&audio);
                    644:                        error(Einuse);
                    645:                }
                    646:                if(audio.bufinit == 0) {
                    647:                        audio.bufinit = 1;
                    648:                        sbbufinit();
                    649:                }
                    650:                audio.amode = amode;
                    651:                setempty();
                    652:                audio.curcount = 0;
                    653:                qunlock(&audio);
                    654:                mxvolume();
                    655:                break;
                    656:        }
                    657:        c = devopen(c, omode, audiodir, NPORT, devgen);
                    658:        c->mode = openmode(omode);
                    659:        c->flag |= COPEN;
                    660:        c->offset = 0;
                    661: 
                    662:        return c;
                    663: }
                    664: 
                    665: void
                    666: audiocreate(Chan *c, char *name, int omode, ulong perm)
                    667: {
                    668:        USED(c);
                    669:        USED(name);
                    670:        USED(omode);
                    671:        USED(perm);
                    672: 
                    673:        error(Eperm);
                    674: }
                    675: 
                    676: void
                    677: audioclose(Chan *c)
                    678: {
                    679: 
                    680:        switch(c->qid.path & ~CHDIR) {
                    681:        default:
                    682:                error(Eperm);
                    683:                break;
                    684: 
                    685:        case Qdir:
                    686:        case Qvolume:
                    687:                break;
                    688: 
                    689:        case Qaudio:
                    690:                if(c->flag & COPEN) {
                    691:                        qlock(&audio);
                    692:                        audio.amode = Aclosed;
                    693:                        if(waserror()){
                    694:                                qunlock(&audio);
                    695:                                nexterror();
                    696:                        }
                    697:                        while(audio.active)
                    698:                                waitaudio();
                    699:                        setempty();
                    700:                        poperror();
                    701:                        qunlock(&audio);
                    702:                }
                    703:                break;
                    704:        }
                    705: }
                    706: 
                    707: long
                    708: audioread(Chan *c, char *a, long n, ulong offset)
                    709: {
                    710:        int liv, riv, lov, rov;
                    711:        long m, n0;
                    712:        char buf[300];
                    713:        Buf *b;
                    714:        int j;
                    715: 
                    716:        n0 = n;
                    717:        switch(c->qid.path & ~CHDIR) {
                    718:        default:
                    719:                error(Eperm);
                    720:                break;
                    721: 
                    722:        case Qdir:
                    723:                return devdirread(c, a, n, audiodir, NPORT, devgen);
                    724: 
                    725:        case Qaudio:
                    726:                if(audio.amode != Aread)
                    727:                        error(Emode);
                    728:                qlock(&audio);
                    729:                if(waserror()){
                    730:                        qunlock(&audio);
                    731:                        nexterror();
                    732:                }
                    733:                while(n > 0) {
                    734:                        b = audio.filling;
                    735:                        if(b == 0) {
                    736:                                b = getbuf(&audio.full);
                    737:                                if(b == 0) {
                    738:                                        waitaudio();
                    739:                                        continue;
                    740:                                }
                    741:                                audio.filling = b;
                    742:                                swab(b->virt);
                    743:                                audio.curcount = 0;
                    744:                        }
                    745:                        m = Bufsize-audio.curcount;
                    746:                        if(m > n)
                    747:                                m = n;
                    748:                        memmove(a, b->virt+audio.curcount, m);
                    749: 
                    750:                        audio.curcount += m;
                    751:                        n -= m;
                    752:                        a += m;
                    753:                        if(audio.curcount >= Bufsize) {
                    754:                                audio.filling = 0;
                    755:                                putbuf(&audio.empty, b);
                    756:                        }
                    757:                }
                    758:                poperror();
                    759:                qunlock(&audio);
                    760:                break;
                    761: 
                    762:        case Qvolume:
                    763:                j = 0;
                    764:                buf[0] = 0;
                    765:                for(m=0; volumes[m].name; m++){
                    766:                        liv = audio.livol[m];
                    767:                        riv = audio.rivol[m];
                    768:                        lov = audio.lovol[m];
                    769:                        rov = audio.rovol[m];
                    770:                        j += snprint(buf+j, sizeof(buf)-j, "%s", volumes[m].name);
                    771:                        if((volumes[m].flag & Fmono) || liv==riv && lov==rov){
                    772:                                if((volumes[m].flag&(Fin|Fout))==(Fin|Fout) && liv==lov)
                    773:                                        j += snprint(buf+j, sizeof(buf)-j, " %d", liv);
                    774:                                else{
                    775:                                        if(volumes[m].flag & Fin)
                    776:                                                j += snprint(buf+j, sizeof(buf)-j, " in %d", liv);
                    777:                                        if(volumes[m].flag & Fout)
                    778:                                                j += snprint(buf+j, sizeof(buf)-j, " out %d", lov);
                    779:                                }
                    780:                        }else{
                    781:                                if((volumes[m].flag&(Fin|Fout))==(Fin|Fout) && liv==lov && riv==rov)
                    782:                                        j += snprint(buf+j, sizeof(buf)-j, " left %d right %d",
                    783:                                                liv, riv);
                    784:                                else{
                    785:                                        if(volumes[m].flag & Fin)
                    786:                                                j += snprint(buf+j, sizeof(buf)-j, " in left %d right %d",
                    787:                                                        liv, riv);
                    788:                                        if(volumes[m].flag & Fout)
                    789:                                                j += snprint(buf+j, sizeof(buf)-j, " out left %d right %d",
                    790:                                                        lov, rov);
                    791:                                }
                    792:                        }
                    793:                        j += snprint(buf+j, sizeof(buf)-j, "\n");
                    794:                }
                    795: 
                    796:                return readstr(offset, a, n, buf);
                    797:        }
                    798:        return n0-n;
                    799: }
                    800: 
                    801: long
                    802: audiowrite(Chan *c, char *a, long n, ulong offset)
                    803: {
                    804:        long m, n0;
                    805:        int i, nf, v, left, right, in, out;
                    806:        char buf[255], *field[Ncmd];
                    807:        Buf *b;
                    808: 
                    809:        USED(offset);
                    810: 
                    811:        n0 = n;
                    812:        switch(c->qid.path & ~CHDIR) {
                    813:        default:
                    814:                error(Eperm);
                    815:                break;
                    816: 
                    817:        case Qvolume:
                    818:                v = Vaudio;
                    819:                left = 1;
                    820:                right = 1;
                    821:                in = 1;
                    822:                out = 1;
                    823:                if(n > sizeof(buf)-1)
                    824:                        n = sizeof(buf)-1;
                    825:                memmove(buf, a, n);
                    826:                buf[n] = '\0';
                    827: 
                    828:                nf = getfields(buf, field, Ncmd, " \t\n");
                    829:                for(i = 0; i < nf; i++){
                    830:                        /*
                    831:                         * a number is volume
                    832:                         */
                    833:                        if(field[i][0] >= '0' && field[i][0] <= '9') {
                    834:                                m = strtoul(field[i], 0, 10);
                    835:                                if(left && out)
                    836:                                        audio.lovol[v] = m;
                    837:                                if(left && in)
                    838:                                        audio.livol[v] = m;
                    839:                                if(right && out)
                    840:                                        audio.rovol[v] = m;
                    841:                                if(right && in)
                    842:                                        audio.rivol[v] = m;
                    843:                                mxvolume();
                    844:                                goto cont0;
                    845:                        }
                    846: 
                    847:                        for(m=0; volumes[m].name; m++) {
                    848:                                if(strcmp(field[i], volumes[m].name) == 0) {
                    849:                                        v = m;
                    850:                                        in = 1;
                    851:                                        out = 1;
                    852:                                        left = 1;
                    853:                                        right = 1;
                    854:                                        goto cont0;
                    855:                                }
                    856:                        }
                    857: 
                    858:                        if(strcmp(field[i], "reset") == 0) {
                    859:                                resetlevel();
                    860:                                mxvolume();
                    861:                                goto cont0;
                    862:                        }
                    863:                        if(strcmp(field[i], "in") == 0) {
                    864:                                in = 1;
                    865:                                out = 0;
                    866:                                goto cont0;
                    867:                        }
                    868:                        if(strcmp(field[i], "out") == 0) {
                    869:                                in = 0;
                    870:                                out = 1;
                    871:                                goto cont0;
                    872:                        }
                    873:                        if(strcmp(field[i], "left") == 0) {
                    874:                                left = 1;
                    875:                                right = 0;
                    876:                                goto cont0;
                    877:                        }
                    878:                        if(strcmp(field[i], "right") == 0) {
                    879:                                left = 0;
                    880:                                right = 1;
                    881:                                goto cont0;
                    882:                        }
                    883:                        error(Evolume);
                    884:                        break;
                    885:                cont0:;
                    886:                }
                    887:                break;
                    888: 
                    889:        case Qaudio:
                    890:                if(audio.amode != Awrite)
                    891:                        error(Emode);
                    892:                qlock(&audio);
                    893:                if(waserror()){
                    894:                        qunlock(&audio);
                    895:                        nexterror();
                    896:                }
                    897:                while(n > 0) {
                    898:                        b = audio.filling;
                    899:                        if(b == 0) {
                    900:                                b = getbuf(&audio.empty);
                    901:                                if(b == 0) {
                    902:                                        waitaudio();
                    903:                                        continue;
                    904:                                }
                    905:                                audio.filling = b;
                    906:                                audio.curcount = 0;
                    907:                        }
                    908: 
                    909:                        m = Bufsize-audio.curcount;
                    910:                        if(m > n)
                    911:                                m = n;
                    912:                        memmove(b->virt+audio.curcount, a, m);
                    913: 
                    914:                        audio.curcount += m;
                    915:                        n -= m;
                    916:                        a += m;
                    917:                        if(audio.curcount >= Bufsize) {
                    918:                                audio.filling = 0;
                    919:                                swab(b->virt);
                    920:                                putbuf(&audio.full, b);
                    921:                        }
                    922:                }
                    923:                poperror();
                    924:                qunlock(&audio);
                    925:                break;
                    926:        }
                    927:        return n0 - n;
                    928: }
                    929: 
                    930: void
                    931: audioremove(Chan *c)
                    932: {
                    933:        USED(c);
                    934: 
                    935:        error(Eperm);
                    936: }
                    937: 
                    938: void
                    939: audiowstat(Chan *c, char *dp)
                    940: {
                    941:        USED(c);
                    942:        USED(dp);
                    943: 
                    944:        error(Eperm);
                    945: }
                    946: 
                    947: static void
                    948: swab(uchar *a)
                    949: {
                    950:        ulong *p, *ep, b;
                    951: 
                    952:        if(!SBswab)
                    953:                return;
                    954:        p = (ulong*)a;
                    955:        ep = p + (Bufsize>>2);
                    956:        while(p < ep) {
                    957:                b = *p;
                    958:                b = (b>>24) | (b<<24) |
                    959:                        ((b&0xff0000) >> 8) |
                    960:                        ((b&0x00ff00) << 8);
                    961:                *p++ = b;
                    962:        }
                    963: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.