The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386/isa/spkr.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * spkr.c -- device driver for console speaker
    3  *
    4  * v1.4 by Eric S. Raymond (esr@snark.thyrsus.com) Aug 1993
    5  * modified for FreeBSD by Andrew A. Chernov <ache@astral.msk.su>
    6  * modified for PC98 by Kakefuda
    7  *
    8  * $FreeBSD: releng/5.0/sys/i386/isa/spkr.c 106323 2002-11-02 04:18:10Z mdodd $
    9  */
   10 
   11 #include <sys/param.h>
   12 #include <sys/systm.h>
   13 #include <sys/bus.h>
   14 #include <sys/kernel.h>
   15 #include <sys/module.h>
   16 #include <sys/uio.h>
   17 #include <sys/conf.h>
   18 #include <sys/ctype.h>
   19 #include <sys/malloc.h>
   20 #include <isa/isavar.h>
   21 #ifdef PC98
   22 #include <pc98/pc98/pc98.h>
   23 #else
   24 #include <i386/isa/isa.h>
   25 #endif
   26 #include <i386/isa/timerreg.h>
   27 #include <machine/clock.h>
   28 #include <machine/speaker.h>
   29 
   30 static  d_open_t        spkropen;
   31 static  d_close_t       spkrclose;
   32 static  d_write_t       spkrwrite;
   33 static  d_ioctl_t       spkrioctl;
   34 
   35 #define CDEV_MAJOR 26
   36 static struct cdevsw spkr_cdevsw = {
   37         /* open */      spkropen,
   38         /* close */     spkrclose,
   39         /* read */      noread,
   40         /* write */     spkrwrite,
   41         /* ioctl */     spkrioctl,
   42         /* poll */      nopoll,
   43         /* mmap */      nommap,
   44         /* strategy */  nostrategy,
   45         /* name */      "spkr",
   46         /* maj */       CDEV_MAJOR,
   47         /* dump */      nodump,
   48         /* psize */     nopsize,
   49         /* flags */     0,
   50 };
   51 
   52 static MALLOC_DEFINE(M_SPKR, "spkr", "Speaker buffer");
   53 
   54 /**************** MACHINE DEPENDENT PART STARTS HERE *************************
   55  *
   56  * This section defines a function tone() which causes a tone of given
   57  * frequency and duration from the ISA console speaker.
   58  * Another function endtone() is defined to force sound off, and there is
   59  * also a rest() entry point to do pauses.
   60  *
   61  * Audible sound is generated using the Programmable Interval Timer (PIT) and
   62  * Programmable Peripheral Interface (PPI) attached to the ISA speaker. The
   63  * PPI controls whether sound is passed through at all; the PIT's channel 2 is
   64  * used to generate clicks (a square wave) of whatever frequency is desired.
   65  */
   66 
   67 /*
   68  * XXX PPI control values should be in a header and used in clock.c.
   69  */
   70 #ifdef PC98
   71 #define PPI_SPKR        0x08    /* turn these PPI bits on to pass sound */
   72 #define PIT_COUNT       0x3fdb  /* PIT count address */
   73 
   74 #define SPEAKER_ON      outb(IO_PPI, inb(IO_PPI) & ~PPI_SPKR)
   75 #define SPEAKER_OFF     outb(IO_PPI, inb(IO_PPI) | PPI_SPKR)
   76 #define TIMER_ACQUIRE   acquire_timer1(TIMER_SEL1 | TIMER_SQWAVE | TIMER_16BIT)
   77 #define TIMER_RELEASE   release_timer1()
   78 #define SPEAKER_WRITE(val)      { \
   79                                         outb(PIT_COUNT, (val & 0xff)); \
   80                                         outb(PIT_COUNT, (val >> 8)); \
   81                                 }
   82 #else
   83 #define PPI_SPKR        0x03    /* turn these PPI bits on to pass sound */
   84 
   85 #define SPEAKER_ON      outb(IO_PPI, inb(IO_PPI) | PPI_SPKR)
   86 #define SPEAKER_OFF     outb(IO_PPI, inb(IO_PPI) & ~PPI_SPKR)
   87 #define TIMER_ACQUIRE   acquire_timer2(TIMER_SEL2 | TIMER_SQWAVE | TIMER_16BIT)
   88 #define TIMER_RELEASE   release_timer2()
   89 #define SPEAKER_WRITE(val)      { \
   90                                         outb(TIMER_CNTR2, (val & 0xff)); \
   91                                         outb(TIMER_CNTR2, (val >> 8)); \
   92                                 }
   93 #endif
   94 
   95 #define SPKRPRI PSOCK
   96 static char endtone, endrest;
   97 
   98 static void tone(unsigned int thz, unsigned int ticks);
   99 static void rest(int ticks);
  100 static void playinit(void);
  101 static void playtone(int pitch, int value, int sustain);
  102 static int abs(int n);
  103 static void playstring(char *cp, size_t slen);
  104 
  105 /* emit tone of frequency thz for given number of ticks */
  106 static void
  107 tone(thz, ticks)
  108         unsigned int thz, ticks;
  109 {
  110     unsigned int divisor;
  111     int sps;
  112 
  113     if (thz <= 0)
  114         return;
  115 
  116     divisor = timer_freq / thz;
  117 
  118 #ifdef DEBUG
  119     (void) printf("tone: thz=%d ticks=%d\n", thz, ticks);
  120 #endif /* DEBUG */
  121 
  122     /* set timer to generate clicks at given frequency in Hertz */
  123     sps = splclock();
  124 
  125     if (TIMER_ACQUIRE) {
  126         /* enter list of waiting procs ??? */
  127         splx(sps);
  128         return;
  129     }
  130     splx(sps);
  131     disable_intr();
  132     SPEAKER_WRITE(divisor);
  133     enable_intr();
  134 
  135     /* turn the speaker on */
  136     SPEAKER_ON;
  137 
  138     /*
  139      * Set timeout to endtone function, then give up the timeslice.
  140      * This is so other processes can execute while the tone is being
  141      * emitted.
  142      */
  143     if (ticks > 0)
  144         tsleep((caddr_t)&endtone, SPKRPRI | PCATCH, "spkrtn", ticks);
  145     SPEAKER_OFF;
  146     sps = splclock();
  147     TIMER_RELEASE;
  148     splx(sps);
  149 }
  150 
  151 /* rest for given number of ticks */
  152 static void
  153 rest(ticks)
  154         int     ticks;
  155 {
  156     /*
  157      * Set timeout to endrest function, then give up the timeslice.
  158      * This is so other processes can execute while the rest is being
  159      * waited out.
  160      */
  161 #ifdef DEBUG
  162     (void) printf("rest: %d\n", ticks);
  163 #endif /* DEBUG */
  164     if (ticks > 0)
  165         tsleep((caddr_t)&endrest, SPKRPRI | PCATCH, "spkrrs", ticks);
  166 }
  167 
  168 /**************** PLAY STRING INTERPRETER BEGINS HERE **********************
  169  *
  170  * Play string interpretation is modelled on IBM BASIC 2.0's PLAY statement;
  171  * M[LNS] are missing; the ~ synonym and the _ slur mark and the octave-
  172  * tracking facility are added.
  173  * Requires tone(), rest(), and endtone(). String play is not interruptible
  174  * except possibly at physical block boundaries.
  175  */
  176 
  177 typedef int     bool;
  178 #define TRUE    1
  179 #define FALSE   0
  180 
  181 #define dtoi(c)         ((c) - '')
  182 
  183 static int octave;      /* currently selected octave */
  184 static int whole;       /* whole-note time at current tempo, in ticks */
  185 static int value;       /* whole divisor for note time, quarter note = 1 */
  186 static int fill;        /* controls spacing of notes */
  187 static bool octtrack;   /* octave-tracking on? */
  188 static bool octprefix;  /* override current octave-tracking state? */
  189 
  190 /*
  191  * Magic number avoidance...
  192  */
  193 #define SECS_PER_MIN    60      /* seconds per minute */
  194 #define WHOLE_NOTE      4       /* quarter notes per whole note */
  195 #define MIN_VALUE       64      /* the most we can divide a note by */
  196 #define DFLT_VALUE      4       /* default value (quarter-note) */
  197 #define FILLTIME        8       /* for articulation, break note in parts */
  198 #define STACCATO        6       /* 6/8 = 3/4 of note is filled */
  199 #define NORMAL          7       /* 7/8ths of note interval is filled */
  200 #define LEGATO          8       /* all of note interval is filled */
  201 #define DFLT_OCTAVE     4       /* default octave */
  202 #define MIN_TEMPO       32      /* minimum tempo */
  203 #define DFLT_TEMPO      120     /* default tempo */
  204 #define MAX_TEMPO       255     /* max tempo */
  205 #define NUM_MULT        3       /* numerator of dot multiplier */
  206 #define DENOM_MULT      2       /* denominator of dot multiplier */
  207 
  208 /* letter to half-tone:  A   B  C  D  E  F  G */
  209 static int notetab[8] = {9, 11, 0, 2, 4, 5, 7};
  210 
  211 /*
  212  * This is the American Standard A440 Equal-Tempered scale with frequencies
  213  * rounded to nearest integer. Thank Goddess for the good ol' CRC Handbook...
  214  * our octave 0 is standard octave 2.
  215  */
  216 #define OCTAVE_NOTES    12      /* semitones per octave */
  217 static int pitchtab[] =
  218 {
  219 /*        C     C#    D     D#    E     F     F#    G     G#    A     A#    B*/
  220 /* 0 */   65,   69,   73,   78,   82,   87,   93,   98,  103,  110,  117,  123,
  221 /* 1 */  131,  139,  147,  156,  165,  175,  185,  196,  208,  220,  233,  247,
  222 /* 2 */  262,  277,  294,  311,  330,  349,  370,  392,  415,  440,  466,  494,
  223 /* 3 */  523,  554,  587,  622,  659,  698,  740,  784,  831,  880,  932,  988,
  224 /* 4 */ 1047, 1109, 1175, 1245, 1319, 1397, 1480, 1568, 1661, 1760, 1865, 1975,
  225 /* 5 */ 2093, 2217, 2349, 2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951,
  226 /* 6 */ 4186, 4435, 4698, 4978, 5274, 5588, 5920, 6272, 6644, 7040, 7459, 7902,
  227 };
  228 
  229 static void
  230 playinit()
  231 {
  232     octave = DFLT_OCTAVE;
  233     whole = (hz * SECS_PER_MIN * WHOLE_NOTE) / DFLT_TEMPO;
  234     fill = NORMAL;
  235     value = DFLT_VALUE;
  236     octtrack = FALSE;
  237     octprefix = TRUE;   /* act as though there was an initial O(n) */
  238 }
  239 
  240 /* play tone of proper duration for current rhythm signature */
  241 static void
  242 playtone(pitch, value, sustain)
  243         int     pitch, value, sustain;
  244 {
  245     register int        sound, silence, snum = 1, sdenom = 1;
  246 
  247     /* this weirdness avoids floating-point arithmetic */
  248     for (; sustain; sustain--)
  249     {
  250         /* See the BUGS section in the man page for discussion */
  251         snum *= NUM_MULT;
  252         sdenom *= DENOM_MULT;
  253     }
  254 
  255     if (value == 0 || sdenom == 0)
  256         return;
  257 
  258     if (pitch == -1)
  259         rest(whole * snum / (value * sdenom));
  260     else
  261     {
  262         sound = (whole * snum) / (value * sdenom)
  263                 - (whole * (FILLTIME - fill)) / (value * FILLTIME);
  264         silence = whole * (FILLTIME-fill) * snum / (FILLTIME * value * sdenom);
  265 
  266 #ifdef DEBUG
  267         (void) printf("playtone: pitch %d for %d ticks, rest for %d ticks\n",
  268                         pitch, sound, silence);
  269 #endif /* DEBUG */
  270 
  271         tone(pitchtab[pitch], sound);
  272         if (fill != LEGATO)
  273             rest(silence);
  274     }
  275 }
  276 
  277 static int
  278 abs(n)
  279         int n;
  280 {
  281     if (n < 0)
  282         return(-n);
  283     else
  284         return(n);
  285 }
  286 
  287 /* interpret and play an item from a notation string */
  288 static void
  289 playstring(cp, slen)
  290         char    *cp;
  291         size_t  slen;
  292 {
  293     int         pitch, oldfill, lastpitch = OCTAVE_NOTES * DFLT_OCTAVE;
  294 
  295 #define GETNUM(cp, v)   for(v=0; isdigit(cp[1]) && slen > 0; ) \
  296                                 {v = v * 10 + (*++cp - ''); slen--;}
  297     for (; slen--; cp++)
  298     {
  299         int             sustain, timeval, tempo;
  300         register char   c = toupper(*cp);
  301 
  302 #ifdef DEBUG
  303         (void) printf("playstring: %c (%x)\n", c, c);
  304 #endif /* DEBUG */
  305 
  306         switch (c)
  307         {
  308         case 'A':  case 'B': case 'C': case 'D': case 'E': case 'F': case 'G':
  309 
  310             /* compute pitch */
  311             pitch = notetab[c - 'A'] + octave * OCTAVE_NOTES;
  312 
  313             /* this may be followed by an accidental sign */
  314             if (cp[1] == '#' || cp[1] == '+')
  315             {
  316                 ++pitch;
  317                 ++cp;
  318                 slen--;
  319             }
  320             else if (cp[1] == '-')
  321             {
  322                 --pitch;
  323                 ++cp;
  324                 slen--;
  325             }
  326 
  327             /*
  328              * If octave-tracking mode is on, and there has been no octave-
  329              * setting prefix, find the version of the current letter note
  330              * closest to the last regardless of octave.
  331              */
  332             if (octtrack && !octprefix)
  333             {
  334                 if (abs(pitch-lastpitch) > abs(pitch+OCTAVE_NOTES-lastpitch))
  335                 {
  336                     ++octave;
  337                     pitch += OCTAVE_NOTES;
  338                 }
  339 
  340                 if (abs(pitch-lastpitch) > abs((pitch-OCTAVE_NOTES)-lastpitch))
  341                 {
  342                     --octave;
  343                     pitch -= OCTAVE_NOTES;
  344                 }
  345             }
  346             octprefix = FALSE;
  347             lastpitch = pitch;
  348 
  349             /* ...which may in turn be followed by an override time value */
  350             GETNUM(cp, timeval);
  351             if (timeval <= 0 || timeval > MIN_VALUE)
  352                 timeval = value;
  353 
  354             /* ...and/or sustain dots */
  355             for (sustain = 0; cp[1] == '.'; cp++)
  356             {
  357                 slen--;
  358                 sustain++;
  359             }
  360 
  361             /* ...and/or a slur mark */
  362             oldfill = fill;
  363             if (cp[1] == '_')
  364             {
  365                 fill = LEGATO;
  366                 ++cp;
  367                 slen--;
  368             }
  369 
  370             /* time to emit the actual tone */
  371             playtone(pitch, timeval, sustain);
  372 
  373             fill = oldfill;
  374             break;
  375 
  376         case 'O':
  377             if (cp[1] == 'N' || cp[1] == 'n')
  378             {
  379                 octprefix = octtrack = FALSE;
  380                 ++cp;
  381                 slen--;
  382             }
  383             else if (cp[1] == 'L' || cp[1] == 'l')
  384             {
  385                 octtrack = TRUE;
  386                 ++cp;
  387                 slen--;
  388             }
  389             else
  390             {
  391                 GETNUM(cp, octave);
  392                 if (octave >= sizeof(pitchtab) / sizeof(pitchtab[0]) / OCTAVE_NOTES)
  393                     octave = DFLT_OCTAVE;
  394                 octprefix = TRUE;
  395             }
  396             break;
  397 
  398         case '>':
  399             if (octave < sizeof(pitchtab) / sizeof(pitchtab[0]) / OCTAVE_NOTES - 1)
  400                 octave++;
  401             octprefix = TRUE;
  402             break;
  403 
  404         case '<':
  405             if (octave > 0)
  406                 octave--;
  407             octprefix = TRUE;
  408             break;
  409 
  410         case 'N':
  411             GETNUM(cp, pitch);
  412             for (sustain = 0; cp[1] == '.'; cp++)
  413             {
  414                 slen--;
  415                 sustain++;
  416             }
  417             oldfill = fill;
  418             if (cp[1] == '_')
  419             {
  420                 fill = LEGATO;
  421                 ++cp;
  422                 slen--;
  423             }
  424             playtone(pitch - 1, value, sustain);
  425             fill = oldfill;
  426             break;
  427 
  428         case 'L':
  429             GETNUM(cp, value);
  430             if (value <= 0 || value > MIN_VALUE)
  431                 value = DFLT_VALUE;
  432             break;
  433 
  434         case 'P':
  435         case '~':
  436             /* this may be followed by an override time value */
  437             GETNUM(cp, timeval);
  438             if (timeval <= 0 || timeval > MIN_VALUE)
  439                 timeval = value;
  440             for (sustain = 0; cp[1] == '.'; cp++)
  441             {
  442                 slen--;
  443                 sustain++;
  444             }
  445             playtone(-1, timeval, sustain);
  446             break;
  447 
  448         case 'T':
  449             GETNUM(cp, tempo);
  450             if (tempo < MIN_TEMPO || tempo > MAX_TEMPO)
  451                 tempo = DFLT_TEMPO;
  452             whole = (hz * SECS_PER_MIN * WHOLE_NOTE) / tempo;
  453             break;
  454 
  455         case 'M':
  456             if (cp[1] == 'N' || cp[1] == 'n')
  457             {
  458                 fill = NORMAL;
  459                 ++cp;
  460                 slen--;
  461             }
  462             else if (cp[1] == 'L' || cp[1] == 'l')
  463             {
  464                 fill = LEGATO;
  465                 ++cp;
  466                 slen--;
  467             }
  468             else if (cp[1] == 'S' || cp[1] == 's')
  469             {
  470                 fill = STACCATO;
  471                 ++cp;
  472                 slen--;
  473             }
  474             break;
  475         }
  476     }
  477 }
  478 
  479 /******************* UNIX DRIVER HOOKS BEGIN HERE **************************
  480  *
  481  * This section implements driver hooks to run playstring() and the tone(),
  482  * endtone(), and rest() functions defined above.
  483  */
  484 
  485 static int spkr_active = FALSE; /* exclusion flag */
  486 static char *spkr_inbuf;  /* incoming buf */
  487 
  488 static int
  489 spkropen(dev, flags, fmt, td)
  490         dev_t           dev;
  491         int             flags;
  492         int             fmt;
  493         struct thread   *td;
  494 {
  495 #ifdef DEBUG
  496     (void) printf("spkropen: entering with dev = %s\n", devtoname(dev));
  497 #endif /* DEBUG */
  498 
  499     if (minor(dev) != 0)
  500         return(ENXIO);
  501     else if (spkr_active)
  502         return(EBUSY);
  503     else
  504     {
  505 #ifdef DEBUG
  506         (void) printf("spkropen: about to perform play initialization\n");
  507 #endif /* DEBUG */
  508         playinit();
  509         spkr_inbuf = malloc(DEV_BSIZE, M_SPKR, M_WAITOK);
  510         spkr_active = TRUE;
  511         return(0);
  512     }
  513 }
  514 
  515 static int
  516 spkrwrite(dev, uio, ioflag)
  517         dev_t           dev;
  518         struct uio      *uio;
  519         int             ioflag;
  520 {
  521 #ifdef DEBUG
  522     printf("spkrwrite: entering with dev = %s, count = %d\n",
  523                 devtoname(dev), uio->uio_resid);
  524 #endif /* DEBUG */
  525 
  526     if (minor(dev) != 0)
  527         return(ENXIO);
  528     else if (uio->uio_resid > (DEV_BSIZE - 1))     /* prevent system crashes */
  529         return(E2BIG);
  530     else
  531     {
  532         unsigned n;
  533         char *cp;
  534         int error;
  535 
  536         n = uio->uio_resid;
  537         cp = spkr_inbuf;
  538         error = uiomove(cp, n, uio);
  539         if (!error) {
  540                 cp[n] = '\0';
  541                 playstring(cp, n);
  542         }
  543         return(error);
  544     }
  545 }
  546 
  547 static int
  548 spkrclose(dev, flags, fmt, td)
  549         dev_t           dev;
  550         int             flags;
  551         int             fmt;
  552         struct thread   *td;
  553 {
  554 #ifdef DEBUG
  555     (void) printf("spkrclose: entering with dev = %s\n", devtoname(dev));
  556 #endif /* DEBUG */
  557 
  558     if (minor(dev) != 0)
  559         return(ENXIO);
  560     else
  561     {
  562         wakeup((caddr_t)&endtone);
  563         wakeup((caddr_t)&endrest);
  564         free(spkr_inbuf, M_SPKR);
  565         spkr_active = FALSE;
  566         return(0);
  567     }
  568 }
  569 
  570 static int
  571 spkrioctl(dev, cmd, cmdarg, flags, td)
  572         dev_t           dev;
  573         unsigned long   cmd;
  574         caddr_t         cmdarg;
  575         int             flags;
  576         struct thread   *td;
  577 {
  578 #ifdef DEBUG
  579     (void) printf("spkrioctl: entering with dev = %s, cmd = %lx\n",
  580         devtoname(dev), cmd);
  581 #endif /* DEBUG */
  582 
  583     if (minor(dev) != 0)
  584         return(ENXIO);
  585     else if (cmd == SPKRTONE)
  586     {
  587         tone_t  *tp = (tone_t *)cmdarg;
  588 
  589         if (tp->frequency == 0)
  590             rest(tp->duration);
  591         else
  592             tone(tp->frequency, tp->duration);
  593         return 0;
  594     }
  595     else if (cmd == SPKRTUNE)
  596     {
  597         tone_t  *tp = (tone_t *)(*(caddr_t *)cmdarg);
  598         tone_t ttp;
  599         int error;
  600 
  601         for (; ; tp++) {
  602             error = copyin(tp, &ttp, sizeof(tone_t));
  603             if (error)
  604                     return(error);
  605             if (ttp.duration == 0)
  606                     break;
  607             if (ttp.frequency == 0)
  608                  rest(ttp.duration);
  609             else
  610                  tone(ttp.frequency, ttp.duration);
  611         }
  612         return(0);
  613     }
  614     return(EINVAL);
  615 }
  616 
  617 /*
  618  * Install placeholder to claim the resources owned by the
  619  * AT tone generator.
  620  */
  621 static struct isa_pnp_id speaker_ids[] = {
  622 #ifndef PC98
  623         { 0x0008d041 /* PNP0800 */, "PC speaker" },
  624 #endif
  625         { 0 }
  626 };
  627 
  628 static dev_t speaker_dev;
  629 
  630 static int
  631 speaker_probe(device_t dev)
  632 {
  633         int     error;
  634 
  635         error = ISA_PNP_PROBE(device_get_parent(dev), dev, speaker_ids);
  636         
  637         /* PnP match */
  638         if (error == 0)
  639                 return (0);
  640 
  641         /* No match */
  642         if (error == ENXIO)
  643                 return (ENXIO);
  644 
  645         /* Not configured by hints. */
  646         if (strncmp(device_get_name(dev), "speaker", 9))
  647                 return (ENXIO);
  648 
  649         device_set_desc(dev, "PC speaker");
  650 
  651         return (0);
  652 }
  653 
  654 static int
  655 speaker_attach(device_t dev)
  656 {
  657 
  658         if (speaker_dev) {
  659                 device_printf(dev, "Already attached!\n");
  660                 return (ENXIO);
  661         }
  662 
  663         speaker_dev = make_dev(&spkr_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
  664             "speaker");
  665         return (0);
  666 }
  667 
  668 static int
  669 speaker_detach(device_t dev)
  670 {
  671         destroy_dev(speaker_dev);
  672         return (0);
  673 }
  674 
  675 static device_method_t speaker_methods[] = {
  676         /* Device interface */
  677         DEVMETHOD(device_probe,         speaker_probe),
  678         DEVMETHOD(device_attach,        speaker_attach),
  679         DEVMETHOD(device_detach,        speaker_detach),
  680         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
  681         DEVMETHOD(device_suspend,       bus_generic_suspend),
  682         DEVMETHOD(device_resume,        bus_generic_resume),
  683         { 0, 0 }
  684 };
  685 
  686 static driver_t speaker_driver = {
  687         "speaker",
  688         speaker_methods,
  689         1,              /* no softc */
  690 };
  691 
  692 static devclass_t speaker_devclass;
  693 
  694 DRIVER_MODULE(speaker, isa, speaker_driver, speaker_devclass, 0, 0);
  695 #ifndef PC98
  696 DRIVER_MODULE(speaker, acpi, speaker_driver, speaker_devclass, 0, 0);
  697 #endif
  698 
  699 /* spkr.c ends here */

Cache object: 67af939a0452f40ca50e256e65b2a1ef


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.