]> Zhao Yanbai Git Server - minix.git/commitdiff
es1370 driver and updated es1371 and framework by Pieter Hijma.
authorBen Gras <ben@minix3.org>
Fri, 23 Nov 2007 11:40:33 +0000 (11:40 +0000)
committerBen Gras <ben@minix3.org>
Fri, 23 Nov 2007 11:40:33 +0000 (11:40 +0000)
19 files changed:
drivers/audio/README
drivers/audio/es1370/Makefile [new file with mode: 0644]
drivers/audio/es1370/ak4531.c [new file with mode: 0644]
drivers/audio/es1370/ak4531.h [new file with mode: 0644]
drivers/audio/es1370/es1370.c [new file with mode: 0644]
drivers/audio/es1370/es1370.h [new file with mode: 0644]
drivers/audio/es1370/pci_helper.c [new file with mode: 0644]
drivers/audio/es1370/pci_helper.h [new file with mode: 0644]
drivers/audio/es1371/.depend [deleted file]
drivers/audio/es1371/Makefile
drivers/audio/es1371/es1371.c
drivers/audio/es1371/es1371.h
drivers/audio/es1371/wait.c
drivers/audio/es1371/wait.h
drivers/audio/framework/audio_fw.c
drivers/audio/framework/audio_fw.h
drivers/audio/sb16/.depend [deleted file]
etc/drivers.conf
include/sys/ioc_sound.h

index b60763d3c7458b54ba562d3988e0078284075fda..4e16a3a690b4b7eec0837674c4099c8d3653549d 100644 (file)
@@ -1,9 +1,9 @@
-
 ***** Minix 3 Audio drivers *****
 
 Directories:
 framework/         Generic driver framework
 sb16/              SB16 ISA driver
+es1370/            ES1370 driver
 es1371/            ES1371 driver
 
 
@@ -18,11 +18,12 @@ Creating special files:
 * mknod rec c 13 1
 * mknod mixer c 13 2
 * chmod 666 audio rec mixer
-(for es1371 one can add a special file for the second DAC-channel, major 13, minor 3)
+(one can add a special file for the second DAC-channel, major 13, minor 3)
 
 
 Running the driver:
 * service up /usr/sbin/sb16 -dev /dev/audio
+* service up /usr/sbin/es1370 -dev /dev/audio
 or:
 * service up /usr/sbin/es1371 -dev /dev/audio
 
