Annotation of lucent/sys/src/9/pc/devaudio.c, revision 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.