Update by paboonst@cs.vu.nl
This commit is contained in:
parent
c10b7c719f
commit
c4e4398043
7 changed files with 576 additions and 87 deletions
|
@ -1,5 +1,4 @@
|
||||||
# Makefile for the Sound Blaster 16 driver (SB16)
|
# Makefile for the Sound Blaster 16 driver (SB16)
|
||||||
DRIVER = sb16_dsp
|
|
||||||
|
|
||||||
# directories
|
# directories
|
||||||
u = /usr
|
u = /usr
|
||||||
|
@ -15,19 +14,20 @@ CFLAGS = -I$i
|
||||||
LDFLAGS = -i
|
LDFLAGS = -i
|
||||||
LIBS = -lsys -lsysutil
|
LIBS = -lsys -lsysutil
|
||||||
|
|
||||||
OBJ = sb16_dsp.o
|
|
||||||
|
|
||||||
# build local binary
|
# build local binary
|
||||||
all build: $(DRIVER)
|
all build: sb16_dsp sb16_mixer
|
||||||
$(DRIVER): $(OBJ)
|
sb16_dsp: sb16.o sb16_dsp.o
|
||||||
$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
|
$(CC) -o $@ $(LDFLAGS) sb16.o sb16_dsp.o $(LIBS)
|
||||||
# install -S 256w $(DRIVER)
|
sb16_mixer: sb16.o sb16_mixer.o
|
||||||
|
$(CC) -o $@ $(LDFLAGS) sb16.o sb16_mixer.o $(LIBS)
|
||||||
|
|
||||||
# install with other drivers
|
# install with other drivers
|
||||||
install: /usr/sbin/$(DRIVER)
|
install: /usr/sbin/sb16_dsp /usr/sbin/sb16_mixer
|
||||||
/usr/sbin/$(DRIVER): $(DRIVER)
|
/usr/sbin/sb16_dsp: sb16_dsp
|
||||||
|
install -o root -c $? $@
|
||||||
|
/usr/sbin/sb16_mixer: sb16_mixer
|
||||||
install -o root -c $? $@
|
install -o root -c $? $@
|
||||||
# install -o root -cs $? $@
|
|
||||||
|
|
||||||
# clean up local files
|
# clean up local files
|
||||||
clean:
|
clean:
|
||||||
|
|
21
drivers/sb16/README
Normal file
21
drivers/sb16/README
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
|
||||||
|
Sound Blaster 16 ISA driver for Minix 3
|
||||||
|
|
||||||
|
Note: supports audio playback and volume control (mixer),
|
||||||
|
recording is not yet supported
|
||||||
|
|
||||||
|
|
||||||
|
Installation instructions SB16 driver Minix >= 3.0.7
|
||||||
|
|
||||||
|
- set IRQ and I/O address in sb16.h
|
||||||
|
(default 7 and 220)
|
||||||
|
- make install
|
||||||
|
- MAKEDEV /dev/audio (if /dev/audio doesn't allready exist)
|
||||||
|
- service up /usr/sbin/sb16_dsp -dev /dev/audio
|
||||||
|
- service up /usr/sbin/sb16_mixer -dev /dev/mixer
|
||||||
|
done... (you can include the last 2 lines in /usr/etc/rc)
|
||||||
|
|
||||||
|
|
||||||
|
Peter Boonstoppel - September 2005
|
||||||
|
paboonst@cs.vu.nl
|
||||||
|
|
46
drivers/sb16/sb16.c
Normal file
46
drivers/sb16/sb16.c
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#include "sb16.h"
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* mixer_set
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int mixer_set(reg, data)
|
||||||
|
int reg;
|
||||||
|
int data;
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
sb16_outb(MIXER_REG, reg);
|
||||||
|
for(i = 0; i < 100; i++);
|
||||||
|
sb16_outb(MIXER_DATA, data);
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* sb16_inb
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int sb16_inb(port)
|
||||||
|
int port;
|
||||||
|
{
|
||||||
|
int s, value = -1;
|
||||||
|
|
||||||
|
if ((s=sys_inb(port, &value)) != OK)
|
||||||
|
panic("SB16DSP","sys_inb() failed", s);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* sb16_outb
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC void sb16_outb(port, value)
|
||||||
|
int port;
|
||||||
|
int value;
|
||||||
|
{
|
||||||
|
int s;
|
||||||
|
|
||||||
|
if ((s=sys_outb(port, value)) != OK)
|
||||||
|
panic("SB16DSP","sys_outb() failed", s);
|
||||||
|
}
|
|
@ -1,8 +1,10 @@
|
||||||
#ifndef SB16_H
|
#ifndef SB16_H
|
||||||
#define SB16_H
|
#define SB16_H
|
||||||
|
|
||||||
#define SB_DEBUG 0 /* 1 = print debug info */
|
#include "../drivers.h"
|
||||||
#define SB_DEBUG_2 0 /* 1 = print more debug info */
|
#include <sys/ioc_sound.h>
|
||||||
|
#include <minix/sound.h>
|
||||||
|
|
||||||
|
|
||||||
#define SB_TIMEOUT 32000 /* timeout count */
|
#define SB_TIMEOUT 32000 /* timeout count */
|
||||||
|
|
||||||
|
@ -32,6 +34,7 @@
|
||||||
#define DMA8_MODE 0x0B
|
#define DMA8_MODE 0x0B
|
||||||
#define DMA8_CLEAR 0x0C
|
#define DMA8_CLEAR 0x0C
|
||||||
|
|
||||||
|
|
||||||
/* If after this preprocessing stuff DMA8_PAGE is not defined
|
/* If after this preprocessing stuff DMA8_PAGE is not defined
|
||||||
* the 8-bit DMA channel specified is not valid
|
* the 8-bit DMA channel specified is not valid
|
||||||
*/
|
*/
|
||||||
|
@ -54,6 +57,7 @@
|
||||||
#define DMA16_MODE 0xD6
|
#define DMA16_MODE 0xD6
|
||||||
#define DMA16_CLEAR 0xD8
|
#define DMA16_CLEAR 0xD8
|
||||||
|
|
||||||
|
|
||||||
/* If after this preprocessing stuff DMA16_PAGE is not defined
|
/* If after this preprocessing stuff DMA16_PAGE is not defined
|
||||||
* the 16-bit DMA channel specified is not valid
|
* the 16-bit DMA channel specified is not valid
|
||||||
*/
|
*/
|
||||||
|
@ -69,12 +73,14 @@
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* DMA modes */
|
/* DMA modes */
|
||||||
#define DMA16_AUTO_PLAY 0x58 + (SB_DMA_16 & 3)
|
#define DMA16_AUTO_PLAY 0x58 + (SB_DMA_16 & 3)
|
||||||
#define DMA16_AUTO_REC 0x54 + (SB_DMA_16 & 3)
|
#define DMA16_AUTO_REC 0x54 + (SB_DMA_16 & 3)
|
||||||
#define DMA8_AUTO_PLAY 0x58 + SB_DMA_8
|
#define DMA8_AUTO_PLAY 0x58 + SB_DMA_8
|
||||||
#define DMA8_AUTO_REC 0x54 + SB_DMA_8
|
#define DMA8_AUTO_REC 0x54 + SB_DMA_8
|
||||||
|
|
||||||
|
|
||||||
/* IO ports for soundblaster */
|
/* IO ports for soundblaster */
|
||||||
#define DSP_RESET 0x6 + SB_BASE_ADDR
|
#define DSP_RESET 0x6 + SB_BASE_ADDR
|
||||||
#define DSP_READ 0xA + SB_BASE_ADDR
|
#define DSP_READ 0xA + SB_BASE_ADDR
|
||||||
|
@ -89,6 +95,7 @@
|
||||||
#define OPL3_RIGHT 0x2 + SB_BASE_ADDR
|
#define OPL3_RIGHT 0x2 + SB_BASE_ADDR
|
||||||
#define OPL3_BOTH 0x8 + SB_BASE_ADDR
|
#define OPL3_BOTH 0x8 + SB_BASE_ADDR
|
||||||
|
|
||||||
|
|
||||||
/* DSP Commands */
|
/* DSP Commands */
|
||||||
#define DSP_INPUT_RATE 0x42 /* set input sample rate */
|
#define DSP_INPUT_RATE 0x42 /* set input sample rate */
|
||||||
#define DSP_OUTPUT_RATE 0x41 /* set output sample rate */
|
#define DSP_OUTPUT_RATE 0x41 /* set output sample rate */
|
||||||
|
@ -106,12 +113,14 @@
|
||||||
#define DSP_CMD_IRQREQ8 0xF2 /* Interrupt request 8 bit */
|
#define DSP_CMD_IRQREQ8 0xF2 /* Interrupt request 8 bit */
|
||||||
#define DSP_CMD_IRQREQ16 0xF3 /* Interrupt request 16 bit */
|
#define DSP_CMD_IRQREQ16 0xF3 /* Interrupt request 16 bit */
|
||||||
|
|
||||||
|
|
||||||
/* DSP Modes */
|
/* DSP Modes */
|
||||||
#define DSP_MODE_MONO_US 0x00 /* Mono unsigned */
|
#define DSP_MODE_MONO_US 0x00 /* Mono unsigned */
|
||||||
#define DSP_MODE_MONO_S 0x10 /* Mono signed */
|
#define DSP_MODE_MONO_S 0x10 /* Mono signed */
|
||||||
#define DSP_MODE_STEREO_US 0x20 /* Stereo unsigned */
|
#define DSP_MODE_STEREO_US 0x20 /* Stereo unsigned */
|
||||||
#define DSP_MODE_STEREO_S 0x30 /* Stereo signed */
|
#define DSP_MODE_STEREO_S 0x30 /* Stereo signed */
|
||||||
|
|
||||||
|
|
||||||
/* MIXER commands */
|
/* MIXER commands */
|
||||||
#define MIXER_RESET 0x00 /* Reset */
|
#define MIXER_RESET 0x00 /* Reset */
|
||||||
#define MIXER_DAC_LEVEL 0x04 /* Used for detection only */
|
#define MIXER_DAC_LEVEL 0x04 /* Used for detection only */
|
||||||
|
@ -160,8 +169,15 @@
|
||||||
#define DSP_MIN_FRAGMENT_SIZE 1024 /* Minimum fragment size */
|
#define DSP_MIN_FRAGMENT_SIZE 1024 /* Minimum fragment size */
|
||||||
#define DSP_NR_OF_BUFFERS 8
|
#define DSP_NR_OF_BUFFERS 8
|
||||||
|
|
||||||
|
|
||||||
/* Number of bytes you can DMA before hitting a 64K boundary: */
|
/* Number of bytes you can DMA before hitting a 64K boundary: */
|
||||||
#define dma_bytes_left(phys) \
|
#define dma_bytes_left(phys) \
|
||||||
((unsigned) (sizeof(int) == 2 ? 0 : 0x10000) - (unsigned) ((phys) & 0xFFFF))
|
((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 */
|
#endif /* SB16_H */
|
||||||
|
|
BIN
drivers/sb16/sb16.tar
Normal file
BIN
drivers/sb16/sb16.tar
Normal file
Binary file not shown.
|
@ -1,6 +1,31 @@
|
||||||
|
/* 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 PROC_NR 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 "sb16.h"
|
#include "sb16.h"
|
||||||
#include "../drivers.h"
|
|
||||||
#include <sys/ioc_sound.h>
|
|
||||||
|
|
||||||
_PROTOTYPE(void main, (void));
|
_PROTOTYPE(void main, (void));
|
||||||
FORWARD _PROTOTYPE( int dsp_open, (void) );
|
FORWARD _PROTOTYPE( int dsp_open, (void) );
|
||||||
|
@ -12,8 +37,6 @@ FORWARD _PROTOTYPE( void dsp_status, (message *m_ptr) );
|
||||||
|
|
||||||
FORWARD _PROTOTYPE( void reply, (int code, int replyee, int process, int status) );
|
FORWARD _PROTOTYPE( void reply, (int code, int replyee, int process, int status) );
|
||||||
FORWARD _PROTOTYPE( void init_buffer, (void) );
|
FORWARD _PROTOTYPE( void init_buffer, (void) );
|
||||||
FORWARD _PROTOTYPE( int dsp_inb, (int port) );
|
|
||||||
FORWARD _PROTOTYPE( void dsp_outb, (int port, int value) );
|
|
||||||
FORWARD _PROTOTYPE( int dsp_init, (void) );
|
FORWARD _PROTOTYPE( int dsp_init, (void) );
|
||||||
FORWARD _PROTOTYPE( int dsp_reset, (void) );
|
FORWARD _PROTOTYPE( int dsp_reset, (void) );
|
||||||
FORWARD _PROTOTYPE( int dsp_command, (int value) );
|
FORWARD _PROTOTYPE( int dsp_command, (int value) );
|
||||||
|
@ -24,7 +47,6 @@ FORWARD _PROTOTYPE( int dsp_set_bits, (unsigned int bits) );
|
||||||
FORWARD _PROTOTYPE( int dsp_set_sign, (unsigned int sign) );
|
FORWARD _PROTOTYPE( int dsp_set_sign, (unsigned int sign) );
|
||||||
FORWARD _PROTOTYPE( void dsp_dma_setup, (phys_bytes address, int count) );
|
FORWARD _PROTOTYPE( void dsp_dma_setup, (phys_bytes address, int count) );
|
||||||
FORWARD _PROTOTYPE( void dsp_setup, (void) );
|
FORWARD _PROTOTYPE( void dsp_setup, (void) );
|
||||||
_PROTOTYPE(int mixer_set, (int reg, int data));
|
|
||||||
|
|
||||||
PRIVATE int irq_hook_id; /* id of irq hook at the kernel */
|
PRIVATE int irq_hook_id; /* id of irq hook at the kernel */
|
||||||
|
|
||||||
|
@ -42,7 +64,6 @@ PRIVATE unsigned int DspSign = DEFAULT_SIGN;
|
||||||
PRIVATE unsigned int DspFragmentSize = DSP_MAX_FRAGMENT_SIZE;
|
PRIVATE unsigned int DspFragmentSize = DSP_MAX_FRAGMENT_SIZE;
|
||||||
PRIVATE int DspAvail = 0;
|
PRIVATE int DspAvail = 0;
|
||||||
PRIVATE int DspBusy = 0;
|
PRIVATE int DspBusy = 0;
|
||||||
PRIVATE int DmaDone = 1;
|
|
||||||
PRIVATE int DmaMode = 0;
|
PRIVATE int DmaMode = 0;
|
||||||
PRIVATE int DmaBusy = -1;
|
PRIVATE int DmaBusy = -1;
|
||||||
PRIVATE int DmaFillNext = 0;
|
PRIVATE int DmaFillNext = 0;
|
||||||
|
@ -55,6 +76,7 @@ PRIVATE int reviveProcNr;
|
||||||
|
|
||||||
#define dprint (void)
|
#define dprint (void)
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* main
|
* main
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -96,6 +118,7 @@ PUBLIC void main()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* dsp_open
|
* dsp_open
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -124,6 +147,7 @@ PRIVATE int dsp_open()
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* dsp_close
|
* dsp_close
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -136,6 +160,7 @@ PRIVATE int dsp_close()
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* dsp_ioctl
|
* dsp_ioctl
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -176,6 +201,7 @@ message *m_ptr;
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* dsp_write
|
* dsp_write
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -191,6 +217,10 @@ message *m_ptr;
|
||||||
reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, EINVAL);
|
reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, EINVAL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if(m_ptr->m_type != DmaMode && DmaBusy >= 0) {
|
||||||
|
reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, EBUSY);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, SUSPEND);
|
reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, SUSPEND);
|
||||||
|
|
||||||
|
@ -235,6 +265,7 @@ message *m_ptr;
|
||||||
notify(m_ptr->m_source);
|
notify(m_ptr->m_source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* dsp_hardware_msg
|
* dsp_hardware_msg
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -245,10 +276,16 @@ PRIVATE void dsp_hardware_msg()
|
||||||
dprint("Finished playing dma[%d]; ", DmaBusy);
|
dprint("Finished playing dma[%d]; ", DmaBusy);
|
||||||
DmaBusy = (DmaBusy + 1) % DMA_NR_OF_BUFFERS;
|
DmaBusy = (DmaBusy + 1) % DMA_NR_OF_BUFFERS;
|
||||||
if(DmaBusy == DmaFillNext) { /* Dma buffer empty, stop Dma transfer */
|
if(DmaBusy == DmaFillNext) { /* Dma buffer empty, stop Dma transfer */
|
||||||
|
|
||||||
dsp_command((DspBits == 8 ? DSP_CMD_DMA8HALT : DSP_CMD_DMA16HALT));
|
dsp_command((DspBits == 8 ? DSP_CMD_DMA8HALT : DSP_CMD_DMA16HALT));
|
||||||
dprint("No more work...!\n");
|
dprint("No more work...!\n");
|
||||||
DmaBusy = -1;
|
DmaBusy = -1;
|
||||||
|
|
||||||
} else if(BufReadNext >= 0) { /* Data in second buffer, copy one fragment to Dma buffer */
|
} 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);
|
memcpy(DmaPtr + DmaFillNext * DspFragmentSize, Buffer + BufReadNext * DspFragmentSize, DspFragmentSize);
|
||||||
dprint("copy buf[%d] -> dma[%d]; ", BufReadNext, DmaFillNext);
|
dprint("copy buf[%d] -> dma[%d]; ", BufReadNext, DmaFillNext);
|
||||||
BufReadNext = (BufReadNext + 1) % DSP_NR_OF_BUFFERS;
|
BufReadNext = (BufReadNext + 1) % DSP_NR_OF_BUFFERS;
|
||||||
|
@ -257,15 +294,19 @@ PRIVATE void dsp_hardware_msg()
|
||||||
BufReadNext = -1;
|
BufReadNext = -1;
|
||||||
}
|
}
|
||||||
dprint("Starting dma[%d]\n", DmaBusy);
|
dprint("Starting dma[%d]\n", DmaBusy);
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
} else { /* Second buffer empty, still data in Dma buffer, continue playback */
|
} else { /* Second buffer empty, still data in Dma buffer, continue playback */
|
||||||
dprint("Starting dma[%d]\n", DmaBusy);
|
dprint("Starting dma[%d]\n", DmaBusy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Acknowledge the interrupt on the DSP */
|
/* Acknowledge the interrupt on the DSP */
|
||||||
dsp_inb((DspBits == 8 ? DSP_DATA_AVL : DSP_DATA16_AVL));
|
sb16_inb((DspBits == 8 ? DSP_DATA_AVL : DSP_DATA16_AVL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* dsp_status *
|
* dsp_status *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -285,6 +326,7 @@ message *m_ptr; /* pointer to the newly arrived message */
|
||||||
send(m_ptr->m_source, m_ptr); /* send the message */
|
send(m_ptr->m_source, m_ptr); /* send the message */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* reply *
|
* reply *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -303,6 +345,7 @@ int status;
|
||||||
send(replyee, &m);
|
send(replyee, &m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* init_buffer
|
* init_buffer
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -328,32 +371,6 @@ PRIVATE void init_buffer()
|
||||||
#endif /* CHIP == INTEL */
|
#endif /* CHIP == INTEL */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* dsp_inb
|
|
||||||
*===========================================================================*/
|
|
||||||
PRIVATE int dsp_inb(port)
|
|
||||||
int port;
|
|
||||||
{
|
|
||||||
int s, value = -1;
|
|
||||||
|
|
||||||
if ((s=sys_inb(port, &value)) != OK)
|
|
||||||
panic("SB16DSP","sys_inb() failed", s);
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* dsp_outb
|
|
||||||
*===========================================================================*/
|
|
||||||
PRIVATE void dsp_outb(port, value)
|
|
||||||
int port;
|
|
||||||
int value;
|
|
||||||
{
|
|
||||||
int s;
|
|
||||||
|
|
||||||
if ((s=sys_outb(port, value)) != OK)
|
|
||||||
panic("SB16DSP","sys_outb() failed", s);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* dsp_init
|
* dsp_init
|
||||||
|
@ -371,11 +388,11 @@ PRIVATE int dsp_init()
|
||||||
dsp_command(DSP_GET_VERSION); /* Get DSP version bytes */
|
dsp_command(DSP_GET_VERSION); /* Get DSP version bytes */
|
||||||
|
|
||||||
for(i = 1000; i; i--) {
|
for(i = 1000; i; i--) {
|
||||||
if(dsp_inb(DSP_DATA_AVL) & 0x80) {
|
if(sb16_inb(DSP_DATA_AVL) & 0x80) {
|
||||||
if(DspVersion[0] == 0) {
|
if(DspVersion[0] == 0) {
|
||||||
DspVersion[0] = dsp_inb(DSP_READ);
|
DspVersion[0] = sb16_inb(DSP_READ);
|
||||||
} else {
|
} else {
|
||||||
DspVersion[1] = dsp_inb(DSP_READ);
|
DspVersion[1] = sb16_inb(DSP_READ);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -402,6 +419,7 @@ PRIVATE int dsp_init()
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* dsp_reset
|
* dsp_reset
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -409,20 +427,20 @@ PRIVATE int dsp_reset()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
dsp_outb(DSP_RESET, 1);
|
sb16_outb(DSP_RESET, 1);
|
||||||
for(i = 0; i < 1000; i++); /* wait a while */
|
for(i = 0; i < 1000; i++); /* wait a while */
|
||||||
dsp_outb(DSP_RESET, 0);
|
sb16_outb(DSP_RESET, 0);
|
||||||
|
|
||||||
for(i = 0; i < 1000 && !(dsp_inb(DSP_DATA_AVL) & 0x80); i++);
|
for(i = 0; i < 1000 && !(sb16_inb(DSP_DATA_AVL) & 0x80); i++);
|
||||||
|
|
||||||
if(dsp_inb(DSP_READ) != 0xAA) return EIO; /* No SoundBlaster */
|
if(sb16_inb(DSP_READ) != 0xAA) return EIO; /* No SoundBlaster */
|
||||||
|
|
||||||
DmaBusy = -1;
|
DmaBusy = -1;
|
||||||
DmaDone = 1;
|
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* dsp_command
|
* dsp_command
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -432,8 +450,8 @@ int value;
|
||||||
int i, status;
|
int i, status;
|
||||||
|
|
||||||
for (i = 0; i < SB_TIMEOUT; i++) {
|
for (i = 0; i < SB_TIMEOUT; i++) {
|
||||||
if((dsp_inb(DSP_STATUS) & 0x80) == 0) {
|
if((sb16_inb(DSP_STATUS) & 0x80) == 0) {
|
||||||
dsp_outb(DSP_COMMAND, value);
|
sb16_outb(DSP_COMMAND, value);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -442,6 +460,7 @@ int value;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* dsp_set_size
|
* dsp_set_size
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -460,6 +479,7 @@ unsigned int size;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* dsp_set_speed
|
* dsp_set_speed
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -491,6 +511,7 @@ unsigned int speed;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* dsp_set_stereo
|
* dsp_set_stereo
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -506,6 +527,7 @@ unsigned int stereo;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* dsp_set_bits
|
* dsp_set_bits
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -522,6 +544,7 @@ unsigned int bits;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* dsp_set_sign
|
* dsp_set_sign
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -535,6 +558,7 @@ unsigned int sign;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* dsp_dma_setup
|
* dsp_dma_setup
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -542,41 +566,50 @@ PRIVATE void dsp_dma_setup(address, count)
|
||||||
phys_bytes address;
|
phys_bytes address;
|
||||||
int count;
|
int count;
|
||||||
{
|
{
|
||||||
|
pvb_pair_t pvb[9];
|
||||||
|
|
||||||
|
|
||||||
dprint("Setting up %d bit DMA\n", DspBits);
|
dprint("Setting up %d bit DMA\n", DspBits);
|
||||||
|
|
||||||
if(DspBits == 8) { /* 8 bit sound */
|
if(DspBits == 8) { /* 8 bit sound */
|
||||||
count--;
|
count--;
|
||||||
|
|
||||||
dsp_outb(DMA8_MASK, SB_DMA_8 | 0x04); /* Disable DMA channel */
|
pv_set(pvb[0], DMA8_MASK, SB_DMA_8 | 0x04); /* Disable DMA channel */
|
||||||
dsp_outb(DMA8_CLEAR, 0x00); /* Clear flip flop */
|
pv_set(pvb[1], DMA8_CLEAR, 0x00); /* Clear flip flop */
|
||||||
|
|
||||||
/* set DMA mode */
|
/* set DMA mode */
|
||||||
dsp_outb(DMA8_MODE, (DmaMode == DEV_WRITE ? DMA8_AUTO_PLAY : DMA8_AUTO_REC));
|
pv_set(pvb[2], DMA8_MODE, (DmaMode == DEV_WRITE ? DMA8_AUTO_PLAY : DMA8_AUTO_REC));
|
||||||
|
|
||||||
dsp_outb(DMA8_ADDR, address >> 0); /* Low_byte of address */
|
pv_set(pvb[3], DMA8_ADDR, address >> 0); /* Low_byte of address */
|
||||||
dsp_outb(DMA8_ADDR, address >> 8); /* High byte of address */
|
pv_set(pvb[4], DMA8_ADDR, address >> 8); /* High byte of address */
|
||||||
dsp_outb(DMA8_PAGE, address >> 16); /* 64K page number */
|
pv_set(pvb[5], DMA8_PAGE, address >> 16); /* 64K page number */
|
||||||
dsp_outb(DMA8_COUNT, count >> 0); /* Low byte of count */
|
pv_set(pvb[6], DMA8_COUNT, count >> 0); /* Low byte of count */
|
||||||
dsp_outb(DMA8_COUNT, count >> 8); /* High byte of count */
|
pv_set(pvb[7], DMA8_COUNT, count >> 8); /* High byte of count */
|
||||||
dsp_outb(DMA8_MASK, SB_DMA_8); /* Enable DMA channel */
|
pv_set(pvb[8], DMA8_MASK, SB_DMA_8); /* Enable DMA channel */
|
||||||
|
|
||||||
|
sys_voutb(pvb, 9);
|
||||||
} else { /* 16 bit sound */
|
} else { /* 16 bit sound */
|
||||||
count-= 2;
|
count-= 2;
|
||||||
|
|
||||||
dsp_outb(DMA16_MASK, (SB_DMA_16 & 3) | 0x04); /* Disable DMA channel */
|
pv_set(pvb[0], DMA16_MASK, (SB_DMA_16 & 3) | 0x04); /* Disable DMA channel */
|
||||||
dsp_outb(DMA16_CLEAR, 0x00); /* Clear flip flop */
|
|
||||||
|
pv_set(pvb[1], DMA16_CLEAR, 0x00); /* Clear flip flop */
|
||||||
|
|
||||||
/* Set dma mode */
|
/* Set dma mode */
|
||||||
dsp_outb(DMA16_MODE, (DmaMode == DEV_WRITE ? DMA16_AUTO_PLAY : DMA16_AUTO_REC));
|
pv_set(pvb[2], DMA16_MODE, (DmaMode == DEV_WRITE ? DMA16_AUTO_PLAY : DMA16_AUTO_REC));
|
||||||
|
|
||||||
dsp_outb(DMA16_ADDR, (address >> 1) & 0xFF); /* Low_byte of address */
|
pv_set(pvb[3], DMA16_ADDR, (address >> 1) & 0xFF); /* Low_byte of address */
|
||||||
dsp_outb(DMA16_ADDR, (address >> 9) & 0xFF); /* High byte of address */
|
pv_set(pvb[4], DMA16_ADDR, (address >> 9) & 0xFF); /* High byte of address */
|
||||||
dsp_outb(DMA16_PAGE, (address >> 16) & 0xFE); /* 128K page number */
|
pv_set(pvb[5], DMA16_PAGE, (address >> 16) & 0xFE); /* 128K page number */
|
||||||
dsp_outb(DMA16_COUNT, count >> 1); /* Low byte of count */
|
pv_set(pvb[6], DMA16_COUNT, count >> 1); /* Low byte of count */
|
||||||
dsp_outb(DMA16_COUNT, count >> 9); /* High byte of count */
|
pv_set(pvb[7], DMA16_COUNT, count >> 9); /* High byte of count */
|
||||||
dsp_outb(DMA16_MASK, SB_DMA_16 & 3); /* Enable DMA channel */
|
pv_set(pvb[8], DMA16_MASK, SB_DMA_16 & 3); /* Enable DMA channel */
|
||||||
|
|
||||||
|
sys_voutb(pvb, 9);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* dsp_setup()
|
* dsp_setup()
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -617,18 +650,4 @@ PRIVATE void dsp_setup()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* mixer_set
|
|
||||||
*===========================================================================*/
|
|
||||||
PUBLIC int mixer_set(reg, data)
|
|
||||||
int reg;
|
|
||||||
int data;
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
dsp_outb(MIXER_REG, reg);
|
|
||||||
for(i = 0; i < 100; i++);
|
|
||||||
dsp_outb(MIXER_DATA, data);
|
|
||||||
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
387
drivers/sb16/sb16_mixer.c
Normal file
387
drivers/sb16/sb16_mixer.c
Normal file
|
@ -0,0 +1,387 @@
|
||||||
|
/* 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 PROC_NR 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"
|
||||||
|
|
||||||
|
|
||||||
|
_PROTOTYPE(void main, (void));
|
||||||
|
FORWARD _PROTOTYPE( int mixer_init, (void));
|
||||||
|
FORWARD _PROTOTYPE( int mixer_open, (message *m_ptr));
|
||||||
|
FORWARD _PROTOTYPE( int mixer_close, (message *m_ptr));
|
||||||
|
FORWARD _PROTOTYPE( int mixer_ioctl, (message *m_ptr));
|
||||||
|
FORWARD _PROTOTYPE( int mixer_get, (int reg));
|
||||||
|
FORWARD _PROTOTYPE( int get_set_volume, (message *m_ptr, int flag));
|
||||||
|
FORWARD _PROTOTYPE( int get_set_input, (message *m_ptr, int flag, int channel));
|
||||||
|
FORWARD _PROTOTYPE( int get_set_output, (message *m_ptr, int flag));
|
||||||
|
|
||||||
|
|
||||||
|
PRIVATE int mixer_avail = 0; /* Mixer exists? */
|
||||||
|
|
||||||
|
|
||||||
|
#define dprint (void)
|
||||||
|
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* main
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC void main() {
|
||||||
|
message mess;
|
||||||
|
int err, caller, proc_nr;
|
||||||
|
|
||||||
|
/* Here is the main loop of the mixer task. It waits for a message, carries
|
||||||
|
* it out, and sends a reply.
|
||||||
|
*/
|
||||||
|
while (TRUE) {
|
||||||
|
receive(ANY, &mess);
|
||||||
|
|
||||||
|
caller = mess.m_source;
|
||||||
|
proc_nr = mess.PROC_NR;
|
||||||
|
|
||||||
|
switch (caller) {
|
||||||
|
case HARDWARE: /* Leftover interrupt. */
|
||||||
|
continue;
|
||||||
|
case FS_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;
|
||||||
|
case DEV_IOCTL: err = mixer_ioctl(&mess); break;
|
||||||
|
default: err = EINVAL; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finally, prepare and send the reply message. */
|
||||||
|
mess.m_type = TASK_REPLY;
|
||||||
|
mess.REP_PROC_NR = proc_nr;
|
||||||
|
|
||||||
|
dprint("%d %d", err, OK);
|
||||||
|
|
||||||
|
mess.REP_STATUS = err; /* error code */
|
||||||
|
send(caller, &mess); /* send reply to caller */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*=========================================================================*
|
||||||
|
* mixer_open
|
||||||
|
*=========================================================================*/
|
||||||
|
PRIVATE int mixer_open(m_ptr)
|
||||||
|
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(m_ptr)
|
||||||
|
message *m_ptr;
|
||||||
|
{
|
||||||
|
dprint("mixer_close\n");
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*=========================================================================*
|
||||||
|
* mixer_ioctl
|
||||||
|
*=========================================================================*/
|
||||||
|
PRIVATE int mixer_ioctl(m_ptr)
|
||||||
|
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(reg)
|
||||||
|
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(m_ptr, flag)
|
||||||
|
message *m_ptr;
|
||||||
|
int flag; /* 0 = get, 1 = set */
|
||||||
|
{
|
||||||
|
phys_bytes user_phys;
|
||||||
|
struct volume_level level;
|
||||||
|
int cmd_left, cmd_right, shift, max_level;
|
||||||
|
|
||||||
|
sys_datacopy(m_ptr->PROC_NR, (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->PROC_NR, (vir_bytes)m_ptr->ADDRESS, (phys_bytes)sizeof(level));
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*=========================================================================*
|
||||||
|
* get_set_input *
|
||||||
|
*=========================================================================*/
|
||||||
|
PRIVATE int get_set_input(m_ptr, flag, channel)
|
||||||
|
message *m_ptr;
|
||||||
|
int flag; /* 0 = get, 1 = set */
|
||||||
|
int channel; /* 0 = left, 1 = right */
|
||||||
|
{
|
||||||
|
phys_bytes user_phys;
|
||||||
|
struct inout_ctrl input;
|
||||||
|
int input_cmd, input_mask, mask, del_mask, shift;
|
||||||
|
|
||||||
|
sys_datacopy(m_ptr->PROC_NR, (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->PROC_NR, (vir_bytes)m_ptr->ADDRESS, (phys_bytes)sizeof(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*=========================================================================*
|
||||||
|
* get_set_output *
|
||||||
|
*=========================================================================*/
|
||||||
|
PRIVATE int get_set_output(m_ptr, flag)
|
||||||
|
message *m_ptr;
|
||||||
|
int flag; /* 0 = get, 1 = set */
|
||||||
|
{
|
||||||
|
phys_bytes user_phys;
|
||||||
|
struct inout_ctrl output;
|
||||||
|
int output_mask, mask, del_mask, shift;
|
||||||
|
|
||||||
|
sys_datacopy(m_ptr->PROC_NR, (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->PROC_NR, (vir_bytes)m_ptr->ADDRESS, (phys_bytes)sizeof(output));
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
Loading…
Reference in a new issue