diff --git a/drivers/audio/es1370/Makefile b/drivers/audio/es1370/Makefile
new file mode 100644 (file)
index 0000000..dafa0a5
--- /dev/null
@@ -0,0 +1,39 @@
+# Makefile for the ES1371 sounddriver (SB16)
+
+# directories
+u = /usr
+i = $u/include
+s = $i/sys
+m = $i/minix
+b = $i/ibm
+gen_drv_dir = ../../gen_drivers/cyclic_dma
+
+# programs, flags, etc.
+CC =   exec cc
+CFLAGS = -I$i
+LDFLAGS = -i
+LIBS = -lsys -lsysutil 
+
+# build local binary
+all:   es1370
+
+es1370:        es1370.o ak4531.o audio_fw.o pci_helper.o
+       $(CC) -o $@ $(LDFLAGS) es1370.o ak4531.o audio_fw.o pci_helper.o $(LIBS)
+
+audio_fw.o: ../framework/audio_fw.c ../framework/audio_fw.h
+       $(CC) -c ../framework/audio_fw.c
+       
+install: /usr/sbin/es1370
+/usr/sbin/es1370:      es1370
+       install -o root -S 1024k -c $? $@
+
+# clean up local files
+clean:
+       rm -f *.o *.bak core es1370
+
+depend: 
+       /usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
+
+# Include generated dependencies.
+include .depend
+
diff --git a/drivers/audio/es1370/ak4531.c b/drivers/audio/es1370/ak4531.c
new file mode 100644 (file)
index 0000000..027bc83
--- /dev/null
@@ -0,0 +1,177 @@
+/* best viewed with tabsize 4 */
+
+
+#include "ak4531.h"
+#include "pci_helper.h"
+
+
+#define MASTER_VOLUME_LCH                              0x00
+#define MASTER_VOLUME_RCH                              0x01
+#define FM_VOLUME_LCH                                  0x04
+#define FM_VOLUME_RCH                                  0x05
+#define CD_AUDIO_VOLUME_LCH                            0x06
+#define CD_AUDIO_VOLUME_RCH                            0x07
+#define LINE_VOLUME_LCH                                        0x08
+#define LINE_VOLUME_RCH                                        0x09
+#define MIC_VOLUME                                             0x0e
+#define MONO_OUT_VOLUME                                        0x0f
+
+#define RESET_AND_POWER_DOWN                   0x16
+#define PD                                                             0x02
+#define RST                                                            0x01
+
+#define AD_INPUT_SELECT                                        0x18
+#define MIC_AMP_GAIN                                   0x19
+
+#define MUTE                                                   0x80
+
+
+FORWARD _PROTOTYPE( int ak4531_write, (u8_t address, u8_t data) );
+FORWARD _PROTOTYPE( int ak4531_finished, (void) );
+FORWARD _PROTOTYPE( int set_volume, (struct volume_level *level, 
+                       int cmd_left, int cmd_right, int max_level) );
+
+PRIVATE u16_t base_address; 
+PRIVATE u16_t status_register;
+PRIVATE u16_t status_bit;
+PRIVATE u16_t poll_address;
+
+u8_t mixer_values[0x20] = {
+       0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 0x00 - 0x07 */
+       0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, /* 0x08 - 0x0f */
+       0x7e, 0x3d, 0x01, 0x01, 0x00, 0x00, 0x03, 0x00, /* 0x10 - 0x17 */
+       0x00, 0x01                                                                              /* 0x18 - 0x19 */
+};
+#if 0
+u8_t mixer_values[0x20] = {
+       0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 0x00 - 0x07 */
+       0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 0x08 - 0x0f */
+       0x7f, 0x3d, 0x55, 0x26, 0xf7, 0xef, 0x03, 0x00, /* 0x10 - 0x17 */
+       0x00, 0x01                                                                              /* 0x18 - 0x19 */
+};
+#endif
+
+
+
+PRIVATE int ak4531_finished(void) {
+       int i;
+       u16_t cstat;
+       for (i = 0; i < 0x40000; i++) {
+               cstat = pci_inw(status_register);
+               if (!(cstat & status_bit)) {
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+
+PRIVATE int ak4531_write (u8_t address, u8_t data) {
+       u16_t to_be_written;
+
+
+       if (address < MASTER_VOLUME_LCH || address > MIC_AMP_GAIN) return -1;
+
+       to_be_written = (u16_t)((address << 8) | data);
+
+       if (!ak4531_finished()) return -1;
+       pci_outw(base_address, to_be_written);
+       return 0;
+}
+
+
+PUBLIC int ak4531_init(u16_t base, u16_t status_reg, u16_t bit, 
+               u16_t poll) {
+       int i;
+
+       base_address = base;
+       status_register = status_reg;
+       status_bit = bit;
+       poll_address = poll;
+
+       for (i=0; i<100; i++) {
+               pci_inb(poll_address);
+       }
+       if(ak4531_write(RESET_AND_POWER_DOWN, PD|RST) < 0) return -1;
+
+       for (i=0; i<100; i++) {
+               pci_inb(poll_address);
+       }
+
+       ak4531_write(AD_INPUT_SELECT, 0x00);
+
+       for (i = MASTER_VOLUME_LCH ; i <= MIC_AMP_GAIN; i++) {
+               if (ak4531_write(i, mixer_values[i]) < 0) return -1;
+       }
+       return 0;
+}
+
+
+PUBLIC int ak4531_get_set_volume(struct volume_level *level, int flag) {
+       int cmd_left, cmd_right, max_level;
+
+       max_level = 0x1f;
+
+       switch(level->device) {
+               case Master:
+                       cmd_left = MASTER_VOLUME_LCH;
+                       cmd_right = MASTER_VOLUME_RCH;
+                       break;
+               case Dac:
+                       return EINVAL;
+                       break;
+               case Fm:
+                       cmd_left = FM_VOLUME_LCH;
+                       cmd_right = FM_VOLUME_RCH;
+                       break;
+               case Cd:
+                       cmd_left = CD_AUDIO_VOLUME_LCH;
+                       cmd_right = CD_AUDIO_VOLUME_RCH;
+                       break;
+               case Line:
+                       cmd_left = LINE_VOLUME_LCH;
+                       cmd_right = LINE_VOLUME_RCH;
+                       break;
+               case Mic:
+                       cmd_left = cmd_right = MIC_VOLUME;
+                       break;
+               case Speaker:
+                       cmd_left = cmd_right = MONO_OUT_VOLUME;
+                       max_level = 0x03;
+                       break;
+               case Treble:
+                       return EINVAL;
+                       break;
+               case Bass:  
+                       return EINVAL;
+                       break;
+               default:     
+                       return EINVAL;
+       }
+
+       if (flag) { /* set volume */
+               return set_volume(level, cmd_left, cmd_right, max_level);
+       }
+       else { /* get volume */
+               level->left = - ((int) (mixer_values[cmd_left] & ~MUTE)) + 0x1f;
+               level->right = - ((int) (mixer_values[cmd_right] & ~MUTE)) + 0x1f;
+               return OK;
+       }
+}
+
+
+PRIVATE int set_volume(struct volume_level *level, int cmd_left, int cmd_right, 
+               int max_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_values[cmd_left] = (-level->left)+0x1f;
+       ak4531_write(cmd_left, mixer_values[cmd_left]);
+       mixer_values[cmd_right] = (-level->right)+0x1f;
+       ak4531_write(cmd_right, mixer_values[cmd_right]);
+
+       return OK;
+}
diff --git a/drivers/audio/es1370/ak4531.h b/drivers/audio/es1370/ak4531.h
new file mode 100644 (file)
index 0000000..561da2e
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef AK4531_H
+#define AK4531_H
+/* best viewed with tabsize=4 */
+
+#include "../../drivers.h"
+#include <minix/sound.h>
+
+_PROTOTYPE( int ak4531_init, (u16_t base, u16_t status_reg, u16_t bit, 
+                       u16_t poll) );
+_PROTOTYPE( int ak4531_get_set_volume, (struct volume_level *level, int flag) );
+
+#endif
diff --git a/drivers/audio/es1370/es1370.c b/drivers/audio/es1370/es1370.c
new file mode 100644 (file)
index 0000000..d9f222a
--- /dev/null
@@ -0,0 +1,653 @@
+/* Best viewed with tabsize 4 */
+
+/* Ensoniq ES1370 driver
+ *
+ * aka AudioPCI '97
+ *
+ * This is the main file of the ES1370 sound driver. There is no main function
+ * over here, instead the main function is located in the generic dma driver.
+ * All this driver does is implement the interface audio/audio_fw.h. All
+ * functions having the prefix 'drv_' are dictated by audio/audio_fw.h. The
+ * function prototypes you see below define a set of private helper functions.
+ * Control over the AK4531 codec is delegated ak4531.c.  
+ *
+ * September 2007    ES1370 driver (Pieter Hijma), 
+ * based on ES1371 driver by Laurens Bronwasser
+ */
+
+#include <ibm/pci.h>
+
+#include "../framework/audio_fw.h"
+#include "es1370.h"
+#include "ak4531.h"
+#include "pci_helper.h"
+
+
+/* reg(n) will be the device specific addresses */
+#define reg(n) dev.base + n
+
+
+/* prototypes of private functions */
+FORWARD _PROTOTYPE( int detect_hw, (void) );  
+FORWARD _PROTOTYPE( int disable_int, (int sub_dev) );
+FORWARD _PROTOTYPE( int set_stereo, (u32_t stereo, int sub_dev) );
+FORWARD _PROTOTYPE( int set_bits, (u32_t nr_of_bits, int sub_dev) );
+FORWARD _PROTOTYPE( int set_sample_rate, (u32_t rate, int sub_dev) );
+FORWARD _PROTOTYPE( int set_sign, (u32_t val, int sub_dev) );
+FORWARD _PROTOTYPE( int get_max_frag_size, 
+               (u32_t * val, int *len, int sub_dev) );
+FORWARD _PROTOTYPE( int set_frag_size, (u32_t fragment_size, int sub_dev) );
+FORWARD _PROTOTYPE( int set_int_cnt, (int sub_dev) );
+FORWARD _PROTOTYPE( int free_buf, (u32_t *val, int *len, int sub_dev) );
+FORWARD _PROTOTYPE( int get_samples_in_buf, 
+               (u32_t *val, int *len, int sub_dev) );
+FORWARD _PROTOTYPE( int get_set_volume, (struct volume_level *level, int *len, 
+               int sub_dev, int flag) );
+FORWARD _PROTOTYPE( int reset, (int sub_dev) );
+
+
+DEV_STRUCT dev;
+aud_sub_dev_conf_t aud_conf[4];
+
+
+PUBLIC sub_dev_t sub_dev[4];
+PUBLIC special_file_t special_file[4];
+PUBLIC drv_t drv;
+
+
+PUBLIC int drv_init(void) {
+       drv.DriverName = DRIVER_NAME;
+       drv.NrOfSubDevices = 4;
+       drv.NrOfSpecialFiles = 4;
+
+       sub_dev[DAC1_CHAN].readable = 0;
+       sub_dev[DAC1_CHAN].writable = 1;
+       sub_dev[DAC1_CHAN].DmaSize = 64 * 1024;
+       sub_dev[DAC1_CHAN].NrOfDmaFragments = 2;
+       sub_dev[DAC1_CHAN].MinFragmentSize = 1024;
+       sub_dev[DAC1_CHAN].NrOfExtraBuffers = 4;
+
+       sub_dev[ADC1_CHAN].readable = 1;
+       sub_dev[ADC1_CHAN].writable = 0;
+       sub_dev[ADC1_CHAN].DmaSize = 64 * 1024;
+       sub_dev[ADC1_CHAN].NrOfDmaFragments = 2;
+       sub_dev[ADC1_CHAN].MinFragmentSize = 1024;
+       sub_dev[ADC1_CHAN].NrOfExtraBuffers = 4;
+
+       sub_dev[MIXER].writable = 0;
+       sub_dev[MIXER].readable = 0;
+
+       sub_dev[DAC2_CHAN].readable = 0;
+       sub_dev[DAC2_CHAN].writable = 1;
+       sub_dev[DAC2_CHAN].DmaSize = 64 * 1024;
+       sub_dev[DAC2_CHAN].NrOfDmaFragments = 2;
+       sub_dev[DAC2_CHAN].MinFragmentSize = 1024;
+       sub_dev[DAC2_CHAN].NrOfExtraBuffers = 4;
+
+       special_file[0].minor_dev_nr = 0;
+       special_file[0].write_chan = DAC1_CHAN;
+       special_file[0].read_chan = NO_CHANNEL;
+       special_file[0].io_ctl = DAC1_CHAN;
+
+       special_file[1].minor_dev_nr = 1;
+       special_file[1].write_chan = NO_CHANNEL;
+       special_file[1].read_chan = ADC1_CHAN;
+       special_file[1].io_ctl = ADC1_CHAN;
+
+       special_file[2].minor_dev_nr = 2;
+       special_file[2].write_chan = NO_CHANNEL;
+       special_file[2].read_chan = NO_CHANNEL;
+       special_file[2].io_ctl = MIXER;
+
+       special_file[3].minor_dev_nr = 3;
+       special_file[3].write_chan = DAC2_CHAN;
+       special_file[3].read_chan = NO_CHANNEL;
+       special_file[3].io_ctl = DAC2_CHAN;
+}
+
+
+PUBLIC int drv_init_hw (void) {
+       u16_t i, j;
+       u16_t chip_sel_ctrl_reg;
+
+       /* First, detect the hardware */
+       if (detect_hw() != OK) {
+               return EIO;
+       }
+
+       /* PCI command register 
+        * enable the SERR# driver, PCI bus mastering and I/O access
+        */
+       pci_attr_w16 (dev.devind, PCI_CR, SERR_EN|PCI_MASTER|IO_ACCESS);
+
+       /* turn everything off */
+       pci_outl(reg(CHIP_SEL_CTRL),  0x0UL);
+
+       /* turn off legacy (legacy control is undocumented) */
+       pci_outl(reg(LEGACY), 0x0UL);
+       pci_outl(reg(LEGACY+4), 0x0UL);
+
+       /* turn off serial interface */
+       pci_outl(reg(SERIAL_INTERFACE_CTRL), 0x0UL);
+       /*pci_outl(reg(SERIAL_INTERFACE_CTRL), 0x3UL);*/
+
+
+       /* enable the codec */
+       chip_sel_ctrl_reg = pci_inw(reg(CHIP_SEL_CTRL));
+       chip_sel_ctrl_reg |= XCTL0 | CDC_EN; 
+       pci_outw(reg(CHIP_SEL_CTRL), chip_sel_ctrl_reg);
+
+       /* initialize the codec */
+       if (ak4531_init(reg(CODEC_WRITE_ADDRESS), 
+                               reg(INTERRUPT_STATUS), CWRIP, reg(0)) < 0) {
+               return EINVAL;
+       }
+
+       /* clear all the memory */
+       for (i = 0; i < 0x10; ++i) {
+               pci_outb(reg(MEM_PAGE), i);
+               for (j = 0; j < 0x10; j += 4) {
+                       pci_outl  (reg(MEMORY) + j, 0x0UL);
+               }
+       }
+
+       /* initialize variables for each sub_device */
+       for (i = 0; i < drv.NrOfSubDevices; i++) {
+               if(i != MIXER) {
+                       aud_conf[i].busy = 0;
+                       aud_conf[i].stereo = DEFAULT_STEREO;
+                       aud_conf[i].sample_rate = DEFAULT_RATE;
+                       aud_conf[i].nr_of_bits = DEFAULT_NR_OF_BITS;
+                       aud_conf[i].sign = DEFAULT_SIGNED;
+                       aud_conf[i].fragment_size = 
+                               sub_dev[i].DmaSize / sub_dev[i].NrOfDmaFragments;
+               }
+       }
+       return OK;
+}
+
+
+PRIVATE int detect_hw(void) {
+       u32_t device;
+       int devind;
+       u16_t v_id, d_id;
+
+       /* detect_hw tries to find device and get IRQ and base address
+          with a little (much) help from the PCI library. 
+          This code is quite device independent and you can copy it. 
+          (just make sure to get the bugs out first)*/
+
+       pci_init();
+       /* get first device and then search through the list */
+       device = pci_first_dev(&devind, &v_id, &d_id);
+       while( device > 0 ) {
+               /* if we have a match...break */
+               if (v_id == VENDOR_ID && d_id == DEVICE_ID) break;
+               device = pci_next_dev(&devind, &v_id, &d_id);
+       }
+
+       /* did we find anything? */
+       if (v_id != VENDOR_ID || d_id != DEVICE_ID) {
+               return EIO;
+       }
+
+       pci_reserve(devind);
+
+       dev.name = pci_dev_name(v_id, d_id);
+
+       /* get base address of our device, ignore least signif. bit 
+          this last bit thing could be device dependent, i don't know */
+       dev.base = pci_attr_r32(devind, PCI_BAR) & 0xfffffffe;
+
+       /* get IRQ */
+       dev.irq = pci_attr_r8(devind, PCI_ILR);  
+       dev.revision = pci_attr_r8(devind, PCI_REV);
+       dev.d_id = d_id;
+       dev.v_id = v_id;
+       dev.devind = devind; /* pci device identifier */
+
+       return OK;
+}
+
+
+PRIVATE int reset(int chan) {
+       drv_stop(chan);
+       sub_dev[chan].OutOfData = 1;
+
+       return OK;
+}
+
+
+int drv_reset() {
+       return OK;
+}
+
+
+int drv_start(int sub_dev, int DmaMode) {
+       u32_t enable_bit, result = 0;
+       u32_t debug;
+
+       /* Write default values to device in case user failed to configure.
+          If user did configure properly, everything is written twice.
+          please raise your hand if you object against to this strategy...*/
+       result |= set_sample_rate(aud_conf[sub_dev].sample_rate, sub_dev);
+       result |= set_stereo(aud_conf[sub_dev].stereo, sub_dev);
+       result |= set_bits(aud_conf[sub_dev].nr_of_bits, sub_dev);
+       result |= set_sign(aud_conf[sub_dev].sign, sub_dev);
+
+       /* set the interrupt count */
+       result |= set_int_cnt(sub_dev);
+
+       if (result) {
+               return EIO;
+       }
+
+       /* if device currently paused, resume */
+       drv_resume(sub_dev);
+
+       switch(sub_dev) {
+               case ADC1_CHAN: enable_bit = ADC1_EN;break;
+               case DAC1_CHAN: enable_bit = DAC1_EN;break;
+               case DAC2_CHAN: enable_bit = DAC2_EN;break;    
+               default: return EINVAL;
+       }
+
+       /* enable interrupts from 'sub device' */
+       drv_reenable_int(sub_dev);
+
+       /* this means play!!! */
+       pci_outw(reg(CHIP_SEL_CTRL), pci_inw(reg(CHIP_SEL_CTRL)) | enable_bit);
+
+       aud_conf[sub_dev].busy = 1;
+
+               return OK;
+}
+
+
+int drv_stop(int sub_dev)
+{
+       u32_t enable_bit;
+
+       switch(sub_dev) {
+               case ADC1_CHAN: enable_bit = ADC1_EN;break;
+               case DAC1_CHAN: enable_bit = DAC1_EN;break;
+               case DAC2_CHAN: enable_bit = DAC2_EN;break;    
+               default: return EINVAL;
+       }
+
+       /* stop the specified channel */
+       pci_outw(reg(CHIP_SEL_CTRL),
+                       pci_inw(reg(CHIP_SEL_CTRL)) & ~enable_bit);
+       aud_conf[sub_dev].busy = 0;
+       disable_int(sub_dev);
+
+       return OK;
+}
+
+
+/* all IO-ctl's sent to the upper driver are passed to this function */
+int drv_io_ctl(int request, void * val, int * len, int sub_dev) {
+
+       int status;
+
+       switch(request) {
+               case DSPIORATE: 
+                       status = set_sample_rate(*((u32_t *) val), sub_dev); break;
+               case DSPIOSTEREO:              
+                       status = set_stereo(*((u32_t *) val), sub_dev); break;
+               case DSPIOBITS:          
+                       status = set_bits(*((u32_t *) val), sub_dev); break;
+               case DSPIOSIZE:          
+                       status = set_frag_size(*((u32_t *) val), sub_dev); break;
+               case DSPIOSIGN:          
+                       status = set_sign(*((u32_t *) val), sub_dev); break;
+               case DSPIOMAX:           
+                       status = get_max_frag_size(val, len, sub_dev); break;
+               case DSPIORESET:         
+                       status = reset(sub_dev); break;
+               case DSPIOFREEBUF:
+                       status = free_buf(val, len, sub_dev); break;
+               case DSPIOSAMPLESINBUF: 
+                       status = get_samples_in_buf(val, len, sub_dev); break;
+               case DSPIOPAUSE:
+                       status = drv_pause(sub_dev); break;
+               case DSPIORESUME:
+                       status = drv_resume(sub_dev); break;
+               case MIXIOGETVOLUME:
+                       status = get_set_volume(val, len, sub_dev, 0); break;
+               case MIXIOSETVOLUME:
+                       status = get_set_volume(val, len, sub_dev, 1); break;
+               default:                 
+                       status = EINVAL; break;
+       }
+
+       return OK;
+}
+
+
+int drv_get_irq(char *irq) {
+       *irq = dev.irq;
+       return OK;
+}
+
+
+int drv_get_frag_size(u32_t *frag_size, int sub_dev) {
+       *frag_size = aud_conf[sub_dev].fragment_size;
+       return OK;  
+}
+
+
+int drv_set_dma(u32_t dma, u32_t length, int chan) {
+       /* dma length in bytes, 
+          max is 64k long words for es1370 = 256k bytes */
+       u32_t page, frame_count_reg, dma_add_reg;
+
+       switch(chan) {
+               case ADC1_CHAN: page = ADC_MEM_PAGE;
+                                               frame_count_reg = ADC_BUFFER_SIZE;
+                                               dma_add_reg = ADC_PCI_ADDRESS;
+                                               break;
+               case DAC1_CHAN: page = DAC_MEM_PAGE;
+                                               frame_count_reg = DAC1_BUFFER_SIZE;
+                                               dma_add_reg = DAC1_PCI_ADDRESS;
+                                               break;;
+               case DAC2_CHAN: page = DAC_MEM_PAGE;
+                                               frame_count_reg = DAC2_BUFFER_SIZE;
+                                               dma_add_reg = DAC2_PCI_ADDRESS;
+                                               break;;    
+               default: return EIO;
+       }
+       pci_outb(reg(MEM_PAGE), page);
+       pci_outl(reg(dma_add_reg), dma);
+
+       /* device expects long word count in stead of bytes */
+       length /= 4;
+
+       /* It seems that register _CURRENT_COUNT is overwritten, but this is
+        * the way to go. The register frame_count_reg is only longword
+        * addressable.
+        * It expects length -1
+        */
+       pci_outl(reg(frame_count_reg), (u32_t) (length - 1));
+
+       return OK;
+}
+
+
+/* return status of the interrupt summary bit */
+int drv_int_sum(void) {
+       return pci_inl(reg(INTERRUPT_STATUS)) & INTR;
+}
+
+
+int drv_int(int sub_dev) {
+       u32_t int_status;
+       u32_t bit;
+       u32_t debug;
+
+       /* return status of interrupt bit of specified channel*/
+       switch (sub_dev) {
+               case DAC1_CHAN:  bit = DAC1;break;
+               case DAC2_CHAN:  bit = DAC2;break;
+               case ADC1_CHAN:  bit = ADC;break;
+       }
+
+       int_status = pci_inl(reg(INTERRUPT_STATUS)) & bit;
+
+       return int_status;
+}
+
+
+int drv_reenable_int(int chan) {
+       u16_t ser_interface, int_en_bit;
+
+       switch(chan) {
+               case ADC1_CHAN: int_en_bit = R1_INT_EN; break;
+               case DAC1_CHAN: int_en_bit = P1_INTR_EN; break;
+               case DAC2_CHAN: int_en_bit = P2_INTR_EN; break;    
+               default: EINVAL;
+       }
+
+       /* clear and reenable an interrupt */
+       ser_interface = pci_inw(reg(SERIAL_INTERFACE_CTRL));
+       pci_outw(reg(SERIAL_INTERFACE_CTRL), ser_interface & ~int_en_bit);
+       pci_outw(reg(SERIAL_INTERFACE_CTRL), ser_interface | int_en_bit);
+
+       return OK;
+}
+
+
+int drv_pause(int sub_dev) { 
+       u32_t pause_bit;
+
+       disable_int(sub_dev); /* don't send interrupts */
+
+       switch(sub_dev) {
+               case DAC1_CHAN: pause_bit = P1_PAUSE;break;
+               case DAC2_CHAN: pause_bit = P2_PAUSE;break;    
+               default: return EINVAL;
+       }
+
+       /* pause */
+       pci_outl(reg(SERIAL_INTERFACE_CTRL),
+                       pci_inl(reg(SERIAL_INTERFACE_CTRL)) | pause_bit);
+
+       return OK;
+}
+
+
+int drv_resume(int sub_dev) {
+       u32_t pause_bit = 0;
+
+       drv_reenable_int(sub_dev); /* enable interrupts */
+
+       switch(sub_dev) {
+               case DAC1_CHAN: pause_bit = P1_PAUSE;break;
+               case DAC2_CHAN: pause_bit = P2_PAUSE;break;    
+               default: return EINVAL;
+       }
+
+       /* clear pause bit */
+       pci_outl(reg(SERIAL_INTERFACE_CTRL),
+                       pci_inl(reg(SERIAL_INTERFACE_CTRL)) & ~pause_bit);
+
+       return OK;
+}
+
+
+PRIVATE int set_bits(u32_t nr_of_bits, int sub_dev) {
+       /* set format bits for specified channel. */
+       u16_t size_16_bit, ser_interface;
+
+       switch(sub_dev) {
+               case ADC1_CHAN: size_16_bit = R1_S_EB; break;
+               case DAC1_CHAN: size_16_bit = P1_S_EB; break;
+               case DAC2_CHAN: size_16_bit = P2_S_EB; break;    
+               default: return EINVAL;
+       }
+
+       ser_interface = pci_inw(reg(SERIAL_INTERFACE_CTRL));
+       ser_interface &= ~size_16_bit;
+       switch(nr_of_bits) {
+               case 16: ser_interface |= size_16_bit;break;
+               case  8: break;
+               default: return EINVAL;
+       }
+       pci_outw(reg(SERIAL_INTERFACE_CTRL), ser_interface);
+       aud_conf[sub_dev].nr_of_bits = nr_of_bits;
+       return OK;
+}
+
+
+PRIVATE int set_stereo(u32_t stereo, int sub_dev) {
+       /* set format bits for specified channel. */
+       u16_t stereo_bit, ser_interface;
+
+       switch(sub_dev) {
+               case ADC1_CHAN: stereo_bit = R1_S_MB; break;
+               case DAC1_CHAN: stereo_bit = P1_S_MB; break;
+               case DAC2_CHAN: stereo_bit = P2_S_MB; break;    
+               default: return EINVAL;
+       }
+       ser_interface = pci_inw(reg(SERIAL_INTERFACE_CTRL));
+       ser_interface &= ~stereo_bit;
+       if (stereo) {
+               ser_interface |= stereo_bit;
+       } 
+       pci_outw(reg(SERIAL_INTERFACE_CTRL), ser_interface);
+       aud_conf[sub_dev].stereo = stereo;
+
+       return OK;
+}
+
+
+PRIVATE int set_sign(u32_t val, int sub_dev) {
+       return OK;
+}
+
+
+PRIVATE int set_frag_size(u32_t fragment_size, int sub_dev_nr) {
+       if (fragment_size > (sub_dev[sub_dev_nr].DmaSize / 
+                               sub_dev[sub_dev_nr].NrOfDmaFragments) || 
+                       fragment_size < sub_dev[sub_dev_nr].MinFragmentSize) {
+               return EINVAL;
+       }
+       aud_conf[sub_dev_nr].fragment_size = fragment_size;
+
+       return OK;
+}
+
+
+PRIVATE int set_sample_rate(u32_t rate, int sub_dev) {
+       /* currently only 44.1kHz */
+       u32_t controlRegister;
+
+       if (rate > MAX_RATE || rate < MIN_RATE) {
+               return EINVAL;
+       }
+
+       controlRegister = pci_inl(reg(CHIP_SEL_CTRL));
+       controlRegister |= FREQ_44K100;
+       pci_outl(reg(CHIP_SEL_CTRL), controlRegister);
+
+       aud_conf[sub_dev].sample_rate = rate;
+
+       return OK;
+}
+
+
+PRIVATE int set_int_cnt(int chan) {
+       /* Write interrupt count for specified channel. 
+          After <DspFragmentSize> bytes, an interrupt will be generated  */
+
+       int sample_count; 
+       u16_t int_cnt_reg;
+
+       if (aud_conf[chan].fragment_size > 
+                       (sub_dev[chan].DmaSize / sub_dev[chan].NrOfDmaFragments) 
+                       || aud_conf[chan].fragment_size < sub_dev[chan].MinFragmentSize) {
+               return EINVAL;
+       }
+
+       switch(chan) {
+               case ADC1_CHAN: int_cnt_reg = ADC_SAMP_CT; break;
+               case DAC1_CHAN: int_cnt_reg = DAC1_SAMP_CT; break;
+               case DAC2_CHAN: int_cnt_reg = DAC2_SAMP_CT; break;    
+               default: return EINVAL;
+       }
+
+       sample_count = aud_conf[chan].fragment_size;
+
+       /* adjust sample count according to sample format */
+       if( aud_conf[chan].stereo == TRUE ) sample_count >>= 1;
+       switch(aud_conf[chan].nr_of_bits) {
+               case 16:   sample_count >>= 1;break;
+               case  8:   break;
+               default: return EINVAL;
+       }    
+
+       /* set the sample count - 1 for the specified channel. */
+       pci_outw(reg(int_cnt_reg), sample_count - 1);
+
+       return OK;
+}
+
+
+PRIVATE int get_max_frag_size(u32_t * val, int * len, int sub_dev_nr) {
+       *len = sizeof(*val);
+       *val = (sub_dev[sub_dev_nr].DmaSize / 
+                       sub_dev[sub_dev_nr].NrOfDmaFragments);
+       return OK;
+}
+
+
+PRIVATE int disable_int(int chan) {
+       u16_t ser_interface, int_en_bit;
+
+       switch(chan) {
+               case ADC1_CHAN: int_en_bit = R1_INT_EN; break;
+               case DAC1_CHAN: int_en_bit = P1_INTR_EN; break;
+               case DAC2_CHAN: int_en_bit = P2_INTR_EN; break;    
+               default: EINVAL;
+       }
+       /* clear the interrupt */
+       ser_interface = pci_inw(reg(SERIAL_INTERFACE_CTRL));
+       pci_outw(reg(SERIAL_INTERFACE_CTRL), ser_interface & ~int_en_bit);
+}
+
+
+PRIVATE int get_samples_in_buf (u32_t *samples_in_buf, int *len, int chan) {
+       u16_t samp_ct_reg; 
+       u16_t curr_samp_ct_reg;
+       u16_t samp_ct;  /* nr of samples - 1 that will be played back */
+       u16_t curr_samp_ct; /* counts back from SAMP_CT till 0 */
+
+       *len = sizeof(*samples_in_buf);
+
+       switch(chan) {
+               case ADC1_CHAN: 
+                       curr_samp_ct_reg = ADC_CURR_SAMP_CT;
+                       samp_ct_reg = ADC_SAMP_CT; break;
+               case DAC1_CHAN: 
+                       curr_samp_ct_reg = DAC1_CURR_SAMP_CT;
+                       samp_ct_reg = DAC1_SAMP_CT; break;
+               case DAC2_CHAN: 
+                       curr_samp_ct_reg = DAC2_CURR_SAMP_CT;
+                       samp_ct_reg = DAC2_SAMP_CT; break;    
+               default: return EINVAL;
+       }
+
+       samp_ct = pci_inw(reg(samp_ct_reg));
+       curr_samp_ct = pci_inw(reg(curr_samp_ct_reg));
+
+       *samples_in_buf = (u32_t) (sub_dev[chan].BufLength * 8192) + 
+               curr_samp_ct;
+
+       return OK;
+}
+
+
+/* returns 1 if there are free buffers */
+PRIVATE int free_buf (u32_t *val, int *len, int sub_dev_nr) {
+       *len = sizeof(*val);
+       if (sub_dev[sub_dev_nr].BufLength ==
+                       sub_dev[sub_dev_nr].NrOfExtraBuffers) {
+               *val = 0;
+       }
+       else {
+               *val = 1;
+       }
+       return OK;
+}
+
+
+PRIVATE int get_set_volume(struct volume_level *level, int *len, int sub_dev, 
+               int flag) {
+       *len = sizeof(struct volume_level);
+       if (sub_dev == MIXER) {
+               return ak4531_get_set_volume(level, flag);
+       }
+       else {
+               return EINVAL;
+       }
+}
diff --git a/drivers/audio/es1370/es1370.h b/drivers/audio/es1370/es1370.h
new file mode 100644 (file)
index 0000000..faabee2
--- /dev/null
@@ -0,0 +1,125 @@
+#ifndef ES1370_H
+#define ES1370_H
+/* best viewed with tabsize=4 */
+
+#include <sys/types.h>
+#include "../../drivers.h"
+#include <sys/ioc_sound.h>
+
+
+/* set your vendor and device ID's here */
+#define VENDOR_ID                              0x1274
+#define DEVICE_ID                              0x5000
+#define DRIVER_NAME                            "ES1370"
+
+
+/* channels or subdevices */
+#define DAC1_CHAN                              0
+#define ADC1_CHAN                              1
+#define MIXER                                  2
+#define DAC2_CHAN                              3
+
+
+/* PCI command register defines */
+#define SERR_EN                                        0x0100
+#define PCI_MASTER                             0x0004
+#define IO_ACCESS                              0x0001
+
+
+/* Interrupt/Chip Select Control */
+#define CHIP_SEL_CTRL                  0x00            
+#define FREQ_44K100                            0x3000          /* 44.1 Khz */
+#define CDC_EN                                 0x0002          /* codec enable */
+#define ADC1_EN                                        0x0010
+#define DAC1_EN                                        0x0040
+#define DAC2_EN                                        0x0020
+#define XCTL0                                  0x0100
+#define CCB_INTRM                              0x0400  
+
+
+/* Interrupt/Chip Select Status */
+#define INTERRUPT_STATUS               0x04            
+#define ADC                                            0x0001
+#define DAC2                                   0x0002
+#define DAC1                                   0x0004
+#define CSTAT                                  0x0400          /* == CBUSY || CWRIP */
+#define CWRIP                                  0x0100          /* == CBUSY || CWRIP */
+#define INTR                                   0x80000000
+
+
+/* AK4531 address */
+#define CODEC_WRITE_ADDRESS            0x10
+
+
+/* Legacy address */
+#define LEGACY                                 0x18            
+
+
+/* Memory related defines */
+#define MEM_PAGE                               0x0c
+#define ADC_MEM_PAGE                   0x0d
+#define DAC_MEM_PAGE                   0x0c            /* for DAC1 and DAC2 */
+
+#define MEMORY                                 0x30
+#define ADC_BUFFER_SIZE                        0x34
+#define DAC1_BUFFER_SIZE               0x34
+#define DAC2_BUFFER_SIZE               0X3c
+#define ADC_PCI_ADDRESS                        0x30
+#define DAC1_PCI_ADDRESS               0x30
+#define DAC2_PCI_ADDRESS               0x38
+
+
+/* Serial Interface Control */
+#define SERIAL_INTERFACE_CTRL  0x20
+#define P1_S_MB                                        0x0001          /* DAC1 Stereo/Mono bit */
+#define P1_S_EB                                        0x0002          /* DAC1 Sixteen/Eight bit */
+#define P2_S_MB                                        0x0004          /* DAC2 Stereo/Mono bit */
+#define P2_S_EB                                        0x0008          /* DAC2 Sixteen/Eight bit */
+#define R1_S_MB                                        0x0010          /* ADC Stereo/Mono bit */
+#define R1_S_EB                                        0x0020          /* ADC Sixteen/Eight bit */
+#define P1_INTR_EN                             0x0100
+#define P2_INTR_EN                             0x0200
+#define R1_INT_EN                              0x0400
+#define P1_PAUSE                               0x0800
+#define P2_PAUSE                               0x1000
+
+
+#define DAC1_SAMP_CT                   0x24
+#define DAC1_CURR_SAMP_CT              0x26
+#define DAC2_SAMP_CT                   0x28
+#define DAC2_CURR_SAMP_CT              0x2a
+#define ADC_SAMP_CT                            0x2c
+#define ADC_CURR_SAMP_CT               0x2e
+
+
+typedef struct {
+       u32_t stereo;
+       u16_t sample_rate; 
+       u32_t nr_of_bits;
+       u32_t sign;
+       u32_t busy;
+       u32_t fragment_size;
+} aud_sub_dev_conf_t;
+
+/* Some defaults for the aud_sub_dev_conf_t*/
+#define DEFAULT_RATE               44100      /* Sample rate */
+#define DEFAULT_NR_OF_BITS             16             /* Nr. of bits per sample per chan */
+#define DEFAULT_SIGNED                 0          /* 0 = unsigned, 1 = signed */
+#define DEFAULT_STEREO                 1          /* 0 = mono, 1 = stereo */
+#define MAX_RATE                               44100      /* Max sample speed in KHz */
+#define MIN_RATE                               4000       /* Min sample speed in KHz */
+
+
+typedef struct DEVSTRUCT {
+       char*     name;
+       u16_t     v_id;                                                 /* vendor id */
+       u16_t     d_id;                                                 /* device id */
+       u32_t     devind;                                               /* minix pci device id, for 
+                                                                                        * pci configuration space */
+       u32_t     base;                                                 /* changed to 32 bits */
+       char      irq; 
+       char      revision;                                             /* version of the device */
+} DEV_STRUCT;
+
+
+#endif /* ES1370_H */
diff --git a/drivers/audio/es1370/pci_helper.c b/drivers/audio/es1370/pci_helper.c
new file mode 100644 (file)
index 0000000..4c3ff12
--- /dev/null
@@ -0,0 +1,65 @@
+/* best viewed with tabsize 4 */
+
+#include "../../drivers.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <minix/sysutil.h>
+#include <errno.h>
+
+
+#include "pci_helper.h"
+
+#include "es1370.h"
+
+/*===========================================================================*
+ *                     helper functions for I/O                                                                                 *
+ *===========================================================================*/
+PUBLIC unsigned pci_inb(U16_t port) {
+       u32_t value;
+       int s;
+       if ((s=sys_inb(port, &value)) !=OK)
+               printf("%s: warning, sys_inb failed: %d\n", DRIVER_NAME, s);
+       return value;
+}
+
+
+PUBLIC unsigned pci_inw(U16_t port) {
+       u32_t value;
+       int s;
+       if ((s=sys_inw(port, &value)) !=OK)
+               printf("%s: warning, sys_inw failed: %d\n", DRIVER_NAME, s);
+       return value;
+}
+
+
+PUBLIC unsigned pci_inl(U16_t port) {
+       U32_t value;
+       int s;
+       if ((s=sys_inl(port, &value)) !=OK)
+               printf("%s: warning, sys_inl failed: %d\n", DRIVER_NAME, s);
+       return value;
+}
+
+
+PUBLIC void pci_outb(U16_t port, U8_t value) {
+       int s;
+       if ((s=sys_outb(port, value)) !=OK)
+               printf("%s: warning, sys_outb failed: %d\n", DRIVER_NAME, s);
+}
+
+
+PUBLIC void pci_outw(U16_t port, U16_t value) {
+       int s;
+       if ((s=sys_outw(port, value)) !=OK)
+               printf("%s: warning, sys_outw failed: %d\n", DRIVER_NAME, s);
+}
+
+
+PUBLIC void pci_outl(U16_t port, U32_t value) {
+       int s;
+       if ((s=sys_outl(port, value)) !=OK)
+               printf("%s: warning, sys_outl failed: %d\n", DRIVER_NAME, s);
+}
+
diff --git a/drivers/audio/es1370/pci_helper.h b/drivers/audio/es1370/pci_helper.h
new file mode 100644 (file)
index 0000000..5c91c69
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef PCI_HELPER
+#define PCI_HELPER
+
+_PROTOTYPE( unsigned pci_inb, (U16_t port) );
+_PROTOTYPE( unsigned pci_inw, (U16_t port) );
+_PROTOTYPE( unsigned pci_inl, (U16_t port) );
+
+_PROTOTYPE( void pci_outb, (U16_t port, U8_t value) );
+_PROTOTYPE( void pci_outw, (U16_t port, U16_t value) );
+_PROTOTYPE( void pci_outl, (U16_t port, U32_t value) );
+
+#endif
diff --git a/drivers/audio/es1371/.depend b/drivers/audio/es1371/.depend
deleted file mode 100755 (executable)
index deb8a33..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-
-SRC.o: ../../drivers.h
-SRC.o: ../../libpci/pci.h
-SRC.o: /usr/include/ansi.h
-SRC.o: /usr/include/errno.h
-SRC.o: /usr/include/ibm/bios.h
-SRC.o: /usr/include/ibm/interrupt.h
-SRC.o: /usr/include/ibm/ports.h
-SRC.o: /usr/include/limits.h
-SRC.o: /usr/include/minix/bitmap.h
-SRC.o: /usr/include/minix/callnr.h
-SRC.o: /usr/include/minix/com.h
-SRC.o: /usr/include/minix/config.h
-SRC.o: /usr/include/minix/const.h
-SRC.o: /usr/include/minix/devio.h
-SRC.o: /usr/include/minix/dmap.h
-SRC.o: /usr/include/minix/ioctl.h
-SRC.o: /usr/include/minix/ipc.h
-SRC.o: /usr/include/minix/sys_config.h
-SRC.o: /usr/include/minix/syslib.h
-SRC.o: /usr/include/minix/sysutil.h
-SRC.o: /usr/include/minix/type.h
-SRC.o: /usr/include/signal.h
-SRC.o: /usr/include/stddef.h
-SRC.o: /usr/include/stdlib.h
-SRC.o: /usr/include/string.h
-SRC.o: /usr/include/sys/dir.h
-SRC.o: /usr/include/sys/ioc_sound.h
-SRC.o: /usr/include/sys/types.h
-SRC.o: /usr/include/unistd.h
-SRC.o: SRC.c
-SRC.o: SRC.h
-SRC.o: es1371.h
-SRC.o: wait.h
-
-codec.o:       ../../drivers.h
-codec.o:       ../../libpci/pci.h
-codec.o:       ../AC97.h
-codec.o:       /usr/include/ansi.h
-codec.o:       /usr/include/errno.h
-codec.o:       /usr/include/ibm/bios.h
-codec.o:       /usr/include/ibm/interrupt.h
-codec.o:       /usr/include/ibm/ports.h
-codec.o:       /usr/include/limits.h
-codec.o:       /usr/include/minix/bitmap.h
-codec.o:       /usr/include/minix/callnr.h
-codec.o:       /usr/include/minix/com.h
-codec.o:       /usr/include/minix/config.h
-codec.o:       /usr/include/minix/const.h
-codec.o:       /usr/include/minix/devio.h
-codec.o:       /usr/include/minix/dmap.h
-codec.o:       /usr/include/minix/ioctl.h
-codec.o:       /usr/include/minix/ipc.h
-codec.o:       /usr/include/minix/sys_config.h
-codec.o:       /usr/include/minix/syslib.h
-codec.o:       /usr/include/minix/sysutil.h
-codec.o:       /usr/include/minix/type.h
-codec.o:       /usr/include/signal.h
-codec.o:       /usr/include/stddef.h
-codec.o:       /usr/include/stdlib.h
-codec.o:       /usr/include/string.h
-codec.o:       /usr/include/sys/dir.h
-codec.o:       /usr/include/sys/ioc_sound.h
-codec.o:       /usr/include/sys/types.h
-codec.o:       /usr/include/unistd.h
-codec.o:       SRC.h
-codec.o:       codec.c
-codec.o:       codec.h
-codec.o:       es1371.h
-codec.o:       wait.h
-
-es1371.o:      ../../drivers.h
-es1371.o:      ../../libpci/pci.h
-es1371.o:      ../AC97.h
-es1371.o:      ../framework/../../drivers.h
-es1371.o:      ../framework/audio_fw.h
-es1371.o:      /usr/include/ansi.h
-es1371.o:      /usr/include/errno.h
-es1371.o:      /usr/include/ibm/bios.h
-es1371.o:      /usr/include/ibm/interrupt.h
-es1371.o:      /usr/include/ibm/ports.h
-es1371.o:      /usr/include/limits.h
-es1371.o:      /usr/include/minix/bitmap.h
-es1371.o:      /usr/include/minix/callnr.h
-es1371.o:      /usr/include/minix/com.h
-es1371.o:      /usr/include/minix/config.h
-es1371.o:      /usr/include/minix/const.h
-es1371.o:      /usr/include/minix/devio.h
-es1371.o:      /usr/include/minix/dmap.h
-es1371.o:      /usr/include/minix/ioctl.h
-es1371.o:      /usr/include/minix/ipc.h
-es1371.o:      /usr/include/minix/sys_config.h
-es1371.o:      /usr/include/minix/syslib.h
-es1371.o:      /usr/include/minix/sysutil.h
-es1371.o:      /usr/include/minix/type.h
-es1371.o:      /usr/include/signal.h
-es1371.o:      /usr/include/stddef.h
-es1371.o:      /usr/include/stdlib.h
-es1371.o:      /usr/include/string.h
-es1371.o:      /usr/include/sys/dir.h
-es1371.o:      /usr/include/sys/ioc_sound.h
-es1371.o:      /usr/include/sys/types.h
-es1371.o:      /usr/include/unistd.h
-es1371.o:      SRC.h
-es1371.o:      codec.h
-es1371.o:      es1371.c
-es1371.o:      es1371.h
-es1371.o:      wait.h
-
-wait.o:        ../../drivers.h
-wait.o:        ../../libpci/pci.h
-wait.o:        /usr/include/ansi.h
-wait.o:        /usr/include/errno.h
-wait.o:        /usr/include/ibm/bios.h
-wait.o:        /usr/include/ibm/interrupt.h
-wait.o:        /usr/include/ibm/ports.h
-wait.o:        /usr/include/limits.h
-wait.o:        /usr/include/minix/bitmap.h
-wait.o:        /usr/include/minix/callnr.h
-wait.o:        /usr/include/minix/com.h
-wait.o:        /usr/include/minix/config.h
-wait.o:        /usr/include/minix/const.h
-wait.o:        /usr/include/minix/devio.h
-wait.o:        /usr/include/minix/dmap.h
-wait.o:        /usr/include/minix/ipc.h
-wait.o:        /usr/include/minix/sys_config.h
-wait.o:        /usr/include/minix/syslib.h
-wait.o:        /usr/include/minix/sysutil.h
-wait.o:        /usr/include/minix/type.h
-wait.o:        /usr/include/signal.h
-wait.o:        /usr/include/stddef.h
-wait.o:        /usr/include/stdlib.h
-wait.o:        /usr/include/string.h
-wait.o:        /usr/include/sys/dir.h
-wait.o:        /usr/include/sys/types.h
-wait.o:        /usr/include/time.h
-wait.o:        /usr/include/unistd.h
-wait.o:        wait.c
index 3d32211b38a51ee6222735399da09d62d733d264..20fba19c14b23f0a0a1a082a9be466075e7a0fe9 100755 (executable)
@@ -6,39 +6,51 @@ i = $u/include
 s = $i/sys
 m = $i/minix
 b = $i/ibm
-pci_dir = ../../libpci
-gen_drv_dir = ../../gen_drivers/cyclic_dma
 
 # programs, flags, etc.
-CC =   exec cc
-CFLAGS = -I$i
+CC             = exec cc
+CFLAGS         = -I$i
 LDFLAGS = -i
-LIBS = -lsys -lsysutil 
-PCI = $(pci_dir)/pci.o $(pci_dir)/pci_table.o
+LIBS   = -lsys -lsysutil 
+
+PROGRAM_NAME   = es1371
+INSTALL_BIN            = /usr/sbin/$(PROGRAM_NAME)
+OBJ                            = es1371.o AC97.o audio_fw.o pci_helper.o wait.o sample_rate_converter.o
+
+
 
 # build local binary
-all:   es1371
+all: $(PROGRAM_NAME)
+
+
+$(PROGRAM_NAME): $(OBJ)
+       $(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
 
-es1371:        es1371.o SRC.o codec.o wait.o audio_fw.o $(PCI)
-       $(CC) -o $@ $(LDFLAGS) es1371.o SRC.o codec.o wait.o audio_fw.o $(PCI) $(LIBS)
 
 audio_fw.o: ../framework/audio_fw.c ../framework/audio_fw.h
        $(CC) -c ../framework/audio_fw.c
        
-install: /usr/sbin/es1371
-/usr/sbin/es1371:      es1371
+
+%.o: %.c
+       $(CC) $(CFLAGS) -c $<
+
+
+install: $(INSTALL_BIN)
+
+
+$(INSTALL_BIN):        $(PROGRAM_NAME)
        install -o root -S 1024k -c $? $@
 
-$(PCI): 
-       cd $(pci_dir) && $(MAKE)
 
 # clean up local files
 clean:
-       rm -f *.o *.bak core es1371
+       rm -f $(OBJ) $(PROGRAM_NAME) core 
+
 
 depend: 
        /usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
 
+
 # Include generated dependencies.
 include .depend
 
index f83d5031aa74d16f2d84372f074d8483b12c9f56..0ce25df60000ba1850e1b40a799efc462273c563 100755 (executable)
@@ -1,40 +1,58 @@
-/* This is the main file of the ES1371 sound driver 
- * There is no main function over here, instead the main function 
- * is located in the generic dma driver. All this driver does is 
- * implement the interface audio/audio_fw.h. All functions having the 
- * prefix 'drv_' are dictated by audio/audio_fw.h. The function 
- * prototypes you see below define a set of private helper functions. 
- * Control over the sample rate converter and the codec is delegated
- * to SRC.c and codec.c respectively.  
- *
+/* Best viewed with tabsize 4 */
+
+/* Original:
  * November 2005    ES1371 driver (Laurens Bronwasser)
  */
 
+/* Ensoniq ES1371 driver
+ *
+ * aka AudioPCI '97
+ *
+ * This is the main file of the ES1371 sound driver. There is no main function
+ * over here, instead the main function is located in the generic dma driver.
+ * All this driver does is implement the interface audio/audio_fw.h. All
+ * functions having the prefix 'drv_' are dictated by audio/audio_fw.h. The
+ * function prototypes you see below define a set of private helper functions.
+ * Control over the AC97 codec is delegated AC97.c.  
+ *
+ * October 2007    ES1371 driver (Pieter Hijma), 
+ * based on ES1370 driver which is based on the ES1371 driver 
+ * by Laurens Bronwasser
+ */
+
+#include <ibm/pci.h>
 
 #include "../framework/audio_fw.h"
 #include "es1371.h"
-#include "codec.h"
-#include "SRC.h"
-#include "../AC97.h"
+#include "AC97.h"
+#include "sample_rate_converter.h"
+#include "pci_helper.h"
 
 
+/* reg(n) will be the device specific addresses */
 #define reg(n) dev.base + n
 
+
+/* prototypes of private functions */
 FORWARD _PROTOTYPE( int detect_hw, (void) );  
 FORWARD _PROTOTYPE( int disable_int, (int sub_dev) );
 FORWARD _PROTOTYPE( int set_stereo, (u32_t stereo, int sub_dev) );
 FORWARD _PROTOTYPE( int set_bits, (u32_t nr_of_bits, int sub_dev) );
 FORWARD _PROTOTYPE( int set_sample_rate, (u32_t rate, int sub_dev) );
 FORWARD _PROTOTYPE( int set_sign, (u32_t val, int sub_dev) );
-FORWARD _PROTOTYPE( int get_max_frag_size, (u32_t * val, int *len, int sub_dev) );
+FORWARD _PROTOTYPE( int get_max_frag_size, 
+               (u32_t * val, int *len, int sub_dev) );
 FORWARD _PROTOTYPE( int set_frag_size, (u32_t fragment_size, int sub_dev) );
 FORWARD _PROTOTYPE( int set_int_cnt, (int sub_dev) );
-FORWARD _PROTOTYPE( int AC97Write, (u16_t wAddr, u16_t wData));
-FORWARD _PROTOTYPE( int AC97Read, (u16_t wAddr, u16_t *data));
-FORWARD _PROTOTYPE( void set_nice_volume, (void) );
+FORWARD _PROTOTYPE( int free_buf, (u32_t *val, int *len, int sub_dev) );
+FORWARD _PROTOTYPE( int get_samples_in_buf, 
+               (u32_t *val, int *len, int sub_dev) );
+FORWARD _PROTOTYPE( int get_set_volume, (struct volume_level *level, int *len, 
+                       int sub_dev, int flag) );
+FORWARD _PROTOTYPE( int reset, (int sub_dev) );
+
 
 DEV_STRUCT dev;
-u32_t base = 0;
 aud_sub_dev_conf_t aud_conf[4];
 
 
@@ -44,10 +62,10 @@ PUBLIC drv_t drv;
 
 
 PUBLIC int drv_init(void) {
-       drv.DriverName = "ES1371";
+       drv.DriverName = DRIVER_NAME;
        drv.NrOfSubDevices = 4;
        drv.NrOfSpecialFiles = 4;
-       
+
        sub_dev[DAC1_CHAN].readable = 0;
        sub_dev[DAC1_CHAN].writable = 1;
        sub_dev[DAC1_CHAN].DmaSize = 64 * 1024;
@@ -71,7 +89,7 @@ PUBLIC int drv_init(void) {
        sub_dev[DAC2_CHAN].NrOfDmaFragments = 2;
        sub_dev[DAC2_CHAN].MinFragmentSize = 1024;
        sub_dev[DAC2_CHAN].NrOfExtraBuffers = 4;
-       
+
        special_file[0].minor_dev_nr = 0;
        special_file[0].write_chan = DAC1_CHAN;
        special_file[0].read_chan = NO_CHANNEL;
@@ -93,496 +111,547 @@ PUBLIC int drv_init(void) {
        special_file[3].io_ctl = DAC2_CHAN;
 }
 
-int drv_init_hw (void)
-{
-    u16_t i, j;
-
-    /* First, detect the hardware */
-    if (detect_hw() != OK) {
-      return EIO;
-    }
-    /*
-      Put HW in a nice state ... all devices enabled except joystick,
-      NMI enables off, clear pending NMIs if any */
-
-    /* PCI command register */
-    pci_attr_w16 (dev.devind, PCI_CR, 0x0105);
-    /* set power management control/status register */
-    pci_attr_w16 (dev.devind, 0xE0, 0x0000);
-
-    pci_outb(reg(CONC_bDEVCTL_OFF),  0x00);
-    pci_outb(reg(CONC_bMISCCTL_OFF), 0x00);
-    pci_outb(reg(CONC_b4SPKR_OFF),   0x00);
-    pci_outb(reg(CONC_bNMIENA_OFF),  0x00);
-    pci_outb(reg(CONC_bNMICTL_OFF),  0x08);
-    pci_outw(reg(CONC_wNMISTAT_OFF), 0x0000);
-    pci_outb(reg(CONC_bSERCTL_OFF),  0x00);
-
-    /* clear all cache RAM */
-    for( i = 0; i < 0x10; ++i )
-    {
-        pci_outb(reg(CONC_bMEMPAGE_OFF), i);
-        for( j = 0; j < 0x10; j += 4 )
-            pci_outl  (reg(CONC_MEMBASE_OFF) + j, 0UL);
-    }
-    /* DO NOT SWITCH THE ORDER OF SRCInit and CODECInit function calls!!! */
-    /* The effect is only noticable after a cold reset (reboot) */
-    if (SRCInit(&dev) != OK) {
-      return EIO;
-    }
-    if (CODECInit(&dev) != OK) {
-      return EIO;
-    }
-    set_nice_volume(); /* of course we need a nice mixer to do this */
-    
-    /* initialize variables for each sub_device */
-    for (i = 0; i < drv.NrOfSubDevices; i++) {
-      if(i != MIXER) {
-          aud_conf[i].busy = 0;
-          aud_conf[i].stereo = DEFAULT_STEREO;
-          aud_conf[i].sample_rate = DEFAULT_RATE;
-          aud_conf[i].nr_of_bits = DEFAULT_NR_OF_BITS;
-          aud_conf[i].sign = DEFAULT_SIGNED;
-          aud_conf[i].fragment_size = sub_dev[i].DmaSize / sub_dev[i].NrOfDmaFragments;
-      }
-    }
-    return OK;
+
+PUBLIC int drv_init_hw (void) {
+       u16_t i, j;
+       u16_t chip_sel_ctrl_reg;
+
+       /* First, detect the hardware */
+       if (detect_hw() != OK) {
+               return EIO;
+       }
+
+       /* PCI command register 
+        * enable the SERR# driver, PCI bus mastering and I/O access
+        */
+       pci_attr_w16 (dev.devind, PCI_CR, SERR_EN|PCI_MASTER|IO_ACCESS);
+
+       /* turn everything off */
+       pci_outl(reg(CHIP_SEL_CTRL),  0x0UL);
+
+       /* turn off legacy (legacy control is undocumented) */
+       pci_outl(reg(LEGACY), 0x0UL);
+       pci_outl(reg(LEGACY+4), 0x0UL);
+
+       /* turn off serial interface */
+       pci_outl(reg(SERIAL_INTERFACE_CTRL), 0x0UL);
+       /*pci_outl(reg(SERIAL_INTERFACE_CTRL), 0x3UL);*/
+
+
+       /* clear all the memory */
+       for (i = 0; i < 0x10; ++i) {
+               pci_outb(reg(MEM_PAGE), i);
+               for (j = 0; j < 0x10; j += 4) {
+                       pci_outl  (reg(MEMORY) + j, 0x0UL);
+               }
+       }
+
+       /* Sample Rate Converter initialization */
+       if (src_init(&dev) != OK) {
+               return EIO;
+       }
+       if (AC97_init(&dev) != OK) {
+               return EIO;
+       }
+
+       /* initialize variables for each sub_device */
+       for (i = 0; i < drv.NrOfSubDevices; i++) {
+               if(i != MIXER) {
+                       aud_conf[i].busy = 0;
+                       aud_conf[i].stereo = DEFAULT_STEREO;
+                       aud_conf[i].sample_rate = DEFAULT_RATE;
+                       aud_conf[i].nr_of_bits = DEFAULT_NR_OF_BITS;
+                       aud_conf[i].sign = DEFAULT_SIGNED;
+                       aud_conf[i].fragment_size = 
+                               sub_dev[i].DmaSize / sub_dev[i].NrOfDmaFragments;
+               }
+       }
+       return OK;
 }
 
 
 PRIVATE int detect_hw(void) {
+       u32_t device;
+       int devind;
+       u16_t v_id, d_id;
+
+       /* detect_hw tries to find device and get IRQ and base address
+          with a little (much) help from the PCI library. 
+          This code is quite device independent and you can copy it. 
+          (just make sure to get the bugs out first)*/
+
+       pci_init();
+       /* get first device and then search through the list */
+       device = pci_first_dev(&devind, &v_id, &d_id);
+       while( device > 0 ) {
+               /* if we have a match...break */
+               if (v_id == VENDOR_ID && d_id == DEVICE_ID) break;
+               device = pci_next_dev(&devind, &v_id, &d_id);
+       }
+
+       /* did we find anything? */
+       if (v_id != VENDOR_ID || d_id != DEVICE_ID) {
+               return EIO;
+       }
+
+       pci_reserve(devind);
+
+       dev.name = pci_dev_name(v_id, d_id);
+
+       /* get base address of our device, ignore least signif. bit 
+          this last bit thing could be device dependent, i don't know */
+       dev.base = pci_attr_r32(devind, PCI_BAR) & 0xfffffffe;
+
+       /* get IRQ */
+       dev.irq = pci_attr_r8(devind, PCI_ILR);  
+       dev.revision = pci_attr_r8(devind, PCI_REV);
+       dev.d_id = d_id;
+       dev.v_id = v_id;
+       dev.devind = devind; /* pci device identifier */
 
-  u32_t r;
-  int devind;
-  u16_t v_id, d_id;
-
-  /* detect_hw tries to find device and get IRQ and base address
-     with a little (much) help from the PCI library. 
-     This code is quite device independent and you can copy it. 
-     (just make sure to get the bugs out first)*/
-  
-  pci_init();
-  /* get first device and then search through the list */
-  r = pci_first_dev(&devind, &v_id, &d_id);
-  while( r > 0 ) {
-    /* if we have a match...break */
-    if (v_id == VENDOR_ID && d_id == DEVICE_ID) break;
-    r = pci_next_dev(&devind, &v_id, &d_id);
-  }
-
-  /* did we find anything? */
-  if (v_id != VENDOR_ID || d_id != DEVICE_ID) {
-    return EIO;
-  }
-  /* right here we should reserve the device, but the pci library
-     doesn't support global reservation of devices yet. This would
-     be a problem if more ES1371's were installed on this system. */
-     
-  dev.name = pci_dev_name(v_id, d_id);
-  /* get base address of our device, ignore least signif. bit 
-     this last bit thing could be device dependent, i don't know */
-  dev.base = pci_attr_r32(devind, PCI_BAR) & 0xfffffffe;
-  /* get IRQ */
-  dev.irq = pci_attr_r8(devind, PCI_ILR);  
-  dev.revision = pci_attr_r8(devind, 0x08);
-  dev.d_id = d_id;
-  dev.v_id = v_id;
-  dev.devind = devind; /* pci device identifier */
-  return OK;
+       return OK;
 }
 
 
-int drv_reset(void) 
-{
-  /* make a WARM reset */
-  u16_t i;
-  
-  /* set SYNC_RES bit */
-  pci_outl(reg(CONC_bDEVCTL_OFF), 
-            pci_inl(reg(CONC_bDEVCTL_OFF)) | SYNC_RES_BIT);
-
-  /* got to delay at least 1 usec, try 18 usec */
-  for (i=0; i<100; i++) {
-      pci_inb(reg(0));
-  }
-  /* clear SYNC_RES bit */
-  pci_outl(reg(CONC_bDEVCTL_OFF), 
-            pci_inl(reg(CONC_bDEVCTL_OFF)) & ~SYNC_RES_BIT);
-  return OK;
+PRIVATE int reset(int chan) {
+       drv_stop(chan);
+       sub_dev[chan].OutOfData = 1;
+
+       return OK;
 }
 
 
-int drv_start(int sub_dev, int DmaMode)
-{
-  u32_t enable_bit, result = 0;
-  
-  /* Write default values to device in case user failed to configure.
-     If user did configure properly, everything is written twice.
-     please raise your hand if you object against to this strategy...*/
-  result |= set_sample_rate(aud_conf[sub_dev].sample_rate, sub_dev);
-  result |= set_stereo(aud_conf[sub_dev].stereo, sub_dev);
-  result |= set_bits(aud_conf[sub_dev].nr_of_bits, sub_dev);
-  result |= set_sign(aud_conf[sub_dev].sign, sub_dev);
-  
-  /* set the interrupt count */
-  result |= set_int_cnt(sub_dev);
-  
-  if (result) {
-    return EIO;
-  }
-  
-  /* if device currently paused, resume */
-  drv_resume(sub_dev);
-  
-  switch(sub_dev) {
-    case ADC1_CHAN: enable_bit = ADC1_EN_BIT;break;
-    case DAC1_CHAN: enable_bit = DAC1_EN_BIT;break;
-    case DAC2_CHAN: enable_bit = DAC2_EN_BIT;break;    
-    default: return EINVAL;
-  }
-  /* enable interrupts from 'sub device' */
-  drv_reenable_int(sub_dev);
-  
-  /* this means GO!!! */
-  pci_outl(reg(CONC_bDEVCTL_OFF),
-           pci_inl(reg(CONC_bDEVCTL_OFF)) | enable_bit);
-  
-  aud_conf[sub_dev].busy = 1;
-  return OK;
+int drv_reset() {
+       return OK;
+}
+
+
+int drv_start(int sub_dev, int DmaMode) {
+       u32_t enable_bit, result = 0;
+       u32_t debug;
+
+       /* Write default values to device in case user failed to configure.
+          If user did configure properly, everything is written twice.
+          please raise your hand if you object against to this strategy...*/
+       result |= set_sample_rate(aud_conf[sub_dev].sample_rate, sub_dev);
+       result |= set_stereo(aud_conf[sub_dev].stereo, sub_dev);
+       result |= set_bits(aud_conf[sub_dev].nr_of_bits, sub_dev);
+       result |= set_sign(aud_conf[sub_dev].sign, sub_dev);
+
+       /* set the interrupt count */
+       result |= set_int_cnt(sub_dev);
+
+       if (result) {
+               return EIO;
+       }
+
+       /* if device currently paused, resume */
+       drv_resume(sub_dev);
+
+       switch(sub_dev) {
+               case ADC1_CHAN: enable_bit = ADC1_EN;break;
+               case DAC1_CHAN: enable_bit = DAC1_EN;break;
+               case DAC2_CHAN: enable_bit = DAC2_EN;break;    
+               default: return EINVAL;
+       }
+
+       /* enable interrupts from 'sub device' */
+       drv_reenable_int(sub_dev);
+
+       /* this means play!!! */
+       pci_outw(reg(CHIP_SEL_CTRL), pci_inw(reg(CHIP_SEL_CTRL)) | enable_bit);
+
+       aud_conf[sub_dev].busy = 1;
+
+       return OK;
 }
 
 
 int drv_stop(int sub_dev)
 {
-  u32_t enable_bit;
-  
-  switch(sub_dev) {
-    case ADC1_CHAN: enable_bit = ADC1_EN_BIT;break;
-    case DAC1_CHAN: enable_bit = DAC1_EN_BIT;break;
-    case DAC2_CHAN: enable_bit = DAC2_EN_BIT;break;    
-    default: return EINVAL;
-  }
-  /* stop the codec */
-  pci_outl(reg(CONC_bDEVCTL_OFF),
-          pci_inl(reg(CONC_bDEVCTL_OFF)) & ~enable_bit);
-  
-  aud_conf[sub_dev].busy = 0;
-  disable_int(sub_dev);
-  return OK;
+       u32_t enable_bit;
+
+       switch(sub_dev) {
+               case ADC1_CHAN: enable_bit = ADC1_EN;break;
+               case DAC1_CHAN: enable_bit = DAC1_EN;break;
+               case DAC2_CHAN: enable_bit = DAC2_EN;break;    
+               default: return EINVAL;
+       }
+
+       /* stop the specified channel */
+       pci_outw(reg(CHIP_SEL_CTRL),
+                       pci_inw(reg(CHIP_SEL_CTRL)) & ~enable_bit);
+       aud_conf[sub_dev].busy = 0;
+       disable_int(sub_dev);
+
+       return OK;
 }
 
 
 /* all IO-ctl's sent to the upper driver are passed to this function */
 int drv_io_ctl(int request, void * val, int * len, int sub_dev) {
 
-  int status;
-  
-  switch(request) {
-    case DSPIORATE:                   status = set_sample_rate(*((u32_t *) val), sub_dev); break;
-    case DSPIOSTEREO:         status = set_stereo(*((u32_t *) val), sub_dev); break;
-    case DSPIOBITS:             status = set_bits(*((u32_t *) val), sub_dev); break;
-    case DSPIOSIZE:             status = set_frag_size(*((u32_t *) val), sub_dev); break;
-         case DSPIOSIGN:                status = set_sign(*((u32_t *) val), sub_dev); break;
-    case DSPIOMAX:           status = get_max_frag_size(val, len, sub_dev);break;
-               case DSPIORESET:         status = drv_reset(); break;
-               case AC97READ:           status = AC97Read (*((u16_t *)val),  ((u16_t *) val+2));break;
-               case AC97WRITE:          status = AC97Write(*((u16_t *)val), *((u16_t *) val+2));break;
-               default:                 status = EINVAL; break;
+       int status;
+
+       switch(request) {
+               case DSPIORATE: 
+                       status = set_sample_rate(*((u32_t *) val), sub_dev); break;
+               case DSPIOSTEREO:              
+                       status = set_stereo(*((u32_t *) val), sub_dev); break;
+               case DSPIOBITS:          
+                       status = set_bits(*((u32_t *) val), sub_dev); break;
+               case DSPIOSIZE:          
+                       status = set_frag_size(*((u32_t *) val), sub_dev); break;
+               case DSPIOSIGN:          
+                       status = set_sign(*((u32_t *) val), sub_dev); break;
+               case DSPIOMAX:           
+                       status = get_max_frag_size(val, len, sub_dev); break;
+               case DSPIORESET:         
+                       status = reset(sub_dev); break;
+               case DSPIOFREEBUF:
+                       status = free_buf(val, len, sub_dev); break;
+               case DSPIOSAMPLESINBUF: 
+                       status = get_samples_in_buf(val, len, sub_dev); break;
+               case DSPIOPAUSE:
+                       status = drv_pause(sub_dev); break;
+               case DSPIORESUME:
+                       status = drv_resume(sub_dev); break;
+               case MIXIOGETVOLUME:
+                       status = get_set_volume(val, len, sub_dev, 0); break;
+               case MIXIOSETVOLUME:
+                       status = get_set_volume(val, len, sub_dev, 1); break;
+               default:                 
+                       status = EINVAL; break;
        }
-  
-  return OK;
+
+       return OK;
 }
 
 
 int drv_get_irq(char *irq) {
-  *irq = dev.irq;
-  return OK;
+       *irq = dev.irq;
+       return OK;
 }
 
 
 int drv_get_frag_size(u32_t *frag_size, int sub_dev) {
-  *frag_size = aud_conf[sub_dev].fragment_size;
-  return OK;  
+       *frag_size = aud_conf[sub_dev].fragment_size;
+       return OK;  
 }
 
 
 int drv_set_dma(u32_t dma, u32_t length, int chan) {
-  /* dma length in bytes, 
-       max is 64k long words for es1371 = 256k bytes */
-  u32_t page, frame_count_reg, dma_add_reg;
-  
-  switch(chan) {
-    case ADC1_CHAN: page = CONC_ADCCTL_PAGE;
-                    frame_count_reg = CONC_wADCFC_OFF;
-                    dma_add_reg = CONC_dADCPADDR_OFF;
-                    break;
-    case DAC1_CHAN: page = CONC_SYNCTL_PAGE;
-                    frame_count_reg = CONC_wSYNFC_OFF;
-                    dma_add_reg = CONC_dSYNPADDR_OFF;
-                    break;;
-    case DAC2_CHAN: page = CONC_DACCTL_PAGE;
-                    frame_count_reg = CONC_wDACFC_OFF;
-                    dma_add_reg = CONC_dDACPADDR_OFF;
-                    break;;    
-    default: return EIO;
-  }
-  pci_outb(reg(CONC_bMEMPAGE_OFF), page);
-  pci_outl(reg(dma_add_reg), dma);
-  /* device expects long word count in stead of bytes */
-  length /= 4;
-  /* device expects length -1 */
-  pci_outl(reg(frame_count_reg), (u32_t) (length - 1));
+       /* dma length in bytes, 
+          max is 64k long words for es1371 = 256k bytes */
+       u32_t page, frame_count_reg, dma_add_reg;
+
+       switch(chan) {
+               case ADC1_CHAN: page = ADC_MEM_PAGE;
+                                               frame_count_reg = ADC_BUFFER_SIZE;
+                                               dma_add_reg = ADC_PCI_ADDRESS;
+                                               break;
+               case DAC1_CHAN: page = DAC_MEM_PAGE;
+                                               frame_count_reg = DAC1_BUFFER_SIZE;
+                                               dma_add_reg = DAC1_PCI_ADDRESS;
+                                               break;;
+               case DAC2_CHAN: page = DAC_MEM_PAGE;
+                                               frame_count_reg = DAC2_BUFFER_SIZE;
+                                               dma_add_reg = DAC2_PCI_ADDRESS;
+                                               break;;    
+               default: return EIO;
+       }
+       pci_outb(reg(MEM_PAGE), page);
+       pci_outl(reg(dma_add_reg), dma);
+
+       /* device expects long word count in stead of bytes */
+       length /= 4;
+
+       /* It seems that register _CURRENT_COUNT is overwritten, but this is
+        * the way to go. The register frame_count_reg is only longword
+        * addressable.
+        * It expects length -1
+        */
+       pci_outl(reg(frame_count_reg), (u32_t) (length - 1));
+
+       return OK;
 }
 
 
 /* return status of the interrupt summary bit */
 int drv_int_sum(void) {
-  u32_t int_status;
-  int_status = pci_inl(reg(CONC_bINTSTAT_OFF)) & 0x80000000UL;
-  return int_status;
+       return pci_inl(reg(INTERRUPT_STATUS)) & INTR;
 }
 
 
 int drv_int(int sub_dev) {
-  u32_t int_status;
-  char bit;
-  
-  /* return status of interrupt bit of specified channel*/
-  
-  switch (sub_dev) {
-    case DAC1_CHAN:  bit = DAC1_INT_STATUS_BIT;break;
-    case DAC2_CHAN:  bit = DAC2_INT_STATUS_BIT;break;
-    case ADC1_CHAN:  bit = ADC1_INT_STATUS_BIT;break;
-  }
-  int_status = pci_inl(reg(CONC_bINTSTAT_OFF)) & bit;
-  return int_status;
+       u32_t int_status;
+       u32_t bit;
+       u32_t debug;
+
+       /* return status of interrupt bit of specified channel*/
+       switch (sub_dev) {
+               case DAC1_CHAN:  bit = DAC1;break;
+               case DAC2_CHAN:  bit = DAC2;break;
+               case ADC1_CHAN:  bit = ADC;break;
+       }
+
+       int_status = pci_inl(reg(INTERRUPT_STATUS)) & bit;
+
+       return int_status;
 }
 
 
 int drv_reenable_int(int chan) {
-  u32_t i, int_en_bit;
-  
-    switch(chan) {
-    case ADC1_CHAN: int_en_bit = ADC1_INT_EN_BIT;break;
-    case DAC1_CHAN: int_en_bit = DAC1_INT_EN_BIT;break;
-    case DAC2_CHAN: int_en_bit = DAC2_INT_EN_BIT;break;    
-    default: EINVAL;
-  }
-  /* clear and reenable an interrupt */
-  i = pci_inl(reg(CONC_bSERFMT_OFF));
-  pci_outl(reg(CONC_bSERFMT_OFF), i & ~int_en_bit);
-  pci_outl(reg(CONC_bSERFMT_OFF), i | int_en_bit);
+       u16_t ser_interface, int_en_bit;
+
+       switch(chan) {
+               case ADC1_CHAN: int_en_bit = R1_INT_EN; break;
+               case DAC1_CHAN: int_en_bit = P1_INTR_EN; break;
+               case DAC2_CHAN: int_en_bit = P2_INTR_EN; break;    
+               default: EINVAL;
+       }
+
+       /* clear and reenable an interrupt */
+       ser_interface = pci_inw(reg(SERIAL_INTERFACE_CTRL));
+       pci_outw(reg(SERIAL_INTERFACE_CTRL), ser_interface & ~int_en_bit);
+       pci_outw(reg(SERIAL_INTERFACE_CTRL), ser_interface | int_en_bit);
+
+       return OK;
 }
 
 
-int drv_pause(int sub_dev)
-{ 
-  u32_t pause_bit;
-  
-  disable_int(sub_dev); /* don't send interrupts */
-  
-  switch(sub_dev) {
-    case DAC1_CHAN: pause_bit = DAC1_PAUSE_BIT;break;
-    case DAC2_CHAN: pause_bit = DAC2_PAUSE_BIT;break;    
-    default: return EINVAL;
-  }
-  /* pause */
-  pci_outl(reg(CONC_bSERFMT_OFF),
-            pci_inl(reg(CONC_bSERFMT_OFF)) | pause_bit);
-  return OK;
+int drv_pause(int sub_dev) { 
+       u32_t pause_bit;
+
+       disable_int(sub_dev); /* don't send interrupts */
+
+       switch(sub_dev) {
+               case DAC1_CHAN: pause_bit = P1_PAUSE;break;
+               case DAC2_CHAN: pause_bit = P2_PAUSE;break;    
+               default: return EINVAL;
+       }
+
+       /* pause */
+       pci_outl(reg(SERIAL_INTERFACE_CTRL),
+                       pci_inl(reg(SERIAL_INTERFACE_CTRL)) | pause_bit);
+
+       return OK;
 }
 
 
-int drv_resume(int sub_dev)
-{
-  u32_t pause_bit = 0;
-  
-  /* todo: drv_reenable_int(sub_dev); *//* enable interrupts */
-  
-  switch(sub_dev) {
-    case DAC1_CHAN: pause_bit = DAC1_PAUSE_BIT;break;
-    case DAC2_CHAN: pause_bit = DAC2_PAUSE_BIT;break;    
-    default: return EINVAL;
-  }
-  /* clear pause bit */
-  pci_outl(reg(CONC_bSERFMT_OFF),
-            pci_inl(reg(CONC_bSERFMT_OFF)) & ~pause_bit);
-  return OK;
+int drv_resume(int sub_dev) {
+       u32_t pause_bit = 0;
+
+       drv_reenable_int(sub_dev); /* enable interrupts */
+
+       switch(sub_dev) {
+               case DAC1_CHAN: pause_bit = P1_PAUSE;break;
+               case DAC2_CHAN: pause_bit = P2_PAUSE;break;    
+               default: return EINVAL;
+       }
+
+       /* clear pause bit */
+       pci_outl(reg(SERIAL_INTERFACE_CTRL),
+                       pci_inl(reg(SERIAL_INTERFACE_CTRL)) & ~pause_bit);
+
+       return OK;
 }
 
 
 PRIVATE int set_bits(u32_t nr_of_bits, int sub_dev) {
-  
-  /* set format bits for specified channel. */
-  u32_t size_16_bit, i;
-  
-  switch(sub_dev) {
-    case ADC1_CHAN: size_16_bit = ADC1_16_8_BIT;break;
-    case DAC1_CHAN: size_16_bit = DAC1_16_8_BIT;break;
-    case DAC2_CHAN: size_16_bit = DAC2_16_8_BIT;break;    
-    default: return EINVAL;
-  }
-  i = pci_inb(reg(CONC_bSERFMT_OFF));
-  i &= ~size_16_bit;
-  switch(nr_of_bits) {
-    case 16: i |= size_16_bit;break;
-    case  8: break;
-    default: return EINVAL;
-  }
-  pci_outb(reg(CONC_bSERFMT_OFF), i);
-  aud_conf[sub_dev].nr_of_bits = nr_of_bits;
-  return OK;
+       /* set format bits for specified channel. */
+       u16_t size_16_bit, ser_interface;
+
+       switch(sub_dev) {
+               case ADC1_CHAN: size_16_bit = R1_S_EB; break;
+               case DAC1_CHAN: size_16_bit = P1_S_EB; break;
+               case DAC2_CHAN: size_16_bit = P2_S_EB; break;    
+               default: return EINVAL;
+       }
+
+       ser_interface = pci_inw(reg(SERIAL_INTERFACE_CTRL));
+       ser_interface &= ~size_16_bit;
+       switch(nr_of_bits) {
+               case 16: ser_interface |= size_16_bit;break;
+               case  8: break;
+               default: return EINVAL;
+       }
+       pci_outw(reg(SERIAL_INTERFACE_CTRL), ser_interface);
+       aud_conf[sub_dev].nr_of_bits = nr_of_bits;
+       return OK;
 }
 
 
 PRIVATE int set_stereo(u32_t stereo, int sub_dev) {
-  
-  /* set format bits for specified channel. */
-  u32_t stereo_bit, i;
-  switch(sub_dev) {
-    case ADC1_CHAN: stereo_bit = ADC1_STEREO_BIT;break;
-    case DAC1_CHAN: stereo_bit = DAC1_STEREO_BIT;break;
-    case DAC2_CHAN: stereo_bit = DAC2_STEREO_BIT;break;    
-    default: return EINVAL;
-  }
-  i = pci_inb(reg(CONC_bSERFMT_OFF));
-  i &= ~stereo_bit;
-  if( stereo == TRUE ) {
-      i |= stereo_bit;
-  } 
-  pci_outb(reg(CONC_bSERFMT_OFF), i);
-  aud_conf[sub_dev].stereo = stereo;
-  return OK;
+       /* set format bits for specified channel. */
+       u16_t stereo_bit, ser_interface;
+
+       switch(sub_dev) {
+               case ADC1_CHAN: stereo_bit = R1_S_MB; break;
+               case DAC1_CHAN: stereo_bit = P1_S_MB; break;
+               case DAC2_CHAN: stereo_bit = P2_S_MB; break;    
+               default: return EINVAL;
+       }
+       ser_interface = pci_inw(reg(SERIAL_INTERFACE_CTRL));
+       ser_interface &= ~stereo_bit;
+       if (stereo) {
+               ser_interface |= stereo_bit;
+       } 
+       pci_outw(reg(SERIAL_INTERFACE_CTRL), ser_interface);
+       aud_conf[sub_dev].stereo = stereo;
+
+       return OK;
 }
 
 
 PRIVATE int set_sign(u32_t val, int sub_dev) {
-  return OK;
+       return OK;
 }
 
 
 PRIVATE int set_frag_size(u32_t fragment_size, int sub_dev_nr) {
-  if (fragment_size > (sub_dev[sub_dev_nr].DmaSize / sub_dev[sub_dev_nr].NrOfDmaFragments) || fragment_size < sub_dev[sub_dev_nr].MinFragmentSize) {
-    return EINVAL;
-  }
-  aud_conf[sub_dev_nr].fragment_size = fragment_size;
-  return OK;
+       if (fragment_size > (sub_dev[sub_dev_nr].DmaSize / 
+                               sub_dev[sub_dev_nr].NrOfDmaFragments) || 
+                       fragment_size < sub_dev[sub_dev_nr].MinFragmentSize) {
+               return EINVAL;
+       }
+       aud_conf[sub_dev_nr].fragment_size = fragment_size;
+
+       return OK;
 }
 
 
 PRIVATE int set_sample_rate(u32_t rate, int sub_dev) {
-  u32_t SRCBaseReg;
-
-  if (rate > MAX_RATE || rate < MIN_RATE) {
-    return EINVAL;
-  }
-  /* set the sample rate for the specified channel*/
-  switch(sub_dev) {
-    case ADC1_CHAN: SRCBaseReg = SRC_ADC_BASE;break;
-    case DAC1_CHAN: SRCBaseReg = SRC_SYNTH_BASE;break;
-    case DAC2_CHAN: SRCBaseReg = SRC_DAC_BASE;break;    
-    default: return EINVAL;
-  }
-  SRCSetRate(&dev, SRCBaseReg, rate);
-  aud_conf[sub_dev].sample_rate = rate;
-  return OK;
+       u32_t src_base_reg;
+
+       if (rate > MAX_RATE || rate < MIN_RATE) {
+               return EINVAL;
+       }
+       /* set the sample rate for the specified channel*/
+       switch(sub_dev) {
+               case ADC1_CHAN: src_base_reg = SRC_ADC_BASE;break;
+               case DAC1_CHAN: src_base_reg = SRC_SYNTH_BASE;break;
+               case DAC2_CHAN: src_base_reg = SRC_DAC_BASE;break;    
+               default: return EINVAL;
+       }
+       src_set_rate(&dev, src_base_reg, rate);
+       aud_conf[sub_dev].sample_rate = rate;
+       return OK;
 }
 
 
 PRIVATE int set_int_cnt(int chan) {
-  /* Write interrupt count for specified channel. 
-     After <DspFragmentSize> bytes, an interrupt will be generated  */
-    
-  int sample_count; u16_t int_cnt_reg;
-  
-  if (aud_conf[chan].fragment_size > (sub_dev[chan].DmaSize / sub_dev[chan].NrOfDmaFragments) 
-       || aud_conf[chan].fragment_size < sub_dev[chan].MinFragmentSize) {
-    return EINVAL;
-  }
-  
-  switch(chan) {
-    case ADC1_CHAN: int_cnt_reg = CONC_wADCIC_OFF;break;
-    case DAC1_CHAN: int_cnt_reg = CONC_wSYNIC_OFF;break;
-    case DAC2_CHAN: int_cnt_reg = CONC_wDACIC_OFF;break;    
-    default: return EINVAL;
-  }
-  
-  sample_count = aud_conf[chan].fragment_size;
-  
-  /* adjust sample count according to sample format */
-  if( aud_conf[chan].stereo == TRUE ) sample_count >>= 1;
-  switch(aud_conf[chan].nr_of_bits) {
-   case 16:   sample_count >>= 1;break;
-   case  8:   break;
-   default: return EINVAL;
-  }    
-  /* set the sample count - 1 for the specified channel. */
-  pci_outw(reg(int_cnt_reg), sample_count - 1);
-  return OK;
+       /* Write interrupt count for specified channel. 
+          After <DspFragmentSize> bytes, an interrupt will be generated  */
+
+       int sample_count; 
+       u16_t int_cnt_reg;
+
+       if (aud_conf[chan].fragment_size > 
+                       (sub_dev[chan].DmaSize / sub_dev[chan].NrOfDmaFragments) 
+                       || aud_conf[chan].fragment_size < sub_dev[chan].MinFragmentSize) {
+               return EINVAL;
+       }
+
+       switch(chan) {
+               case ADC1_CHAN: int_cnt_reg = ADC_SAMP_CT; break;
+               case DAC1_CHAN: int_cnt_reg = DAC1_SAMP_CT; break;
+               case DAC2_CHAN: int_cnt_reg = DAC2_SAMP_CT; break;    
+               default: return EINVAL;
+       }
+
+       sample_count = aud_conf[chan].fragment_size;
+
+       /* adjust sample count according to sample format */
+       if( aud_conf[chan].stereo == TRUE ) sample_count >>= 1;
+       switch(aud_conf[chan].nr_of_bits) {
+               case 16:   sample_count >>= 1;break;
+               case  8:   break;
+               default: return EINVAL;
+       }    
+
+       /* set the sample count - 1 for the specified channel. */
+       pci_outw(reg(int_cnt_reg), sample_count - 1);
+
+       return OK;
 }
 
 
 PRIVATE int get_max_frag_size(u32_t * val, int * len, int sub_dev_nr) {
-  *len = sizeof(*val);
-  *val = (sub_dev[sub_dev_nr].DmaSize / sub_dev[sub_dev_nr].NrOfDmaFragments);
-  return OK;
+       *len = sizeof(*val);
+       *val = (sub_dev[sub_dev_nr].DmaSize / 
+                       sub_dev[sub_dev_nr].NrOfDmaFragments);
+       return OK;
 }
 
 
 PRIVATE int disable_int(int chan) {
-  u32_t i, int_en_bit;
-  
-    switch(chan) {
-    case ADC1_CHAN: int_en_bit = ADC1_INT_EN_BIT;break;
-    case DAC1_CHAN: int_en_bit = DAC1_INT_EN_BIT;break;
-    case DAC2_CHAN: int_en_bit = DAC2_INT_EN_BIT;break;    
-    default: EINVAL;
-  }
-  /* clear the interrupt */
-  i = pci_inl(reg(CONC_bSERFMT_OFF));
-  pci_outl(reg(CONC_bSERFMT_OFF), i & ~int_en_bit);
+       u16_t ser_interface, int_en_bit;
+
+       switch(chan) {
+               case ADC1_CHAN: int_en_bit = R1_INT_EN; break;
+               case DAC1_CHAN: int_en_bit = P1_INTR_EN; break;
+               case DAC2_CHAN: int_en_bit = P2_INTR_EN; break;    
+               default: EINVAL;
+       }
+       /* clear the interrupt */
+       ser_interface = pci_inw(reg(SERIAL_INTERFACE_CTRL));
+       pci_outw(reg(SERIAL_INTERFACE_CTRL), ser_interface & ~int_en_bit);
 }
 
 
-PRIVATE void set_nice_volume(void) {
-  /* goofy code to set the DAC1 channel to an audibe volume 
-     to be able to test it without using the mixer */
-  
-  AC97Write(AC97_PCM_OUT_VOLUME, 0x0808);/* the higher, the softer */
-  AC97Write(AC97_MASTER_VOLUME, 0x0101);
-  AC97Write(0x38, 0);                    /* not crucial */
-  
-  AC97Write(AC97_LINE_IN_VOLUME, 0x0303);
-  AC97Write(AC97_MIC_VOLUME, 0x0303);
-  
-  /* mute record gain */
-  AC97Write(AC97_RECORD_GAIN_VOLUME, 0xFFFF);
-  
-    /* Also, to be able test recording without mixer:
-     select ONE channel as input below. */
-     
-  /* select LINE IN */
-  /*CodecWrite(AC97_RECORD_SELECT, 0x0404);*/
-  
-  /* select MIC */
-  AC97Write(AC97_RECORD_SELECT, 0x0000);
-  
-  /* unmute record gain */
-  AC97Write(AC97_RECORD_GAIN_VOLUME, 0x0000);
+PRIVATE int get_samples_in_buf (u32_t *samples_in_buf, int *len, int chan) {
+       u16_t samp_ct_reg; 
+       u16_t curr_samp_ct_reg;
+       u16_t samp_ct;  /* nr of samples - 1 that will be played back */
+       u16_t curr_samp_ct; /* counts back from SAMP_CT till 0 */
+
+       *len = sizeof(*samples_in_buf);
+
+       switch(chan) {
+               case ADC1_CHAN: 
+                       curr_samp_ct_reg = ADC_CURR_SAMP_CT;
+                       samp_ct_reg = ADC_SAMP_CT; break;
+               case DAC1_CHAN: 
+                       curr_samp_ct_reg = DAC1_CURR_SAMP_CT;
+                       samp_ct_reg = DAC1_SAMP_CT; break;
+               case DAC2_CHAN: 
+                       curr_samp_ct_reg = DAC2_CURR_SAMP_CT;
+                       samp_ct_reg = DAC2_SAMP_CT; break;    
+               default: return EINVAL;
+       }
+
+       samp_ct = pci_inw(reg(samp_ct_reg));
+       curr_samp_ct = pci_inw(reg(curr_samp_ct_reg));
+
+       *samples_in_buf = (u32_t) (sub_dev[chan].BufLength * 8192) + 
+               curr_samp_ct;
+
+       return OK;
 }
 
 
-/* The following two functions can be used by the mixer to 
-     control and read volume settings. */
-PRIVATE int  AC97Write (u16_t addr, u16_t data)
-{ 
-  /* todo: only allow volume control, 
-     no serial data or dev ctl please*/
-       return CodecWriteUnsynced(&dev, addr, data);
-}  
+/* returns 1 if there are free buffers */
+PRIVATE int free_buf (u32_t *val, int *len, int sub_dev_nr) {
+       *len = sizeof(*val);
+       if (sub_dev[sub_dev_nr].BufLength ==
+                       sub_dev[sub_dev_nr].NrOfExtraBuffers) {
+               *val = 0;
+       }
+       else {
+               *val = 1;
+       }
+       return OK;
+}
 
 
-PRIVATE int  AC97Read (u16_t addr, u16_t *data)
-{
-  return CodecReadUnsynced(&dev, addr, data);
+PRIVATE int get_set_volume(struct volume_level *level, int *len, int sub_dev, 
+               int flag) {
+       *len = sizeof(struct volume_level);
+       if (sub_dev == MIXER) {
+               return AC97_get_set_volume(level, flag);
+       }
+       else {
+               return EINVAL;
+       }
 }
index 309b1c0b4e8df099dd9e9db62fed10868480d698..c3df787939656c6ea3af34ea5a122566f284b4c9 100755 (executable)
 #ifndef ES1371_H
 #define ES1371_H
-
+/* best viewed with tabsize=4 */
+       
 #include <sys/types.h>
 #include "../../drivers.h"
-#include "../../libpci/pci.h"
 #include <sys/ioc_sound.h>
+#include <minix/sound.h>
 
-#define DAC1_CHAN 0
-#define ADC1_CHAN 1
-#define MIXER 2
-#define DAC2_CHAN 3
 
 /* set your vendor and device ID's here */
-#define VENDOR_ID 0x1274
-#define DEVICE_ID 0x1371
-
-/* Concert97 direct register offset defines */
-#define CONC_bDEVCTL_OFF        0x00    /* Device control/enable */
-#define CONC_bMISCCTL_OFF       0x01    /* Miscellaneous control */
-#define CONC_bGPIO_OFF          0x02    /* General purpose I/O control */
-#define CONC_bJOYCTL_OFF        0x03    /* Joystick control (decode) */
-#define CONC_bINTSTAT_OFF       0x04    /* Device interrupt status */
-#define CONC_bCODECSTAT_OFF     0x05    /* CODEC interface status */
-#define CONC_bINTSUMM_OFF       0x07    /* Interrupt summary status */
-#define CONC_b4SPKR_OFF         0x07    /* Also 4 speaker config reg */
-#define CONC_bSPDIF_ROUTE_OFF   0x07    /* Also S/PDIF route control reg */
-#define CONC_bUARTDATA_OFF      0x08    /* UART data R/W - read clears RX int */
-#define CONC_bUARTCSTAT_OFF     0x09    /* UART control and status */
-#define CONC_bUARTTEST_OFF      0x0a    /* UART test control reg */
-#define CONC_bMEMPAGE_OFF       0x0c    /* Memory page select */
-#define CONC_dSRCIO_OFF         0x10    /* I/O ctl/stat/data for SRC RAM */
-#define CONC_dCODECCTL_OFF      0x14    /* CODEC control - u32_t read/write */
-#define CONC_wNMISTAT_OFF       0x18    /* Legacy NMI status */
-#define CONC_bNMIENA_OFF        0x1a    /* Legacy NMI enable */
-#define CONC_bNMICTL_OFF        0x1b    /* Legacy control */
-#define CONC_bSERFMT_OFF        0x20    /* Serial device format */
-#define CONC_bSERCTL_OFF        0x21    /* Serial device control */
-#define CONC_bSKIPC_OFF         0x22    /* DAC skip count reg */
-#define CONC_wSYNIC_OFF         0x24    /* Synth int count in sample frames */
-#define CONC_wSYNCIC_OFF        0x26    /* Synth current int count */
-#define CONC_wDACIC_OFF         0x28    /* DAC int count in sample frames */
-#define CONC_wDACCIC_OFF        0x2a    /* DAC current int count */
-#define CONC_wADCIC_OFF         0x2c    /* ADC int count in sample frames */
-#define CONC_wADCCIC_OFF        0x2e    /* ADC current int count */
-#define CONC_MEMBASE_OFF        0x30    /* Memory window base - 16 byte window */
-
-/* Concert memory page-banked register offset defines */
-#define CONC_dSYNPADDR_OFF  0x30    /* Synth host frame PCI phys addr */
-#define CONC_wSYNFC_OFF     0x34    /* Synth host frame count in u32_t'S */
-#define CONC_wSYNCFC_OFF    0x36    /* Synth host current frame count */
-#define CONC_dDACPADDR_OFF  0x38    /* DAC host frame PCI phys addr */
-#define CONC_wDACFC_OFF     0x3c    /* DAC host frame count in u32_t'S */
-#define CONC_wDACCFC_OFF    0x3e    /* DAC host current frame count */
-#define CONC_dADCPADDR_OFF  0x30    /* ADC host frame PCI phys addr */
-#define CONC_wADCFC_OFF     0x34    /* ADC host frame count in u32_t'S */
-#define CONC_wADCCFC_OFF    0x36    /* ADC host current frame count */
-
-/*  memory page number defines */
-#define CONC_SYNRAM_PAGE    0x00    /* Synth host/serial I/F RAM */
-#define CONC_DACRAM_PAGE    0x04    /* DAC host/serial I/F RAM */
-#define CONC_ADCRAM_PAGE    0x08    /* ADC host/serial I/F RAM */
-#define CONC_SYNCTL_PAGE    0x0c    /* Page bank for synth host control */
-#define CONC_DACCTL_PAGE    0x0c    /* Page bank for DAC host control */
-#define CONC_ADCCTL_PAGE    0x0d    /* Page bank for ADC host control */
-#define CONC_FIFO0_PAGE     0x0e    /* page 0 of UART "FIFO" (rx stash) */
-#define CONC_FIFO1_PAGE     0x0f    /* page 1 of UART "FIFO" (rx stash) */
-
-
-
-/* bits for Interrupt/Chip Select Control Register (offset 0x00)*/
-#define DAC1_EN_BIT           bit(6)
-#define DAC2_EN_BIT           bit(5)
-#define ADC1_EN_BIT           bit(4)
-#define SYNC_RES_BIT          bit(14)
-
-/* bits for Interrupt/Chip Select Status Register (offset 0x04)*/
-#define DAC1_INT_STATUS_BIT   bit(2)
-#define DAC2_INT_STATUS_BIT   bit(1)
-#define ADC1_INT_STATUS_BIT   bit(0)
-
-/* some bits for Serial Interface Control Register (CONC_bSERFMT_OFF 20H) */
-#define DAC1_STEREO_BIT         bit(0)   /* stereo or mono format */
-#define DAC1_16_8_BIT           bit(1)   /* 16 or 8 bit format */
-#define DAC2_STEREO_BIT         bit(2)
-#define DAC2_16_8_BIT           bit(3)
-#define ADC1_STEREO_BIT         bit(4)
-#define ADC1_16_8_BIT           bit(5)
-#define DAC1_INT_EN_BIT         bit(8)   /* interupt enable bits */
-#define DAC2_INT_EN_BIT         bit(9)
-#define ADC1_INT_EN_BIT         bit(10)
-#define DAC1_PAUSE_BIT          bit(11)
-#define DAC2_PAUSE_BIT          bit(12)
-
-/* Some return values */
-#define SRC_SUCCESS                 0
-#define CONC_SUCCESS                0
-                                                /* Timeout waiting for: */
-#define SRC_ERR_NOT_BUSY_TIMEOUT            -1       /* SRC not busy */
-#define CONC_ERR_NO_PCI_BIOS                -2       
-#define CONC_ERR_DEVICE_NOT_FOUND           -3       
-#define CONC_ERR_SPDIF_NOT_AVAIL            -4       
-#define CONC_ERR_SPDIF_ROUTING_NOT_AVAIL    -5       
-#define CONC_ERR_4SPEAKER_NOT_AVAIL         -6       
-#define CONC_ERR_ECHO_NOT_AVAIL             -7       
+#define VENDOR_ID                              0x1274
+#define DEVICE_ID                              0x1371
+#define DRIVER_NAME                            "ES1371"
+
+
+/* channels or subdevices */
+#define DAC1_CHAN                              0
+#define ADC1_CHAN                              1
+#define MIXER                                  2
+#define DAC2_CHAN                              3
+
+
+/* PCI command register defines */
+#define SERR_EN                                        0x0100
+#define PCI_MASTER                             0x0004
+#define IO_ACCESS                              0x0001
+
+
+/* Interrupt/Chip Select Control */
+#define CHIP_SEL_CTRL                  0x00            
+#define ADC1_EN                                        0x0010
+#define DAC1_EN                                        0x0040
+#define DAC2_EN                                        0x0020
+#define CCB_INTRM                              0x0400  
+
+
+/* Interrupt/Chip Select Status */
+#define INTERRUPT_STATUS               0x04            
+#define ADC                                            0x0001
+#define DAC2                                   0x0002
+#define DAC1                                   0x0004
+#define INTR                                   0x80000000
+
+
+/* Sample Rate Converter */
+#define SAMPLE_RATE_CONV               0x10
+
+
+/* CODEC Write/Read register */
+#define CODEC_WRITE                            0x14
+#define CODEC_READ                             0x14
+
+
+/* Legacy address */
+#define LEGACY                                 0x18            
+
+
+/* Memory related defines */
+#define MEM_PAGE                               0x0c
+#define ADC_MEM_PAGE                   0x0d
+#define DAC_MEM_PAGE                   0x0c            /* for DAC1 and DAC2 */
+
+#define MEMORY                                 0x30
+#define ADC_BUFFER_SIZE                        0x34
+#define DAC1_BUFFER_SIZE               0x34
+#define DAC2_BUFFER_SIZE               0X3c
+#define ADC_PCI_ADDRESS                        0x30
+#define DAC1_PCI_ADDRESS               0x30
+#define DAC2_PCI_ADDRESS               0x38
+
+
+/* Serial Interface Control */
+#define SERIAL_INTERFACE_CTRL  0x20
+#define P1_S_MB                                        0x0001          /* DAC1 Stereo/Mono bit */
+#define P1_S_EB                                        0x0002          /* DAC1 Sixteen/Eight bit */
+#define P2_S_MB                                        0x0004          /* DAC2 Stereo/Mono bit */
+#define P2_S_EB                                        0x0008          /* DAC2 Sixteen/Eight bit */
+#define R1_S_MB                                        0x0010          /* ADC Stereo/Mono bit */
+#define R1_S_EB                                        0x0020          /* ADC Sixteen/Eight bit */
+#define P1_INTR_EN                             0x0100
+#define P2_INTR_EN                             0x0200
+#define R1_INT_EN                              0x0400
+#define P1_PAUSE                               0x0800
+#define P2_PAUSE                               0x1000
+
+
+#define DAC1_SAMP_CT                   0x24
+#define DAC1_CURR_SAMP_CT              0x26
+#define DAC2_SAMP_CT                   0x28
+#define DAC2_CURR_SAMP_CT              0x2a
+#define ADC_SAMP_CT                            0x2c
+#define ADC_CURR_SAMP_CT               0x2e
+
 
 typedef struct {
-  u32_t stereo;
-  u16_t sample_rate; 
-  u32_t nr_of_bits;
-  u32_t sign;
-  u32_t busy;
-  u32_t fragment_size;
+       u32_t stereo;
+       u16_t sample_rate; 
+       u32_t nr_of_bits;
+       u32_t sign;
+       u32_t busy;
+       u32_t fragment_size;
 } aud_sub_dev_conf_t;
 
 /* Some defaults for the aud_sub_dev_conf_t*/
 #define DEFAULT_RATE               44100      /* Sample rate */
-#define DEFAULT_NR_OF_BITS     16             /* Nr. of bits per sample per channel*/
-#define DEFAULT_SIGNED           0          /* 0 = unsigned, 1 = signed */
-#define DEFAULT_STEREO           1                /* 0 = mono, 1 = stereo */
-#define MAX_RATE                             44100      /* Max sample speed in KHz */
-#define MIN_RATE                             4000       /* Min sample speed in KHz */
+#define DEFAULT_NR_OF_BITS             16             /* Nr. of bits per sample per chan */
+#define DEFAULT_SIGNED                 0          /* 0 = unsigned, 1 = signed */
+#define DEFAULT_STEREO                 1          /* 0 = mono, 1 = stereo */
+#define MAX_RATE                               44100      /* Max sample speed in KHz */
+#define MIN_RATE                               4000       /* Min sample speed in KHz */
 
 
 typedef struct DEVSTRUCT {
-    char*     name;
-    u16_t     v_id;    /* vendor id */
-    u16_t     d_id;    /* device id */
-    u32_t     devind;  /* minix pci device id, for pci configuration space */
-    u32_t     base;    /* changed to 32 bits */
-    char      irq; 
-    char      revision;/* version of the device */
+       char*     name;
+       u16_t     v_id;                                                 /* vendor id */
+       u16_t     d_id;                                                 /* device id */
+       u32_t     devind;                                               /* minix pci device id, for 
+                                                                                        * pci configuration space */
+       u32_t     base;                                                 /* changed to 32 bits */
+       char      irq; 
+       char      revision;                                             /* version of the device */
 } DEV_STRUCT;
 
-#define bit(n) 1UL << n
-
+#define SRC_ERR_NOT_BUSY_TIMEOUT            -1       /* SRC not busy */
+#define SRC_SUCCESS                                                    0
 
 #endif /* ES1371_H */
index 00db6bfae54bc8452d61bf20f4455bb8d418b23c..afe6bda3a2cfa7f427a4e55d7f6f78cf4594c702 100755 (executable)
@@ -1,7 +1,8 @@
 #include "../../drivers.h"
 #include <sys/types.h>
 #include <time.h>
-#include "../../libpci/pci.h"
+#include "pci_helper.h"
+
 
 int WaitBitd (int paddr, int bitno, int state, long tmout)
 {
index 5df6a39a1f52d9ddfaef145926a9b281933dec53..1d8cf8bc66d8e39e07839b0f78cf01a640af6807 100755 (executable)
@@ -1,3 +1,5 @@
+#ifndef WAIT_H
+#define WAIT_H
 /* WAIT.H
 // General purpose waiting routines
 
@@ -8,3 +10,4 @@ int WaitBitw (int paddr, int bitno, int state, long tmout);
 int WaitBitd (int paddr, int bitno, int state, long tmout);
 int MemWaitw (unsigned int volatile *gaddr, int bitno, int state, long tmout);
 
+#endif
index bd380990a29741b5d5d638dcf123500ea930d668..dbdcd3d922ebe0869728f0ef5c3d5f8a2f3549d7 100755 (executable)
@@ -1,4 +1,6 @@
-/* This file contains a standard driver for audio devices.
+/* Best viewed with tabsize 4
+ *
+ * This file contains a standard driver for audio devices.
  * It supports double dma buffering and can be configured to use
  * extra buffer space beside the dma buffer.
  * This driver also support sub devices, which can be independently 
@@ -6,37 +8,43 @@
  *
  * The driver supports the following operations:
  *
- *    m_type      DEVICE    PROC_NR     COUNT    POSITION  ADRRESS
+ *    m_type      DEVICE    IO_ENDPT     COUNT    POSITION  ADRRESS
  * -----------------------------------------------------------------
- * |  DEV_OPEN   | device  | proc nr |         |         |         |
+ * | DEV_OPEN    | device  | proc nr |         |         |         |
  * |-------------+---------+---------+---------+---------+---------|
- * |  DEV_CLOSE  | device  | proc nr |         |         |         |
+ * | DEV_CLOSE   | device  | proc nr |         |         |         |
  * |-------------+---------+---------+---------+---------+---------|
- * |  DEV_READ   | device  | proc nr |  bytes  |         | buf ptr |
+ * | DEV_READ_S  | device  | proc nr |  bytes  |         | buf ptr |
  * |-------------+---------+---------+---------+---------+---------|
- * |  DEV_WRITE  | device  | proc nr |  bytes  |         | buf ptr |
+ * | DEV_WRITE_S | device  | proc nr |  bytes  |         | buf ptr |
  * |-------------+---------+---------+---------+---------+---------|
- * |  DEV_IOCTL  | device  | proc nr |func code|         | buf ptr |
+ * | DEV_IOCTL_S | device  | proc nr |func code|         | buf ptr |
  * |-------------+---------+---------+---------+---------+---------|
- * |  DEV_STATUS |         |         |         |         |         |
+ * | DEV_STATUS  |         |         |         |         |         |
  * |-------------+---------+---------+---------+---------+---------|
- * |  HARD_INT   |         |         |         |         |         | 
+ * | HARD_INT    |         |         |         |         |         | 
  * |-------------+---------+---------+---------+---------+---------|
- * |  SIG_STOP   |         |         |         |         |         | 
+ * | SIG_STOP    |         |         |         |         |         | 
  * ----------------------------------------------------------------- 
  * 
  * The file contains one entry point:
  *
  *   main:     main entry when driver is brought up
  *     
- *  February 2006   Updated audio framework, changed driver-framework relation (Peter Boonstoppel)
+ *     October 2007    Updated audio framework to work with mplayer, added
+ *                                     savecopies (Pieter Hijma)
+ *  February 2006   Updated audio framework, 
+ *             changed driver-framework relation (Peter Boonstoppel)
  *  November 2005   Created generic DMA driver framework (Laurens Bronwasser)
- *  August 24 2005  Ported audio driver to user space (only audio playback) (Peter Boonstoppel)
+ *  August 24 2005  Ported audio driver to user space 
+ *             (only audio playback) (Peter Boonstoppel)
  *  May 20 1995            SB16 Driver: Michel R. Prevenier 
  */
+
+
 #include "audio_fw.h"
 
+
 FORWARD _PROTOTYPE( int msg_open, (int minor_dev_nr) );
 FORWARD _PROTOTYPE( int msg_close, (int minor_dev_nr) );
 FORWARD _PROTOTYPE( int msg_ioctl, (message *m_ptr) );
@@ -73,242 +81,238 @@ PUBLIC void main(void)
        drv_init();
 
        /* Here is the main loop of the dma driver.  It waits for a message, 
-     carries it out, and sends a reply. */
+          carries it out, and sends a reply. */
        printf("%s up and running\n", drv.DriverName);
-       
+
        while(1) {
                receive(ANY, &mess);
                caller = mess.m_source;
-               proc_nr = mess.PROC_NR;
+               proc_nr = mess.IO_ENDPT;
+
 
                /* Now carry out the work. */
                switch(mess.m_type) {
                        case DEV_OPEN:          /* open the special file ( = parameter) */
-        r = msg_open(mess.DEVICE);break;
-        
+                               r = msg_open(mess.DEVICE);break;
                        case DEV_CLOSE:         /* close the special file ( = parameter) */
-        r = msg_close(mess.DEVICE); break;
-        
-                       case DEV_IOCTL:         
-        r = msg_ioctl(&mess); break; 
-        
-                       case DEV_READ:          
-        msg_read(&mess); continue; /* don't reply */
-        
-                       case DEV_WRITE:         
-        msg_write(&mess); continue; /* don't reply */
-        
-      case DEV_STATUS: 
-        msg_status(&mess);continue; /* don't reply */
-        
+                               r = msg_close(mess.DEVICE); break;
+                       case DEV_IOCTL_S:               
+                               r = msg_ioctl(&mess); break; 
+                       case DEV_READ_S:                
+                               msg_read(&mess); continue; /* don't reply */
+                       case DEV_WRITE_S:               
+                               msg_write(&mess); continue; /* don't reply */
+                       case DEV_STATUS:        
+                               msg_status(&mess);continue; /* don't reply */
                        case HARD_INT:
-        msg_hardware();continue;  /* don't reply */
-        
+                               msg_hardware();continue;  /* don't reply */
                        case SYS_SIG:             
-        msg_sig_stop(); continue; /* don't reply */
-        
+                               msg_sig_stop(); continue; /* don't reply */
                        default:          
-        r = EINVAL;    dprint("%s: %d uncaught msg!\n", mess.m_type ,drv.DriverName);
-        break;
+                               r = EINVAL;     
+                               dprint("%s: %d uncaught msg!\n", drv.DriverName, mess.m_type);
+                               break;
                }
                /* Finally, prepare and send the reply message. */
                reply(TASK_REPLY, caller, proc_nr, r);
        }
-       
 }
 
+
 PRIVATE int init_driver(void) {
-  u32_t i; char irq;
-  static int executed = 0;
-  sub_dev_t* sub_dev_ptr;
-  
-  /* init variables, get dma buffers */
-  for (i = 0; i < drv.NrOfSubDevices; i++) {
-  
-    sub_dev_ptr = &sub_dev[i];
-    
-    sub_dev_ptr->Opened = FALSE;
-    sub_dev_ptr->DmaBusy = FALSE;
-    sub_dev_ptr->DmaMode = NO_DMA;
-    sub_dev_ptr->DmaReadNext = 0;
-    sub_dev_ptr->DmaFillNext = 0;
-    sub_dev_ptr->DmaLength = 0;
-    sub_dev_ptr->BufReadNext = 0;
-    sub_dev_ptr->BufFillNext = 0;
-    sub_dev_ptr->RevivePending = FALSE;
-    sub_dev_ptr->OutOfData = FALSE;
-    sub_dev_ptr->Nr = i;
-  }
-  
-  /* initialize hardware*/
-  if (drv_init_hw() != OK) {
-    error("%s: Could not initialize hardware\n", drv.DriverName, 0);
-    return EIO;
-  }
-  
+       u32_t i; char irq;
+       static int executed = 0;
+       sub_dev_t* sub_dev_ptr;
+
+       /* init variables, get dma buffers */
+       for (i = 0; i < drv.NrOfSubDevices; i++) {
+
+               sub_dev_ptr = &sub_dev[i];
+
+               sub_dev_ptr->Opened = FALSE;
+               sub_dev_ptr->DmaBusy = FALSE;
+               sub_dev_ptr->DmaMode = NO_DMA;
+               sub_dev_ptr->DmaReadNext = 0;
+               sub_dev_ptr->DmaFillNext = 0;
+               sub_dev_ptr->DmaLength = 0;
+               sub_dev_ptr->BufReadNext = 0;
+               sub_dev_ptr->BufFillNext = 0;
+               sub_dev_ptr->RevivePending = FALSE;
+               sub_dev_ptr->OutOfData = FALSE;
+               sub_dev_ptr->Nr = i;
+       }
+
+       /* initialize hardware*/
+       if (drv_init_hw() != OK) {
+               error("%s: Could not initialize hardware\n", drv.DriverName, 0);
+               return EIO;
+       }
+
        /* get irq from device driver...*/
        if (drv_get_irq(&irq) != OK) {
-         error("%s: init driver couldn't get IRQ", drv.DriverName, i);
-         return EIO;
+               error("%s: init driver couldn't get IRQ", drv.DriverName, i);
+               return EIO;
        }
        /* todo: execute the rest of this function only once 
-     we don't want to set irq policy twice */
-  if (executed) return OK;
-  executed = TRUE;
-  
+          we don't want to set irq policy twice */
+       if (executed) return OK;
+       executed = TRUE;
+
        /* ...and register interrupt vector */
-  if ((i=sys_irqsetpolicy(irq, 0, &irq_hook_id )) != OK){
-       error("%s: init driver couldn't set IRQ policy", drv.DriverName, i);
-       return EIO;
-  }
-  irq_hook_set = TRUE; /* now msg_sig_stop knows it must unregister policy*/
+       if ((i=sys_irqsetpolicy(irq, 0, &irq_hook_id )) != OK){
+               error("%s: init driver couldn't set IRQ policy", drv.DriverName, i);
+               return EIO;
+       }
+       irq_hook_set = TRUE; /* now msg_sig_stop knows it must unregister policy*/
        return OK;
 }
 
 
 PRIVATE int msg_open (int minor_dev_nr) {
-  int r, read_chan, write_chan, io_ctl;
-  special_file_t* special_file_ptr;
-
-  dprint("%s: msg_open() special file %d\n", drv.DriverName, minor_dev_nr);
-  
-  special_file_ptr = get_special_file(minor_dev_nr);
-  if(special_file_ptr == NULL) {
-       return EIO;
-  }
-  
-  read_chan = special_file_ptr->read_chan;
-  write_chan = special_file_ptr->write_chan;
-  io_ctl = special_file_ptr->io_ctl;
-  
-  if (read_chan==NO_CHANNEL && write_chan==NO_CHANNEL && io_ctl==NO_CHANNEL) {
-    error("%s: No channel specified for minor device!\n", drv.DriverName, minor_dev_nr);
-    return EIO;
-  }
-  if (read_chan == write_chan && read_chan != NO_CHANNEL) {
-    error("%s: Read and write channels are equal!\n", drv.DriverName,minor_dev_nr);
-    return EIO;
-  }
-  /* init driver */
-  if (!device_available) {  
-    if (init_driver() != OK) {
-      error("%s: Couldn't init driver!\n", drv.DriverName, minor_dev_nr);
-      return EIO;
-    } else {
-      device_available = TRUE;
-    }
-  }  
-  /* open the sub devices specified in the interface header file */
-  if (write_chan != NO_CHANNEL) {
-    /* open sub device for writing */
-    if (open_sub_dev(write_chan, DEV_WRITE) != OK) return EIO;
-  }  
-  if (read_chan != NO_CHANNEL) {
-    if (open_sub_dev(read_chan, DEV_READ) != OK) return EIO;
-  }
-  if (read_chan == io_ctl || write_chan == io_ctl) {
-    /* io_ctl is already opened because it's the same as read or write */
-    return OK; /* we're done */
-  }
-  if (io_ctl != NO_CHANNEL) { /* Ioctl differs from read/write channels, */
-    r = open_sub_dev(io_ctl, NO_DMA); /* open it explicitly */
-    if (r != OK) return EIO;
-  } 
-  return OK;
+       int r, read_chan, write_chan, io_ctl;
+       special_file_t* special_file_ptr;
+
+       dprint("%s: msg_open() special file %d\n", drv.DriverName, minor_dev_nr);
+
+       special_file_ptr = get_special_file(minor_dev_nr);
+       if(special_file_ptr == NULL) {
+               return EIO;
+       }
+
+       read_chan = special_file_ptr->read_chan;
+       write_chan = special_file_ptr->write_chan;
+       io_ctl = special_file_ptr->io_ctl;
+
+       if (read_chan==NO_CHANNEL && write_chan==NO_CHANNEL && io_ctl==NO_CHANNEL) {
+               error("%s: No channel specified for minor device!\n", 
+                               drv.DriverName, minor_dev_nr);
+               return EIO;
+       }
+       if (read_chan == write_chan && read_chan != NO_CHANNEL) {
+               error("%s: Read and write channels are equal!\n", 
+                               drv.DriverName, minor_dev_nr);
+               return EIO;
+       }
+       /* init driver */
+       if (!device_available) {  
+               if (init_driver() != OK) {
+                       error("%s: Couldn't init driver!\n", drv.DriverName, minor_dev_nr);
+                       return EIO;
+               } else {
+                       device_available = TRUE;
+               }
+       }  
+       /* open the sub devices specified in the interface header file */
+       if (write_chan != NO_CHANNEL) {
+               /* open sub device for writing */
+               if (open_sub_dev(write_chan, DEV_WRITE_S) != OK) return EIO;
+       }  
+       if (read_chan != NO_CHANNEL) {
+               if (open_sub_dev(read_chan, DEV_READ_S) != OK) return EIO;
+       }
+       if (read_chan == io_ctl || write_chan == io_ctl) {
+               /* io_ctl is already opened because it's the same as read or write */
+               return OK; /* we're done */
+       }
+       if (io_ctl != NO_CHANNEL) { /* Ioctl differs from read/write channels, */
+               r = open_sub_dev(io_ctl, NO_DMA); /* open it explicitly */
+               if (r != OK) return EIO;
+       } 
+       return OK;
 }
 
 
 PRIVATE int open_sub_dev(int sub_dev_nr, int dma_mode) {
-  sub_dev_t* sub_dev_ptr; int i;
-  sub_dev_ptr = &sub_dev[sub_dev_nr];
-  
-  /* Only one open at a time per sub device */
+       sub_dev_t* sub_dev_ptr; int i;
+       sub_dev_ptr = &sub_dev[sub_dev_nr];
+
+       /* Only one open at a time per sub device */
        if (sub_dev_ptr->Opened) { 
-    error("%s: Sub device %d is already opened\n", drv.DriverName, sub_dev_nr);
-    return EBUSY;
-  }
+               error("%s: Sub device %d is already opened\n", 
+                               drv.DriverName, sub_dev_nr);
+               return EBUSY;
+       }
        if (sub_dev_ptr->DmaBusy) { 
-    error("%s: Sub device %d is still busy\n", drv.DriverName, sub_dev_nr);
-    return EBUSY;
-  }
+               error("%s: Sub device %d is still busy\n", drv.DriverName, sub_dev_nr);
+               return EBUSY;
+       }
        /* Setup variables */
        sub_dev_ptr->Opened = TRUE;
        sub_dev_ptr->DmaReadNext = 0;
        sub_dev_ptr->DmaFillNext = 0;
        sub_dev_ptr->DmaLength = 0;
        sub_dev_ptr->DmaMode = dma_mode;
-  sub_dev_ptr->BufReadNext = 0;
-  sub_dev_ptr->BufFillNext = 0;
-  sub_dev_ptr->BufLength = 0;
+       sub_dev_ptr->BufReadNext = 0;
+       sub_dev_ptr->BufFillNext = 0;
+       sub_dev_ptr->BufLength = 0;
        sub_dev_ptr->RevivePending = FALSE;
        sub_dev_ptr->OutOfData = TRUE;
-  
-  /* arrange DMA */
-  if (dma_mode != NO_DMA) { /* sub device uses DMA */
-    /* allocate dma buffer and extra buffer space
-       and configure sub device for dma */
-    if (init_buffers(sub_dev_ptr) != OK ) return EIO;
-  }
-  return OK;  
+
+       /* arrange DMA */
+       if (dma_mode != NO_DMA) { /* sub device uses DMA */
+               /* allocate dma buffer and extra buffer space
+                  and configure sub device for dma */
+               if (init_buffers(sub_dev_ptr) != OK ) return EIO;
+       }
+       return OK;  
 }
 
 
 PRIVATE int msg_close(int minor_dev_nr) {
 
-  int r, read_chan, write_chan, io_ctl; 
-  special_file_t* special_file_ptr;
-   
-  dprint("%s: msg_close() minor device %d\n", drv.DriverName, minor_dev_nr);
-  
-  special_file_ptr = get_special_file(minor_dev_nr);
-  if(special_file_ptr == NULL) {
-       return EIO;
-  }
-  
-  read_chan = special_file_ptr->read_chan;
-  write_chan = special_file_ptr->write_chan;
-  io_ctl = special_file_ptr->io_ctl;
-  
-  /* close all sub devices */
-  if (write_chan != NO_CHANNEL) {
-    if (close_sub_dev(write_chan) != OK) r = EIO;
-  }  
-  if (read_chan != NO_CHANNEL) {
-    if (close_sub_dev(read_chan) != OK) r = EIO;
-  }
-  if (read_chan == io_ctl || write_chan == io_ctl) {
-    /* io_ctl is already closed because it's the same as read or write */
-    return r; /* we're done */
-  }
-  /* Ioctl differs from read/write channels... */
-  if (io_ctl != NO_CHANNEL) { 
-    if (close_sub_dev(io_ctl) != OK) r = EIO; /* ...close it explicitly */
-  } 
-  return r;
+       int r, read_chan, write_chan, io_ctl; 
+       special_file_t* special_file_ptr;
+
+       dprint("%s: msg_close() minor device %d\n", drv.DriverName, minor_dev_nr);
+
+       special_file_ptr = get_special_file(minor_dev_nr);
+       if(special_file_ptr == NULL) {
+               return EIO;
+       }
+
+       read_chan = special_file_ptr->read_chan;
+       write_chan = special_file_ptr->write_chan;
+       io_ctl = special_file_ptr->io_ctl;
+
+       /* close all sub devices */
+       if (write_chan != NO_CHANNEL) {
+               if (close_sub_dev(write_chan) != OK) r = EIO;
+       }  
+       if (read_chan != NO_CHANNEL) {
+               if (close_sub_dev(read_chan) != OK) r = EIO;
+       }
+       if (read_chan == io_ctl || write_chan == io_ctl) {
+               /* io_ctl is already closed because it's the same as read or write */
+               return r; /* we're done */
+       }
+       /* ioctl differs from read/write channels... */
+       if (io_ctl != NO_CHANNEL) { 
+               if (close_sub_dev(io_ctl) != OK) r = EIO; /* ...close it explicitly */
+       
+       return r;
 }
 
 
 PRIVATE int close_sub_dev(int sub_dev_nr) {
-  sub_dev_t *sub_dev_ptr;
-  sub_dev_ptr = &sub_dev[sub_dev_nr];
-   
-  if (sub_dev_ptr->DmaMode == DEV_WRITE && !sub_dev_ptr->OutOfData) {
-    /* do nothing, still data in buffers that has to be transferred */
-    sub_dev_ptr->Opened = FALSE;  /* keep DMA busy */
-    return OK;
-  }
-  if (sub_dev_ptr->DmaMode == NO_DMA) {
-    /* do nothing, there is no dma going on */
-    sub_dev_ptr->Opened = FALSE;
-    return OK;
-  }
-  sub_dev_ptr->Opened = FALSE;
-  sub_dev_ptr->DmaBusy = FALSE;
-  /* stop the device */
-  drv_stop(sub_dev_ptr->Nr);
-  /* free the buffers */
-  free(sub_dev_ptr->DmaBuf);
-  free(sub_dev_ptr->ExtraBuf);
+       sub_dev_t *sub_dev_ptr;
+       sub_dev_ptr = &sub_dev[sub_dev_nr];
+       if (sub_dev_ptr->DmaMode == DEV_WRITE_S && !sub_dev_ptr->OutOfData) {
+               /* do nothing, still data in buffers that has to be transferred */
+               sub_dev_ptr->Opened = FALSE;  /* keep DMA busy */
+               return OK;
+       }
+       if (sub_dev_ptr->DmaMode == NO_DMA) {
+               /* do nothing, there is no dma going on */
+               sub_dev_ptr->Opened = FALSE;
+               return OK;
+       }
+       sub_dev_ptr->Opened = FALSE;
+       sub_dev_ptr->DmaBusy = FALSE;
+       /* stop the device */
+       drv_stop(sub_dev_ptr->Nr);
+       /* free the buffers */
+       free(sub_dev_ptr->DmaBuf);
+       free(sub_dev_ptr->ExtraBuf);
 }
 
 
@@ -316,49 +320,61 @@ PRIVATE int msg_ioctl(message *m_ptr)
 {
        int status, len, chan;
        phys_bytes user_phys;
-  sub_dev_t *sub_dev_ptr;
-  special_file_t* special_file_ptr;
-       
-  dprint("%s: msg_ioctl() device %d\n", drv.DriverName, m_ptr->DEVICE);
-
-  special_file_ptr = get_special_file(m_ptr->DEVICE);
-  if(special_file_ptr == NULL) {
-       return EIO;
-  }
-  
-  chan = special_file_ptr->io_ctl;
-  
+       sub_dev_t *sub_dev_ptr;
+       special_file_t* special_file_ptr;
+
+       dprint("%s: msg_ioctl() device %d\n", drv.DriverName, m_ptr->DEVICE);
+
+       special_file_ptr = get_special_file(m_ptr->DEVICE);
+       if(special_file_ptr == NULL) {
+               return EIO;
+       }
+
+       chan = special_file_ptr->io_ctl;
+
        if (chan == NO_CHANNEL) {
-         error("%s: No io control channel specified!\n", drv.DriverName);
-         return EIO;
+               error("%s: No io control channel specified!\n", drv.DriverName);
+               return EIO;
        }
        /* get pointer to sub device data */
        sub_dev_ptr = &sub_dev[chan];
-       
-  if(!sub_dev_ptr->Opened) {
-    error("%s: io control impossible - not opened!\n", drv.DriverName);
-    return EIO;
-  }
 
-  /* this is a hack...todo: may we intercept reset calls? */
+       if(!sub_dev_ptr->Opened) {
+               error("%s: io control impossible - not opened!\n", drv.DriverName);
+               return EIO;
+       }
+
+
+       /* this is a hack...todo: may we intercept reset calls? */
+       /*
        if(m_ptr->REQUEST == DSPIORESET) {
-    device_available = FALSE;
-  }
-  /* this is confusing, _IOC_OUT bit means that there is incoming data */
-  if (m_ptr->REQUEST & _IOC_OUT) { /* if there is data for us, copy it */
-    len = io_ctl_length(m_ptr->REQUEST);
-    sys_vircopy(m_ptr->PROC_NR, D, 
-        (vir_bytes)m_ptr->ADDRESS, SELF, D, 
-        (vir_bytes)io_ctl_buf, len);
-  }
-
-  /* all ioctl's are passed to the device specific part of the driver */
-  status = drv_io_ctl(m_ptr->REQUEST, (void *)io_ctl_buf, &len, chan); 
-       
-                                              /* _IOC_IN bit -> user expects data */
-  if (status == OK && m_ptr->REQUEST & _IOC_IN) { 
-    /* copy result back to user */
-               sys_vircopy(SELF, D, (vir_bytes)io_ctl_buf, m_ptr->PROC_NR, D, (vir_bytes)m_ptr->ADDRESS, len);
+               device_available = FALSE;
+       }
+       */
+
+
+       if (m_ptr->REQUEST & _IOC_IN) { /* if there is data for us, copy it */
+               len = io_ctl_length(m_ptr->REQUEST);
+
+               if(sys_safecopyfrom(m_ptr->IO_ENDPT, 
+                                       (vir_bytes)m_ptr->ADDRESS, 0,
+                                       (vir_bytes)io_ctl_buf, len, D) != OK) {
+                       printf("%s:%d: safecopyfrom failed\n", __FILE__, __LINE__);
+               }
+       }
+
+       /* all ioctl's are passed to the device specific part of the driver */
+       status = drv_io_ctl(m_ptr->REQUEST, (void *)io_ctl_buf, &len, chan); 
+
+       /* _IOC_OUT bit -> user expects data */
+       if (status == OK && m_ptr->REQUEST & _IOC_OUT) { 
+               /* copy result back to user */
+
+               if(sys_safecopyto(m_ptr->IO_ENDPT, (vir_bytes)m_ptr->ADDRESS, 0, 
+                                       (vir_bytes)io_ctl_buf, len, D) != OK) {
+                       printf("%s:%d: safecopyto failed\n", __FILE__, __LINE__);
+               }
+
        }
        return status;
 }
@@ -366,460 +382,489 @@ PRIVATE int msg_ioctl(message *m_ptr)
 
 PRIVATE void msg_write(message *m_ptr) 
 {
-  int s, chan; sub_dev_t *sub_dev_ptr;
-  special_file_t* special_file_ptr;
-       
-  dprint("%s: msg_write() device %d\n", drv.DriverName, m_ptr->DEVICE);
-
-  special_file_ptr = get_special_file(m_ptr->DEVICE); 
-  chan = special_file_ptr->write_chan;
-  
+       int s, chan; sub_dev_t *sub_dev_ptr;
+       special_file_t* special_file_ptr;
+
+       dprint("%s: msg_write() device %d\n", drv.DriverName, m_ptr->DEVICE);
+
+       special_file_ptr = get_special_file(m_ptr->DEVICE); 
+       chan = special_file_ptr->write_chan;
+
        if (chan == NO_CHANNEL) {
-         error("%s: No write channel specified!\n", drv.DriverName);
-    reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, EIO);
-         return;
+               error("%s: No write channel specified!\n", drv.DriverName);
+               reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, EIO);
+               return;
        }
        /* get pointer to sub device data */
        sub_dev_ptr = &sub_dev[chan];
-       
-  if (!sub_dev_ptr->DmaBusy) { /* get fragment size on first write */
-    if (drv_get_frag_size(&(sub_dev_ptr->FragSize), sub_dev_ptr->Nr) != OK){
-      error("%s; Failed to get fragment size!\n", drv.DriverName, 0);
-      return;  
-    }
-  }
+
+       if (!sub_dev_ptr->DmaBusy) { /* get fragment size on first write */
+               if (drv_get_frag_size(&(sub_dev_ptr->FragSize), sub_dev_ptr->Nr) != OK){
+                       error("%s; Failed to get fragment size!\n", drv.DriverName, 0);
+                       return; 
+               }
+       }
        if(m_ptr->COUNT != sub_dev_ptr->FragSize) {
                error("Fragment size does not match user's buffer length\n");
-    reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, EINVAL);                
+               reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, EINVAL);            
                return;
        }
        /* if we are busy with something else than writing, return EBUSY */
-       if(sub_dev_ptr->DmaBusy && sub_dev_ptr->DmaMode != DEV_WRITE) {
-         error("Already busy with something else then writing\n");
-               reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, EBUSY);
+       if(sub_dev_ptr->DmaBusy && sub_dev_ptr->DmaMode != DEV_WRITE_S) {
+               error("Already busy with something else then writing\n");
+               reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, EBUSY);
                return;
        }
        /* unblock the FileSystem, but keep user process blocked until REVIVE*/
-       reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, SUSPEND);
+       reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, SUSPEND);
        sub_dev_ptr->RevivePending = TRUE;
-       sub_dev_ptr->ReviveProcNr = m_ptr->PROC_NR;
-       sub_dev_ptr->UserBuf = m_ptr->ADDRESS;
+       sub_dev_ptr->ReviveProcNr = m_ptr->IO_ENDPT;
+       sub_dev_ptr->ReviveGrant = (cp_grant_id_t) m_ptr->ADDRESS;
        sub_dev_ptr->NotifyProcNr = m_ptr->m_source;
 
-  data_from_user(sub_dev_ptr);
-  
+       data_from_user(sub_dev_ptr);
+
        if(!sub_dev_ptr->DmaBusy) { /* Dma tranfer not yet started */
-       dprint("starting audio device\n");
-    get_started(sub_dev_ptr);    
-               sub_dev_ptr->DmaMode = DEV_WRITE; /* Dma mode is writing */
+               dprint("starting audio device\n");
+               get_started(sub_dev_ptr);    
+               sub_dev_ptr->DmaMode = DEV_WRITE_S; /* Dma mode is writing */
        } 
 }
 
 
 PRIVATE void msg_read(message *m_ptr) 
 {
-  int s, chan; sub_dev_t *sub_dev_ptr;
-  special_file_t* special_file_ptr;
-       
-  dprint("%s: msg_read() device %d\n", drv.DriverName, m_ptr->DEVICE);
-  
-  special_file_ptr = get_special_file(m_ptr->DEVICE); 
-  chan = special_file_ptr->read_chan;
-  
+       int s, chan; sub_dev_t *sub_dev_ptr;
+       special_file_t* special_file_ptr;
+
+       dprint("%s: msg_read() device %d\n", drv.DriverName, m_ptr->DEVICE);
+
+       special_file_ptr = get_special_file(m_ptr->DEVICE); 
+       chan = special_file_ptr->read_chan;
+
        if (chan == NO_CHANNEL) {
-         error("%s: No read channel specified!\n", drv.DriverName);
-    reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, EIO);
-         return;
+               error("%s: No read channel specified!\n", drv.DriverName);
+               reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, EIO);
+               return;
        }
        /* get pointer to sub device data */
        sub_dev_ptr = &sub_dev[chan];
-       
-  if (!sub_dev_ptr->DmaBusy) { /* get fragment size on first read */
-    if (drv_get_frag_size(&(sub_dev_ptr->FragSize), sub_dev_ptr->Nr) != OK){
-      error("%s: Could not retrieve fragment size!\n", drv.DriverName);
-      reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, EIO);         
-      return;
-    }
-  }
+
+       if (!sub_dev_ptr->DmaBusy) { /* get fragment size on first read */
+               if (drv_get_frag_size(&(sub_dev_ptr->FragSize), sub_dev_ptr->Nr) != OK){
+                       error("%s: Could not retrieve fragment size!\n", drv.DriverName);
+                       reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, EIO);       
+                       return;
+               }
+       }
        if(m_ptr->COUNT != sub_dev_ptr->FragSize) {
-               reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, EINVAL);
+               reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, EINVAL);
                error("fragment size does not match message size\n");
                return;
        }
        /* if we are busy with something else than reading, reply EBUSY */
-       if(sub_dev_ptr->DmaBusy && sub_dev_ptr->DmaMode != DEV_READ) {
-               reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, EBUSY);
+       if(sub_dev_ptr->DmaBusy && sub_dev_ptr->DmaMode != DEV_READ_S) {
+               reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, EBUSY);
                return;
        }
        /* unblock the FileSystem, but keep user process blocked until REVIVE*/
