+++ /dev/null
-#ifndef SB16_H
-#define SB16_H
-
-#include <minix/drivers.h>
-#include <minix/driver.h>
-#include <sys/ioc_sound.h>
-#include <minix/sound.h>
-
-#define SB_TIMEOUT 32000 /* timeout count */
-
-/* IRQ, base address and DMA channels */
-#define SB_IRQ 7
-#define SB_BASE_ADDR 0x220 /* 0x210, 0x220, 0x230, 0x240,
- * 0x250, 0x260, 0x280
- */
-#define SB_DMA_8 1 /* 0, 1, 3 */
-#define SB_DMA_16 5 /* 5, 6, 7 */
-#if _WORD_SIZE == 2
-#define DMA_SIZE 8192 /* Dma buffer MUST BE MULTIPLE OF 2 */
-#else
-#define DMA_SIZE (64 * 1024) /* Dma buffer MUST BE MULTIPLE OF 2 */
-#endif
-
-/* Some defaults for the DSP */
-#define DEFAULT_SPEED 22050 /* Sample rate */
-#define DEFAULT_BITS 8 /* Nr. of bits */
-#define DEFAULT_SIGN 0 /* 0 = unsigned, 1 = signed */
-#define DEFAULT_STEREO 0 /* 0 = mono, 1 = stereo */
-
-/* DMA port addresses */
-#define DMA8_ADDR (((SB_DMA_8 & 3) << 1) + 0x00)
-#define DMA8_COUNT (((SB_DMA_8 & 3) << 1) + 0x01)
-#define DMA8_MASK 0x0A
-#define DMA8_MODE 0x0B
-#define DMA8_CLEAR 0x0C
-
-
-/* If after this preprocessing stuff DMA8_PAGE is not defined
- * the 8-bit DMA channel specified is not valid
- */
-#if SB_DMA_8 == 0
-# define DMA8_PAGE 0x87
-#else
-# if SB_DMA_8 == 1
-# define DMA8_PAGE 0x83
-# else
-# if SB_DMA_8 == 3
-# define DMA8_PAGE 0x82
-# endif
-# endif
-#endif
-
-
-#define DMA16_ADDR (((SB_DMA_16 & 3) << 2) + 0xC0)
-#define DMA16_COUNT (((SB_DMA_16 & 3) << 2) + 0xC2)
-#define DMA16_MASK 0xD4
-#define DMA16_MODE 0xD6
-#define DMA16_CLEAR 0xD8
-
-
-/* If after this preprocessing stuff DMA16_PAGE is not defined
- * the 16-bit DMA channel specified is not valid
- */
-#if SB_DMA_16 == 5
-# define DMA16_PAGE 0x8B
-#else
-# if SB_DMA_16 == 6
-# define DMA16_PAGE 0x89
-# else
-# if SB_DMA_16 == 7
-# define DMA16_PAGE 0x8A
-# endif
-# endif
-#endif
-
-
-/* DMA modes */
-#define DMA16_AUTO_PLAY (0x58 + (SB_DMA_16 & 3))
-#define DMA16_AUTO_REC (0x54 + (SB_DMA_16 & 3))
-#define DMA8_AUTO_PLAY (0x58 + SB_DMA_8)
-#define DMA8_AUTO_REC (0x54 + SB_DMA_8)
-
-
-/* IO ports for soundblaster */
-#define DSP_RESET (0x6 + SB_BASE_ADDR)
-#define DSP_READ (0xA + SB_BASE_ADDR)
-#define DSP_WRITE (0xC + SB_BASE_ADDR)
-#define DSP_COMMAND (0xC + SB_BASE_ADDR)
-#define DSP_STATUS (0xC + SB_BASE_ADDR)
-#define DSP_DATA_AVL (0xE + SB_BASE_ADDR)
-#define DSP_DATA16_AVL (0xF + SB_BASE_ADDR)
-#define MIXER_REG (0x4 + SB_BASE_ADDR)
-#define MIXER_DATA (0x5 + SB_BASE_ADDR)
-#define OPL3_LEFT (0x0 + SB_BASE_ADDR)
-#define OPL3_RIGHT (0x2 + SB_BASE_ADDR)
-#define OPL3_BOTH (0x8 + SB_BASE_ADDR)
-
-
-/* DSP Commands */
-#define DSP_INPUT_RATE 0x42 /* set input sample rate */
-#define DSP_OUTPUT_RATE 0x41 /* set output sample rate */
-#define DSP_CMD_SPKON 0xD1 /* set speaker on */
-#define DSP_CMD_SPKOFF 0xD3 /* set speaker off */
-#define DSP_CMD_DMA8HALT 0xD0 /* halt DMA 8-bit operation */
-#define DSP_CMD_DMA8CONT 0xD4 /* continue DMA 8-bit operation */
-#define DSP_CMD_DMA16HALT 0xD5 /* halt DMA 16-bit operation */
-#define DSP_CMD_DMA16CONT 0xD6 /* continue DMA 16-bit operation */
-#define DSP_GET_VERSION 0xE1 /* get version number of DSP */
-#define DSP_CMD_8BITAUTO_IN 0xCE /* 8 bit auto-initialized input */
-#define DSP_CMD_8BITAUTO_OUT 0xC6 /* 8 bit auto-initialized output */
-#define DSP_CMD_16BITAUTO_IN 0xBE /* 16 bit auto-initialized input */
-#define DSP_CMD_16BITAUTO_OUT 0xB6 /* 16 bit auto-initialized output */
-#define DSP_CMD_IRQREQ8 0xF2 /* Interrupt request 8 bit */
-#define DSP_CMD_IRQREQ16 0xF3 /* Interrupt request 16 bit */
-
-
-/* DSP Modes */
-#define DSP_MODE_MONO_US 0x00 /* Mono unsigned */
-#define DSP_MODE_MONO_S 0x10 /* Mono signed */
-#define DSP_MODE_STEREO_US 0x20 /* Stereo unsigned */
-#define DSP_MODE_STEREO_S 0x30 /* Stereo signed */
-
-
-/* MIXER commands */
-#define MIXER_RESET 0x00 /* Reset */
-#define MIXER_DAC_LEVEL 0x04 /* Used for detection only */
-#define MIXER_MASTER_LEFT 0x30 /* Master volume left */
-#define MIXER_MASTER_RIGHT 0x31 /* Master volume right */
-#define MIXER_DAC_LEFT 0x32 /* Dac level left */
-#define MIXER_DAC_RIGHT 0x33 /* Dac level right */
-#define MIXER_FM_LEFT 0x34 /* Fm level left */
-#define MIXER_FM_RIGHT 0x35 /* Fm level right */
-#define MIXER_CD_LEFT 0x36 /* Cd audio level left */
-#define MIXER_CD_RIGHT 0x37 /* Cd audio level right */
-#define MIXER_LINE_LEFT 0x38 /* Line in level left */
-#define MIXER_LINE_RIGHT 0x39 /* Line in level right */
-#define MIXER_MIC_LEVEL 0x3A /* Microphone level */
-#define MIXER_PC_LEVEL 0x3B /* Pc speaker level */
-#define MIXER_OUTPUT_CTRL 0x3C /* Output control */
-#define MIXER_IN_LEFT 0x3D /* Input control left */
-#define MIXER_IN_RIGHT 0x3E /* Input control right */
-#define MIXER_GAIN_IN_LEFT 0x3F /* Input gain control left */
-#define MIXER_GAIN_IN_RIGHT 0x40 /* Input gain control right */
-#define MIXER_GAIN_OUT_LEFT 0x41 /* Output gain control left */
-#define MIXER_GAIN_OUT_RIGHT 0x42 /* Output gain control rigth */
-#define MIXER_AGC 0x43 /* Automatic gain control */
-#define MIXER_TREBLE_LEFT 0x44 /* Treble left */
-#define MIXER_TREBLE_RIGHT 0x45 /* Treble right */
-#define MIXER_BASS_LEFT 0x46 /* Bass left */
-#define MIXER_BASS_RIGHT 0x47 /* Bass right */
-#define MIXER_SET_IRQ 0x80 /* Set irq number */
-#define MIXER_SET_DMA 0x81 /* Set DMA channels */
-#define MIXER_IRQ_STATUS 0x82 /* Irq status */
-
-/* Mixer constants */
-#define MIC 0x01 /* Microphone */
-#define CD_RIGHT 0x02
-#define CD_LEFT 0x04
-#define LINE_RIGHT 0x08
-#define LINE_LEFT 0x10
-#define FM_RIGHT 0x20
-#define FM_LEFT 0x40
-
-/* DSP constants */
-#define DMA_NR_OF_BUFFERS 2
-#define DSP_MAX_SPEED 44100 /* Max sample speed in KHz */
-#define DSP_MIN_SPEED 4000 /* Min sample speed in KHz */
-#define DSP_MAX_FRAGMENT_SIZE (DMA_SIZE / DMA_NR_OF_BUFFERS) /* Maximum fragment size */
-#define DSP_MIN_FRAGMENT_SIZE 1024 /* Minimum fragment size */
-#define DSP_NR_OF_BUFFERS 8
-
-
-/* Number of bytes you can DMA before hitting a 64K boundary: */
-#define dma_bytes_left(phys) \
- ((unsigned) (sizeof(int) == 2 ? 0 : 0x10000) - (unsigned) ((phys) & 0xFFFF))
-
-
-_PROTOTYPE(int mixer_set, (int reg, int data));
-_PROTOTYPE( int sb16_inb, (int port) );
-_PROTOTYPE( void sb16_outb, (int port, int value) );
-
-
-#endif /* SB16_H */
+++ /dev/null
-/* This file contains the driver for a DSP (Digital Sound Processor) on
- * a SoundBlaster 16 soundcard.
- *
- * The driver supports the following operations (using message format m2):
- *
- * m_type DEVICE IO_ENDPT COUNT POSITION ADRRESS
- * ----------------------------------------------------------------
- * | DEV_OPEN | device | proc nr | | | |
- * |------------+---------+---------+---------+---------+---------|
- * | DEV_CLOSE | device | proc nr | | | |
- * |------------+---------+---------+---------+---------+---------|
- * | DEV_READ | device | proc nr | bytes | | buf ptr |
- * |------------+---------+---------+---------+---------+---------|
- * | DEV_WRITE | device | proc nr | bytes | | buf ptr |
- * |------------+---------+---------+---------+---------+---------|
- * | DEV_IOCTL | device | proc nr |func code| | buf ptr |
- * ----------------------------------------------------------------
- *
- * The file contains one entry point:
- *
- * main: main entry when driver is brought up
- *
- * August 24 2005 Ported driver to user space (only audio playback) (Peter Boonstoppel)
- * May 20 1995 Author: Michel R. Prevenier
- */
-
-#include <minix/endpoint.h>
-#include "sb16.h"
-
-
-FORWARD _PROTOTYPE( int dsp_open, (void) );
-FORWARD _PROTOTYPE( int dsp_close, (void) );
-FORWARD _PROTOTYPE( int dsp_ioctl, (const message *m_ptr) );
-FORWARD _PROTOTYPE( void dsp_write, (const message *m_ptr) );
-FORWARD _PROTOTYPE( void dsp_hardware_msg, (void) );
-FORWARD _PROTOTYPE( void dsp_status, (message *m_ptr) );
-
-FORWARD _PROTOTYPE( void reply, (int code, int replyee, int process, int status) );
-FORWARD _PROTOTYPE( int dsp_init, (void) );
-FORWARD _PROTOTYPE( int dsp_reset, (void) );
-FORWARD _PROTOTYPE( int dsp_command, (int value) );
-FORWARD _PROTOTYPE( int dsp_set_size, (unsigned int size) );
-FORWARD _PROTOTYPE( int dsp_set_speed, (unsigned int speed) );
-FORWARD _PROTOTYPE( int dsp_set_stereo, (unsigned int stereo) );
-FORWARD _PROTOTYPE( int dsp_set_bits, (unsigned int bits) );
-FORWARD _PROTOTYPE( int dsp_set_sign, (unsigned int sign) );
-FORWARD _PROTOTYPE( void dsp_dma_setup, (phys_bytes address, int count) );
-FORWARD _PROTOTYPE( void dsp_setup, (void) );
-
-PRIVATE int irq_hook_id; /* id of irq hook at the kernel */
-
-PRIVATE char DmaBuffer[DMA_SIZE + 64 * 1024];
-PRIVATE char* DmaPtr;
-PRIVATE phys_bytes DmaPhys;
-
-PRIVATE char Buffer[DSP_MAX_FRAGMENT_SIZE * DSP_NR_OF_BUFFERS];
-
-PRIVATE int DspVersion[2];
-PRIVATE unsigned int DspStereo = DEFAULT_STEREO;
-PRIVATE unsigned int DspSpeed = DEFAULT_SPEED;
-PRIVATE unsigned int DspBits = DEFAULT_BITS;
-PRIVATE unsigned int DspSign = DEFAULT_SIGN;
-PRIVATE unsigned int DspFragmentSize = DSP_MAX_FRAGMENT_SIZE;
-PRIVATE int DspAvail = 0;
-PRIVATE int DspBusy = 0;
-PRIVATE int DmaMode = 0;
-PRIVATE int DmaBusy = -1;
-PRIVATE int DmaFillNext = 0;
-PRIVATE int BufReadNext = -1;
-PRIVATE int BufFillNext = 0;
-
-PRIVATE int revivePending = 0;
-PRIVATE int reviveStatus;
-PRIVATE int reviveProcNr;
-
-#define dprint (void)
-
-/* SEF functions and variables. */
-FORWARD _PROTOTYPE( void sef_local_startup, (void) );
-FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
-EXTERN _PROTOTYPE( int sef_cb_lu_prepare, (int state) );
-EXTERN _PROTOTYPE( int sef_cb_lu_state_isvalid, (int state) );
-EXTERN _PROTOTYPE( void sef_cb_lu_state_dump, (int state) );
-PUBLIC int is_processing = FALSE;
-PUBLIC int is_status_msg_expected = FALSE;
-
-/*===========================================================================*
- * main
- *===========================================================================*/
-PUBLIC int main(int argc, char *argv[])
-{
- int r;
- endpoint_t caller;
- int proc_nr;
- message mess;
- int ipc_status;
-
- /* SEF local startup. */
- sef_local_startup();
-
- while(TRUE) {
- /* Wait for an incoming message */
- driver_receive(ANY, &mess, &ipc_status);
-
- caller = mess.m_source;
- proc_nr = mess.IO_ENDPT;
-
- if (is_ipc_notify(ipc_status)) {
- switch (_ENDPOINT_P(mess.m_source)) {
- case HARDWARE:
- dsp_hardware_msg();
- continue; /* don't reply */
- default:
- r = EINVAL;
- }
-
- /* dont with this message */
- goto send_reply;
- }
-
- /* Now carry out the work. */
- switch(mess.m_type) {
- case DEV_OPEN: r = dsp_open(); break;
- case DEV_CLOSE: r = dsp_close(); break;
-#ifdef DEV_IOCTL
- case DEV_IOCTL: r = dsp_ioctl(&mess); break;
-#endif
-#ifdef DEV_READ
-
- case DEV_READ: r = EINVAL; break; /* Not yet implemented */
- case DEV_WRITE: dsp_write(&mess); continue; /* don't reply */
-#endif
-
- case DEV_STATUS: dsp_status(&mess); continue; /* don't reply */
- default: r = EINVAL;
- }
-
-send_reply:
- /* Finally, prepare and send the reply message. */
- reply(TASK_REPLY, caller, proc_nr, r);
- }
-
-}
-
-/*===========================================================================*
- * sef_local_startup *
- *===========================================================================*/
-PRIVATE void sef_local_startup(void)
-{
- /* Register init callbacks. */
- sef_setcb_init_fresh(sef_cb_init_fresh);
- sef_setcb_init_lu(sef_cb_init_fresh);
- sef_setcb_init_restart(sef_cb_init_fresh);
-
- /* Register live update callbacks. */
- sef_setcb_lu_prepare(sef_cb_lu_prepare);
- sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid);
- sef_setcb_lu_state_dump(sef_cb_lu_state_dump);
-
- /* Let SEF perform startup. */
- sef_startup();
-}
-
-/*===========================================================================*
- * sef_cb_init_fresh *
- *===========================================================================*/
-PRIVATE int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
-{
-/* Initialize the rtl8169 driver. */
- unsigned left;
-
- /* Select a buffer that can safely be used for dma transfers.
- * Its absolute address is 'DmaPhys', the normal address is 'DmaPtr'.
- */
-#if (CHIP == INTEL)
- DmaPtr = DmaBuffer;
- sys_umap(SELF, D, (vir_bytes)DmaBuffer, sizeof(DmaBuffer), &DmaPhys);
-
- if((left = dma_bytes_left(DmaPhys)) < DMA_SIZE) {
- /* First half of buffer crosses a 64K boundary, can't DMA into that */
- DmaPtr += left;
- DmaPhys += left;
- }
-#else /* CHIP != INTEL */
- panic("initialization failed: CHIP != INTEL: %d", 0);
-#endif /* CHIP == INTEL */
-
- /* Announce we are up! */
- driver_announce();
-
- return(OK);
-}
-
-/*===========================================================================*
- * dsp_open
- *===========================================================================*/
-PRIVATE int dsp_open(void)
-{
- dprint("sb16_dsp.c: dsp_open()\n");
-
- /* try to detect SoundBlaster card */
- if(!DspAvail && dsp_init() != OK) return EIO;
-
- /* Only one open at a time with soundcards */
- if(DspBusy) return EBUSY;
-
- /* Start with a clean DSP */
- if(dsp_reset() != OK) return EIO;
-
- /* Setup default values */
- DspStereo = DEFAULT_STEREO;
- DspSpeed = DEFAULT_SPEED;
- DspBits = DEFAULT_BITS;
- DspSign = DEFAULT_SIGN;
- DspFragmentSize = DMA_SIZE / 2;
-
- DspBusy = 1;
-
- return OK;
-}
-
-
-/*===========================================================================*
- * dsp_close
- *===========================================================================*/
-PRIVATE int dsp_close(void)
-{
- dprint("sb16_dsp.c: dsp_close()\n");
-
- DspBusy = 0; /* soundcard available again */
-
- return OK;
-}
-
-
-/*===========================================================================*
- * dsp_ioctl
- *===========================================================================*/
-PRIVATE int dsp_ioctl(const message *m_ptr)
-{
- int status;
- unsigned int val;
-
- dprint("sb16_dsp.c: dsp_ioctl()\n");
-
- /* Cannot change parameters during play or recording */
- if(DmaBusy >= 0) return EBUSY;
-
- /* Get user data */
- if(m_ptr->REQUEST != DSPIORESET) {
- sys_vircopy(m_ptr->IO_ENDPT, D, (vir_bytes)m_ptr->ADDRESS, SELF, D, (vir_bytes)&val, sizeof(val));
- }
-
- dprint("dsp_ioctl: got ioctl %d, argument: %d\n", m_ptr->REQUEST, val);
-
- switch(m_ptr->REQUEST) {
- case DSPIORATE: status = dsp_set_speed(val); break;
- case DSPIOSTEREO: status = dsp_set_stereo(val); break;
- case DSPIOBITS: status = dsp_set_bits(val); break;
- case DSPIOSIZE: status = dsp_set_size(val); break;
- case DSPIOSIGN: status = dsp_set_sign(val); break;
- case DSPIOMAX:
- val = DSP_MAX_FRAGMENT_SIZE;
- sys_vircopy(SELF, D, (vir_bytes)&val, m_ptr->IO_ENDPT, D, (vir_bytes)m_ptr->ADDRESS, sizeof(val));
- status = OK;
- break;
- case DSPIORESET: status = dsp_reset(); break;
- default: status = ENOTTY; break;
- }
-
- return status;
-}
-
-
-/*===========================================================================*
- * dsp_write
- *===========================================================================*/
-PRIVATE void dsp_write(const message *m_ptr)
-{
- message mess;
- int ipc_status;
-
- dprint("sb16_dsp.c: dsp_write()\n");
-
- if(m_ptr->COUNT != DspFragmentSize) {
- reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, EINVAL);
- return;
- }
- if(m_ptr->m_type != DmaMode && DmaBusy >= 0) {
- reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, EBUSY);
- return;
- }
-
- reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, SUSPEND);
- is_processing = TRUE;
-
- if(DmaBusy < 0) { /* Dma tranfer not yet started */
-
- DmaMode = DEV_WRITE_S; /* Dma mode is writing */
- sys_datacopy(m_ptr->IO_ENDPT, (vir_bytes)m_ptr->ADDRESS, SELF, (vir_bytes)DmaPtr, (phys_bytes)DspFragmentSize);
- dsp_dma_setup(DmaPhys, DspFragmentSize * DMA_NR_OF_BUFFERS);
- dsp_setup();
- DmaBusy = 0; /* Dma is busy */
- dprint(" filled dma[0]\n");
- DmaFillNext = 1;
-
- } else if(DmaBusy != DmaFillNext) { /* Dma transfer started, but Dma buffer not yet full */
-
- sys_datacopy(m_ptr->IO_ENDPT, (vir_bytes)m_ptr->ADDRESS, SELF, (vir_bytes)DmaPtr + DmaFillNext * DspFragmentSize, (phys_bytes)DspFragmentSize);
- dprint(" filled dma[%d]\n", DmaFillNext);
- DmaFillNext = (DmaFillNext + 1) % DMA_NR_OF_BUFFERS;
-
- } else if(BufReadNext < 0) { /* Dma buffer full, fill first element of second buffer */
-
- sys_datacopy(m_ptr->IO_ENDPT, (vir_bytes)m_ptr->ADDRESS, SELF, (vir_bytes)Buffer, (phys_bytes)DspFragmentSize);
- dprint(" filled buf[0]\n");
- BufReadNext = 0;
- BufFillNext = 1;
-
- } else { /* Dma buffer is full, filling second buffer */
-
- while(BufReadNext == BufFillNext) { /* Second buffer also full, wait for space to become available */
- driver_receive(HARDWARE, &mess, &ipc_status);
- dsp_hardware_msg();
- }
- sys_datacopy(m_ptr->IO_ENDPT, (vir_bytes)m_ptr->ADDRESS, SELF, (vir_bytes)Buffer + BufFillNext * DspFragmentSize, (phys_bytes)DspFragmentSize);
- dprint(" filled buf[%d]\n", BufFillNext);
- BufFillNext = (BufFillNext + 1) % DSP_NR_OF_BUFFERS;
-
- }
-
- is_status_msg_expected = TRUE;
- revivePending = 1;
- reviveStatus = DspFragmentSize;
- reviveProcNr = m_ptr->IO_ENDPT;
- notify(m_ptr->m_source);
-}
-
-
-/*===========================================================================*
- * dsp_hardware_msg
- *===========================================================================*/
-PRIVATE void dsp_hardware_msg()
-{
- dprint("Interrupt: ");
- if(DmaBusy >= 0) { /* Dma transfer was actually busy */
- dprint("Finished playing dma[%d]; ", DmaBusy);
- DmaBusy = (DmaBusy + 1) % DMA_NR_OF_BUFFERS;
- if(DmaBusy == DmaFillNext) { /* Dma buffer empty, stop Dma transfer */
-
- dsp_command((DspBits == 8 ? DSP_CMD_DMA8HALT : DSP_CMD_DMA16HALT));
- dprint("No more work...!\n");
- DmaBusy = -1;
-
- } else if(BufReadNext >= 0) { /* Data in second buffer, copy one fragment to Dma buffer */
-
- /* Acknowledge the interrupt on the DSP */
- sb16_inb((DspBits == 8 ? DSP_DATA_AVL : DSP_DATA16_AVL));
-
- memcpy(DmaPtr + DmaFillNext * DspFragmentSize, Buffer + BufReadNext * DspFragmentSize, DspFragmentSize);
- dprint("copy buf[%d] -> dma[%d]; ", BufReadNext, DmaFillNext);
- BufReadNext = (BufReadNext + 1) % DSP_NR_OF_BUFFERS;
- DmaFillNext = (DmaFillNext + 1) % DMA_NR_OF_BUFFERS;
- if(BufReadNext == BufFillNext) {
- BufReadNext = -1;
- }
- dprint("Starting dma[%d]\n", DmaBusy);
-
- return;
-
- } else { /* Second buffer empty, still data in Dma buffer, continue playback */
- dprint("Starting dma[%d]\n", DmaBusy);
- }
- }
-
- /* Acknowledge the interrupt on the DSP */
- sb16_inb((DspBits == 8 ? DSP_DATA_AVL : DSP_DATA16_AVL));
-}
-
-
-/*===========================================================================*
- * dsp_status *
- *===========================================================================*/
-PRIVATE void dsp_status(message *m_ptr)
-/* m_ptr pointer to the newly arrived message */
-{
- if(revivePending) {
- m_ptr->m_type = DEV_REVIVE; /* build message */
- m_ptr->REP_ENDPT = reviveProcNr;
- m_ptr->REP_STATUS = reviveStatus;
-
- revivePending = 0; /* unmark event */
- is_processing = FALSE;
- } else {
- m_ptr->m_type = DEV_NO_STATUS;
-
- is_status_msg_expected = FALSE;
- }
-
- send(m_ptr->m_source, m_ptr); /* send the message */
-}
-
-
-/*===========================================================================*
- * reply *
- *===========================================================================*/
-PRIVATE void reply(int code, int replyee, int process, int status)
-{
- message m;
-
- m.m_type = code; /* TASK_REPLY or REVIVE */
- m.REP_STATUS = status; /* result of device operation */
- m.REP_ENDPT = process; /* which user made the request */
-
- send(replyee, &m);
-}
-
-/*===========================================================================*
- * dsp_init
- *===========================================================================*/
-PRIVATE int dsp_init()
-{
- int i, s;
-
- if(dsp_reset () != OK) {
- dprint("sb16: No SoundBlaster card detected\n");
- return -1;
- }
-
- DspVersion[0] = DspVersion[1] = 0;
- dsp_command(DSP_GET_VERSION); /* Get DSP version bytes */
-
- for(i = 1000; i; i--) {
- if(sb16_inb(DSP_DATA_AVL) & 0x80) {
- if(DspVersion[0] == 0) {
- DspVersion[0] = sb16_inb(DSP_READ);
- } else {
- DspVersion[1] = sb16_inb(DSP_READ);
- break;
- }
- }
- }
-
- if(DspVersion[0] < 4) {
- dprint("sb16: No SoundBlaster 16 compatible card detected\n");
- return -1;
- }
-
- dprint("sb16: SoundBlaster DSP version %d.%d detected\n", DspVersion[0], DspVersion[1]);
-
- /* set SB to use our IRQ and DMA channels */
- mixer_set(MIXER_SET_IRQ, (1 << (SB_IRQ / 2 - 1)));
- mixer_set(MIXER_SET_DMA, (1 << SB_DMA_8 | 1 << SB_DMA_16));
-
- /* register interrupt vector and enable irq */
- if ((s=sys_irqsetpolicy(SB_IRQ, IRQ_REENABLE, &irq_hook_id )) != OK)
- panic("Couldn't set IRQ policy: %d", s);
- if ((s=sys_irqenable(&irq_hook_id)) != OK)
- panic("Couldn't enable IRQ: %d", s);
-
- DspAvail = 1;
- return OK;
-}
-
-
-/*===========================================================================*
- * dsp_reset
- *===========================================================================*/
-PRIVATE int dsp_reset()
-{
- int i;
-
- sb16_outb(DSP_RESET, 1);
- for(i = 0; i < 1000; i++); /* wait a while */
- sb16_outb(DSP_RESET, 0);
-
- for(i = 0; i < 1000 && !(sb16_inb(DSP_DATA_AVL) & 0x80); i++);
-
- if(sb16_inb(DSP_READ) != 0xAA) return EIO; /* No SoundBlaster */
-
- DmaBusy = -1;
-
- return OK;
-}
-
-
-/*===========================================================================*
- * dsp_command
- *===========================================================================*/
-PRIVATE int dsp_command(int value)
-{
- int i;
-
- for (i = 0; i < SB_TIMEOUT; i++) {
- if((sb16_inb(DSP_STATUS) & 0x80) == 0) {
- sb16_outb(DSP_COMMAND, value);
- return OK;
- }
- }
-
- dprint("sb16: SoundBlaster: DSP Command(%x) timeout\n", value);
- return -1;
-}
-
-
-/*===========================================================================*
- * dsp_set_size
- *===========================================================================*/
-static int dsp_set_size(unsigned int size)
-{
- dprint("dsp_set_size(): set fragment size to %u\n", size);
-
- /* Sanity checks */
- if(size < DSP_MIN_FRAGMENT_SIZE || size > DSP_MAX_FRAGMENT_SIZE || size % 2 != 0) {
- return EINVAL;
- }
-
- DspFragmentSize = size;
-
- return OK;
-}
-
-
-/*===========================================================================*
- * dsp_set_speed
- *===========================================================================*/
-static int dsp_set_speed(unsigned int speed)
-{
- dprint("sb16: setting speed to %u, stereo = %d\n", speed, DspStereo);
-
- if(speed < DSP_MIN_SPEED || speed > DSP_MAX_SPEED) {
- return EPERM;
- }
-
- /* Soundblaster 16 can be programmed with real sample rates
- * instead of time constants
- *
- * Since you cannot sample and play at the same time
- * we set in- and output rate to the same value
- */
-
- dsp_command(DSP_INPUT_RATE); /* set input rate */
- dsp_command(speed >> 8); /* high byte of speed */
- dsp_command(speed); /* low byte of speed */
- dsp_command(DSP_OUTPUT_RATE); /* same for output rate */
- dsp_command(speed >> 8);
- dsp_command(speed);
-
- DspSpeed = speed;
-
- return OK;
-}
-
-
-/*===========================================================================*
- * dsp_set_stereo
- *===========================================================================*/
-static int dsp_set_stereo(unsigned int stereo)
-{
- if(stereo) {
- DspStereo = 1;
- } else {
- DspStereo = 0;
- }
-
- return OK;
-}
-
-
-/*===========================================================================*
- * dsp_set_bits
- *===========================================================================*/
-static int dsp_set_bits(unsigned int bits)
-{
- /* Sanity checks */
- if(bits != 8 && bits != 16) {
- return EINVAL;
- }
-
- DspBits = bits;
-
- return OK;
-}
-
-
-/*===========================================================================*
- * dsp_set_sign
- *===========================================================================*/
-static int dsp_set_sign(unsigned int sign)
-{
- dprint("sb16: set sign to %u\n", sign);
-
- DspSign = (sign > 0 ? 1 : 0);
-
- return OK;
-}
-
-
-/*===========================================================================*
- * dsp_dma_setup
- *===========================================================================*/
-PRIVATE void dsp_dma_setup(phys_bytes address, int count)
-{
- pvb_pair_t pvb[9];
-
-
- dprint("Setting up %d bit DMA\n", DspBits);
-
- if(DspBits == 8) { /* 8 bit sound */
- count--;
-
- pv_set(pvb[0], DMA8_MASK, SB_DMA_8 | 0x04); /* Disable DMA channel */
- pv_set(pvb[1], DMA8_CLEAR, 0x00); /* Clear flip flop */
-
- /* set DMA mode */
- pv_set(pvb[2], DMA8_MODE, (DmaMode == DEV_WRITE_S ? DMA8_AUTO_PLAY : DMA8_AUTO_REC));
-
- pv_set(pvb[3], DMA8_ADDR, (address >> 0) & 0xff); /* Low_byte of address */
- pv_set(pvb[4], DMA8_ADDR, (address >> 8) & 0xff); /* High byte of address */
- pv_set(pvb[5], DMA8_PAGE, (address >> 16) & 0xff); /* 64K page number */
- pv_set(pvb[6], DMA8_COUNT, (count >> 0) & 0xff); /* Low byte of count */
- pv_set(pvb[7], DMA8_COUNT, (count >> 8) & 0xff); /* High byte of count */
- pv_set(pvb[8], DMA8_MASK, SB_DMA_8); /* Enable DMA channel */
-
- sys_voutb(pvb, 9);
- } else { /* 16 bit sound */
- count-= 2;
-
- pv_set(pvb[0], DMA16_MASK, (SB_DMA_16 & 3) | 0x04); /* Disable DMA channel */
-
- pv_set(pvb[1], DMA16_CLEAR, 0x00); /* Clear flip flop */
-
- /* Set dma mode */
- pv_set(pvb[2], DMA16_MODE, (DmaMode == DEV_WRITE_S ? DMA16_AUTO_PLAY : DMA16_AUTO_REC));
-
- pv_set(pvb[3], DMA16_ADDR, (address >> 1) & 0xFF); /* Low_byte of address */
- pv_set(pvb[4], DMA16_ADDR, (address >> 9) & 0xFF); /* High byte of address */
- pv_set(pvb[5], DMA16_PAGE, (address >> 16) & 0xFE); /* 128K page number */
- pv_set(pvb[6], DMA16_COUNT, (count >> 1) & 0xff); /* Low byte of count */
- pv_set(pvb[7], DMA16_COUNT, (count >> 9) & 0xff); /* High byte of count */
- pv_set(pvb[8], DMA16_MASK, SB_DMA_16 & 3); /* Enable DMA channel */
-
- sys_voutb(pvb, 9);
- }
-}
-
-
-/*===========================================================================*
- * dsp_setup()
- *===========================================================================*/
-PRIVATE void dsp_setup()
-{
- /* Set current sample speed */
- dsp_set_speed(DspSpeed);
-
- /* Put the speaker on */
- if(DmaMode == DEV_WRITE_S) {
- dsp_command (DSP_CMD_SPKON); /* put speaker on */
-
- /* Program DSP with dma mode */
- dsp_command((DspBits == 8 ? DSP_CMD_8BITAUTO_OUT : DSP_CMD_16BITAUTO_OUT));
- } else {
- dsp_command (DSP_CMD_SPKOFF); /* put speaker off */
-
- /* Program DSP with dma mode */
- dsp_command((DspBits == 8 ? DSP_CMD_8BITAUTO_IN : DSP_CMD_16BITAUTO_IN));
- }
-
- /* Program DSP with transfer mode */
- if (!DspSign) {
- dsp_command((DspStereo == 1 ? DSP_MODE_STEREO_US : DSP_MODE_MONO_US));
- } else {
- dsp_command((DspStereo == 1 ? DSP_MODE_STEREO_S : DSP_MODE_MONO_S));
- }
-
- /* Give length of fragment to DSP */
- if (DspBits == 8) { /* 8 bit transfer */
- /* #bytes - 1 */
- dsp_command((DspFragmentSize - 1) >> 0);
- dsp_command((DspFragmentSize - 1) >> 8);
- } else { /* 16 bit transfer */
- /* #words - 1 */
- dsp_command((DspFragmentSize - 1) >> 1);
- dsp_command((DspFragmentSize - 1) >> 9);
- }
-}
-
-
+++ /dev/null
-/* This file contains the driver for the mixer on
- * a SoundBlaster 16 soundcard.
- *
- * The driver supports the following operations (using message format m2):
- *
- * m_type DEVICE IO_ENDPT COUNT POSITION ADRRESS
- * ----------------------------------------------------------------
- * | DEV_OPEN | device | proc nr | | | |
- * |------------+---------+---------+---------+---------+---------|
- * | DEV_CLOSE | device | proc nr | | | |
- * |------------+---------+---------+---------+---------+---------|
- * | DEV_IOCTL | device | proc nr |func code| | buf_ptr |
- * ----------------------------------------------------------------
- *
- * The file contains one entry point:
- *
- * sb16mixer_task: main entry when system is brought up
- *
- * August 24 2005 Ported driver to user space (Peter Boonstoppel)
- * May 20 1995 Author: Michel R. Prevenier
- */
-
-
-#include "sb16.h"
-
-
-FORWARD _PROTOTYPE( int mixer_init, (void));
-FORWARD _PROTOTYPE( int mixer_open, (const message *m_ptr));
-FORWARD _PROTOTYPE( int mixer_close, (const message *m_ptr));
-FORWARD _PROTOTYPE( int mixer_ioctl, (const message *m_ptr));
-FORWARD _PROTOTYPE( int mixer_get, (int reg));
-FORWARD _PROTOTYPE( int get_set_volume, (const message *m_ptr, int flag));
-FORWARD _PROTOTYPE( int get_set_input, (const message *m_ptr, int flag, int channel));
-FORWARD _PROTOTYPE( int get_set_output, (const message *m_ptr, int flag));
-
-
-PRIVATE int mixer_avail = 0; /* Mixer exists? */
-
-
-#define dprint (void)
-
-/* SEF functions and variables. */
-FORWARD _PROTOTYPE( void sef_local_startup, (void) );
-FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
-
-/*===========================================================================*
- * main
- *===========================================================================*/
-PUBLIC int main(int argc, char *argv[])
-{
- message mess;
- int ipc_status;
- int err, caller, proc_nr;
-
- /* SEF local startup. */
- sef_local_startup();
-
- /* Here is the main loop of the mixer task. It waits for a message, carries
- * it out, and sends a reply.
- */
- while (TRUE) {
- driver_receive(ANY, &mess, &ipc_status);
-
- caller = mess.m_source;
- proc_nr = mess.IO_ENDPT;
-
- switch (caller) {
- case HARDWARE: /* Leftover interrupt. */
- continue;
- case VFS_PROC_NR: /* The only legitimate caller. */
- break;
- default:
- dprint("sb16: got message from %d\n", caller);
- continue;
- }
-
- /* Now carry out the work. */
- switch(mess.m_type) {
- case DEV_OPEN: err = mixer_open(&mess); break;
- case DEV_CLOSE: err = mixer_close(&mess); break;
-#ifdef DEV_IOCTL
- case DEV_IOCTL: err = mixer_ioctl(&mess); break;
-#endif
- default: err = EINVAL; break;
- }
-
- /* Finally, prepare and send the reply message. */
- mess.m_type = TASK_REPLY;
- mess.REP_ENDPT = proc_nr;
-
- dprint("%d %d", err, OK);
-
- mess.REP_STATUS = err; /* error code */
- send(caller, &mess); /* send reply to caller */
- }
-}
-
-/*===========================================================================*
- * sef_local_startup *
- *===========================================================================*/
-PRIVATE void sef_local_startup()
-{
- /* Register init callbacks. */
- sef_setcb_init_fresh(sef_cb_init_fresh);
- sef_setcb_init_lu(sef_cb_init_fresh);
- sef_setcb_init_restart(sef_cb_init_fresh);
-
- /* Register live update callbacks. */
- sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready);
- sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_standard);
-
- /* Let SEF perform startup. */
- sef_startup();
-}
-
-/*===========================================================================*
- * sef_cb_init_fresh *
- *===========================================================================*/
-PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
-{
-/* Initialize the sb16 mixer driver. */
- /* Announce we are up! */
- driver_announce();
-
- return(OK);
-}
-
-/*=========================================================================*
- * mixer_open
- *=========================================================================*/
-PRIVATE int mixer_open(const message *m_ptr)
-{
- dprint("mixer_open\n");
-
- /* try to detect the mixer type */
- if (!mixer_avail && mixer_init() != OK) return EIO;
-
- return OK;
-}
-
-
-/*=========================================================================*
- * mixer_close
- *=========================================================================*/
-PRIVATE int mixer_close(const message *m_ptr)
-{
- dprint("mixer_close\n");
-
- return OK;
-}
-
-
-/*=========================================================================*
- * mixer_ioctl
- *=========================================================================*/
-PRIVATE int mixer_ioctl(const message *m_ptr)
-{
- int status;
-
- dprint("mixer: got ioctl %d\n", m_ptr->REQUEST);
-
-
- switch(m_ptr->REQUEST) {
- case MIXIOGETVOLUME: status = get_set_volume(m_ptr, 0); break;
- case MIXIOSETVOLUME: status = get_set_volume(m_ptr, 1); break;
- case MIXIOGETINPUTLEFT: status = get_set_input(m_ptr, 0, 0); break;
- case MIXIOGETINPUTRIGHT: status = get_set_input(m_ptr, 0, 1); break;
- case MIXIOGETOUTPUT: status = get_set_output(m_ptr, 0); break;
- case MIXIOSETINPUTLEFT: status = get_set_input(m_ptr, 1, 0); break;
- case MIXIOSETINPUTRIGHT: status = get_set_input(m_ptr, 1, 1); break;
- case MIXIOSETOUTPUT: status = get_set_output(m_ptr, 1); break;
- default: status = ENOTTY;
- }
-
- return status;
-}
-
-
-/*=========================================================================*
- * mixer_init
- *=========================================================================*/
-PRIVATE int mixer_init()
-{
- /* Try to detect the mixer by writing to MIXER_DAC_LEVEL if the
- * value written can be read back the mixer is there
- */
-
- mixer_set(MIXER_DAC_LEVEL, 0x10); /* write something to it */
- if(mixer_get(MIXER_DAC_LEVEL) != 0x10) {
- dprint("sb16: Mixer not detected\n");
- return EIO;
- }
-
- /* Enable Automatic Gain Control */
- mixer_set(MIXER_AGC, 0x01);
-
- dprint("Mixer detected\n");
-
- mixer_avail = 1;
- return OK;
-}
-
-
-/*=========================================================================*
- * mixer_get
- *=========================================================================*/
-PRIVATE int mixer_get(int reg)
-{
- int i;
-
- sb16_outb(MIXER_REG, reg);
- for(i = 0; i < 100; i++);
- return sb16_inb(MIXER_DATA) & 0xff;
-}
-
-
-/*=========================================================================*
- * get_set_volume *
- *=========================================================================*/
-PRIVATE int get_set_volume(const message *m_ptr, int flag)
-/* flag 0 = get, 1 = set */
-{
- struct volume_level level;
- int cmd_left, cmd_right, shift, max_level;
-
- sys_datacopy(m_ptr->IO_ENDPT, (vir_bytes)m_ptr->ADDRESS, SELF, (vir_bytes)&level, (phys_bytes)sizeof(level));
-
- shift = 3;
- max_level = 0x1F;
-
- switch(level.device) {
- case Master:
- cmd_left = MIXER_MASTER_LEFT;
- cmd_right = MIXER_MASTER_RIGHT;
- break;
- case Dac:
- cmd_left = MIXER_DAC_LEFT;
- cmd_right = MIXER_DAC_RIGHT;
- break;
- case Fm:
- cmd_left = MIXER_FM_LEFT;
- cmd_right = MIXER_FM_RIGHT;
- break;
- case Cd:
- cmd_left = MIXER_CD_LEFT;
- cmd_right = MIXER_CD_RIGHT;
- break;
- case Line:
- cmd_left = MIXER_LINE_LEFT;
- cmd_right = MIXER_LINE_RIGHT;
- break;
- case Mic:
- cmd_left = cmd_right = MIXER_MIC_LEVEL;
- break;
- case Speaker:
- cmd_left = cmd_right = MIXER_PC_LEVEL;
- shift = 6;
- max_level = 0x03;
- break;
- case Treble:
- cmd_left = MIXER_TREBLE_LEFT;
- cmd_right = MIXER_TREBLE_RIGHT;
- shift = 4;
- max_level = 0x0F;
- break;
- case Bass:
- cmd_left = MIXER_BASS_LEFT;
- cmd_right = MIXER_BASS_RIGHT;
- shift = 4;
- max_level = 0x0F;
- break;
- default:
- return EINVAL;
- }
-
- if(flag) { /* Set volume level */
- if(level.right < 0) level.right = 0;
- else if(level.right > max_level) level.right = max_level;
- if(level.left < 0) level.left = 0;
- else if(level.left > max_level) level.left = max_level;
-
- mixer_set(cmd_right, (level.right << shift));
- mixer_set(cmd_left, (level.left << shift));
- } else { /* Get volume level */
- level.left = mixer_get(cmd_left);
- level.right = mixer_get(cmd_right);
-
- level.left >>= shift;
- level.right >>= shift;
-
- /* Copy back to user */
- sys_datacopy(SELF, (vir_bytes)&level, m_ptr->IO_ENDPT, (vir_bytes)m_ptr->ADDRESS, (phys_bytes)sizeof(level));
- }
-
- return OK;
-}
-
-
-/*=========================================================================*
- * get_set_input *
- *=========================================================================*/
-PRIVATE int get_set_input(const message *m_ptr, int flag, int channel)
-/*
- * flag 0 = get, 1 = set
- * channel 0 = left, 1 = right
- */
-{
- struct inout_ctrl input;
- int input_cmd, input_mask, mask, del_mask, shift;
-
- sys_datacopy(m_ptr->IO_ENDPT, (vir_bytes)m_ptr->ADDRESS, SELF, (vir_bytes)&input, (phys_bytes)sizeof(input));
-
- input_cmd = (channel == 0 ? MIXER_IN_LEFT : MIXER_IN_RIGHT);
-
- mask = mixer_get(input_cmd);
-
- switch (input.device) {
- case Fm:
- shift = 5;
- del_mask = 0x1F;
- break;
- case Cd:
- shift = 1;
- del_mask = 0x79;
- break;
- case Line:
- shift = 3;
- del_mask = 0x67;
- break;
- case Mic:
- shift = 0;
- del_mask = 0x7E;
- break;
- default:
- return EINVAL;
- }
-
- if (flag) { /* Set input */
- input_mask = ((input.left == ON ? 1 : 0) << 1) | (input.right == ON ? 1 : 0);
-
- if (shift > 0) input_mask <<= shift;
- else input_mask >>= 1;
-
- mask &= del_mask;
- mask |= input_mask;
-
- mixer_set(input_cmd, mask);
- } else { /* Get input */
- if (shift > 0) {
- input.left = ((((mask >> (shift+1)) & 1) == 1) ? ON : OFF);
- input.right = ((((mask >> shift) & 1) == 1) ? ON : OFF);
- } else {
- input.left = (((mask & 1) == 1) ? ON : OFF);
- }
-
- /* Copy back to user */
- sys_datacopy(SELF, (vir_bytes)&input, m_ptr->IO_ENDPT, (vir_bytes)m_ptr->ADDRESS, (phys_bytes)sizeof(input));
- }
-
- return OK;
-}
-
-
-/*=========================================================================*
- * get_set_output *
- *=========================================================================*/
-PRIVATE int get_set_output(const message *m_ptr, int flag)
-/* flag 0 = get, 1 = set */
-{
- struct inout_ctrl output;
- int output_mask, mask, del_mask, shift;
-
- sys_datacopy(m_ptr->IO_ENDPT, (vir_bytes)m_ptr->ADDRESS, SELF, (vir_bytes)&output, (phys_bytes)sizeof(output));
-
- mask = mixer_get(MIXER_OUTPUT_CTRL);
-
- switch (output.device) {
- case Cd:
- shift = 1;
- del_mask = 0x79;
- break;
- case Line:
- shift = 3;
- del_mask = 0x67;
- break;
- case Mic:
- shift = 0;
- del_mask = 0x7E;
- break;
- default:
- return EINVAL;
- }
-
- if (flag) { /* Set input */
- output_mask = ((output.left == ON ? 1 : 0) << 1) | (output.right == ON ? 1 : 0);
-
- if (shift > 0) output_mask <<= shift;
- else output_mask >>= 1;
-
- mask &= del_mask;
- mask |= output_mask;
-
- mixer_set(MIXER_OUTPUT_CTRL, mask);
- } else { /* Get input */
- if (shift > 0) {
- output.left = ((((mask >> (shift+1)) & 1) == 1) ? ON : OFF);
- output.right = ((((mask >> shift) & 1) == 1) ? ON : OFF);
- } else {
- output.left = (((mask & 1) == 1) ? ON : OFF);
- }
-
- /* Copy back to user */
- sys_datacopy(SELF, (vir_bytes)&output, m_ptr->IO_ENDPT, (vir_bytes)m_ptr->ADDRESS, (phys_bytes)sizeof(output));
- }
-
- return OK;
-}