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/drivers/sb16/sb16_dsp.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* This file contains the driver for a DSP (Digital Sound Processor) on
    2  * a SoundBlaster 16 soundcard.
    3  *
    4  * The driver supports the following operations (using message format m2):
    5  *
    6  *    m_type      DEVICE    PROC_NR     COUNT    POSITION  ADRRESS
    7  * ----------------------------------------------------------------
    8  * |  DEV_OPEN  | device  | proc nr |         |         |         |
    9  * |------------+---------+---------+---------+---------+---------|
   10  * |  DEV_CLOSE | device  | proc nr |         |         |         |
   11  * |------------+---------+---------+---------+---------+---------|
   12  * |  DEV_READ  | device  | proc nr |  bytes  |         | buf ptr |
   13  * |------------+---------+---------+---------+---------+---------|
   14  * |  DEV_WRITE | device  | proc nr |  bytes  |         | buf ptr |
   15  * |------------+---------+---------+---------+---------+---------|
   16  * |  DEV_IOCTL | device  | proc nr |func code|         | buf ptr |
   17  * ----------------------------------------------------------------
   18  *
   19  * The file contains one entry point:
   20  *
   21  *   main:      main entry when driver is brought up
   22  *      
   23  *  August 24 2005              Ported driver to user space (only audio playback) (Peter Boonstoppel)
   24  *  May 20 1995                 Author: Michel R. Prevenier 
   25  */
   26 
   27 #include "sb16.h"
   28 
   29 
   30 _PROTOTYPE(void main, (void));
   31 FORWARD _PROTOTYPE( int dsp_open, (void) );
   32 FORWARD _PROTOTYPE( int dsp_close, (void) );
   33 FORWARD _PROTOTYPE( int dsp_ioctl, (message *m_ptr) );
   34 FORWARD _PROTOTYPE( void dsp_write, (message *m_ptr) );
   35 FORWARD _PROTOTYPE( void dsp_hardware_msg, (void) );
   36 FORWARD _PROTOTYPE( void dsp_status, (message *m_ptr) );
   37 
   38 FORWARD _PROTOTYPE( void reply, (int code, int replyee, int process, int status) );
   39 FORWARD _PROTOTYPE( void init_buffer, (void) );
   40 FORWARD _PROTOTYPE( int dsp_init, (void) );
   41 FORWARD _PROTOTYPE( int dsp_reset, (void) );
   42 FORWARD _PROTOTYPE( int dsp_command, (int value) );
   43 FORWARD _PROTOTYPE( int dsp_set_size, (unsigned int size) );
   44 FORWARD _PROTOTYPE( int dsp_set_speed, (unsigned int speed) );
   45 FORWARD _PROTOTYPE( int dsp_set_stereo, (unsigned int stereo) );
   46 FORWARD _PROTOTYPE( int dsp_set_bits, (unsigned int bits) );
   47 FORWARD _PROTOTYPE( int dsp_set_sign, (unsigned int sign) );
   48 FORWARD _PROTOTYPE( void dsp_dma_setup, (phys_bytes address, int count) );
   49 FORWARD _PROTOTYPE( void dsp_setup, (void) );
   50 
   51 PRIVATE int irq_hook_id;        /* id of irq hook at the kernel */
   52 
   53 PRIVATE char DmaBuffer[DMA_SIZE + 64 * 1024];
   54 PRIVATE char* DmaPtr;
   55 PRIVATE phys_bytes DmaPhys;
   56 
   57 PRIVATE char Buffer[DSP_MAX_FRAGMENT_SIZE * DSP_NR_OF_BUFFERS];
   58 
   59 PRIVATE int DspVersion[2]; 
   60 PRIVATE unsigned int DspStereo = DEFAULT_STEREO;
   61 PRIVATE unsigned int DspSpeed = DEFAULT_SPEED; 
   62 PRIVATE unsigned int DspBits = DEFAULT_BITS;
   63 PRIVATE unsigned int DspSign = DEFAULT_SIGN;
   64 PRIVATE unsigned int DspFragmentSize = DSP_MAX_FRAGMENT_SIZE;
   65 PRIVATE int DspAvail = 0;
   66 PRIVATE int DspBusy = 0;
   67 PRIVATE int DmaMode = 0;
   68 PRIVATE int DmaBusy = -1;
   69 PRIVATE int DmaFillNext = 0;
   70 PRIVATE int BufReadNext = -1;
   71 PRIVATE int BufFillNext = 0;
   72 
   73 PRIVATE int revivePending = 0;
   74 PRIVATE int reviveStatus;
   75 PRIVATE int reviveProcNr;
   76 
   77 #define dprint (void)
   78 
   79 
   80 /*===========================================================================*
   81  *                              main
   82  *===========================================================================*/
   83 PUBLIC void main() 
   84 {       
   85         int r, caller, proc_nr, s;
   86         message mess;
   87 
   88         dprint("sb16_dsp.c: main()\n");
   89 
   90         /* Get a DMA buffer. */
   91         init_buffer();
   92 
   93         while(TRUE) {
   94                 /* Wait for an incoming message */
   95                 receive(ANY, &mess);
   96 
   97                 caller = mess.m_source;
   98                 proc_nr = mess.PROC_NR;
   99 
  100                 /* Now carry out the work. */
  101                 switch(mess.m_type) {
  102                         case DEV_OPEN:          r = dsp_open(); break;
  103                         case DEV_CLOSE:         r = dsp_close(); break;
  104                         case DEV_IOCTL:         r = dsp_ioctl(&mess); break;
  105 
  106                         case DEV_READ:          r = EINVAL; break; /* Not yet implemented */
  107                         case DEV_WRITE:         dsp_write(&mess); continue; /* don't reply */
  108                         
  109                         case DEV_STATUS:        dsp_status(&mess); continue; /* don't reply */
  110                         case HARD_INT:          dsp_hardware_msg(); continue; /* don't reply */
  111                         case SYS_SIG:           continue; /* don't reply */
  112                         default:                        r = EINVAL;
  113                 }
  114 
  115                 /* Finally, prepare and send the reply message. */
  116                 reply(TASK_REPLY, caller, proc_nr, r);
  117         }
  118 
  119 }
  120 
  121 
  122 /*===========================================================================*
  123  *                              dsp_open
  124  *===========================================================================*/
  125 PRIVATE int dsp_open()
  126 {
  127         dprint("sb16_dsp.c: dsp_open()\n");
  128         
  129         /* try to detect SoundBlaster card */
  130         if(!DspAvail && dsp_init() != OK) return EIO;
  131 
  132         /* Only one open at a time with soundcards */
  133         if(DspBusy) return EBUSY;
  134 
  135         /* Start with a clean DSP */
  136         if(dsp_reset() != OK) return EIO;
  137 
  138         /* Setup default values */
  139         DspStereo = DEFAULT_STEREO;
  140         DspSpeed = DEFAULT_SPEED;
  141         DspBits = DEFAULT_BITS;
  142         DspSign = DEFAULT_SIGN;
  143         DspFragmentSize = DMA_SIZE / 2;
  144 
  145         DspBusy = 1;
  146 
  147         return OK;
  148 }
  149 
  150 
  151 /*===========================================================================*
  152  *                              dsp_close
  153  *===========================================================================*/
  154 PRIVATE int dsp_close()
  155 {
  156         dprint("sb16_dsp.c: dsp_close()\n");
  157 
  158         DspBusy = 0;                  /* soundcard available again */
  159 
  160         return OK;
  161 }
  162 
  163 
  164 /*===========================================================================*
  165  *                              dsp_ioctl
  166  *===========================================================================*/
  167 PRIVATE int dsp_ioctl(m_ptr)
  168 message *m_ptr;
  169 {
  170         int status;
  171         phys_bytes user_phys;
  172         unsigned int val;
  173 
  174         dprint("sb16_dsp.c: dsp_ioctl()\n");
  175 
  176         /* Cannot change parameters during play or recording */
  177         if(DmaBusy >= 0) return EBUSY;
  178 
  179         /* Get user data */
  180         if(m_ptr->REQUEST != DSPIORESET) {
  181                 sys_vircopy(m_ptr->PROC_NR, D, (vir_bytes)m_ptr->ADDRESS, SELF, D, (vir_bytes)&val, sizeof(val));
  182         }
  183 
  184         dprint("dsp_ioctl: got ioctl %d, argument: %d\n", m_ptr->REQUEST, val);
  185 
  186         switch(m_ptr->REQUEST) {
  187                 case DSPIORATE:         status = dsp_set_speed(val); break;
  188                 case DSPIOSTEREO:       status = dsp_set_stereo(val); break;
  189                 case DSPIOBITS:         status = dsp_set_bits(val); break;
  190                 case DSPIOSIZE:         status = dsp_set_size(val); break;
  191                 case DSPIOSIGN:         status = dsp_set_sign(val); break;
  192                 case DSPIOMAX: 
  193                         val = DSP_MAX_FRAGMENT_SIZE;
  194                         sys_vircopy(SELF, D, (vir_bytes)&val, m_ptr->PROC_NR, D, (vir_bytes)m_ptr->ADDRESS, sizeof(val));
  195                         status = OK;
  196                         break;
  197                 case DSPIORESET:    status = dsp_reset(); break;
  198                 default:            status = ENOTTY; break;
  199         }
  200 
  201         return status;
  202 }
  203 
  204 
  205 /*===========================================================================*
  206  *                              dsp_write
  207  *===========================================================================*/
  208 PRIVATE void dsp_write(m_ptr)
  209 message *m_ptr;
  210 {
  211         int s;
  212         message mess;
  213         
  214         dprint("sb16_dsp.c: dsp_write()\n");
  215 
  216         if(m_ptr->COUNT != DspFragmentSize) {
  217                 reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, EINVAL);
  218                 return;
  219         }
  220         if(m_ptr->m_type != DmaMode && DmaBusy >= 0) {
  221                 reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, EBUSY);
  222                 return;
  223         }
  224         
  225         reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, SUSPEND);
  226 
  227         if(DmaBusy < 0) { /* Dma tranfer not yet started */
  228 
  229                 DmaMode = DEV_WRITE;           /* Dma mode is writing */
  230                 sys_datacopy(m_ptr->PROC_NR, (vir_bytes)m_ptr->ADDRESS, SELF, (vir_bytes)DmaPtr, (phys_bytes)DspFragmentSize);
  231                 dsp_dma_setup(DmaPhys, DspFragmentSize * DMA_NR_OF_BUFFERS);
  232                 dsp_setup();
  233                 DmaBusy = 0;         /* Dma is busy */
  234                 dprint(" filled dma[0]\n");
  235                 DmaFillNext = 1;
  236 
  237         } else if(DmaBusy != DmaFillNext) { /* Dma transfer started, but Dma buffer not yet full */
  238 
  239                 sys_datacopy(m_ptr->PROC_NR, (vir_bytes)m_ptr->ADDRESS, SELF, (vir_bytes)DmaPtr + DmaFillNext * DspFragmentSize, (phys_bytes)DspFragmentSize);
  240                 dprint(" filled dma[%d]\n", DmaFillNext);
  241                 DmaFillNext = (DmaFillNext + 1) % DMA_NR_OF_BUFFERS;
  242 
  243         } else if(BufReadNext < 0) { /* Dma buffer full, fill first element of second buffer */ 
  244 
  245                 sys_datacopy(m_ptr->PROC_NR, (vir_bytes)m_ptr->ADDRESS, SELF, (vir_bytes)Buffer, (phys_bytes)DspFragmentSize);
  246                 dprint(" filled buf[0]\n");
  247                 BufReadNext = 0;
  248                 BufFillNext = 1;
  249 
  250         } else { /* Dma buffer is full, filling second buffer */ 
  251 
  252                 while(BufReadNext == BufFillNext) { /* Second buffer also full, wait for space to become available */ 
  253                         receive(HARDWARE, &mess);
  254                         dsp_hardware_msg();
  255                 }
  256                 sys_datacopy(m_ptr->PROC_NR, (vir_bytes)m_ptr->ADDRESS, SELF, (vir_bytes)Buffer + BufFillNext * DspFragmentSize, (phys_bytes)DspFragmentSize);
  257                 dprint(" filled buf[%d]\n", BufFillNext);
  258                 BufFillNext = (BufFillNext + 1) % DSP_NR_OF_BUFFERS;
  259 
  260         } 
  261         
  262         revivePending = 1;
  263         reviveStatus = DspFragmentSize;
  264         reviveProcNr = m_ptr->PROC_NR;
  265         notify(m_ptr->m_source);
  266 }
  267 
  268 
  269 /*===========================================================================*
  270  *                              dsp_hardware_msg
  271  *===========================================================================*/
  272 PRIVATE void dsp_hardware_msg()
  273 {       
  274         dprint("Interrupt: ");
  275         if(DmaBusy >= 0) { /* Dma transfer was actually busy */
  276                 dprint("Finished playing dma[%d]; ", DmaBusy);
  277                 DmaBusy = (DmaBusy + 1) % DMA_NR_OF_BUFFERS;
  278                 if(DmaBusy == DmaFillNext) { /* Dma buffer empty, stop Dma transfer */
  279 
  280                         dsp_command((DspBits == 8 ? DSP_CMD_DMA8HALT : DSP_CMD_DMA16HALT));
  281                         dprint("No more work...!\n");
  282                         DmaBusy = -1;
  283 
  284                 } else if(BufReadNext >= 0) { /* Data in second buffer, copy one fragment to Dma buffer */
  285                         
  286                         /* Acknowledge the interrupt on the DSP */
  287                         sb16_inb((DspBits == 8 ? DSP_DATA_AVL : DSP_DATA16_AVL));
  288 
  289                         memcpy(DmaPtr + DmaFillNext * DspFragmentSize, Buffer + BufReadNext * DspFragmentSize, DspFragmentSize);
  290                         dprint("copy buf[%d] -> dma[%d]; ", BufReadNext, DmaFillNext);
  291                         BufReadNext = (BufReadNext + 1) % DSP_NR_OF_BUFFERS;
  292                         DmaFillNext = (DmaFillNext + 1) % DMA_NR_OF_BUFFERS;
  293                         if(BufReadNext == BufFillNext) {
  294                                 BufReadNext = -1;
  295                         } 
  296                         dprint("Starting dma[%d]\n", DmaBusy);
  297                         
  298                         return;
  299 
  300                 } else { /* Second buffer empty, still data in Dma buffer, continue playback */
  301                         dprint("Starting dma[%d]\n", DmaBusy);
  302                 }
  303         }
  304 
  305         /* Acknowledge the interrupt on the DSP */
  306         sb16_inb((DspBits == 8 ? DSP_DATA_AVL : DSP_DATA16_AVL));
  307 }
  308 
  309 
  310 /*===========================================================================*
  311  *                              dsp_status                                   *
  312  *===========================================================================*/
  313 PRIVATE void dsp_status(m_ptr)
  314 message *m_ptr; /* pointer to the newly arrived message */
  315 {
  316         if(revivePending) {
  317                 m_ptr->m_type = DEV_REVIVE;                     /* build message */
  318                 m_ptr->REP_PROC_NR = reviveProcNr;
  319                 m_ptr->REP_STATUS = reviveStatus;
  320 
  321                 revivePending = 0;                                      /* unmark event */
  322         } else {
  323                 m_ptr->m_type = DEV_NO_STATUS;
  324         }
  325 
  326         send(m_ptr->m_source, m_ptr);                   /* send the message */
  327 }
  328 
  329 
  330 /*===========================================================================*
  331  *                              reply                                        *
  332  *===========================================================================*/
  333 PRIVATE void reply(code, replyee, process, status)
  334 int code;
  335 int replyee;
  336 int process;
  337 int status;
  338 {
  339         message m;
  340 
  341         m.m_type = code;                /* TASK_REPLY or REVIVE */
  342         m.REP_STATUS = status;  /* result of device operation */
  343         m.REP_PROC_NR = process;        /* which user made the request */
  344 
  345         send(replyee, &m);
  346 }
  347 
  348 
  349 /*===========================================================================*
  350  *                              init_buffer
  351  *===========================================================================*/
  352 PRIVATE void init_buffer()
  353 {
  354 /* Select a buffer that can safely be used for dma transfers.  
  355  * Its absolute address is 'DmaPhys', the normal address is 'DmaPtr'.
  356  */
  357 
  358 #if (CHIP == INTEL)
  359         unsigned left;
  360 
  361         DmaPtr = DmaBuffer;
  362         sys_umap(SELF, D, (vir_bytes)DmaBuffer, (phys_bytes)sizeof(DmaBuffer), &DmaPhys);
  363 
  364         if((left = dma_bytes_left(DmaPhys)) < DMA_SIZE) {
  365                 /* First half of buffer crosses a 64K boundary, can't DMA into that */
  366                 DmaPtr += left;
  367                 DmaPhys += left;
  368         }
  369 #else /* CHIP != INTEL */
  370         panic("SB16DSP","init_buffer() failed, CHIP != INTEL", 0);
  371 #endif /* CHIP == INTEL */
  372 }
  373 
  374 
  375 /*===========================================================================*
  376  *                              dsp_init
  377  *===========================================================================*/
  378 PRIVATE int dsp_init()
  379 {
  380         int i, s;
  381 
  382         if(dsp_reset () != OK) { 
  383                 dprint("sb16: No SoundBlaster card detected\n");
  384                 return -1;
  385         }
  386 
  387         DspVersion[0] = DspVersion[1] = 0;
  388         dsp_command(DSP_GET_VERSION);   /* Get DSP version bytes */
  389 
  390         for(i = 1000; i; i--) {
  391                 if(sb16_inb(DSP_DATA_AVL) & 0x80) {             
  392                         if(DspVersion[0] == 0) {
  393                                 DspVersion[0] = sb16_inb(DSP_READ);
  394                         } else {
  395                                 DspVersion[1] = sb16_inb(DSP_READ);
  396                                 break;
  397                         }
  398                 }
  399         }
  400 
  401         if(DspVersion[0] < 4) {
  402                 dprint("sb16: No SoundBlaster 16 compatible card detected\n");
  403                 return -1;
  404         } 
  405         
  406         dprint("sb16: SoundBlaster DSP version %d.%d detected\n", DspVersion[0], DspVersion[1]);
  407 
  408         /* set SB to use our IRQ and DMA channels */
  409         mixer_set(MIXER_SET_IRQ, (1 << (SB_IRQ / 2 - 1)));
  410         mixer_set(MIXER_SET_DMA, (1 << SB_DMA_8 | 1 << SB_DMA_16)); 
  411 
  412         /* register interrupt vector and enable irq */
  413         if ((s=sys_irqsetpolicy(SB_IRQ, IRQ_REENABLE, &irq_hook_id )) != OK)
  414                 panic("SB16DSP", "Couldn't set IRQ policy", s);
  415         if ((s=sys_irqenable(&irq_hook_id)) != OK)
  416                 panic("SB16DSP", "Couldn't enable IRQ", s);
  417 
  418         DspAvail = 1;
  419         return OK;
  420 }
  421 
  422 
  423 /*===========================================================================*
  424  *                              dsp_reset
  425  *===========================================================================*/
  426 PRIVATE int dsp_reset()
  427 {
  428         int i;
  429 
  430         sb16_outb(DSP_RESET, 1);
  431         for(i = 0; i < 1000; i++); /* wait a while */
  432         sb16_outb(DSP_RESET, 0);
  433 
  434         for(i = 0; i < 1000 && !(sb16_inb(DSP_DATA_AVL) & 0x80); i++);  
  435         
  436         if(sb16_inb(DSP_READ) != 0xAA) return EIO; /* No SoundBlaster */
  437 
  438         DmaBusy = -1;
  439 
  440         return OK;
  441 }
  442 
  443 
  444 /*===========================================================================*
  445  *                              dsp_command
  446  *===========================================================================*/
  447 PRIVATE int dsp_command(value)
  448 int value;
  449 {
  450         int i, status;
  451 
  452         for (i = 0; i < SB_TIMEOUT; i++) {
  453                 if((sb16_inb(DSP_STATUS) & 0x80) == 0) {
  454                         sb16_outb(DSP_COMMAND, value);
  455                         return OK;
  456                 }
  457         }
  458 
  459         dprint("sb16: SoundBlaster: DSP Command(%x) timeout\n", value);
  460         return -1;
  461 }
  462 
  463 
  464 /*===========================================================================*
  465  *                              dsp_set_size
  466  *===========================================================================*/
  467 static int dsp_set_size(size)
  468 unsigned int size;
  469 {
  470         dprint("dsp_set_size(): set fragment size to %u\n", size);
  471 
  472         /* Sanity checks */
  473         if(size < DSP_MIN_FRAGMENT_SIZE || size > DSP_MAX_FRAGMENT_SIZE || size % 2 != 0) {
  474                 return EINVAL;
  475         }
  476 
  477         DspFragmentSize = size; 
  478 
  479         return OK;
  480 }
  481 
  482 
  483 /*===========================================================================*
  484  *                              dsp_set_speed
  485  *===========================================================================*/
  486 static int dsp_set_speed(speed)
  487 unsigned int speed;
  488 {
  489         dprint("sb16: setting speed to %u, stereo = %d\n", speed, DspStereo);
  490 
  491         if(speed < DSP_MIN_SPEED || speed > DSP_MAX_SPEED) {
  492                 return EPERM;
  493         }
  494 
  495         /* Soundblaster 16 can be programmed with real sample rates
  496         * instead of time constants
  497         *
  498         * Since you cannot sample and play at the same time
  499         * we set in- and output rate to the same value 
  500         */
  501 
  502         dsp_command(DSP_INPUT_RATE);            /* set input rate */
  503         dsp_command(speed >> 8);                        /* high byte of speed */
  504         dsp_command(speed);                                     /* low byte of speed */
  505         dsp_command(DSP_OUTPUT_RATE);           /* same for output rate */
  506         dsp_command(speed >> 8);        
  507         dsp_command(speed); 
  508 
  509         DspSpeed = speed;
  510 
  511         return OK;
  512 }
  513 
  514 
  515 /*===========================================================================*
  516  *                              dsp_set_stereo
  517  *===========================================================================*/
  518 static int dsp_set_stereo(stereo)
  519 unsigned int stereo;
  520 {
  521         if(stereo) { 
  522                 DspStereo = 1;
  523         } else { 
  524                 DspStereo = 0;
  525         }
  526 
  527         return OK;
  528 }
  529 
  530 
  531 /*===========================================================================*
  532  *                              dsp_set_bits
  533  *===========================================================================*/
  534 static int dsp_set_bits(bits)
  535 unsigned int bits;
  536 {
  537         /* Sanity checks */
  538         if(bits != 8 && bits != 16) {
  539                 return EINVAL;
  540         }
  541 
  542         DspBits = bits; 
  543 
  544         return OK;
  545 }
  546 
  547 
  548 /*===========================================================================*
  549  *                              dsp_set_sign
  550  *===========================================================================*/
  551 static int dsp_set_sign(sign)
  552 unsigned int sign;
  553 {
  554         dprint("sb16: set sign to %u\n", sign);
  555 
  556         DspSign = (sign > 0 ? 1 : 0); 
  557 
  558         return OK;
  559 }
  560 
  561 
  562 /*===========================================================================*
  563  *                              dsp_dma_setup
  564  *===========================================================================*/
  565 PRIVATE void dsp_dma_setup(address, count)
  566 phys_bytes address;
  567 int count;
  568 {
  569         pvb_pair_t pvb[9];
  570 
  571 
  572         dprint("Setting up %d bit DMA\n", DspBits);
  573 
  574         if(DspBits == 8) {   /* 8 bit sound */
  575                 count--;     
  576 
  577                 pv_set(pvb[0], DMA8_MASK, SB_DMA_8 | 0x04);      /* Disable DMA channel */
  578                 pv_set(pvb[1], DMA8_CLEAR, 0x00);                      /* Clear flip flop */
  579 
  580                 /* set DMA mode */
  581                 pv_set(pvb[2], DMA8_MODE, (DmaMode == DEV_WRITE ? DMA8_AUTO_PLAY : DMA8_AUTO_REC)); 
  582 
  583                 pv_set(pvb[3], DMA8_ADDR, address >>  0);        /* Low_byte of address */
  584                 pv_set(pvb[4], DMA8_ADDR, address >>  8);        /* High byte of address */
  585                 pv_set(pvb[5], DMA8_PAGE, address >> 16);        /* 64K page number */
  586                 pv_set(pvb[6], DMA8_COUNT, count >> 0);          /* Low byte of count */
  587                 pv_set(pvb[7], DMA8_COUNT, count >> 8);          /* High byte of count */
  588                 pv_set(pvb[8], DMA8_MASK, SB_DMA_8);           /* Enable DMA channel */
  589 
  590                 sys_voutb(pvb, 9);
  591         } else {  /* 16 bit sound */
  592                 count-= 2;
  593 
  594                 pv_set(pvb[0], DMA16_MASK, (SB_DMA_16 & 3) | 0x04);     /* Disable DMA channel */
  595                 
  596                 pv_set(pvb[1], DMA16_CLEAR, 0x00);                  /* Clear flip flop */
  597 
  598                 /* Set dma mode */
  599                 pv_set(pvb[2], DMA16_MODE, (DmaMode == DEV_WRITE ? DMA16_AUTO_PLAY : DMA16_AUTO_REC));        
  600 
  601                 pv_set(pvb[3], DMA16_ADDR, (address >> 1) & 0xFF);  /* Low_byte of address */
  602                 pv_set(pvb[4], DMA16_ADDR, (address >> 9) & 0xFF);  /* High byte of address */
  603                 pv_set(pvb[5], DMA16_PAGE, (address >> 16) & 0xFE); /* 128K page number */
  604                 pv_set(pvb[6], DMA16_COUNT, count >> 1);            /* Low byte of count */
  605                 pv_set(pvb[7], DMA16_COUNT, count >> 9);            /* High byte of count */
  606                 pv_set(pvb[8], DMA16_MASK, SB_DMA_16 & 3);          /* Enable DMA channel */
  607 
  608                 sys_voutb(pvb, 9);
  609         }
  610 }
  611 
  612 
  613 /*===========================================================================*
  614  *                              dsp_setup()
  615  *===========================================================================*/
  616 PRIVATE void dsp_setup()
  617 { 
  618         /* Set current sample speed */
  619         dsp_set_speed(DspSpeed);
  620 
  621         /* Put the speaker on */
  622         if(DmaMode == DEV_WRITE) {
  623                 dsp_command (DSP_CMD_SPKON); /* put speaker on */
  624 
  625                 /* Program DSP with dma mode */
  626                 dsp_command((DspBits == 8 ? DSP_CMD_8BITAUTO_OUT : DSP_CMD_16BITAUTO_OUT));     
  627         } else {
  628                 dsp_command (DSP_CMD_SPKOFF); /* put speaker off */
  629 
  630                 /* Program DSP with dma mode */
  631                 dsp_command((DspBits == 8 ? DSP_CMD_8BITAUTO_IN : DSP_CMD_16BITAUTO_IN));     
  632         }
  633 
  634         /* Program DSP with transfer mode */
  635         if (!DspSign) {
  636                 dsp_command((DspStereo == 1 ? DSP_MODE_STEREO_US : DSP_MODE_MONO_US));
  637         } else {
  638                 dsp_command((DspStereo == 1 ? DSP_MODE_STEREO_S : DSP_MODE_MONO_S));
  639         }
  640 
  641         /* Give length of fragment to DSP */
  642         if (DspBits == 8) { /* 8 bit transfer */
  643                 /* #bytes - 1 */
  644                 dsp_command((DspFragmentSize - 1) >> 0); 
  645                 dsp_command((DspFragmentSize - 1) >> 8);
  646         } else {             /* 16 bit transfer */
  647                 /* #words - 1 */
  648                 dsp_command((DspFragmentSize - 1) >> 1);
  649                 dsp_command((DspFragmentSize - 1) >> 9);
  650         }
  651 }
  652 
  653   

Cache object: 53b894c024784696c79178e71de8e737


[ 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.