-       reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, SUSPEND);
+       reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, SUSPEND);
        sub_dev_ptr->RevivePending = TRUE;
-       sub_dev_ptr->ReviveProcNr = m_ptr->PROC_NR;
-       sub_dev_ptr->UserBuf = m_ptr->ADDRESS;
+       sub_dev_ptr->ReviveProcNr = m_ptr->IO_ENDPT;
+       sub_dev_ptr->ReviveGrant = (cp_grant_id_t) m_ptr->ADDRESS;
        sub_dev_ptr->NotifyProcNr = m_ptr->m_source;
 
        if(!sub_dev_ptr->DmaBusy) { /* Dma tranfer not yet started */
-    get_started(sub_dev_ptr);
-               sub_dev_ptr->DmaMode = DEV_READ; /* Dma mode is reading */
+               get_started(sub_dev_ptr);
+               sub_dev_ptr->DmaMode = DEV_READ_S; /* Dma mode is reading */
                return;  /* no need to get data from DMA buffer at this point */
        }
-  /* check if data is available and possibly fill user's buffer */
-  data_to_user(sub_dev_ptr);
+       /* check if data is available and possibly fill user's buffer */
+       data_to_user(sub_dev_ptr);
 }
 
 
 PRIVATE void msg_hardware(void) {
-  
-  u32_t     i;
-  int j = 0;
-  
-  dprint("%s: handling hardware message\n", drv.DriverName);
-  
-  /* while we have an interrupt  */
-  while ( drv_int_sum()) {
-    /* loop over all sub devices */
-    for ( i = 0; i < drv.NrOfSubDevices; i++) {
-      /* if interrupt from sub device and Dma transfer 
-         was actually busy, take care of business */
-      if( drv_int(i) && sub_dev[i].DmaBusy ) {
-        if (sub_dev[i].DmaMode == DEV_WRITE) handle_int_write(i);
-        if (sub_dev[i].DmaMode == DEV_READ) handle_int_read(i);  
-      }
-    }
-  }
+
+       u32_t     i;
+       int j = 0;
+
+       dprint("%s: handling hardware message\n", drv.DriverName);
+
+       /* while we have an interrupt  */
+       while ( drv_int_sum()) {
+               /* loop over all sub devices */
+               for ( i = 0; i < drv.NrOfSubDevices; i++) {
+                       /* if interrupt from sub device and Dma transfer 
+                          was actually busy, take care of business */
+                       if( drv_int(i) && sub_dev[i].DmaBusy ) {
+                               if (sub_dev[i].DmaMode == DEV_WRITE_S) handle_int_write(i);
+                               if (sub_dev[i].DmaMode == DEV_READ_S) handle_int_read(i);  
+                       }
+               }
+       }
 }
 
 
 PRIVATE void msg_status(message *m_ptr)
 {
-  int i; 
-
-  dprint("got a status message\n");
-  for (i = 0; i < drv.NrOfSubDevices; i++) {
-  
-       if(sub_dev[i].ReadyToRevive) 
-    {
-               m_ptr->m_type = DEV_REVIVE;                     /* build message */
-               m_ptr->REP_PROC_NR = sub_dev[i].ReviveProcNr;
-               m_ptr->REP_STATUS = sub_dev[i].ReviveStatus;
-      send(m_ptr->m_source, m_ptr);                    /* send the message */
-               
-               /* reset variables */
-               sub_dev[i].ReadyToRevive = FALSE;
-               sub_dev[i].RevivePending = 0;
-               
-               return; /* stop after one mess, 
-                    file system will get back for other processes */
-       }
-  }
-  m_ptr->m_type = DEV_NO_STATUS;
-  m_ptr->REP_STATUS = 0;
-  send(m_ptr->m_source, m_ptr);                        /* send DEV_NO_STATUS message */
+       int i; 
+
+       dprint("got a status message\n");
+       for (i = 0; i < drv.NrOfSubDevices; i++) {
+
+               if(sub_dev[i].ReadyToRevive) 
+               {
+                       m_ptr->m_type = DEV_REVIVE;                     /* build message */
+                       m_ptr->REP_ENDPT = sub_dev[i].ReviveProcNr;
+                       m_ptr->REP_IO_GRANT = sub_dev[i].ReviveGrant;
+                       m_ptr->REP_STATUS = sub_dev[i].ReviveStatus;
+                       send(m_ptr->m_source, m_ptr);                   /* send the message */
+
+                       /* reset variables */
+                       sub_dev[i].ReadyToRevive = FALSE;
+                       sub_dev[i].RevivePending = 0;
+
+                       return; /* stop after one mess, 
+                                          file system will get back for other processes */
+               }
+       }
+       m_ptr->m_type = DEV_NO_STATUS;
+       m_ptr->REP_STATUS = 0;
+       send(m_ptr->m_source, m_ptr);                   /* send DEV_NO_STATUS message */
 }
 
 
 PRIVATE void msg_sig_stop(void) 
 {
-  int i; char irq;
-  for (i = 0; i < drv.NrOfSubDevices; i++) {
-    drv_stop(i); /* stop all sub devices */
-  }
-  if (irq_hook_set) {
-    if (sys_irqdisable(&irq_hook_id) != OK) {
-      error("Could not disable IRQ\n");
-    }
-    /* get irq from device driver*/
-       if (drv_get_irq(&irq) != OK) {
-         error("Msg SIG_STOP Couldn't get IRQ");
-       }
-       /* remove the policy */
-    if (sys_irqrmpolicy(irq, &irq_hook_id) != OK) {
-      error("%s: Could not disable IRQ\n",drv.DriverName);
-    }
-  }
+       int i; char irq;
+       for (i = 0; i < drv.NrOfSubDevices; i++) {
+               drv_stop(i); /* stop all sub devices */
+       }
+       if (irq_hook_set) {
+               if (sys_irqdisable(&irq_hook_id) != OK) {
+                       error("Could not disable IRQ\n");
+               }
+               /* get irq from device driver*/
+               if (drv_get_irq(&irq) != OK) {
+                       error("Msg SIG_STOP Couldn't get IRQ");
+               }
+               /* remove the policy */
+               if (sys_irqrmpolicy(irq, &irq_hook_id) != OK) {
+                       error("%s: Could not disable IRQ\n",drv.DriverName);
+               }
+       }
 }
 
 
-/* handle interrupt for specified sub device; DmaMode == DEV_WRITE*/
+/* handle interrupt for specified sub device; DmaMode == DEV_WRITE_S*/
 PRIVATE void handle_int_write(int sub_dev_nr) 
 {
-  sub_dev_t *sub_dev_ptr;
-  int r;
-  
-  sub_dev_ptr = &sub_dev[sub_dev_nr];
-  
-  dprint("Finished playing dma[%d] ", sub_dev_ptr->DmaReadNext);
-       sub_dev_ptr->DmaReadNext = (sub_dev_ptr->DmaReadNext + 1) % sub_dev_ptr->NrOfDmaFragments;
+       sub_dev_t *sub_dev_ptr;
+       int r;
+
+       sub_dev_ptr = &sub_dev[sub_dev_nr];
+
+       dprint("Finished playing dma[%d] ", sub_dev_ptr->DmaReadNext);
+       sub_dev_ptr->DmaReadNext = 
+               (sub_dev_ptr->DmaReadNext + 1) % sub_dev_ptr->NrOfDmaFragments;
        sub_dev_ptr->DmaLength -= 1;
-        
-  if (sub_dev_ptr->BufLength != 0) { /* Data in extra buf, copy to Dma buf */
-
-    dprint(" buf[%d] -> dma[%d] ", sub_dev_ptr->BufReadNext, sub_dev_ptr->DmaFillNext);
-    memcpy(sub_dev_ptr->DmaPtr + sub_dev_ptr->DmaFillNext * sub_dev_ptr->FragSize, 
-           sub_dev_ptr->ExtraBuf + sub_dev_ptr->BufReadNext * sub_dev_ptr->FragSize, 
-           sub_dev_ptr->FragSize);
-               
-               sub_dev_ptr->BufReadNext = (sub_dev_ptr->BufReadNext + 1) % sub_dev_ptr->NrOfExtraBuffers;
-               sub_dev_ptr->DmaFillNext = (sub_dev_ptr->DmaFillNext + 1) % sub_dev_ptr->NrOfDmaFragments;
-               
+
+       if (sub_dev_ptr->BufLength != 0) { /* Data in extra buf, copy to Dma buf */
+
+               dprint(" buf[%d] -> dma[%d] ", 
+                               sub_dev_ptr->BufReadNext, sub_dev_ptr->DmaFillNext);
+               memcpy(sub_dev_ptr->DmaPtr + 
+                               sub_dev_ptr->DmaFillNext * sub_dev_ptr->FragSize, 
+                               sub_dev_ptr->ExtraBuf + 
+                               sub_dev_ptr->BufReadNext * sub_dev_ptr->FragSize, 
+                               sub_dev_ptr->FragSize);
+
+               sub_dev_ptr->BufReadNext = 
+                       (sub_dev_ptr->BufReadNext + 1) % sub_dev_ptr->NrOfExtraBuffers;
+               sub_dev_ptr->DmaFillNext = 
+                       (sub_dev_ptr->DmaFillNext + 1) % sub_dev_ptr->NrOfDmaFragments;
+
                sub_dev_ptr->BufLength -= 1;
-         sub_dev_ptr->DmaLength += 1;
-  } 
-  
-  /* space became available, possibly copy new data from user */
+               sub_dev_ptr->DmaLength += 1;
+       
+
+       /* space became available, possibly copy new data from user */
        data_from_user(sub_dev_ptr);
-    
-  if(sub_dev_ptr->DmaLength == 0) { /* Dma buffer empty, stop Dma transfer */
-
-    sub_dev_ptr->OutOfData = TRUE; /* we're out of data */
-    dprint("No more work...!\n");
-    if (!sub_dev_ptr->Opened) {
-      close_sub_dev(sub_dev_ptr->Nr);
-      dprint("Stopping sub device %d\n", sub_dev_ptr->Nr);
-      return;
-    }
-    dprint("Pausing sub device %d\n",sub_dev_ptr->Nr);
-    drv_pause(sub_dev_ptr->Nr);
-    return;
-  }
-
-  dprint("\n");
-  
-  /* confirm and reenable interrupt from this sub dev */
-  drv_reenable_int(sub_dev_nr);
-  /* reenable irq_hook*/
+
+       if(sub_dev_ptr->DmaLength == 0) { /* Dma buffer empty, stop Dma transfer */
+
+               sub_dev_ptr->OutOfData = TRUE; /* we're out of data */
+               dprint("No more work...!\n");
+               if (!sub_dev_ptr->Opened) {
+                       close_sub_dev(sub_dev_ptr->Nr);
+                       dprint("Stopping sub device %d\n", sub_dev_ptr->Nr);
+                       return;
+               }
+               dprint("Pausing sub device %d\n",sub_dev_ptr->Nr);
+               drv_pause(sub_dev_ptr->Nr);
+               return;
+       }
+
+       dprint("\n");
+
+       /* confirm and reenable interrupt from this sub dev */
+       drv_reenable_int(sub_dev_nr);
+       /* reenable irq_hook*/
        if ((r=sys_irqenable(&irq_hook_id)) != OK) {
-    error("%s Couldn't enable IRQ\n", drv.DriverName);
-  }
+               error("%s Couldn't enable IRQ\n", drv.DriverName);
+       }
 }
 
 
-/* handle interrupt for specified sub device; DmaMode == DEV_READ */
+/* handle interrupt for specified sub device; DmaMode == DEV_READ_S */
 PRIVATE void handle_int_read(int sub_dev_nr) 
 {
-  sub_dev_t *sub_dev_ptr; int r,i;
-  
-  sub_dev_ptr = &sub_dev[sub_dev_nr];
-  
-  dprint("Device filled dma[%d]\n", sub_dev_ptr->DmaFillNext);
-  sub_dev_ptr->DmaLength += 1; 
-  sub_dev_ptr->DmaFillNext = (sub_dev_ptr->DmaFillNext + 1) % sub_dev_ptr->NrOfDmaFragments;
-
-  /* possibly copy data to user (if it is waiting for us) */
-  data_to_user(sub_dev_ptr);
-  
-       if (sub_dev_ptr->DmaLength == sub_dev_ptr->NrOfDmaFragments) { /* if dma buffer full */
-    
-    if (sub_dev_ptr->BufLength == sub_dev_ptr->NrOfExtraBuffers) {
-      error("All buffers full, we have a problem.\n");
-      drv_stop(sub_dev_nr);        /* stop the sub device */
-      sub_dev_ptr->DmaBusy = FALSE;
-      sub_dev_ptr->ReviveStatus = 0;   /* no data for user, this is a sad story */
-      sub_dev_ptr->ReadyToRevive = TRUE; /* wake user up */
-      return;
-    } 
-    else { /* dma full, still room in extra buf; copy from dma to extra buf */
-      dprint("dma full: going to copy buf[%d] <- dma[%d]\n", sub_dev_ptr->BufFillNext, 
-                                                       sub_dev_ptr->DmaReadNext);
-      memcpy(sub_dev_ptr->ExtraBuf + sub_dev_ptr->BufFillNext * sub_dev_ptr->FragSize, 
-                sub_dev_ptr->DmaPtr + sub_dev_ptr->DmaReadNext * sub_dev_ptr->FragSize,
-                                                         sub_dev_ptr->FragSize);
-      sub_dev_ptr->DmaLength -= 1;
-      sub_dev_ptr->DmaReadNext = (sub_dev_ptr->DmaReadNext + 1) % sub_dev_ptr->NrOfDmaFragments;
-      sub_dev_ptr->BufFillNext = (sub_dev_ptr->BufFillNext + 1) % sub_dev_ptr->NrOfExtraBuffers;
-    }
-  }
-  /* confirm interrupt, and reenable interrupt from this sub dev*/
-  drv_reenable_int(sub_dev_ptr->Nr);
-  
-  /* reenable irq_hook*/
-  if ((r=sys_irqenable(&irq_hook_id)) != OK) {
-    error("%s: Couldn't reenable IRQ", drv.DriverName);
-       }
+       sub_dev_t *sub_dev_ptr; int r,i;
+
+       sub_dev_ptr = &sub_dev[sub_dev_nr];
+
+       dprint("Device filled dma[%d]\n", sub_dev_ptr->DmaFillNext);
+       sub_dev_ptr->DmaLength += 1; 
+       sub_dev_ptr->DmaFillNext = 
+               (sub_dev_ptr->DmaFillNext + 1) % sub_dev_ptr->NrOfDmaFragments;
+
+       /* possibly copy data to user (if it is waiting for us) */
+       data_to_user(sub_dev_ptr);
+
+       if (sub_dev_ptr->DmaLength == sub_dev_ptr->NrOfDmaFragments) { 
+               /* if dma buffer full */
+
+               if (sub_dev_ptr->BufLength == sub_dev_ptr->NrOfExtraBuffers) {
+                       error("All buffers full, we have a problem.\n");
+                       drv_stop(sub_dev_nr);        /* stop the sub device */
+                       sub_dev_ptr->DmaBusy = FALSE;
+                       sub_dev_ptr->ReviveStatus = 0;   /* no data for user, 
+                                                                                               this is a sad story */
+                       sub_dev_ptr->ReadyToRevive = TRUE; /* wake user up */
+                       return;
+               } 
+               else { /* dma full, still room in extra buf; 
+                                 copy from dma to extra buf */
+                       dprint("dma full: going to copy buf[%d] <- dma[%d]\n", 
+                                       sub_dev_ptr->BufFillNext, sub_dev_ptr->DmaReadNext);
+                       memcpy(sub_dev_ptr->ExtraBuf + 
+                                       sub_dev_ptr->BufFillNext * sub_dev_ptr->FragSize, 
+                                       sub_dev_ptr->DmaPtr + 
+                                       sub_dev_ptr->DmaReadNext * sub_dev_ptr->FragSize,
+                                       sub_dev_ptr->FragSize);
+                       sub_dev_ptr->DmaLength -= 1;
+                       sub_dev_ptr->DmaReadNext = 
+                               (sub_dev_ptr->DmaReadNext + 1) % sub_dev_ptr->NrOfDmaFragments;
+                       sub_dev_ptr->BufFillNext = 
+                               (sub_dev_ptr->BufFillNext + 1) % sub_dev_ptr->NrOfExtraBuffers;
+               }
+       }
+       /* confirm interrupt, and reenable interrupt from this sub dev*/
+       drv_reenable_int(sub_dev_ptr->Nr);
+
+       /* reenable irq_hook*/
+       if ((r=sys_irqenable(&irq_hook_id)) != OK) {
+               error("%s: Couldn't reenable IRQ", drv.DriverName);
+       }
 }
 
 
 PRIVATE int get_started(sub_dev_t *sub_dev_ptr) {
-  u32_t i;char c;  
-  
-  /* enable interrupt messages from MINIX */
-  if ((i=sys_irqenable(&irq_hook_id)) != OK) {
-    error("%s: Couldn't enable IRQs",drv.DriverName);
-    return EIO;
-  }
-  /* let the lower part of the driver start the device */
-  if (drv_start(sub_dev_ptr->Nr, sub_dev_ptr->DmaMode) != OK) {
-    error("%s: Could not start device %d\n", drv.DriverName, sub_dev_ptr->Nr);
-  }
-  
-  sub_dev_ptr->DmaBusy = TRUE;     /* Dma is busy from now on */
+       u32_t i;char c;  
+
+       /* enable interrupt messages from MINIX */
+       if ((i=sys_irqenable(&irq_hook_id)) != OK) {
+               error("%s: Couldn't enable IRQs",drv.DriverName);
+               return EIO;
+       }
+       /* let the lower part of the driver start the device */
+       if (drv_start(sub_dev_ptr->Nr, sub_dev_ptr->DmaMode) != OK) {
+               error("%s: Could not start device %d\n", 
+                               drv.DriverName, sub_dev_ptr->Nr);
+       }
+
+       sub_dev_ptr->DmaBusy = TRUE;     /* Dma is busy from now on */
        sub_dev_ptr->DmaReadNext = 0;    
-  return OK;
+       return OK;
 }
 
 
 PRIVATE void data_from_user(sub_dev_t *subdev) {
 
-  if (subdev->DmaLength == subdev->NrOfDmaFragments &&
-      subdev->BufLength == subdev->NrOfExtraBuffers) return; /* no space */
-  
-  if (!subdev->RevivePending) return; /* no new data waiting to be copied */
-  
-  if (subdev->RevivePending && 
-      subdev->ReadyToRevive) return; /* we already got this data */
-  
-  
-  if (subdev->DmaLength < subdev->NrOfDmaFragments) { /* room in dma buf */
-    
-      sys_datacopy(subdev->ReviveProcNr, 
-      (vir_bytes)subdev->UserBuf, 
-      SELF, 
-      (vir_bytes)subdev->DmaPtr + subdev->DmaFillNext * subdev->FragSize, 
-      (phys_bytes)subdev->FragSize);
-  
-    dprint(" user -> dma[%d]\n", subdev->DmaFillNext);
-    subdev->DmaLength += 1;
-    subdev->DmaFillNext = (subdev->DmaFillNext + 1) % subdev->NrOfDmaFragments;
-    
-  } else { /* room in extra buf */ 
-
-               sys_datacopy(subdev->ReviveProcNr, 
-      (vir_bytes)subdev->UserBuf, 
-      SELF, 
-      (vir_bytes)subdev->ExtraBuf + subdev->BufFillNext * subdev->FragSize, 
-      (phys_bytes)subdev->FragSize);
-      
+       if (subdev->DmaLength == subdev->NrOfDmaFragments &&
+                       subdev->BufLength == subdev->NrOfExtraBuffers) return;/* no space */
+
+       if (!subdev->RevivePending) return; /* no new data waiting to be copied */
+
+       if (subdev->RevivePending && 
+                       subdev->ReadyToRevive) return; /* we already got this data */
+
+       if (subdev->DmaLength < subdev->NrOfDmaFragments) { /* room in dma buf */
+
+               sys_safecopyfrom(subdev->ReviveProcNr, 
+                               (vir_bytes)subdev->ReviveGrant, 0, 
+                               (vir_bytes)subdev->DmaPtr + 
+                               subdev->DmaFillNext * subdev->FragSize,
+                               (phys_bytes)subdev->FragSize, D);
+
+
+               dprint(" user -> dma[%d]\n", subdev->DmaFillNext);
+               subdev->DmaLength += 1;
+               subdev->DmaFillNext = 
+                       (subdev->DmaFillNext + 1) % subdev->NrOfDmaFragments;
+
+       } else { /* room in extra buf */ 
+
+               sys_safecopyfrom(subdev->ReviveProcNr, 
+                               (vir_bytes)subdev->ReviveGrant, 0,
+                               (vir_bytes)subdev->ExtraBuf + 
+                               subdev->BufFillNext * subdev->FragSize, 
+                               (phys_bytes)subdev->FragSize, D);
+
                dprint(" user -> buf[%d]\n", subdev->BufFillNext);
                subdev->BufLength += 1;
-               
-               subdev->BufFillNext = (subdev->BufFillNext + 1) % subdev->NrOfExtraBuffers;
+
+               subdev->BufFillNext = 
+                       (subdev->BufFillNext + 1) % subdev->NrOfExtraBuffers;
 
        }
        if(subdev->OutOfData) { /* if device paused (because of lack of data) */
-    subdev->OutOfData = FALSE;
-    drv_reenable_int(subdev->Nr);
-    /* reenable irq_hook*/
-       if ((sys_irqenable(&irq_hook_id)) != OK) {
-      error("%s: Couldn't enable IRQ", drv.DriverName);
-    }
-    drv_resume(subdev->Nr);  /* resume resume the sub device */
-    
-  }
-  
+               subdev->OutOfData = FALSE;
+               drv_reenable_int(subdev->Nr);
+               /* reenable irq_hook*/
+               if ((sys_irqenable(&irq_hook_id)) != OK) {
+                       error("%s: Couldn't enable IRQ", drv.DriverName);
+               }
+               drv_resume(subdev->Nr);  /* resume resume the sub device */
+       }
+
        subdev->ReviveStatus = subdev->FragSize;
        subdev->ReadyToRevive = TRUE;
        notify(subdev->NotifyProcNr);
 }
 
 
-PRIVATE void data_to_user(sub_dev_t *sub_dev_ptr) 
-{
-  if (!sub_dev_ptr->RevivePending) return; /* nobody is wating for data */
-  if (sub_dev_ptr->ReadyToRevive) return;  /* we already filled user's buffer */
-  if (sub_dev_ptr->BufLength == 0 && sub_dev_ptr->DmaLength == 0) return; 
-                                                          /* no data for user */
-  
-  if(sub_dev_ptr->BufLength != 0) { /* data in extra buffer available */
-    
-               sys_datacopy(SELF, 
-      (vir_bytes)sub_dev_ptr->ExtraBuf + sub_dev_ptr->BufReadNext * sub_dev_ptr->FragSize,
-      sub_dev_ptr->ReviveProcNr, 
-      (vir_bytes)sub_dev_ptr->UserBuf, 
-      (phys_bytes)sub_dev_ptr->FragSize);
-      
+PRIVATE void data_to_user(sub_dev_t *sub_dev_ptr) {
+       if (!sub_dev_ptr->RevivePending) return; /* nobody is wating for data */
+       if (sub_dev_ptr->ReadyToRevive) return;/* we already filled user's buffer */
+       if (sub_dev_ptr->BufLength == 0 && sub_dev_ptr->DmaLength == 0) return; 
+               /* no data for user */
+
+       if(sub_dev_ptr->BufLength != 0) { /* data in extra buffer available */
+
+               sys_safecopyto(sub_dev_ptr->ReviveProcNr, 
+                               (vir_bytes)sub_dev_ptr->ReviveGrant,
+                               0, (vir_bytes)sub_dev_ptr->ExtraBuf + 
+                               sub_dev_ptr->BufReadNext * sub_dev_ptr->FragSize,
+                               (phys_bytes)sub_dev_ptr->FragSize, D);
+
                dprint(" copied buf[%d] to user\n", sub_dev_ptr->BufReadNext); 
+
                /* adjust the buffer status variables */
-    sub_dev_ptr->BufReadNext = (sub_dev_ptr->BufReadNext + 1) % sub_dev_ptr->NrOfExtraBuffers;
+               sub_dev_ptr->BufReadNext = 
+                       (sub_dev_ptr->BufReadNext + 1) % sub_dev_ptr->NrOfExtraBuffers;
                sub_dev_ptr->BufLength -= 1;
-               
+
        } else { /* extra buf empty, but data in dma buf*/ 
+               sys_safecopyto(
+                               sub_dev_ptr->ReviveProcNr, 
+                               (vir_bytes)sub_dev_ptr->ReviveGrant, 0, 
+                               (vir_bytes)sub_dev_ptr->DmaPtr + 
+                               sub_dev_ptr->DmaReadNext * sub_dev_ptr->FragSize,
+                               (phys_bytes)sub_dev_ptr->FragSize, D);
 
-                 sys_datacopy(SELF, 
-      (vir_bytes)sub_dev_ptr->DmaPtr + sub_dev_ptr->DmaReadNext * sub_dev_ptr->FragSize,
-      sub_dev_ptr->ReviveProcNr, 
-      (vir_bytes)sub_dev_ptr->UserBuf, 
-      (phys_bytes)sub_dev_ptr->FragSize);
-      
                dprint(" copied dma[%d] to user\n", sub_dev_ptr->DmaReadNext);
+
                /* adjust the buffer status variables */
-    sub_dev_ptr->DmaReadNext = (sub_dev_ptr->DmaReadNext + 1) % sub_dev_ptr->NrOfDmaFragments;
+               sub_dev_ptr->DmaReadNext = 
+                       (sub_dev_ptr->DmaReadNext + 1) % sub_dev_ptr->NrOfDmaFragments;
                sub_dev_ptr->DmaLength -= 1;
        }
+
        sub_dev_ptr->ReviveStatus = sub_dev_ptr->FragSize;
-       sub_dev_ptr->ReadyToRevive = TRUE; /* drv_status will send REVIVE mess to FS*/  
-  notify(sub_dev_ptr->NotifyProcNr);     /* notify the File Systam to make it 
-                                        send DEV_STATUS messages*/
+       sub_dev_ptr->ReadyToRevive = TRUE; 
+               /* drv_status will send REVIVE mess to FS*/     
+       notify(sub_dev_ptr->NotifyProcNr);     /* notify the File Systam to make it 
+                                                                                         send DEV_STATUS messages*/
 }
 
 
-PRIVATE int init_buffers(sub_dev_t *sub_dev_ptr) {
+       PRIVATE int init_buffers(sub_dev_t *sub_dev_ptr) {
 #if (CHIP == INTEL)
-       unsigned left;
-       u32_t i;
-  
-  /* allocate dma buffer space */
-  if (!(sub_dev_ptr->DmaBuf = malloc(sub_dev_ptr->DmaSize + 64 * 1024))) {
-    error("%s: failed to allocate dma buffer for channel %d\n", drv.DriverName,i);
-    return EIO;
-  }
-  /* allocate extra buffer space */
-  if (!(sub_dev_ptr->ExtraBuf = malloc(sub_dev_ptr->NrOfExtraBuffers * sub_dev_ptr->DmaSize / sub_dev_ptr->NrOfDmaFragments))) {
-    error("%s failed to allocate extra buffer for channel %d\n", drv.DriverName,i);
-    return EIO;
-  }
-  
-       sub_dev_ptr->DmaPtr = sub_dev_ptr->DmaBuf;
-       i = sys_umap(SELF, D, 
-               (vir_bytes) sub_dev_ptr->DmaBuf, 
-               (phys_bytes) sizeof(sub_dev_ptr->DmaBuf), 
-               &(sub_dev_ptr->DmaPhys));
-  
-  if (i != OK) {
-    return EIO;
-  }
-       if((left = dma_bytes_left(sub_dev_ptr->DmaPhys)) < sub_dev_ptr->DmaSize) {
-               /* First half of buffer crosses a 64K boundary, can't DMA into that */
-               sub_dev_ptr->DmaPtr += left;
-               sub_dev_ptr->DmaPhys += left;
-       }
-       /* write the physical dma address and size to the device */
-  drv_set_dma(sub_dev_ptr->DmaPhys, sub_dev_ptr->DmaSize, sub_dev_ptr->Nr);
-       return OK;
-       
+               unsigned left;
+               u32_t i;
+
+               /* allocate dma buffer space */
+               if (!(sub_dev_ptr->DmaBuf = malloc(sub_dev_ptr->DmaSize + 64 * 1024))) {
+                       error("%s: failed to allocate dma buffer for channel %d\n", 
+                                       drv.DriverName,i);
+                       return EIO;
+               }
+               /* allocate extra buffer space */
+               if (!(sub_dev_ptr->ExtraBuf = malloc(sub_dev_ptr->NrOfExtraBuffers * 
+                                               sub_dev_ptr->DmaSize / 
+                                               sub_dev_ptr->NrOfDmaFragments))) {
+                       error("%s failed to allocate extra buffer for channel %d\n", 
+                                       drv.DriverName,i);
+                       return EIO;
+               }
+
+               sub_dev_ptr->DmaPtr = sub_dev_ptr->DmaBuf;
+               i = sys_umap(SELF, D, 
+                               (vir_bytes) sub_dev_ptr->DmaBuf, 
+                               (phys_bytes) sizeof(sub_dev_ptr->DmaBuf), 
+                               &(sub_dev_ptr->DmaPhys));
+
+               if (i != OK) {
+                       return EIO;
+               }
+               if ((left = dma_bytes_left(sub_dev_ptr->DmaPhys)) < 
+                               sub_dev_ptr->DmaSize) {
+                       /* First half of buffer crosses a 64K boundary,
+                        * can't DMA into that */
+                       sub_dev_ptr->DmaPtr += left;
+                       sub_dev_ptr->DmaPhys += left;
+               }
+               /* write the physical dma address and size to the device */
+               drv_set_dma(sub_dev_ptr->DmaPhys, 
+                               sub_dev_ptr->DmaSize, sub_dev_ptr->Nr);
+               return OK;
+
 #else /* CHIP != INTEL */
-       error("%s: init_buffer() failed, CHIP != INTEL", drv.DriverName);
-       return EIO;
+               error("%s: init_buffer() failed, CHIP != INTEL", drv.DriverName);
+               return EIO;
 #endif /* CHIP == INTEL */
-}
+       }
 
 
-PRIVATE void reply(int code, int replyee, int process, int status)
-{
+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_PROC_NR = process;        /* which user made the request */
+       m.REP_ENDPT = process;  /* which user made the request */
        send(replyee, &m);
 }
 
 
 PRIVATE int io_ctl_length(int io_request) {
-  io_request >>= 16; 
-  return io_request & _IOCPARM_MASK;
+       io_request >>= 16; 
+       return io_request & _IOCPARM_MASK;
 }
 
 
 PRIVATE special_file_t* get_special_file(int minor_dev_nr) {
        int i;
-       
+
        for(i = 0; i < drv.NrOfSpecialFiles; i++) {
                if(special_file[i].minor_dev_nr == minor_dev_nr) {
                        return &special_file[i];
                }
        }
 
-       error("%s: No subdevice specified for minor device %d!\n", drv.DriverName, minor_dev_nr);
-       
+       error("%s: No subdevice specified for minor device %d!\n", 
+                       drv.DriverName, minor_dev_nr);
+
        return NULL;
-}
\ No newline at end of file
+}
index bad32803db0f75b58efbd236997aabb34ec33587..ea3b6e7a182c6af00c730d45eea73a8080ada853 100755 (executable)
@@ -5,8 +5,15 @@
 #include <sys/ioc_sound.h>
 
 
-/* change '(void)' to 'printf' to print debug info and error messages */
-#define dprint (void)
+/* change to DEBUG to 1 to print debug info and error messages */
+
+#define DEBUG 0
+
+#if DEBUG
+#define dprint printf 
+#else
+#define dprint (void) 
+#endif
 #define error printf
 
 
@@ -51,6 +58,7 @@ typedef struct {
        int RevivePending;                        /* process waiting for this dev? */
        int ReviveStatus;                         /* return val when proc unblocked */
        int ReviveProcNr;                         /* the process to unblock */
+       cp_grant_id_t ReviveGrant;                /* grant id associated with io */
        void *UserBuf;                            /* address of user's data buffer */
        int ReadyToRevive;                        /* are we ready to revive process?*/
        int NotifyProcNr;                         /* process to send notify to (FS) */
diff --git a/drivers/audio/sb16/.depend b/drivers/audio/sb16/.depend
deleted file mode 100755 (executable)
index 418f83b..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-
-mixer.o:       ../framework/../../drivers.h
-mixer.o:       ../framework/audio_fw.h
-mixer.o:       /usr/include/ansi.h
-mixer.o:       /usr/include/errno.h
-mixer.o:       /usr/include/ibm/bios.h
-mixer.o:       /usr/include/ibm/interrupt.h
-mixer.o:       /usr/include/ibm/ports.h
-mixer.o:       /usr/include/limits.h
-mixer.o:       /usr/include/minix/bitmap.h
-mixer.o:       /usr/include/minix/callnr.h
-mixer.o:       /usr/include/minix/com.h
-mixer.o:       /usr/include/minix/config.h
-mixer.o:       /usr/include/minix/const.h
-mixer.o:       /usr/include/minix/devio.h
-mixer.o:       /usr/include/minix/dmap.h
-mixer.o:       /usr/include/minix/ioctl.h
-mixer.o:       /usr/include/minix/ipc.h
-mixer.o:       /usr/include/minix/sound.h
-mixer.o:       /usr/include/minix/sys_config.h
-mixer.o:       /usr/include/minix/syslib.h
-mixer.o:       /usr/include/minix/sysutil.h
-mixer.o:       /usr/include/minix/type.h
-mixer.o:       /usr/include/signal.h
-mixer.o:       /usr/include/stddef.h
-mixer.o:       /usr/include/stdlib.h
-mixer.o:       /usr/include/string.h
-mixer.o:       /usr/include/sys/dir.h
-mixer.o:       /usr/include/sys/ioc_sound.h
-mixer.o:       /usr/include/sys/types.h
-mixer.o:       /usr/include/unistd.h
-mixer.o:       mixer.c
-mixer.o:       mixer.h
-mixer.o:       sb16.h
-
-sb16.o:        ../framework/../../drivers.h
-sb16.o:        ../framework/audio_fw.h
-sb16.o:        /usr/include/ansi.h
-sb16.o:        /usr/include/errno.h
-sb16.o:        /usr/include/ibm/bios.h
-sb16.o:        /usr/include/ibm/interrupt.h
-sb16.o:        /usr/include/ibm/ports.h
-sb16.o:        /usr/include/limits.h
-sb16.o:        /usr/include/minix/bitmap.h
-sb16.o:        /usr/include/minix/callnr.h
-sb16.o:        /usr/include/minix/com.h
-sb16.o:        /usr/include/minix/config.h
-sb16.o:        /usr/include/minix/const.h
-sb16.o:        /usr/include/minix/devio.h
-sb16.o:        /usr/include/minix/dmap.h
-sb16.o:        /usr/include/minix/ioctl.h
-sb16.o:        /usr/include/minix/ipc.h
-sb16.o:        /usr/include/minix/sound.h
-sb16.o:        /usr/include/minix/sys_config.h
-sb16.o:        /usr/include/minix/syslib.h
-sb16.o:        /usr/include/minix/sysutil.h
-sb16.o:        /usr/include/minix/type.h
-sb16.o:        /usr/include/signal.h
-sb16.o:        /usr/include/stddef.h
-sb16.o:        /usr/include/stdlib.h
-sb16.o:        /usr/include/string.h
-sb16.o:        /usr/include/sys/dir.h
-sb16.o:        /usr/include/sys/ioc_sound.h
-sb16.o:        /usr/include/sys/types.h
-sb16.o:        /usr/include/unistd.h
-sb16.o:        mixer.h
-sb16.o:        sb16.c
-sb16.o:        sb16.h
index 57b1a6d02d00690443c793246e27575aace1d108..bd52e0ad7f27a1eb61931f3d90763975be60e301 100644 (file)
@@ -241,4 +241,29 @@ driver orinoco
        uid     0;
 };
 
+driver es1370
+{
+       system
+               SAFECOPYFROM
+               SAFECOPYTO
+               UMAP
+               SETGRANT
+               IRQCTL          # 19
+               DEVIO           # 21
+       ;
+       pci device 1274/5000;
+};
+
+driver es1371
+{
+       system
+               SAFECOPYFROM
+               SAFECOPYTO
+               UMAP
+               SETGRANT
+               IRQCTL          # 19
+               DEVIO           # 21
+       ;
+       pci device 1274/1371;
+};
 
index 59ed32a1d30a683312401e6a6b3585cc68c638e9..f875ab3b566805bdbe4af5f1dafb38f80c101c6c 100755 (executable)
@@ -9,13 +9,17 @@
 #include <minix/ioctl.h>
 
 /* Soundcard DSP ioctls. */
-#define        DSPIORATE       _IOR('s', 1, unsigned int)
-#define DSPIOSTEREO    _IOR('s', 2, unsigned int)
-#define DSPIOSIZE      _IOR('s', 3, unsigned int)
-#define DSPIOBITS      _IOR('s', 4, unsigned int)
-#define DSPIOSIGN      _IOR('s', 5, unsigned int)
-#define DSPIOMAX       _IOW('s', 6, unsigned int)
-#define DSPIORESET     _IO ('s', 7)
+#define        DSPIORATE               _IOW('s', 1, unsigned int)
+#define DSPIOSTEREO            _IOW('s', 2, unsigned int)
+#define DSPIOSIZE              _IOW('s', 3, unsigned int)
+#define DSPIOBITS              _IOW('s', 4, unsigned int)
+#define DSPIOSIGN              _IOW('s', 5, unsigned int)
+#define DSPIOMAX               _IOR('s', 6, unsigned int)
+#define DSPIORESET             _IO ('s', 7)
+#define DSPIOFREEBUF           _IOR('s', 30, unsigned int)
+#define DSPIOSAMPLESINBUF      _IOR('s', 31, unsigned int)
+#define DSPIOPAUSE             _IO ('s', 32)
+#define DSPIORESUME            _IO ('s', 33)
 
 /* Soundcard mixer ioctls. */
 #define MIXIOGETVOLUME         _IORW('s', 10, struct volume_level)
@@ -27,7 +31,4 @@
 #define MIXIOSETINPUTRIGHT     _IORW('s', 22, struct inout_ctrl)
 #define MIXIOSETOUTPUT         _IORW('s', 23, struct inout_ctrl)
 
-#define AC97READ _IOW('s', 8, u16_t[2])
-#define AC97WRITE _IOR('s', 9, u16_t[2])
-
 #endif /* _S_I_SOUND_H */