diff -u --recursive --new-file v1.3.33/linux/Makefile linux/Makefile --- v1.3.33/linux/Makefile Tue Oct 10 18:46:30 1995 +++ linux/Makefile Tue Oct 10 18:55:26 1995 @@ -1,6 +1,6 @@ VERSION = 1 PATCHLEVEL = 3 -SUBLEVEL = 33 +SUBLEVEL = 34 ARCH = i386 diff -u --recursive --new-file v1.3.33/linux/arch/alpha/Makefile linux/arch/alpha/Makefile --- v1.3.33/linux/arch/alpha/Makefile Mon Sep 25 12:26:20 1995 +++ linux/arch/alpha/Makefile Fri Oct 13 10:57:51 1995 @@ -10,10 +10,15 @@ NM := nm -B +ifdef CONFIG_CROSSCOMPILE # enable this for linking under OSF/1: -#LINKFLAGS = -non_shared -T 0xfffffc0000310000 -N +LINKFLAGS = -non_shared -T 0xfffffc0000310000 -N +else # enable this for linking under Linux: LINKFLAGS = -static -T arch/alpha/vmlinux.lds -N +# GNU gcc/cc1/as can use pipes instead of temporary files +CFLAGS := $(CFLAGS) -pipe +endif CFLAGS := $(CFLAGS) -mno-fp-regs diff -u --recursive --new-file v1.3.33/linux/arch/alpha/boot/Makefile linux/arch/alpha/boot/Makefile --- v1.3.33/linux/arch/alpha/boot/Makefile Mon Sep 25 12:26:20 1995 +++ linux/arch/alpha/boot/Makefile Fri Oct 13 10:57:51 1995 @@ -8,10 +8,13 @@ # Copyright (C) 1994 by Linus Torvalds # +ifdef CONFIG_CROSSCOMPILE # enable this for linking under OSF/1: -#LINKFLAGS = -non_shared -T 0x20000000 -N +LINKFLAGS = -non_shared -T 0x20000000 -N +else # enable this for linking under Linux: LINKFLAGS = -static -T bootloader.lds -N +endif .S.s: $(CC) -D__ASSEMBLY__ -traditional -E -o $*.o $< diff -u --recursive --new-file v1.3.33/linux/arch/alpha/config.in linux/arch/alpha/config.in --- v1.3.33/linux/arch/alpha/config.in Tue Oct 10 18:46:30 1995 +++ linux/arch/alpha/config.in Fri Oct 13 10:57:51 1995 @@ -5,6 +5,12 @@ comment 'General setup' +if [ "`uname`" != "Linux" ]; then + define_bool CONFIG_CROSSCOMPILE y +else + define_bool CONFIG_NATIVE y +fi + tristate 'Normal floppy disk support' CONFIG_BLK_DEV_FD y bool 'Normal (MFM/RLL) disk and IDE disk/cdrom support' CONFIG_ST506 y if [ "$CONFIG_ST506" = "y" ]; then diff -u --recursive --new-file v1.3.33/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S --- v1.3.33/linux/arch/alpha/kernel/entry.S Fri Oct 6 14:35:13 1995 +++ linux/arch/alpha/kernel/entry.S Fri Oct 13 07:34:36 1995 @@ -190,7 +190,6 @@ * stack buildup, as we can't do system calls from kernel space. */ .align 3 -.globl kernel_clone .ent kernel_clone kernel_clone: subq $30,6*8,$30 @@ -207,6 +206,36 @@ stq $0,0($30) br ret_from_sys_call .end kernel_clone + +/* + * __kernel_thread(clone_flags, fn, arg) + */ +.align 3 +.globl __kernel_thread +.ent __kernel_thread +__kernel_thread: + subq $30,4*8,$30 + stq $9,0($30) + stq $10,8($30) + stq $26,16($30) + bis $17,$17,$9 /* save fn */ + bis $18,$18,$10 /* save arg */ + bsr $26,kernel_clone + bne $20,1f /* $20 is non-zero in child */ + ldq $9,0($30) + ldq $10,8($30) + ldq $26,16($30) + addq $30,4*8,$30 + ret $31,($26),1 +/* this is in child: look out as we don't have any stack here.. */ +1: bis $9,$9,$27 /* get fn */ + bis $10,$10,$16 /* get arg */ + jsr $26,($27) + bis $0,$0,$16 + lda $27,sys_exit + jsr $26,($27),sys_exit + call_pal PAL_halt +.end __kernel_thread .align 3 .ent do_switch_stack diff -u --recursive --new-file v1.3.33/linux/arch/i386/config.in linux/arch/i386/config.in --- v1.3.33/linux/arch/i386/config.in Tue Oct 10 18:46:31 1995 +++ linux/arch/i386/config.in Wed Oct 11 08:14:17 1995 @@ -302,11 +302,6 @@ fi fi -bool 'QIC-117 tape support' CONFIG_FTAPE n -if [ "$CONFIG_FTAPE" = "y" ]; then - int ' number of ftape buffers' NR_FTAPE_BUFFERS 3 -fi - comment 'Sound' tristate 'Sound card support' CONFIG_SOUND n diff -u --recursive --new-file v1.3.33/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c --- v1.3.33/linux/arch/i386/mm/init.c Wed Oct 4 14:14:29 1995 +++ linux/arch/i386/mm/init.c Wed Oct 11 12:43:20 1995 @@ -22,7 +22,6 @@ #include extern void scsi_mem_init(unsigned long); -extern void sound_mem_init(void); extern void die_if_kernel(char *,struct pt_regs *,long); extern void show_net_buffers(void); @@ -230,9 +229,6 @@ } #ifdef CONFIG_SCSI scsi_mem_init(high_memory); -#endif -#ifdef CONFIG_SOUND - sound_mem_init(); #endif for (tmp = 0 ; tmp < high_memory ; tmp += PAGE_SIZE) { if (mem_map[MAP_NR(tmp)].reserved) { diff -u --recursive --new-file v1.3.33/linux/drivers/Makefile linux/drivers/Makefile --- v1.3.33/linux/drivers/Makefile Mon Sep 18 14:53:48 1995 +++ linux/drivers/Makefile Wed Oct 11 14:08:58 1995 @@ -15,14 +15,20 @@ SUB_DIRS += pci endif -ifdef CONFIG_SCSI +ifeq ($(CONFIG_SCSI),y) SUB_DIRS += scsi -MOD_SUB_DIRS += scsi +else + ifeq ($(CONFIG_SCSI),m) + MOD_SUB_DIRS += scsi + endif endif -ifdef CONFIG_SOUND +ifeq ($(CONFIG_SOUND),y) SUB_DIRS += sound -MOD_SUB_DIRS += sound +else + ifeq ($(CONFIG_SOUND),m) + MOD_SUB_DIRS += sound + endif endif include $(TOPDIR)/Rules.make diff -u --recursive --new-file v1.3.33/linux/drivers/block/README.fd linux/drivers/block/README.fd --- v1.3.33/linux/drivers/block/README.fd Thu Feb 9 18:29:53 1995 +++ linux/drivers/block/README.fd Wed Oct 11 13:06:45 1995 @@ -32,15 +32,10 @@ The floppy related options include: floppy=,allowed_drive_mask - Sets the bitmask of allowed drives to . By default, only units - 0 and 1 of each floppy controller are allowed. This is done because - certain non-standard hardware (ASUS PCI motherboards) mess up the - keyboard when accessing units 2 or 3. This option is somewhat - obsoleted by the cmos option. + Obsolete. Use the floppy=,,cmos option instead floppy=all_drives - Sets the bitmask of allowed drives to all drives. Use this if you have - more than two drives connected to a floppy controller. + Obsolete. Use the floppy=,,cmos option instead floppy=asus_pci Sets the bitmask to allow only units 0 and 1. (The default) @@ -60,8 +55,9 @@ floppy=two_fdc floppy=
,two_fdc Tells the floppy driver that you have two floppy controllers. The - second floppy controller is assumed to be at
. If
- is not given, 0x370 is assumed. + second floppy controller is assumed to be at
. This + option is not needed if the second controller is at address + 0x370, and if you use the 'cmos' option floppy=thinkpad Tells the floppy driver that you have a Thinkpad. Thinkpads use an @@ -71,10 +67,10 @@ Tells the floppy driver that you don't have a Thinkpad. floppy=,,cmos - Sets the cmos type of to . Additionally, this drive is - allowed in the bitmask. This is useful if you have more than two - floppy drives (only two can be described in the physical cmos), or if - your BIOS uses non-standard CMOS types. The CMOS types are: + Sets the cmos type of to . This is mandatory if + you have more than two floppy drives (only two can be + described in the physical cmos), or if your BIOS uses + non-standard CMOS types. The CMOS types are: 0 - unknown or not installed 1 - 5 1/4 DD 2 - 5 1/4 HD @@ -110,9 +106,9 @@ allows to access high capacity disks (up to 1992K on a high density 3 1/2 disk!). It also contains additional documentation about the floppy driver. It can be found at: - ftp.imag.fr:pub/Linux/ZLIBC/fdutils/fdutils-4.0.src.tar.gz - sunsite.unc.edu:/pub/Linux/system/Misc/fdutils-4.0.src.tar.gz - tsx-11.mit.edu:/pub/linux/sources/sbin/fdutils-4.0.src.tar.gz + ftp.imag.fr:pub/Linux/ZLIBC/fdutils/fdutils-4.1.src.tar.gz + sunsite.unc.edu:/pub/Linux/system/Misc/fdutils-4.1.src.tar.gz + tsx-11.mit.edu:/pub/linux/sources/sbin/fdutils-4.1.src.tar.gz Alpha patches to these utilities are at: ftp.imag.fr:pub/Linux/ZLIBC/fdutils/ALPHA diff -u --recursive --new-file v1.3.33/linux/drivers/block/blk.h linux/drivers/block/blk.h --- v1.3.33/linux/drivers/block/blk.h Tue Oct 10 18:46:31 1995 +++ linux/drivers/block/blk.h Fri Oct 13 11:03:11 1995 @@ -363,7 +363,6 @@ req->bh = bh->b_reqnext; bh->b_reqnext = NULL; bh->b_uptodate = uptodate; - if (!uptodate) bh->b_req = 0; /* So no "Weird" errors */ unlock_buffer(bh); if ((bh = req->bh) != NULL) { req->current_nr_sectors = bh->b_size >> 9; diff -u --recursive --new-file v1.3.33/linux/drivers/block/floppy.c linux/drivers/block/floppy.c --- v1.3.33/linux/drivers/block/floppy.c Wed Sep 27 15:59:57 1995 +++ linux/drivers/block/floppy.c Fri Oct 13 10:58:24 1995 @@ -77,7 +77,7 @@ * format bug fixes, but unfortunately some new bugs too... */ -/* 1994/9/17 -- Koen Holtman -- added logging of physical floppy write +/* 1994/9/17 -- Koen Holtman -- added logging of physical floppy write * errors to allow safe writing by specialized programs. */ @@ -141,6 +141,77 @@ #include #define FDPATCHES #include + +/* ============================================ * + * old fd.h * + * =========================================== */ + +#define OLDFDCLRPRM 0 /* clear user-defined parameters */ +#define OLDFDSETPRM 1 /* set user-defined parameters for current media */ +#define OLDFDSETMEDIAPRM 1 +#define OLDFDDEFPRM 2 /* set user-defined parameters until explicitly cleared */ +#define OLDFDDEFMEDIAPRM 2 +#define OLDFDGETPRM 3 /* get disk parameters */ +#define OLDFDGETMEDIAPRM 3 +#define OLDFDMSGON 4 /* issue kernel messages on media type change */ +#define OLDFDMSGOFF 5 /* don't issue kernel messages on media type change */ +#define OLDFDFMTBEG 6 /* begin formatting a disk */ +#define OLDFDFMTTRK 7 /* format the specified track */ +#define OLDFDFMTEND 8 /* end formatting a disk */ +#define OLDFDSETEMSGTRESH 10 /* set fdc error reporting threshold */ +#define OLDFDFLUSH 11 /* flush buffers for media; either for verifying media, or for + handling a media change without closing the file + descriptor */ +#define OLDFDSETMAXERRS 12 /* set abortion and read_track threshold */ +#define OLDFDGETMAXERRS 14 /* get abortion and read_track threshold */ +#define OLDFDGETDRVTYP 16 /* get drive type: 5 1/4 or 3 1/2 */ + +#define OLDFDSETDRVPRM 20 /* set drive parameters */ +#define OLDFDGETDRVPRM 21 /* get drive parameters */ +#define OLDFDGETDRVSTAT 22 /* get drive state */ +#define OLDFDPOLLDRVSTAT 23 /* get drive state */ +#define OLDFDRESET 24 /* reset FDC */ + +#define OLDFD_RESET_IF_NEEDED 0 +#define OLDFD_RESET_IF_RAWCMD 1 +#define OLDFD_RESET_ALWAYS 2 + +#define OLDFDGETFDCSTAT 25 /* get fdc state */ +#define OLDFDWERRORCLR 27 /* clear write error and badness information */ +#define OLDFDWERRORGET 28 /* get write error and badness information */ + +#define OLDFDRAWCMD 30 /* send a raw command to the fdc */ + +#define OLDFDTWADDLE 40 /* flicker motor-on bit before reading a sector */ + +struct old_floppy_raw_cmd { + void *data; + long length; + + unsigned char rate; + unsigned char flags; + unsigned char cmd_count; + unsigned char cmd[9]; + unsigned char reply_count; + unsigned char reply[7]; + int track; +}; + +struct old_floppy_fdc_state { + int spec1; /* spec1 value last used */ + int spec2; /* spec2 value last used */ + int dtr; + unsigned char version; /* FDC version code */ + unsigned char dor; + int address; /* io address */ + unsigned int rawcmd:2; + unsigned int reset:1; + unsigned int need_configure:1; + unsigned int perp_mode:2; + unsigned int has_fifo:1; +}; + + #include #include #include @@ -171,11 +242,11 @@ #ifdef _ASM_IO_H2 __asm__ __volatile__("bsr %1,%0" : "=r" (order) - : "r" (size / PAGE_SIZE) ); + : "r" (size / PAGE_SIZE) ); #else for (order = 0; order < NR_MEM_LISTS; ++order) if (size <= (PAGE_SIZE << order)) - return order; + return order; #endif return NR_MEM_LISTS; } @@ -183,7 +254,7 @@ static unsigned long dma_mem_alloc(int size) { int order = __get_order(size); - + if (order >= NR_MEM_LISTS) return(0); return __get_dma_pages(GFP_KERNEL,order); @@ -208,12 +279,6 @@ #define N_FDC 2 #define N_DRIVE 8 -static inline int ITYPE(int x) { - return (x>>2) & 0x1f; -} -static inline int XTYPE(int x) { /* called with a fd_device field as arg */ - return ITYPE(x); -} static inline int TYPE(kdev_t x) { return (MINOR(x)>>2) & 0x1f; } @@ -243,35 +308,32 @@ #define DPRINT(x) printk(DEVICE_NAME "%d: " x,current_drive) -#define DPRINT1(x,x1) \ -printk(DEVICE_NAME "%d: " x,current_drive,(x1)) +#define DPRINT1(x,x1) printk(DEVICE_NAME "%d: " x,current_drive,(x1)) -#define DPRINT2(x,x1,x2) \ -printk(DEVICE_NAME "%d: " x,current_drive,(x1),(x2)) +#define DPRINT2(x,x1,x2) printk(DEVICE_NAME "%d: " x,current_drive,(x1),(x2)) -#define DPRINT3(x,x1,x2,x3) \ -printk(DEVICE_NAME "%d: " x,current_drive,(x1),(x2),(x3)) +#define DPRINT3(x,x1,x2,x3) printk(DEVICE_NAME "%d: " x,current_drive,(x1),(x2),(x3)) #define PH_HEAD(floppy,head) (((((floppy)->stretch & 2) >>1) ^ head) << 2) #define STRETCH(floppy) ((floppy)->stretch & FD_STRETCH) /* read/write */ -#define COMMAND raw_cmd.cmd[0] -#define DR_SELECT raw_cmd.cmd[1] -#define TRACK raw_cmd.cmd[2] -#define HEAD raw_cmd.cmd[3] -#define SECTOR raw_cmd.cmd[4] -#define SIZECODE raw_cmd.cmd[5] -#define SECT_PER_TRACK raw_cmd.cmd[6] -#define GAP raw_cmd.cmd[7] -#define SIZECODE2 raw_cmd.cmd[8] +#define COMMAND raw_cmd->cmd[0] +#define DR_SELECT raw_cmd->cmd[1] +#define TRACK raw_cmd->cmd[2] +#define HEAD raw_cmd->cmd[3] +#define SECTOR raw_cmd->cmd[4] +#define SIZECODE raw_cmd->cmd[5] +#define SECT_PER_TRACK raw_cmd->cmd[6] +#define GAP raw_cmd->cmd[7] +#define SIZECODE2 raw_cmd->cmd[8] #define NR_RW 9 /* format */ -#define F_SIZECODE raw_cmd.cmd[2] -#define F_SECT_PER_TRACK raw_cmd.cmd[3] -#define F_GAP raw_cmd.cmd[4] -#define F_FILL raw_cmd.cmd[5] +#define F_SIZECODE raw_cmd->cmd[2] +#define F_SECT_PER_TRACK raw_cmd->cmd[3] +#define F_GAP raw_cmd->cmd[4] +#define F_FILL raw_cmd->cmd[5] #define NR_F 6 /* @@ -295,8 +357,7 @@ #ifdef __alpha__ # define CROSS_64KB(a,s) (0) #else -# define CROSS_64KB(a,s) \ - ((unsigned long)(a)/K_64 != ((unsigned long)(a) + (s) - 1) / K_64) +# define CROSS_64KB(a,s) ((unsigned long)(a)/K_64 != ((unsigned long)(a) + (s) - 1) / K_64) #endif /* @@ -359,16 +420,16 @@ {{6, 1000, 15, 8, 3000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5, 83, 3*HZ, 40, {3,1,2,0,2}, 0, 0, { 7, 8, 4,25,28,22,31,21}, 3*HZ/2, 8 }, "2.88M" } /*3 1/2 ED*/ -/* | ---autodetected formats-- | | | - read_track | | Name printed when booting - | Native format - Frequency of disk change checks */ +/* | --autodetected formats--- | | | + * read_track | | Name printed when booting + * | Native format + * Frequency of disk change checks */ }; static struct floppy_drive_params drive_params[N_DRIVE]; static struct floppy_drive_struct drive_state[N_DRIVE]; static struct floppy_write_errors write_errors[N_DRIVE]; -static struct floppy_raw_cmd raw_cmd; +static struct floppy_raw_cmd *raw_cmd, default_raw_cmd; /* * This struct defines the different floppy types. @@ -456,7 +517,8 @@ static volatile int command_status = FD_COMMAND_NONE, fdc_busy = 0; static struct wait_queue *fdc_wait = NULL, *command_done = NULL; #define NO_SIGNAL (!(current->signal & ~current->blocked) || !interruptible) -#define CALL(x) if( (x) == -EINTR) return -EINTR; +#define CALL(x) if( (x) == -EINTR) return -EINTR +#define ECALL(x) if((ret = (x))) return ret; #define _WAIT(x,i) CALL(ret=wait_til_done((x),i)) #define WAIT(x) _WAIT((x),interruptible) #define IWAIT(x) _WAIT((x),1) @@ -486,11 +548,12 @@ int *errors; typedef void (*done_f)(int); struct cont_t { -void (*interrupt)(void); /* this is called after the interrupt of the - * main command */ -void (*redo)(void); /* this is called to retry the operation */ -void (*error)(void); /* this is called to tally an error */ -done_f done; /* this is called to say if the operation has succeeded/failed */ + void (*interrupt)(void); /* this is called after the interrupt of the + * main command */ + void (*redo)(void); /* this is called to retry the operation */ + void (*error)(void); /* this is called to tally an error */ + done_f done; /* this is called to say if the operation has + * succeeded/failed */ } *cont=NULL; static void floppy_ready(void); @@ -538,7 +601,6 @@ static struct floppy_struct * floppy = floppy_type; static unsigned char current_drive = 0; static long current_count_sectors = 0; -static char *current_addr = 0; static unsigned char sector_t; /* sector in track */ #ifdef DEBUGT @@ -559,14 +621,14 @@ static inline void debugt(const char *message) { #ifdef DEBUGT - if ( DP->flags & DEBUGT ) - printk("%s dtime=%lu\n", message, jiffies-debugtimer ); + if ( DP->flags & DEBUGT ) + printk("%s dtime=%lu\n", message, jiffies-debugtimer ); #endif } typedef void (*timeout_fn)(unsigned long); -static struct timer_list fd_timeout ={ NULL, NULL, 0, 0, - (timeout_fn) floppy_shutdown }; +static struct timer_list fd_timeout ={ NULL, NULL, 0, 0, + (timeout_fn) floppy_shutdown }; static const char *timeout_message; @@ -795,8 +857,6 @@ return -1; } floppy_grab_irq_and_dma(); - if (!current->pid) - run_task_queue(&tq_timer); cli(); while (fdc_busy && NO_SIGNAL) interruptible_sleep_on(&fdc_wait); @@ -819,6 +879,7 @@ /* unlocks the driver */ static inline void unlock_fdc(void) { + raw_cmd = 0; if (!fdc_busy) DPRINT("FDC access conflict!\n"); @@ -882,7 +943,7 @@ static void scandrives(void) { int i, drive, saved_drive; - + if (DP->select_delay) return; @@ -916,7 +977,7 @@ if ( disk_change(current_drive) ){ DPRINT("disk removed during i/o\n"); floppy_shutdown(); - } else { + } else { del_timer(&fd_timer); fd_timer.function = (timeout_fn) fd_watchdog; fd_timer.expires = jiffies + HZ / 10; @@ -978,30 +1039,33 @@ } restore_flags(flags); } - + static void setup_DMA(void) { #ifdef CONFIG_FLOPPY_SANITY - if (raw_cmd.length == 0){ + if (raw_cmd->length == 0){ int i; printk("zero dma transfer size:"); - for(i=0; i< raw_cmd.cmd_count; i++) - printk("%x,", raw_cmd.cmd[i]); + for(i=0; i< raw_cmd->cmd_count; i++) + printk("%x,", raw_cmd->cmd[i]); printk("\n"); cont->done(0); FDCS->reset = 1; return; } +#if 0 + /* disabled because of new buffer location for raw cmd */ if ((!CURRENT || - CURRENT->buffer != current_addr || - raw_cmd.length > 512 * CURRENT->nr_sectors) && - (current_addr < floppy_track_buffer || - current_addr + raw_cmd.length > + CURRENT->buffer != raw_cmd->kernel_data || + raw_cmd->length > 512 * CURRENT->nr_sectors) && + (raw_cmd->kernel_data < floppy_track_buffer || + raw_cmd->kernel_data + raw_cmd->length > floppy_track_buffer + 1024 * max_buffer_sectors)){ printk("bad address. start=%p lg=%lx tb=%p\n", - current_addr, raw_cmd.length, floppy_track_buffer); + raw_cmd->kernel_data, raw_cmd->length, + floppy_track_buffer); if ( CURRENT ){ printk("buffer=%p nr=%lx cnr=%lx\n", CURRENT->buffer, CURRENT->nr_sectors, @@ -1011,15 +1075,17 @@ FDCS->reset=1; return; } - if ((long) current_addr % 512 ){ - printk("non aligned address: %p\n", current_addr ); +#endif + if ((long) raw_cmd->kernel_data % 512 ){ + printk("non aligned address: %p\n", raw_cmd->kernel_data ); cont->done(0); FDCS->reset=1; return; } - if (CROSS_64KB(current_addr, raw_cmd.length)) { + if (CROSS_64KB(raw_cmd->kernel_data, raw_cmd->length)) { printk("DMA crossing 64-K boundary %p-%p\n", - current_addr, current_addr + raw_cmd.length); + raw_cmd->kernel_data, + raw_cmd->kernel_data + raw_cmd->length); cont->done(0); FDCS->reset=1; return; @@ -1029,10 +1095,10 @@ disable_dma(FLOPPY_DMA); clear_dma_ff(FLOPPY_DMA); set_dma_mode(FLOPPY_DMA, - (raw_cmd.flags & FD_RAW_READ)? + (raw_cmd->flags & FD_RAW_READ)? DMA_MODE_READ : DMA_MODE_WRITE); - set_dma_addr(FLOPPY_DMA, virt_to_bus(current_addr)); - set_dma_count(FLOPPY_DMA, raw_cmd.length); + set_dma_addr(FLOPPY_DMA, virt_to_bus(raw_cmd->kernel_data)); + set_dma_count(FLOPPY_DMA, raw_cmd->length); enable_dma(FLOPPY_DMA); sti(); floppy_disable_hlt(); @@ -1042,13 +1108,13 @@ static int output_byte(char byte) { int counter; - unsigned char status = 0; /* keep gcc quiet */ + unsigned char status = 0; unsigned char rstatus; if (FDCS->reset) return -1; for(counter = 0 ; counter < 10000 && !FDCS->reset ; counter++) { - rstatus = inb_p(FD_STATUS); + rstatus = inb_p(FD_STATUS); status = rstatus &(STATUS_READY|STATUS_DIR|STATUS_DMA); if (!(status & STATUS_READY)) continue; @@ -1119,24 +1185,24 @@ if (!floppy) return; if (floppy->rate & 0x40){ - switch(raw_cmd.rate){ - case 0: - perp_mode=2; - break; - case 3: - perp_mode=3; - break; - default: - DPRINT("Invalid data rate for perpendicular mode!\n"); - cont->done(0); - FDCS->reset = 1; /* convenient way to return to - * redo without to much hassle (deep - * stack et al. */ - return; + switch(raw_cmd->rate){ + case 0: + perp_mode=2; + break; + case 3: + perp_mode=3; + break; + default: + DPRINT("Invalid data rate for perpendicular mode!\n"); + cont->done(0); + FDCS->reset = 1; /* convenient way to return to + * redo without to much hassle (deep + * stack et al. */ + return; } } else perp_mode = 0; - + if ( FDCS->perp_mode == perp_mode ) return; if (FDCS->version >= FDC_82077_ORIG && FDCS->has_fifo) { @@ -1195,16 +1261,16 @@ /*DPRINT("FIFO enabled\n");*/ } - switch (raw_cmd.rate & 0x03) { - case 3: - dtr = 1000; - break; - case 1: - dtr = 300; - break; - case 2: - dtr = 250; - break; + switch (raw_cmd->rate & 0x03) { + case 3: + dtr = 1000; + break; + case 1: + dtr = 300; + break; + case 2: + dtr = 250; + break; } if (FDCS->version >= FDC_82072) { @@ -1251,18 +1317,18 @@ static int fdc_dtr(void) { /* If data rate not already set to desired value, set it. */ - if ( raw_cmd.rate == FDCS->dtr) + if ( raw_cmd->rate == FDCS->dtr) return 0; - + /* Set dtr */ - outb_p(raw_cmd.rate, FD_DCR); - + outb_p(raw_cmd->rate, FD_DCR); + /* TODO: some FDC/drive combinations (C&T 82C711 with TEAC 1.2MB) * need a stabilization period of several milliseconds to be * enforced after data rate changes before R/W operations. * Pause 5 msec to avoid trouble. (Needs to be 2 jiffies) */ - FDCS->dtr = raw_cmd.rate; + FDCS->dtr = raw_cmd->rate; return(wait_for_completion(jiffies+2*HZ/100, (timeout_fn) floppy_ready)); } /* fdc_dtr */ @@ -1292,8 +1358,8 @@ } /* check IC to find cause of interrupt */ - switch ((ST0 & ST0_INTR)>>6) { - case 1: /* error occurred during command execution */ + switch (ST0 & ST0_INTR) { + case 0x40: /* error occurred during command execution */ bad = 1; if (ST1 & ST1_WP) { DPRINT("Drive is write protected\n"); @@ -1337,11 +1403,11 @@ /* wrong cylinder => recal */ DRS->track = NEED_2_RECAL; return bad; - case 2: /* invalid command given */ + case 0x80: /* invalid command given */ DPRINT("Invalid FDC command given!\n"); cont->done(0); return 2; - case 3: + case 0xc0: DPRINT("Abnormal termination caused by polling\n"); cont->error(); return 2; @@ -1360,12 +1426,12 @@ int i,ready_date,r, flags,dflags; timeout_fn function; - flags = raw_cmd.flags; + flags = raw_cmd->flags; if ( flags & ( FD_RAW_READ | FD_RAW_WRITE)) flags |= FD_RAW_INTR; if ((flags & FD_RAW_SPIN) && !(flags & FD_RAW_NO_MOTOR)){ - ready_date = DRS->spinup_date + DP->spinup; + ready_date = DRS->spinup_date + DP->spinup; /* If spinup will take a long time, rerun scandrives * again just before spinup completion. Beware that * after scandrives, we must again wait for selection. @@ -1384,13 +1450,13 @@ if ( (flags & FD_RAW_READ) || (flags & FD_RAW_WRITE)) setup_DMA(); - + if ( flags & FD_RAW_INTR ) SET_INTR(main_command_interrupt); r=0; - for(i=0; i< raw_cmd.cmd_count; i++) - r|=output_byte( raw_cmd.cmd[i] ); + for(i=0; i< raw_cmd->cmd_count; i++) + r|=output_byte( raw_cmd->cmd[i] ); #ifdef DEBUGT debugt("rw_command: "); @@ -1478,7 +1544,7 @@ if (!TESTF(FD_DISK_NEWCHANGE) && disk_change(current_drive) && - (raw_cmd.flags & FD_RAW_NEED_DISK)){ + (raw_cmd->flags & FD_RAW_NEED_DISK)){ /* the media changed flag should be cleared after the seek. * If it isn't, this means that there is really no disk in * the drive. @@ -1492,25 +1558,25 @@ recalibrate_floppy(); return; } else if (TESTF(FD_DISK_NEWCHANGE) && - (raw_cmd.flags & FD_RAW_NEED_DISK) && - (DRS->track <= NO_TRACK || DRS->track == raw_cmd.track)) { + (raw_cmd->flags & FD_RAW_NEED_DISK) && + (DRS->track <= NO_TRACK || DRS->track == raw_cmd->track)) { /* we seek to clear the media-changed condition. Does anybody * know a more elegant way, which works on all drives? */ - if ( raw_cmd.track ) - track = raw_cmd.track - 1; + if ( raw_cmd->track ) + track = raw_cmd->track - 1; else { if(DP->flags & FD_SILENT_DCL_CLEAR){ set_dor(fdc, ~(0x10 << UNIT(current_drive)), 0); blind_seek = 1; - raw_cmd.flags |= FD_RAW_NEED_SEEK; + raw_cmd->flags |= FD_RAW_NEED_SEEK; } track = 1; } } else { check_wp(); - if (raw_cmd.track != DRS->track && - (raw_cmd.flags & FD_RAW_NEED_SEEK)) - track = raw_cmd.track; + if (raw_cmd->track != DRS->track && + (raw_cmd->flags & FD_RAW_NEED_SEEK)) + track = raw_cmd->track; else { setup_rw_floppy(); return; @@ -1535,46 +1601,48 @@ FDCS->reset = 1; else if (ST0 & ST0_ECE) { switch(DRS->track){ - case NEED_1_RECAL: + case NEED_1_RECAL: #ifdef DEBUGT - debugt("recal interrupt need 1 recal:"); + debugt("recal interrupt need 1 recal:"); #endif - /* after a second recalibrate, we still haven't - * reached track 0. Probably no drive. Raise an - * error, as failing immediately might upset - * computers possessed by the Devil :-) */ - cont->error(); - cont->redo(); - return; - case NEED_2_RECAL: + /* after a second recalibrate, we still haven't + * reached track 0. Probably no drive. Raise an + * error, as failing immediately might upset + * computers possessed by the Devil :-) */ + cont->error(); + cont->redo(); + return; + case NEED_2_RECAL: #ifdef DEBUGT - debugt("recal interrupt need 2 recal:"); + debugt("recal interrupt need 2 recal:"); #endif - /* If we already did a recalibrate, and we are not at - * track 0, this means we have moved. (The only way - * not to move at recalibration is to be already at - * track 0.) Clear the new change flag - */ + /* If we already did a recalibrate, + * and we are not at track 0, this + * means we have moved. (The only way + * not to move at recalibration is to + * be already at track 0.) Clear the + * new change flag */ #ifdef DCL_DEBUG - if (DP->flags & FD_DEBUG){ - DPRINT("clearing NEWCHANGE flag because of second recalibrate\n"); - } + if (DP->flags & FD_DEBUG){ + DPRINT("clearing NEWCHANGE flag because of second recalibrate\n"); + } #endif - CLEARF(FD_DISK_NEWCHANGE); - DRS->select_date = jiffies; - /* fall through */ - default: + CLEARF(FD_DISK_NEWCHANGE); + DRS->select_date = jiffies; + /* fall through */ + default: #ifdef DEBUGT - debugt("recal interrupt default:"); + debugt("recal interrupt default:"); #endif - /* Recalibrate moves the head by at most 80 steps. If - * after one recalibrate we don't have reached track - * 0, this might mean that we started beyond track 80. - * Try again. - */ - DRS->track = NEED_1_RECAL; - break; + /* Recalibrate moves the head by at + * most 80 steps. If after one + * recalibrate we don't have reached + * track 0, this might mean that we + * started beyond track 80. Try + * again. */ + DRS->track = NEED_1_RECAL; + break; } } else DRS->track = ST1; @@ -1610,7 +1678,7 @@ FDCS->reset = 1; } -struct tq_struct floppy_tq = +struct tq_struct floppy_tq = { 0, 0, (void *) (void *) unexpected_floppy_interrupt, 0 }; /* interrupt handler */ @@ -1666,7 +1734,7 @@ #ifdef DEBUGT debugt("reset interrupt:"); #endif - fdc_specify(); /* reprogram fdc */ + /* fdc_specify(); reprogram fdc */ result(); /* get the status ready for set_fdc */ if ( FDCS->reset ) cont->error(); /* a reset just after a reset. BAD! */ @@ -1702,7 +1770,7 @@ printk("\n"); printk("floppy driver state\n"); printk("-------------------\n"); - printk("now=%ld last interrupt=%d last called handler=%p\n", + printk("now=%ld last interrupt=%d last called handler=%p\n", jiffies, interruptjiffies, lasthandler); @@ -1710,7 +1778,7 @@ printk("timeout_message=%s\n", timeout_message); printk("last output bytes:\n"); for(i=0; i < OLOGSIZE; i++) - printk("%2x %2x %ld\n", + printk("%2x %2x %ld\n", output_log[(i+output_log_pos) % OLOGSIZE].data, output_log[(i+output_log_pos) % OLOGSIZE].status, output_log[(i+output_log_pos) % OLOGSIZE].jiffies); @@ -1757,6 +1825,7 @@ CLEAR_INTR; floppy_tq.routine = (void *)(void *) empty; del_timer( &fd_timer); + sti(); floppy_enable_hlt(); disable_dma(FLOPPY_DMA); @@ -1783,7 +1852,7 @@ mask = 0xfc; data = UNIT(current_drive); - if (!(raw_cmd.flags & FD_RAW_NO_MOTOR)){ + if (!(raw_cmd->flags & FD_RAW_NO_MOTOR)){ if(!(FDCS->dor & ( 0x10 << UNIT(current_drive) ) )){ set_debugt(); /* no read since this drive is running */ @@ -1817,13 +1886,13 @@ } #endif - if(!(raw_cmd.flags & FD_RAW_NO_MOTOR) && + if(!(raw_cmd->flags & FD_RAW_NO_MOTOR) && disk_change(current_drive) && !DP->select_delay) twaddle(); /* this clears the dcl on certain drive/controller * combinations */ - if ( raw_cmd.flags & (FD_RAW_NEED_SEEK | FD_RAW_NEED_DISK)){ + if ( raw_cmd->flags & (FD_RAW_NEED_SEEK | FD_RAW_NEED_DISK)){ perpendicular_mode(); fdc_specify(); /* must be done here because of hut, hlt ... */ seek_floppy(); @@ -1837,9 +1906,9 @@ scandrives(); #ifdef DCL_DEBUG - if (DP->flags & FD_DEBUG){ - DPRINT("setting NEWCHANGE in floppy_start\n"); - } + if (DP->flags & FD_DEBUG){ + DPRINT("setting NEWCHANGE in floppy_start\n"); + } #endif SETF(FD_DISK_NEWCHANGE); floppy_ready(); @@ -1874,7 +1943,7 @@ (done_f)empty }; -static int wait_til_done( void (*handler)(void ), int interruptible ) +static int wait_til_done(void (*handler)(void ), int interruptible) { int ret; @@ -1883,18 +1952,15 @@ cli(); while(command_status < 2 && NO_SIGNAL){ - is_alive("wait_til_done"); - if (current->pid) + is_alive("wait_til_done"); + if(interruptible) interruptible_sleep_on(&command_done); - else { - sti(); - run_task_queue(&tq_timer); - cli(); - } + else + sleep_on(&command_done); } if(command_status < 2){ - sti(); floppy_shutdown(); + sti(); process_fd_request(); return -EINTR; } @@ -1918,25 +1984,20 @@ static void generic_success(void) { - generic_done(1); + cont->done(1); } static void generic_failure(void) { - generic_done(0); + cont->done(0); } static void success_and_wakeup(void) { generic_success(); - do_wakeup(); + cont->redo(); } -static void failure_and_wakeup(void) -{ - generic_failure(); - do_wakeup(); -} /* * formatting and rw support. @@ -1950,7 +2011,7 @@ probed_format = DRS->probed_format; while(1){ if ( probed_format >= 8 || - ! DP->autodetect[probed_format] ){ + ! DP->autodetect[probed_format] ){ DRS->probed_format = 0; return 1; } @@ -1995,12 +2056,12 @@ static void format_interrupt(void) { switch (interpret_errors()){ - case 1: - cont->error(); - case 2: - break; - case 0: - cont->done(1); + case 1: + cont->error(); + case 2: + break; + case 0: + cont->done(1); } cont->redo(); } @@ -2008,7 +2069,7 @@ #define CODE2SIZE (ssize = ( ( 1 << SIZECODE ) + 3 ) >> 2) #define FM_MODE(x,y) ((y) & ~(((x)->rate & 0x80 ) >>1)) #define CT(x) ( (x) | 0x40 ) -static void setup_format_params(void) +static void setup_format_params(int track) { struct fparm { unsigned char track,head,sect,size; @@ -2016,10 +2077,13 @@ int il,n; int count,head_shift,track_shift; - raw_cmd.flags = FD_RAW_WRITE | FD_RAW_INTR | FD_RAW_SPIN | + raw_cmd = &default_raw_cmd; + raw_cmd->track = track; + + raw_cmd->flags = FD_RAW_WRITE | FD_RAW_INTR | FD_RAW_SPIN | /*FD_RAW_NEED_DISK |*/ FD_RAW_NEED_SEEK; - raw_cmd.rate = floppy->rate & 0x3; - raw_cmd.cmd_count = NR_F; + raw_cmd->rate = floppy->rate & 0x3; + raw_cmd->cmd_count = NR_F; COMMAND = FM_MODE(floppy,FD_FORMAT); DR_SELECT = UNIT(current_drive) + PH_HEAD(floppy,format_req.head); F_SIZECODE = FD_SIZECODE(floppy); @@ -2027,8 +2091,8 @@ F_GAP = floppy->fmt_gap; F_FILL = FD_FILL_BYTE; - current_addr = floppy_track_buffer; - raw_cmd.length = 4 * F_SECT_PER_TRACK; + raw_cmd->kernel_data = floppy_track_buffer; + raw_cmd->length = 4 * F_SECT_PER_TRACK; /* allow for about 30ms for data transport per track */ head_shift = (F_SECT_PER_TRACK + 5) / 6; @@ -2068,9 +2132,8 @@ static void redo_format(void) { - raw_cmd.track = format_req.track << STRETCH(floppy); buffer_track = -1; - setup_format_params(); + setup_format_params(format_req.track << STRETCH(floppy)); floppy_start(); #ifdef DEBUGT debugt("queue format request"); @@ -2128,7 +2191,7 @@ } if (uptodate){ /* maintain values for invalidation on geometry - change */ + * change */ block = current_count_sectors + CURRENT->sector; if (block > DRS->maxblock) DRS->maxblock=block; @@ -2182,12 +2245,12 @@ CODE2SIZE; nr_sectors = ((R_TRACK-TRACK)*floppy->head+R_HEAD-HEAD) * floppy->sect + ((R_SECTOR-SECTOR) << SIZECODE >> 2) - - (sector_t % floppy->sect) % ssize; + (sector_t % floppy->sect) % ssize; #ifdef CONFIG_FLOPPY_SANITY if ( nr_sectors > current_count_sectors + ssize - - (current_count_sectors + sector_t) % ssize + - sector_t % ssize){ + (current_count_sectors + sector_t) % ssize + + sector_t % ssize){ DPRINT2("long rw: %x instead of %lx\n", nr_sectors, current_count_sectors); printk("rs=%d s=%d\n", R_SECTOR, SECTOR); @@ -2203,24 +2266,24 @@ current_count_sectors = nr_sectors; switch (interpret_errors()){ - case 2: - cont->redo(); - return; - case 1: - if ( !current_count_sectors){ - cont->error(); + case 2: cont->redo(); return; - } - break; - case 0: - if ( !current_count_sectors){ - cont->redo(); - return; - } - current_type[current_drive] = floppy; - floppy_sizes[TOMINOR(current_drive)] = floppy->size >> 1; - break; + case 1: + if ( !current_count_sectors){ + cont->error(); + cont->redo(); + return; + } + break; + case 0: + if ( !current_count_sectors){ + cont->redo(); + return; + } + current_type[current_drive] = floppy; + floppy_sizes[TOMINOR(current_drive) ]= floppy->size>>1; + break; } if (probing) { @@ -2232,11 +2295,12 @@ probing = 0; } - if ( CT(COMMAND) != FD_READ || current_addr == CURRENT->buffer ){ + if ( CT(COMMAND) != FD_READ || + raw_cmd->kernel_data == CURRENT->buffer ){ /* transfer directly from buffer */ cont->done(1); } else if ( CT(COMMAND) == FD_READ){ - buffer_track = raw_cmd.track; + buffer_track = raw_cmd->track; buffer_drive = current_drive; if ( nr_sectors + sector_t > buffer_max ) buffer_max = nr_sectors + sector_t; @@ -2303,7 +2367,7 @@ } remaining = current_count_sectors << 9; #ifdef CONFIG_FLOPPY_SANITY - if ((remaining >> 9) > CURRENT->nr_sectors && + if ((remaining >> 9) > CURRENT->nr_sectors && CT(COMMAND) == FD_WRITE ){ DPRINT("in copy buffer\n"); printk("current_count_sectors=%ld\n", current_count_sectors); @@ -2392,14 +2456,15 @@ set_fdc(DRIVE(CURRENT->rq_dev)); - raw_cmd.flags = FD_RAW_SPIN | FD_RAW_NEED_DISK | FD_RAW_NEED_DISK | + raw_cmd = &default_raw_cmd; + raw_cmd->flags = FD_RAW_SPIN | FD_RAW_NEED_DISK | FD_RAW_NEED_DISK | FD_RAW_NEED_SEEK; - raw_cmd.cmd_count = NR_RW; + raw_cmd->cmd_count = NR_RW; if (CURRENT->cmd == READ){ - raw_cmd.flags |= FD_RAW_READ; + raw_cmd->flags |= FD_RAW_READ; COMMAND = FM_MODE(floppy,FD_READ); } else if (CURRENT->cmd == WRITE){ - raw_cmd.flags |= FD_RAW_WRITE; + raw_cmd->flags |= FD_RAW_WRITE; COMMAND = FM_MODE(floppy,FD_WRITE); } else { DPRINT("make_raw_rw_request: unknown command\n"); @@ -2414,7 +2479,7 @@ return 0; HEAD = sector_t / floppy->sect; - if (((floppy->stretch & FD_SWAPSIDES) || TESTF( FD_NEED_TWADDLE)) && + if (((floppy->stretch & FD_SWAPSIDES) || TESTF( FD_NEED_TWADDLE)) && sector_t < floppy->sect ) max_sector = floppy->sect; @@ -2430,17 +2495,17 @@ SIZECODE = 2; } else SIZECODE = FD_SIZECODE(floppy); - raw_cmd.rate = floppy->rate & 3; + raw_cmd->rate = floppy->rate & 3; if ((floppy->rate & FD_2M) && (TRACK || HEAD ) && - raw_cmd.rate == 2) - raw_cmd.rate = 1; + raw_cmd->rate == 2) + raw_cmd->rate = 1; if ( SIZECODE ) SIZECODE2 = 0xff; else SIZECODE2 = 0x80; - raw_cmd.track = TRACK << STRETCH(floppy); + raw_cmd->track = TRACK << STRETCH(floppy); DR_SELECT = UNIT(current_drive) + PH_HEAD(floppy,HEAD); GAP = floppy->gap; CODE2SIZE; @@ -2465,7 +2530,7 @@ aligned_sector_t = sector_t - ( sector_t % floppy->sect ) % ssize; max_size = CURRENT->nr_sectors; - if ((raw_cmd.track == buffer_track) && (current_drive == buffer_drive) && + if ((raw_cmd->track == buffer_track) && (current_drive == buffer_drive) && (sector_t >= buffer_min) && (sector_t < buffer_max)) { /* data already in track buffer */ if (CT(COMMAND) == FD_READ) { @@ -2480,8 +2545,8 @@ else max_size = ssize; } - raw_cmd.flags &= ~FD_RAW_WRITE; - raw_cmd.flags |= FD_RAW_READ; + raw_cmd->flags &= ~FD_RAW_WRITE; + raw_cmd->flags |= FD_RAW_READ; COMMAND = FM_MODE(floppy,FD_READ); } else if ((unsigned long)CURRENT->buffer < MAX_DMA_ADDRESS ) { int direct, indirect; @@ -2510,9 +2575,9 @@ ((!probing || (DP->read_track&(1<probed_format)))))){ max_size = CURRENT->nr_sectors; } else { - current_addr = CURRENT->buffer; - raw_cmd.length = current_count_sectors << 9; - if (raw_cmd.length == 0){ + raw_cmd->kernel_data = CURRENT->buffer; + raw_cmd->length = current_count_sectors << 9; + if (raw_cmd->length == 0){ DPRINT("zero dma transfer attempted from make_raw_request\n"); DPRINT3("indirect=%d direct=%d sector_t=%d", indirect, direct, sector_t); @@ -2526,7 +2591,7 @@ max_size = max_sector; /* unbounded */ /* claim buffer track if needed */ - if (buffer_track != raw_cmd.track || /* bad track */ + if (buffer_track != raw_cmd->track || /* bad track */ buffer_drive !=current_drive || /* bad drive */ sector_t > buffer_max || sector_t < buffer_min || @@ -2539,7 +2604,8 @@ buffer_drive = current_drive; buffer_max = buffer_min = aligned_sector_t; } - current_addr = floppy_track_buffer +((aligned_sector_t-buffer_min )<<9); + raw_cmd->kernel_data = floppy_track_buffer + + ((aligned_sector_t-buffer_min )<<9); if ( CT(COMMAND) == FD_WRITE ){ /* copy write buffer to track buffer. @@ -2550,7 +2616,7 @@ if (sector_t != aligned_sector_t && buffer_track == -1 ) DPRINT("internal error offset !=0 on write\n"); #endif - buffer_track = raw_cmd.track; + buffer_track = raw_cmd->track; buffer_drive = current_drive; copy_buffer(ssize, max_sector, 2*max_buffer_sectors+buffer_min); } else @@ -2558,22 +2624,23 @@ 2*max_buffer_sectors+buffer_min-aligned_sector_t); /* round up current_count_sectors to get dma xfer size */ - raw_cmd.length = sector_t+current_count_sectors-aligned_sector_t; - raw_cmd.length = ((raw_cmd.length -1)|(ssize-1))+1; - raw_cmd.length <<= 9; + raw_cmd->length = sector_t+current_count_sectors-aligned_sector_t; + raw_cmd->length = ((raw_cmd->length -1)|(ssize-1))+1; + raw_cmd->length <<= 9; #ifdef CONFIG_FLOPPY_SANITY - if ((raw_cmd.length < current_count_sectors << 9) || - (current_addr != CURRENT->buffer && + if ((raw_cmd->length < current_count_sectors << 9) || + (raw_cmd->kernel_data != CURRENT->buffer && CT(COMMAND) == FD_WRITE && - (aligned_sector_t + (raw_cmd.length >> 9) > buffer_max || + (aligned_sector_t + (raw_cmd->length >> 9) > buffer_max || aligned_sector_t < buffer_min )) || - raw_cmd.length % ( 128 << SIZECODE ) || - raw_cmd.length <= 0 || current_count_sectors <= 0){ + raw_cmd->length % ( 128 << SIZECODE ) || + raw_cmd->length <= 0 || current_count_sectors <= 0){ DPRINT2("fractionary current count b=%lx s=%lx\n", - raw_cmd.length, current_count_sectors); - if ( current_addr != CURRENT->buffer ) + raw_cmd->length, current_count_sectors); + if ( raw_cmd->kernel_data != CURRENT->buffer ) printk("addr=%d, length=%ld\n", - (int) ((current_addr - floppy_track_buffer ) >> 9), + (int) ((raw_cmd->kernel_data - + floppy_track_buffer ) >> 9), current_count_sectors); printk("st=%d ast=%d mse=%d msi=%d\n", sector_t, aligned_sector_t, max_sector, max_size); @@ -2587,16 +2654,16 @@ return 0; } - if (current_addr != CURRENT->buffer ){ - if (current_addr < floppy_track_buffer || + if (raw_cmd->kernel_data != CURRENT->buffer ){ + if (raw_cmd->kernel_data < floppy_track_buffer || current_count_sectors < 0 || - raw_cmd.length < 0 || - current_addr + raw_cmd.length > + raw_cmd->length < 0 || + raw_cmd->kernel_data + raw_cmd->length > floppy_track_buffer + (max_buffer_sectors << 10)){ DPRINT("buffer overrun in schedule dma\n"); printk("sector_t=%d buffer_min=%d current_count=%ld\n", sector_t, buffer_min, - raw_cmd.length >> 9 ); + raw_cmd->length >> 9 ); printk("current_count_sectors=%ld\n", current_count_sectors); if ( CT(COMMAND) == FD_READ ) @@ -2605,16 +2672,16 @@ printk("write\n"); return 0; } - } else if (raw_cmd.length > CURRENT->nr_sectors << 9 || + } else if (raw_cmd->length > CURRENT->nr_sectors << 9 || current_count_sectors > CURRENT->nr_sectors){ DPRINT("buffer overrun in direct transfer\n"); return 0; - } else if ( raw_cmd.length < current_count_sectors << 9 ){ + } else if ( raw_cmd->length < current_count_sectors << 9 ){ DPRINT("more sectors than bytes\n"); - printk("bytes=%ld\n", raw_cmd.length >> 9 ); + printk("bytes=%ld\n", raw_cmd->length >> 9 ); printk("sectors=%ld\n", current_count_sectors); } - if (raw_cmd.length == 0){ + if (raw_cmd->length == 0){ DPRINT("zero dma transfer attempted from make_raw_request\n"); return 0; } @@ -2627,9 +2694,6 @@ #define REPEAT {request_done(0); continue; } kdev_t device; int tmp; -#if 0 - kdev_t error = 0; -#endif lastredo = jiffies; if (current_drive < N_DRIVE) @@ -2650,20 +2714,14 @@ panic(DEVICE_NAME ": request list destroyed"); if (CURRENT->bh && !CURRENT->bh->b_lock) panic(DEVICE_NAME ": block not locked"); -#if 0 - if (!CURRENT->bh->b_count && - (CURRENT->errors || error == CURRENT->rq_dev)){ - error = CURRENT->rq_dev; - DPRINT("skipping read ahead buffer\n"); - REPEAT; - } - error = 0; -#endif + device = CURRENT->rq_dev; - set_fdc( DRIVE(device)); + set_fdc(DRIVE(device)); reschedule_timeout(CURRENTD, "redo fd request", 0); set_floppy(device); + raw_cmd = & default_raw_cmd; + raw_cmd->flags = 0; if(start_motor(redo_fd_request)) return; if(test_bit(current_drive, &fake_change) || TESTF(FD_DISK_CHANGED)){ @@ -2708,7 +2766,7 @@ bad_flp_intr, request_done }; -struct tq_struct request_tq = +struct tq_struct request_tq = { 0, 0, (void *) (void *) redo_fd_request, 0 }; static void process_fd_request(void) @@ -2743,14 +2801,15 @@ { int ret; /* no auto-sense, just clear dcl */ - raw_cmd.flags= flag; - raw_cmd.track=0; - raw_cmd.cmd_count=0; + raw_cmd = &default_raw_cmd; + raw_cmd->flags= flag; + raw_cmd->track=0; + raw_cmd->cmd_count=0; cont = &poll_cont; #ifdef DCL_DEBUG - if (DP->flags & FD_DEBUG){ - DPRINT("setting NEWCHANGE in poll_drive\n"); - } + if (DP->flags & FD_DEBUG){ + DPRINT("setting NEWCHANGE in poll_drive\n"); + } #endif SETF(FD_DISK_NEWCHANGE); WAIT(floppy_ready); @@ -2807,12 +2866,23 @@ return 0; } -#define COPYOUT(x) (fd_copyout( (void *)param, &(x), sizeof(x))) -#define COPYIN(x) (memcpy_fromfs( &(x), (void *) param, sizeof(x)),0) +static int fd_copyin(void *param, volatile void *address, int size) +{ + int i; + + i = verify_area(VERIFY_READ,param,size); + if (i) + return i; + memcpy_fromfs((void *) address, param, size); + return 0; +} + +#define COPYOUT(x) ECALL(fd_copyout( (void *)param, &(x), sizeof(x))) +#define COPYIN(x) ECALL(fd_copyin( (void *)param, &(x), sizeof(x))) static const char *drive_name(int type, int drive ) { - struct floppy_struct *floppy; + struct floppy_struct *floppy; if ( type ) floppy = floppy_type + type; @@ -2828,16 +2898,176 @@ return "(null)"; } + /* raw commands */ +static void raw_cmd_done(int flag) +{ + int i; + + if(!flag) { + raw_cmd->flags = FD_RAW_FAILURE; + raw_cmd->flags |= FD_RAW_HARDFAILURE; + } else { + raw_cmd->reply_count = inr; + for( i=0; i< raw_cmd->reply_count; i++) + raw_cmd->reply[i] = reply_buffer[i]; + + if ( raw_cmd->flags & ( FD_RAW_READ | FD_RAW_WRITE )) + raw_cmd->length = get_dma_residue(FLOPPY_DMA); + + if( (raw_cmd->flags & FD_RAW_SOFTFAILURE) && + (!raw_cmd->reply_count || (raw_cmd->reply[0] & 0xc0))) + raw_cmd->flags |= FD_RAW_FAILURE; + + if( disk_change(current_drive) ) + raw_cmd->flags |= FD_RAW_DISK_CHANGE; + else + raw_cmd->flags &= ~FD_RAW_DISK_CHANGE; + if(raw_cmd->flags & FD_RAW_NO_MOTOR_AFTER) + motor_off_callback(current_drive); + + if(raw_cmd->next && + (!(raw_cmd->flags & FD_RAW_FAILURE) || + !(raw_cmd->flags & FD_RAW_STOP_IF_FAILURE)) && + ((raw_cmd->flags & FD_RAW_FAILURE) || + !(raw_cmd->flags &FD_RAW_STOP_IF_SUCCESS))) { + raw_cmd = raw_cmd->next; + return; + } + } + generic_done(flag); +} + + static struct cont_t raw_cmd_cont={ success_and_wakeup, - failure_and_wakeup, + floppy_start, generic_failure, - generic_done }; + raw_cmd_done +}; + +static inline int raw_cmd_copyout(int cmd, char *param, + struct floppy_raw_cmd *ptr) +{ + struct old_floppy_raw_cmd old_raw_cmd; + int ret; + + while(ptr) { + if(cmd == OLDFDRAWCMD) { + old_raw_cmd.flags = ptr->flags; + old_raw_cmd.data = ptr->data; + old_raw_cmd.length = ptr->length; + old_raw_cmd.rate = ptr->rate; + old_raw_cmd.reply_count = ptr->reply_count; + memcpy(old_raw_cmd.reply, ptr->reply, 7); + COPYOUT(old_raw_cmd); + param += sizeof(old_raw_cmd); + } else { + COPYOUT(*ptr); + param += sizeof(struct floppy_raw_cmd); + } + + if ( (ptr->flags & FD_RAW_READ) && ptr->buffer_length){ + if(ptr->length>=0 && ptr->length<=ptr->buffer_length) + ECALL(fd_copyout(ptr->data, + ptr->kernel_data, + ptr->buffer_length - + ptr->length)); + } + ptr = ptr->next; + } + return 0; +} -static int raw_cmd_ioctl(void *param) + +static void raw_cmd_free(struct floppy_raw_cmd **ptr) { - int i, drive, count, ret; + struct floppy_raw_cmd **next; + + while(*ptr) { + next = & (*ptr)->next; + if((*ptr)->buffer_length) { + free_pages((unsigned long)(*ptr)->kernel_data, + __get_order((*ptr)->buffer_length)); + (*ptr)->buffer_length = 0; + } + kfree(*ptr); + *ptr = 0; + ptr = next; + } +} + + +static inline int raw_cmd_copyin(int cmd, char *param, + struct floppy_raw_cmd **rcmd) +{ + struct floppy_raw_cmd *ptr; + struct old_floppy_raw_cmd old_raw_cmd; + int ret; + int i; + + *rcmd = 0; + while(1) { + ptr = (struct floppy_raw_cmd *) + kmalloc(sizeof(struct floppy_raw_cmd ), GFP_USER); + if(!ptr) + return -ENOMEM; + ptr->next = 0; + ptr->buffer_length = 0; + *rcmd = ptr; + if(cmd == OLDFDRAWCMD){ + COPYIN(old_raw_cmd); + ptr->flags = old_raw_cmd.flags; + ptr->data = old_raw_cmd.data; + ptr->length = old_raw_cmd.length; + ptr->rate = old_raw_cmd.rate; + ptr->cmd_count = old_raw_cmd.cmd_count; + ptr->track = old_raw_cmd.track; + memcpy(ptr->cmd, old_raw_cmd.cmd, 9); + if(ptr->cmd_count > 9) + return -EINVAL; + ptr->next = 0; + ptr->phys_length = 0; + param += sizeof(struct old_floppy_raw_cmd); + } else { + COPYIN(*ptr); + param += sizeof(struct floppy_raw_cmd); + if(ptr->cmd_count > 16) + return -EINVAL; + } + + for(i=0; i< 16; i++) + ptr->reply[i] = 0; + ptr->resultcode = 0; + + ptr->next = 0; + ptr->buffer_length = 0; + ptr->kernel_data = 0; + + if(ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) { + if(!ptr->length) + return -EINVAL; + + ptr->kernel_data =(char*)dma_mem_alloc(ptr->length); + if(!ptr->kernel_data) + return -ENOMEM; + ptr->buffer_length = ptr->length; + } + if(ptr->flags & FD_RAW_WRITE) + fd_copyin(ptr->data, ptr->kernel_data, ptr->length); + rcmd = & (ptr->next); + if( ! (ptr->flags & FD_RAW_MORE)) + return 0; + ptr->rate &= 0x03; + + } +} + + +static int raw_cmd_ioctl(int cmd, void *param) +{ + int drive, ret, ret2; + struct floppy_raw_cmd *my_raw_cmd; if ( FDCS->rawcmd <= 1 ) FDCS->rawcmd = 1; @@ -2858,59 +3088,31 @@ if(FDCS->reset) return -EIO; - COPYIN(raw_cmd); - raw_cmd.rate &= 0x03; - count = raw_cmd.length; - if (raw_cmd.flags & (FD_RAW_WRITE | FD_RAW_READ)){ - if(count > max_buffer_sectors * 1024 ) - return -ENOMEM; - if(count == 0){ - printk("attempt to do a 0 byte dma transfer\n"); - return -EINVAL; - } - buffer_track = -1; - } - if ( raw_cmd.flags & FD_RAW_WRITE ){ - i = verify_area(VERIFY_READ, raw_cmd.data, count ); - if (i) - return i; - memcpy_fromfs(floppy_track_buffer, raw_cmd.data, count); + ret = raw_cmd_copyin(cmd, param, &my_raw_cmd); + if(ret) { + raw_cmd_free(&my_raw_cmd); + return ret; } - current_addr = floppy_track_buffer; + raw_cmd = my_raw_cmd; cont = &raw_cmd_cont; - IWAIT(floppy_start); + ret=wait_til_done(floppy_start,1); #ifdef DCL_DEBUG if (DP->flags & FD_DEBUG){ DPRINT("calling disk change from raw_cmd ioctl\n"); } #endif - if( disk_change(current_drive) ) - raw_cmd.flags |= FD_RAW_DISK_CHANGE; - else - raw_cmd.flags &= ~FD_RAW_DISK_CHANGE; - if(raw_cmd.flags & FD_RAW_NO_MOTOR_AFTER) - motor_off_callback(current_drive); - - if ( !ret && !FDCS->reset ){ - raw_cmd.reply_count = inr; - for( i=0; i< raw_cmd.reply_count; i++) - raw_cmd.reply[i] = reply_buffer[i]; - if ( raw_cmd.flags & ( FD_RAW_READ | FD_RAW_WRITE )) - raw_cmd.length = get_dma_residue(FLOPPY_DMA); - } else - ret = -EIO; + + if(ret != -EINTR && FDCS->reset) + ret = -EINTR; + DRS->track = NO_TRACK; - if ( ret ) - return ret; - if ( raw_cmd.flags & FD_RAW_READ ){ - i=fd_copyout( raw_cmd.data, floppy_track_buffer, count); - if (i) - return i; - } - - return COPYOUT(raw_cmd); + ret2 = raw_cmd_copyout(cmd, param, my_raw_cmd); + if(!ret) + ret = ret2; + raw_cmd_free(&my_raw_cmd); + return ret; } static int invalidate_drive(kdev_t rdev) @@ -2923,7 +3125,7 @@ } static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long param) + unsigned long param) { #define IOCTL_MODE_BIT 8 #define OPEN_WRITE_BIT 16 @@ -2935,6 +3137,7 @@ kdev_t device; struct floppy_struct *this_floppy; const char *name; + int ret; device = inode->i_rdev; switch (cmd) { @@ -2943,166 +3146,200 @@ type = TYPE(device); drive = DRIVE(device); switch (cmd) { - case FDGETDRVTYP: - i=verify_area(VERIFY_WRITE,(void *) param,16); - if (i) - return i; - name = drive_name(type,drive); - for ( cnt=0; cnt<16; cnt++){ - put_user(name[cnt], ((char*)param)+cnt); - if ( ! *name ) - break; - } - return 0; - case FDGETMAXERRS: - return COPYOUT(UDP->max_errors); - case FDGETPRM: - if (type) - this_floppy = &floppy_type[type]; - else if ((this_floppy = current_type[drive]) == - NULL) - return -ENODEV; - return COPYOUT(this_floppy[0]); - case FDPOLLDRVSTAT: - LOCK_FDC(drive,1); - CALL(poll_drive(1, FD_RAW_NEED_DISK)); - process_fd_request(); - /* fall through */ - case FDGETDRVSTAT: - return COPYOUT(*UDRS); - case FDGETFDCSTAT: - return COPYOUT(*UFDCS); - case FDGETDRVPRM: - return COPYOUT(*UDP); - case FDWERRORGET: - return COPYOUT(*UDRWE); + case OLDFDGETDRVTYP: + case FDGETDRVTYP: + i=verify_area(VERIFY_WRITE,(void *) param,16); + if (i) + return i; + name = drive_name(type,drive); + for ( cnt=0; cnt<16; cnt++){ + put_user(name[cnt], ((char*)param)+cnt); + if ( ! *name ) + break; + } + return 0; + case OLDFDGETMAXERRS: + case FDGETMAXERRS: + COPYOUT(UDP->max_errors); + return 0; + case OLDFDGETPRM: + case FDGETPRM: + if (type) + this_floppy = &floppy_type[type]; + else if ((this_floppy = current_type[drive]) == NULL) + return -ENODEV; + COPYOUT(this_floppy[0]); + return 0; + case OLDFDPOLLDRVSTAT: + case FDPOLLDRVSTAT: + LOCK_FDC(drive,1); + CALL(poll_drive(1, FD_RAW_NEED_DISK)); + process_fd_request(); + /* fall through */ + case OLDFDGETDRVSTAT: + case FDGETDRVSTAT: + COPYOUT(*UDRS); + return 0; + case OLDFDGETFDCSTAT: + COPYOUT(* (struct old_floppy_fdc_state *) UFDCS); + return 0; + case FDGETFDCSTAT: + COPYOUT(*UFDCS); + return 0; + case OLDFDGETDRVPRM: + case FDGETDRVPRM: + COPYOUT(*UDP); + return 0; + case OLDFDWERRORGET: + case FDWERRORGET: + COPYOUT(*UDRWE); + return 0; } if (!IOCTL_ALLOWED) return -EPERM; switch (cmd) { - case FDWERRORCLR: - UDRWE->write_errors = 0; - UDRWE->first_error_sector = 0; - UDRWE->first_error_generation = 0; - UDRWE->last_error_sector = 0; - UDRWE->last_error_generation = 0; - UDRWE->badness = 0; - return 0; - case FDRAWCMD: - if (type) - return -EINVAL; - LOCK_FDC(drive,1); - set_floppy(device); - CALL(i = raw_cmd_ioctl((void *) param)); - process_fd_request(); - return i; - case FDFMTTRK: - if (UDRS->fd_ref != 1) - return -EBUSY; - COPYIN(tmp_format_req); - return do_format(device, &tmp_format_req); - case FDSETMAXERRS: - return COPYIN(UDP->max_errors); - case FDFMTBEG: - return 0; - case FDCLRPRM: - LOCK_FDC(drive,1); - current_type[drive] = NULL; - floppy_sizes[drive] = MAX_DISK_SIZE; - UDRS->keep_data = 0; - return invalidate_drive(device); - case FDFMTEND: - case FDFLUSH: - LOCK_FDC(drive,1); - return invalidate_drive(device); - case FDSETPRM: - case FDDEFPRM: - COPYIN(newparams); - /* sanity checking for parameters.*/ - if(newparams.sect <= 0 || - newparams.head <= 0 || - newparams.track <= 0 || - newparams.track > UDP->tracks>> STRETCH(&newparams) || - /* check if reserved bits are set */ - (newparams.stretch & ~(FD_STRETCH | FD_SWAPSIDES)) != 0) - return -EINVAL; - if ( type){ - if ( !suser() ) - return -EPERM; + case OLDFDWERRORCLR: + case FDWERRORCLR: + UDRWE->write_errors = 0; + UDRWE->first_error_sector = 0; + UDRWE->first_error_generation = 0; + UDRWE->last_error_sector = 0; + UDRWE->last_error_generation = 0; + UDRWE->badness = 0; + return 0; + case OLDFDRAWCMD: + case FDRAWCMD: + if (type) + return -EINVAL; LOCK_FDC(drive,1); - for ( cnt = 0; cnt < N_DRIVE; cnt++){ - if (XTYPE(drive_state[cnt].fd_device) == type && - drive_state[cnt].fd_ref) - set_bit(drive, &fake_change); - } - floppy_type[type] = newparams; - floppy_type[type].name="user format"; - for (cnt = type << 2 ; - cnt < (type << 2 ) + 4 ; - cnt++) - floppy_sizes[cnt]= - floppy_sizes[cnt+0x80]= - floppy_type[type].size>>1; + set_floppy(device); + CALL(i = raw_cmd_ioctl(cmd,(void *) param)); process_fd_request(); - for ( cnt = 0; cnt < N_DRIVE; cnt++){ - if (XTYPE(drive_state[cnt].fd_device) == type && - drive_state[cnt].fd_ref) - check_disk_change(to_kdev_t(drive_state[cnt].fd_device)); - } + return i; + case OLDFDFMTTRK: + case FDFMTTRK: + if (UDRS->fd_ref != 1) + return -EBUSY; + COPYIN(tmp_format_req); + return do_format(device, &tmp_format_req); + case OLDFDSETMAXERRS: + case FDSETMAXERRS: + COPYIN(UDP->max_errors); return 0; - } + case OLDFDFMTBEG: + case FDFMTBEG: + return 0; + case OLDFDCLRPRM: + case FDCLRPRM: + LOCK_FDC(drive,1); + current_type[drive] = NULL; + floppy_sizes[drive] = MAX_DISK_SIZE; + UDRS->keep_data = 0; + return invalidate_drive(device); + case OLDFDFMTEND: + case FDFMTEND: + case OLDFDFLUSH: + case FDFLUSH: + LOCK_FDC(drive,1); + return invalidate_drive(device); + case OLDFDSETPRM: + case FDSETPRM: + case OLDFDDEFPRM: + case FDDEFPRM: + COPYIN(newparams); + /* sanity checking for parameters.*/ + if(newparams.sect <= 0 || + newparams.head <= 0 || + newparams.track <= 0 || + newparams.track > UDP->tracks>> STRETCH(&newparams) || + /* check if reserved bits are set */ + (newparams.stretch & ~(FD_STRETCH | FD_SWAPSIDES)) != 0) + return -EINVAL; + if ( type){ + if ( !suser() ) + return -EPERM; + LOCK_FDC(drive,1); + for ( cnt = 0; cnt < N_DRIVE; cnt++){ + if (TYPE(drive_state[cnt].fd_device) == type && + drive_state[cnt].fd_ref) + set_bit(drive, &fake_change); + } + floppy_type[type] = newparams; + floppy_type[type].name="user format"; + for (cnt = type << 2 ; + cnt < (type << 2 ) + 4 ; + cnt++) + floppy_sizes[cnt]= + floppy_sizes[cnt+0x80]= + floppy_type[type].size>>1; + process_fd_request(); + for ( cnt = 0; cnt < N_DRIVE; cnt++){ + if (TYPE(drive_state[cnt].fd_device) == type && + drive_state[cnt].fd_ref) + check_disk_change(drive_state[cnt]. + fd_device); + } + return 0; + } - LOCK_FDC(drive,1); - if ( cmd != FDDEFPRM ) - /* notice a disk change immediately, else - * we loose our settings immediately*/ - CALL(poll_drive(1,0)); - user_params[drive] = newparams; - if (buffer_drive == drive && - buffer_max > user_params[drive].sect) - buffer_max=user_params[drive].sect; - current_type[drive] = &user_params[drive]; - floppy_sizes[drive] = user_params[drive].size >> 1; - if (cmd == FDDEFPRM) - DRS->keep_data = -1; - else - DRS->keep_data = 1; - /* invalidation. Invalidate only when needed, i.e. - * when there are already sectors in the buffer cache - * whose number will change. This is useful, because - * mtools often changes the geometry of the disk after - * looking at the boot block */ - if (DRS->maxblock > - user_params[drive].sect || - DRS->maxtrack ) - invalidate_drive(device); - else - process_fd_request(); - return 0; - case FDRESET: - return user_reset_fdc( drive, (int)param, 1); - case FDMSGON: - UDP->flags |= FTD_MSG; - return 0; - case FDMSGOFF: - UDP->flags &= ~FTD_MSG; - return 0; - case FDSETEMSGTRESH: - UDP->max_errors.reporting = + LOCK_FDC(drive,1); + if ( cmd != FDDEFPRM ) + /* notice a disk change immediately, else + * we loose our settings immediately*/ + CALL(poll_drive(1,0)); + user_params[drive] = newparams; + if (buffer_drive == drive && + buffer_max > user_params[drive].sect) + buffer_max=user_params[drive].sect; + current_type[drive] = &user_params[drive]; + floppy_sizes[drive] = user_params[drive].size >> 1; + if (cmd == FDDEFPRM) + DRS->keep_data = -1; + else + DRS->keep_data = 1; + /* invalidation. Invalidate only when needed, i.e. + * when there are already sectors in the buffer cache + * whose number will change. This is useful, because + * mtools often changes the geometry of the disk after + * looking at the boot block */ + if (DRS->maxblock > + user_params[drive].sect || + DRS->maxtrack ) + invalidate_drive(device); + else + process_fd_request(); + return 0; + case OLDFDRESET: + case FDRESET: + return user_reset_fdc( drive, (int)param, 1); + case OLDFDMSGON: + case FDMSGON: + UDP->flags |= FTD_MSG; + return 0; + case OLDFDMSGOFF: + case FDMSGOFF: + UDP->flags &= ~FTD_MSG; + return 0; + case OLDFDSETEMSGTRESH: + case FDSETEMSGTRESH: + UDP->max_errors.reporting = (unsigned short) (param & 0x0f); - return 0; - case FDTWADDLE: - LOCK_FDC(drive,1); - twaddle(); - process_fd_request(); + return 0; + case OLDFDTWADDLE: + case FDTWADDLE: + LOCK_FDC(drive,1); + twaddle(); + process_fd_request(); } if ( ! suser() ) return -EPERM; switch(cmd){ - case FDSETDRVPRM: - return COPYIN(*UDP); - default: - return -EINVAL; + case OLDFDSETDRVPRM: + case FDSETDRVPRM: + COPYIN(*UDP); + return 0; + default: + return -EINVAL; } return 0; #undef IOCTL_ALLOWED @@ -3169,7 +3406,7 @@ if(!UDRS->maxblock) UDRS->maxblock=1;/* make change detectable */ check_disk_change(inode->i_rdev); - if (UTESTF(FD_DISK_CHANGED)) + if (UTESTF(FD_DISK_CHANGED)) return -ENXIO; if(!UTESTF(FD_DISK_WRITABLE)) return -EROFS; @@ -3183,14 +3420,14 @@ static void floppy_release(struct inode * inode, struct file * filp) { int drive; - + drive = DRIVE(inode->i_rdev); if( !filp || (filp->f_mode & (2 | OPEN_WRITE_BIT))) /* if the file is mounted OR (writable now AND writable at * open time) Linus: Does this cover all cases? */ block_fsync(inode,filp); - + if (UDRS->fd_ref < 0) UDRS->fd_ref=0; else if (!UDRS->fd_ref--) { @@ -3205,14 +3442,12 @@ * /dev/PS0 etc), and disallows simultaneous access to the same * drive with different device numbers. */ -#define RETERR(x) \ - do{floppy_release(inode,filp); \ - return -(x);}while(0) +#define RETERR(x) do{floppy_release(inode,filp); return -(x);}while(0) static int floppy_open(struct inode * inode, struct file * filp) { int drive; - kdev_t old_dev; + int old_dev; int try; char *tmp; @@ -3223,15 +3458,15 @@ drive = DRIVE(inode->i_rdev); - if (drive >= N_DRIVE || + if (drive >= N_DRIVE || !( ALLOWED_DRIVE_MASK & ( 1 << drive)) || fdc_state[FDC(drive)].version == FDC_NONE) return -ENXIO; if (TYPE(inode->i_rdev) >= NUMBER(floppy_type)) return -ENXIO; - old_dev = to_kdev_t(UDRS->fd_device); - if (UDRS->fd_ref && old_dev != inode->i_rdev) + old_dev = UDRS->fd_device; + if (UDRS->fd_ref && old_dev != MINOR(inode->i_rdev)) return -EBUSY; if(!UDRS->fd_ref && (UDP->flags & FD_BROKEN_DCL)){ @@ -3278,7 +3513,7 @@ } } - UDRS->fd_device = kdev_t_to_nr(inode->i_rdev); + UDRS->fd_device = MINOR(inode->i_rdev); if (old_dev && old_dev != inode->i_rdev) { if (buffer_drive == drive) @@ -3293,7 +3528,7 @@ filp->f_mode |= OPEN_WRITE_BIT; if (UFDCS->rawcmd == 1) - UFDCS->rawcmd = 2; + UFDCS->rawcmd = 2; if (filp->f_flags & O_NDELAY) return 0; @@ -3349,9 +3584,9 @@ int drive=DRIVE(dev); int cf; - if(UTESTF(FD_DISK_CHANGED) || + if(UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY) || - test_bit(drive, &fake_change) || + test_bit(drive, &fake_change) || NO_GEOM){ lock_fdc(drive,0); cf = UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY); @@ -3382,9 +3617,9 @@ wait_on_buffer(bh); brelse(bh); return 0; - } + } if(cf) - poll_drive(0, FD_RAW_NEED_DISK); + poll_drive(0, FD_RAW_NEED_DISK); process_fd_request(); } return 0; @@ -3462,7 +3697,7 @@ void floppy_invert_dcl(int *ints,int param) { int i; - + for (i=0; i < ARRAY_SIZE(default_drive_params); i++){ if (param) default_drive_params[i].params.flags |= 0x80; @@ -3523,6 +3758,8 @@ DPRINT("bad drive for set_cmos\n"); return; } + if(current_drive >= 4 && !FDC2) + fdc2_adr(0, 0x370); if(ints[2] <= 0 || ints[2] >= NUMBER(default_drive_params)){ DPRINT1("bad cmos code %d\n", ints[2]); return; @@ -3530,59 +3767,64 @@ DP->cmos = ints[2]; DPRINT1("setting cmos code to %d\n", ints[2]); } - + static struct param_table { const char *name; void (*fn)(int *ints, int param); int def_param; } config_params[]={ -{ "allowed_drive_mask", allow_drives, 0xff }, -{ "all_drives", allow_drives, 0xff }, -{ "asus_pci", allow_drives, 0x33 }, + { "allowed_drive_mask", allow_drives, 0xff }, + { "all_drives", allow_drives, 0xff }, + { "asus_pci", allow_drives, 0x33 }, -{ "daring", daring, 1}, + { "daring", daring, 1}, -{ "two_fdc", fdc2_adr, 0x370 }, -{ "one_fdc", fdc2_adr, 0 }, + { "two_fdc", fdc2_adr, 0x370 }, + { "one_fdc", fdc2_adr, 0 }, -{ "thinkpad", floppy_invert_dcl, 1 }, + { "thinkpad", floppy_invert_dcl, 1 }, -{ "cmos", set_cmos, 0 }, + { "cmos", set_cmos, 0 }, -{ "unexpected_interrupts", unex, 1 }, -{ "no_unexpected_interrupts", unex, 0 }, -{ "L40SX", unex, 0 } }; + { "unexpected_interrupts", unex, 1 }, + { "no_unexpected_interrupts", unex, 0 }, + { "L40SX", unex, 0 } }; #define FLOPPY_SETUP void floppy_setup(char *str, int *ints) { int i; int param; - if(!str) - return; - for(i=0; i< ARRAY_SIZE(config_params); i++){ - if (strcmp(str,config_params[i].name) == 0 ){ - if (ints[0] ) - param = ints[1]; - else - param = config_params[i].def_param; - config_params[i].fn(ints,param); - return; + if(str) + for(i=0; i< ARRAY_SIZE(config_params); i++){ + if (strcmp(str,config_params[i].name) == 0 ){ + if (ints[0] ) + param = ints[1]; + else + param = config_params[i].def_param; + config_params[i].fn(ints,param); + return; + } } - } - DPRINT1("unknown floppy option [%s]\n", str); - DPRINT("allowed options are:"); - for(i=0; i< ARRAY_SIZE(config_params); i++) - printk(" %s",config_params[i].name); - printk("\n"); + if(str) { + DPRINT1("unknown floppy option [%s]\n", str); + + DPRINT("allowed options are:"); + for(i=0; i< ARRAY_SIZE(config_params); i++) + printk(" %s",config_params[i].name); + printk("\n"); + } else + DPRINT("botched floppy option\n"); DPRINT("Read linux/drivers/block/README.fd\n"); } int floppy_init(void) { - int i,drive; + int i,unit,drive; int have_no_fdc=0; + raw_cmd = 0; + sti(); if (register_blkdev(MAJOR_NR,"fd",&floppy_fops)) { @@ -3591,8 +3833,8 @@ } for(i=0; i<256; i++) - if ( ITYPE(i)) - floppy_sizes[i] = floppy_type[ITYPE(i)].size >> 1; + if (TYPE(i)) + floppy_sizes[i] = floppy_type[TYPE(i)].size >> 1; else floppy_sizes[i] = MAX_DISK_SIZE; @@ -3641,6 +3883,9 @@ for (i = 0 ; i < N_FDC ; i++) { fdc = i; + FDCS->driver_version = FD_DRIVER_VERSION; + for(unit=0; unit<4; unit++) + FDCS->track[unit] = 0; if (FDCS->address == -1 ) continue; FDCS->rawcmd = 2; @@ -3654,7 +3899,7 @@ FDCS->address = -1; continue; } - + request_region(FDCS->address, 6, "floppy"); request_region(FDCS->address+7, 1, "floppy DIR"); /* address + 6 is reserved, and may be taken by IDE. @@ -3691,7 +3936,7 @@ MOD_INC_USE_COUNT; #endif for(i=0; i< N_FDC; i++){ - if(FDCS->address != -1){ + if(FDCS->address != -1){ fdc = i; reset_fdc_info(1); outb_p(FDCS->dor, FD_DOR); @@ -3759,7 +4004,7 @@ for(drive=0; drive < N_FDC * 4; drive++) if( motor_off_timer[drive].next ) printk("motor off timer %d still active\n", drive); - + if(fd_timeout.next) printk("floppy timer still active:%s\n", timeout_message); if (fd_timer.next) @@ -3787,9 +4032,7 @@ match=0; j=1; - for(i=current->mm->env_start; - i< current->mm->env_end; - i ++){ + for(i=current->mm->env_start; i< current->mm->env_end; i ++){ c= get_fs_byte(i); if(match){ if(j==99) @@ -3807,8 +4050,7 @@ break; continue; } - if( (!j && !c) || - ( j && c == pattern[j-1])) + if( (!j && !c) || ( j && c == pattern[j-1])) j++; else j=0; @@ -3827,23 +4069,23 @@ { int ret; printk("inserting floppy driver for %s\n", kernel_version); - + mod_setup("floppy=", floppy_setup); - + ret = floppy_init(); - return 0; + return 0; } void cleanup_module(void) { int fdc; - + for(fdc=0; fdc<2; fdc++) if (FDCS->address != -1){ release_region(FDCS->address, 6); release_region(FDCS->address+7, 1); - } - + } + unregister_blkdev(MAJOR_NR, "fd"); blk_dev[MAJOR_NR].request_fn = 0; diff -u --recursive --new-file v1.3.33/linux/drivers/char/mem.c linux/drivers/char/mem.c --- v1.3.33/linux/drivers/char/mem.c Tue Oct 10 18:46:33 1995 +++ linux/drivers/char/mem.c Wed Oct 11 12:43:41 1995 @@ -23,7 +23,7 @@ #include #ifdef CONFIG_SOUND -int soundcard_init(void); +void soundcard_init(void); #endif static int read_ram(struct inode * inode, struct file * file, char * buf, int count) diff -u --recursive --new-file v1.3.33/linux/drivers/net/README.multicast linux/drivers/net/README.multicast --- v1.3.33/linux/drivers/net/README.multicast Tue Oct 10 18:46:35 1995 +++ linux/drivers/net/README.multicast Tue Oct 10 19:09:57 1995 @@ -1,5 +1,5 @@ Behaviour of cards under Multicast. This is how they currently -behave not what the hardware can do. In paticular all the 8390 based +behave not what the hardware can do. In particular all the 8390 based cards don't use the onboard hash filter, and the lance driver doesn't use its filter, even though the code for loading it is in the DEC lance based driver. diff -u --recursive --new-file v1.3.33/linux/drivers/net/pi2.c linux/drivers/net/pi2.c --- v1.3.33/linux/drivers/net/pi2.c Tue Oct 10 18:46:36 1995 +++ linux/drivers/net/pi2.c Thu Oct 12 15:43:00 1995 @@ -654,6 +654,7 @@ /* 'skb->data' points to the start of sk_buff data area. */ memcpy(cfix, lp->rcvbuf->data, pkt_len - 1); skb->protocol=ntohs(ETH_P_AX25); + skb->mac.raw=skb->data; IS_SKB(skb); netif_rx(skb); lp->stats.rx_packets++; diff -u --recursive --new-file v1.3.33/linux/drivers/scsi/fdomain.c linux/drivers/scsi/fdomain.c --- v1.3.33/linux/drivers/scsi/fdomain.c Mon Sep 18 14:53:57 1995 +++ linux/drivers/scsi/fdomain.c Fri Oct 13 07:38:18 1995 @@ -1,10 +1,10 @@ /* fdomain.c -- Future Domain TMC-16x0 SCSI driver * Created: Sun May 3 18:53:19 1992 by faith@cs.unc.edu - * Revised: Sun Sep 17 00:23:26 1995 by r.faith@ieee.org + * Revised: Thu Oct 12 15:59:37 1995 by r.faith@ieee.org * Author: Rickard E. Faith, faith@cs.unc.edu * Copyright 1992, 1993, 1994, 1995 Rickard E. Faith * - * $Id: fdomain.c,v 5.36 1995/09/17 04:23:42 root Exp $ + * $Id: fdomain.c,v 5.39 1995/10/12 20:31:47 root Exp $ * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -209,14 +209,14 @@ #include #include #include -#include +#include struct proc_dir_entry proc_scsi_fdomain = { PROC_SCSI_FDOMAIN, 7, "fdomain", S_IFDIR | S_IRUGO | S_IXUGO, 2 }; -#define VERSION "$Revision: 5.36 $" +#define VERSION "$Revision: 5.39 $" /* START OF USER DEFINABLE OPTIONS */ @@ -404,6 +404,7 @@ { "Future Domain Corp. V2.0108/18/93", 5, 33, 3, 5, 0 }, { "FUTURE DOMAIN CORP. V3.5008/18/93", 5, 34, 3, 5, 0 }, { "FUTURE DOMAIN 18c30/18c50/1800 (C) 1994 V3.5", 5, 44, 3, 5, 0 }, + { "FUTURE DOMAIN CORP. V3.6008/18/93", 5, 34, 3, 6, 0 }, { "FUTURE DOMAIN CORP. V3.6108/18/93", 5, 34, 3, 6, 0 }, { "FUTURE DOMAIN TMC-18XX", 5, 22, -1, -1, 0 }, @@ -468,9 +469,9 @@ printk( "fdomain: bad LILO parameters?\n" ); } - port_base = ints[0] >= 1 ? ints[1] : 0; - interrupt_level = ints[0] >= 2 ? ints[2] : 0; - adapter_mask = ints[0] >= 3 ? (1 << ints[3]) : 0; + port_base = ints[0] >= 1 ? ints[1] : 0; + interrupt_level = ints[0] >= 2 ? ints[2] : 0; + this_id = ints[0] >= 3 ? ints[3] : 0; bios_major = bios_minor = -1; /* Use geometry for BIOS version >= 3.4 */ } @@ -953,7 +954,7 @@ } if (this_id) { - tpnt->this_id = (this_id & 0x7); + tpnt->this_id = (this_id & 0x07); adapter_mask = (1 << tpnt->this_id); } else { if ((bios_major == 3 && bios_minor >= 2) || bios_major < 0) { @@ -1077,7 +1078,6 @@ return buffer; } -#if 0 /* First pass at /proc information routine. */ /* * inout : decides on the direction of the dataflow and the meaning of the @@ -1092,17 +1092,30 @@ int fdomain_16x0_proc_info( char *buffer, char **start, off_t offset, int length, int hostno, int inout ) { - int len = 0; const char *info = fdomain_16x0_info( NULL ); - - if (inout) return -ENOSYS; + int len; + int pos; + int begin; + if (inout) return(-ENOSYS); + + begin = 0; strcpy( buffer, info ); - len += strlen( info ); + strcat( buffer, "\n" ); + + pos = len = strlen( buffer ); - return( len ); + if(pos < offset) { + len = 0; + begin = pos; + } + + *start = buffer + (offset - begin); /* Start of wanted data */ + len -= (offset - begin); + if(len > length) len = length; + + return(len); } -#endif #if 0 static int fdomain_arbitrate( void ) diff -u --recursive --new-file v1.3.33/linux/drivers/scsi/fdomain.h linux/drivers/scsi/fdomain.h --- v1.3.33/linux/drivers/scsi/fdomain.h Mon Sep 18 14:53:57 1995 +++ linux/drivers/scsi/fdomain.h Fri Oct 13 07:38:18 1995 @@ -1,10 +1,10 @@ /* fdomain.h -- Header for Future Domain TMC-16x0 driver * Created: Sun May 3 18:47:33 1992 by faith@cs.unc.edu - * Revised: Sat Jan 14 20:56:52 1995 by faith@cs.unc.edu + * Revised: Thu Oct 12 13:21:35 1995 by r.faith@ieee.org * Author: Rickard E. Faith, faith@cs.unc.edu * Copyright 1992, 1993, 1994, 1995 Rickard E. Faith * - * $Id: fdomain.h,v 5.10 1995/01/15 01:56:56 root Exp $ + * $Id: fdomain.h,v 5.12 1995/10/12 19:01:09 root Exp $ * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -32,14 +32,16 @@ int fdomain_16x0_reset( Scsi_Cmnd * ); int fdomain_16x0_queue( Scsi_Cmnd *, void (*done)(Scsi_Cmnd *) ); int fdomain_16x0_biosparam( Disk *, kdev_t, int * ); +int fdomain_16x0_proc_info( char *buffer, char **start, off_t offset, + int length, int hostno, int inout ); extern struct proc_dir_entry proc_scsi_fdomain; #define FDOMAIN_16X0 { NULL, \ NULL, \ NULL, \ + fdomain_16x0_proc_info, \ NULL, \ - NULL, \ fdomain_16x0_detect, \ NULL, \ fdomain_16x0_info, \ diff -u --recursive --new-file v1.3.33/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c --- v1.3.33/linux/drivers/scsi/scsi.c Tue Oct 10 18:46:37 1995 +++ linux/drivers/scsi/scsi.c Thu Oct 12 17:20:19 1995 @@ -2259,6 +2259,8 @@ } +int scsi_loadable_module_flag; /* Set after we scan builtin drivers */ + void * scsi_init_malloc(unsigned int size, int priority) { void * retval; @@ -2351,6 +2353,9 @@ /* Yes we're here... */ dispatch_scsi_info_ptr = dispatch_scsi_info; + /* Init a few things so we can "malloc" memory. */ + scsi_loadable_module_flag = 0; + timer_table[SCSI_TIMER].fn = scsi_main_timeout; timer_table[SCSI_TIMER].expires = 0; @@ -2435,6 +2440,8 @@ for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) if(sdtpnt->finish && sdtpnt->nr_dev) (*sdtpnt->finish)(); + + scsi_loadable_module_flag = 1; return 0; } diff -u --recursive --new-file v1.3.33/linux/drivers/sound/.blurb linux/drivers/sound/.blurb --- v1.3.33/linux/drivers/sound/.blurb Tue Jul 11 10:02:51 1995 +++ linux/drivers/sound/.blurb Wed Oct 11 07:55:38 1995 @@ -6,3 +6,7 @@ * Readme.cards (this directory) contains some card * * specific instructions. * ********************************************************* +* NOTE!!!! THIS IS AN _EXPERIMENTAL_ ALPHA TEST VERSION * +* WHICH CERTAINLY HAS BUGS AND MAY SERIOUSLY DAMAGE YOUR* +* SYSTEM. YOU HAVE A CHANCE TO HIT CTRL-C NOW!!!!!!!! * +********************************************************* diff -u --recursive --new-file v1.3.33/linux/drivers/sound/.version linux/drivers/sound/.version --- v1.3.33/linux/drivers/sound/.version Sun Aug 13 14:45:32 1995 +++ linux/drivers/sound/.version Wed Oct 11 07:55:38 1995 @@ -1 +1 @@ -3.0.1 +3.5-alpha2 diff -u --recursive --new-file v1.3.33/linux/drivers/sound/CHANGELOG linux/drivers/sound/CHANGELOG --- v1.3.33/linux/drivers/sound/CHANGELOG Sun Aug 13 14:45:32 1995 +++ linux/drivers/sound/CHANGELOG Wed Oct 11 07:55:38 1995 @@ -1,5 +1,23 @@ -Changelog for version 3.0.1 ---------------------------- +Changelog for version 3.5 +------------------------- + +Since 3.0.2 +- Support for CS4232 based PnP cards (AcerMagic S23 etc). +- Full duplex support for some CS4231, CS4232 and AD1845 based cards +(GUA MAX, AudioTrix Pro, AcerMagic S23 and many MAD16/Mozart cards +having a codec mentioned above). +- Almost fully rewritten loadable modules support. +- Fixed some bugs. +- Huge amount of testing (more testing is still required). +- mmap() support (works with some cards). Requires much more testing. +- Sample/patch/program loading for TB Maui/Tropez. No initialization +since TB doesn't allow me to release that code. +- Using CS4231 compatible codecs as timer for /dev/music. + +Since 3.0.1 +- Added allocation of I/O ports, DMA channels and interrupts +to the initialization code. This may break modules support since +the driver may not free some resources on unload. Should be fixed soon. Since 3.0 - Some important bug fixes. diff -u --recursive --new-file v1.3.33/linux/drivers/sound/Makefile linux/drivers/sound/Makefile --- v1.3.33/linux/drivers/sound/Makefile Mon Sep 18 14:54:04 1995 +++ linux/drivers/sound/Makefile Wed Oct 11 12:54:57 1995 @@ -8,6 +8,7 @@ VERSION = `cat .version` TARGET_OS = linux USRINCDIR = /usr/include +MODULEDIR = /lib/modules/misc OBJS = soundcard.o audio.o dmabuf.o sb_dsp.o dev_table.o \ opl3.o sequencer.o midibuf.o sb_card.o pas2_card.o adlib_card.o \ @@ -15,30 +16,45 @@ gus_midi.o gus_vol.o patmgr.o sb_mixer.o sb16_dsp.o sb_midi.o \ sb16_midi.o sound_switch.o midi_synth.o uart6850.o sound_timer.o \ sys_timer.o ics2101.o ad1848.o pss.o sscape.o trix.o aedsp16.o \ - mad16.o + mad16.o mad16_sb_midi.o cs4232.o maui.o sound_pnp.o -# Don't compile the sound driver during a normal kernel build if we have -# configured for a module build instead. -ifeq ($(CONFIG_SOUND),y) -all: local.h sound.a -else -all: +ifndef HOSTCC +# +# Running outside the kernel build. +# +CC = gcc +HOSTCC = gcc +CFLAGS = -D__KERNEL__ -DMODULE -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -m486 + +build: + @echo Compiling modularized sound driver + @make sound.o + @echo Sound module compiled. + +install: sound.o + cp sound.o $(MODULEDIR) + +.c.o: + $(CC) $(CFLAGS) -c $< endif +all: local.h sound.a + +include $(TOPDIR)/Rules.make + sound.a: $(OBJS) -rm -f sound.a $(AR) rcs sound.a $(OBJS) sync clean: - rm -f core core.* *.o *.a tmp_make *~ x z *% - rm -f configure - for i in *.c;do rm -f `basename $$i .c`.s;done + rm -f core core.* *.o *.a tmp_make *~ x y z *% + rm -f configure sound_stub.c indent: for n in *.c;do echo indent $$n;indent $$n;done -local.h: +local.h: $(MAKE) clean $(MAKE) setup-$(TARGET_OS) $(MAKE) config @@ -49,8 +65,9 @@ @./configure > local.h @echo \#define SOUND_CONFIG_DATE \"`date`\" >> local.h @echo \#define SOUND_CONFIG_BY \"`whoami`\" >> local.h - @echo \#define SOUND_CONFIG_HOST \"`hostname`\" >> local.h - @echo \#define SOUND_CONFIG_DOMAIN \"`hostname -d`\" >> local.h +# @echo \#define SOUND_CONFIG_HOST \"`hostname`\" >> local.h 2>/dev/null +# @echo \#define SOUND_CONFIG_DOMAIN \"`hostname -d`\" >> local.h 2>/dev/null + @echo \#define SOUND_UNAME_A \"`uname -a`\" >> local.h clrconf: rm -f local.h .depend synth-ld.h trix_boot.h smw-midi0001.h @@ -65,11 +82,9 @@ setup-linux: @echo Compiling Sound Driver v $(VERSION) for Linux -sound.o: sound.a +sound.o: $(OBJS) -rm -f sound.o - $(LD) -r -o sound.o soundcard.o sound.a + $(LD) -r -o sound.o $(OBJS) -modules: sound.o - (cd ../../modules; ln -fs ../drivers/sound/sound.o .) - -include $(TOPDIR)/Rules.make +modules: local.h sound.o + ln -fs `pwd`/sound.o /usr/src/linux/modules/sound.o diff -u --recursive --new-file v1.3.33/linux/drivers/sound/Readme linux/drivers/sound/Readme --- v1.3.33/linux/drivers/sound/Readme Sun Aug 13 14:45:32 1995 +++ linux/drivers/sound/Readme Wed Oct 11 07:55:37 1995 @@ -1,3 +1,12 @@ +IMPORTANT! This version of the driver is compatible only with Linux versions + 1.3.33 and later. It may work with earlier ones as a loadable + module but... + + Also this is an ALPHA test version which has not been tested + with all cards. At least AEDSP16 support will not work. PAS16 + and PSS supports have not been tested. /dev/dsp and /dev/audio + playback with standard GUS sounds scrambled. + Please read the SOUND-HOWTO (available from sunsite.unc.edu and other Linux ftp sites). It contains much more information than this file. @@ -7,39 +16,19 @@ * about configuring various cards. * ***************************************************************** -VoxWare v3.0.1 release notes ----------------------------- +VoxWare v3.5-alpha2 release notes +--------------------------------- -This version is the final v3.0. All features I have planned to -include in v3.0 are there but some of them are completely untested -(see experimental.txt). - -*** GUS MAX enhancements ***************************************************** -Recording with GUS MAX works now. The configuration program asks -two DMA channels for GUS MAX. You have to use two different 16 bit -DMA numbers (5, 6 or 7) if you want to record (8 bit DMA channels -may or may not work). It's still possible to use just one DMA channel -with GUS MAX but recording doesn't work in this case (a hardware limitation). -Even the driver has capability to use two DMA channels, simultaneous recording -and playback is not possible with GUS MAX (will not be before v4.0 -of the driver). However it's now possible to play using /dev/dsp and /dev/dsp1 -at the same time (or /dev/dsp and /dev/sequencer as well). -Recording using /dev/dsp1 will not work if GUS MAX is configured to use two -DMA channels. -****************************************************************************** - -There are some additional device files (since v2.90-2 andv3.0-proto-94mmdd -versions). -You will need to create additional device files using the script at the -end of ./linux/Readme. Also recompile all mixer programs since there are -some new channels that are not enabled in mixers compiled with older -soundcard.h. +This is not an official release but just an experimental alpha +test version. The official version is included in Linux-1.3.3x +version sources. There are some programming information (little bit old) in the Hacker's Guide (ftp://nic.funet.fi/pub/OS/Linux/ALPHA/sound/snd-sdk-doc-0.1.ps.gz). Believe me: The file is really there. The directory is just hidden and -you have to cd into it before the file is visible. +you have to cd into it before the file is visible. Note: This directory +was accidently removed some time ago but it's now back. I have got many patches from various persons during last year. Some of them are still on my mailbox and they should be included in versions @@ -62,8 +51,7 @@ You will also need the latest version of the soundscape.co[01] file. The old sndscape.cod will ___NOT___ work (it propably just hangs your system completely). The latest code file is available from ftp.ensoniq.com - as part of the DOS/Windows driver distribution. See sndscape/ssinit.c - for more info. + as part of the DOS/Windows driver distribution. - This is Linux only version. It should work in other operating systems (SCO, UW, FreeBSD and NetBSD) too but may require some fixes before it compiles. @@ -89,7 +77,7 @@ (NOTE! WSS mode may not work (DMA channel setup problem)). MediaTriX AudioTriX Pro (OPL4 and the optional effect daughtercard require special initialization. There is a program (setfx) in - the audiotrix directory which does it). + the snd-util-3.0.tar.gz package which does it). Ensoniq SoundScape (works but needs some improvements) MV Jazz16 based soundcards (ProSonic, 3D etc). SoundMan Wave (recording may not work, mixer support is limited) @@ -154,7 +142,7 @@ Hunyue Yau Mixer support for SG NX Pro. Marc Hoffman PSS support. Rainer Vranken Initialization for Jazz16 (ProSonic, MV3D, SM Wave). - Peter Trattler Loadable module support for Linux. + Peter Trattler Initial version of loadable module support for Linux. JRA Gibson 16 bit mode for Jazz16 Davor Jadrijevic MAD16 support Gregor Hoffleit Mozart support @@ -173,6 +161,7 @@ The Santa Cruz Operation, Inc. A SCO OpenServer + SDK Ensoniq Corp, a SoundScape card and extensive amount of assistance MediaTriX Peripherals Inc, a AudioTriX Pro card + SDK +Acer, Inc. a pair of AcerMagic S23 cards. In addition the following companies have provided me sufficial amount of technical information at least some of their products (free or $$$): diff -u --recursive --new-file v1.3.33/linux/drivers/sound/Readme.cards linux/drivers/sound/Readme.cards --- v1.3.33/linux/drivers/sound/Readme.cards Sun Aug 13 14:45:32 1995 +++ linux/drivers/sound/Readme.cards Wed Oct 11 07:55:37 1995 @@ -46,7 +46,7 @@ GUS GUS + the 16 bit option GUS MAX - (GUS ACE ????????????) + GUS ACE (No MIDI port and audio recording) MPU-401 and compatibles The driver works both with the full (intelligent mode) MPU-401 @@ -65,7 +65,7 @@ (AD1848 by Analog Devices and CS4231/CS4248 by Crystal Semiconductor). Currently most soundcards are based on one of the MSS compatible codec chip. The CS4231 is used in the high quality cards such as GUS MAX, - MediaTriX AudioTriX Pro and TB Tropez. + MediaTriX AudioTriX Pro and TB Tropez (GUS MAX is not MSS compatible). Having a AD1848, CS4248 or CS4231 codec chip on the card is a good sign. Even if the card is not MSS compatible, it could be easy to write @@ -267,6 +267,9 @@ please look at the card specific instructions later in this file before answering this question. For an unknown card you may answer 'y' if the card claims to be SB compatible. + + Don't enable SB if you have a MAD16 or Mozart compatible card. + "Generic OPL2/OPL3 FM synthesizer support", - Answer 'y' if your card has a FM chip made by Yamaha (OPL2/OPL3/OPL4). Answering 'y' is usually a safe and recommended choice. However some @@ -431,7 +434,7 @@ do. Use I/O 0x220 and DMA1 for the SB mode. Ensure that you assign different IRQ numbers for the SB and PAS16 modes. -With PAS16 you can use two audio devices at the same time. /dev/dsp (and +With PAS16 you can use two audio device files at the same time. /dev/dsp (and /dev/audio) is connected to the 8/16 bit native codec and the /dev/dsp1 (and /dev/audio1) is connected to the SB emulation (8 bit mono only). @@ -452,7 +455,7 @@ Configuring GUS is simple. Just enable the GUS support and GUS MAX or the 16 bit daughtercard if you have them. Note that enabling the daughter -card disables GUS MAX. +card disables GUS MAX driver. With just the standard GUS enabled the configuration program prompts for the I/O, IRQ and DMA numbers for the card. Use the same values than @@ -466,16 +469,18 @@ GUS MAX uses the same I/O address and IRQ settings than the original GUS (GUS MAX = GUS + a CS4231 codec). In addition an extra DMA channel may be used. -Using two DMA channels permits simultaneous playback using two devices but -simultaneous recording and playback is not possible (not before v4.0). -Also using two DMA channels is required if you want to record in 16 bit modes. +Using two DMA channels permits simultaneous playback using two devices +(dev/dsp0 and /dev/dsp1). The second DMA channel is required for +full duplex audio. To enable the second DMA channels, give a valid DMA channel when the config -program asks for the GUS MAX DMA (entering 0 disables the second DMA). -Using 16 bit DMA channels (5,6 or 7) is recommended. The drawback of -using two DMA channels with GUS MAX is that recording from /dev/dsp1 -(the 8 bit codec) is disabled. +program asks for the GUS MAX DMA (entering -1 disables the second DMA). +Using 16 bit DMA channels (5,6 or 7) is recommended. + +If you have problems in recording with GUS MAX, you could try to use +just one 8 bit DMA channel. Recording will not work with one DMA +channel if it's a 16 bit one. + -It's not guaranteed that recording using GUS MAX works (in 3.0-beta2). MPU401 and Windows Sound System ------------------------------- @@ -551,7 +556,7 @@ initialization after boot. Since information about the effect processor is not public, the initialization must be done by running a special program after boot. The setfx program is distributed in Linux binary form (only) -in directory sound/audiotrix (of VoxWare-3.0.tar.gz package). +in snd-util-3.0.tar.gz package. It's calls ioperm() so it must be run as root. Another way to initialize the effects processor (and OPL4) is to boot DOS @@ -579,11 +584,12 @@ and one DMA is used by the MSS codec. The second IRQ is required for the MPU401 mode (you have to use different IRQs for both purposes). The second DMA channel is required for initialization of the microcontroller. +You have to use separate DMA channels. The SoundScape card has a Motorola microcontroller which must initialized _after_ boot (the driver doesn't initialize it during boot). The initialization is done by running the 'ssinit' program which is -distributed in directory sound/sndscape. You have to edit two +distributed in the snd-util-3.0.tar.gz package. You have to edit two defines in the ssinit.c and then compile the program. You may run ssinit manually (after each boot) or add it to /etc/rc.d/rc.local. @@ -621,18 +627,20 @@ ---------------------- You need to enable just the MAD16 /Mozart support when configuring -the driver. Don't enable SB, MPU401 or MSS. However you will need the +the driver. _Don't_ enable SB, MPU401 or MSS. However you will need the /dev/audio, /dev/sequencer and MIDI supports. Mozart and OPTi 82C928 (the original MAD16) chips don't support MPU401 mode so enter just 0 when the configuration program asks the MPU/MIDI I/O base. The MAD16 Pro (OPTi 82C929) has MPU401 mode. -TB Tropez is based on the 82C929 chip. However it has two MIDI ports. +TB Tropez is based on the 82C929 chip. It has two MIDI ports. The one connected to the MAD16 chip is the second one (there is a second MIDI connector/pins somewhere??). If you have not connected the second MIDI port, just disable the MIDI port of MAD16. The 'Maui' compatible synth of Tropez is jumper configurable and not connected to the MAD16 chip. +It can be used by enabling the stand alone MPU401 support but you have +to initialize it by using the MS-DOS SNDSETUP program. There are some other OPTi chips which may be used in soundcards such as 82C930 and MAC32. These chips are not supported by VoxWare yet. Please diff -u --recursive --new-file v1.3.33/linux/drivers/sound/Readme.linux linux/drivers/sound/Readme.linux --- v1.3.33/linux/drivers/sound/Readme.linux Tue Jul 11 10:02:51 1995 +++ linux/drivers/sound/Readme.linux Wed Oct 11 07:55:37 1995 @@ -27,11 +27,15 @@ - Configure and compile Linux as normally (remember to include the sound support during "make config"). -Boot time configuration (using lilo) ------------------------------------- +Boot time configuration (using lilo and insmod) +----------------------------------------------- NOTE! This information is little bit obsolete since it doesn't cover - some cards recently added to the driver. + some cards recently added to the driver. The following text + describes parameters just for some older cards. In addition + this method will not work with cards which have more than one + DMA channel or if the driver number is bigger than 15. (Driver + numbers are defined in soundcard.h). ------------------------------------------------------------------- NOTE2! This method to configure the sound driver is not normally @@ -42,6 +46,15 @@ So THE METHOD PRESENTED IN THIS CHAPTER IS NORMALLY COMPLETELY USELESS. DON'T USE IT UNLESS YOU HAVE A VERY SPECIAL REASON TO DO THAT. + + !!!!!!!!!!!!!!!!!!!! PLEASE NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !!! Finding a working sound= command line is a difficult !!! + !!! and timeconsuming task. For this reason I will not !!! + !!! answer to messages asking about how to do it. So !!! + !!! please don't use this method if you have any problems !!! + !!! with it. !!! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + ------------------------------------------------------------------- This version of the sound driver has capability to accept the configuration diff -u --recursive --new-file v1.3.33/linux/drivers/sound/Readme.modules linux/drivers/sound/Readme.modules --- v1.3.33/linux/drivers/sound/Readme.modules Tue Jul 11 10:02:51 1995 +++ linux/drivers/sound/Readme.modules Wed Oct 11 07:55:38 1995 @@ -1,87 +1,88 @@ - Linux sound-driver module - (c) Peter Trattler - License: GPL (Gnu Public License) +Building a loadable sound driver +================================ +Loadable module support in version 3.5 of VoxWare is mostly rewritten since +the previous version (3.0.1). This means that some things have changed. -Idea: +To compile the sound driver as a loadable module you have to perform +the following steps: -I've modified the sources for the sound driver to allow simply insert and -remove the sound driver from the kernel by calling (only available for Linux) - - insmod /usr/src/linux/modules/sound.o - -and - - rmmod sound - -This may be useful if you are doing one of the following things: - -1) Debugging the sound driver -2) Creating a new device within the sound-driver -3) You do not the sound driver all the time (as it wastes quite a lot of -memory for its buffers) - - -Compilation: - -Go to /usr/src/linux and make the following steps: - -a) configure the sound driver: To do that call "make config" and enable the -sound-driver -- you will be asked different questions about your -sound-hardware (remember not to use a too big DMA-Buffer size; you -should use 16kB, if you have 16Bit devices, otherwise you can use 32kB) - -b) disable the sound driver in the kernel: call make config again but answer -'N' to "Sound card support" - -c) run "make modules"; the sound-driver sound.o should end up in -/usr/src/linux/modules - - -If memory is tight: - -I've allocated at about 70kB for the sound-drivers internal tables. If this -is too much, 'insmod sound.o' will generate the following warning -... -use 'insmod memsize=xxxx' -... -You can only use this command, if you have (I think) at least -modules-1.1.87 or up. You can also switch debugging on by running the command - -insmod sound.o debugmem=1 - - -Files I changed: - -I've only changed the files soundcard.c(most changes) and some changes within -the Makefile, sound_config.h and the Makefile in /usr/src/linux/drivers - - -Bugs: - -a) As the kmalloc (..., GFP_DMA) caused some unexpected errors (I don't know if -it is my fault), I created some code, which is (by default) enabled by - -#define KMALLOC_DMA_BROKEN 1 (within soundcard.c). - -It trys to allocate a large enough region, so that the complete dma-buffer -can be occupied in this space. If it does not fit within this region it -doubles the size of it. But this can cause problems, if the sound-buffer is -too big (as kmalloc can only handle regions at up to circa 100kB). - -So take care to use for 8Bit devices a sound-DMA-buffer of 32kB (maximum) -and for 16Bit devices a maximum of 16kB. Otherwise the allocation scheme -might fail. - -b) Buffers allocated by the different sound devices via calls to kmalloc are -not freed, if the sound driver is removed again (these buffers tend to be -quite small -- so it does not harm a lot) - -c) If there is not enough (kernel-) memory available, the installation of -the sound-driver fails. (This happens quite often, if you did not install the -driver right after booting -- [PS: I've only got 5MB of Ram, so this might -be the source for this problem]) - - -Author: - Peter Trattler (peter@sbox.tu-graz.ac.at) +1) Install modules-1.2.8.tar.gz package (or later if available). +2a) Check that symbol remap_page_range is defined in linux/init/ksyms.c. +Insert a line containing "X(remap_page_range)," if required. The driver will +not load if this line is missing. +2b) Recompile kernel with soundcard support disabled. +3) Boot the new kernel. +4) cd to the sound driver source directory (this directory). It's no +longer required that the sound driver sources are installed in the +kernel source tree (linux/drivers/sound). When installing a separately +distributed sound driver you may install the sources for example to +/usr/src/sound. +5) Execute make in the sound driver source directory. Enter +configuration parameters as described in Readme.cards. Then just wait until +the driver is compiled OK. +6) Copy sound.o to the directory where insmod expects to find it. +("make install" copies it to /lib/modules/misc). +7) Use command "insmod sound" to load the driver. + +8) The sound driver can be removed using command "rmmod sound". + + +Parameters accepted by the loadable sound driver +================================================ + +Setting DMA buffer size +----------------------- + +The driver allocates a DMA buffer (or two for full duplex devices) +every time the audio device (/dev/dsp or /dev/audio) is opened +and frees it when the device is closed. Size of this buffer is defined +when the driver is configured (the last question). The buffer size +can be redefined when loading the driver if required (note that this is +an optional feature which is not normally required). The buffer size +is redefined by adding dma_pagesize= parameter to the insmod command line. +For example: + + insmod sound dma_buffsize=32768 + +Minimum buffer size is 4096 and the maximum depends on the DMA channe. +For 8 bit channels (0 to 3) the limit is 64k and for 16 bit ones (5 to 7) +it's 128k. Driver selects a suitable buffer size automaticly in case +you try to spesify an invalid size. + +Q: What is the right DMA buffer size? + +A: It depends on the sampling rate, machine speed and the load of the system. +Large buffers are required on slow machines, when recording/playing CD-quality +audio or when there are other processes running on the same system. Also +recording to hard disk is likely to require large buffers. + +Very small buffers are sufficient when you are just playing 8kHz audio files +on an empty P133 system. Using a 128k byffer just wastes 120k (or 250k) +of valuable physical RAM memory. + +The right buffer sice can be easily found by making some experiments +with the dma_buffsize= parameter. I use usually 16k buffers on a DX4/100 system +and 64k on an old 386 system. + +NOTE! DMA buffers are used only by /dev/audio# and /dev/dsp# devices. + Other device files don't use them but there are two exceptions: + GUS driver uses DMA buffers when loading samples to the card. + Ensoniq SoundScape driver uses them when doanloading the microcode + file (sndscape.co[012]) to the card. Using large buffers doesn't + increase performance in these cases. + +Configuring device parameters when loading the driver +----------------------------------------------------- + +The loadable version of the sound driver accepts now the same +sound= parameter that has been available in the LILO command line. +In this way it's possible to change I/O port, IRQ and DMA addresses +and to enable/disable various cards at load time. Normally +the driver uses the configuration parameters entered when compiling +and configuring the driver. +Look at Readme.linux for more info. + +NOTE! This method is not normally required. You should use it only when + you have to use different configuration than normally. The sound= + command line parameter is error phrone and not recommended. diff -u --recursive --new-file v1.3.33/linux/drivers/sound/ad1848.c linux/drivers/sound/ad1848.c --- v1.3.33/linux/drivers/sound/ad1848.c Mon Aug 28 14:52:21 1995 +++ linux/drivers/sound/ad1848.c Wed Oct 11 07:55:38 1995 @@ -10,7 +10,8 @@ * CS4231A and AD1845 are upward compatible with CS4231. However * the new features of these chips are different. * - * CS4232 is a PnP audio chip which contains a CS4231A. + * CS4232 is a PnP audio chip which contains a CS4231A (and SB, MPU). + * CS4232A is an improved version of CS4232. * * Copyright by Hannu Savolainen 1994, 1995 * @@ -47,17 +48,10 @@ #include "ad1848_mixer.h" -#define IMODE_NONE 0 -#define IMODE_OUTPUT 1 -#define IMODE_INPUT 2 -#define IMODE_INIT 3 -#define IMODE_MIDI 4 - typedef struct { int base; int irq; - int dma_capture, dma_playback; int dual_dma; /* 1, when two DMA channels allocated */ unsigned char MCE_bit; unsigned char saved_regs[16]; @@ -74,29 +68,42 @@ int opened; char *chip_name; int mode; +#define MD_1848 1 +#define MD_4231 2 +#define MD_4231A 3 +#define MD_1845 4 /* Mixer parameters */ int recmask; int supported_devices; int supported_rec_devices; unsigned short levels[32]; + int dev_no; + volatile unsigned long timer_ticks; + int timer_running; + int irq_ok; + sound_os_info *osp; } ad1848_info; static int nr_ad1848_devs = 0; -static char irq2dev[16] = +static volatile char irq2dev[17] = {-1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1}; + -1, -1, -1, -1, -1, -1, -1, -1, -1}; + +static int timer_installed = -1; static char mixer2codec[MAX_MIXER_DEV] = {0}; -static int ad_format_mask[3 /*devc->mode */ ] = +static int ad_format_mask[5 /*devc->mode */ ] = { 0, AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW, - AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_U16_LE | AFMT_IMA_ADPCM + AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_U16_LE | AFMT_IMA_ADPCM, + AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_U16_LE | AFMT_IMA_ADPCM, + AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW /* AD1845 */ }; static ad1848_info dev_info[MAX_AUDIO_DEV]; @@ -108,13 +115,17 @@ static int ad1848_open (int dev, int mode); static void ad1848_close (int dev); -static int ad1848_ioctl (int dev, unsigned int cmd, unsigned int arg, int local); +static int ad1848_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local); static void ad1848_output_block (int dev, unsigned long buf, int count, int intrflag, int dma_restart); static void ad1848_start_input (int dev, unsigned long buf, int count, int intrflag, int dma_restart); static int ad1848_prepare_for_IO (int dev, int bsize, int bcount); static void ad1848_reset (int dev); static void ad1848_halt (int dev); -void ad1848_interrupt (INT_HANDLER_PARMS (irq, dummy)); +static void ad1848_halt_input (int dev); +static void ad1848_halt_output (int dev); +static void ad1848_trigger (int dev, int bits); +static int ad1848_tmr_install (int dev); +static void ad1848_tmr_reprogram (int dev); static int ad_read (ad1848_info * devc, int reg) @@ -123,14 +134,15 @@ int x; int timeout = 900000; - while (timeout > 0 && INB (devc->base) == 0x80) /*Are we initializing */ + while (timeout > 0 && inb (devc->base) == 0x80) /*Are we initializing */ timeout--; - DISABLE_INTR (flags); - OUTB ((unsigned char) (reg & 0xff) | devc->MCE_bit, io_Index_Addr (devc)); - x = INB (io_Indexed_Data (devc)); + save_flags (flags); + cli (); + outb ((unsigned char) (reg & 0xff) | devc->MCE_bit, io_Index_Addr (devc)); + x = inb (io_Indexed_Data (devc)); /* printk("(%02x<-%02x) ", reg|devc->MCE_bit, x); */ - RESTORE_INTR (flags); + restore_flags (flags); return x; } @@ -141,14 +153,15 @@ unsigned long flags; int timeout = 90000; - while (timeout > 0 && INB (devc->base) == 0x80) /*Are we initializing */ + while (timeout > 0 && inb (devc->base) == 0x80) /*Are we initializing */ timeout--; - DISABLE_INTR (flags); - OUTB ((unsigned char) (reg & 0xff) | devc->MCE_bit, io_Index_Addr (devc)); - OUTB ((unsigned char) (data & 0xff), io_Indexed_Data (devc)); + save_flags (flags); + cli (); + outb ((unsigned char) (reg & 0xff) | devc->MCE_bit, io_Index_Addr (devc)); + outb ((unsigned char) (data & 0xff), io_Indexed_Data (devc)); /* printk("(%02x->%02x) ", reg|devc->MCE_bit, data); */ - RESTORE_INTR (flags); + restore_flags (flags); } static void @@ -164,9 +177,9 @@ */ timeout = 100000; - while (timeout > 0 && INB (devc->base) & 0x80) + while (timeout > 0 && inb (devc->base) & 0x80) timeout--; - if (INB (devc->base) & 0x80) + if (inb (devc->base) & 0x80) printk ("ad1848: Auto calibration timed out(1).\n"); timeout = 100; @@ -219,21 +232,22 @@ int timeout = 1000; unsigned short prev; - while (timeout > 0 && INB (devc->base) == 0x80) /*Are we initializing */ + while (timeout > 0 && inb (devc->base) == 0x80) /*Are we initializing */ timeout--; - DISABLE_INTR (flags); + save_flags (flags); + cli (); devc->MCE_bit = 0x40; - prev = INB (io_Index_Addr (devc)); + prev = inb (io_Index_Addr (devc)); if (prev & 0x40) { - RESTORE_INTR (flags); + restore_flags (flags); return; } - OUTB (devc->MCE_bit, io_Index_Addr (devc)); - RESTORE_INTR (flags); + outb (devc->MCE_bit, io_Index_Addr (devc)); + restore_flags (flags); } static void @@ -243,24 +257,25 @@ unsigned char prev; int timeout = 1000; - while (timeout > 0 && INB (devc->base) == 0x80) /*Are we initializing */ + while (timeout > 0 && inb (devc->base) == 0x80) /*Are we initializing */ timeout--; - DISABLE_INTR (flags); + save_flags (flags); + cli (); devc->MCE_bit = 0x00; - prev = INB (io_Index_Addr (devc)); - OUTB (0x00, io_Index_Addr (devc)); /* Clear the MCE bit */ + prev = inb (io_Index_Addr (devc)); + outb (0x00, io_Index_Addr (devc)); /* Clear the MCE bit */ - if ((prev & 0x40) == 0) /* Not in MCE mode */ + if ((prev & 0x40) == 0) /* Not in MCE mode */ { - RESTORE_INTR (flags); + restore_flags (flags); return; } - OUTB (0x00, io_Index_Addr (devc)); /* Clear the MCE bit */ + outb (0x00, io_Index_Addr (devc)); /* Clear the MCE bit */ wait_for_calibration (devc); - RESTORE_INTR (flags); + restore_flags (flags); } @@ -308,6 +323,10 @@ recdev = 1; break; + case SOUND_MASK_IMIX: + recdev = 3; + break; + default: mask = SOUND_MASK_MIC; recdev = 2; @@ -342,7 +361,7 @@ ad1848_mixer_get (ad1848_info * devc, int dev) { if (!((1 << dev) & devc->supported_devices)) - return RET_ERROR (EINVAL); + return -EINVAL; return devc->levels[dev]; } @@ -352,6 +371,7 @@ { int left = value & 0x000000ff; int right = (value & 0x0000ff00) >> 8; + int retvol; int regoffs; unsigned char val; @@ -361,14 +381,29 @@ if (right > 100) right = 100; + if (mix_devices[dev][RIGHT_CHN].nbits == 0) /* Mono control */ + right = left; + + retvol = left | (left << 8); + + /* Scale volumes */ + left = mix_cvt[left]; + right = mix_cvt[right]; + + /* Scale it again */ + left = mix_cvt[left]; + right = mix_cvt[right]; + if (dev > 31) - return RET_ERROR (EINVAL); + return -EINVAL; if (!(devc->supported_devices & (1 << dev))) - return RET_ERROR (EINVAL); + return -EINVAL; if (mix_devices[dev][LEFT_CHN].nbits == 0) - return RET_ERROR (EINVAL); + return -EINVAL; + + devc->levels[dev] = retvol; /* * Set the left channel @@ -377,16 +412,15 @@ regoffs = mix_devices[dev][LEFT_CHN].regno; val = ad_read (devc, regoffs); change_bits (&val, dev, LEFT_CHN, left); - devc->levels[dev] = left | (left << 8); ad_write (devc, regoffs, val); devc->saved_regs[regoffs] = val; /* - * Set the left right + * Set the right channel */ if (mix_devices[dev][RIGHT_CHN].nbits == 0) - return left | (left << 8); /* Was just a mono channel */ + return retvol; /* Was just a mono channel */ regoffs = mix_devices[dev][RIGHT_CHN].regno; val = ad_read (devc, regoffs); @@ -394,8 +428,7 @@ ad_write (devc, regoffs, val); devc->saved_regs[regoffs] = val; - devc->levels[dev] = left | (right << 8); - return left | (right << 8); + return retvol; } static void @@ -404,7 +437,7 @@ int i; devc->recmask = 0; - if (devc->mode == 2) + if (devc->mode != MD_1848) devc->supported_devices = MODE2_MIXER_DEVICES; else devc->supported_devices = MODE1_MIXER_DEVICES; @@ -412,19 +445,20 @@ devc->supported_rec_devices = MODE1_REC_DEVICES; for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) - ad1848_mixer_set (devc, i, devc->levels[i] = default_mixer_levels[i]); + if (devc->supported_devices & (1 << i)) + ad1848_mixer_set (devc, i, default_mixer_levels[i]); ad1848_set_recmask (devc, SOUND_MASK_MIC); } static int -ad1848_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg) +ad1848_mixer_ioctl (int dev, unsigned int cmd, ioctl_arg arg) { ad1848_info *devc; int codec_dev = mixer2codec[dev]; if (!codec_dev) - return RET_ERROR (ENXIO); + return -ENXIO; codec_dev--; @@ -436,11 +470,11 @@ switch (cmd & 0xff) { case SOUND_MIXER_RECSRC: - return IOCTL_OUT (arg, ad1848_set_recmask (devc, IOCTL_IN (arg))); + return snd_ioctl_return ((int *) arg, ad1848_set_recmask (devc, get_fs_long ((long *) arg))); break; default: - return IOCTL_OUT (arg, ad1848_mixer_set (devc, cmd & 0xff, IOCTL_IN (arg))); + return snd_ioctl_return ((int *) arg, ad1848_mixer_set (devc, cmd & 0xff, get_fs_long ((long *) arg))); } else switch (cmd & 0xff) /* @@ -449,32 +483,31 @@ { case SOUND_MIXER_RECSRC: - return IOCTL_OUT (arg, devc->recmask); + return snd_ioctl_return ((int *) arg, devc->recmask); break; case SOUND_MIXER_DEVMASK: - return IOCTL_OUT (arg, devc->supported_devices); + return snd_ioctl_return ((int *) arg, devc->supported_devices); break; case SOUND_MIXER_STEREODEVS: - return IOCTL_OUT (arg, devc->supported_devices & - ~(SOUND_MASK_SPEAKER | SOUND_MASK_IMIX)); + return snd_ioctl_return ((int *) arg, devc->supported_devices & ~(SOUND_MASK_SPEAKER | SOUND_MASK_IMIX)); break; case SOUND_MIXER_RECMASK: - return IOCTL_OUT (arg, devc->supported_rec_devices); + return snd_ioctl_return ((int *) arg, devc->supported_rec_devices); break; case SOUND_MIXER_CAPS: - return IOCTL_OUT (arg, SOUND_CAP_EXCL_INPUT); + return snd_ioctl_return ((int *) arg, SOUND_CAP_EXCL_INPUT); break; default: - return IOCTL_OUT (arg, ad1848_mixer_get (devc, cmd & 0xff)); + return snd_ioctl_return ((int *) arg, ad1848_mixer_get (devc, cmd & 0xff)); } } else - return RET_ERROR (EINVAL); + return -EINVAL; } static struct audio_operations ad1848_pcm_operations[MAX_AUDIO_DEV] = @@ -494,7 +527,10 @@ ad1848_reset, ad1848_halt, NULL, - NULL + NULL, + ad1848_halt_input, + ad1848_halt_output, + ad1848_trigger }}; static struct mixer_operations ad1848_mixer_operations = @@ -506,71 +542,35 @@ static int ad1848_open (int dev, int mode) { - int err; ad1848_info *devc = NULL; unsigned long flags; - DEB (printk ("ad1848_open(int mode = %X)\n", mode)); - if (dev < 0 || dev >= num_audiodevs) - return RET_ERROR (ENXIO); + return -ENXIO; devc = (ad1848_info *) audio_devs[dev]->devc; - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (devc->opened) { - RESTORE_INTR (flags); + restore_flags (flags); printk ("ad1848: Already opened\n"); - return RET_ERROR (EBUSY); + return -EBUSY; } - if (devc->irq) /* Not managed by another driver */ - if ((err = snd_set_irq_handler (devc->irq, ad1848_interrupt, - audio_devs[dev]->name)) < 0) - { - printk ("ad1848: IRQ in use\n"); - RESTORE_INTR (flags); - return err; - } - -/* - * Allocate DMA - */ - - if (mode & OPEN_WRITE) - audio_devs[dev]->dmachan = devc->dma_playback; - else - audio_devs[dev]->dmachan = devc->dma_capture; - - if (DMAbuf_open_dma (dev) < 0) - { - RESTORE_INTR (flags); - if (devc->irq) /* Don't leave IRQ reserved */ - snd_release_irq (devc->irq); - - printk ("ad1848: DMA in use\n"); - return RET_ERROR (EBUSY); - } devc->dual_dma = 0; - if (devc->dma_capture != devc->dma_playback && mode == OPEN_READWRITE) + if (audio_devs[dev]->flags & DMA_DUPLEX) { devc->dual_dma = 1; - - if (ALLOC_DMA_CHN (devc->dma_capture, "Sound System (capture)")) - { - if (devc->irq) /* Don't leave IRQ reserved */ - snd_release_irq (devc->irq); - DMAbuf_close_dma (dev); - return RET_ERROR (EBUSY); - } } devc->intr_active = 0; devc->opened = 1; - RESTORE_INTR (flags); + devc->irq_mode = 0; + restore_flags (flags); /* * Mute output until the playback really starts. This decreases clicking. */ @@ -587,26 +587,18 @@ DEB (printk ("ad1848_close(void)\n")); - DISABLE_INTR (flags); + save_flags (flags); + cli (); devc->intr_active = 0; - if (devc->irq) /* Not managed by another driver */ - snd_release_irq (devc->irq); ad1848_reset (dev); - DMAbuf_close_dma (dev); - if (devc->dual_dma) /* Release the second DMA channel */ - { - if (audio_devs[dev]->dmachan == devc->dma_playback) - RELEASE_DMA_CHN (devc->dma_capture); - else - RELEASE_DMA_CHN (devc->dma_playback); - } devc->opened = 0; + devc->irq_mode = 0; ad_unmute (devc); - RESTORE_INTR (flags); + restore_flags (flags); } static int @@ -650,6 +642,18 @@ n = sizeof (speed_table) / sizeof (speed_struct); + if (devc->mode == MD_1845) /* AD1845 has different timer than others */ + { + if (arg < 4000) + arg = 4000; + if (arg > 50000) + arg = 50000; + + devc->speed = arg; + devc->speed_bits = speed_table[selected].bits; + return devc->speed; + } + if (arg < speed_table[0].speed) selected = 0; if (arg > speed_table[n - 1].speed) @@ -765,7 +769,7 @@ } static int -ad1848_ioctl (int dev, unsigned int cmd, unsigned int arg, int local) +ad1848_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local) { ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; @@ -773,42 +777,42 @@ { case SOUND_PCM_WRITE_RATE: if (local) - return set_speed (devc, arg); - return IOCTL_OUT (arg, set_speed (devc, IOCTL_IN (arg))); + return set_speed (devc, (int) arg); + return snd_ioctl_return ((int *) arg, set_speed (devc, get_fs_long ((long *) arg))); case SOUND_PCM_READ_RATE: if (local) return devc->speed; - return IOCTL_OUT (arg, devc->speed); + return snd_ioctl_return ((int *) arg, devc->speed); case SNDCTL_DSP_STEREO: if (local) - return set_channels (devc, arg + 1) - 1; - return IOCTL_OUT (arg, set_channels (devc, IOCTL_IN (arg) + 1) - 1); + return set_channels (devc, (int) arg + 1) - 1; + return snd_ioctl_return ((int *) arg, set_channels (devc, get_fs_long ((long *) arg) + 1) - 1); case SOUND_PCM_WRITE_CHANNELS: if (local) - return set_channels (devc, arg); - return IOCTL_OUT (arg, set_channels (devc, IOCTL_IN (arg))); + return set_channels (devc, (int) arg); + return snd_ioctl_return ((int *) arg, set_channels (devc, get_fs_long ((long *) arg))); case SOUND_PCM_READ_CHANNELS: if (local) return devc->channels; - return IOCTL_OUT (arg, devc->channels); + return snd_ioctl_return ((int *) arg, devc->channels); case SNDCTL_DSP_SAMPLESIZE: if (local) - return set_format (devc, arg); - return IOCTL_OUT (arg, set_format (devc, IOCTL_IN (arg))); + return set_format (devc, (int) arg); + return snd_ioctl_return ((int *) arg, set_format (devc, get_fs_long ((long *) arg))); case SOUND_PCM_READ_BITS: if (local) return devc->audio_format; - return IOCTL_OUT (arg, devc->audio_format); + return snd_ioctl_return ((int *) arg, devc->audio_format); default:; } - return RET_ERROR (EINVAL); + return -EINVAL; } static void @@ -819,8 +823,6 @@ cnt = count; - audio_devs[dev]->dmachan = devc->dma_playback; - if (devc->audio_format == AFMT_IMA_ADPCM) { cnt /= 4; @@ -834,17 +836,18 @@ cnt >>= 1; cnt--; - if (audio_devs[dev]->flags & DMA_AUTOMODE && + if (devc->irq_mode & PCM_ENABLE_OUTPUT && audio_devs[dev]->flags & DMA_AUTOMODE && intrflag && cnt == devc->xfer_count) { - devc->irq_mode = IMODE_OUTPUT; + devc->irq_mode |= PCM_ENABLE_OUTPUT; devc->intr_active = 1; return; /* * Auto DMA mode on. No need to react */ } - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (dma_restart) { @@ -852,39 +855,16 @@ DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE); } - ad_enter_MCE (devc); - ad_write (devc, 15, (unsigned char) (cnt & 0xff)); ad_write (devc, 14, (unsigned char) ((cnt >> 8) & 0xff)); - if (devc->dma_playback == devc->dma_capture) - { - ad_write (devc, 9, 0x0d); /* - * Playback enable, single DMA channel mode, - * auto calibration on. - */ - } - else - { - ad_write (devc, 9, 0x09); /* - * Playback enable, dual DMA channel mode. - * auto calibration on. - */ - } - - ad_leave_MCE (devc); /* - * Starts the calibration process and - * enters playback mode after it. - */ + /* ad_write (devc, 9, ad_read (devc, 9) | 0x01); *//* Playback enable */ ad_unmute (devc); devc->xfer_count = cnt; - devc->irq_mode = IMODE_OUTPUT; + devc->irq_mode |= PCM_ENABLE_OUTPUT; devc->intr_active = 1; - INB (io_Status (devc)); - OUTB (0, io_Status (devc)); /* Clear pending interrupts */ - RESTORE_INTR (flags); - + restore_flags (flags); } static void @@ -893,8 +873,6 @@ unsigned long flags, cnt; ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; - audio_devs[dev]->dmachan = devc->dma_capture; - cnt = count; if (devc->audio_format == AFMT_IMA_ADPCM) { @@ -909,17 +887,18 @@ cnt >>= 1; cnt--; - if (audio_devs[dev]->flags & DMA_AUTOMODE && + if (devc->irq_mode & PCM_ENABLE_INPUT && audio_devs[dev]->flags & DMA_AUTOMODE && intrflag && cnt == devc->xfer_count) { - devc->irq_mode = IMODE_INPUT; + devc->irq_mode |= PCM_ENABLE_INPUT; devc->intr_active = 1; return; /* * Auto DMA mode on. No need to react */ } - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (dma_restart) { @@ -927,71 +906,73 @@ DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ); } - ad_enter_MCE (devc); - - if (devc->dma_playback == devc->dma_capture) /* Single DMA channel mode */ + if (devc->mode == MD_1848 || !devc->dual_dma) /* Single DMA channel mode */ { ad_write (devc, 15, (unsigned char) (cnt & 0xff)); ad_write (devc, 14, (unsigned char) ((cnt >> 8) & 0xff)); - - ad_write (devc, 9, 0x0e); /* - * Capture enable, single DMA channel mode, - * auto calibration on. - */ } else /* Dual DMA channel mode */ { ad_write (devc, 31, (unsigned char) (cnt & 0xff)); ad_write (devc, 30, (unsigned char) ((cnt >> 8) & 0xff)); - - ad_write (devc, 9, 0x0a); /* - * Capture enable, dual DMA channel mode, - * auto calibration on. - */ } - ad_leave_MCE (devc); /* - * Starts the calibration process and - * enters playback mode after it. - */ + /* ad_write (devc, 9, ad_read (devc, 9) | 0x02); *//* Capture enable */ ad_unmute (devc); devc->xfer_count = cnt; - devc->irq_mode = IMODE_INPUT; + devc->irq_mode |= PCM_ENABLE_INPUT; devc->intr_active = 1; - INB (io_Status (devc)); - OUTB (0, io_Status (devc)); /* Clear interrupt status */ - RESTORE_INTR (flags); + restore_flags (flags); } static int ad1848_prepare_for_IO (int dev, int bsize, int bcount) { int timeout; - unsigned char fs; + unsigned char fs, old_fs; unsigned long flags; ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; - DISABLE_INTR (flags); - ad_enter_MCE (devc); /* Enables changes to the format select reg */ + if (devc->irq_mode) + return 0; + + save_flags (flags); + cli (); fs = devc->speed_bits | (devc->format_bits << 5); if (devc->channels > 1) fs |= 0x10; + if (devc->mode == MD_1845) /* Use alternate speed select registers */ + { + fs &= 0xf0; /* Mask off the rate select bits */ + + ad_write (devc, 22, (devc->speed >> 8) & 0xff); /* Speed MSB */ + ad_write (devc, 23, devc->speed & 0xff); /* Speed LSB */ + } + + if (fs == (old_fs = ad_read (devc, 8))) /* No change */ + { + restore_flags (flags); + devc->xfer_count = 0; + return 0; + } + + ad_enter_MCE (devc); /* Enables changes to the format select reg */ ad_write (devc, 8, fs); /* * Write to I8 starts resyncronization. Wait until it completes. */ timeout = 10000; - while (timeout > 0 && INB (devc->base) == 0x80) + while (timeout > 0 && inb (devc->base) == 0x80) timeout--; /* * If mode == 2 (CS4231), set I28 also. It's the capture format register. */ - if (devc->mode == 2) + if (devc->mode != MD_1848) { ad_write (devc, 28, fs); @@ -999,7 +980,7 @@ * Write to I28 starts resyncronization. Wait until it completes. */ timeout = 10000; - while (timeout > 0 && INB (devc->base) == 0x80) + while (timeout > 0 && inb (devc->base) == 0x80) timeout--; } @@ -1007,8 +988,16 @@ ad_leave_MCE (devc); /* * Starts the calibration process. */ - RESTORE_INTR (flags); + restore_flags (flags); devc->xfer_count = 0; + +#ifndef EXCLUDE_SEQUENCER + if (dev == timer_installed && devc->timer_running) + if ((fs & 0x01) != (old_fs & 0x01)) + { + ad1848_tmr_reprogram (dev); + } +#endif return 0; } @@ -1022,17 +1011,18 @@ ad1848_halt (int dev) { ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; + unsigned long flags; + + save_flags (flags); + cli (); ad_mute (devc); ad_write (devc, 9, ad_read (devc, 9) & ~0x03); /* Stop DMA */ - OUTB (0, io_Status (devc)); /* Clear interrupt status */ - ad_enter_MCE (devc); - OUTB (0, io_Status (devc)); /* Clear interrupt status */ ad_write (devc, 15, 0); /* Clear DMA counter */ ad_write (devc, 14, 0); /* Clear DMA counter */ - if (devc->mode == 2) + if (devc->mode != MD_1848) { ad_write (devc, 30, 0); /* Clear DMA counter */ ad_write (devc, 31, 0); /* Clear DMA counter */ @@ -1040,15 +1030,85 @@ ad_write (devc, 9, ad_read (devc, 9) & ~0x03); /* Stop DMA */ - OUTB (0, io_Status (devc)); /* Clear interrupt status */ - OUTB (0, io_Status (devc)); /* Clear interrupt status */ - ad_leave_MCE (devc); + outb (0, io_Status (devc)); /* Clear interrupt status */ + outb (0, io_Status (devc)); /* Clear interrupt status */ + devc->irq_mode = 0; /* DMAbuf_reset_dma (dev); */ + restore_flags (flags); +} + +static void +ad1848_halt_input (int dev) +{ + ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; + unsigned long flags; + + if (devc->mode == MD_1848) + { + ad1848_halt (dev); + return; + } + + save_flags (flags); + cli (); + + ad_mute (devc); + ad_write (devc, 9, ad_read (devc, 9) & ~0x02); /* Stop capture */ + + + devc->irq_mode &= ~PCM_ENABLE_INPUT; + + restore_flags (flags); +} + +static void +ad1848_halt_output (int dev) +{ + ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; + unsigned long flags; + + if (devc->mode == MD_1848) + { + ad1848_halt (dev); + return; + } + + save_flags (flags); + cli (); + + ad_mute (devc); + ad_write (devc, 9, ad_read (devc, 9) & ~0x01); /* Stop playback */ + + + devc->irq_mode &= ~PCM_ENABLE_OUTPUT; + + restore_flags (flags); +} + +static void +ad1848_trigger (int dev, int state) +{ + ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; + unsigned long flags; + unsigned char tmp; + + save_flags (flags); + cli (); + state &= devc->irq_mode; + + tmp = ad_read (devc, 9) & ~0x03; + if (state & PCM_ENABLE_INPUT) + tmp |= 0x02; + if (state & PCM_ENABLE_OUTPUT) + tmp |= 0x01; + ad_write (devc, 9, tmp); + + restore_flags (flags); } int -ad1848_detect (int io_base) +ad1848_detect (int io_base, int *ad_flags, sound_os_info * osp) { unsigned char tmp; @@ -1056,20 +1116,29 @@ ad1848_info *devc = &dev_info[nr_ad1848_devs]; unsigned char tmp1 = 0xff, tmp2 = 0xff; + if (ad_flags) + *ad_flags = 0; + if (nr_ad1848_devs >= MAX_AUDIO_DEV) { DDB (printk ("ad1848 detect error - step 0\n")); return 0; } + if (check_region (io_base, 4)) + { + printk ("\n\nad1848.c: Port %x not free.\n\n", io_base); + return 0; + } devc->base = io_base; + devc->irq_ok = 0; + devc->timer_running = 0; devc->MCE_bit = 0x40; devc->irq = 0; - devc->dma_capture = 0; - devc->dma_playback = 0; devc->opened = 0; devc->chip_name = "AD1848"; - devc->mode = 1; /* MODE1 = original AD1848 */ + devc->mode = MD_1848; /* AD1848 or CS4248 */ + devc->osp = osp; /* * Check that the I/O address is in use. @@ -1080,10 +1149,10 @@ * * If the I/O address is unused, it typically returns 0xff. */ - - if ((INB (devc->base) & 0x80) != 0x00) /* Not a AD1884 */ + if ((inb (devc->base) & 0x80) != 0x00) /* Not a AD1848 */ { - DDB (printk ("ad1848 detect error - step A\n")); + DDB (printk ("ad1848 detect error - step A (%02x)\n", + inb (devc->base))); return 0; } @@ -1155,7 +1224,12 @@ tmp1 = ad_read (devc, 12); if (tmp1 & 0x80) - devc->chip_name = "CS4248"; /* Our best knowledge just now */ + { + if (ad_flags) + *ad_flags |= AD_F_CS4248; + + devc->chip_name = "CS4248"; /* Our best knowledge just now */ + } if ((tmp1 & 0xc0) == (0x80 | 0x40)) { @@ -1185,6 +1259,8 @@ ad_write (devc, 25, ~tmp1); /* Invert all bits */ if ((ad_read (devc, 25) & 0xe7) == (tmp1 & 0xe7)) { + int id; + /* * It's at least CS4231 */ @@ -1193,7 +1269,7 @@ #ifdef MOZART_PORT if (devc->base != MOZART_PORT + 4) #endif - devc->mode = 2; + devc->mode = MD_4231; /* * It could be an AD1845 or CS4231A as well. @@ -1201,41 +1277,69 @@ * while the CS4231A reports different. */ - if ((ad_read (devc, 25) & 0xe7) == 0xa0) + id = ad_read (devc, 25) & 0xe7; + + switch (id) { + + case 0xa0: devc->chip_name = "CS4231A"; - } - else if ((ad_read (devc, 25) & 0xe7) == 0x80) - { - /* - * It must be a CS4231 or AD1845. The register I23 of - * CS4231 is undefined and it appears to be read only. - * AD1845 uses I23 for setting sample rate. Assume - * the chip is AD1845 if I23 is changeable. - */ - - unsigned char tmp = ad_read (devc, 23); - - ad_write (devc, 23, ~tmp); - if (ad_read (devc, 23) != tmp) /* AD1845 ? */ - { - devc->chip_name = "AD1845"; - } + devc->mode = MD_4231A; + break; - ad_write (devc, 23, tmp); /* Restore */ - } + case 0xa2: + devc->chip_name = "CS4232"; + devc->mode = MD_4231A; + break; + + case 0xb2: + devc->chip_name = "CS4232A"; + devc->mode = MD_4231A; + break; + + case 0x80: + { + /* + * It must be a CS4231 or AD1845. The register I23 of + * CS4231 is undefined and it appears to be read only. + * AD1845 uses I23 for setting sample rate. Assume + * the chip is AD1845 if I23 is changeable. + */ + + unsigned char tmp = ad_read (devc, 23); + + ad_write (devc, 23, ~tmp); + if (ad_read (devc, 23) != tmp) /* AD1845 ? */ + { + devc->chip_name = "AD1845"; + devc->mode = MD_1845; + } + + ad_write (devc, 23, tmp); /* Restore */ + } + break; - /* Otherwise behave just as if the chip is a CS4231 */ + default: /* Assume CS4231 */ + devc->mode = MD_4231; + + } } ad_write (devc, 25, tmp1); /* Restore bits */ + } } + if (ad_flags) + { + if (devc->mode != MD_1848) + *ad_flags |= AD_F_CS4231; + } + return 1; } void -ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture) +ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture, int share_dma, sound_os_info * osp) { /* * NOTE! If irq < 0, there is another driver which has allocated the IRQ @@ -1249,7 +1353,7 @@ static int init_values[] = { 0xa8, 0xa8, 0x08, 0x08, 0x08, 0x08, 0x80, 0x80, - 0x00, 0x08, 0x02, 0x00, 0x8a, 0x01, 0x00, 0x00, + 0x00, 0x0c, 0x02, 0x00, 0x8a, 0x01, 0x00, 0x00, /* Positions 16 to 31 just for CS4231 */ 0x80, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, @@ -1258,18 +1362,15 @@ int i, my_dev; ad1848_info *devc = &dev_info[nr_ad1848_devs]; - if (!ad1848_detect (io_base)) + if (!ad1848_detect (io_base, NULL, osp)) return; - devc->irq = (irq > 0) ? irq : 0; - devc->dma_playback = dma_playback; - - if (devc->mode == 2) - devc->dma_capture = dma_capture; - else - devc->dma_capture = dma_playback; /* Use just single DMA */ + request_region (devc->base, 4, devc->chip_name); + devc->irq = (irq > 0) ? irq : 0; devc->opened = 0; + devc->timer_ticks = 0; + devc->osp = osp; if (nr_ad1848_devs != 0) { @@ -1284,16 +1385,35 @@ ad_mute (devc); /* Initialize some variables */ ad_unmute (devc); /* Leave it unmuted now */ - if (devc->mode == 2) + if (devc->mode > MD_1848) { + if (dma_capture == dma_playback || dma_capture == -1 || dma_playback == -1) + { + ad_write (devc, 9, ad_read (devc, 9) | 0x04); /* Single DMA mode */ + ad1848_pcm_operations[nr_ad1848_devs].flags &= ~DMA_DUPLEX; + } + else + { + ad_write (devc, 9, ad_read (devc, 9) & ~0x04); /* Dual DMA mode */ + ad1848_pcm_operations[nr_ad1848_devs].flags |= DMA_DUPLEX; + } + ad_write (devc, 12, ad_read (devc, 12) | 0x40); /* Mode2 = enabled */ for (i = 16; i < 32; i++) ad_write (devc, i, init_values[i]); + + if (devc->mode == MD_4231A) + ad_write (devc, 9, init_values[9] | 0x18); /* Enable full calibration */ + + if (devc->mode == MD_1845) + ad_write (devc, 27, init_values[27] | 0x08); /* Alternate freq select enabled */ } + else + ad_write (devc, 9, ad_read (devc, 9) | 0x04); /* Single DMA mode */ - OUTB (0, io_Status (devc)); /* Clear pending interrupts */ + outb (0, io_Status (devc)); /* Clear pending interrupts */ - if (name[0] != 0) + if (name != NULL && name[0] != 0) sprintf (ad1848_pcm_operations[nr_ad1848_devs].name, "%s (%s)", name, devc->chip_name); else @@ -1306,17 +1426,68 @@ { audio_devs[my_dev = num_audiodevs++] = &ad1848_pcm_operations[nr_ad1848_devs]; if (irq > 0) - irq2dev[irq] = my_dev; + { + audio_devs[my_dev]->devc = devc; + irq2dev[irq] = my_dev; + if (snd_set_irq_handler (devc->irq, ad1848_interrupt, + audio_devs[my_dev]->name, + devc->osp) < 0) + { + printk ("ad1848: IRQ in use\n"); + } + +#ifdef NO_IRQ_TEST + if (devc->mode != MD_1848) + { + int x; + unsigned char tmp = ad_read (devc, 16); + + devc->timer_ticks = 0; + + ad_write (devc, 21, 0x00); /* Timer msb */ + ad_write (devc, 20, 0x10); /* Timer lsb */ + + ad_write (devc, 16, tmp | 0x40); /* Enable timer */ + for (x = 0; x < 100000 && devc->timer_ticks == 0; x++); + ad_write (devc, 16, tmp & ~0x40); /* Disable timer */ + + if (devc->timer_ticks == 0) + printk ("[IRQ conflict???]"); + else + devc->irq_ok = 1; + + } + else + devc->irq_ok = 1; /* Couldn't test. assume it's OK */ +#else + devc->irq_ok = 1; +#endif + } else if (irq < 0) - irq2dev[-irq] = my_dev; + irq2dev[-irq] = devc->dev_no = my_dev; - audio_devs[my_dev]->dmachan = dma_playback; - audio_devs[my_dev]->buffcount = 1; - audio_devs[my_dev]->buffsize = DSP_BUFFSIZE * 2; + audio_devs[my_dev]->dmachan1 = dma_playback; + audio_devs[my_dev]->dmachan2 = dma_capture; + audio_devs[my_dev]->buffsize = DSP_BUFFSIZE; audio_devs[my_dev]->devc = devc; audio_devs[my_dev]->format_mask = ad_format_mask[devc->mode]; nr_ad1848_devs++; +#ifndef EXCLUDE_SEQUENCER + if (devc->mode != MD_1848 && devc->irq_ok) + ad1848_tmr_install (my_dev); +#endif + + if (!share_dma) + { + if (sound_alloc_dma (dma_playback, "Sound System")) + printk ("ad1848.c: Can't allocate DMA%d\n", dma_playback); + + if (dma_capture != dma_playback) + if (sound_alloc_dma (dma_capture, "Sound System (capture)")) + printk ("ad1848.c: Can't allocate DMA%d\n", dma_capture); + } + /* * Toggle the MCE bit. It completes the initialization phase. */ @@ -1337,43 +1508,107 @@ } void -ad1848_interrupt (INT_HANDLER_PARMS (irq, dummy)) +ad1848_unload (int io_base, int irq, int dma_playback, int dma_capture, int share_dma) +{ + int i, dev = 0; + ad1848_info *devc = NULL; + + for (i = 0; devc == NULL && nr_ad1848_devs; i++) + if (dev_info[i].base == io_base) + { + devc = &dev_info[i]; + dev = devc->dev_no; + } + + if (devc != NULL) + { + release_region (devc->base, 4); + + if (!share_dma) + { + if (irq > 0) + snd_release_irq (devc->irq); + + sound_free_dma (audio_devs[dev]->dmachan1); + + if (audio_devs[dev]->dmachan2 != audio_devs[dev]->dmachan1) + sound_free_dma (audio_devs[dev]->dmachan2); + } + } + else + printk ("ad1848: Can't find device to be undoaded. Base=%x\n", + io_base); +} + +void +ad1848_interrupt (int irq, struct pt_regs *dummy) { unsigned char status; ad1848_info *devc; int dev; if (irq < 0 || irq > 15) - return; /* Bogus irq */ - dev = irq2dev[irq]; + { + dev = -1; + } + else + dev = irq2dev[irq]; + if (dev < 0 || dev >= num_audiodevs) - return; /* Bogus dev */ + { + for (irq = 0; irq < 17; irq++) + if (irq2dev[irq] != -1) + break; - devc = (ad1848_info *) audio_devs[dev]->devc; - status = INB (io_Status (devc)); + if (irq > 15) + { + printk ("ad1848.c: Bogus interrupt %d\n", irq); + return; + } + + dev = irq2dev[irq]; + devc = (ad1848_info *) audio_devs[dev]->devc; + } + else + devc = (ad1848_info *) audio_devs[dev]->devc; + + status = inb (io_Status (devc)); if (status == 0x80) printk ("ad1848_interrupt: Why?\n"); if (status & 0x01) { - if (devc->opened && devc->irq_mode == IMODE_OUTPUT) + int alt_stat; + + if (devc->mode != MD_1848) { - DMAbuf_outputintr (dev, 1); + alt_stat = ad_read (devc, 24); + if (alt_stat & 0x40) /* Timer interrupt */ + { + devc->timer_ticks++; +#ifndef EXCLUDE_SEQUENCER + if (timer_installed == dev && devc->timer_running) + sound_timer_interrupt (); +#endif + } } + else + alt_stat = 0xff; - if (devc->opened && devc->irq_mode == IMODE_INPUT) - DMAbuf_inputintr (dev); + if (devc->opened && devc->irq_mode & PCM_ENABLE_INPUT && alt_stat & 0x20) + { + DMAbuf_inputintr (dev); + } + + if (devc->opened && devc->irq_mode & PCM_ENABLE_OUTPUT && alt_stat & 0x10) + { + DMAbuf_outputintr (dev, 1); + } } - OUTB (0, io_Status (devc)); /* Clear interrupt status */ + outb (0, io_Status (devc)); /* Clear interrupt status */ - status = INB (io_Status (devc)); - if (status == 0x80 || status & 0x01) - { - printk ("ad1848: Problems when clearing interrupt, status=%x\n", status); - OUTB (0, io_Status (devc)); /* Try again */ - } } /* @@ -1383,6 +1618,14 @@ int probe_ms_sound (struct address_info *hw_config) { + unsigned char tmp; + + if (check_region (hw_config->io_base, 8)) + { + printk ("MSS: I/O port conflict\n"); + return 0; + } + #if !defined(EXCLUDE_AEDSP16) && defined(AEDSP16_MSS) /* * Initialize Audio Excel DSP 16 to MSS: before any operation @@ -1395,14 +1638,17 @@ /* * Check if the IO port returns valid signature. The original MS Sound * system returns 0x04 while some cards (AudioTriX Pro for example) - * return 0x00. + * return 0x00 or 0x0f. */ - if ((INB (hw_config->io_base + 3) & 0x3f) != 0x04 && - (INB (hw_config->io_base + 3) & 0x3f) != 0x00) + if ((tmp = inb (hw_config->io_base + 3)) == 0xff) /* Bus float */ + return 0; + if ((tmp & 0x3f) != 0x04 && + (tmp & 0x3f) != 0x0f && + (tmp & 0x3f) != 0x00) { DDB (printk ("No MSS signature detected on port 0x%x (0x%x)\n", - hw_config->io_base, INB (hw_config->io_base + 3))); + hw_config->io_base, inb (hw_config->io_base + 3))); return 0; } @@ -1422,19 +1668,19 @@ * Check that DMA0 is not in use with a 8 bit board. */ - if (hw_config->dma == 0 && INB (hw_config->io_base + 3) & 0x80) + if (hw_config->dma == 0 && inb (hw_config->io_base + 3) & 0x80) { printk ("MSS: Can't use DMA0 with a 8 bit card/slot\n"); return 0; } - if (hw_config->irq > 7 && hw_config->irq != 9 && INB (hw_config->io_base + 3) & 0x80) + if (hw_config->irq > 7 && hw_config->irq != 9 && inb (hw_config->io_base + 3) & 0x80) { printk ("MSS: Can't use IRQ%d with a 8 bit card/slot\n", hw_config->irq); return 0; } - return ad1848_detect (hw_config->io_base + 4); + return ad1848_detect (hw_config->io_base + 4, NULL, hw_config->osp); } long @@ -1453,7 +1699,7 @@ int config_port = hw_config->io_base + 0, version_port = hw_config->io_base + 3; - if (!ad1848_detect (hw_config->io_base + 4)) + if (!ad1848_detect (hw_config->io_base + 4, NULL, hw_config->osp)) return mem_start; /* @@ -1464,17 +1710,174 @@ if (bits == -1) return mem_start; - OUTB (bits | 0x40, config_port); - if ((INB (version_port) & 0x40) == 0) + outb (bits | 0x40, config_port); + if ((inb (version_port) & 0x40) == 0) printk ("[IRQ Conflict?]"); - OUTB (bits | dma_bits[hw_config->dma], config_port); /* Write IRQ+DMA setup */ + outb (bits | dma_bits[hw_config->dma], config_port); /* Write IRQ+DMA setup */ ad1848_init ("MS Sound System", hw_config->io_base + 4, hw_config->irq, hw_config->dma, - hw_config->dma); + hw_config->dma, 0, hw_config->osp); + request_region (hw_config->io_base, 4, "WSS config"); return mem_start; } +void +unload_ms_sound (struct address_info *hw_config) +{ + ad1848_unload (hw_config->io_base + 4, + hw_config->irq, + hw_config->dma, + hw_config->dma, 0); + release_region (hw_config->io_base, 4); +} + +/* + * WSS compatible PnP codec support + */ + +int +probe_pnp_ad1848 (struct address_info *hw_config) +{ + return ad1848_detect (hw_config->io_base, NULL, hw_config->osp); +} + +long +attach_pnp_ad1848 (long mem_start, struct address_info *hw_config) +{ + + ad1848_init (hw_config->name, hw_config->io_base, + hw_config->irq, + hw_config->dma, + hw_config->dma2, 0, hw_config->osp); + return mem_start; +} + +void +unload_pnp_ad1848 (struct address_info *hw_config) +{ + ad1848_unload (hw_config->io_base, + hw_config->irq, + hw_config->dma, + hw_config->dma2, 0); + release_region (hw_config->io_base, 4); +} + +#ifndef EXCLUDE_SEQUENCER +/* + * Timer stuff (for /dev/music). + */ + +static unsigned int current_interval = 0; + +static unsigned int +ad1848_tmr_start (int dev, unsigned int usecs) +{ + unsigned long flags; + ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; + unsigned long xtal_nsecs; /* nanoseconds per xtal oscillaror tick */ + unsigned long divider; + + save_flags (flags); + cli (); + +/* + * Length of the timer interval (in nanoseconds) depends on the + * selected crystal oscillator. Check this from bit 0x01 of I8. + * + * AD1845 has just one oscillator which has cycle time of 10.050 us + * (when a 24.576 MHz xtal oscillator is used). + * + * Convert requested interval to nanoseconds before computing + * the timer divider. + */ + + if (devc->mode == MD_1845) + xtal_nsecs = 10050; + else if (ad_read (devc, 8) & 0x01) + xtal_nsecs = 9920; + else + xtal_nsecs = 9969; + + divider = (usecs * 1000 + xtal_nsecs / 2) / xtal_nsecs; + + if (divider < 100) /* Don't allow shorter intervals than about 1ms */ + divider = 100; + + if (divider > 65535) /* Overflow check */ + divider = 65535; + + ad_write (devc, 21, (divider >> 8) & 0xff); /* Set upper bits */ + ad_write (devc, 20, divider & 0xff); /* Set lower bits */ + ad_write (devc, 16, ad_read (devc, 16) | 0x40); /* Start the timer */ + devc->timer_running = 1; + restore_flags (flags); + + return current_interval = (divider * xtal_nsecs + 500) / 1000; +} + +static void +ad1848_tmr_reprogram (int dev) +{ +/* + * Audio driver has changed sampling rate so that a different xtal + * oscillator was selected. We have to reprogram the timer rate. + */ + + ad1848_tmr_start (dev, current_interval); + sound_timer_syncinterval (current_interval); +} + +static void +ad1848_tmr_disable (int dev) +{ + unsigned long flags; + ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; + + save_flags (flags); + cli (); + ad_write (devc, 16, ad_read (devc, 16) & ~0x40); + devc->timer_running = 0; + restore_flags (flags); +} + +static void +ad1848_tmr_restart (int dev) +{ + unsigned long flags; + ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; + + if (current_interval == 0) + return; + + save_flags (flags); + cli (); + ad_write (devc, 16, ad_read (devc, 16) | 0x40); + devc->timer_running = 1; + restore_flags (flags); +} + +static struct sound_lowlev_timer ad1848_tmr = +{ + 0, + ad1848_tmr_start, + ad1848_tmr_disable, + ad1848_tmr_restart +}; + +static int +ad1848_tmr_install (int dev) +{ + + if (timer_installed != -1) + return 0; /* Don't install another timer */ + + timer_installed = ad1848_tmr.dev = dev; + sound_timer_init (&ad1848_tmr, audio_devs[dev]->name); + + return 1; +} +#endif #endif diff -u --recursive --new-file v1.3.33/linux/drivers/sound/ad1848_mixer.h linux/drivers/sound/ad1848_mixer.h --- v1.3.33/linux/drivers/sound/ad1848_mixer.h Mon Jul 31 15:59:02 1995 +++ linux/drivers/sound/ad1848_mixer.h Wed Oct 11 07:55:36 1995 @@ -37,7 +37,7 @@ */ #ifdef GUSMAX_MIXER #define MODE1_REC_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | \ - SOUND_MASK_CD) + SOUND_MASK_CD|SOUND_MASK_IMIX) #define MODE1_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_MIC | \ SOUND_MASK_CD | \ @@ -50,7 +50,7 @@ SOUND_MASK_PCM | SOUND_MASK_IMIX) #else /* Generic mapping */ #define MODE1_REC_DEVICES (SOUND_MASK_LINE3 | SOUND_MASK_MIC | \ - SOUND_MASK_LINE1) + SOUND_MASK_LINE1|SOUND_MASK_IMIX) #define MODE1_MIXER_DEVICES (SOUND_MASK_LINE1 | SOUND_MASK_MIC | \ SOUND_MASK_LINE2 | \ @@ -70,6 +70,14 @@ unsigned int nbits:4; }; +static char mix_cvt[101] = { + 0, 0,3,7,10,13,16,19,21,23,26,28,30,32,34,35,37,39,40,42, + 43,45,46,47,49,50,51,52,53,55,56,57,58,59,60,61,62,63,64,65, + 65,66,67,68,69,70,70,71,72,73,73,74,75,75,76,77,77,78,79,79, + 80,81,81,82,82,83,84,84,85,85,86,86,87,87,88,88,89,89,90,90, + 91,91,92,92,93,93,94,94,95,95,96,96,96,97,97,98,98,98,99,99, + 100 +}; typedef struct mixer_def mixer_ent; @@ -83,7 +91,7 @@ */ #define MIX_ENT(name, reg_l, pola_l, pos_l, len_l, reg_r, pola_r, pos_r, len_r) \ - {{reg_l, pola_l, pos_r, len_l}, {reg_r, pola_r, pos_r, len_r}} + {{reg_l, pola_l, pos_l, len_l}, {reg_r, pola_r, pos_r, len_r}} mixer_ent mix_devices[32][2] = { /* As used in GUS MAX */ MIX_ENT(SOUND_MIXER_VOLUME, 0, 0, 0, 0, 0, 0, 0, 0), @@ -111,9 +119,9 @@ 0x3232, /* Bass */ 0x3232, /* Treble */ 0x4b4b, /* FM */ - 0x6464, /* PCM */ + 0x4040, /* PCM */ 0x4b4b, /* PC Speaker */ - 0x4b4b, /* Ext Line */ + 0x2020, /* Ext Line */ 0x1010, /* Mic */ 0x4b4b, /* CD */ 0x0000, /* Recording monitor */ @@ -121,9 +129,9 @@ 0x4b4b, /* Recording level */ 0x4b4b, /* Input gain */ 0x4b4b, /* Output gain */ - 0x4b4b, /* Line1 */ - 0x4b4b, /* Line2 */ - 0x3232 /* Line3 (usually line in)*/ + 0x4040, /* Line1 */ + 0x4040, /* Line2 */ + 0x2020 /* Line3 (usually line in)*/ }; #define LEFT_CHN 0 diff -u --recursive --new-file v1.3.33/linux/drivers/sound/adlib_card.c linux/drivers/sound/adlib_card.c --- v1.3.33/linux/drivers/sound/adlib_card.c Mon Jul 18 09:50:55 1994 +++ linux/drivers/sound/adlib_card.c Wed Oct 11 07:55:38 1995 @@ -35,9 +35,10 @@ attach_adlib_card (long mem_start, struct address_info *hw_config) { - if (opl3_detect (FM_MONO)) + if (opl3_detect (hw_config->io_base, hw_config->osp)) { - mem_start = opl3_init (mem_start); + mem_start = opl3_init (mem_start, hw_config->io_base, hw_config->osp); + request_region (hw_config->io_base, 4, "OPL3/OPL2"); } return mem_start; } @@ -45,7 +46,20 @@ int probe_adlib (struct address_info *hw_config) { - return opl3_detect (FM_MONO); + + if (check_region (hw_config->io_base, 4)) + { + printk ("\n\nopl3.c: I/O port %x already in use\n\n", hw_config->io_base); + return 0; + } + + return opl3_detect (hw_config->io_base, hw_config->osp); +} + +void +unload_adlib (struct address_info *hw_config) +{ + release_region (hw_config->io_base, 4); } #endif diff -u --recursive --new-file v1.3.33/linux/drivers/sound/aedsp16.c linux/drivers/sound/aedsp16.c --- v1.3.33/linux/drivers/sound/aedsp16.c Tue Jul 11 10:02:52 1995 +++ linux/drivers/sound/aedsp16.c Wed Oct 11 07:55:38 1995 @@ -30,10 +30,10 @@ * headers needed by this source. */ #include "sound_config.h" -/* - * all but ioport.h :) - */ -#include + +#ifndef AEDSP16_BASE +#define EXCLUDE_AEDSP16 +#endif #if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_AEDSP16) /* @@ -209,8 +209,7 @@ - Rearranged the code to let InitAEDSP16 be more general. - Erased the REALLY_SLOW_IO. We don't need it. Erased the linux/io.h inclusion too. We rely on os.h - - Used the INB and OUTB #defined in os.h instead of inb and outb. - - Corrected the code for GetCardName (DSP Copyright) to get a variable + - Used the to get a variable len string (we are not sure about the len of Copyright string). This works with any SB and compatible. - Added the code to request_region at device init (should go in @@ -370,7 +369,7 @@ do { - ret = INB (port + DSP_DATAVAIL); + ret = inb (port + DSP_DATAVAIL); /* * Wait for data available (bit 7 of ret == 1) */ @@ -388,7 +387,7 @@ { if (WaitForDataAvail (port)) return -1; - return INB (port + DSP_READ); + return inb (port + DSP_READ); } static int @@ -403,9 +402,9 @@ /* * Reset DSP */ - OUTB (1, (port + DSP_RESET)); + outb (1, (port + DSP_RESET)); tenmicrosec (); - OUTB (0, (port + DSP_RESET)); + outb (0, (port + DSP_RESET)); tenmicrosec (); tenmicrosec (); return CheckDSPOkay (port); @@ -419,13 +418,13 @@ do { - ret = INB (port + DSP_STATUS); + ret = inb (port + DSP_STATUS); /* * DSP ready to receive data if bit 7 of ret == 0 */ if (!(ret & 0x80)) { - OUTB (cmd, port + DSP_COMMAND); + outb (cmd, port + DSP_COMMAND); return 0; } } @@ -695,6 +694,7 @@ portbase = hw_config->io_base; irq = hw_config->irq; dma = hw_config->dma; + if (InitAEDSP16 (INIT_SBPRO)) return -1; @@ -762,6 +762,7 @@ */ irq = hw_config->irq; dma = hw_config->dma; + if (InitAEDSP16 (INIT_MSS)) return -1; diff -u --recursive --new-file v1.3.33/linux/drivers/sound/audio.c linux/drivers/sound/audio.c --- v1.3.33/linux/drivers/sound/audio.c Sun Aug 13 14:45:33 1995 +++ linux/drivers/sound/audio.c Wed Oct 11 07:55:38 1995 @@ -74,7 +74,7 @@ else fmt = AFMT_U8; /* This is always supported */ - audio_format[dev] = DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, fmt, 1); + audio_format[dev] = DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, (ioctl_arg) fmt, 1); } if (local_conversion[dev]) /* This shadows the HW format */ @@ -113,10 +113,10 @@ local_conversion[dev] = 0; - if (DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, bits, 1) != bits) + if (DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, (ioctl_arg) bits, 1) != bits) { audio_release (dev, file); - return RET_ERROR (ENXIO); + return -ENXIO; } if (dev_type == SND_DEV_AUDIO) @@ -156,31 +156,37 @@ #ifdef NO_INLINE_ASM static void -translate_bytes (const unsigned char *table, unsigned char *buff, unsigned long n) +translate_bytes (const unsigned char *table, unsigned char *buff, int n) { unsigned long i; + if (n <= 0) + return; + for (i = 0; i < n; ++i) buff[i] = table[buff[i]]; } #else extern inline void -translate_bytes (const void *table, void *buff, unsigned long n) +translate_bytes (const void *table, void *buff, int n) { - __asm__ ("cld\n" - "1:\tlodsb\n\t" - "xlatb\n\t" - "stosb\n\t" -"loop 1b\n\t": -: "b" ((long) table), "c" (n), "D" ((long) buff), "S" ((long) buff) -: "bx", "cx", "di", "si", "ax"); + if (n > 0) + { + __asm__ ("cld\n" + "1:\tlodsb\n\t" + "xlatb\n\t" + "stosb\n\t" + "loop 1b\n\t": + : "b" ((long) table), "c" (n), "D" ((long) buff), "S" ((long) buff) + : "bx", "cx", "di", "si", "ax"); + } } #endif int -audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) +audio_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count) { int c, p, l; int err; @@ -190,14 +196,15 @@ p = 0; c = count; - if (audio_mode[dev] == AM_READ) /* - * Direction changed - */ - { + if ((audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX)) + { /* Direction change */ wr_buff_no[dev] = -1; } - audio_mode[dev] = AM_WRITE; + if (audio_devs[dev]->flags & DMA_DUPLEX) + audio_mode[dev] |= AM_WRITE; + else + audio_mode[dev] = AM_WRITE; if (!count) /* * Flush output @@ -225,7 +232,7 @@ dev_nblock[dev])) < 0) { /* Handle nonblocking mode */ - if (dev_nblock[dev] && wr_buff_no[dev] == RET_ERROR (EAGAIN)) + if (dev_nblock[dev] && wr_buff_no[dev] == -EAGAIN) return p; /* No more space. Return # of accepted bytes */ return wr_buff_no[dev]; } @@ -240,7 +247,7 @@ { /* * No device specific copy routine */ - COPY_FROM_USER (&wr_dma_buf[dev][wr_buff_ptr[dev]], buf, p, l); + memcpy_fromfs ((&wr_dma_buf[dev][wr_buff_ptr[dev]]), &((buf)[p]), (l)); } else audio_devs[dev]->copy_from_user (dev, @@ -253,12 +260,10 @@ if (local_conversion[dev] == AFMT_MU_LAW) { -#ifdef linux /* * This just allows interrupts while the conversion is running */ __asm__ ("sti"); -#endif translate_bytes (ulaw_dsp, (unsigned char *) &wr_dma_buf[dev][wr_buff_ptr[dev]], l); } @@ -292,17 +297,21 @@ p = 0; c = count; - if (audio_mode[dev] == AM_WRITE) + if ((audio_mode[dev] & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX)) { if (wr_buff_no[dev] >= 0) { DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]); - wr_buff_no[dev] = -1; + if (!(audio_devs[dev]->flags & DMA_DUPLEX)) + wr_buff_no[dev] = -1; } } - audio_mode[dev] = AM_READ; + if (audio_devs[dev]->flags & DMA_DUPLEX) + audio_mode[dev] |= AM_READ; + else + audio_mode[dev] = AM_READ; while (c) { @@ -311,7 +320,7 @@ { /* Nonblocking mode handling. Return current # of bytes */ - if (dev_nblock[dev] && buff_no == RET_ERROR (EAGAIN)) + if (dev_nblock[dev] && buff_no == -EAGAIN) return p; return buff_no; @@ -326,17 +335,15 @@ if (local_conversion[dev] == AFMT_MU_LAW) { -#ifdef linux /* * This just allows interrupts while the conversion is running */ __asm__ ("sti"); -#endif translate_bytes (dsp_ulaw, (unsigned char *) dmabuf, l); } - COPY_TO_USER (buf, p, dmabuf, l); + memcpy_tofs (&((buf)[p]), (dmabuf), (l)); DMAbuf_rmchars (dev, buff_no, l); @@ -349,7 +356,7 @@ int audio_ioctl (int dev, struct fileinfo *file, - unsigned int cmd, unsigned int arg) + unsigned int cmd, ioctl_arg arg) { dev = dev >> 4; @@ -361,7 +368,7 @@ else printk ("/dev/dsp%d: No coprocessor for this device\n", dev); - return RET_ERROR (EREMOTEIO); + return -ENXIO; } else switch (cmd) @@ -388,40 +395,41 @@ case SNDCTL_DSP_RESET: wr_buff_no[dev] = -1; + audio_mode[dev] = AM_NONE; return DMAbuf_ioctl (dev, cmd, arg, 0); break; case SNDCTL_DSP_GETFMTS: - return IOCTL_OUT (arg, audio_devs[dev]->format_mask); + return snd_ioctl_return ((int *) arg, audio_devs[dev]->format_mask); break; case SNDCTL_DSP_SETFMT: - return IOCTL_OUT (arg, set_format (dev, IOCTL_IN (arg))); + return snd_ioctl_return ((int *) arg, set_format (dev, get_fs_long ((long *) arg))); case SNDCTL_DSP_GETISPACE: - if (audio_mode[dev] == AM_WRITE) - return RET_ERROR (EBUSY); + if ((audio_mode[dev] & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX)) + return -EBUSY; { audio_buf_info info; - int err = DMAbuf_ioctl (dev, cmd, (unsigned long) &info, 1); + int err = DMAbuf_ioctl (dev, cmd, (ioctl_arg) & info, 1); if (err < 0) return err; - IOCTL_TO_USER ((char *) arg, 0, (char *) &info, sizeof (info)); + memcpy_tofs (&(((char *) arg)[0]), ((char *) &info), (sizeof (info))); return 0; } case SNDCTL_DSP_GETOSPACE: - if (audio_mode[dev] == AM_READ) - return RET_ERROR (EBUSY); + if ((audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX)) + return -EBUSY; { audio_buf_info info; - int err = DMAbuf_ioctl (dev, cmd, (unsigned long) &info, 1); + int err = DMAbuf_ioctl (dev, cmd, (ioctl_arg) & info, 1); if (err < 0) return err; @@ -429,7 +437,7 @@ if (wr_buff_no[dev] != -1) info.bytes += wr_buff_size[dev] - wr_buff_ptr[dev]; - IOCTL_TO_USER ((char *) arg, 0, (char *) &info, sizeof (info)); + memcpy_tofs (&(((char *) arg)[0]), ((char *) &info), (sizeof (info))); return 0; } @@ -438,6 +446,27 @@ return 0; break; + case SNDCTL_DSP_GETCAPS: + { + int info = 1; /* Revision level of this ioctl() */ + + if (audio_devs[dev]->flags & DMA_DUPLEX) + info |= DSP_CAP_DUPLEX; + + if (audio_devs[dev]->coproc) + info |= DSP_CAP_COPROC; + + if (audio_devs[dev]->local_qlen) /* Device has hidden buffers */ + info |= DSP_CAP_BATCH; + + if (audio_devs[dev]->trigger) /* Supports SETTRIGGER */ + info |= DSP_CAP_TRIGGER; + + memcpy_tofs (&(((char *) arg)[0]), ((char *) &info), (sizeof (info))); + return 0; + } + break; + default: return DMAbuf_ioctl (dev, cmd, arg, 0); } @@ -452,31 +481,25 @@ return mem_start; } -#ifdef ALLOW_SELECT int audio_select (int dev, struct fileinfo *file, int sel_type, select_table * wait) { - int l; - char *dmabuf; dev = dev >> 4; switch (sel_type) { case SEL_IN: - if (audio_mode[dev] != AM_READ) /* Wrong direction */ - return 0; + if (!(audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX)) + return 0; /* Not recording */ - if (DMAbuf_getrdbuffer (dev, &dmabuf, &l, - 1 /* Don't block */ ) >= 0) - return 1; /* We have data */ return DMAbuf_select (dev, file, sel_type, wait); break; case SEL_OUT: - if (audio_mode[dev] == AM_READ) /* Wrong direction */ - return 0; + if (!(audio_mode[dev] & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX)) + return 0; /* Wrong direction */ if (wr_buff_no[dev] != -1) return 1; /* There is space in the current buffer */ @@ -491,7 +514,6 @@ return 0; } -#endif /* ALLOW_SELECT */ #else /* EXCLUDE_AUDIO */ /* @@ -501,19 +523,19 @@ int audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) { - return RET_ERROR (EIO); + return -EIO; } int audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) { - return RET_ERROR (EIO); + return -EIO; } int audio_open (int dev, struct fileinfo *file) { - return RET_ERROR (ENXIO); + return -ENXIO; } void @@ -524,13 +546,13 @@ audio_ioctl (int dev, struct fileinfo *file, unsigned int cmd, unsigned int arg) { - return RET_ERROR (EIO); + return -EIO; } int audio_lseek (int dev, struct fileinfo *file, off_t offset, int orig) { - return RET_ERROR (EIO); + return -EIO; } long diff -u --recursive --new-file v1.3.33/linux/drivers/sound/configure.c linux/drivers/sound/configure.c --- v1.3.33/linux/drivers/sound/configure.c Tue Jul 11 10:02:52 1995 +++ linux/drivers/sound/configure.c Wed Oct 11 07:55:39 1995 @@ -2,7 +2,7 @@ /* * sound/configure.c - Configuration program for the Linux Sound Driver * - * Copyright by Hannu Savolainen 1993 + * Copyright by Hannu Savolainen 1993-1995 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -27,6 +27,8 @@ */ #include +#include +#include #define B(x) (1 << (x)) @@ -49,28 +51,31 @@ #define OPT_SSCAPE 10 #define OPT_TRIX 11 #define OPT_MAD16 12 +#define OPT_CS4232 13 +#define OPT_MAUI 14 -#define OPT_HIGHLEVEL 13 /* This must be same than the next one */ -#define OPT_SBPRO 13 -#define OPT_SB16 14 -#define OPT_AEDSP16 15 -#define OPT_AUDIO 16 -#define OPT_MIDI_AUTO 17 -#define OPT_MIDI 18 -#define OPT_YM3812_AUTO 19 -#define OPT_YM3812 20 -#define OPT_SEQUENCER 21 -#define OPT_LAST 21 /* Last defined OPT number */ +#define OPT_HIGHLEVEL 15 /* This must be same than the next one */ +#define OPT_SBPRO 15 +#define OPT_SB16 16 +#define OPT_AEDSP16 17 +#define OPT_AUDIO 18 +#define OPT_MIDI_AUTO 19 +#define OPT_MIDI 20 +#define OPT_YM3812_AUTO 21 +#define OPT_YM3812 22 +#define OPT_SEQUENCER 23 +#define OPT_LAST 23 /* Last defined OPT number */ #define ANY_DEVS (B(OPT_AUDIO)|B(OPT_MIDI)|B(OPT_SEQUENCER)|B(OPT_GUS)| \ B(OPT_MPU401)|B(OPT_PSS)|B(OPT_GUS16)|B(OPT_GUSMAX)| \ B(OPT_MSS)|B(OPT_SSCAPE)|B(OPT_UART6850)|B(OPT_TRIX)| \ - B(OPT_MAD16)) + B(OPT_MAD16)|B(OPT_CS4232)|B(OPT_MAUI)) #define AUDIO_CARDS (B (OPT_PSS) | B (OPT_SB) | B (OPT_PAS) | B (OPT_GUS) | \ B (OPT_MSS) | B (OPT_GUS16) | B (OPT_GUSMAX) | B (OPT_TRIX) | \ - B (OPT_SSCAPE)| B(OPT_MAD16)) + B (OPT_SSCAPE)| B(OPT_MAD16) | B(OPT_CS4232)) #define MIDI_CARDS (B (OPT_PSS) | B (OPT_SB) | B (OPT_PAS) | B (OPT_MPU401) | \ - B (OPT_GUS) | B (OPT_TRIX) | B (OPT_SSCAPE)|B(OPT_MAD16)) + B (OPT_GUS) | B (OPT_TRIX) | B (OPT_SSCAPE)|B(OPT_MAD16) | \ + B (OPT_CS4232)|B(OPT_MAUI)) /* * Options that have been disabled for some reason (incompletely implemented * and/or tested). Don't remove from this list before looking at file @@ -123,6 +128,8 @@ {0, 0, "SSCAPE", 1, 0, 0}, {0, 0, "TRIX", 1, 0, 0}, {0, 0, "MAD16", 1, 0, 0}, + {0, 0, "CS4232", 1, 0, 0}, + {0, 0, "MAUI", 1, 0, 0}, {B (OPT_SB), B (OPT_PAS), "SBPRO", 1, 0, 1}, {B (OPT_SB) | B (OPT_SBPRO), B (OPT_PAS), "SB16", 1, 0, 1}, @@ -150,6 +157,8 @@ "Ensoniq Soundscape support", "MediaTriX AudioTriX Pro support", "Support for MAD16 and/or Mozart based cards", + "Support for Crystal CS4232 based (PnP) cards", + "Support for Turtle Beach Wave Front (Maui, Tropez) synthesizers", "SoundBlaster Pro support", "SoundBlaster 16 support", @@ -172,33 +181,6 @@ int can_select_option (int nr) { -#if 0 - switch (nr) - { - case 0: - fprintf (stderr, "The SoundBlaster, AdLib and ProAudioSpectrum\n" - "CARDS cannot be installed at the same time.\n\n" - "However the PAS16 has a SB emulator so you could select" - "the SoundBlaster DRIVER with it.\n"); - fprintf (stderr, " - ProAudioSpectrum 16\n"); - fprintf (stderr, " - SoundBlaster / SB Pro\n"); - fprintf (stderr, " (Could be selected with a PAS16 also)\n"); - fprintf (stderr, " - AdLib\n"); - fprintf (stderr, "\nDon't enable SoundBlaster if you have GUS at 0x220!\n\n"); - break; - - case OPT_LAST_MUTUAL + 1: - fprintf (stderr, "\nThe following cards should work with any other cards.\n" - "CAUTION! Don't enable MPU-401 if you don't have it.\n"); - break; - - case OPT_HIGHLEVEL: - fprintf (stderr, "\nSelect one or more of the following options\n"); - break; - - - } -#endif if (hw_table[nr].conditions) if (!(hw_table[nr].conditions & selected_options)) @@ -220,7 +202,7 @@ char answ[512]; int len; - if ((len = read (0, &answ, sizeof (answ))) < 1) + if ((len = read (0, answ, sizeof (answ))) < 1) { fprintf (stderr, "\n\nERROR! Cannot read stdin\n"); @@ -251,7 +233,7 @@ play_it_again_Sam: - if ((len = read (0, &answ, sizeof (answ))) < 1) + if ((len = read (0, answ, sizeof (answ))) < 1) { fprintf (stderr, "\n\nERROR! Cannot read stdin\n"); @@ -282,76 +264,46 @@ { int i, num, def_size, full_driver = 1; char answ[10]; + int sb_base = 0; printf ("/*\tGenerated by configure. Don't edit!!!!\t*/\n\n"); fprintf (stderr, "\nConfiguring the sound support\n\n"); -#if 0 - /* - * The full driver appeared to be impossible to compile and boot. - * There are too much supported cards now. - */ - fprintf (stderr, "Do you want to include full version of the sound driver (n/y) ? "); + { + /* + * Partial driver + */ - if (think_positively (0)) - { - /* - * Select all but some most dangerous cards. These cards are difficult to - * detect reliably or conflict with some other cards (SCSI, Mitsumi) - */ - selected_options = 0xffffffff & - ~(B (OPT_MPU401) | B (OPT_UART6850) | B (OPT_PSS)) & - ~DISABLED_OPTIONS; + full_driver = 0; - fprintf (stderr, "Note! MPU-401, PSS and 6850 UART drivers not enabled\n"); - full_driver = 1; - } - else -#endif - { -#if 0 - fprintf (stderr, "Do you want to DISABLE the Sound Driver (n/y) ?"); - if (think_positively (0)) + for (i = 0; i <= OPT_LAST; i++) + if (can_select_option (i)) { - printf ("#undef CONFIGURE_SOUNDCARD\n"); - printf ("#undef KERNEL_SOUNDCARD\n"); - exit (0); - } -#endif - /* - * Partial driver - */ - - full_driver = 0; - - for (i = 0; i <= OPT_LAST; i++) - if (can_select_option (i)) - { - if (!(selected_options & B (i))) /* + if (!(selected_options & B (i))) /* * Not selected yet */ - if (!hw_table[i].verify) - { + if (!hw_table[i].verify) + { + if (hw_table[i].alias) + selected_options |= B (hw_table[i].alias); + else + selected_options |= B (i); + } + else + { + int def_answ = hw_table[i].default_answ; + + fprintf (stderr, + def_answ ? " %s (y/n) ? " : " %s (n/y) ? ", + questions[i]); + if (think_positively (def_answ)) if (hw_table[i].alias) selected_options |= B (hw_table[i].alias); else selected_options |= B (i); - } - else - { - int def_answ = hw_table[i].default_answ; - - fprintf (stderr, - def_answ ? " %s (y/n) ? " : " %s (n/y) ? ", - questions[i]); - if (think_positively (def_answ)) - if (hw_table[i].alias) - selected_options |= B (hw_table[i].alias); - else - selected_options |= B (i); - } - } - } + } + } + } if (selected_options & B (OPT_SBPRO)) { @@ -493,6 +445,8 @@ if (think_positively (1)) goto genld_again; } + else + printf ("#define PSS_HAVE_LD\n"); } else { @@ -543,6 +497,8 @@ else printf ("#define KERNEL_SOUNDCARD\n"); + printf ("#define EXCLUDE_PNP\n"); + for (i = 0; i <= OPT_LAST; i++) if (!hw_table[i].alias) if (selected_options & B (i)) @@ -556,7 +512,6 @@ */ printf ("\n"); -#if defined(linux) if (selected_options & B (OPT_AEDSP16)) { fprintf (stderr, "\nI/O base for Audio Excel DSP 16 ?\n" @@ -577,7 +532,7 @@ "The factory default is 220\n" "Enter the SB I/O base: "); - num = ask_value ("%x", 0x220); + sb_base = num = ask_value ("%x", 0x220); fprintf (stderr, "SB I/O base set to %03x\n", num); printf ("#define SBC_BASE 0x%03x\n", num); @@ -718,7 +673,7 @@ num = 0x220; } - if ((selected_options & B (OPT_SB)) && (num == 0x220)) + if ((selected_options & B (OPT_SB)) && (num == sb_base)) { fprintf (stderr, "FATAL ERROR!!!!!!!!!!!!!!\n" "\t0x220 cannot be used if SoundBlaster is enabled.\n" @@ -763,26 +718,20 @@ fprintf (stderr, "\nGravis UltraSound DMA set to %d\n", num); printf ("#define GUS_DMA %d\n", num); - if (selected_options & B (OPT_GUSMAX)) - { - fprintf (stderr, "\nSecond DMA channel for GUS MAX (optional)?\n" - "The default value is 7 (0 disables)\n" - "Enter the value: "); - - num = ask_value ("%d", 7); - if (num > 0) - { - if (num > 7) - { - fprintf (stderr, "*** Illegal input! ***\n"); - num = 7; - } + fprintf (stderr, "\nSecond DMA channel for GUS (optional)?\n" + "The default value is 7 (-1 disables)\n" + "Enter the value: "); - fprintf (stderr, "\nGUSMAX DMA set to %d\n", num); - printf ("#define GUSMAX_DMA %d\n", num); - } + num = ask_value ("%d", 7); + if (num > 7) + { + fprintf (stderr, "*** Illegal input! ***\n"); + num = 7; } + fprintf (stderr, "\nGUS DMA2 set to %d\n", num); + printf ("#define GUS_DMA2 %d\n", num); + if (selected_options & B (OPT_GUS16)) { fprintf (stderr, "\nI/O base for GUS16 (GUS 16 bit sampling option)?\n" @@ -895,6 +844,7 @@ fprintf (stderr, "PSS I/O base set to %03x\n", num); printf ("#define PSS_BASE 0x%03x\n", num); +#if YOU_WANT_TO_WASTE_RESOURCES fprintf (stderr, "\nIRQ number for PSS?\n" "Valid numbers are: 3, 4, 5, 7, 9(=2) or 10.\n" "The default value is 10.\n" @@ -922,6 +872,7 @@ } fprintf (stderr, "\nECHO-PSS DMA set to %d\n", num); printf ("#define PSS_DMA %d\n", num); +#endif fprintf (stderr, "\nMSS (MS Sound System) I/O base for the PSS card?\n" "The factory default is 530\n" @@ -1155,6 +1106,21 @@ fprintf (stderr, "\nAudioTriX/WSS DMA set to %d\n", num); printf ("#define TRIX_DMA %d\n", num); + fprintf (stderr, "\nSecond (capture) DMA number for AudioTriX?\n" + "Valid values are 0, 1 and 3.\n" + "The default value is 0\n" + "(-1 disables the second DMA)\n" + "Enter the value: "); + + num = ask_value ("%d", 0); + if (num != 0 && num != 1 && num != 3 || num != -1) + { + fprintf (stderr, "*** Illegal input! ***\n"); + num = 0; + } + fprintf (stderr, "\nAudioTriX/WSS DMA2 set to %d\n", num); + printf ("#define TRIX_DMA2 %d\n", num); + fprintf (stderr, "\nSoundBlaster I/O address for the AudioTriX card?\n" "The factory default is 220\n" "Other possible values are 200, 210, 230, 240, 250, 260 and 270\n" @@ -1216,6 +1182,88 @@ printf ("#define TRIX_MPU_IRQ %d\n", num); } + if (selected_options & B (OPT_CS4232)) + { + int dma1; + + fprintf (stderr, "\nWindows Sound System I/O base for CS4232?\n" + "The factory default is 534\n" + "Other possible values are 608, E84 or F44\n" + "Enter the MSS I/O base: "); + + num = ask_value ("%x", 0x534); + fprintf (stderr, "CS4232 MSS I/O base set to %03x\n", num); + printf ("#define CS4232_BASE 0x%03x\n", num); + + fprintf (stderr, "\nIRQ number for the WSS mode of CS4232 ?\n" + "Valid numbers are: 5, 7, 9(=2), 11, 12 or 15.\n" + "The default value is 11.\n" + "Enter the value: "); + + num = ask_value ("%d", 11); + if (num != 5 && num != 7 && num != 9 && num != 11 && num != 12 || num != 15) + { + fprintf (stderr, "*** Illegal input! ***\n"); + num = 11; + } + fprintf (stderr, " CS4232 WSS IRQ set to %d\n", num); + printf ("#define CS4232_IRQ %d\n", num); + + fprintf (stderr, "\nWSS DMA number for CS4232?\n" + "Valid values are 0, 1 and 3.\n" + "The default value is 0\n" + "(select the lowes possible one if you want to\n" + "use full duplex mode)\n" + "Enter the value: "); + + num = ask_value ("%d", 0); + if (num != 0 && num != 1 && num != 3) + { + fprintf (stderr, "*** Illegal input! ***\n"); + num = 0; + } + fprintf (stderr, "\nCS4232/WSS DMA set to %d\n", num); + printf ("#define CS4232_DMA %d\n", num); + dma1 = num; + + fprintf (stderr, "\n Second WSS DMA number for CS4232?\n" + "Valid values are 0, 1 and 3.\n" + "The default value is 3\n" + "Enter the value (-1 disables duplex mode): "); + + num = ask_value ("%d", 3); + if (num == dma1 || (num != -1 && num != 0 && num != 1 && num != 3)) + { + fprintf (stderr, "*** Illegal input! ***\n"); + num = 3; + } + fprintf (stderr, "\nCS4232/WSS DMA2 set to %d\n", num); + printf ("#define CS4232_DMA2 %d\n", num); + + fprintf (stderr, "\nMIDI (MPU-401) I/O address for the CS4232 card?\n" + "The factory default is 330\n" + "Other possible values are 330, 370, 3B0 and 3F0\n" + "Enter the MPU I/O base: "); + + num = ask_value ("%x", 0x330); + fprintf (stderr, "CS4232 MIDI I/O base set to %03x\n", num); + printf ("#define CS4232_MPU_BASE 0x%03x\n", num); + + fprintf (stderr, "\nMIDI IRQ number for CS4232?\n" + "Valid numbers are: 5, 7, 9(=2), 11, 12 or 15.\n" + "The default value is 5.\n" + "Enter the value: "); + + num = ask_value ("%d", 5); + if (num != 5 && num != 7 && num != 9 && num != 11 && num != 12 || num != 15) + { + fprintf (stderr, "*** Illegal input! ***\n"); + num = 5; + } + fprintf (stderr, " CS4232 MIDI IRQ set to %d\n", num); + printf ("#define CS4232_MPU_IRQ %d\n", num); + } + if (selected_options & B (OPT_MAD16)) { fprintf (stderr, "\n*** Options for the MAD16 and Mozart based cards ***\n\n"); @@ -1230,6 +1278,20 @@ fprintf (stderr, "MAD16 MSS I/O base set to %03x\n", num); printf ("#define MAD16_BASE 0x%03x\n", num); + if ((sb_base == 0x220 && (num == 0x530 || num == 0x480)) || + (sb_base == 0x240 && (num == 0xf40 || num == 0x604))) + { + fprintf (stderr, "FATAL ERROR!!!!!!!!!!!!!!\n" + "\tThis I/O port selection makes MAD16/Mozart\n" + "\tto use 0x%03x as the SB port.\n" + "\tThis conflicts with the true SB card.\n" + "\tRun the config again and select another I/O base.\n", + sb_base); + printf ("#undef CONFIGURE_SOUNDCARD\n"); + printf ("#undef KERNEL_SOUNDCARD\n"); + exit (-1); + } + fprintf (stderr, "\nIRQ number for the WSS mode of MAD16/Mozart ?\n" "Valid numbers are: 7, 9(=2), 10 and 11.\n" "The default value is 11.\n" @@ -1244,7 +1306,7 @@ fprintf (stderr, " MAD16 WSS IRQ set to %d\n", num); printf ("#define MAD16_IRQ %d\n", num); - fprintf (stderr, "\nWSS DMA number for MAD16/Mozart?\n" + fprintf (stderr, "\nWSS DMA (playback) number for MAD16/Mozart?\n" "Valid values are 0, 1 and 3.\n" "The default value is 3\n" "Enter the value: "); @@ -1258,12 +1320,29 @@ fprintf (stderr, "\nMAD16/WSS DMA set to %d\n", num); printf ("#define MAD16_DMA %d\n", num); - fprintf (stderr, "\nMIDI (MPU-401) I/O address for the MAD16 card?\n" - "(MPU401 is not supported by Mozart and 82C928)\n" + num = (num == 0) ? 1 : 0; + + fprintf (stderr, "\nMAD16/Mozart supports full duplex mode if the\n" + "card has a suitable codec chip (CS423x or AD1845).\n" + "This mode requires another DMA channel (DMA%d)\n" + "Do you want to enable this mode? (n/y)", num); + + if (think_positively (0)) + { + fprintf (stderr, "\nMAD16/WSS capture DMA set to %d\n", num); + printf ("#define MAD16_DMA2 %d\n", num); + } + else + printf ("#define MAD16_DMA2 -1\n"); + + + fprintf (stderr, "\nMIDI (MPU-401/SB) I/O address for the MAD16 card?\n" "(This is the second MIDI port in TB Tropez)\n" - "The factory default is 330 (use 0 to disable)\n" "Other possible values are 330, 320, 310 and 300\n" - "Enter the MPU I/O base: "); + "For 82C928 and Mozart you may use any nonzero value\n" + "since the driver ignores this setting.\n" + "The factory default is 330 (use 0 to disable)\n" + "Enter the MIDI I/O base: "); num = ask_value ("%x", 0x330); if (num == 0) @@ -1288,7 +1367,6 @@ printf ("#define MAD16_MPU_IRQ %d\n", num); } } -#endif if (selected_options & B (OPT_AUDIO)) { diff -u --recursive --new-file v1.3.33/linux/drivers/sound/cs4232.c linux/drivers/sound/cs4232.c --- v1.3.33/linux/drivers/sound/cs4232.c Thu Jan 1 02:00:00 1970 +++ linux/drivers/sound/cs4232.c Wed Oct 11 07:55:39 1995 @@ -0,0 +1,256 @@ +/* + * sound/cs4232.c + * + * The low level driver for Crystal CS4232 based cards. The CS4232 is + * a PnP compatible chip which contains a CS4231A codec, SB emulation, + * a MPU401 compatible MIDI port, joystick and synthesizer and IDE CD-ROM + * interfaces. This is just a temporary driver until full PnP support + * gets inplemented. Just the WSS codec, FM synth and the MIDI ports are + * supported. Other interfaces are left uninitialized. + * + * Copyright by Hannu Savolainen 1995 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. 2. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include "sound_config.h" + +#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_CS4232) + +#define KEY_PORT 0x279 /* Same as LPT1 status port */ +#define CSN_NUM 0x99 /* Just a random number */ + +#define CS_OUT(a) outb( a, KEY_PORT) +#define CS_OUT2(a, b) {CS_OUT(a);CS_OUT(b);} +#define CS_OUT3(a, b, c) {CS_OUT(a);CS_OUT(b);CS_OUT(c);} + +static int mpu_base = 0, mpu_irq = 0; + +int +probe_cs4232_mpu (struct address_info *hw_config) +{ +/* + * Just write down the config values. + */ + + mpu_base = hw_config->io_base; + mpu_irq = hw_config->irq; + return 0; +} + +long +attach_cs4232_mpu (long mem_start, struct address_info *hw_config) +{ + return mem_start; +} + +static unsigned char crystal_key[] = /* A 32 byte magic key sequence */ +{ + 0x96, 0x35, 0x9a, 0xcd, 0xe6, 0xf3, 0x79, 0xbc, + 0x5e, 0xaf, 0x57, 0x2b, 0x15, 0x8a, 0xc5, 0xe2, + 0xf1, 0xf8, 0x7c, 0x3e, 0x9f, 0x4f, 0x27, 0x13, + 0x09, 0x84, 0x42, 0xa1, 0xd0, 0x68, 0x34, 0x1a +}; + +int +probe_cs4232 (struct address_info *hw_config) +{ + int i; + int base = hw_config->io_base, irq = hw_config->irq; + int dma1 = hw_config->dma, dma2 = hw_config->dma2; + +/* + * Verify that the I/O port range is free. + */ + + if (check_region (base, 4)) + { + printk ("cs4232.c: I/O port 0x%03x not free\n", base); + return 0; + } + +/* + * This version of the driver doesn't use the PnP method when configuring + * the card but a simplified method defined by Crystal. This means that + * just one CS4232 compatible device can exist on the system. Also this + * method conflicts with possible PnP support in the OS. For this reason + * driver is just a temporary kludge. + */ + +/* + * Wake up the card by sending a 32 byte Crystal key to the key port. + */ + for (i = 0; i < 32; i++) + CS_OUT (crystal_key[i]); + +/* + * Now set the CSN (Card Select Number). + */ + + CS_OUT2 (0x06, CSN_NUM); + +/* + * Ensure that there is no other codec using the same address. + */ + + CS_OUT2 (0x15, 0x00); /* Select logical device 0 (WSS/SB/FM) */ + CS_OUT2 (0x33, 0x00); /* Inactivate logical dev 0 */ + if (ad1848_detect (hw_config->io_base, NULL, hw_config->osp)) + return 0; + +/* + * Then set some config bytes. First logical device 0 + */ + + CS_OUT2 (0x15, 0x00); /* Select logical device 0 (WSS/SB/FM) */ + CS_OUT3 (0x47, (base >> 8) & 0xff, base & 0xff); /* WSSbase */ + + if (check_region (0x388, 4)) /* Not free */ + CS_OUT3 (0x48, 0x00, 0x00) /* FMbase off */ + else + CS_OUT3 (0x48, 0x03, 0x88); /* FMbase 0x388 */ + + CS_OUT3 (0x42, 0x00, 0x00); /* SBbase off */ + CS_OUT2 (0x22, irq); /* SB+WSS IRQ */ + CS_OUT2 (0x2a, dma1); /* SB+WSS DMA */ + + if (dma2 != -1) + CS_OUT2 (0x25, dma2) /* WSS DMA2 */ + else + CS_OUT2 (0x25, 4); /* No WSS DMA2 */ + + CS_OUT2 (0x33, 0x01); /* Activate logical dev 0 */ + +/* + * Initialize logical device 3 (MPU) + */ + +#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI) + if (mpu_base != 0 && mpu_irq != 0) + { + CS_OUT2 (0x15, 0x03); /* Select logical device 3 (MPU) */ + CS_OUT3 (0x47, (mpu_base >> 8) & 0xff, mpu_base & 0xff); /* MPUbase */ + CS_OUT2 (0x22, mpu_irq); /* MPU IRQ */ + CS_OUT2 (0x33, 0x01); /* Activate logical dev 3 */ + } +#endif + +/* + * Finally activate the chip + */ + CS_OUT (0x79); + +/* + * Then try to detect the codec part of the chip + */ + + return ad1848_detect (hw_config->io_base, NULL, hw_config->osp); +} + +long +attach_cs4232 (long mem_start, struct address_info *hw_config) +{ + int base = hw_config->io_base, irq = hw_config->irq; + int dma1 = hw_config->dma, dma2 = hw_config->dma2; + + if (dma2 == -1) + dma2 = dma1; + + ad1848_init ("CS4232", base, + irq, + dma1, /* Playback DMA */ + dma2, /* Capture DMA */ + 0, + hw_config->osp); + +#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI) + if (mpu_base != 0 && mpu_irq != 0) + { + static struct address_info hw_config2 = + {0}; /* Ensure it's initialized */ + + hw_config2.io_base = mpu_base; + hw_config2.irq = mpu_irq; + hw_config2.dma = -1; + hw_config2.dma2 = -1; + hw_config2.always_detect = 0; + hw_config2.name = NULL; + hw_config2.driver_use_1 = 0; + hw_config2.driver_use_2 = 0; + hw_config2.osp = hw_config->osp; + + if (probe_mpu401 (&hw_config2)) + { + mem_start = attach_mpu401 (mem_start, &hw_config2); + } + else + { + mpu_base = mpu_irq = 0; + } + } +#endif + return mem_start; +} + +void +unload_cs4232 (struct address_info *hw_config) +{ + int base = hw_config->io_base, irq = hw_config->irq; + int dma1 = hw_config->dma, dma2 = hw_config->dma2; + + if (dma2 == -1) + dma2 = dma1; + + ad1848_unload (base, + irq, + dma1, /* Playback DMA */ + dma2, /* Capture DMA */ + 0); + +#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI) + if (mpu_base != 0 && mpu_irq != 0) + { + static struct address_info hw_config2 = + {0}; /* Ensure it's initialized */ + + hw_config2.io_base = mpu_base; + hw_config2.irq = mpu_irq; + hw_config2.dma = -1; + hw_config2.dma2 = -1; + hw_config2.always_detect = 0; + hw_config2.name = NULL; + hw_config2.driver_use_1 = 0; + hw_config2.driver_use_2 = 0; + hw_config2.osp = hw_config->osp; + + unload_mpu401 (&hw_config2); + } +#endif +} + +void +unload_cs4232_mpu (struct address_info *hw_config) +{ + /* Not required. Handled by cs4232_unload */ +} + +#endif diff -u --recursive --new-file v1.3.33/linux/drivers/sound/dev_table.c linux/drivers/sound/dev_table.c --- v1.3.33/linux/drivers/sound/dev_table.c Tue Jul 11 10:02:52 1995 +++ linux/drivers/sound/dev_table.c Wed Oct 11 07:55:39 1995 @@ -35,9 +35,9 @@ int snd_find_driver (int type) { - int i, n = sizeof (sound_drivers) / sizeof (struct driver_info); + int i, n = num_sound_drivers; - for (i = 0; i < (n - 1); i++) + for (i = 0; i < n; i++) if (sound_drivers[i].card_type == type) return i; @@ -49,69 +49,118 @@ long sndtable_init (long mem_start) { - int i, n = sizeof (snd_installed_cards) / sizeof (struct card_info); + int i, n = num_sound_cards; int drv; printk ("Sound initialization started\n"); - for (i = 0; i < (n - 1); i++) +/* + * Check the number of cards actually defined in the table + */ + + for (i = 0; i < n && snd_installed_cards[i].card_type; i++) + num_sound_cards = i + 1; + + for (i = 0; i < n && snd_installed_cards[i].card_type; i++) if (snd_installed_cards[i].enabled) - if ((drv = snd_find_driver (snd_installed_cards[i].card_type)) == -1) - snd_installed_cards[i].enabled = 0; /* + { + snd_installed_cards[i].for_driver_use = NULL; + + if ((drv = snd_find_driver (snd_installed_cards[i].card_type)) == -1) + snd_installed_cards[i].enabled = 0; /* * Mark as not detected */ - else if (sound_drivers[drv].probe (&snd_installed_cards[i].config)) - { + else if (sound_drivers[drv].probe (&snd_installed_cards[i].config)) + { #ifndef SHORT_BANNERS - printk ("snd%d", - snd_installed_cards[i].card_type); + printk ("snd%d", + snd_installed_cards[i].card_type); #endif - mem_start = sound_drivers[drv].attach (mem_start, &snd_installed_cards[i].config); + mem_start = sound_drivers[drv].attach (mem_start, &snd_installed_cards[i].config); #ifndef SHORT_BANNERS - printk (" at 0x%x irq %d drq %d\n", - snd_installed_cards[i].config.io_base, - snd_installed_cards[i].config.irq, - snd_installed_cards[i].config.dma); + printk (" at 0x%x irq %d drq %d", + snd_installed_cards[i].config.io_base, + snd_installed_cards[i].config.irq, + snd_installed_cards[i].config.dma); + if (snd_installed_cards[i].config.dma2 != -1) + printk (",%d\n", + snd_installed_cards[i].config.dma2); + else + printk ("\n"); #endif - } - else - snd_installed_cards[i].enabled = 0; /* + } + else + snd_installed_cards[i].enabled = 0; /* * Mark as not detected */ + } + printk ("Sound initialization complete\n"); return mem_start; } +void +sound_unload_drivers (void) +{ + int i, n = num_sound_cards; + int drv; + + printk ("Sound unload started\n"); + + for (i = 0; i < n && snd_installed_cards[i].card_type; i++) + if (snd_installed_cards[i].enabled) + if ((drv = snd_find_driver (snd_installed_cards[i].card_type)) != -1) + if (sound_drivers[drv].unload) + sound_drivers[drv].unload (&snd_installed_cards[i].config); + + printk ("Sound unload complete\n"); +} + int sndtable_probe (int unit, struct address_info *hw_config) { - int i, n = sizeof (snd_installed_cards) / sizeof (struct card_info); + int i, sel = -1, n = num_sound_cards; if (!unit) return TRUE; - for (i = 0; i < (n - 1); i++) + for (i = 0; i < n && sel == -1 && snd_installed_cards[i].card_type; i++) if (snd_installed_cards[i].enabled) if (snd_installed_cards[i].card_type == unit) + sel = i; + + if (sel == -1 && num_sound_cards < max_sound_cards) + { + int i; + + i = sel = (num_sound_cards++); + + snd_installed_cards[sel].card_type = unit; + snd_installed_cards[sel].enabled = 1; + } + + if (sel != -1) + { + int drv; + + snd_installed_cards[sel].for_driver_use = NULL; + snd_installed_cards[sel].config.io_base = hw_config->io_base; + snd_installed_cards[sel].config.irq = hw_config->irq; + snd_installed_cards[sel].config.dma = hw_config->dma; + snd_installed_cards[sel].config.dma2 = hw_config->dma2; + if ((drv = snd_find_driver (snd_installed_cards[sel].card_type)) == -1) { - int drv; + snd_installed_cards[sel].enabled = 0; + } + else if (sound_drivers[drv].probe (hw_config)) + return TRUE; - snd_installed_cards[i].config.io_base = hw_config->io_base; - snd_installed_cards[i].config.irq = hw_config->irq; - snd_installed_cards[i].config.dma = hw_config->dma; - if ((drv = snd_find_driver (snd_installed_cards[i].card_type)) == -1) - snd_installed_cards[i].enabled = 0; /* - * Mark as not - * detected - */ - else if (sound_drivers[drv].probe (hw_config)) - return 1; - snd_installed_cards[i].enabled = 0; /* + snd_installed_cards[sel].enabled = 0; /* * Mark as not detected */ - return 0; - } + return FALSE; + } return FALSE; } @@ -119,16 +168,18 @@ int sndtable_init_card (int unit, struct address_info *hw_config) { - int i, n = sizeof (snd_installed_cards) / sizeof (struct card_info); + int i, n = num_sound_cards; + + DDB (printk ("sndtable_init_card(%d) entered\n", unit)); if (!unit) { if (sndtable_init (0) != 0) - panic ("snd: Invalid memory allocation\n"); + panic ("sound: Invalid memory allocation\n"); return TRUE; } - for (i = 0; i < (n - 1); i++) + for (i = 0; i < n && snd_installed_cards[i].card_type; i++) if (snd_installed_cards[i].card_type == unit) { int drv; @@ -136,16 +187,36 @@ snd_installed_cards[i].config.io_base = hw_config->io_base; snd_installed_cards[i].config.irq = hw_config->irq; snd_installed_cards[i].config.dma = hw_config->dma; + snd_installed_cards[i].config.dma2 = hw_config->dma2; if ((drv = snd_find_driver (snd_installed_cards[i].card_type)) == -1) snd_installed_cards[i].enabled = 0; /* * Mark as not detected */ - else if (sound_drivers[drv].attach (0, hw_config) != 0) - panic ("snd#: Invalid memory allocation\n"); + else + { + + DDB (printk ("Located card - calling attach routine\n")); + printk ("snd%d", unit); + if (sound_drivers[drv].attach (0, hw_config) != 0) + panic ("sound: Invalid memory allocation\n"); + + DDB (printk ("attach routine finished\n")); + printk (" at 0x%x irq %d drq %d", + snd_installed_cards[i].config.io_base, + snd_installed_cards[i].config.irq, + snd_installed_cards[i].config.dma); + if (snd_installed_cards[i].config.dma2 != -1) + printk (",%d\n", + snd_installed_cards[i].config.dma2); + else + printk ("\n"); + } return TRUE; } + printk ("sndtable_init_card: No card defined with type=%d, num cards: %d\n", + unit, num_sound_cards); return FALSE; } @@ -155,17 +226,38 @@ return num_audiodevs + num_mixers + num_synths + num_midis; } -#ifdef linux +int +sndtable_identify_card (char *name) +{ + int i, n = num_sound_drivers; + + if (name == NULL) + return 0; + + for (i = 0; i < n; i++) + if (sound_drivers[i].driver_id != NULL) + { + char *id = sound_drivers[i].driver_id; + int j; + + for (j = 0; j < 80 && name[j] == id[j]; j++) + if (id[j] == 0 && name[j] == 0) /* Match */ + return sound_drivers[i].card_type; + } + + return 0; +} + void sound_setup (char *str, int *ints) { - int i, n = sizeof (snd_installed_cards) / sizeof (struct card_info); + int i, n = num_sound_cards; /* * First disable all drivers */ - for (i = 0; i < n; i++) + for (i = 0; i < n && snd_installed_cards[i].card_type; i++) snd_installed_cards[i].enabled = 0; if (ints[0] == 0 || ints[1] == 0) @@ -211,48 +303,20 @@ snd_installed_cards[ptr].config.io_base = ioaddr; snd_installed_cards[ptr].config.irq = irq; snd_installed_cards[ptr].config.dma = dma; + snd_installed_cards[ptr].config.dma2 = -1; } } } -#else -void -sound_chconf (int card_type, int ioaddr, int irq, int dma) -{ - int i, n = sizeof (snd_installed_cards) / sizeof (struct card_info); - - int ptr, j; - - ptr = -1; - for (j = 0; j < n && ptr == -1; j++) - if (snd_installed_cards[j].card_type == card_type && - !snd_installed_cards[j].enabled) /* - * Not already found - */ - ptr = j; - - if (ptr != -1) - { - snd_installed_cards[ptr].enabled = 1; - if (ioaddr) - snd_installed_cards[ptr].config.io_base = ioaddr; - if (irq) - snd_installed_cards[ptr].config.irq = irq; - if (dma) - snd_installed_cards[ptr].config.dma = dma; - } -} - -#endif struct address_info * sound_getconf (int card_type) { int j, ptr; - int n = sizeof (snd_installed_cards) / sizeof (struct card_info); + int n = num_sound_cards; ptr = -1; - for (j = 0; j < n && ptr == -1; j++) + for (j = 0; j < n && ptr == -1 && snd_installed_cards[j].card_type; j++) if (snd_installed_cards[j].card_type == card_type) ptr = j; diff -u --recursive --new-file v1.3.33/linux/drivers/sound/dev_table.h linux/drivers/sound/dev_table.h --- v1.3.33/linux/drivers/sound/dev_table.h Tue Jul 11 10:02:52 1995 +++ linux/drivers/sound/dev_table.h Wed Oct 11 07:55:36 1995 @@ -41,18 +41,28 @@ */ struct driver_info { + char *driver_id; int card_type; /* From soundcard.h */ char *name; long (*attach) (long mem_start, struct address_info *hw_config); int (*probe) (struct address_info *hw_config); + void (*unload) (struct address_info *hw_config); }; struct card_info { int card_type; /* Link (search key) to the driver list */ struct address_info config; int enabled; + void *for_driver_use; }; +typedef struct pnp_sounddev +{ + int id; + void (*setup)(void *dev); + char *driver_name; +}pnp_sounddev; + /* * Device specific parameters (used only by dmabuf.c) */ @@ -69,9 +79,8 @@ * Pointers to raw buffers */ - char *raw_buf[DSP_BUFFCOUNT]; - unsigned long raw_buf_phys[DSP_BUFFCOUNT]; - int raw_count; + char *raw_buf; + unsigned long raw_buf_phys; /* * Device state tables @@ -96,8 +105,6 @@ int nbufs; int counts[MAX_SUB_BUFFERS]; int subdivision; - char *buf[MAX_SUB_BUFFERS]; - unsigned long buf_phys[MAX_SUB_BUFFERS]; int fragment_size; int max_fragments; @@ -105,6 +112,11 @@ int bytes_in_use; int underrun_count; + int byte_counter; + + int mapping_flags; +#define DMA_MAP_MAPPED 0x00000001 + char neutral_byte; }; /* @@ -115,7 +127,7 @@ char name[32]; int (*open) (void *devc, int sub_device); void (*close) (void *devc, int sub_device); - int (*ioctl) (void *devc, unsigned int cmd, unsigned int arg, int local); + int (*ioctl) (void *devc, unsigned int cmd, ioctl_arg arg, int local); void (*reset) (void *devc); void *devc; /* Driver specific info */ @@ -127,6 +139,7 @@ #define NOTHING_SPECIAL 0 #define NEEDS_RESTART 1 #define DMA_AUTOMODE 2 +#define DMA_DUPLEX 4 int format_mask; /* Bitmask for supported audio formats */ void *devc; /* Driver specific info */ int (*open) (int dev, int mode); @@ -135,25 +148,30 @@ int count, int intrflag, int dma_restart); void (*start_input) (int dev, unsigned long buf, int count, int intrflag, int dma_restart); - int (*ioctl) (int dev, unsigned int cmd, unsigned int arg, int local); + int (*ioctl) (int dev, unsigned int cmd, ioctl_arg arg, int local); int (*prepare_for_input) (int dev, int bufsize, int nbufs); int (*prepare_for_output) (int dev, int bufsize, int nbufs); void (*reset) (int dev); void (*halt_xfer) (int dev); int (*local_qlen)(int dev); void (*copy_from_user)(int dev, char *localbuf, int localoffs, - snd_rw_buf *userbuf, int useroffs, int len); - int buffcount; + const snd_rw_buf *userbuf, int useroffs, int len); + void (*halt_input) (int dev); + void (*halt_output) (int dev); + void (*trigger) (int dev, int bits); long buffsize; - int dmachan; - struct dma_buffparms *dmap; + int dmachan1, dmachan2; + struct dma_buffparms *dmap_in, *dmap_out; struct coproc_operations *coproc; int mixer_dev; + int enable_bits; + int open_mode; + int go; }; struct mixer_operations { char name[32]; - int (*ioctl) (int dev, unsigned int cmd, unsigned int arg); + int (*ioctl) (int dev, unsigned int cmd, ioctl_arg arg); }; struct synth_operations { @@ -164,13 +182,13 @@ int (*open) (int dev, int mode); void (*close) (int dev); - int (*ioctl) (int dev, unsigned int cmd, unsigned int arg); + int (*ioctl) (int dev, unsigned int cmd, ioctl_arg arg); int (*kill_note) (int dev, int voice, int note, int velocity); int (*start_note) (int dev, int voice, int note, int velocity); int (*set_instr) (int dev, int voice, int instr); void (*reset) (int dev); void (*hw_control) (int dev, unsigned char *event); - int (*load_patch) (int dev, int format, snd_rw_buf *addr, + int (*load_patch) (int dev, int format, const snd_rw_buf *addr, int offs, int count, int pmgr_flag); void (*aftertouch) (int dev, int voice, int pressure); void (*controller) (int dev, int voice, int ctrl_num, int value); @@ -180,6 +198,7 @@ void (*bender) (int dev, int chn, int value); int (*alloc_voice) (int dev, int chn, int note, struct voice_alloc_info *alloc); void (*setup_voice) (int dev, int voice, int chn); + int (*send_sysex)(int dev, unsigned char *bytes, int len); struct voice_alloc_info alloc; struct channel_info chn_info[16]; @@ -207,7 +226,7 @@ void (*outputintr)(int dev) ); void (*close) (int dev); - int (*ioctl) (int dev, unsigned int cmd, unsigned int arg); + int (*ioctl) (int dev, unsigned int cmd, ioctl_arg arg); int (*putc) (int dev, unsigned char data); int (*start_read) (int dev); int (*end_read) (int dev); @@ -218,6 +237,13 @@ struct coproc_operations *coproc; }; +struct sound_lowlev_timer { + int dev; + unsigned int (*tmr_start)(int dev, unsigned int usecs); + void (*tmr_disable)(int dev); + void (*tmr_restart)(int dev); + }; + struct sound_timer_operations { struct sound_timer_info info; int priority; @@ -226,7 +252,7 @@ void (*close)(int dev); int (*event)(int dev, unsigned char *ev); unsigned long (*get_time)(int dev); - int (*ioctl) (int dev, unsigned int cmd, unsigned int arg); + int (*ioctl) (int dev, unsigned int cmd, ioctl_arg arg); void (*arm_timer)(int dev, long time); }; @@ -253,63 +279,75 @@ struct driver_info sound_drivers[] = { #ifndef EXCLUDE_PSS - {SNDCARD_PSS, "Echo Personal Sound System PSS (ESC614)", attach_pss, probe_pss}, + {"PSSECHO", SNDCARD_PSS, "Echo Personal Sound System PSS (ESC614)", attach_pss, probe_pss, unload_pss}, # ifdef PSS_MPU_BASE - {SNDCARD_PSS_MPU, "PSS-MPU", attach_pss_mpu, probe_pss_mpu}, + {"PSSMPU", SNDCARD_PSS_MPU, "PSS-MPU", attach_pss_mpu, probe_pss_mpu, unload_pss_mpu}, # endif # ifdef PSS_MSS_BASE - {SNDCARD_PSS_MSS, "PSS-MSS", attach_pss_mss, probe_pss_mss}, + {"PSSMSS", SNDCARD_PSS_MSS, "PSS-MSS", attach_pss_mss, probe_pss_mss, unload_pss_mss}, # endif #endif +#ifndef EXCLUDE_MSS + {"MSS", SNDCARD_MSS, "MS Sound System", attach_ms_sound, probe_ms_sound, unload_ms_sound}, + {"PCXBJ", SNDCARD_MSS, "MS Sound System", attach_ms_sound, probe_ms_sound, unload_ms_sound}, +#endif #ifndef EXCLUDE_MAD16 - {SNDCARD_MAD16, "MAD16/Mozart (MSS)", attach_mad16, probe_mad16}, - {SNDCARD_MAD16_MPU, "MAD16/Mozart (MPU)", attach_mad16_mpu, probe_mad16_mpu}, + {"MAD16", SNDCARD_MAD16, "MAD16/Mozart (MSS)", attach_mad16, probe_mad16, unload_mad16}, + {"MAD16MPU", SNDCARD_MAD16_MPU, "MAD16/Mozart (MPU)", attach_mad16_mpu, probe_mad16_mpu, unload_mad16_mpu}, +#endif +#ifndef EXCLUDE_CS4232 + {"CS4232", SNDCARD_CS4232, "CS4232", attach_cs4232, probe_cs4232, unload_cs4232}, + {"CS4232MPU", SNDCARD_CS4232_MPU, "CS4232 MIDI", attach_cs4232_mpu, probe_cs4232_mpu, unload_cs4232_mpu}, #endif #ifndef EXCLUDE_YM3812 - {SNDCARD_ADLIB, "OPL-2/OPL-3 FM", attach_adlib_card, probe_adlib}, + {"OPL3", SNDCARD_ADLIB, "OPL-2/OPL-3 FM", attach_adlib_card, probe_adlib, unload_adlib}, #endif #ifndef EXCLUDE_PAS - {SNDCARD_PAS, "ProAudioSpectrum", attach_pas_card, probe_pas}, + {"PAS16", SNDCARD_PAS, "ProAudioSpectrum", attach_pas_card, probe_pas, unload_pas}, #endif #if !defined(EXCLUDE_MPU401) && !defined(EXCLUDE_MIDI) - {SNDCARD_MPU401,"Roland MPU-401", attach_mpu401, probe_mpu401}, + {"MPU401", SNDCARD_MPU401,"Roland MPU-401", attach_mpu401, probe_mpu401, unload_mpu401}, +#endif +#if !defined(EXCLUDE_MAUI) + {"MAUI", SNDCARD_MAUI,"TB Maui", attach_maui, probe_maui, unload_maui}, #endif #if !defined(EXCLUDE_UART6850) && !defined(EXCLUDE_MIDI) - {SNDCARD_UART6850,"6860 UART Midi", attach_uart6850, probe_uart6850}, + {"MIDI6850", SNDCARD_UART6850,"6860 UART Midi", attach_uart6850, probe_uart6850, unload_uart6850}, #endif #ifndef EXCLUDE_SB - {SNDCARD_SB, "SoundBlaster", attach_sb_card, probe_sb}, + {"SBLAST", SNDCARD_SB, "SoundBlaster", attach_sb_card, probe_sb, unload_sb}, #endif #if !defined(EXCLUDE_SB) && !defined(EXCLUDE_SB16) #ifndef EXCLUDE_AUDIO - {SNDCARD_SB16, "SoundBlaster16", sb16_dsp_init, sb16_dsp_detect}, + {"SB16", SNDCARD_SB16, "SoundBlaster16", sb16_dsp_init, sb16_dsp_detect, unload_sb16}, #endif #ifndef EXCLUDE_MIDI - {SNDCARD_SB16MIDI,"SB16 MIDI", attach_sb16midi, probe_sb16midi}, + {"SB16MIDI", SNDCARD_SB16MIDI,"SB16 MIDI", attach_sb16midi, probe_sb16midi, unload_sb16midi}, #endif #endif #ifndef EXCLUDE_GUS16 - {SNDCARD_GUS16, "Ultrasound 16-bit opt.", attach_gus_db16, probe_gus_db16}, -#endif -#ifndef EXCLUDE_MSS - {SNDCARD_MSS, "MS Sound System", attach_ms_sound, probe_ms_sound}, + {"GUS16", SNDCARD_GUS16, "Ultrasound 16-bit opt.", attach_gus_db16, probe_gus_db16, unload_gus_db16}, #endif #ifndef EXCLUDE_GUS - {SNDCARD_GUS, "Gravis Ultrasound", attach_gus_card, probe_gus}, + {"GUS", SNDCARD_GUS, "Gravis Ultrasound", attach_gus_card, probe_gus, unload_gus}, #endif #ifndef EXCLUDE_SSCAPE - {SNDCARD_SSCAPE, "Ensoniq Soundscape", attach_sscape, probe_sscape}, - {SNDCARD_SSCAPE_MSS, "MS Sound System (SoundScape)", attach_ss_ms_sound, probe_ss_ms_sound}, + {"SSCAPE", SNDCARD_SSCAPE, "Ensoniq Soundscape", attach_sscape, probe_sscape, unload_sscape}, + {"SCAPEMSS", SNDCARD_SSCAPE_MSS, "MS Sound System (SoundScape)", attach_ss_ms_sound, probe_ss_ms_sound, unload_ss_ms_sound}, #endif #ifndef EXCLUDE_TRIX - {SNDCARD_TRXPRO, "MediaTriX AudioTriX Pro", attach_trix_wss, probe_trix_wss}, - {SNDCARD_TRXPRO_SB, "AudioTriX (SB mode)", attach_trix_sb, probe_trix_sb}, - {SNDCARD_TRXPRO_MPU, "AudioTriX MIDI", attach_trix_mpu, probe_trix_mpu}, + {"TRXPRO", SNDCARD_TRXPRO, "MediaTriX AudioTriX Pro", attach_trix_wss, probe_trix_wss, unload_trix_wss}, + {"TRXPROSB", SNDCARD_TRXPRO_SB, "AudioTriX (SB mode)", attach_trix_sb, probe_trix_sb, unload_trix_sb}, + {"TRXPROMPU", SNDCARD_TRXPRO_MPU, "AudioTriX MIDI", attach_trix_mpu, probe_trix_mpu, unload_trix_mpu}, +#endif +#ifndef EXCLUDE_PNP + {"AD1848", 1000, "PnP MSS", attach_pnp_ad1848, probe_pnp_ad1848, unload_pnp_ad1848}, #endif - {0, "*?*", NULL, NULL} + {NULL, 0, "*?*", NULL, NULL, NULL} }; -#ifdef linux + +#ifndef FULL_SOUND /* * List of devices actually configured in the system. * @@ -318,94 +356,113 @@ struct card_info snd_installed_cards[] = { #ifndef EXCLUDE_PSS - {SNDCARD_PSS, {PSS_BASE, PSS_IRQ, PSS_DMA}, SND_DEFAULT_ENABLE}, + {SNDCARD_PSS, {PSS_BASE, PSS_IRQ, PSS_DMA, -1}, SND_DEFAULT_ENABLE}, # ifdef PSS_MPU_BASE - {SNDCARD_PSS_MPU, {PSS_MPU_BASE, PSS_MPU_IRQ, 0}, SND_DEFAULT_ENABLE}, + {SNDCARD_PSS_MPU, {PSS_MPU_BASE, PSS_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, # endif # ifdef PSS_MSS_BASE - {SNDCARD_PSS_MSS, {PSS_MSS_BASE, PSS_MSS_IRQ, PSS_MSS_DMA}, SND_DEFAULT_ENABLE}, + {SNDCARD_PSS_MSS, {PSS_MSS_BASE, PSS_MSS_IRQ, PSS_MSS_DMA, -1}, SND_DEFAULT_ENABLE}, # endif #endif #ifndef EXCLUDE_TRIX - {SNDCARD_TRXPRO, {TRIX_BASE, TRIX_IRQ, TRIX_DMA}, SND_DEFAULT_ENABLE}, + {SNDCARD_TRXPRO, {TRIX_BASE, TRIX_IRQ, TRIX_DMA, TRIX_DMA2}, SND_DEFAULT_ENABLE}, # ifdef TRIX_SB_BASE - {SNDCARD_TRXPRO_SB, {TRIX_SB_BASE, TRIX_SB_IRQ, TRIX_SB_DMA}, SND_DEFAULT_ENABLE}, + {SNDCARD_TRXPRO_SB, {TRIX_SB_BASE, TRIX_SB_IRQ, TRIX_SB_DMA, -1}, SND_DEFAULT_ENABLE}, # endif # ifdef TRIX_MPU_BASE - {SNDCARD_TRXPRO_MPU, {TRIX_MPU_BASE, TRIX_MPU_IRQ, 0}, SND_DEFAULT_ENABLE}, + {SNDCARD_TRXPRO_MPU, {TRIX_MPU_BASE, TRIX_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, # endif #endif #ifndef EXCLUDE_SSCAPE - {SNDCARD_SSCAPE, {SSCAPE_BASE, SSCAPE_IRQ, SSCAPE_DMA}, SND_DEFAULT_ENABLE}, - {SNDCARD_SSCAPE_MSS, {SSCAPE_MSS_BASE, SSCAPE_MSS_IRQ, SSCAPE_MSS_DMA}, SND_DEFAULT_ENABLE}, + {SNDCARD_SSCAPE, {SSCAPE_BASE, SSCAPE_IRQ, SSCAPE_DMA, -1}, SND_DEFAULT_ENABLE}, + {SNDCARD_SSCAPE_MSS, {SSCAPE_MSS_BASE, SSCAPE_MSS_IRQ, SSCAPE_MSS_DMA, -1}, SND_DEFAULT_ENABLE}, #endif #ifndef EXCLUDE_MAD16 - {SNDCARD_MAD16, {MAD16_BASE, MAD16_IRQ, MAD16_DMA}, SND_DEFAULT_ENABLE}, + {SNDCARD_MAD16, {MAD16_BASE, MAD16_IRQ, MAD16_DMA, MAD16_DMA2}, SND_DEFAULT_ENABLE}, # ifdef MAD16_MPU_BASE - {SNDCARD_MAD16_MPU, {MAD16_MPU_BASE, MAD16_MPU_IRQ, 0}, SND_DEFAULT_ENABLE}, + {SNDCARD_MAD16_MPU, {MAD16_MPU_BASE, MAD16_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, # endif #endif +#ifndef EXCLUDE_CS4232 +# ifdef CS4232_MPU_BASE + {SNDCARD_CS4232_MPU, {CS4232_MPU_BASE, CS4232_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, +# endif + {SNDCARD_CS4232, {CS4232_BASE, CS4232_IRQ, CS4232_DMA, CS4232_DMA2}, SND_DEFAULT_ENABLE}, +#endif + #ifndef EXCLUDE_MSS - {SNDCARD_MSS, {MSS_BASE, MSS_IRQ, MSS_DMA}, SND_DEFAULT_ENABLE}, + {SNDCARD_MSS, {MSS_BASE, MSS_IRQ, MSS_DMA, -1}, SND_DEFAULT_ENABLE}, # ifdef MSS2_BASE - {SNDCARD_MSS, {MSS2_BASE, MSS2_IRQ, MSS2_DMA}, SND_DEFAULT_ENABLE}, + {SNDCARD_MSS, {MSS2_BASE, MSS2_IRQ, MSS2_DMA, -1}, SND_DEFAULT_ENABLE}, # endif #endif #ifndef EXCLUDE_PAS - {SNDCARD_PAS, {PAS_BASE, PAS_IRQ, PAS_DMA}, SND_DEFAULT_ENABLE}, + {SNDCARD_PAS, {PAS_BASE, PAS_IRQ, PAS_DMA, -1}, SND_DEFAULT_ENABLE}, #endif #ifndef EXCLUDE_SB # ifndef SBC_DMA # define SBC_DMA 1 # endif - {SNDCARD_SB, {SBC_BASE, SBC_IRQ, SBC_DMA}, SND_DEFAULT_ENABLE}, + {SNDCARD_SB, {SBC_BASE, SBC_IRQ, SBC_DMA, -1}, SND_DEFAULT_ENABLE}, +#endif +#if !defined(EXCLUDE_MAUI) + {SNDCARD_MAUI, {MAUI_BASE, MAUI_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, #endif #if !defined(EXCLUDE_MPU401) && !defined(EXCLUDE_MIDI) - {SNDCARD_MPU401, {MPU_BASE, MPU_IRQ, 0}, SND_DEFAULT_ENABLE}, + {SNDCARD_MPU401, {MPU_BASE, MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, #ifdef MPU2_BASE - {SNDCARD_MPU401, {MPU2_BASE, MPU2_IRQ, 0}, SND_DEFAULT_ENABLE}, + {SNDCARD_MPU401, {MPU2_BASE, MPU2_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, #endif #ifdef MPU3_BASE - {SNDCARD_MPU401, {MPU3_BASE, MPU2_IRQ, 0}, SND_DEFAULT_ENABLE}, + {SNDCARD_MPU401, {MPU3_BASE, MPU2_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, #endif #endif #if !defined(EXCLUDE_UART6850) && !defined(EXCLUDE_MIDI) - {SNDCARD_UART6850, {U6850_BASE, U6850_IRQ, 0}, SND_DEFAULT_ENABLE}, + {SNDCARD_UART6850, {U6850_BASE, U6850_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, #endif #if !defined(EXCLUDE_SB) && !defined(EXCLUDE_SB16) #ifndef EXCLUDE_AUDIO - {SNDCARD_SB16, {SBC_BASE, SBC_IRQ, SB16_DMA}, SND_DEFAULT_ENABLE}, + {SNDCARD_SB16, {SBC_BASE, SBC_IRQ, SB16_DMA, -1}, SND_DEFAULT_ENABLE}, #endif #ifndef EXCLUDE_MIDI - {SNDCARD_SB16MIDI,{SB16MIDI_BASE, SBC_IRQ, 0}, SND_DEFAULT_ENABLE}, + {SNDCARD_SB16MIDI,{SB16MIDI_BASE, SBC_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, #endif #endif #ifndef EXCLUDE_GUS #ifndef EXCLUDE_GUS16 - {SNDCARD_GUS16, {GUS16_BASE, GUS16_IRQ, GUS16_DMA}, SND_DEFAULT_ENABLE}, + {SNDCARD_GUS16, {GUS16_BASE, GUS16_IRQ, GUS16_DMA, -1}, SND_DEFAULT_ENABLE}, #endif - {SNDCARD_GUS, {GUS_BASE, GUS_IRQ, GUS_DMA}, SND_DEFAULT_ENABLE}, + {SNDCARD_GUS, {GUS_BASE, GUS_IRQ, GUS_DMA, GUS_DMA2}, SND_DEFAULT_ENABLE}, #endif #ifndef EXCLUDE_YM3812 - {SNDCARD_ADLIB, {FM_MONO, 0, 0}, SND_DEFAULT_ENABLE}, + {SNDCARD_ADLIB, {FM_MONO, 0, 0, -1}, SND_DEFAULT_ENABLE}, #endif +/* Define some expansion space */ + {0, {0}, 0}, + {0, {0}, 0}, + {0, {0}, 0}, + {0, {0}, 0}, {0, {0}, 0} }; int num_sound_cards = sizeof(snd_installed_cards) / sizeof (struct card_info); + int max_sound_cards = + sizeof(snd_installed_cards) / sizeof (struct card_info); #else int num_sound_cards = 0; -#endif /* linux */ + struct card_info snd_installed_cards[20] = {{0}}; + int max_sound_cards = 20; +#endif int num_sound_drivers = sizeof(sound_drivers) / sizeof (struct driver_info); @@ -421,12 +478,24 @@ extern int num_sound_drivers; extern struct card_info snd_installed_cards[]; extern int num_sound_cards; + extern int max_sound_cards; long sndtable_init(long mem_start); int sndtable_get_cardcount (void); struct address_info *sound_getconf(int card_type); void sound_chconf(int card_type, int ioaddr, int irq, int dma); int snd_find_driver(int type); +void sound_unload_drivers(void); +int sndtable_identify_card(char *name); +void sound_setup (char *str, int *ints); + +int sound_alloc_dmap (int dev, struct dma_buffparms *dmap, int chan); +void sound_free_dmap (int dev, struct dma_buffparms *dmap); +extern int soud_map_buffer (int dev, struct dma_buffparms *dmap, buffmem_desc *info); +void install_pnp_sounddrv(struct pnp_sounddev *drv); +int sndtable_probe (int unit, struct address_info *hw_config); +int sndtable_init_card (int unit, struct address_info *hw_config); +void sound_timer_init (struct sound_lowlev_timer *t, char *name); #endif /* _DEV_TABLE_C_ */ #endif /* _DEV_TABLE_H_ */ diff -u --recursive --new-file v1.3.33/linux/drivers/sound/dmabuf.c linux/drivers/sound/dmabuf.c --- v1.3.33/linux/drivers/sound/dmabuf.c Mon Sep 18 14:54:04 1995 +++ linux/drivers/sound/dmabuf.c Wed Oct 11 07:55:39 1995 @@ -31,15 +31,24 @@ #ifdef CONFIGURE_SOUNDCARD -#include "sound_calls.h" - #if !defined(EXCLUDE_AUDIO) || !defined(EXCLUDE_GUS) -static int space_in_queue (int dev); +static struct wait_queue *in_sleeper[MAX_AUDIO_DEV] = +{NULL}; +static volatile struct snd_wait in_sleep_flag[MAX_AUDIO_DEV] = +{ + {0}}; +static struct wait_queue *out_sleeper[MAX_AUDIO_DEV] = +{NULL}; +static volatile struct snd_wait out_sleep_flag[MAX_AUDIO_DEV] = +{ + {0}}; + +static int ndmaps = 0; -DEFINE_WAIT_QUEUES (dev_sleeper[MAX_AUDIO_DEV], dev_sleep_flag[MAX_AUDIO_DEV]); +#define MAX_DMAP (MAX_AUDIO_DEV*2) -static struct dma_buffparms dmaps[MAX_AUDIO_DEV] = +static struct dma_buffparms dmaps[MAX_DMAP] = { {0}}; /* @@ -47,18 +56,21 @@ * such a large array. * Needs dynamic run-time alloction. */ +static int space_in_queue (int dev); + +static void dma_reset_output (int dev); +static void dma_reset_input (int dev); static void -reorganize_buffers (int dev) +reorganize_buffers (int dev, struct dma_buffparms *dmap) { /* * This routine breaks the physical device buffers to logical ones. */ - struct dma_buffparms *dmap = audio_devs[dev]->dmap; struct audio_operations *dsp_dev = audio_devs[dev]; - unsigned i, p, n; + unsigned i, n; unsigned sr, nc, sz, bsz; if (dmap->fragment_size == 0) @@ -68,6 +80,11 @@ nc = dsp_dev->ioctl (dev, SOUND_PCM_READ_CHANNELS, 0, 1); sz = dsp_dev->ioctl (dev, SOUND_PCM_READ_BITS, 0, 1); + if (sz == 8) + dmap->neutral_byte = 0x80; + else + dmap->neutral_byte = 0x00; + if (sr < 1 || nc < 1 || sz < 1) { printk ("Warning: Invalid PCM parameters[%d] sr=%d, nc=%d, sz=%d\n", @@ -77,10 +94,10 @@ sz = 8; } - sz /= 8; /* #bits -> #bytes */ - sz = sr * nc * sz; + sz /= 8; /* #bits -> #bytes */ + /* * Compute a buffer size for time not exeeding 1 second. * Usually this algorithm gives a buffer size for 0.5 to 1.0 seconds @@ -91,19 +108,16 @@ while (bsz > sz) bsz /= 2; - if (dsp_dev->buffcount == 1 && bsz == dsp_dev->buffsize) + if (bsz == dsp_dev->buffsize) bsz /= 2; /* Needs at least 2 buffers */ if (dmap->subdivision == 0) /* Not already set */ dmap->subdivision = 1; /* Init to default value */ + else + bsz /= dmap->subdivision; - bsz /= dmap->subdivision; - - if (bsz < 64) - bsz = 4096; /* Just a sanity check */ - - while ((dsp_dev->buffsize * dsp_dev->buffcount) / bsz > MAX_SUB_BUFFERS) - bsz *= 2; + if (bsz < 16) + bsz = 16; /* Just a sanity check */ dmap->fragment_size = bsz; } @@ -113,33 +127,18 @@ * The process has specified the buffer sice with SNDCTL_DSP_SETFRAGMENT or * the buffer sice computation has already been done. */ - if (dmap->fragment_size > audio_devs[dev]->buffsize) - dmap->fragment_size = audio_devs[dev]->buffsize; + if (dmap->fragment_size > (audio_devs[dev]->buffsize / 2)) + dmap->fragment_size = (audio_devs[dev]->buffsize / 2); bsz = dmap->fragment_size; } - /* - * Now computing addresses for the logical buffers - */ - - n = 0; - for (i = 0; i < dmap->raw_count && - n < dmap->max_fragments && - n < MAX_SUB_BUFFERS; i++) - { - p = 0; - - while ((p + bsz) <= dsp_dev->buffsize && - n < dmap->max_fragments && - n < MAX_SUB_BUFFERS) - { - dmap->buf[n] = dmap->raw_buf[i] + p; - dmap->buf_phys[n] = dmap->raw_buf_phys[i] + p; - p += bsz; - n++; - } - } + bsz &= ~0x03; /* Force size which is multiple of 4 bytes */ + n = dsp_dev->buffsize / bsz; + if (n > MAX_SUB_BUFFERS) + n = MAX_SUB_BUFFERS; + if (n > dmap->max_fragments) + n = dmap->max_fragments; dmap->nbufs = n; dmap->bytes_in_use = n * bsz; @@ -152,61 +151,127 @@ } static void -dma_init_buffers (int dev) +dma_init_buffers (int dev, struct dma_buffparms *dmap) { - struct dma_buffparms *dmap = audio_devs[dev]->dmap = &dmaps[dev]; - - RESET_WAIT_QUEUE (dev_sleeper[dev], dev_sleep_flag[dev]); + if (dmap == audio_devs[dev]->dmap_out) + { + { + out_sleep_flag[dev].aborting = 0; + out_sleep_flag[dev].mode = WK_NONE; + }; + } + else + { + in_sleep_flag[dev].aborting = 0; + in_sleep_flag[dev].mode = WK_NONE; + }; dmap->flags = DMA_BUSY; /* Other flags off */ dmap->qlen = dmap->qhead = dmap->qtail = 0; + dmap->nbufs = 1; + dmap->bytes_in_use = audio_devs[dev]->buffsize; dmap->dma_mode = DMODE_NONE; + dmap->mapping_flags = 0; + dmap->neutral_byte = 0x00; +} + +static int +open_dmap (int dev, int mode, struct dma_buffparms *dmap, int chan) +{ + if (dmap->flags & DMA_BUSY) + return -EBUSY; + + { + int err; + + if ((err = sound_alloc_dmap (dev, dmap, chan)) < 0) + return err; + } + + if (dmap->raw_buf == NULL) + return -ENOSPC; /* Memory allocation failed during boot */ + + if (sound_open_dma (chan, audio_devs[dev]->name)) + { + printk ("Unable to grab(2) DMA%d for the audio driver\n", chan); + return -EBUSY; + } + + dmap->open_mode = mode; + dmap->subdivision = dmap->underrun_count = 0; + dmap->fragment_size = 0; + dmap->max_fragments = 65536; /* Just a large value */ + dmap->byte_counter = 0; + + dma_init_buffers (dev, dmap); + + return 0; +} + +static void +close_dmap (int dev, struct dma_buffparms *dmap, int chan) +{ + sound_close_dma (chan); + + if (dmap->flags & DMA_BUSY) + dmap->dma_mode = DMODE_NONE; + dmap->flags &= ~DMA_BUSY; + + sound_free_dmap (dev, dmap); } int DMAbuf_open (int dev, int mode) { int retval; - struct dma_buffparms *dmap = NULL; + struct dma_buffparms *dmap_in = NULL; + struct dma_buffparms *dmap_out = NULL; if (dev >= num_audiodevs) { printk ("PCM device %d not installed.\n", dev); - return RET_ERROR (ENXIO); + return -ENXIO; } if (!audio_devs[dev]) { printk ("PCM device %d not initialized\n", dev); - return RET_ERROR (ENXIO); + return -ENXIO; } - dmap = audio_devs[dev]->dmap = &dmaps[dev]; - - if (dmap->flags & DMA_BUSY) - return RET_ERROR (EBUSY); - -#ifdef USE_RUNTIME_DMAMEM - dmap->raw_buf[0] = NULL; - sound_dma_malloc (dev); -#endif - - if (dmap->raw_buf[0] == NULL) - return RET_ERROR (ENOSPC); /* Memory allocation failed during boot */ + if (!(audio_devs[dev]->flags & DMA_DUPLEX)) + { + audio_devs[dev]->dmap_in = audio_devs[dev]->dmap_out; + audio_devs[dev]->dmachan2 = audio_devs[dev]->dmachan1; + } if ((retval = audio_devs[dev]->open (dev, mode)) < 0) return retval; - dmap->open_mode = mode; - dmap->subdivision = dmap->underrun_count = 0; - dmap->fragment_size = 0; - dmap->max_fragments = 65536; /* Just a large value */ + dmap_out = audio_devs[dev]->dmap_out; + dmap_in = audio_devs[dev]->dmap_in; - dma_init_buffers (dev); - audio_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_BITS, 8, 1); - audio_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_CHANNELS, 1, 1); - audio_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_RATE, DSP_DEFAULT_SPEED, 1); + if ((retval = open_dmap (dev, mode, dmap_out, audio_devs[dev]->dmachan1)) < 0) + { + audio_devs[dev]->close (dev); + return retval; + } + + audio_devs[dev]->enable_bits = mode; + if (audio_devs[dev]->flags & DMA_DUPLEX && dmap_out != dmap_in) + if ((retval = open_dmap (dev, mode, dmap_in, audio_devs[dev]->dmachan2)) < 0) + { + audio_devs[dev]->close (dev); + close_dmap (dev, dmap_out, audio_devs[dev]->dmachan1); + return retval; + } + audio_devs[dev]->open_mode = mode; + audio_devs[dev]->go = 1; + + audio_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_BITS, (ioctl_arg) 8, 1); + audio_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_CHANNELS, (ioctl_arg) 1, 1); + audio_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_RATE, (ioctl_arg) DSP_DEFAULT_SPEED, 1); return 0; } @@ -214,20 +279,53 @@ static void dma_reset (int dev) { - int retval; unsigned long flags; - DISABLE_INTR (flags); - + save_flags (flags); + cli (); audio_devs[dev]->reset (dev); - audio_devs[dev]->close (dev); + restore_flags (flags); + + dma_reset_output (dev); + + if (audio_devs[dev]->flags & DMA_DUPLEX) + dma_reset_input (dev); +} + +static void +dma_reset_output (int dev) +{ + unsigned long flags; - if ((retval = audio_devs[dev]->open (dev, audio_devs[dev]->dmap->open_mode)) < 0) - printk ("Sound: Reset failed - Can't reopen device\n"); - RESTORE_INTR (flags); + save_flags (flags); + cli (); + if (!(audio_devs[dev]->flags & DMA_DUPLEX) || + !audio_devs[dev]->halt_output) + audio_devs[dev]->reset (dev); + else + audio_devs[dev]->halt_output (dev); + restore_flags (flags); - dma_init_buffers (dev); - reorganize_buffers (dev); + dma_init_buffers (dev, audio_devs[dev]->dmap_out); + reorganize_buffers (dev, audio_devs[dev]->dmap_out); +} + +static void +dma_reset_input (int dev) +{ + unsigned long flags; + + save_flags (flags); + cli (); + if (!(audio_devs[dev]->flags & DMA_DUPLEX) || + !audio_devs[dev]->halt_input) + audio_devs[dev]->reset (dev); + else + audio_devs[dev]->halt_input (dev); + restore_flags (flags); + + dma_init_buffers (dev, audio_devs[dev]->dmap_in); + reorganize_buffers (dev, audio_devs[dev]->dmap_in); } static int @@ -235,39 +333,80 @@ { unsigned long flags; - if (audio_devs[dev]->dmap->dma_mode == DMODE_OUTPUT) + if (!audio_devs[dev]->go && (!audio_devs[dev]->enable_bits & PCM_ENABLE_OUTPUT)) + return 0; + + if (audio_devs[dev]->dmap_out->dma_mode == DMODE_OUTPUT) { - DISABLE_INTR (flags); + save_flags (flags); + cli (); - while (!PROCESS_ABORTING (dev_sleeper[dev], dev_sleep_flag[dev]) - && audio_devs[dev]->dmap->qlen) + while (!((current->signal & ~current->blocked)) + && audio_devs[dev]->dmap_out->qlen) { - DO_SLEEP (dev_sleeper[dev], dev_sleep_flag[dev], 10 * HZ); - if (TIMED_OUT (dev_sleeper[dev], dev_sleep_flag[dev])) + + { + unsigned long tl; + + if (10 * HZ) + tl = current->timeout = jiffies + (10 * HZ); + else + tl = 0xffffffff; + out_sleep_flag[dev].mode = WK_SLEEP; + interruptible_sleep_on (&out_sleeper[dev]); + if (!(out_sleep_flag[dev].mode & WK_WAKEUP)) + { + if (current->signal & ~current->blocked) + out_sleep_flag[dev].aborting = 1; + else if (jiffies >= tl) + out_sleep_flag[dev].mode |= WK_TIMEOUT; + } + out_sleep_flag[dev].mode &= ~WK_SLEEP; + }; + if ((out_sleep_flag[dev].mode & WK_TIMEOUT)) { - RESTORE_INTR (flags); - return audio_devs[dev]->dmap->qlen; + restore_flags (flags); + return audio_devs[dev]->dmap_out->qlen; } } - RESTORE_INTR (flags); + restore_flags (flags); /* * Some devices such as GUS have huge amount of on board RAM for the * audio data. We have to wait until the device has finished playing. */ - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (audio_devs[dev]->local_qlen) /* Device has hidden buffers */ { - while (!(PROCESS_ABORTING (dev_sleeper[dev], dev_sleep_flag[dev])) + while (!(((current->signal & ~current->blocked))) && audio_devs[dev]->local_qlen (dev)) { - DO_SLEEP (dev_sleeper[dev], dev_sleep_flag[dev], HZ); + + { + unsigned long tl; + + if (HZ) + tl = current->timeout = jiffies + (HZ); + else + tl = 0xffffffff; + out_sleep_flag[dev].mode = WK_SLEEP; + interruptible_sleep_on (&out_sleeper[dev]); + if (!(out_sleep_flag[dev].mode & WK_WAKEUP)) + { + if (current->signal & ~current->blocked) + out_sleep_flag[dev].aborting = 1; + else if (jiffies >= tl) + out_sleep_flag[dev].mode |= WK_TIMEOUT; + } + out_sleep_flag[dev].mode &= ~WK_SLEEP; + }; } } - RESTORE_INTR (flags); + restore_flags (flags); } - return audio_devs[dev]->dmap->qlen; + return audio_devs[dev]->dmap_out->qlen; } int @@ -275,25 +414,75 @@ { unsigned long flags; - if (!(PROCESS_ABORTING (dev_sleeper[dev], dev_sleep_flag[dev])) - && (audio_devs[dev]->dmap->dma_mode == DMODE_OUTPUT)) + if (!(((current->signal & ~current->blocked))) + && (audio_devs[dev]->dmap_out->dma_mode == DMODE_OUTPUT)) { dma_sync (dev); } -#ifdef USE_RUNTIME_DMAMEM - sound_dma_free (dev); -#endif - - DISABLE_INTR (flags); + save_flags (flags); + cli (); audio_devs[dev]->reset (dev); audio_devs[dev]->close (dev); - audio_devs[dev]->dmap->dma_mode = DMODE_NONE; - audio_devs[dev]->dmap->flags &= ~DMA_BUSY; - RESTORE_INTR (flags); + close_dmap (dev, audio_devs[dev]->dmap_out, audio_devs[dev]->dmachan1); + + if (audio_devs[dev]->flags & DMA_DUPLEX) + close_dmap (dev, audio_devs[dev]->dmap_in, audio_devs[dev]->dmachan2); + audio_devs[dev]->open_mode = 0; + + restore_flags (flags); + + return 0; +} + +static int +activate_recording (int dev, struct dma_buffparms *dmap) +{ + if (!(audio_devs[dev]->enable_bits & PCM_ENABLE_INPUT)) + return 0; + + if (dmap->flags & DMA_RESTART) + { + dma_reset_input (dev); + dmap->flags &= ~DMA_RESTART; + } + + if (dmap->dma_mode == DMODE_OUTPUT) /* Direction change */ + { + dma_sync (dev); + dma_reset (dev); + dmap->dma_mode = DMODE_NONE; + } + + if (!(dmap->flags & DMA_ALLOC_DONE)) + reorganize_buffers (dev, dmap); + + if (!dmap->dma_mode) + { + int err; + + if ((err = audio_devs[dev]->prepare_for_input (dev, + dmap->fragment_size, dmap->nbufs)) < 0) + { + return err; + } + dmap->dma_mode = DMODE_INPUT; + } + if (!(dmap->flags & DMA_ACTIVE)) + { + audio_devs[dev]->start_input (dev, dmap->raw_buf_phys + + dmap->qtail * dmap->fragment_size, + dmap->fragment_size, 0, + !(audio_devs[dev]->flags & DMA_AUTOMODE) || + !(dmap->flags & DMA_STARTED)); + dmap->flags |= DMA_ACTIVE | DMA_STARTED; + if (audio_devs[dev]->trigger) + audio_devs[dev]->trigger (dev, + audio_devs[dev]->enable_bits * audio_devs[dev]->go); + } return 0; } @@ -302,73 +491,79 @@ { unsigned long flags; int err = EIO; - struct dma_buffparms *dmap = audio_devs[dev]->dmap; + struct dma_buffparms *dmap = audio_devs[dev]->dmap_in; - DISABLE_INTR (flags); - if (!dmap->qlen) + save_flags (flags); + cli (); + if (audio_devs[dev]->dmap_in->mapping_flags & DMA_MAP_MAPPED) { - if (dmap->flags & DMA_RESTART) - { - dma_reset (dev); - dmap->flags &= ~DMA_RESTART; - } + printk ("Sound: Can't read from mmapped device (1)\n"); + return -EINVAL; + } + else if (!dmap->qlen) + { + int timeout; - if (dmap->dma_mode == DMODE_OUTPUT) /* Direction change */ + if ((err = activate_recording (dev, dmap)) < 0) { - dma_sync (dev); - dma_reset (dev); - dmap->dma_mode = DMODE_NONE; + restore_flags (flags); + return err; } - if (!(dmap->flags & DMA_ALLOC_DONE)) - reorganize_buffers (dev); + /* Wait for the next block */ - if (!dmap->dma_mode) + if (dontblock) { - int err; - - if ((err = audio_devs[dev]->prepare_for_input (dev, - dmap->fragment_size, dmap->nbufs)) < 0) - { - RESTORE_INTR (flags); - return err; - } - dmap->dma_mode = DMODE_INPUT; + restore_flags (flags); + return -EAGAIN; } - if (!(dmap->flags & DMA_ACTIVE)) + if (!(audio_devs[dev]->enable_bits & PCM_ENABLE_INPUT) & + audio_devs[dev]->go) { - audio_devs[dev]->start_input (dev, dmap->buf_phys[dmap->qtail], - dmap->fragment_size, 0, - !(audio_devs[dev]->flags & DMA_AUTOMODE) || - !(dmap->flags & DMA_STARTED)); - dmap->flags |= DMA_ACTIVE | DMA_STARTED; + restore_flags (flags); + return -EAGAIN; } - if (dontblock) - { - RESTORE_INTR (flags); - return RET_ERROR (EAGAIN); - } + if (!audio_devs[dev]->go) + timeout = 0; + else + timeout = 2 * HZ; - /* Wait for the next block */ - DO_SLEEP (dev_sleeper[dev], dev_sleep_flag[dev], 2 * HZ); - if (TIMED_OUT (dev_sleeper[dev], dev_sleep_flag[dev])) + { + unsigned long tl; + + if (timeout) + tl = current->timeout = jiffies + (timeout); + else + tl = 0xffffffff; + in_sleep_flag[dev].mode = WK_SLEEP; + interruptible_sleep_on (&in_sleeper[dev]); + if (!(in_sleep_flag[dev].mode & WK_WAKEUP)) + { + if (current->signal & ~current->blocked) + in_sleep_flag[dev].aborting = 1; + else if (jiffies >= tl) + in_sleep_flag[dev].mode |= WK_TIMEOUT; + } + in_sleep_flag[dev].mode &= ~WK_SLEEP; + }; + if ((in_sleep_flag[dev].mode & WK_TIMEOUT)) { - printk ("Sound: DMA timed out - IRQ/DRQ config error?\n"); + printk ("Sound: DMA (input) timed out - IRQ/DRQ config error?\n"); err = EIO; - SET_ABORT_FLAG (dev_sleeper[dev], dev_sleep_flag[dev]); + in_sleep_flag[dev].aborting = 1; } else err = EINTR; } - RESTORE_INTR (flags); + restore_flags (flags); if (!dmap->qlen) - return RET_ERROR (err); + return -err; - *buf = &dmap->buf[dmap->qhead][dmap->counts[dmap->qhead]]; + *buf = &dmap->raw_buf[dmap->qhead * dmap->fragment_size + dmap->counts[dmap->qhead]]; *len = dmap->fragment_size - dmap->counts[dmap->qhead]; return dmap->qhead; @@ -377,11 +572,16 @@ int DMAbuf_rmchars (int dev, int buff_no, int c) { - struct dma_buffparms *dmap = audio_devs[dev]->dmap; + struct dma_buffparms *dmap = audio_devs[dev]->dmap_in; int p = dmap->counts[dmap->qhead] + c; - if (p >= dmap->fragment_size) + if (audio_devs[dev]->dmap_in->mapping_flags & DMA_MAP_MAPPED) + { + printk ("Sound: Can't read from mmapped device (2)\n"); + return -EINVAL; + } + else if (p >= dmap->fragment_size) { /* This buffer is completely empty */ dmap->counts[dmap->qhead] = 0; if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs) @@ -396,10 +596,105 @@ return 0; } +static int +dma_subdivide (int dev, struct dma_buffparms *dmap, ioctl_arg arg, int fact) +{ + if (fact == 0) + { + fact = dmap->subdivision; + if (fact == 0) + fact = 1; + return snd_ioctl_return ((int *) arg, fact); + } + + if (dmap->subdivision != 0 || + dmap->fragment_size) /* Loo late to change */ + return -EINVAL; + + if (fact > MAX_REALTIME_FACTOR) + return -EINVAL; + + if (fact != 1 && fact != 2 && fact != 4 && fact != 8 && fact != 16) + return -EINVAL; + + dmap->subdivision = fact; + return snd_ioctl_return ((int *) arg, fact); +} + +static int +dma_set_fragment (int dev, struct dma_buffparms *dmap, ioctl_arg arg, int fact) +{ + int bytes, count; + + if (fact == 0) + return -EIO; + + if (dmap->subdivision != 0 || + dmap->fragment_size) /* Loo late to change */ + return -EINVAL; + + bytes = fact & 0xffff; + count = (fact >> 16) & 0xffff; + + if (count == 0) + count = MAX_SUB_BUFFERS; + + if (bytes < 4 || bytes > 17) /* <16 || > 128k */ + return -EINVAL; + + if (count < 2) + return -EINVAL; + + dmap->fragment_size = (1 << bytes); + dmap->max_fragments = count; + + if (dmap->fragment_size > audio_devs[dev]->buffsize) + dmap->fragment_size = audio_devs[dev]->buffsize; + + if (dmap->fragment_size == audio_devs[dev]->buffsize && + audio_devs[dev]->flags & DMA_AUTOMODE) + dmap->fragment_size /= 2; /* Needs at least 2 buffers */ + + dmap->subdivision = 1; /* Disable SNDCTL_DSP_SUBDIVIDE */ + return snd_ioctl_return ((int *) arg, bytes | (count << 16)); +} + +static int +get_buffer_pointer (int dev, int chan, struct dma_buffparms *dmap) +{ + int pos; + unsigned long flags; + + save_flags (flags); + cli (); + if (!(dmap->flags & DMA_ACTIVE)) + pos = 0; + else + { + clear_dma_ff (chan); + disable_dma (chan); + pos = get_dma_residue (chan); + enable_dma (chan); + } + restore_flags (flags); + /* printk ("%04x ", pos); */ + + if (audio_devs[dev]->flags & DMA_AUTOMODE) + return dmap->bytes_in_use - pos; + else + { + pos = dmap->fragment_size - pos; + if (pos < 0) + return 0; + return pos; + } +} + int -DMAbuf_ioctl (int dev, unsigned int cmd, unsigned int arg, int local) +DMAbuf_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local) { - struct dma_buffparms *dmap = audio_devs[dev]->dmap; + struct dma_buffparms *dmap_out = audio_devs[dev]->dmap_out; + struct dma_buffparms *dmap_in = audio_devs[dev]->dmap_in; switch (cmd) { @@ -415,88 +710,64 @@ break; case SNDCTL_DSP_GETBLKSIZE: - if (!(dmap->flags & DMA_ALLOC_DONE)) - reorganize_buffers (dev); + if (!(dmap_out->flags & DMA_ALLOC_DONE)) + reorganize_buffers (dev, dmap_out); - return IOCTL_OUT (arg, dmap->fragment_size); + return snd_ioctl_return ((int *) arg, dmap_out->fragment_size); break; case SNDCTL_DSP_SUBDIVIDE: { - int fact = IOCTL_IN (arg); - - if (fact == 0) - { - fact = dmap->subdivision; - if (fact == 0) - fact = 1; - return IOCTL_OUT (arg, fact); - } + int fact = get_fs_long ((long *) arg); + int ret; - if (dmap->subdivision != 0 || - dmap->fragment_size) /* Loo late to change */ - return RET_ERROR (EINVAL); + ret = dma_subdivide (dev, dmap_out, arg, fact); + if (ret < 0) + return ret; - if (fact > MAX_REALTIME_FACTOR) - return RET_ERROR (EINVAL); + if (audio_devs[dev]->flags & DMA_DUPLEX) + ret = dma_subdivide (dev, dmap_in, arg, fact); - if (fact != 1 && fact != 2 && fact != 4 && fact != 8 && fact != 16) - return RET_ERROR (EINVAL); - - dmap->subdivision = fact; - return IOCTL_OUT (arg, fact); + return ret; } break; case SNDCTL_DSP_SETFRAGMENT: { - int fact = IOCTL_IN (arg); - int bytes, count; - - if (fact == 0) - return RET_ERROR (EIO); - - if (dmap->subdivision != 0 || - dmap->fragment_size) /* Loo late to change */ - return RET_ERROR (EINVAL); - - bytes = fact & 0xffff; - count = (fact >> 16) & 0xffff; - - if (count == 0) - count = MAX_SUB_BUFFERS; - - if (bytes < 7 || bytes > 17) /* <64 || > 128k */ - return RET_ERROR (EINVAL); + int fact = get_fs_long ((long *) arg); + int ret; - if (count < 2) - return RET_ERROR (EINVAL); + ret = dma_set_fragment (dev, dmap_out, arg, fact); + if (ret < 0) + return ret; - dmap->fragment_size = (1 << bytes); - dmap->max_fragments = count; + if (audio_devs[dev]->flags & DMA_DUPLEX) + ret = dma_set_fragment (dev, dmap_in, arg, fact); - if (dmap->fragment_size > audio_devs[dev]->buffsize) - dmap->fragment_size = audio_devs[dev]->buffsize; - - if (dmap->fragment_size == audio_devs[dev]->buffsize && - audio_devs[dev]->flags & DMA_AUTOMODE) - dmap->fragment_size /= 2; /* Needs at least 2 buffers */ - - dmap->subdivision = 1; /* Disable SNDCTL_DSP_SUBDIVIDE */ - return IOCTL_OUT (arg, bytes | (count << 16)); + return ret; } break; case SNDCTL_DSP_GETISPACE: case SNDCTL_DSP_GETOSPACE: if (!local) - return RET_ERROR (EINVAL); + return -EINVAL; else { + struct dma_buffparms *dmap = dmap_out; + audio_buf_info *info = (audio_buf_info *) arg; + if (cmd == SNDCTL_DSP_GETISPACE && audio_devs[dev]->flags & DMA_DUPLEX) + dmap = dmap_in; + + if (dmap->mapping_flags & DMA_MAP_MAPPED) + return -EINVAL; + if (!(dmap->flags & DMA_ALLOC_DONE)) - reorganize_buffers (dev); + reorganize_buffers (dev, dmap); + + info->fragstotal = dmap->nbufs; if (cmd == SNDCTL_DSP_GETISPACE) info->fragments = dmap->qlen; @@ -533,17 +804,127 @@ } return 0; + case SNDCTL_DSP_SETTRIGGER: + { + unsigned long flags; + + int bits = get_fs_long ((long *) arg) & audio_devs[dev]->open_mode; + int changed; + + if (audio_devs[dev]->trigger == NULL) + return -EINVAL; + + if (!(audio_devs[dev]->flags & DMA_DUPLEX)) + if ((bits & PCM_ENABLE_INPUT) && (bits & PCM_ENABLE_OUTPUT)) + { + printk ("Sound: Device doesn't have full duplex capability\n"); + return -EINVAL; + } + + save_flags (flags); + cli (); + changed = audio_devs[dev]->enable_bits ^ bits; + + if ((changed & bits) & PCM_ENABLE_INPUT && audio_devs[dev]->go) + { + if (!(dmap_in->flags & DMA_ALLOC_DONE)) + reorganize_buffers (dev, dmap_in); + + activate_recording (dev, dmap_in); + } + + if ((changed & bits) & PCM_ENABLE_OUTPUT && + dmap_out->mapping_flags & DMA_MAP_MAPPED && + audio_devs[dev]->go) + { + if (!(dmap_out->flags & DMA_ALLOC_DONE)) + reorganize_buffers (dev, dmap_out); + + dmap_out->counts[dmap_out->qhead] = dmap_out->fragment_size; + DMAbuf_start_output (dev, 0, dmap_out->fragment_size); + } + + audio_devs[dev]->enable_bits = bits; + if (changed && audio_devs[dev]->trigger) + audio_devs[dev]->trigger (dev, bits * audio_devs[dev]->go); + restore_flags (flags); + } + case SNDCTL_DSP_GETTRIGGER: + return snd_ioctl_return ((int *) arg, audio_devs[dev]->enable_bits); + break; + + case SNDCTL_DSP_GETIPTR: + { + count_info info; + unsigned long flags; + + save_flags (flags); + cli (); + info.bytes = audio_devs[dev]->dmap_in->byte_counter; + info.ptr = get_buffer_pointer (dev, audio_devs[dev]->dmachan2, audio_devs[dev]->dmap_in); + info.blocks = audio_devs[dev]->dmap_in->qlen; + info.bytes += info.ptr; + memcpy_tofs (&(((char *) arg)[0]), ((char *) &info), (sizeof (info))); + + if (audio_devs[dev]->dmap_in->mapping_flags & DMA_MAP_MAPPED) + audio_devs[dev]->dmap_in->qlen = 0; /* Acknowledge interrupts */ + restore_flags (flags); + return 0; + } + break; + + case SNDCTL_DSP_GETOPTR: + { + count_info info; + unsigned long flags; + + save_flags (flags); + cli (); + info.bytes = audio_devs[dev]->dmap_out->byte_counter; + info.ptr = get_buffer_pointer (dev, audio_devs[dev]->dmachan1, audio_devs[dev]->dmap_out); + info.blocks = audio_devs[dev]->dmap_out->qlen; + info.bytes += info.ptr; + memcpy_tofs (&(((char *) arg)[0]), ((char *) &info), (sizeof (info))); + + if (audio_devs[dev]->dmap_out->mapping_flags & DMA_MAP_MAPPED) + audio_devs[dev]->dmap_out->qlen = 0; /* Acknowledge interrupts */ + restore_flags (flags); + return 0; + } + break; + + default: return audio_devs[dev]->ioctl (dev, cmd, arg, local); } } +/* + * DMAbuf_start_devices() is called by the /dev/music driver to start + * one or more audio devices at desired moment. + */ + +void +DMAbuf_start_devices (unsigned int devmask) +{ + int dev; + + for (dev = 0; dev < num_audiodevs; dev++) + if (devmask & (1 << dev)) + if (audio_devs[dev]->open_mode != 0) + if (!audio_devs[dev]->go) + { + /* OK to start the device */ + audio_devs[dev]->go = 1; + } +} + static int space_in_queue (int dev) { int len, max, tmp; - struct dma_buffparms *dmap = audio_devs[dev]->dmap; + struct dma_buffparms *dmap = audio_devs[dev]->dmap_out; if (dmap->qlen >= dmap->nbufs) /* No space at all */ return 0; @@ -576,7 +957,13 @@ { unsigned long flags; int abort, err = EIO; - struct dma_buffparms *dmap = audio_devs[dev]->dmap; + struct dma_buffparms *dmap = audio_devs[dev]->dmap_out; + + if (audio_devs[dev]->dmap_out->mapping_flags & DMA_MAP_MAPPED) + { + printk ("Sound: Can't write to mmapped device (3)\n"); + return -EINVAL; + } if (dmap->dma_mode == DMODE_INPUT) /* Direction change */ { @@ -586,13 +973,13 @@ else if (dmap->flags & DMA_RESTART) /* Restart buffering */ { dma_sync (dev); - dma_reset (dev); + dma_reset_output (dev); } dmap->flags &= ~DMA_RESTART; if (!(dmap->flags & DMA_ALLOC_DONE)) - reorganize_buffers (dev); + reorganize_buffers (dev, dmap); if (!dmap->dma_mode) { @@ -604,41 +991,76 @@ return err; } - - if (dontblock) - return RET_ERROR (EAGAIN); - - DISABLE_INTR (flags); + save_flags (flags); + cli (); abort = 0; while (!space_in_queue (dev) && !abort) { + int timeout; + + if (dontblock) + { + restore_flags (flags); + return -EAGAIN; + } + + if (!(audio_devs[dev]->enable_bits & PCM_ENABLE_OUTPUT) && + audio_devs[dev]->go) + { + restore_flags (flags); + return -EAGAIN; + } + /* * Wait for free space */ - DO_SLEEP (dev_sleeper[dev], dev_sleep_flag[dev], 2 * HZ); - if (TIMED_OUT (dev_sleeper[dev], dev_sleep_flag[dev])) + if (!audio_devs[dev]->go) + timeout = 0; + else + timeout = 2 * HZ; + + + { + unsigned long tl; + + if (timeout) + tl = current->timeout = jiffies + (timeout); + else + tl = 0xffffffff; + out_sleep_flag[dev].mode = WK_SLEEP; + interruptible_sleep_on (&out_sleeper[dev]); + if (!(out_sleep_flag[dev].mode & WK_WAKEUP)) + { + if (current->signal & ~current->blocked) + out_sleep_flag[dev].aborting = 1; + else if (jiffies >= tl) + out_sleep_flag[dev].mode |= WK_TIMEOUT; + } + out_sleep_flag[dev].mode &= ~WK_SLEEP; + }; + if ((out_sleep_flag[dev].mode & WK_TIMEOUT)) { - printk ("Sound: DMA timed out - IRQ/DRQ config error?\n"); + printk ("Sound: DMA (output) timed out - IRQ/DRQ config error?\n"); err = EIO; abort = 1; - SET_ABORT_FLAG (dev_sleeper[dev], dev_sleep_flag[dev]); + out_sleep_flag[dev].aborting = 1; } - else if (PROCESS_ABORTING (dev_sleeper[dev], dev_sleep_flag[dev])) + else if (((current->signal & ~current->blocked))) { err = EINTR; abort = 1; } } - RESTORE_INTR (flags); + restore_flags (flags); if (!space_in_queue (dev)) { - return RET_ERROR (err); /* Caught a signal ? */ + return -err; /* Caught a signal ? */ } - *buf = dmap->buf[dmap->qtail]; + *buf = dmap->raw_buf + dmap->qtail * dmap->fragment_size; *size = dmap->fragment_size; dmap->counts[dmap->qtail] = 0; @@ -648,35 +1070,54 @@ int DMAbuf_start_output (int dev, int buff_no, int l) { - struct dma_buffparms *dmap = audio_devs[dev]->dmap; + struct dma_buffparms *dmap = audio_devs[dev]->dmap_out; - if (buff_no != dmap->qtail) - printk ("Sound warning: DMA buffers out of sync %d != %d\n", buff_no, dmap->qtail); +/* + * Bypass buffering if using mmaped access + */ - dmap->qlen++; - if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs) - printk ("\nSound: Audio queue2 corrupted for dev%d (%d/%d)\n", - dev, dmap->qlen, dmap->nbufs); - - dmap->counts[dmap->qtail] = l; - - if ((l != dmap->fragment_size) && - ((audio_devs[dev]->flags & DMA_AUTOMODE) && - audio_devs[dev]->flags & NEEDS_RESTART)) - dmap->flags |= DMA_RESTART; + if (audio_devs[dev]->dmap_out->mapping_flags & DMA_MAP_MAPPED) + { + l = dmap->fragment_size; + dmap->counts[dmap->qtail] = l; + dmap->flags &= ~DMA_RESTART; + dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; + } else - dmap->flags &= ~DMA_RESTART; + { + + if (buff_no != dmap->qtail) + printk ("Sound warning: DMA buffers out of sync %d != %d\n", buff_no, dmap->qtail); + + dmap->qlen++; + if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs) + printk ("\nSound: Audio queue2 corrupted for dev%d (%d/%d)\n", + dev, dmap->qlen, dmap->nbufs); + + dmap->counts[dmap->qtail] = l; - dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; + if ((l != dmap->fragment_size) && + ((audio_devs[dev]->flags & DMA_AUTOMODE) && + audio_devs[dev]->flags & NEEDS_RESTART)) + dmap->flags |= DMA_RESTART; + else + dmap->flags &= ~DMA_RESTART; + + dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; + } if (!(dmap->flags & DMA_ACTIVE)) { dmap->flags |= DMA_ACTIVE; - audio_devs[dev]->output_block (dev, dmap->buf_phys[dmap->qhead], + audio_devs[dev]->output_block (dev, dmap->raw_buf_phys + + dmap->qhead * dmap->fragment_size, dmap->counts[dmap->qhead], 0, !(audio_devs[dev]->flags & DMA_AUTOMODE) || !(dmap->flags & DMA_STARTED)); dmap->flags |= DMA_STARTED; + if (audio_devs[dev]->trigger) + audio_devs[dev]->trigger (dev, + audio_devs[dev]->enable_bits * audio_devs[dev]->go); } return 0; @@ -685,13 +1126,20 @@ int DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode) { - int chan = audio_devs[dev]->dmachan; - struct dma_buffparms *dmap = audio_devs[dev]->dmap; + int chan; + struct dma_buffparms *dmap; unsigned long flags; - /* - * This function is not as portable as it should be. - */ + if (dma_mode == DMA_MODE_WRITE) + { + chan = audio_devs[dev]->dmachan1; + dmap = audio_devs[dev]->dmap_out; + } + else + { + chan = audio_devs[dev]->dmachan2; + dmap = audio_devs[dev]->dmap_in; + } /* * The count must be one less than the actual size. This is handled by @@ -703,89 +1151,27 @@ * Auto restart mode. Transfer the whole * * buffer */ -#ifdef linux - DISABLE_INTR (flags); + save_flags (flags); + cli (); disable_dma (chan); clear_dma_ff (chan); set_dma_mode (chan, dma_mode | DMA_AUTOINIT); - set_dma_addr (chan, dmap->raw_buf_phys[0]); + set_dma_addr (chan, dmap->raw_buf_phys); set_dma_count (chan, dmap->bytes_in_use); enable_dma (chan); - RESTORE_INTR (flags); -#else - -#ifdef __386BSD__ - printk ("sound: Invalid DMA mode for device %d\n", dev); - - isa_dmastart ((dma_mode == DMA_MODE_READ) ? B_READ : B_WRITE, - dmap->raw_buf_phys[0], - dmap->bytes_in_use, - chan); -#else -#if defined(GENERIC_SYSV) -#ifndef DMAMODE_AUTO - printk ("sound: Invalid DMA mode for device %d\n", dev); -#endif -#if defined(SVR42) - - /* - ** send full count to snd_dma_prog, it will take care of subtracting - ** one if it is required. - */ - snd_dma_prog (chan, dmap->raw_buf_phys[0], dmap->bytes_in_use, - dma_mode, TRUE); - -#else /* !SVR42 */ - dma_param (chan, ((dma_mode == DMA_MODE_READ) ? DMA_Rdmode : DMA_Wrmode) -#ifdef DMAMODE_AUTO - | DMAMODE_AUTO -#endif - , - dmap->raw_buf_phys[0], dmap->bytes_in_use - 1); - dma_enable (chan); -#endif /* ! SVR42 */ -#else -#error This routine is not valid for this OS. -#endif -#endif - -#endif + restore_flags (flags); } else { -#ifdef linux - DISABLE_INTR (flags); + save_flags (flags); + cli (); disable_dma (chan); clear_dma_ff (chan); set_dma_mode (chan, dma_mode); set_dma_addr (chan, physaddr); set_dma_count (chan, count); enable_dma (chan); - RESTORE_INTR (flags); -#else -#ifdef __386BSD__ - isa_dmastart ((dma_mode == DMA_MODE_READ) ? B_READ : B_WRITE, - physaddr, - count, - chan); -#else - -#if defined(GENERIC_SYSV) -#if defined(SVR42) - - snd_dma_prog (chan, physaddr, count, dma_mode, FALSE); - -#else /* ! SVR42 */ - dma_param (chan, ((dma_mode == DMA_MODE_READ) ? DMA_Rdmode : DMA_Wrmode), - physaddr, count); - dma_enable (chan); -#endif /* SVR42 */ -#else -#error This routine is not valid for this OS. -#endif /* GENERIC_SYSV */ -#endif - -#endif + restore_flags (flags); } return count; @@ -796,16 +1182,22 @@ { int dev; -#if defined(SVR42) - snd_dma_init (); -#endif /* SVR42 */ /* * NOTE! This routine could be called several times. */ for (dev = 0; dev < num_audiodevs; dev++) - audio_devs[dev]->dmap = &dmaps[dev]; + if (audio_devs[dev]->dmap_out == NULL) + { + audio_devs[dev]->dmap_out = + audio_devs[dev]->dmap_in = + &dmaps[ndmaps++]; + + if (audio_devs[dev]->flags & DMA_DUPLEX) + audio_devs[dev]->dmap_in = + &dmaps[ndmaps++]; + } return mem_start; } @@ -823,13 +1215,39 @@ */ unsigned long flags; - struct dma_buffparms *dmap = audio_devs[dev]->dmap; + struct dma_buffparms *dmap = audio_devs[dev]->dmap_out; -#if defined(SVR42) - snd_dma_intr (audio_devs[dev]->dmachan); -#endif /* SVR42 */ + dmap->byte_counter += dmap->counts[dmap->qhead]; + + + if (dmap->mapping_flags & DMA_MAP_MAPPED) + { + /* mmapped access */ - if (event_type != 2) + int p = dmap->fragment_size * dmap->qhead; + + memset (dmap->raw_buf + p, + dmap->neutral_byte, + dmap->fragment_size); + + dmap->qhead = (dmap->qhead + 1) % dmap->nbufs; + dmap->qlen++; /* Yes increment it (don't decrement) */ + dmap->flags &= ~DMA_ACTIVE; + dmap->counts[dmap->qhead] = dmap->fragment_size; + + if (!(audio_devs[dev]->flags & DMA_AUTOMODE)) + { + audio_devs[dev]->output_block (dev, dmap->raw_buf_phys + + dmap->qhead * dmap->fragment_size, + dmap->counts[dmap->qhead], 1, + !(audio_devs[dev]->flags & DMA_AUTOMODE)); + if (audio_devs[dev]->trigger) + audio_devs[dev]->trigger (dev, + audio_devs[dev]->enable_bits * audio_devs[dev]->go); + } + dmap->flags |= DMA_ACTIVE; + } + else if (event_type != 2) { if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs) { @@ -844,15 +1262,27 @@ if (dmap->qlen) { - audio_devs[dev]->output_block (dev, dmap->buf_phys[dmap->qhead], - dmap->counts[dmap->qhead], 1, + if (!(audio_devs[dev]->flags & DMA_AUTOMODE)) + { + audio_devs[dev]->output_block (dev, dmap->raw_buf_phys + + dmap->qhead * dmap->fragment_size, + dmap->counts[dmap->qhead], 1, !(audio_devs[dev]->flags & DMA_AUTOMODE)); + if (audio_devs[dev]->trigger) + audio_devs[dev]->trigger (dev, + audio_devs[dev]->enable_bits * audio_devs[dev]->go); + } dmap->flags |= DMA_ACTIVE; } else if (event_type == 1) { dmap->underrun_count++; - audio_devs[dev]->halt_xfer (dev); + if ((audio_devs[dev]->flags & DMA_DUPLEX) && + audio_devs[dev]->halt_output) + audio_devs[dev]->halt_output (dev); + else + audio_devs[dev]->halt_xfer (dev); + if ((audio_devs[dev]->flags & DMA_AUTOMODE) && audio_devs[dev]->flags & NEEDS_RESTART) dmap->flags |= DMA_RESTART; @@ -861,29 +1291,55 @@ } } /* event_type != 2 */ - DISABLE_INTR (flags); - if (SOMEONE_WAITING (dev_sleeper[dev], dev_sleep_flag[dev])) + save_flags (flags); + cli (); + if ((out_sleep_flag[dev].mode & WK_SLEEP)) { - WAKE_UP (dev_sleeper[dev], dev_sleep_flag[dev]); + { + out_sleep_flag[dev].mode = WK_WAKEUP; + wake_up (&out_sleeper[dev]); + }; } - RESTORE_INTR (flags); + restore_flags (flags); } void DMAbuf_inputintr (int dev) { unsigned long flags; - struct dma_buffparms *dmap = audio_devs[dev]->dmap; + struct dma_buffparms *dmap = audio_devs[dev]->dmap_in; -#if defined(SVR42) - snd_dma_intr (audio_devs[dev]->dmachan); -#endif /* SVR42 */ + dmap->byte_counter += dmap->fragment_size; - if (dmap->qlen == (dmap->nbufs - 1)) + + if (dmap->mapping_flags & DMA_MAP_MAPPED) + { + dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; + dmap->qlen++; + + if (!(audio_devs[dev]->flags & DMA_AUTOMODE)) + { + audio_devs[dev]->start_input (dev, dmap->raw_buf_phys + + dmap->qtail * dmap->fragment_size, + dmap->fragment_size, 1, + !(audio_devs[dev]->flags & DMA_AUTOMODE)); + if (audio_devs[dev]->trigger) + audio_devs[dev]->trigger (dev, + audio_devs[dev]->enable_bits * audio_devs[dev]->go); + } + + dmap->flags |= DMA_ACTIVE; + } + else if (dmap->qlen == (dmap->nbufs - 1)) { printk ("Sound: Recording overrun\n"); dmap->underrun_count++; - audio_devs[dev]->halt_xfer (dev); + if ((audio_devs[dev]->flags & DMA_DUPLEX) && + audio_devs[dev]->halt_input) + audio_devs[dev]->halt_input (dev); + else + audio_devs[dev]->halt_xfer (dev); + dmap->flags &= ~DMA_ACTIVE; if (audio_devs[dev]->flags & DMA_AUTOMODE) dmap->flags |= DMA_RESTART; @@ -898,38 +1354,74 @@ dev, dmap->qlen, dmap->nbufs); dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; - audio_devs[dev]->start_input (dev, dmap->buf_phys[dmap->qtail], - dmap->fragment_size, 1, + if (!(audio_devs[dev]->flags & DMA_AUTOMODE)) + { + audio_devs[dev]->start_input (dev, dmap->raw_buf_phys + + dmap->qtail * dmap->fragment_size, + dmap->fragment_size, 1, !(audio_devs[dev]->flags & DMA_AUTOMODE)); + if (audio_devs[dev]->trigger) + audio_devs[dev]->trigger (dev, + audio_devs[dev]->enable_bits * audio_devs[dev]->go); + } + dmap->flags |= DMA_ACTIVE; } - DISABLE_INTR (flags); - if (SOMEONE_WAITING (dev_sleeper[dev], dev_sleep_flag[dev])) + save_flags (flags); + cli (); + if ((in_sleep_flag[dev].mode & WK_SLEEP)) { - WAKE_UP (dev_sleeper[dev], dev_sleep_flag[dev]); + { + in_sleep_flag[dev].mode = WK_WAKEUP; + wake_up (&in_sleeper[dev]); + }; } - RESTORE_INTR (flags); + restore_flags (flags); } int DMAbuf_open_dma (int dev) { + int chan = audio_devs[dev]->dmachan1; + int err; unsigned long flags; - int chan = audio_devs[dev]->dmachan; - if (ALLOC_DMA_CHN (chan, audio_devs[dev]->name)) + if ((err = open_dmap (dev, OPEN_READWRITE, audio_devs[dev]->dmap_out, audio_devs[dev]->dmachan1)) < 0) { - printk ("Unable to grab DMA%d for the audio driver\n", chan); - return RET_ERROR (EBUSY); + return -EBUSY; } + dma_init_buffers (dev, audio_devs[dev]->dmap_out); + audio_devs[dev]->dmap_out->flags |= DMA_ALLOC_DONE; + audio_devs[dev]->dmap_out->fragment_size = audio_devs[dev]->buffsize; + /* reorganize_buffers (dev, audio_devs[dev]->dmap_out); */ - DISABLE_INTR (flags); -#ifdef linux + if (audio_devs[dev]->flags & DMA_DUPLEX) + { + if ((err = open_dmap (dev, OPEN_READWRITE, audio_devs[dev]->dmap_in, audio_devs[dev]->dmachan2)) < 0) + { + printk ("Unable to grab DMA%d for the audio driver\n", + audio_devs[dev]->dmachan2); + close_dmap (dev, audio_devs[dev]->dmap_out, audio_devs[dev]->dmachan1); + return -EBUSY; + } + dma_init_buffers (dev, audio_devs[dev]->dmap_in); + audio_devs[dev]->dmap_in->flags |= DMA_ALLOC_DONE; + audio_devs[dev]->dmap_in->fragment_size = audio_devs[dev]->buffsize; + /* reorganize_buffers (dev, audio_devs[dev]->dmap_in); */ + } + else + { + audio_devs[dev]->dmap_in = audio_devs[dev]->dmap_out; + audio_devs[dev]->dmachan2 = audio_devs[dev]->dmachan1; + } + + + save_flags (flags); + cli (); disable_dma (chan); clear_dma_ff (chan); -#endif - RESTORE_INTR (flags); + restore_flags (flags); return 0; } @@ -937,48 +1429,60 @@ void DMAbuf_close_dma (int dev) { - int chan = audio_devs[dev]->dmachan; - DMAbuf_reset_dma (dev); - RELEASE_DMA_CHN (chan); + close_dmap (dev, audio_devs[dev]->dmap_out, audio_devs[dev]->dmachan1); + + if (audio_devs[dev]->flags & DMA_DUPLEX) + close_dmap (dev, audio_devs[dev]->dmap_in, audio_devs[dev]->dmachan2); + } void DMAbuf_reset_dma (int dev) { -#if 0 - int chan = audio_devs[dev]->dmachan; - - disable_dma (chan); -#endif } -#ifdef ALLOW_SELECT int DMAbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wait) { - struct dma_buffparms *dmap = audio_devs[dev]->dmap; + struct dma_buffparms *dmap; unsigned long flags; switch (sel_type) { case SEL_IN: + dmap = audio_devs[dev]->dmap_in; if (dmap->dma_mode != DMODE_INPUT) - return 0; + { + if ((audio_devs[dev]->flags & DMA_DUPLEX) && !dmap->qlen && + audio_devs[dev]->enable_bits & PCM_ENABLE_INPUT && + audio_devs[dev]->go) + { + unsigned long flags; + + save_flags (flags); + cli (); + activate_recording (dev, dmap); + restore_flags (flags); + } + return 0; + } if (!dmap->qlen) { - DISABLE_INTR (flags); - dev_sleep_flag[dev].mode = WK_SLEEP; - select_wait (&dev_sleeper[dev], wait); - RESTORE_INTR (flags); + save_flags (flags); + cli (); + in_sleep_flag[dev].mode = WK_SLEEP; + select_wait (&in_sleeper[dev], wait); + restore_flags (flags); return 0; } return 1; break; case SEL_OUT: + dmap = audio_devs[dev]->dmap_out; if (dmap->dma_mode == DMODE_INPUT) { return 0; @@ -991,10 +1495,11 @@ if (!space_in_queue (dev)) { - DISABLE_INTR (flags); - dev_sleep_flag[dev].mode = WK_SLEEP; - select_wait (&dev_sleeper[dev], wait); - RESTORE_INTR (flags); + save_flags (flags); + cli (); + out_sleep_flag[dev].mode = WK_SLEEP; + select_wait (&out_sleeper[dev], wait); + restore_flags (flags); return 0; } return 1; @@ -1007,7 +1512,6 @@ return 0; } -#endif /* ALLOW_SELECT */ #else /* EXCLUDE_AUDIO */ /* @@ -1017,7 +1521,7 @@ int DMAbuf_open (int dev, int mode) { - return RET_ERROR (ENXIO); + return -ENXIO; } int @@ -1029,31 +1533,31 @@ int DMAbuf_getwrbuffer (int dev, char **buf, int *size, int dontblock) { - return RET_ERROR (EIO); + return -EIO; } int DMAbuf_getrdbuffer (int dev, char **buf, int *len, int dontblock) { - return RET_ERROR (EIO); + return -EIO; } int DMAbuf_rmchars (int dev, int buff_no, int c) { - return RET_ERROR (EIO); + return -EIO; } int DMAbuf_start_output (int dev, int buff_no, int l) { - return RET_ERROR (EIO); + return -EIO; } int -DMAbuf_ioctl (int dev, unsigned int cmd, unsigned int arg, int local) +DMAbuf_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local) { - return RET_ERROR (EIO); + return -EIO; } long @@ -1065,13 +1569,13 @@ int DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode) { - return RET_ERROR (EIO); + return -EIO; } int DMAbuf_open_dma (int dev) { - return RET_ERROR (ENXIO); + return -ENXIO; } void @@ -1097,7 +1601,6 @@ { return; } - #endif #endif diff -u --recursive --new-file v1.3.33/linux/drivers/sound/gus_card.c linux/drivers/sound/gus_card.c --- v1.3.33/linux/drivers/sound/gus_card.c Tue Jul 11 10:02:52 1995 +++ linux/drivers/sound/gus_card.c Wed Oct 11 07:55:40 1995 @@ -33,31 +33,40 @@ #include "gus_hw.h" -void gusintr (INT_HANDLER_PARMS (irq, dummy)); +void gusintr (int irq, struct pt_regs *dummy); int gus_base, gus_irq, gus_dma; extern int gus_wave_volume; extern int gus_pcm_volume; extern int have_gus_max; +sound_os_info *gus_osp; + long attach_gus_card (long mem_start, struct address_info *hw_config) { int io_addr; - snd_set_irq_handler (hw_config->irq, gusintr, "Gravis Ultrasound"); + gus_osp = hw_config->osp; + snd_set_irq_handler (hw_config->irq, gusintr, "Gravis Ultrasound", hw_config->osp); if (gus_wave_detect (hw_config->io_base)) /* * Try first the default */ { - mem_start = gus_wave_init (mem_start, hw_config->irq, hw_config->dma); + mem_start = gus_wave_init (mem_start, hw_config); + + request_region (hw_config->io_base, 16, "GUS"); + request_region (hw_config->io_base + 0x100, 12, "GUS"); /* 0x10c-> is MAX */ + + if (sound_alloc_dma (hw_config->dma, "GUS")) + printk ("gus_card.c: Can't allocate DMA channel\n"); + if (hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma) + if (sound_alloc_dma (hw_config->dma2, "GUS(2)")) + printk ("gus_card.c: Can't allocate DMA channel2\n"); #ifndef EXCLUDE_MIDI mem_start = gus_midi_init (mem_start); #endif -#ifndef EXCLUDE_SEQUENCER - sound_timer_init (hw_config->io_base + 8); -#endif return mem_start; } @@ -73,14 +82,20 @@ */ if (gus_wave_detect (io_addr)) { + hw_config->io_base = io_addr; + printk (" WARNING! GUS found at %x, config was %x ", io_addr, hw_config->io_base); - mem_start = gus_wave_init (mem_start, hw_config->irq, hw_config->dma); + mem_start = gus_wave_init (mem_start, hw_config); + request_region (io_addr, 16, "GUS"); + request_region (io_addr + 0x100, 12, "GUS"); /* 0x10c-> is MAX */ + if (sound_alloc_dma (hw_config->dma, "GUS")) + printk ("gus_card.c: Can't allocate DMA channel\n"); + if (hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma) + if (sound_alloc_dma (hw_config->dma2, "GUS")) + printk ("gus_card.c: Can't allocate DMA channel2\n"); #ifndef EXCLUDE_MIDI mem_start = gus_midi_init (mem_start); #endif -#ifndef EXCLUDE_SEQUENCER - sound_timer_init (io_addr + 8); -#endif return mem_start; } @@ -96,8 +111,12 @@ { int io_addr; - if (gus_wave_detect (hw_config->io_base)) - return 1; + gus_osp = hw_config->osp; + + if (!check_region (hw_config->io_base, 16)) + if (!check_region (hw_config->io_base + 0x100, 16)) + if (gus_wave_detect (hw_config->io_base)) + return 1; #ifndef EXCLUDE_GUS_IODETECT @@ -109,8 +128,13 @@ if (io_addr != hw_config->io_base) /* * Already tested */ - if (gus_wave_detect (io_addr)) - return 1; + if (!check_region (io_addr, 16)) + if (!check_region (io_addr + 0x100, 16)) + if (gus_wave_detect (io_addr)) + { + hw_config->io_base = io_addr; + return 1; + } #endif @@ -118,22 +142,36 @@ } void -gusintr (INT_HANDLER_PARMS (irq, dummy)) +unload_gus (struct address_info *hw_config) +{ + gus_wave_unload (); + + release_region (hw_config->io_base, 16); + release_region (hw_config->io_base + 0x100, 12); /* 0x10c-> is MAX */ + snd_release_irq (hw_config->irq); + + sound_free_dma (hw_config->dma); + + if (hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma) + sound_free_dma (hw_config->dma2); +} + +void +gusintr (int irq, struct pt_regs *dummy) { unsigned char src; + extern int gus_timer_enabled; -#ifdef linux sti (); -#endif #ifndef EXCLUDE_GUSMAX if (have_gus_max) - ad1848_interrupt (INT_HANDLER_CALL (irq)); + ad1848_interrupt (irq, NULL); #endif while (1) { - if (!(src = INB (u_IrqStatus))) + if (!(src = inb (u_IrqStatus))) return; if (src & DMA_TC_IRQ) @@ -151,7 +189,11 @@ if (src & (GF1_TIMER1_IRQ | GF1_TIMER2_IRQ)) { #ifndef EXCLUDE_SEQUENCER - sound_timer_interrupt (); + if (gus_timer_enabled) + sound_timer_interrupt (); + gus_write8 (0x45, 0); /* Ack IRQ */ + gus_timer_command (4, 0x80); /* Reset IRQ flags */ + #else gus_write8 (0x45, 0); /* Stop timers */ #endif @@ -174,7 +216,7 @@ int probe_gus_db16 (struct address_info *hw_config) { - return ad1848_detect (hw_config->io_base); + return ad1848_detect (hw_config->io_base, NULL, hw_config->osp); } long @@ -186,8 +228,18 @@ ad1848_init ("GUS 16 bit sampling", hw_config->io_base, hw_config->irq, hw_config->dma, - hw_config->dma); + hw_config->dma, 0, + hw_config->osp); return mem_start; } +void +unload_gus_db16 (struct address_info *hw_config) +{ + + ad1848_unload (hw_config->io_base, + hw_config->irq, + hw_config->dma, + hw_config->dma, 0); +} #endif diff -u --recursive --new-file v1.3.33/linux/drivers/sound/gus_midi.c linux/drivers/sound/gus_midi.c --- v1.3.33/linux/drivers/sound/gus_midi.c Tue Jul 11 10:02:52 1995 +++ linux/drivers/sound/gus_midi.c Wed Oct 11 07:55:40 1995 @@ -46,8 +46,9 @@ static volatile int qlen; static volatile unsigned char qhead, qtail; extern int gus_base, gus_irq, gus_dma; +extern sound_os_info *gus_osp; -#define GUS_MIDI_STATUS() INB(u_MidiStatus) +#define GUS_MIDI_STATUS() inb( u_MidiStatus) static int gus_midi_open (int dev, int mode, @@ -59,10 +60,10 @@ if (midi_busy) { printk ("GUS: Midi busy\n"); - return RET_ERROR (EBUSY); + return -EBUSY; } - OUTB (MIDI_RESET, u_MidiControl); + outb (MIDI_RESET, u_MidiControl); gus_delay (); gus_midi_control = 0; @@ -79,7 +80,7 @@ gus_midi_control |= MIDI_ENABLE_XMIT; } - OUTB (gus_midi_control, u_MidiControl); /* + outb (gus_midi_control, u_MidiControl); /* * Enable */ @@ -98,12 +99,13 @@ output_used = 1; - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (GUS_MIDI_STATUS () & MIDI_XMIT_EMPTY) { ok = 1; - OUTB (midi_byte, u_MidiData); + outb (midi_byte, u_MidiData); } else { @@ -111,10 +113,10 @@ * Enable Midi xmit interrupts (again) */ gus_midi_control |= MIDI_ENABLE_XMIT; - OUTB (gus_midi_control, u_MidiControl); + outb (gus_midi_control, u_MidiControl); } - RESTORE_INTR (flags); + restore_flags (flags); return ok; } @@ -125,7 +127,7 @@ * Reset FIFO pointers, disable intrs */ - OUTB (MIDI_RESET, u_MidiControl); + outb (MIDI_RESET, u_MidiControl); midi_busy = 0; } @@ -139,7 +141,8 @@ * Drain the local queue first */ - DISABLE_INTR (flags); + save_flags (flags); + cli (); while (qlen && dump_to_midi (tmp_queue[qhead])) { @@ -147,7 +150,7 @@ qhead++; } - RESTORE_INTR (flags); + restore_flags (flags); /* * Output the byte if the local queue is empty. @@ -168,13 +171,14 @@ * Local queue full */ - DISABLE_INTR (flags); + save_flags (flags); + cli (); tmp_queue[qtail] = midi_byte; qlen++; qtail++; - RESTORE_INTR (flags); + restore_flags (flags); return 1; } @@ -192,9 +196,9 @@ } static int -gus_midi_ioctl (int dev, unsigned cmd, unsigned arg) +gus_midi_ioctl (int dev, unsigned cmd, ioctl_arg arg) { - return RET_ERROR (EINVAL); + return -EINVAL; } static void @@ -210,7 +214,8 @@ if (!output_used) return 0; - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (qlen && dump_to_midi (tmp_queue[qhead])) { @@ -218,7 +223,7 @@ qhead++; } - RESTORE_INTR (flags); + restore_flags (flags); return (qlen > 0) | !(GUS_MIDI_STATUS () & MIDI_XMIT_EMPTY); } @@ -255,7 +260,7 @@ return mem_start; } - OUTB (MIDI_RESET, u_MidiControl); + outb (MIDI_RESET, u_MidiControl); std_midi_synth.midi_dev = my_dev = num_midis; midi_devs[num_midis++] = &gus_midi_operations; @@ -268,13 +273,14 @@ unsigned char stat, data; unsigned long flags; - DISABLE_INTR (flags); + save_flags (flags); + cli (); stat = GUS_MIDI_STATUS (); if (stat & MIDI_RCV_FULL) { - data = INB (u_MidiData); + data = inb (u_MidiData); if (input_opened) midi_input_intr (my_dev, data); } @@ -293,18 +299,12 @@ * Disable Midi output interrupts, since no data in the buffer */ gus_midi_control &= ~MIDI_ENABLE_XMIT; - OUTB (gus_midi_control, u_MidiControl); + outb (gus_midi_control, u_MidiControl); } } -#if 0 - if (stat & MIDI_FRAME_ERR) - printk ("GUS: Midi framing error\n"); - if (stat & MIDI_OVERRUN && input_opened) - printk ("GUS: Midi input overrun\n"); -#endif - RESTORE_INTR (flags); + restore_flags (flags); } #endif diff -u --recursive --new-file v1.3.33/linux/drivers/sound/gus_vol.c linux/drivers/sound/gus_vol.c --- v1.3.33/linux/drivers/sound/gus_vol.c Mon Jul 18 09:50:55 1994 +++ linux/drivers/sound/gus_vol.c Wed Oct 11 07:55:40 1995 @@ -138,10 +138,10 @@ else if (mainvol >= 127) mainvol = 127; #else - mainvol = 128; + mainvol = 127; #endif - return gus_linearvol[(((vol * mainvol) / 128) * mixer_mainvol) / 100]; + return gus_linearvol[(((vol * mainvol) / 127) * mixer_mainvol) / 100]; } #endif diff -u --recursive --new-file v1.3.33/linux/drivers/sound/gus_wave.c linux/drivers/sound/gus_wave.c --- v1.3.33/linux/drivers/sound/gus_wave.c Tue Jul 11 10:02:53 1995 +++ linux/drivers/sound/gus_wave.c Wed Oct 11 07:55:40 1995 @@ -76,7 +76,7 @@ extern int gus_base; extern int gus_irq, gus_dma; -static int gusmax_dma = -1; +static int gus_dma2 = -1; static int dual_dma_mode = 0; static long gus_mem_size = 0; static long free_mem_ptr = 0; @@ -88,6 +88,7 @@ static int gus_recmask = SOUND_MASK_MIC; static int recording_active = 0; static int only_read_access = 0; +static int only_8_bits = 0; int gus_wave_volume = 60; int gus_pcm_volume = 80; @@ -95,6 +96,8 @@ static int gus_line_vol = 100, gus_mic_vol = 0; static unsigned char mix_image = 0x00; +int gus_timer_enabled = 0; + /* * Current version of this driver doesn't allow synth and PCM functions * at the same time. The active_device specifies the active driver @@ -109,7 +112,9 @@ static int gus_sampling_channels; static int gus_sampling_bits; -DEFINE_WAIT_QUEUE (dram_sleeper, dram_sleep_flag); +static struct wait_queue *dram_sleeper = NULL; +static volatile struct snd_wait dram_sleep_flag = +{0}; /* * Variables and buffers for PCM output @@ -128,6 +133,8 @@ static int pcm_current_count; static int pcm_current_intrflag; +extern sound_os_info *gus_osp; + struct voice_info voices[32]; static int freq_div_table[] = @@ -157,6 +164,7 @@ static long sample_ptrs[MAX_SAMPLE + 1]; static int sample_map[32]; static int free_sample; +static int mixer_type = 0; static int patch_table[MAX_PATCH]; @@ -172,6 +180,7 @@ static void compute_volume (int voice, int volume); static void do_volume_irq (int voice); static void set_input_volumes (void); +static void gus_tmr_install (int io_base); #define INSTANT_RAMP -1 /* Instant change. No ramping */ #define FAST_RAMP 0 /* Fastest possible ramp */ @@ -204,7 +213,7 @@ int i; for (i = 0; i < 7; i++) - INB (u_DRAMIO); + inb (u_DRAMIO); } static void @@ -212,15 +221,16 @@ { /* Writes a byte to the DRAM */ unsigned long flags; - DISABLE_INTR (flags); - OUTB (0x43, u_Command); - OUTB (addr & 0xff, u_DataLo); - OUTB ((addr >> 8) & 0xff, u_DataHi); - - OUTB (0x44, u_Command); - OUTB ((addr >> 16) & 0xff, u_DataHi); - OUTB (data, u_DRAMIO); - RESTORE_INTR (flags); + save_flags (flags); + cli (); + outb (0x43, u_Command); + outb (addr & 0xff, u_DataLo); + outb ((addr >> 8) & 0xff, u_DataHi); + + outb (0x44, u_Command); + outb ((addr >> 16) & 0xff, u_DataHi); + outb (data, u_DRAMIO); + restore_flags (flags); } static unsigned char @@ -229,15 +239,16 @@ unsigned long flags; unsigned char tmp; - DISABLE_INTR (flags); - OUTB (0x43, u_Command); - OUTB (addr & 0xff, u_DataLo); - OUTB ((addr >> 8) & 0xff, u_DataHi); - - OUTB (0x44, u_Command); - OUTB ((addr >> 16) & 0xff, u_DataHi); - tmp = INB (u_DRAMIO); - RESTORE_INTR (flags); + save_flags (flags); + cli (); + outb (0x43, u_Command); + outb (addr & 0xff, u_DataLo); + outb ((addr >> 8) & 0xff, u_DataHi); + + outb (0x44, u_Command); + outb ((addr >> 16) & 0xff, u_DataHi); + tmp = inb (u_DRAMIO); + restore_flags (flags); return tmp; } @@ -247,12 +258,13 @@ { /* Writes to an indirect register (8 bit) */ unsigned long flags; - DISABLE_INTR (flags); + save_flags (flags); + cli (); - OUTB (reg, u_Command); - OUTB ((unsigned char) (data & 0xff), u_DataHi); + outb (reg, u_Command); + outb ((unsigned char) (data & 0xff), u_DataHi); - RESTORE_INTR (flags); + restore_flags (flags); } unsigned char @@ -261,10 +273,11 @@ unsigned long flags; unsigned char val; - DISABLE_INTR (flags); - OUTB (reg | 0x80, u_Command); - val = INB (u_DataHi); - RESTORE_INTR (flags); + save_flags (flags); + cli (); + outb (reg | 0x80, u_Command); + val = inb (u_DataHi); + restore_flags (flags); return val; } @@ -275,10 +288,11 @@ unsigned long flags; unsigned char val; - DISABLE_INTR (flags); - OUTB (reg, u_Command); - val = INB (u_DataHi); - RESTORE_INTR (flags); + save_flags (flags); + cli (); + outb (reg, u_Command); + val = inb (u_DataHi); + restore_flags (flags); return val; } @@ -288,14 +302,15 @@ { /* Writes to an indirect register (16 bit) */ unsigned long flags; - DISABLE_INTR (flags); + save_flags (flags); + cli (); - OUTB (reg, u_Command); + outb (reg, u_Command); - OUTB ((unsigned char) (data & 0xff), u_DataLo); - OUTB ((unsigned char) ((data >> 8) & 0xff), u_DataHi); + outb ((unsigned char) (data & 0xff), u_DataLo); + outb ((unsigned char) ((data >> 8) & 0xff), u_DataHi); - RESTORE_INTR (flags); + restore_flags (flags); } unsigned short @@ -304,14 +319,15 @@ unsigned long flags; unsigned char hi, lo; - DISABLE_INTR (flags); + save_flags (flags); + cli (); - OUTB (reg | 0x80, u_Command); + outb (reg | 0x80, u_Command); - lo = INB (u_DataLo); - hi = INB (u_DataHi); + lo = inb (u_DataLo); + hi = inb (u_DataHi); - RESTORE_INTR (flags); + restore_flags (flags); return ((hi << 8) & 0xff00) | lo; } @@ -322,7 +338,8 @@ unsigned long hold_address; unsigned long flags; - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (is16bit) { /* @@ -341,7 +358,7 @@ gus_delay (); gus_write16 (reg, (unsigned short) ((address >> 7) & 0xffff)); gus_write16 (reg + 1, (unsigned short) ((address << 9) & 0xffff)); - RESTORE_INTR (flags); + restore_flags (flags); } static void @@ -350,7 +367,7 @@ if (voice < 0 || voice > 31) return; - OUTB (voice, u_Voice); + outb (voice, u_Voice); } static void @@ -475,7 +492,8 @@ { unsigned long flags; - DISABLE_INTR (flags); + save_flags (flags); + cli (); gus_select_voice (voice); gus_voice_volume (0); gus_voice_off (); @@ -484,7 +502,7 @@ gus_write8 (0x0d, 0x03); /* Ramping off */ voice_alloc->map[voice] = 0; voice_alloc->alloc_times[voice] = 0; - RESTORE_INTR (flags); + restore_flags (flags); } @@ -519,10 +537,11 @@ if (voices[voice].mode & WAVE_SUSTAIN_ON && voices[voice].env_phase == 2) { - DISABLE_INTR (flags); + save_flags (flags); + cli (); gus_select_voice (voice); gus_rampoff (); - RESTORE_INTR (flags); + restore_flags (flags); return; /* * Sustain phase begins. Continue envelope after receiving note off. @@ -541,7 +560,8 @@ vol = voices[voice].initial_volume * voices[voice].env_offset[phase] / 255; rate = voices[voice].env_rate[phase]; - DISABLE_INTR (flags); + save_flags (flags); + cli (); gus_select_voice (voice); gus_voice_volume (prev_vol); @@ -553,7 +573,7 @@ if (((vol - prev_vol) / 64) == 0) /* No significant volume change */ { - RESTORE_INTR (flags); + restore_flags (flags); step_envelope (voice); /* Continue the envelope on the next step */ return; } @@ -573,7 +593,7 @@ gus_rampon (0x60); /* Decreasing volume, with IRQ */ } voices[voice].current_volume = vol; - RESTORE_INTR (flags); + restore_flags (flags); } static void @@ -599,7 +619,7 @@ voices[voice].mode &= ~WAVE_SUSTAIN_ON; gus_rampoff (); - RESTORE_INTR (flags); + restore_flags (flags); step_envelope (voice); } @@ -609,14 +629,15 @@ int instr_no = sample_map[voice], is16bits; long int flags; - DISABLE_INTR (flags); + save_flags (flags); + cli (); gus_select_voice (voice); if (instr_no < 0 || instr_no > MAX_SAMPLE) { gus_write8 (0x00, 0x03); /* Hard stop */ voice_alloc->map[voice] = 0; - RESTORE_INTR (flags); + restore_flags (flags); return; } @@ -643,7 +664,7 @@ gus_ramp_rate (2, 4); gus_rampon (0x40 | 0x20); /* Down, once, with IRQ */ voices[voice].volume_irq_mode = VMODE_HALT; - RESTORE_INTR (flags); + restore_flags (flags); } static void @@ -662,7 +683,7 @@ gus_voice_init2 (i); } - INB (u_Status); /* Touch the status register */ + inb (u_Status); /* Touch the status register */ gus_look8 (0x41); /* Clear any pending DMA IRQs */ gus_look8 (0x49); /* Clear any pending sample IRQs */ @@ -683,7 +704,8 @@ static unsigned char gus_dma_map[8] = {0, 1, 0, 2, 0, 3, 4, 5}; - DISABLE_INTR (flags); + save_flags (flags); + cli (); gus_write8 (0x4c, 0); /* Reset GF1 */ gus_delay (); gus_delay (); @@ -702,7 +724,7 @@ gus_select_max_voices (24); - INB (u_Status); /* Touch the status register */ + inb (u_Status); /* Touch the status register */ gus_look8 (0x41); /* Clear any pending DMA IRQs */ gus_look8 (0x49); /* Clear any pending sample IRQs */ @@ -720,14 +742,14 @@ * Set up for Digital ASIC */ - OUTB (0x05, gus_base + 0x0f); + outb (0x05, gus_base + 0x0f); mix_image |= 0x02; /* Disable line out (for a moment) */ - OUTB (mix_image, u_Mixer); + outb (mix_image, u_Mixer); - OUTB (0x00, u_IRQDMAControl); + outb (0x00, u_IRQDMAControl); - OUTB (0x00, gus_base + 0x0f); + outb (0x00, gus_base + 0x0f); /* * Now set up the DMA and IRQ interface @@ -747,7 +769,7 @@ irq_image |= 0x40; /* Combine IRQ1 (GF1) and IRQ2 (Midi) */ dual_dma_mode = 1; - if (!have_gus_max || gusmax_dma == gus_dma || gusmax_dma == -1) + if (gus_dma2 == gus_dma || gus_dma2 == -1) { dual_dma_mode = 0; dma_image = 0x40; /* Combine DMA1 (DRAM) and IRQ2 (ADC) */ @@ -765,7 +787,7 @@ if (!dma_image) printk ("Warning! GUS DMA not selected\n"); - tmp = gus_dma_map[gusmax_dma] << 3; + tmp = gus_dma_map[gus_dma2] << 3; if (!tmp) { printk ("Warning! Invalid GUS MAX DMA\n"); @@ -784,35 +806,35 @@ * Doing it first time */ - OUTB (mix_image, u_Mixer); /* Select DMA control */ - OUTB (dma_image | 0x80, u_IRQDMAControl); /* Set DMA address */ + outb (mix_image, u_Mixer); /* Select DMA control */ + outb (dma_image | 0x80, u_IRQDMAControl); /* Set DMA address */ - OUTB (mix_image | 0x40, u_Mixer); /* Select IRQ control */ - OUTB (irq_image, u_IRQDMAControl); /* Set IRQ address */ + outb (mix_image | 0x40, u_Mixer); /* Select IRQ control */ + outb (irq_image, u_IRQDMAControl); /* Set IRQ address */ /* * Doing it second time */ - OUTB (mix_image, u_Mixer); /* Select DMA control */ - OUTB (dma_image, u_IRQDMAControl); /* Set DMA address */ + outb (mix_image, u_Mixer); /* Select DMA control */ + outb (dma_image, u_IRQDMAControl); /* Set DMA address */ - OUTB (mix_image | 0x40, u_Mixer); /* Select IRQ control */ - OUTB (irq_image, u_IRQDMAControl); /* Set IRQ address */ + outb (mix_image | 0x40, u_Mixer); /* Select IRQ control */ + outb (irq_image, u_IRQDMAControl); /* Set IRQ address */ gus_select_voice (0); /* This disables writes to IRQ/DMA reg */ mix_image &= ~0x02; /* Enable line out */ mix_image |= 0x08; /* Enable IRQ */ - OUTB (mix_image, u_Mixer); /* + outb (mix_image, u_Mixer); /* * Turn mixer channels on * Note! Mic in is left off. */ gus_select_voice (0); /* This disables writes to IRQ/DMA reg */ - gusintr (INT_HANDLER_CALL (0)); /* Serve pending interrupts */ - RESTORE_INTR (flags); + gusintr (0, NULL); /* Serve pending interrupts */ + restore_flags (flags); } int @@ -867,14 +889,14 @@ static int guswave_ioctl (int dev, - unsigned int cmd, unsigned int arg) + unsigned int cmd, ioctl_arg arg) { switch (cmd) { case SNDCTL_SYNTH_INFO: gus_info.nr_voices = nr_voices; - IOCTL_TO_USER ((char *) arg, 0, &gus_info, sizeof (gus_info)); + memcpy_tofs (&(((char *) arg)[0]), (&gus_info), (sizeof (gus_info))); return 0; break; @@ -891,7 +913,7 @@ return gus_mem_size - free_mem_ptr - 32; default: - return RET_ERROR (EINVAL); + return -EINVAL; } } @@ -901,10 +923,10 @@ int sample_no; if (instr_no < 0 || instr_no > MAX_PATCH) - return RET_ERROR (EINVAL); + return -EINVAL; if (voice < 0 || voice > 31) - return RET_ERROR (EINVAL); + return -EINVAL; if (voices[voice].volume_irq_mode == VMODE_START_NOTE) { @@ -918,14 +940,14 @@ if (sample_no < 0) { printk ("GUS: Undefined patch %d for voice %d\n", instr_no, voice); - return RET_ERROR (EINVAL); /* Patch not defined */ + return -EINVAL; /* Patch not defined */ } if (sample_ptrs[sample_no] == -1) /* Sample not loaded */ { printk ("GUS: Sample #%d not loaded for patch %d (voice %d)\n", sample_no, instr_no, voice); - return RET_ERROR (EINVAL); + return -EINVAL; } sample_map[voice] = sample_no; @@ -938,63 +960,27 @@ { unsigned long flags; - DISABLE_INTR (flags); + save_flags (flags); + cli (); /* voice_alloc->map[voice] = 0xffff; */ if (voices[voice].volume_irq_mode == VMODE_START_NOTE) { voices[voice].kill_pending = 1; - RESTORE_INTR (flags); + restore_flags (flags); } else { - RESTORE_INTR (flags); + restore_flags (flags); gus_voice_fade (voice); } - RESTORE_INTR (flags); + restore_flags (flags); return 0; } static void guswave_aftertouch (int dev, int voice, int pressure) { -#if 0 - short lo_limit, hi_limit; - unsigned long flags; - - if (voice < 0 || voice > 31) - return; - - if (voices[voice].mode & WAVE_ENVELOPES && voices[voice].env_phase != 2) - return; /* Don't mix with envelopes */ - - if (pressure < 32) - { - DISABLE_INTR (flags); - gus_select_voice (voice); - gus_rampoff (); - compute_and_set_volume (voice, 255, 0); /* Back to original volume */ - RESTORE_INTR (flags); - return; - } - - hi_limit = voices[voice].current_volume; - lo_limit = hi_limit * 99 / 100; - if (lo_limit < 65) - lo_limit = 65; - - DISABLE_INTR (flags); - gus_select_voice (voice); - if (hi_limit > (4095 - 65)) - { - hi_limit = 4095 - 65; - gus_voice_volume (hi_limit); - } - gus_ramp_range (lo_limit, hi_limit); - gus_ramp_rate (3, 8); - gus_rampon (0x58); /* Bidirectional, dow, loop */ - RESTORE_INTR (flags); -#endif /* 0 */ } static void @@ -1049,7 +1035,8 @@ compute_volume (voice, volume); voices[voice].current_volume = voices[voice].initial_volume; - DISABLE_INTR (flags); + save_flags (flags); + cli (); /* * CAUTION! Interrupts disabled. Enable them before returning */ @@ -1063,7 +1050,7 @@ { gus_rampoff (); gus_voice_volume (target); - RESTORE_INTR (flags); + restore_flags (flags); return; } @@ -1077,7 +1064,7 @@ { gus_rampoff (); gus_voice_volume (target); - RESTORE_INTR (flags); + restore_flags (flags); return; } @@ -1096,7 +1083,7 @@ gus_ramp_range (target, current); gus_rampon (0x40); /* Ramp down, once, no irq */ } - RESTORE_INTR (flags); + restore_flags (flags); } static void @@ -1105,10 +1092,11 @@ unsigned char status; unsigned long flags; - DISABLE_INTR (flags); + save_flags (flags); + cli (); gus_select_voice (voice); status = gus_read8 (0x00); /* Get voice status */ - RESTORE_INTR (flags); + restore_flags (flags); if (status & 0x03) return; /* Voice was not running */ @@ -1123,10 +1111,11 @@ * Voice is running and has envelopes. */ - DISABLE_INTR (flags); + save_flags (flags); + cli (); gus_select_voice (voice); status = gus_read8 (0x0d); /* Ramping status */ - RESTORE_INTR (flags); + restore_flags (flags); if (status & 0x03) /* Sustain phase? */ { @@ -1161,10 +1150,11 @@ voices[voice].bender_range); voices[voice].current_freq = freq; - DISABLE_INTR (flags); + save_flags (flags); + cli (); gus_select_voice (voice); gus_voice_freq (freq); - RESTORE_INTR (flags); + restore_flags (flags); } break; @@ -1211,7 +1201,7 @@ if (voice < 0 || voice > 31) { printk ("GUS: Invalid voice\n"); - return RET_ERROR (EINVAL); + return -EINVAL; } if (note_num == 255) @@ -1229,12 +1219,12 @@ if ((patch = patch_map[voice]) == -1) { - return RET_ERROR (EINVAL); + return -EINVAL; } if ((samplep = patch_table[patch]) == -1) { - return RET_ERROR (EINVAL); + return -EINVAL; } note_freq = note_to_freq (note_num); @@ -1326,12 +1316,13 @@ * CAUTION! Interrupts disabled. Don't return before enabling *************************************************************************/ - DISABLE_INTR (flags); + save_flags (flags); + cli (); gus_select_voice (voice); gus_voice_off (); gus_rampoff (); - RESTORE_INTR (flags); + restore_flags (flags); if (voices[voice].mode & WAVE_ENVELOPES) { @@ -1341,7 +1332,8 @@ else compute_and_set_volume (voice, volume, 0); - DISABLE_INTR (flags); + save_flags (flags); + cli (); gus_select_voice (voice); if (samples[sample].mode & WAVE_LOOP_BACK) @@ -1384,7 +1376,7 @@ gus_voice_freq (freq); gus_voice_balance (pan); gus_voice_on (mode); - RESTORE_INTR (flags); + restore_flags (flags); return 0; } @@ -1402,7 +1394,8 @@ int mode; int ret_val = 0; - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (note_num == 255) { if (voices[voice].volume_irq_mode == VMODE_START_NOTE) @@ -1426,11 +1419,12 @@ if (voices[voice].sample_pending >= 0) { - RESTORE_INTR (flags); /* Run temporarily with interrupts enabled */ + restore_flags (flags); /* Run temporarily with interrupts enabled */ guswave_set_instr (voices[voice].dev_pending, voice, voices[voice].sample_pending); voices[voice].sample_pending = -1; - DISABLE_INTR (flags); + save_flags (flags); + cli (); gus_select_voice (voice); /* Reselect the voice (just to be sure) */ } @@ -1451,7 +1445,7 @@ gus_rampon (0x20 | 0x40); /* Ramp down, once, irq */ } } - RESTORE_INTR (flags); + restore_flags (flags); return ret_val; } @@ -1473,17 +1467,23 @@ int err; if (gus_busy) - return RET_ERROR (EBUSY); + return -EBUSY; gus_initialize (); voice_alloc->timestamp = 0; if ((err = DMAbuf_open_dma (gus_devnum)) < 0) - gus_no_dma = 1; /* Upload samples using PIO */ + { + printk ("GUS: Loading saples without DMA\n"); + gus_no_dma = 1; /* Upload samples using PIO */ + } else gus_no_dma = 0; - RESET_WAIT_QUEUE (dram_sleeper, dram_sleep_flag); + { + dram_sleep_flag.aborting = 0; + dram_sleep_flag.mode = WK_NONE; + }; gus_busy = 1; active_device = GUS_DEV_WAVE; @@ -1504,7 +1504,7 @@ } static int -guswave_load_patch (int dev, int format, snd_rw_buf * addr, +guswave_load_patch (int dev, int format, const snd_rw_buf * addr, int offs, int count, int pmgr_flag) { struct patch_info patch; @@ -1518,13 +1518,13 @@ if (format != GUS_PATCH) { printk ("GUS Error: Invalid patch format (key) 0x%x\n", format); - return RET_ERROR (EINVAL); + return -EINVAL; } if (count < sizeof_patch) { printk ("GUS Error: Patch header too short\n"); - return RET_ERROR (EINVAL); + return -EINVAL; } count -= sizeof_patch; @@ -1532,7 +1532,7 @@ if (free_sample >= MAX_SAMPLE) { printk ("GUS: Sample table full\n"); - return RET_ERROR (ENOSPC); + return -ENOSPC; } /* @@ -1540,14 +1540,14 @@ * been transferred already. */ - COPY_FROM_USER (&((char *) &patch)[offs], addr, offs, sizeof_patch - offs); + memcpy_fromfs ((&((char *) &patch)[offs]), &((addr)[offs]), (sizeof_patch - offs)); instr = patch.instr_no; if (instr < 0 || instr > MAX_PATCH) { printk ("GUS: Invalid patch number %d\n", instr); - return RET_ERROR (EINVAL); + return -EINVAL; } if (count < patch.len) @@ -1560,7 +1560,7 @@ if (patch.len <= 0 || patch.len > gus_mem_size) { printk ("GUS: Invalid sample length %d\n", (int) patch.len); - return RET_ERROR (EINVAL); + return -EINVAL; } if (patch.mode & WAVE_LOOPING) @@ -1568,13 +1568,13 @@ if (patch.loop_start < 0 || patch.loop_start >= patch.len) { printk ("GUS: Invalid loop start\n"); - return RET_ERROR (EINVAL); + return -EINVAL; } if (patch.loop_end < patch.loop_start || patch.loop_end > patch.len) { printk ("GUS: Invalid loop end\n"); - return RET_ERROR (EINVAL); + return -EINVAL; } } @@ -1590,7 +1590,7 @@ if (patch.len >= GUS_BANK_SIZE) { printk ("GUS: Sample (16 bit) too long %d\n", (int) patch.len); - return RET_ERROR (ENOSPC); + return -ENOSPC; } if ((free_mem_ptr / GUS_BANK_SIZE) != @@ -1600,14 +1600,14 @@ ((free_mem_ptr / GUS_BANK_SIZE) + 1) * GUS_BANK_SIZE; if ((tmp_mem + patch.len) > gus_mem_size) - return RET_ERROR (ENOSPC); + return -ENOSPC; free_mem_ptr = tmp_mem; /* This leaves unusable memory */ } } if ((free_mem_ptr + patch.len) > gus_mem_size) - return RET_ERROR (ENOSPC); + return -ENOSPC; sample_ptrs[free_sample] = free_mem_ptr; @@ -1637,7 +1637,8 @@ while (left) /* Not completely transferred yet */ { - blk_size = audio_devs[gus_devnum]->buffsize; + /* blk_size = audio_devs[gus_devnum]->buffsize; */ + blk_size = audio_devs[gus_devnum]->dmap_out->bytes_in_use; if (blk_size > left) blk_size = left; @@ -1661,9 +1662,10 @@ long i; unsigned char data; + for (i = 0; i < blk_size; i++) { - GET_BYTE_FROM_USER (data, addr, sizeof_patch + i); + data = get_fs_byte (&((addr)[sizeof_patch + i])); if (patch.mode & WAVE_UNSIGNED) if (!(patch.mode & WAVE_16_BITS) || (i & 0x01)) @@ -1681,15 +1683,14 @@ * OK, move now. First in and then out. */ - COPY_FROM_USER (audio_devs[gus_devnum]->dmap->raw_buf[0], - addr, sizeof_patch + src_offs, - blk_size); + memcpy_fromfs ((audio_devs[gus_devnum]->dmap_out->raw_buf), &((addr)[sizeof_patch + src_offs]), (blk_size)); - DISABLE_INTR (flags); + save_flags (flags); + cli (); /******** INTERRUPTS DISABLED NOW ********/ gus_write8 (0x41, 0); /* Disable GF1 DMA */ DMAbuf_start_dma (gus_devnum, - audio_devs[gus_devnum]->dmap->raw_buf_phys[0], + audio_devs[gus_devnum]->dmap_out->raw_buf_phys, blk_size, DMA_MODE_WRITE); /* @@ -1698,7 +1699,7 @@ address = target; - if (audio_devs[gus_devnum]->dmachan > 3) + if (audio_devs[gus_devnum]->dmachan1 > 3) { hold_address = address; address = address >> 1; @@ -1717,7 +1718,7 @@ dma_command |= 0x80; /* Invert MSB */ if (patch.mode & WAVE_16_BITS) dma_command |= 0x40; /* 16 bit _DATA_ */ - if (audio_devs[gus_devnum]->dmachan > 3) + if (audio_devs[gus_devnum]->dmachan1 > 3) dma_command |= 0x04; /* 16 bit DMA _channel_ */ gus_write8 (0x41, dma_command); /* Lets bo luteet (=bugs) */ @@ -1727,10 +1728,28 @@ */ active_device = GUS_DEV_WAVE; - DO_SLEEP (dram_sleeper, dram_sleep_flag, HZ); - if (TIMED_OUT (dram_sleeper, dram_sleep_flag)) + + { + unsigned long tl; + + if (HZ) + tl = current->timeout = jiffies + (HZ); + else + tl = 0xffffffff; + dram_sleep_flag.mode = WK_SLEEP; + interruptible_sleep_on (&dram_sleeper); + if (!(dram_sleep_flag.mode & WK_WAKEUP)) + { + if (current->signal & ~current->blocked) + dram_sleep_flag.aborting = 1; + else if (jiffies >= tl) + dram_sleep_flag.mode |= WK_TIMEOUT; + } + dram_sleep_flag.mode &= ~WK_SLEEP; + }; + if ((dram_sleep_flag.mode & WK_TIMEOUT)) printk ("GUS: DMA Transfer timed out\n"); - RESTORE_INTR (flags); + restore_flags (flags); } /* @@ -1773,10 +1792,11 @@ { case _GUS_NUMVOICES: - DISABLE_INTR (flags); + save_flags (flags); + cli (); gus_select_voice (voice); gus_select_max_voices (p1); - RESTORE_INTR (flags); + restore_flags (flags); break; case _GUS_VOICESAMPLE: @@ -1784,18 +1804,20 @@ break; case _GUS_VOICEON: - DISABLE_INTR (flags); + save_flags (flags); + cli (); gus_select_voice (voice); p1 &= ~0x20; /* Don't allow interrupts */ gus_voice_on (p1); - RESTORE_INTR (flags); + restore_flags (flags); break; case _GUS_VOICEOFF: - DISABLE_INTR (flags); + save_flags (flags); + cli (); gus_select_voice (voice); gus_voice_off (); - RESTORE_INTR (flags); + restore_flags (flags); break; case _GUS_VOICEFADE: @@ -1803,32 +1825,36 @@ break; case _GUS_VOICEMODE: - DISABLE_INTR (flags); + save_flags (flags); + cli (); gus_select_voice (voice); p1 &= ~0x20; /* Don't allow interrupts */ gus_voice_mode (p1); - RESTORE_INTR (flags); + restore_flags (flags); break; case _GUS_VOICEBALA: - DISABLE_INTR (flags); + save_flags (flags); + cli (); gus_select_voice (voice); gus_voice_balance (p1); - RESTORE_INTR (flags); + restore_flags (flags); break; case _GUS_VOICEFREQ: - DISABLE_INTR (flags); + save_flags (flags); + cli (); gus_select_voice (voice); gus_voice_freq (plong); - RESTORE_INTR (flags); + restore_flags (flags); break; case _GUS_VOICEVOL: - DISABLE_INTR (flags); + save_flags (flags); + cli (); gus_select_voice (voice); gus_voice_volume (p1); - RESTORE_INTR (flags); + restore_flags (flags); break; case _GUS_VOICEVOL2: /* Just update the software voice level */ @@ -1839,48 +1865,53 @@ case _GUS_RAMPRANGE: if (voices[voice].mode & WAVE_ENVELOPES) break; /* NO-NO */ - DISABLE_INTR (flags); + save_flags (flags); + cli (); gus_select_voice (voice); gus_ramp_range (p1, p2); - RESTORE_INTR (flags); + restore_flags (flags); break; case _GUS_RAMPRATE: if (voices[voice].mode & WAVE_ENVELOPES) break; /* NJET-NJET */ - DISABLE_INTR (flags); + save_flags (flags); + cli (); gus_select_voice (voice); gus_ramp_rate (p1, p2); - RESTORE_INTR (flags); + restore_flags (flags); break; case _GUS_RAMPMODE: if (voices[voice].mode & WAVE_ENVELOPES) break; /* NO-NO */ - DISABLE_INTR (flags); + save_flags (flags); + cli (); gus_select_voice (voice); p1 &= ~0x20; /* Don't allow interrupts */ gus_ramp_mode (p1); - RESTORE_INTR (flags); + restore_flags (flags); break; case _GUS_RAMPON: if (voices[voice].mode & WAVE_ENVELOPES) break; /* EI-EI */ - DISABLE_INTR (flags); + save_flags (flags); + cli (); gus_select_voice (voice); p1 &= ~0x20; /* Don't allow interrupts */ gus_rampon (p1); - RESTORE_INTR (flags); + restore_flags (flags); break; case _GUS_RAMPOFF: if (voices[voice].mode & WAVE_ENVELOPES) break; /* NEJ-NEJ */ - DISABLE_INTR (flags); + save_flags (flags); + cli (); gus_select_voice (voice); gus_rampoff (); - RESTORE_INTR (flags); + restore_flags (flags); break; case _GUS_VOLUME_SCALE: @@ -1889,10 +1920,11 @@ break; case _GUS_VOICE_POS: - DISABLE_INTR (flags); + save_flags (flags); + cli (); gus_select_voice (voice); gus_set_voice_pos (voice, plong); - RESTORE_INTR (flags); + restore_flags (flags); break; default:; @@ -1946,66 +1978,69 @@ if (bits != 8 && bits != 16) bits = 8; + if (only_8_bits) + bits = 8; + gus_sampling_bits = bits; return bits; } static int -gus_sampling_ioctl (int dev, unsigned int cmd, unsigned int arg, int local) +gus_sampling_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local) { switch (cmd) { case SOUND_PCM_WRITE_RATE: if (local) - return gus_sampling_set_speed (arg); - return IOCTL_OUT (arg, gus_sampling_set_speed (IOCTL_IN (arg))); + return gus_sampling_set_speed ((int) arg); + return snd_ioctl_return ((int *) arg, gus_sampling_set_speed (get_fs_long ((long *) arg))); break; case SOUND_PCM_READ_RATE: if (local) return gus_sampling_speed; - return IOCTL_OUT (arg, gus_sampling_speed); + return snd_ioctl_return ((int *) arg, gus_sampling_speed); break; case SNDCTL_DSP_STEREO: if (local) - return gus_sampling_set_channels (arg + 1) - 1; - return IOCTL_OUT (arg, gus_sampling_set_channels (IOCTL_IN (arg) + 1) - 1); + return gus_sampling_set_channels ((int) arg + 1) - 1; + return snd_ioctl_return ((int *) arg, gus_sampling_set_channels (get_fs_long ((long *) arg) + 1) - 1); break; case SOUND_PCM_WRITE_CHANNELS: if (local) - return gus_sampling_set_channels (arg); - return IOCTL_OUT (arg, gus_sampling_set_channels (IOCTL_IN (arg))); + return gus_sampling_set_channels ((int) arg); + return snd_ioctl_return ((int *) arg, gus_sampling_set_channels (get_fs_long ((long *) arg))); break; case SOUND_PCM_READ_CHANNELS: if (local) return gus_sampling_channels; - return IOCTL_OUT (arg, gus_sampling_channels); + return snd_ioctl_return ((int *) arg, gus_sampling_channels); break; case SNDCTL_DSP_SETFMT: if (local) - return gus_sampling_set_bits (arg); - return IOCTL_OUT (arg, gus_sampling_set_bits (IOCTL_IN (arg))); + return gus_sampling_set_bits ((int) arg); + return snd_ioctl_return ((int *) arg, gus_sampling_set_bits (get_fs_long ((long *) arg))); break; case SOUND_PCM_READ_BITS: if (local) return gus_sampling_bits; - return IOCTL_OUT (arg, gus_sampling_bits); + return snd_ioctl_return ((int *) arg, gus_sampling_bits); case SOUND_PCM_WRITE_FILTER: /* NOT POSSIBLE */ - return IOCTL_OUT (arg, RET_ERROR (EINVAL)); + return snd_ioctl_return ((int *) arg, -EINVAL); break; case SOUND_PCM_READ_FILTER: - return IOCTL_OUT (arg, RET_ERROR (EINVAL)); + return snd_ioctl_return ((int *) arg, -EINVAL); break; } - return RET_ERROR (EINVAL); + return -EINVAL; } static void @@ -2021,14 +2056,8 @@ static int gus_sampling_open (int dev, int mode) { - if (mode & OPEN_READ && dual_dma_mode) - { - printk ("GUS: The 8 bit input device is disabled. Use GUS MAX\n"); - return RET_ERROR (ENOTTY); - } - if (gus_busy) - return RET_ERROR (EBUSY); + return -EBUSY; gus_initialize (); @@ -2048,6 +2077,11 @@ set_input_volumes (); } only_read_access = !(mode & OPEN_WRITE); + only_8_bits = mode & OPEN_READ; + if (only_8_bits) + audio_devs[dev]->format_mask = AFMT_U8; + else + audio_devs[dev]->format_mask = AFMT_U8 | AFMT_S16_LE; return 0; } @@ -2078,12 +2112,13 @@ if (pcm_active && pcm_opened) for (voice = 0; voice < gus_sampling_channels; voice++) { - DISABLE_INTR (flags); + save_flags (flags); + cli (); gus_select_voice (voice); gus_rampoff (); gus_voice_volume (1530 + (25 * gus_pcm_volume)); gus_ramp_range (65, 1530 + (25 * gus_pcm_volume)); - RESTORE_INTR (flags); + restore_flags (flags); } } @@ -2134,7 +2169,8 @@ ramp_mode[chn] = 0x04; /* Enable rollover bit */ } - DISABLE_INTR (flags); + save_flags (flags); + cli (); gus_select_voice (chn); gus_voice_freq (speed); @@ -2193,16 +2229,17 @@ } } - RESTORE_INTR (flags); + restore_flags (flags); } for (chn = 0; chn < gus_sampling_channels; chn++) { - DISABLE_INTR (flags); + save_flags (flags); + cli (); gus_select_voice (chn); gus_write8 (0x0d, ramp_mode[chn]); gus_voice_on (mode[chn]); - RESTORE_INTR (flags); + restore_flags (flags); } pcm_active = 1; @@ -2226,7 +2263,8 @@ unsigned char dma_command; unsigned long address, hold_address; - DISABLE_INTR (flags); + save_flags (flags); + cli (); count = total_count / gus_sampling_channels; @@ -2249,7 +2287,7 @@ address = this_one * pcm_bsize; address += chn * pcm_banksize; - if (audio_devs[dev]->dmachan > 3) + if (audio_devs[dev]->dmachan1 > 3) { hold_address = address; address = address >> 1; @@ -2266,7 +2304,7 @@ else dma_command |= 0x80; /* Invert MSB */ - if (audio_devs[dev]->dmachan > 3) + if (audio_devs[dev]->dmachan1 > 3) dma_command |= 0x04; /* 16 bit DMA channel */ gus_write8 (0x41, dma_command); /* Kickstart */ @@ -2292,7 +2330,7 @@ active_device = GUS_DEV_PCM_CONTINUE; } - RESTORE_INTR (flags); + restore_flags (flags); } static void @@ -2313,13 +2351,14 @@ unsigned long flags; unsigned char mode; - DISABLE_INTR (flags); + save_flags (flags); + cli (); DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ); mode = 0xa0; /* DMA IRQ enabled, invert MSB */ - if (audio_devs[dev]->dmachan > 3) + if (audio_devs[dev]->dmachan2 > 3) mode |= 0x04; /* 16 bit DMA channel */ if (gus_sampling_channels > 1) mode |= 0x02; /* Stereo */ @@ -2327,7 +2366,7 @@ gus_write8 (0x49, mode); - RESTORE_INTR (flags); + restore_flags (flags); } static int @@ -2342,7 +2381,7 @@ if (gus_sampling_bits != 8) { printk ("GUS Error: 16 bit recording not supported\n"); - return RET_ERROR (EINVAL); + return -EINVAL; } return 0; @@ -2387,11 +2426,11 @@ static void gus_copy_from_user (int dev, char *localbuf, int localoffs, - snd_rw_buf * userbuf, int useroffs, int len) + const snd_rw_buf * userbuf, int useroffs, int len) { if (gus_sampling_channels == 1) { - COPY_FROM_USER (&localbuf[localoffs], userbuf, useroffs, len); + memcpy_fromfs ((&localbuf[localoffs]), &((userbuf)[useroffs]), (len)); } else if (gus_sampling_bits == 8) { @@ -2407,9 +2446,9 @@ for (i = 0; i < len; i++) { - GET_BYTE_FROM_USER (*out_left++, userbuf, in_left); + *out_left++ = get_fs_byte (&((userbuf)[in_left])); in_left += 2; - GET_BYTE_FROM_USER (*out_right++, userbuf, in_right); + *out_right++ = get_fs_byte (&((userbuf)[in_right])); in_right += 2; } } @@ -2428,9 +2467,9 @@ for (i = 0; i < len; i++) { - GET_SHORT_FROM_USER (*out_left++, (short *) userbuf, in_left); + *out_left++ = get_fs_word (&(((short *) userbuf)[in_left])); in_left += 2; - GET_SHORT_FROM_USER (*out_right++, (short *) userbuf, in_right); + *out_right++ = get_fs_word (&(((short *) userbuf)[in_right])); in_right += 2; } } @@ -2479,14 +2518,15 @@ unsigned long flags; voices[voice].bender = value - 8192; - freq = compute_finetune (voices[voice].orig_freq, value, + freq = compute_finetune (voices[voice].orig_freq, value - 8192, voices[voice].bender_range); voices[voice].current_freq = freq; - DISABLE_INTR (flags); + save_flags (flags); + cli (); gus_select_voice (voice); gus_voice_freq (freq); - RESTORE_INTR (flags); + restore_flags (flags); } static int @@ -2546,7 +2586,7 @@ struct patch_info *pat; if (ptr < 0 || ptr >= free_sample) - return RET_ERROR (EINVAL); + return -EINVAL; memcpy (rec->data.data8, (char *) &samples[ptr], sizeof (struct patch_info)); @@ -2566,12 +2606,12 @@ struct patch_info *pat; if (ptr < 0 || ptr >= free_sample) - return RET_ERROR (EINVAL); + return -EINVAL; pat = (struct patch_info *) rec->data.data8; if (pat->len > samples[ptr].len) /* Cannot expand sample */ - return RET_ERROR (EINVAL); + return -EINVAL; pat->key = samples[ptr].key; /* Ensure the link is correct */ @@ -2591,10 +2631,10 @@ int l = rec->parm3; if (sample < 0 || sample >= free_sample) - return RET_ERROR (EINVAL); + return -EINVAL; if (offs < 0 || offs >= samples[sample].len) - return RET_ERROR (EINVAL); /* Invalid offset */ + return -EINVAL; /* Invalid offset */ n = samples[sample].len - offs; /* Num of bytes left */ @@ -2605,9 +2645,9 @@ l = sizeof (rec->data.data8); if (l <= 0) - return RET_ERROR (EINVAL); /* - * Was there a bug? - */ + return -EINVAL; /* + * Was there a bug? + */ offs += sample_ptrs[sample]; /* * Begin offsess + offset to DRAM @@ -2632,12 +2672,12 @@ int l = rec->parm3; if (sample < 0 || sample >= free_sample) - return RET_ERROR (EINVAL); + return -EINVAL; if (offs < 0 || offs >= samples[sample].len) - return RET_ERROR (EINVAL); /* - * Invalid offset - */ + return -EINVAL; /* + * Invalid offset + */ n = samples[sample].len - offs; /* * Nr of bytes left @@ -2650,9 +2690,9 @@ l = sizeof (rec->data.data8); if (l <= 0) - return RET_ERROR (EINVAL); /* - * Was there a bug? - */ + return -EINVAL; /* + * Was there a bug? + */ offs += sample_ptrs[sample]; /* * Begin offsess + offset to DRAM @@ -2668,7 +2708,7 @@ break; default: - return RET_ERROR (EINVAL); + return -EINVAL; } } @@ -2752,7 +2792,8 @@ if (have_gus_max) /* Don't disturb GUS MAX */ return; - DISABLE_INTR (flags); + save_flags (flags); + cli (); /* * Enable channels having vol > 10% @@ -2777,13 +2818,13 @@ mix_image &= ~0x07; mix_image |= mask & 0x07; - OUTB (mix_image, u_Mixer); + outb (mix_image, u_Mixer); - RESTORE_INTR (flags); + restore_flags (flags); } int -gus_default_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg) +gus_default_mixer_ioctl (int dev, unsigned int cmd, ioctl_arg arg) { #define MIX_DEVS (SOUND_MASK_MIC|SOUND_MASK_LINE| \ SOUND_MASK_SYNTH|SOUND_MASK_PCM) @@ -2793,16 +2834,16 @@ switch (cmd & 0xff) { case SOUND_MIXER_RECSRC: - gus_recmask = IOCTL_IN (arg) & MIX_DEVS; + gus_recmask = get_fs_long ((long *) arg) & MIX_DEVS; if (!(gus_recmask & (SOUND_MASK_MIC | SOUND_MASK_LINE))) gus_recmask = SOUND_MASK_MIC; /* Note! Input volumes are updated during next open for recording */ - return IOCTL_OUT (arg, gus_recmask); + return snd_ioctl_return ((int *) arg, gus_recmask); break; case SOUND_MIXER_MIC: { - int vol = IOCTL_IN (arg) & 0xff; + int vol = get_fs_long ((long *) arg) & 0xff; if (vol < 0) vol = 0; @@ -2810,13 +2851,13 @@ vol = 100; gus_mic_vol = vol; set_input_volumes (); - return IOCTL_OUT (arg, vol | (vol << 8)); + return snd_ioctl_return ((int *) arg, vol | (vol << 8)); } break; case SOUND_MIXER_LINE: { - int vol = IOCTL_IN (arg) & 0xff; + int vol = get_fs_long ((long *) arg) & 0xff; if (vol < 0) vol = 0; @@ -2824,25 +2865,25 @@ vol = 100; gus_line_vol = vol; set_input_volumes (); - return IOCTL_OUT (arg, vol | (vol << 8)); + return snd_ioctl_return ((int *) arg, vol | (vol << 8)); } break; case SOUND_MIXER_PCM: - gus_pcm_volume = IOCTL_IN (arg) & 0xff; + gus_pcm_volume = get_fs_long ((long *) arg) & 0xff; if (gus_pcm_volume < 0) gus_pcm_volume = 0; if (gus_pcm_volume > 100) gus_pcm_volume = 100; gus_sampling_update_volume (); - return IOCTL_OUT (arg, gus_pcm_volume | (gus_pcm_volume << 8)); + return snd_ioctl_return ((int *) arg, gus_pcm_volume | (gus_pcm_volume << 8)); break; case SOUND_MIXER_SYNTH: { int voice; - gus_wave_volume = IOCTL_IN (arg) & 0xff; + gus_wave_volume = get_fs_long ((long *) arg) & 0xff; if (gus_wave_volume < 0) gus_wave_volume = 0; @@ -2853,12 +2894,12 @@ for (voice = 0; voice < nr_voices; voice++) dynamic_volume_change (voice); /* Apply the new vol */ - return IOCTL_OUT (arg, gus_wave_volume | (gus_wave_volume << 8)); + return snd_ioctl_return ((int *) arg, gus_wave_volume | (gus_wave_volume << 8)); } break; default: - return RET_ERROR (EINVAL); + return -EINVAL; } else switch (cmd & 0xff) /* @@ -2867,47 +2908,47 @@ { case SOUND_MIXER_RECSRC: - return IOCTL_OUT (arg, gus_recmask); + return snd_ioctl_return ((int *) arg, gus_recmask); break; case SOUND_MIXER_DEVMASK: - return IOCTL_OUT (arg, MIX_DEVS); + return snd_ioctl_return ((int *) arg, MIX_DEVS); break; case SOUND_MIXER_STEREODEVS: - return IOCTL_OUT (arg, 0); + return snd_ioctl_return ((int *) arg, 0); break; case SOUND_MIXER_RECMASK: - return IOCTL_OUT (arg, SOUND_MASK_MIC | SOUND_MASK_LINE); + return snd_ioctl_return ((int *) arg, SOUND_MASK_MIC | SOUND_MASK_LINE); break; case SOUND_MIXER_CAPS: - return IOCTL_OUT (arg, 0); + return snd_ioctl_return ((int *) arg, 0); break; case SOUND_MIXER_MIC: - return IOCTL_OUT (arg, gus_mic_vol | (gus_mic_vol << 8)); + return snd_ioctl_return ((int *) arg, gus_mic_vol | (gus_mic_vol << 8)); break; case SOUND_MIXER_LINE: - return IOCTL_OUT (arg, gus_line_vol | (gus_line_vol << 8)); + return snd_ioctl_return ((int *) arg, gus_line_vol | (gus_line_vol << 8)); break; case SOUND_MIXER_PCM: - return IOCTL_OUT (arg, gus_pcm_volume | (gus_pcm_volume << 8)); + return snd_ioctl_return ((int *) arg, gus_pcm_volume | (gus_pcm_volume << 8)); break; case SOUND_MIXER_SYNTH: - return IOCTL_OUT (arg, gus_wave_volume | (gus_wave_volume << 8)); + return snd_ioctl_return ((int *) arg, gus_wave_volume | (gus_wave_volume << 8)); break; default: - return RET_ERROR (EINVAL); + return -EINVAL; } } else - return RET_ERROR (EINVAL); + return -EINVAL; } static struct mixer_operations gus_mixer_operations = @@ -2933,19 +2974,20 @@ */ mix_image &= ~0x07; mix_image |= 0x04; /* All channels enabled */ - OUTB (mix_image, u_Mixer); + outb (mix_image, u_Mixer); } return mem_start; } long -gus_wave_init (long mem_start, int irq, int dma) +gus_wave_init (long mem_start, struct address_info *hw_config) { unsigned long flags; unsigned char val; char *model_num = "2.4"; int gus_type = 0x24; /* 2.4 */ - int mixer_type = 0; + + int irq = hw_config->irq, dma = hw_config->dma, dma2 = hw_config->dma2; if (irq < 0 || irq > 15) { @@ -2961,13 +3003,10 @@ gus_irq = irq; gus_dma = dma; -#ifdef GUSMAX_DMA - if (gusmax_dma == -1) /* Not already set */ - gusmax_dma = GUSMAX_DMA; -#else - if (gusmax_dma == -1) - gusmax_dma = dma; -#endif + gus_dma2 = dma2; + + if (gus_dma2 == -1) + gus_dma2 = dma; /* * Try to identify the GUS model. @@ -2975,10 +3014,11 @@ * Versions < 3.6 don't have the digital ASIC. Try to probe it first. */ - DISABLE_INTR (flags); - OUTB (0x20, gus_base + 0x0f); - val = INB (gus_base + 0x0f); - RESTORE_INTR (flags); + save_flags (flags); + cli (); + outb (0x20, gus_base + 0x0f); + val = inb (gus_base + 0x0f); + restore_flags (flags); if (val != 0xff && (val & 0x06)) /* Should be 0x02?? */ { @@ -2987,7 +3027,7 @@ * Next try to detect the true model. */ - val = INB (u_MixSelect); + val = inb (u_MixSelect); /* * Value 255 means pre-3.7 which don't have mixer. @@ -3006,6 +3046,7 @@ model_num = "3.7"; gus_type = 0x37; mixer_type = ICS2101; + request_region (u_MixSelect, 1, "GUS mixer"); } else { @@ -3016,26 +3057,32 @@ { unsigned char max_config = 0x40; /* Codec enable */ + if (gus_dma2 == -1) + gus_dma2 = gus_dma; + if (gus_dma > 3) max_config |= 0x10; /* 16 bit capture DMA */ - if (gusmax_dma > 3) + if (gus_dma2 > 3) max_config |= 0x20; /* 16 bit playback DMA */ max_config |= (gus_base >> 4) & 0x0f; /* Extract the X from 2X0 */ - OUTB (max_config, gus_base + 0x106); /* UltraMax control */ + outb (max_config, gus_base + 0x106); /* UltraMax control */ } - if (ad1848_detect (gus_base + 0x10c)) + if (ad1848_detect (gus_base + 0x10c, NULL, hw_config->osp)) { + gus_mic_vol = gus_line_vol = gus_pcm_volume = 100; gus_wave_volume = 90; have_gus_max = 1; ad1848_init ("GUS MAX", gus_base + 0x10c, -irq, - gusmax_dma, /* Playback DMA */ - gus_dma); /* Capture DMA */ + gus_dma2, /* Playback DMA */ + gus_dma, /* Capture DMA */ + 1, /* Share DMA channels with GF1 */ + hw_config->osp); } else printk ("[Where's the CS4231?]"); @@ -3063,10 +3110,20 @@ { voice_alloc = &guswave_operations.alloc; synth_devs[num_synths++] = &guswave_operations; +#ifndef EXCLUDE_SEQUENCER + gus_tmr_install (gus_base + 8); +#endif } - PERMANENT_MALLOC (struct patch_info *, samples, - (MAX_SAMPLE + 1) * sizeof (*samples), mem_start); + + { + caddr_t ptr; + + ptr = sound_mem_blocks[sound_num_blocks] = kmalloc ((MAX_SAMPLE + 1) * sizeof (*samples), GFP_KERNEL); + if (sound_num_blocks < 1024) + sound_num_blocks++; + samples = (struct patch_info *) ptr; + }; reset_sample_memory (); @@ -3075,9 +3132,11 @@ if (num_audiodevs < MAX_AUDIO_DEV) { audio_devs[gus_devnum = num_audiodevs++] = &gus_sampling_operations; - audio_devs[gus_devnum]->dmachan = dma; - audio_devs[gus_devnum]->buffcount = 1; + audio_devs[gus_devnum]->dmachan1 = dma; + audio_devs[gus_devnum]->dmachan2 = dma2; audio_devs[gus_devnum]->buffsize = DSP_BUFFSIZE; + if (dma2 != dma && dma2 != -1) + audio_devs[gus_devnum]->flags |= DMA_DUPLEX; } else printk ("GUS: Too many PCM devices available\n"); @@ -3091,6 +3150,7 @@ case ICS2101: gus_mic_vol = gus_line_vol = gus_pcm_volume = 100; gus_wave_volume = 90; + request_region (u_MixSelect, 1, "GUS mixer"); return ics2101_mixer_init (mem_start); case CS4231: @@ -3100,6 +3160,26 @@ } } +void +gus_wave_unload (void) +{ +#ifndef EXCLUDE_GUSMAX + if (have_gus_max) + { + ad1848_unload (gus_base + 0x10c, + -gus_irq, + gus_dma2, /* Playback DMA */ + gus_dma, /* Capture DMA */ + 1); /* Share DMA channels with GF1 */ + } +#endif + + if (mixer_type == ICS2101) + { + release_region (u_MixSelect, 1); + } +} + static void do_loop_irq (int voice) { @@ -3107,7 +3187,8 @@ int mode, parm; unsigned long flags; - DISABLE_INTR (flags); + save_flags (flags); + cli (); gus_select_voice (voice); tmp = gus_read8 (0x00); @@ -3192,7 +3273,7 @@ default:; } - RESTORE_INTR (flags); + restore_flags (flags); } static void @@ -3202,7 +3283,8 @@ int mode, parm; unsigned long flags; - DISABLE_INTR (flags); + save_flags (flags); + cli (); gus_select_voice (voice); @@ -3221,18 +3303,18 @@ case VMODE_HALT: /* * Decay phase finished */ - RESTORE_INTR (flags); + restore_flags (flags); gus_voice_init (voice); break; case VMODE_ENVELOPE: gus_rampoff (); - RESTORE_INTR (flags); + restore_flags (flags); step_envelope (voice); break; case VMODE_START_NOTE: - RESTORE_INTR (flags); + restore_flags (flags); guswave_start_note2 (voices[voice].dev_pending, voice, voices[voice].note_pending, voices[voice].volume_pending); if (voices[voice].kill_pending) @@ -3310,8 +3392,11 @@ switch (active_device) { case GUS_DEV_WAVE: - if (SOMEONE_WAITING (dram_sleeper, dram_sleep_flag)) - WAKE_UP (dram_sleeper, dram_sleep_flag); + if ((dram_sleep_flag.mode & WK_SLEEP)) + { + dram_sleep_flag.mode = WK_WAKEUP; + wake_up (&dram_sleeper); + }; break; case GUS_DEV_PCM_CONTINUE: /* Left channel data transferred */ @@ -3346,5 +3431,109 @@ } } + +#ifndef EXCLUDE_SEQUENCER +/* + * Timer stuff + */ + +static volatile int select_addr, data_addr; +static volatile int curr_timer = 0; + +void +gus_timer_command (unsigned int addr, unsigned int val) +{ + int i; + + outb ((unsigned char) (addr & 0xff), select_addr); + + for (i = 0; i < 2; i++) + inb (select_addr); + + outb ((unsigned char) (val & 0xff), data_addr); + + for (i = 0; i < 2; i++) + inb (select_addr); +} + +static void +arm_timer (int timer, unsigned int interval) +{ + + curr_timer = timer; + + if (timer == 1) + { + gus_write8 (0x46, 256 - interval); /* Set counter for timer 1 */ + gus_write8 (0x45, 0x04); /* Enable timer 1 IRQ */ + gus_timer_command (0x04, 0x01); /* Start timer 1 */ + } + else + { + gus_write8 (0x47, 256 - interval); /* Set counter for timer 2 */ + gus_write8 (0x45, 0x08); /* Enable timer 2 IRQ */ + gus_timer_command (0x04, 0x02); /* Start timer 2 */ + } + + gus_timer_enabled = 0; +} + +static unsigned int +gus_tmr_start (int dev, unsigned int usecs_per_tick) +{ + int timer_no, resolution; + int divisor; + + if (usecs_per_tick > (256 * 80)) + { + timer_no = 2; + resolution = 320; /* usec */ + } + else + { + timer_no = 1; + resolution = 80; /* usec */ + } + + divisor = (usecs_per_tick + (resolution / 2)) / resolution; + + arm_timer (timer_no, divisor); + + return divisor * resolution; +} + +static void +gus_tmr_disable (int dev) +{ + gus_write8 (0x45, 0); /* Disable both timers */ + gus_timer_enabled = 0; +} + +static void +gus_tmr_restart (int dev) +{ + if (curr_timer == 1) + gus_write8 (0x45, 0x04); /* Start timer 1 again */ + else + gus_write8 (0x45, 0x08); /* Start timer 2 again */ +} + +static struct sound_lowlev_timer gus_tmr = +{ + 0, + gus_tmr_start, + gus_tmr_disable, + gus_tmr_restart +}; + +static void +gus_tmr_install (int io_base) +{ + select_addr = io_base; + data_addr = io_base + 1; + + sound_timer_init (&gus_tmr, "GUS"); +} +#endif #endif diff -u --recursive --new-file v1.3.33/linux/drivers/sound/ics2101.c linux/drivers/sound/ics2101.c --- v1.3.33/linux/drivers/sound/ics2101.c Tue Jul 18 16:28:58 1995 +++ linux/drivers/sound/ics2101.c Wed Oct 11 07:55:40 1995 @@ -47,7 +47,6 @@ static int scale_vol (int vol) { -#if 1 /* * Experimental volume scaling by Risto Kankkunen. * This should give smoother volume response than just @@ -72,9 +71,6 @@ e += 7; } return ((e << 4) + vol); -#else - return ((vol * 127) + 50) / 100; -#endif } static void @@ -100,12 +96,13 @@ attn_addr |= 0x03; } - DISABLE_INTR (flags); - OUTB (ctrl_addr, u_MixSelect); - OUTB (selector[dev], u_MixData); - OUTB (attn_addr, u_MixSelect); - OUTB ((unsigned char) vol, u_MixData); - RESTORE_INTR (flags); + save_flags (flags); + cli (); + outb (ctrl_addr, u_MixSelect); + outb (selector[dev], u_MixData); + outb (attn_addr, u_MixSelect); + outb ((unsigned char) vol, u_MixData); + restore_flags (flags); } static int @@ -132,7 +129,7 @@ } static int -ics2101_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg) +ics2101_mixer_ioctl (int dev, unsigned int cmd, ioctl_arg arg) { if (((cmd >> 8) & 0xff) == 'M') { @@ -144,27 +141,27 @@ break; case SOUND_MIXER_MIC: - return IOCTL_OUT (arg, set_volumes (DEV_MIC, IOCTL_IN (arg))); + return snd_ioctl_return ((int *) arg, set_volumes (DEV_MIC, get_fs_long ((long *) arg))); break; case SOUND_MIXER_CD: - return IOCTL_OUT (arg, set_volumes (DEV_CD, IOCTL_IN (arg))); + return snd_ioctl_return ((int *) arg, set_volumes (DEV_CD, get_fs_long ((long *) arg))); break; case SOUND_MIXER_LINE: - return IOCTL_OUT (arg, set_volumes (DEV_LINE, IOCTL_IN (arg))); + return snd_ioctl_return ((int *) arg, set_volumes (DEV_LINE, get_fs_long ((long *) arg))); break; case SOUND_MIXER_SYNTH: - return IOCTL_OUT (arg, set_volumes (DEV_GF1, IOCTL_IN (arg))); + return snd_ioctl_return ((int *) arg, set_volumes (DEV_GF1, get_fs_long ((long *) arg))); break; case SOUND_MIXER_VOLUME: - return IOCTL_OUT (arg, set_volumes (DEV_VOL, IOCTL_IN (arg))); + return snd_ioctl_return ((int *) arg, set_volumes (DEV_VOL, get_fs_long ((long *) arg))); break; default: - return RET_ERROR (EINVAL); + return -EINVAL; } else switch (cmd & 0xff) /* @@ -177,49 +174,47 @@ break; case SOUND_MIXER_DEVMASK: - return IOCTL_OUT (arg, MIX_DEVS); + return snd_ioctl_return ((int *) arg, MIX_DEVS); break; case SOUND_MIXER_STEREODEVS: - return IOCTL_OUT (arg, SOUND_MASK_LINE | SOUND_MASK_CD | - SOUND_MASK_SYNTH | SOUND_MASK_VOLUME | - SOUND_MASK_MIC); + return snd_ioctl_return ((int *) arg, SOUND_MASK_LINE | SOUND_MASK_CD | SOUND_MASK_SYNTH | SOUND_MASK_VOLUME | SOUND_MASK_MIC); break; case SOUND_MIXER_RECMASK: - return IOCTL_OUT (arg, SOUND_MASK_MIC | SOUND_MASK_LINE); + return snd_ioctl_return ((int *) arg, SOUND_MASK_MIC | SOUND_MASK_LINE); break; case SOUND_MIXER_CAPS: - return IOCTL_OUT (arg, 0); + return snd_ioctl_return ((int *) arg, 0); break; case SOUND_MIXER_MIC: - return IOCTL_OUT (arg, volumes[DEV_MIC]); + return snd_ioctl_return ((int *) arg, volumes[DEV_MIC]); break; case SOUND_MIXER_LINE: - return IOCTL_OUT (arg, volumes[DEV_LINE]); + return snd_ioctl_return ((int *) arg, volumes[DEV_LINE]); break; case SOUND_MIXER_CD: - return IOCTL_OUT (arg, volumes[DEV_CD]); + return snd_ioctl_return ((int *) arg, volumes[DEV_CD]); break; case SOUND_MIXER_VOLUME: - return IOCTL_OUT (arg, volumes[DEV_VOL]); + return snd_ioctl_return ((int *) arg, volumes[DEV_VOL]); break; case SOUND_MIXER_SYNTH: - return IOCTL_OUT (arg, volumes[DEV_GF1]); + return snd_ioctl_return ((int *) arg, volumes[DEV_GF1]); break; default: - return RET_ERROR (EINVAL); + return -EINVAL; } } - return RET_ERROR (EINVAL); + return -EINVAL; } static struct mixer_operations ics2101_mixer_operations = @@ -242,7 +237,7 @@ * the flipping feature if the model id is other than 5. */ - if (INB (u_MixSelect) != 5) + if (inb (u_MixSelect) != 5) { for (i = 0; i < ICS_MIXDEVS; i++) left_fix[i] = 1; diff -u --recursive --new-file v1.3.33/linux/drivers/sound/mad16.c linux/drivers/sound/mad16.c --- v1.3.33/linux/drivers/sound/mad16.c Sun Aug 13 14:45:33 1995 +++ linux/drivers/sound/mad16.c Wed Oct 11 07:55:40 1995 @@ -1,4 +1,3 @@ -#define MAD16_OPL4 /* Disable this if you have problems with OPL3 */ /* * sound/mad16.c * @@ -101,6 +100,8 @@ static int board_type = C928; +static sound_os_info *mad16_osp; + #ifndef DDB #define DDB(x) #endif @@ -111,22 +112,23 @@ unsigned long flags; unsigned char tmp; - DISABLE_INTR (flags); + save_flags (flags); + cli (); switch (board_type) /* Output password */ { case C928: case MOZART: - OUTB (0xE2, PASSWD_REG); + outb (0xE2, PASSWD_REG); break; case C929: - OUTB (0xE3, PASSWD_REG); + outb (0xE3, PASSWD_REG); break; } - tmp = INB (port); - RESTORE_INTR (flags); + tmp = inb (port); + restore_flags (flags); return tmp; } @@ -136,22 +138,23 @@ { unsigned long flags; - DISABLE_INTR (flags); + save_flags (flags); + cli (); switch (board_type) /* Output password */ { case C928: case MOZART: - OUTB (0xE2, PASSWD_REG); + outb (0xE2, PASSWD_REG); break; case C929: - OUTB (0xE3, PASSWD_REG); + outb (0xE3, PASSWD_REG); break; } - OUTB ((unsigned char) (value & 0xff), port); - RESTORE_INTR (flags); + outb ((unsigned char) (value & 0xff), port); + restore_flags (flags); } static int @@ -175,7 +178,7 @@ * the password. (This is how a MAD16 compatible card works). */ - if ((tmp2 = INB (MC1_PORT)) == tmp) /* It didn't close */ + if ((tmp2 = inb (MC1_PORT)) == tmp) /* It didn't close */ { DDB (printk ("MC1_PORT didn't close after read (0x%02x)\n", tmp2)); return 0; @@ -202,10 +205,14 @@ static int valid_ports[] = {0x530, 0xe80, 0xf40, 0x604}; unsigned char tmp; + unsigned char cs4231_mode = 0; + + int ad_flags = 0; if (already_initialized) return 0; + mad16_osp = hw_config->osp; /* * Check that all ports return 0xff (bus float) when no password * is written to the password register. @@ -213,14 +220,6 @@ DDB (printk ("--- Detecting MAD16 / Mozart ---\n")); -#if 0 - for (i = 0xf8d; i <= 0xf93; i++) - if (INB (i) != 0xff) - { - DDB (printk ("port 0x%03x != 0xff (0x%02x)\n", i, INB (i))); - return 0; - } -#endif /* * Then try to detect with the old password @@ -238,7 +237,7 @@ if (!detect_mad16 ()) return 0; - printk ("mad16.c: 82C929 detected???\n"); + DDB (printk ("mad16.c: 82C929 detected\n")); } else { @@ -246,12 +245,12 @@ if (((model = mad_read (MC3_PORT)) & 0x03) == 0x03) { - printk ("mad16.c: Mozart detected???\n"); + DDB (printk ("mad16.c: Mozart detected\n")); board_type = MOZART; } else { - printk ("mad16.c: 82C928 detected???\n"); + DDB (printk ("mad16.c: 82C928 detected???\n")); board_type = C928; } } @@ -283,8 +282,6 @@ /* * Set optional CD-ROM and joystick settings. */ -#define MAD16_CONF 0x06 -#define MAD16_CDSEL 0x03 #ifdef MAD16_CONF tmp |= ((MAD16_CONF) & 0x0f); /* CD-ROM and joystick bits */ @@ -304,36 +301,168 @@ mad_write (MC2_PORT, tmp); mad_write (MC3_PORT, 0xf0); /* Disable SB */ + if (!ad1848_detect (hw_config->io_base + 4, &ad_flags, mad16_osp)) + return 0; + + if (ad_flags & (AD_F_CS4231 | AD_F_CS4248)) + cs4231_mode = 0x02; /* CS4248/CS4231 sync delay switch */ + if (board_type == C929) { mad_write (MC4_PORT, 0xa2); - mad_write (MC5_PORT, 0x95); /* AD184x mode (0x9f for CS42xx) */ + mad_write (MC5_PORT, 0xA5 | cs4231_mode); mad_write (MC6_PORT, 0x03); /* Disable MPU401 */ } else { mad_write (MC4_PORT, 0x02); - mad_write (MC5_PORT, 0x10); /* AD184x mode (0x12 for CS42xx) */ + mad_write (MC5_PORT, 0x30 | cs4231_mode); } for (i = 0xf8d; i <= 0xf93; i++) DDB (printk ("port %03x after init = %03x\n", i, mad_read (i))); - return probe_ms_sound (hw_config); +/* + * Verify the WSS parameters + */ + + if (check_region (hw_config->io_base, 8)) + { + printk ("MSS: I/O port conflict\n"); + return 0; + } + + /* + * Check if the IO port returns valid signature. The original MS Sound + * system returns 0x04 while some cards (AudioTriX Pro for example) + * return 0x00. + */ + + if ((inb (hw_config->io_base + 3) & 0x3f) != 0x04 && + (inb (hw_config->io_base + 3) & 0x3f) != 0x00) + { + DDB (printk ("No MSS signature detected on port 0x%x (0x%x)\n", + hw_config->io_base, inb (hw_config->io_base + 3))); + return 0; + } + + if (hw_config->irq > 11) + { + printk ("MSS: Bad IRQ %d\n", hw_config->irq); + return 0; + } + + if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3) + { + printk ("MSS: Bad DMA %d\n", hw_config->dma); + return 0; + } + + /* + * Check that DMA0 is not in use with a 8 bit board. + */ + + if (hw_config->dma == 0 && inb (hw_config->io_base + 3) & 0x80) + { + printk ("MSS: Can't use DMA0 with a 8 bit card/slot\n"); + return 0; + } + + if (hw_config->irq > 7 && hw_config->irq != 9 && inb (hw_config->io_base + 3) & 0x80) + { + printk ("MSS: Can't use IRQ%d with a 8 bit card/slot\n", hw_config->irq); + return 0; + } + + return 1; } long attach_mad16 (long mem_start, struct address_info *hw_config) { + static char interrupt_bits[12] = + { + -1, -1, -1, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20 + }; + char bits; + + static char dma_bits[4] = + { + 1, 2, 0, 3 + }; + + int config_port = hw_config->io_base + 0, version_port = hw_config->io_base + 3; + int ad_flags = 0, dma = hw_config->dma, dma2 = hw_config->dma2; + unsigned char dma2_bit = 0; + already_initialized = 1; - return attach_ms_sound (mem_start, hw_config); + if (!ad1848_detect (hw_config->io_base + 4, &ad_flags, mad16_osp)) + return mem_start; + + /* + * Set the IRQ and DMA addresses. + */ + + bits = interrupt_bits[hw_config->irq]; + if (bits == -1) + return mem_start; + + outb (bits | 0x40, config_port); + if ((inb (version_port) & 0x40) == 0) + printk ("[IRQ Conflict?]"); + +/* + * Handle the capture DMA channel + */ + + if (ad_flags & AD_F_CS4231 && dma2 != -1 && dma2 != dma) + { + if ((dma == 0 && dma2 == 1) || + (dma == 1 && dma2 == 0) || + (dma == 3 && dma2 == 0)) + { + dma2_bit = 0x04; /* Enable capture DMA */ + } + else + { + printk ("MAD16: Invalid capture DMA\n"); + dma2 = dma; + } + } + else + dma2 = dma; + + outb (bits | dma_bits[dma] | dma2_bit, config_port); /* Write IRQ+DMA setup */ + + ad1848_init ("MAD16 WSS", hw_config->io_base + 4, + hw_config->irq, + dma, + dma2, 0, + hw_config->osp); + request_region (hw_config->io_base, 4, "MAD16 WSS config"); + + return mem_start; } long attach_mad16_mpu (long mem_start, struct address_info *hw_config) { + if (board_type < C929) /* Early chip. No MPU support. Just SB MIDI */ + { +#ifndef EXCLUDE_MIDI + + if (mad_read (MC1_PORT) & 0x20) + hw_config->io_base = 0x240; + else + hw_config->io_base = 0x220; + + return mad16_sb_dsp_init (mem_start, hw_config); +#else + return 0; +#endif + } #if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI) if (!already_initialized) @@ -365,10 +494,46 @@ return 0; mpu_attached = 1; - if (board_type < C929) /* Early chip. No MPU support */ + if (board_type < C929) /* Early chip. No MPU support. Just SB MIDI */ { - printk ("Mozart and OPTi 82C928 based cards don't support MPU401. Sorry\n"); + +#ifndef EXCLUDE_MIDI + unsigned char tmp; + + tmp = mad_read (MC3_PORT); + + /* + * MAD16 SB base is defined by the WSS base. It cannot be changed + * alone. + * Ignore configured I/O base. Use the active setting. + */ + + if (mad_read (MC1_PORT) & 0x20) + hw_config->io_base = 0x240; + else + hw_config->io_base = 0x220; + + switch (hw_config->irq) + { + case 5: + tmp = (tmp & 0x3f) | 0x80; + break; + case 7: + tmp = (tmp & 0x3f); + break; + case 11: + tmp = (tmp & 0x3f) | 0x40; + break; + default: + printk ("mad16/Mozart: Invalid MIDI IRQ\n"); + return 0; + } + + mad_write (MC3_PORT, tmp | 0x04); + return mad16_sb_dsp_detect (hw_config); +#else return 0; +#endif } tmp = 0x83; /* MPU-401 enable */ @@ -415,6 +580,25 @@ return probe_mpu401 (hw_config); #else return 0; +#endif +} + +void +unload_mad16 (struct address_info *hw_config) +{ + ad1848_unload (hw_config->io_base + 4, + hw_config->irq, + hw_config->dma, + hw_config->dma2, 0); + release_region (hw_config->io_base, 4); + +} + +void +unload_mad16_mpu (struct address_info *hw_config) +{ +#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI) + unload_mpu401 (hw_config); #endif } diff -u --recursive --new-file v1.3.33/linux/drivers/sound/mad16_sb_midi.c linux/drivers/sound/mad16_sb_midi.c --- v1.3.33/linux/drivers/sound/mad16_sb_midi.c Thu Jan 1 02:00:00 1970 +++ linux/drivers/sound/mad16_sb_midi.c Wed Oct 11 07:55:40 1995 @@ -0,0 +1,340 @@ +/* + * sound/mad16_sb_midi.c + * + * The low level driver for MAD16 SoundBlaster-DS-chip-based MIDI. + * + * Copyright by Hannu Savolainen 1993, Aaron Ucko 1995 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. 2. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include "sound_config.h" + +#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_MAD16) && !defined(EXCLUDE_MIDI) + +#define sbc_base mad16_sb_base +#include "sb.h" + +static int input_opened = 0; +static int my_dev; +static int mad16_sb_base = 0x220; +static int mad16_sb_irq = 0; +static int mad16_sb_dsp_ok = 0; +static sound_os_info *midi_osp; + +int mad16_sb_midi_mode = NORMAL_MIDI; +int mad16_sb_midi_busy = 0; + +int mad16_sb_duplex_midi = 0; +volatile int mad16_sb_intr_active = 0; + +void (*midi_input_intr) (int dev, unsigned char data); + +static void mad16_sb_midi_init (int model); + +static int +mad16_sb_dsp_command (unsigned char val) +{ + int i; + unsigned long limit; + + limit = jiffies + HZ / 10; /* + * The timeout is 0.1 secods + */ + + /* + * Note! the i<500000 is an emergency exit. The mad16_sb_dsp_command() is sometimes + * called while interrupts are disabled. This means that the timer is + * disabled also. However the timeout situation is a abnormal condition. + * Normally the DSP should be ready to accept commands after just couple of + * loops. + */ + + for (i = 0; i < 500000 && jiffies < limit; i++) + { + if ((inb (DSP_STATUS) & 0x80) == 0) + { + outb (val, DSP_COMMAND); + return 1; + } + } + + printk ("MAD16 (SBP mode): DSP Command(%x) Timeout.\n", val); + printk ("IRQ conflict???\n"); + return 0; +} + +void +mad16_sbintr (int irq, struct pt_regs *dummy) +{ + int status; + + unsigned long flags; + unsigned char data; + + status = inb (DSP_DATA_AVAIL); /* + * Clear interrupt + */ + + save_flags (flags); + cli (); + + data = inb (DSP_READ); + if (input_opened) + midi_input_intr (my_dev, data); + + restore_flags (flags); +} + +static int +mad16_sb_reset_dsp (void) +{ + int loopc; + + outb (1, DSP_RESET); + tenmicrosec (); + outb (0, DSP_RESET); + tenmicrosec (); + tenmicrosec (); + tenmicrosec (); + + for (loopc = 0; loopc < 1000 && !(inb (DSP_DATA_AVAIL) & 0x80); loopc++); /* + * Wait + * for + * data + * * + * available + * status + */ + + if (inb (DSP_READ) != 0xAA) + return 0; /* + * Sorry + */ + + return 1; +} + +int +mad16_sb_dsp_detect (struct address_info *hw_config) +{ + mad16_sb_base = hw_config->io_base; + mad16_sb_irq = hw_config->irq; + midi_osp = hw_config->osp; + + if (check_region (hw_config->io_base, 16)) + { + printk ("MAD16 SB MIDI: I/O base %x not free\n", hw_config->io_base); + return 0; + } + + if (mad16_sb_dsp_ok) + return 0; /* + * Already initialized + */ + if (!mad16_sb_reset_dsp ()) + return 0; + + return 1; /* + * Detected + */ +} + +long +mad16_sb_dsp_init (long mem_start, struct address_info *hw_config) +/* this function now just verifies the reported version and calls + * mad16_sb_midi_init -- everything else is done elsewhere */ +{ + + midi_osp = hw_config->osp; + if (snd_set_irq_handler (mad16_sb_irq, mad16_sbintr, "MAD16 SB MIDI", midi_osp) < 0) + { + printk ("MAD16 SB MIDI: IRQ not free\n"); + return mem_start; + } + + request_region (hw_config->io_base, 16, "mad16/Mozart MIDI"); + + printk (" "); + mad16_sb_midi_init (2); + + mad16_sb_dsp_ok = 1; + return mem_start; +} + +static int +mad16_sb_midi_open (int dev, int mode, + void (*input) (int dev, unsigned char data), + void (*output) (int dev) +) +{ + + if (!mad16_sb_dsp_ok) + { + printk ("MAD16_SB Error: MIDI hardware not installed\n"); + return -ENXIO; + } + + if (mad16_sb_midi_busy) + return -EBUSY; + + if (mode != OPEN_WRITE && !mad16_sb_duplex_midi) + { + if (num_midis == 1) + printk ("MAD16 (SBP mode): Midi input not currently supported\n"); + return -EPERM; + } + + mad16_sb_midi_mode = NORMAL_MIDI; + if (mode != OPEN_WRITE) + { + if (mad16_sb_intr_active) + return -EBUSY; + mad16_sb_midi_mode = UART_MIDI; + } + + if (mad16_sb_midi_mode == UART_MIDI) + { + mad16_sb_reset_dsp (); + + if (!mad16_sb_dsp_command (0x35)) + return -EIO; /* + * Enter the UART mode + */ + mad16_sb_intr_active = 1; + + input_opened = 1; + midi_input_intr = input; + } + + mad16_sb_midi_busy = 1; + + return 0; +} + +static void +mad16_sb_midi_close (int dev) +{ + if (mad16_sb_midi_mode == UART_MIDI) + { + mad16_sb_reset_dsp (); /* + * The only way to kill the UART mode + */ + } + mad16_sb_intr_active = 0; + mad16_sb_midi_busy = 0; + input_opened = 0; +} + +static int +mad16_sb_midi_out (int dev, unsigned char midi_byte) +{ + unsigned long flags; + + if (mad16_sb_midi_mode == NORMAL_MIDI) + { + save_flags (flags); + cli (); + if (mad16_sb_dsp_command (0x38)) + mad16_sb_dsp_command (midi_byte); + else + printk ("MAD16_SB Error: Unable to send a MIDI byte\n"); + restore_flags (flags); + } + else + mad16_sb_dsp_command (midi_byte); /* + * UART write + */ + + return 1; +} + +static int +mad16_sb_midi_start_read (int dev) +{ + if (mad16_sb_midi_mode != UART_MIDI) + { + printk ("MAD16 (SBP mode): MIDI input not implemented.\n"); + return -EPERM; + } + return 0; +} + +static int +mad16_sb_midi_end_read (int dev) +{ + if (mad16_sb_midi_mode == UART_MIDI) + { + mad16_sb_reset_dsp (); + mad16_sb_intr_active = 0; + } + return 0; +} + +static int +mad16_sb_midi_ioctl (int dev, unsigned cmd, ioctl_arg arg) +{ + return -EPERM; +} + +#define MIDI_SYNTH_NAME "pseudo-SoundBlaster Midi" +#define MIDI_SYNTH_CAPS 0 +#include "midi_synth.h" + +static struct midi_operations mad16_sb_midi_operations = +{ + {"MAD16 (SBP mode)", 0, 0, SNDCARD_MAD16}, + &std_midi_synth, + {0}, + mad16_sb_midi_open, + mad16_sb_midi_close, + mad16_sb_midi_ioctl, + mad16_sb_midi_out, + mad16_sb_midi_start_read, + mad16_sb_midi_end_read, + NULL, /* + * Kick + */ + NULL, /* + * command + */ + NULL, /* + * buffer_status + */ + NULL +}; + +static void +mad16_sb_midi_init (int model) +{ + if (num_midis >= MAX_MIDI_DEV) + { + printk ("Sound: Too many midi devices detected\n"); + return; + } + + std_midi_synth.midi_dev = num_midis; + my_dev = num_midis; + midi_devs[num_midis++] = &mad16_sb_midi_operations; +} + +#endif diff -u --recursive --new-file v1.3.33/linux/drivers/sound/maui.c linux/drivers/sound/maui.c --- v1.3.33/linux/drivers/sound/maui.c Thu Jan 1 02:00:00 1970 +++ linux/drivers/sound/maui.c Wed Oct 11 07:55:40 1995 @@ -0,0 +1,268 @@ +/* + * sound/maui.c + * + * The low level driver for Turtle Beach Maui and Tropez. + * + * Copyright by Hannu Savolainen 1995 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. 2. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#define USE_SEQ_MACROS +#define USE_SIMPLE_MACROS + +#include "sound_config.h" + +#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_MAUI) + +static int maui_base = 0x330; + +static volatile int irq_ok = 0; +static sound_os_info *maui_osp; + +#define HOST_DATA_PORT (maui_base + 2) +#define HOST_STAT_PORT (maui_base + 3) +#define HOST_CTRL_PORT (maui_base + 3) + +#define STAT_TX_INTR 0x40 +#define STAT_TX_AVAIL 0x20 +#define STAT_TX_IENA 0x10 +#define STAT_RX_INTR 0x04 +#define STAT_RX_AVAIL 0x02 +#define STAT_RX_IENA 0x01 + +static int (*orig_load_patch) (int dev, int format, const snd_rw_buf * addr, + int offs, int count, int pmgr_flag) = NULL; + +static int +maui_read (void) +{ + int timeout; + + for (timeout = 0; timeout < 1000000; timeout++) + { + if (inb (HOST_STAT_PORT) & STAT_RX_AVAIL) + { + return inb (HOST_DATA_PORT); + } + } + + printk ("Maui: Receive timeout\n"); + + return -1; +} + +static int +maui_write (unsigned char data) +{ + int timeout; + + for (timeout = 0; timeout < 10000000; timeout++) + { + if (inb (HOST_STAT_PORT) & STAT_TX_AVAIL) + { + outb (data, HOST_DATA_PORT); + return 1; + } + } + + printk ("Maui: Transmit timeout\n"); + + return 0; +} + +void +mauiintr (int irq, struct pt_regs *dummy) +{ + irq_ok = 1; +} + + +int +maui_load_patch (int dev, int format, const snd_rw_buf * addr, + int offs, int count, int pmgr_flag) +{ + + struct sysex_info header; + unsigned long left, src_offs; + int hdr_size = (unsigned long) &header.data[0] - (unsigned long) &header; + int i; + + if (format == SYSEX_PATCH) /* Handled by midi_synth.c */ + return orig_load_patch (dev, format, addr, offs, count, pmgr_flag); + + if (format != MAUI_PATCH) + { + printk ("Maui: Unknown patch format\n"); + } + + if (count < hdr_size) + { + printk ("Maui error: Patch header too short\n"); + return -EINVAL; + } + + count -= hdr_size; + + /* + * Copy the header from user space but ignore the first bytes which have + * been transferred already. + */ + + memcpy_fromfs ((&((char *) &header)[offs]), &((addr)[offs]), (hdr_size - offs)); + + if (count < header.len) + { + printk ("Maui warning: Host command record too short (%d<%d)\n", + count, (int) header.len); + header.len = count; + } + + left = header.len; + src_offs = 0; + + for (i = 0; i < left; i++) + { + unsigned char data; + + data = get_fs_byte (&((addr)[hdr_size + i])); + if (i == 0 && !(data & 0x80)) + return -EINVAL; + + if (maui_write (data) == -1) + return -EIO; + } + + if ((i = maui_read ()) != 0x80) + { + if (i != -1) + printk ("Maui: Error status %02x\n", i); + + return -EIO; + } + + return 0; +} + +int +probe_maui (struct address_info *hw_config) +{ + int i; + int tmp1, tmp2; + + if (check_region (hw_config->io_base, 8)) + return 0; + + maui_base = hw_config->io_base; + maui_osp = hw_config->osp; + + if (snd_set_irq_handler (hw_config->irq, mauiintr, "Maui", maui_osp) < 0) + return 0; + + + if (!maui_write (0xCF)) /* Report hardware version */ + { + snd_release_irq (hw_config->irq); + return 0; + } + + if ((tmp1 = maui_read ()) == -1 || (tmp2 = maui_read ()) == -1) + { + snd_release_irq (hw_config->irq); + return 0; + } + + printk ("WaveFront hardware version %d.%d\n", tmp1, tmp2); + + if (!maui_write (0x9F)) /* Report firmware version */ + return 0; + if ((tmp1 = maui_read ()) == -1 || (tmp2 = maui_read ()) == -1) + return 0; + printk ("WaveFront firmware version %d.%d\n", tmp1, tmp2); + + if (!maui_write (0x85)) /* Report free DRAM */ + return 0; + tmp1 = 0; + for (i = 0; i < 4; i++) + { + tmp1 |= maui_read () << (7 * i); + } + printk ("Available DRAM %dk\n", tmp1 / 1024); + + request_region (hw_config->io_base + 2, 6, "Maui"); + + for (i = 0; i < 1000; i++) + if (probe_mpu401 (hw_config)) + break; + + return probe_mpu401 (hw_config); +} + +long +attach_maui (long mem_start, struct address_info *hw_config) +{ + int this_dev = num_midis; + + printk (" "); + + hw_config->irq *= -1; + mem_start = attach_mpu401 (mem_start, hw_config); + + if (num_midis > this_dev) /* The MPU401 driver installed itself */ + { + struct synth_operations *synth; + + /* + * Intercept patch loading calls so that they canbe handled + * by the Maui driver. + */ + + synth = midi_devs[this_dev]->converter; + + if (synth != NULL) + { + orig_load_patch = synth->load_patch; + synth->load_patch = &maui_load_patch; + } + else + printk ("Maui: Can't install patch loader\n"); + } + return mem_start; +} + +void +unload_maui (struct address_info *hw_config) +{ + int irq = hw_config->irq; + + release_region (hw_config->io_base + 2, 6); + + unload_mpu401 (hw_config); + + if (irq < 0) + irq = -irq; + + if (irq > 0) + snd_release_irq (irq); +} + +#endif diff -u --recursive --new-file v1.3.33/linux/drivers/sound/midi_synth.c linux/drivers/sound/midi_synth.c --- v1.3.33/linux/drivers/sound/midi_synth.c Tue Jul 11 10:02:53 1995 +++ linux/drivers/sound/midi_synth.c Wed Oct 11 07:55:40 1995 @@ -36,11 +36,15 @@ #define _MIDI_SYNTH_C_ -DEFINE_WAIT_QUEUE (sysex_sleeper, sysex_sleep_flag); +static struct wait_queue *sysex_sleeper = NULL; +static volatile struct snd_wait sysex_sleep_flag = +{0}; #include "midi_synth.h" static int midi2synth[MAX_MIDI_DEV]; +static int sysex_state[MAX_MIDI_DEV] = +{0}; static unsigned char prev_out_status[MAX_MIDI_DEV]; #define STORE(cmd) \ @@ -95,6 +99,7 @@ default: /* printk ("MPU: Unknown midi channel message %02x\n", msg[0]); */ + ; } } @@ -242,6 +247,24 @@ } static void +leave_sysex (int dev) +{ + int orig_dev = synth_devs[dev]->midi_dev; + int timeout = 0; + + if (!sysex_state[dev]) + return; + + sysex_state[dev] = 0; + + while (!midi_devs[orig_dev]->putc (orig_dev, 0xf7) && + timeout < 1000) + timeout++; + + sysex_state[dev] = 0; +} + +static void midi_synth_output (int dev) { /* @@ -251,7 +274,7 @@ int midi_synth_ioctl (int dev, - unsigned int cmd, unsigned int arg) + unsigned int cmd, ioctl_arg arg) { /* * int orig_dev = synth_devs[dev]->midi_dev; @@ -261,8 +284,7 @@ { case SNDCTL_SYNTH_INFO: - IOCTL_TO_USER ((char *) arg, 0, synth_devs[dev]->info, - sizeof (struct synth_info)); + memcpy_tofs (&(((char *) arg)[0]), (synth_devs[dev]->info), (sizeof (struct synth_info))); return 0; break; @@ -272,7 +294,7 @@ break; default: - return RET_ERROR (EINVAL); + return -EINVAL; } } @@ -291,6 +313,8 @@ if (velocity > 127) velocity = 127; + leave_sysex (dev); + msg = prev_out_status[orig_dev] & 0xf0; chn = prev_out_status[orig_dev] & 0x0f; @@ -352,6 +376,8 @@ if (channel < 0 || channel > 15) return 0; + leave_sysex (dev); + if (!prefix_cmd (orig_dev, 0xc0 | (channel & 0x0f))) return 0; midi_outc (orig_dev, 0xc0 | (channel & 0x0f)); /* @@ -377,6 +403,8 @@ if (velocity > 127) velocity = 127; + leave_sysex (dev); + msg = prev_out_status[orig_dev] & 0xf0; chn = prev_out_status[orig_dev] & 0x0f; @@ -405,6 +433,8 @@ void midi_synth_reset (int dev) { + + leave_sysex (dev); } int @@ -416,9 +446,10 @@ struct midi_input_info *inc; if (orig_dev < 0 || orig_dev > num_midis) - return RET_ERROR (ENXIO); + return -ENXIO; midi2synth[orig_dev] = dev; + sysex_state[dev] = 0; prev_out_status[orig_dev] = 0; if ((err = midi_devs[orig_dev]->open (orig_dev, mode, @@ -427,13 +458,14 @@ inc = &midi_devs[orig_dev]->in_info; - DISABLE_INTR (flags); + save_flags (flags); + cli (); inc->m_busy = 0; inc->m_state = MST_INIT; inc->m_ptr = 0; inc->m_left = 0; inc->m_prev_status = 0x00; - RESTORE_INTR (flags); + restore_flags (flags); return 1; } @@ -443,8 +475,10 @@ { int orig_dev = synth_devs[dev]->midi_dev; + leave_sysex (dev); + /* - * Shut up the synths by sending just single active sensing message. + * Shut up the synths by sending just single active sensing message. */ midi_devs[orig_dev]->putc (orig_dev, 0xfe); @@ -457,7 +491,7 @@ } int -midi_synth_load_patch (int dev, int format, snd_rw_buf * addr, +midi_synth_load_patch (int dev, int format, const snd_rw_buf * addr, int offs, int count, int pmgr_flag) { int orig_dev = synth_devs[dev]->midi_dev; @@ -468,19 +502,21 @@ int first_byte = 1; int hdr_size = (unsigned long) &sysex.data[0] - (unsigned long) &sysex; + leave_sysex (dev); + if (!prefix_cmd (orig_dev, 0xf0)) return 0; if (format != SYSEX_PATCH) { printk ("MIDI Error: Invalid patch format (key) 0x%x\n", format); - return RET_ERROR (EINVAL); + return -EINVAL; } if (count < hdr_size) { printk ("MIDI Error: Patch header too short\n"); - return RET_ERROR (EINVAL); + return -EINVAL; } count -= hdr_size; @@ -490,7 +526,7 @@ * been transferred already. */ - COPY_FROM_USER (&((char *) &sysex)[offs], addr, offs, hdr_size - offs); + memcpy_fromfs ((&((char *) &sysex)[offs]), &((addr)[offs]), (hdr_size - offs)); if (count < sysex.len) { @@ -502,13 +538,16 @@ left = sysex.len; src_offs = 0; - RESET_WAIT_QUEUE (sysex_sleeper, sysex_sleep_flag); + { + sysex_sleep_flag.aborting = 0; + sysex_sleep_flag.mode = WK_NONE; + }; - for (i = 0; i < left && !PROCESS_ABORTING (sysex_sleeper, sysex_sleep_flag); i++) + for (i = 0; i < left && !((current->signal & ~current->blocked)); i++) { unsigned char data; - GET_BYTE_FROM_USER (data, addr, hdr_size + i); + data = get_fs_byte (&((addr)[hdr_size + i])); eox_seen = (i > 0 && data & 0x80); /* End of sysex */ @@ -520,13 +559,31 @@ if (data != 0xf0) { printk ("Error: Sysex start missing\n"); - return RET_ERROR (EINVAL); + return -EINVAL; } } while (!midi_devs[orig_dev]->putc (orig_dev, (unsigned char) (data & 0xff)) && - !PROCESS_ABORTING (sysex_sleeper, sysex_sleep_flag)) - DO_SLEEP (sysex_sleeper, sysex_sleep_flag, 1); /* Wait for timeout */ + !((current->signal & ~current->blocked))) + + { + unsigned long tl; + + if (1) + tl = current->timeout = jiffies + (1); + else + tl = 0xffffffff; + sysex_sleep_flag.mode = WK_SLEEP; + interruptible_sleep_on (&sysex_sleeper); + if (!(sysex_sleep_flag.mode & WK_WAKEUP)) + { + if (current->signal & ~current->blocked) + sysex_sleep_flag.aborting = 1; + else if (jiffies >= tl) + sysex_sleep_flag.mode |= WK_TIMEOUT; + } + sysex_sleep_flag.mode &= ~WK_SLEEP; + }; /* Wait for timeout */ if (!first_byte && data & 0x80) return 0; @@ -554,6 +611,8 @@ if (channel < 0 || channel > 15) return; + leave_sysex (dev); + msg = prev_out_status[orig_dev] & 0xf0; chn = prev_out_status[orig_dev] & 0x0f; @@ -584,6 +643,8 @@ if (channel < 0 || channel > 15) return; + leave_sysex (dev); + msg = prev_out_status[orig_dev] & 0xf0; chn = prev_out_status[orig_dev] & 0x0f; @@ -603,7 +664,7 @@ int midi_synth_patchmgr (int dev, struct patmgr_info *rec) { - return RET_ERROR (EINVAL); + return -EINVAL; } void @@ -618,6 +679,8 @@ if (value < 0 || value > 16383) return; + leave_sysex (dev); + msg = prev_out_status[orig_dev] & 0xf0; prev_chn = prev_out_status[orig_dev] & 0x0f; @@ -639,6 +702,62 @@ void midi_synth_setup_voice (int dev, int voice, int channel) { +} + +int +midi_synth_send_sysex (int dev, unsigned char *bytes, int len) +{ + int orig_dev = synth_devs[dev]->midi_dev; + int i; + + for (i = 0; i < len; i++) + { + switch (bytes[i]) + { + case 0xf0: /* Start sysex */ + if (!prefix_cmd (orig_dev, 0xf0)) + return 0; + sysex_state[dev] = 1; + break; + + case 0xf7: /* End sysex */ + if (!sysex_state[dev]) /* Orphan sysex end */ + return 0; + sysex_state[dev] = 0; + break; + + default: + if (!sysex_state[dev]) + return 0; + + if (bytes[i] & 0x80) /* Error. Another message before sysex end */ + { + bytes[i] = 0xf7; /* Sysex end */ + sysex_state[dev] = 0; + } + } + + if (!midi_devs[orig_dev]->putc (orig_dev, bytes[i])) + { +/* + * Hardware leve buffer is full. Abort the sysex message. + */ + + int timeout = 0; + + bytes[i] = 0xf7; + sysex_state[dev] = 0; + + while (!midi_devs[orig_dev]->putc (orig_dev, bytes[i]) && + timeout < 1000) + timeout++; + } + + if (!sysex_state[dev]) + return 0; + } + + return 0; } #endif diff -u --recursive --new-file v1.3.33/linux/drivers/sound/midi_synth.h linux/drivers/sound/midi_synth.h --- v1.3.33/linux/drivers/sound/midi_synth.h Tue Jul 11 10:02:53 1995 +++ linux/drivers/sound/midi_synth.h Wed Oct 11 07:55:36 1995 @@ -1,5 +1,5 @@ int midi_synth_ioctl (int dev, - unsigned int cmd, unsigned int arg); + unsigned int cmd, ioctl_arg arg); int midi_synth_kill_note (int dev, int channel, int note, int velocity); int midi_synth_set_instr (int dev, int channel, int instr_no); int midi_synth_start_note (int dev, int channel, int note, int volume); @@ -7,7 +7,7 @@ int midi_synth_open (int dev, int mode); void midi_synth_close (int dev); void midi_synth_hw_control (int dev, unsigned char *event); -int midi_synth_load_patch (int dev, int format, snd_rw_buf * addr, +int midi_synth_load_patch (int dev, int format, const snd_rw_buf * addr, int offs, int count, int pmgr_flag); void midi_synth_panning (int dev, int channel, int pressure); void midi_synth_aftertouch (int dev, int channel, int pressure); @@ -16,7 +16,7 @@ void midi_synth_bender (int dev, int chn, int value); void midi_synth_setup_voice (int dev, int voice, int chn); void do_midi_msg (int synthno, unsigned char *msg, int mlen); - +int midi_synth_send_sysex(int dev, unsigned char *bytes,int len); #ifndef _MIDI_SYNTH_C_ static struct synth_info std_synth_info = @@ -44,6 +44,7 @@ midi_synth_patchmgr, midi_synth_bender, NULL, /* alloc_voice */ - midi_synth_setup_voice + midi_synth_setup_voice, + midi_synth_send_sysex }; #endif diff -u --recursive --new-file v1.3.33/linux/drivers/sound/midibuf.c linux/drivers/sound/midibuf.c --- v1.3.33/linux/drivers/sound/midibuf.c Tue Jul 11 10:02:53 1995 +++ linux/drivers/sound/midibuf.c Wed Oct 11 07:55:40 1995 @@ -37,8 +37,16 @@ #define MAX_QUEUE_SIZE 4000 -DEFINE_WAIT_QUEUES (midi_sleeper[MAX_MIDI_DEV], midi_sleep_flag[MAX_MIDI_DEV]); -DEFINE_WAIT_QUEUES (input_sleeper[MAX_MIDI_DEV], input_sleep_flag[MAX_MIDI_DEV]); +static struct wait_queue *midi_sleeper[MAX_MIDI_DEV] = +{NULL}; +static volatile struct snd_wait midi_sleep_flag[MAX_MIDI_DEV] = +{ + {0}}; +static struct wait_queue *input_sleeper[MAX_MIDI_DEV] = +{NULL}; +static volatile struct snd_wait input_sleep_flag[MAX_MIDI_DEV] = +{ + {0}}; struct midi_buf { @@ -61,7 +69,9 @@ static void midi_poll (unsigned long dummy); -DEFINE_TIMER (poll_timer, midi_poll); + +static struct timer_list poll_timer = +{NULL, NULL, 0, 0, midi_poll}; static volatile int open_devs = 0; #define DATA_AVAIL(q) (q->len) @@ -71,20 +81,20 @@ if (SPACE_AVAIL(q)) \ { \ unsigned long flags; \ - DISABLE_INTR(flags); \ + save_flags(flags);cli(); \ q->queue[q->tail] = (data); \ q->len++; q->tail = (q->tail+1) % MAX_QUEUE_SIZE; \ - RESTORE_INTR(flags); \ + restore_flags(flags); \ } #define REMOVE_BYTE(q, data) \ if (DATA_AVAIL(q)) \ { \ unsigned long flags; \ - DISABLE_INTR(flags); \ + save_flags(flags);cli(); \ data = q->queue[q->head]; \ q->len--; q->head = (q->head+1) % MAX_QUEUE_SIZE; \ - RESTORE_INTR(flags); \ + restore_flags(flags); \ } void @@ -96,9 +106,27 @@ */ if (midi_devs[dev]->buffer_status != NULL) - while (!PROCESS_ABORTING (midi_sleeper[dev], midi_sleep_flag[dev]) && + while (!((current->signal & ~current->blocked)) && midi_devs[dev]->buffer_status (dev)) - DO_SLEEP (midi_sleeper[dev], midi_sleep_flag[dev], HZ / 10); + + { + unsigned long tl; + + if (HZ / 10) + tl = current->timeout = jiffies + (HZ / 10); + else + tl = 0xffffffff; + midi_sleep_flag[dev].mode = WK_SLEEP; + interruptible_sleep_on (&midi_sleeper[dev]); + if (!(midi_sleep_flag[dev].mode & WK_WAKEUP)) + { + if (current->signal & ~current->blocked) + midi_sleep_flag[dev].aborting = 1; + else if (jiffies >= tl) + midi_sleep_flag[dev].mode |= WK_TIMEOUT; + } + midi_sleep_flag[dev].mode &= ~WK_SLEEP; + }; } static void @@ -117,8 +145,11 @@ if (SPACE_AVAIL (midi_in_buf[dev])) { QUEUE_BYTE (midi_in_buf[dev], data); - if (SOMEONE_WAITING (input_sleeper[dev], input_sleep_flag[dev])) - WAKE_UP (input_sleeper[dev], input_sleep_flag[dev]); + if ((input_sleep_flag[dev].mode & WK_SLEEP)) + { + input_sleep_flag[dev].mode = WK_WAKEUP; + wake_up (&input_sleeper[dev]); + }; } } @@ -137,7 +168,8 @@ unsigned long flags; int dev; - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (open_devs) { for (dev = 0; dev < num_midis; dev++) @@ -152,14 +184,21 @@ } if (DATA_AVAIL (midi_out_buf[dev]) < 100 && - SOMEONE_WAITING (midi_sleeper[dev], midi_sleep_flag[dev])) - WAKE_UP (midi_sleeper[dev], midi_sleep_flag[dev]); + (midi_sleep_flag[dev].mode & WK_SLEEP)) + { + midi_sleep_flag[dev].mode = WK_WAKEUP; + wake_up (&midi_sleeper[dev]); + }; } - ACTIVATE_TIMER (poll_timer, midi_poll, 1); /* - * Come back later - */ + + { + poll_timer.expires = (1) + jiffies; + add_timer (&poll_timer); + }; /* + * Come back later + */ } - RESTORE_INTR (flags); + restore_flags (flags); } int @@ -180,55 +219,80 @@ if (dev < 0 || dev >= num_midis) { printk ("Sound: Nonexistent MIDI interface %d\n", dev); - return RET_ERROR (ENXIO); + return -ENXIO; } /* * Interrupts disabled. Be careful */ - DISABLE_INTR (flags); + save_flags (flags); + cli (); if ((err = midi_devs[dev]->open (dev, mode, midi_input_intr, midi_output_intr)) < 0) { - RESTORE_INTR (flags); + restore_flags (flags); return err; } parms[dev].prech_timeout = 0; - RESET_WAIT_QUEUE (midi_sleeper[dev], midi_sleep_flag[dev]); - RESET_WAIT_QUEUE (input_sleeper[dev], input_sleep_flag[dev]); + { + midi_sleep_flag[dev].aborting = 0; + midi_sleep_flag[dev].mode = WK_NONE; + }; + { + input_sleep_flag[dev].aborting = 0; + input_sleep_flag[dev].mode = WK_NONE; + }; - midi_in_buf[dev] = (struct midi_buf *) KERNEL_MALLOC (sizeof (struct midi_buf)); + midi_in_buf[dev] = (struct midi_buf *) ( + { + caddr_t x; + x = kmalloc (sizeof (struct midi_buf), GFP_KERNEL); + + x; + } + ); if (midi_in_buf[dev] == NULL) { printk ("midi: Can't allocate buffer\n"); midi_devs[dev]->close (dev); - RESTORE_INTR (flags); - return RET_ERROR (EIO); + restore_flags (flags); + return -EIO; } midi_in_buf[dev]->len = midi_in_buf[dev]->head = midi_in_buf[dev]->tail = 0; - midi_out_buf[dev] = (struct midi_buf *) KERNEL_MALLOC (sizeof (struct midi_buf)); + midi_out_buf[dev] = (struct midi_buf *) ( + { + caddr_t x; + x = kmalloc (sizeof (struct midi_buf), GFP_KERNEL); + + x; + } + ); if (midi_out_buf[dev] == NULL) { printk ("midi: Can't allocate buffer\n"); midi_devs[dev]->close (dev); - KERNEL_FREE (midi_in_buf[dev]); + kfree (midi_in_buf[dev]); midi_in_buf[dev] = NULL; - RESTORE_INTR (flags); - return RET_ERROR (EIO); + restore_flags (flags); + return -EIO; } midi_out_buf[dev]->len = midi_out_buf[dev]->head = midi_out_buf[dev]->tail = 0; if (!open_devs) - ACTIVATE_TIMER (poll_timer, midi_poll, 1); /* - * Come back later - */ + + { + poll_timer.expires = (1) + jiffies; + add_timer (&poll_timer); + }; /* + * Come back later + */ open_devs++; - RESTORE_INTR (flags); + restore_flags (flags); return err; } @@ -242,7 +306,8 @@ dev = dev >> 4; mode = file->mode & O_ACCMODE; - DISABLE_INTR (flags); + save_flags (flags); + cli (); /* * Wait until the queue is empty @@ -255,11 +320,29 @@ * devices */ - while (!PROCESS_ABORTING (midi_sleeper[dev], midi_sleep_flag[dev]) && + while (!((current->signal & ~current->blocked)) && DATA_AVAIL (midi_out_buf[dev])) - DO_SLEEP (midi_sleeper[dev], midi_sleep_flag[dev], 0); /* - * Sync - */ + + { + unsigned long tl; + + if (0) + tl = current->timeout = jiffies + (0); + else + tl = 0xffffffff; + midi_sleep_flag[dev].mode = WK_SLEEP; + interruptible_sleep_on (&midi_sleeper[dev]); + if (!(midi_sleep_flag[dev].mode & WK_WAKEUP)) + { + if (current->signal & ~current->blocked) + midi_sleep_flag[dev].aborting = 1; + else if (jiffies >= tl) + midi_sleep_flag[dev].mode |= WK_TIMEOUT; + } + midi_sleep_flag[dev].mode &= ~WK_SLEEP; + }; /* + * Sync + */ drain_midi_queue (dev); /* * Ensure the output queues are empty @@ -267,16 +350,17 @@ } midi_devs[dev]->close (dev); - KERNEL_FREE (midi_in_buf[dev]); - KERNEL_FREE (midi_out_buf[dev]); + kfree (midi_in_buf[dev]); + kfree (midi_out_buf[dev]); midi_in_buf[dev] = NULL; midi_out_buf[dev] = NULL; open_devs--; - RESTORE_INTR (flags); + del_timer (&poll_timer);; + restore_flags (flags); } int -MIDIbuf_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) +MIDIbuf_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count) { unsigned long flags; int c, n, i; @@ -287,7 +371,8 @@ if (!count) return 0; - DISABLE_INTR (flags); + save_flags (flags); + cli (); c = 0; @@ -299,11 +384,29 @@ * No space just now. We have to sleep */ { - DO_SLEEP (midi_sleeper[dev], midi_sleep_flag[dev], 0); - if (PROCESS_ABORTING (midi_sleeper[dev], midi_sleep_flag[dev])) + + { + unsigned long tl; + + if (0) + tl = current->timeout = jiffies + (0); + else + tl = 0xffffffff; + midi_sleep_flag[dev].mode = WK_SLEEP; + interruptible_sleep_on (&midi_sleeper[dev]); + if (!(midi_sleep_flag[dev].mode & WK_WAKEUP)) + { + if (current->signal & ~current->blocked) + midi_sleep_flag[dev].aborting = 1; + else if (jiffies >= tl) + midi_sleep_flag[dev].mode |= WK_TIMEOUT; + } + midi_sleep_flag[dev].mode &= ~WK_SLEEP; + }; + if (((current->signal & ~current->blocked))) { - RESTORE_INTR (flags); - return RET_ERROR (EINTR); + restore_flags (flags); + return -EINTR; } n = SPACE_AVAIL (midi_out_buf[dev]); @@ -314,13 +417,13 @@ for (i = 0; i < n; i++) { - COPY_FROM_USER (&tmp_data, buf, c, 1); + memcpy_fromfs ((&tmp_data), &((buf)[c]), (1)); QUEUE_BYTE (midi_out_buf[dev], tmp_data); c++; } } - RESTORE_INTR (flags); + restore_flags (flags); return c; } @@ -335,17 +438,35 @@ dev = dev >> 4; - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (!DATA_AVAIL (midi_in_buf[dev])) /* * No data yet, wait */ { - DO_SLEEP (input_sleeper[dev], input_sleep_flag[dev], - parms[dev].prech_timeout); - if (PROCESS_ABORTING (input_sleeper[dev], input_sleep_flag[dev])) - c = RET_ERROR (EINTR); /* - * The user is getting restless + + { + unsigned long tl; + + if (parms[dev].prech_timeout) + tl = current->timeout = jiffies + (parms[dev].prech_timeout); + else + tl = 0xffffffff; + input_sleep_flag[dev].mode = WK_SLEEP; + interruptible_sleep_on (&input_sleeper[dev]); + if (!(input_sleep_flag[dev].mode & WK_WAKEUP)) + { + if (current->signal & ~current->blocked) + input_sleep_flag[dev].aborting = 1; + else if (jiffies >= tl) + input_sleep_flag[dev].mode |= WK_TIMEOUT; + } + input_sleep_flag[dev].mode &= ~WK_SLEEP; + }; + if (((current->signal & ~current->blocked))) + c = -EINTR; /* + * The user is getting restless */ } @@ -361,19 +482,19 @@ while (c < n) { REMOVE_BYTE (midi_in_buf[dev], tmp_data); - COPY_TO_USER (buf, c, &tmp_data, 1); + memcpy_tofs (&((buf)[c]), (&tmp_data), (1)); c++; } } - RESTORE_INTR (flags); + restore_flags (flags); return c; } int MIDIbuf_ioctl (int dev, struct fileinfo *file, - unsigned int cmd, unsigned int arg) + unsigned int cmd, ioctl_arg arg) { int val; @@ -386,20 +507,20 @@ else printk ("/dev/midi%d: No coprocessor for this device\n", dev); - return RET_ERROR (EREMOTEIO); + return -ENXIO; } else switch (cmd) { case SNDCTL_MIDI_PRETIME: - val = IOCTL_IN (arg); + val = (int) get_fs_long ((long *) arg); if (val < 0) val = 0; val = (HZ * val) / 10; parms[dev].prech_timeout = val; - return IOCTL_OUT (arg, val); + return snd_ioctl_return ((int *) arg, val); break; default: @@ -407,7 +528,6 @@ } } -#ifdef ALLOW_SELECT int MIDIbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wait) { @@ -442,7 +562,6 @@ return 0; } -#endif /* ALLOW_SELECT */ long MIDIbuf_init (long mem_start) diff -u --recursive --new-file v1.3.33/linux/drivers/sound/mpu401.c linux/drivers/sound/mpu401.c --- v1.3.33/linux/drivers/sound/mpu401.c Sun Aug 13 14:45:33 1995 +++ linux/drivers/sound/mpu401.c Wed Oct 11 07:55:40 1995 @@ -80,19 +80,20 @@ unsigned char last_status; void (*inputintr) (int dev, unsigned char data); int shared_irq; + sound_os_info *osp; }; #define DATAPORT(base) (base) #define COMDPORT(base) (base+1) #define STATPORT(base) (base+1) -#define mpu401_status(base) INB(STATPORT(base)) -#define input_avail(base) (!(mpu401_status(base)&INPUT_AVAIL)) -#define output_ready(base) (!(mpu401_status(base)&OUTPUT_READY)) -#define write_command(base, cmd) OUTB(cmd, COMDPORT(base)) -#define read_data(base) INB(DATAPORT(base)) +#define mpu401_status(devc) inb( STATPORT(devc->base)) +#define input_avail(devc) (!(mpu401_status(devc)&INPUT_AVAIL)) +#define output_ready(devc) (!(mpu401_status(devc)&OUTPUT_READY)) +#define write_command(devc, cmd) outb( cmd, COMDPORT(devc->base)) +#define read_data(devc) inb( DATAPORT(devc->base)) -#define write_data(base, byte) OUTB(byte, DATAPORT(base)) +#define write_data(devc, byte) outb( byte, DATAPORT(devc->base)) #define OUTPUT_READY 0x40 #define INPUT_AVAIL 0x80 @@ -105,9 +106,9 @@ {0}}; static int n_mpu_devs = 0; -static int irq2dev[16] = +static volatile int irq2dev[17] = {-1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1}; + -1, -1, -1, -1, -1, -1, -1, -1, -1}; static int reset_mpu401 (struct mpu_config *devc); static void set_uart_mode (int dev, struct mpu_config *devc, int arg); @@ -216,14 +217,14 @@ case ST_TIMED: { - int msg = (midic & 0xf0) >> 4; + int msg = ((int) (midic & 0xf0) >> 4); devc->m_state = ST_DATABYTE; if (msg < 8) /* Data byte */ { /* printk("midi msg (running status) "); */ - msg = (devc->last_status & 0xf0) >> 4; + msg = ((int) (devc->last_status & 0xf0) >> 4); msg -= 8; devc->m_left = len_tab[msg] - 1; @@ -399,19 +400,20 @@ int busy; int n; - DISABLE_INTR (flags); + save_flags (flags); + cli (); busy = devc->m_busy; devc->m_busy = 1; - RESTORE_INTR (flags); + restore_flags (flags); if (busy) /* Already inside the scanner */ return; n = 50; - while (input_avail (devc->base) && n-- > 0) + while (input_avail (devc) && n-- > 0) { - unsigned char c = read_data (devc->base); + unsigned char c = read_data (devc); if (devc->mode == MODE_SYNTH) { @@ -425,37 +427,50 @@ } void -mpuintr (INT_HANDLER_PARMS (irq, dummy)) +mpuintr (int irq, struct pt_regs *dummy) { struct mpu_config *devc; int dev; -#ifdef linux sti (); -#endif + +/* + * FreeBSD (and some others) pass unit number to the interrupt handler. + * In this case we have to scan the table for first handler. + */ if (irq < 1 || irq > 15) { - printk ("MPU-401: Interrupt #%d?\n", irq); - return; + dev = -1; } + else + dev = irq2dev[irq]; - dev = irq2dev[irq]; if (dev == -1) { - /* printk ("MPU-401: Interrupt #%d?\n", irq); */ - return; - } + int origirq = irq; - devc = &dev_conf[dev]; + for (irq = 0; irq <= 16; irq++) + if (irq2dev[irq] != -1) + break; + if (irq > 15) + { + printk ("MPU-401: Bogus interrupt #%d?\n", origirq); + return; + } + dev = irq2dev[irq]; + devc = &dev_conf[dev]; + } + else + devc = &dev_conf[dev]; - if (input_avail (devc->base)) + if (input_avail (devc)) if (devc->base != 0 && (devc->opened & OPEN_READ || devc->mode == MODE_SYNTH)) mpu401_input_loop (devc); else { /* Dummy read (just to acknowledge the interrupt) */ - read_data (devc->base); + read_data (devc); } } @@ -470,14 +485,14 @@ struct mpu_config *devc; if (dev < 0 || dev >= num_midis) - return RET_ERROR (ENXIO); + return -ENXIO; devc = &dev_conf[dev]; if (devc->opened) { printk ("MPU-401: Midi busy\n"); - return RET_ERROR (EBUSY); + return -EBUSY; } /* @@ -489,27 +504,20 @@ if (!devc->initialized) { - if (mpu401_status (devc->base) == 0xff) /* Bus float */ + if (mpu401_status (devc) == 0xff) /* Bus float */ { printk ("MPU-401: Device not initialized properly\n"); - return RET_ERROR (EIO); + return -EIO; } reset_mpu401 (devc); } irq2dev[devc->irq] = dev; - if (devc->shared_irq == 0) - if ((err = snd_set_irq_handler (devc->irq, mpuintr, midi_devs[dev]->info.name) < 0)) - { - return err; - } if (midi_devs[dev]->coproc) if ((err = midi_devs[dev]->coproc-> open (midi_devs[dev]->coproc->devc, COPR_MIDI)) < 0) { - if (devc->shared_irq == 0) - snd_release_irq (devc->irq); printk ("MPU-401: Can't access coprocessor device\n"); return err; @@ -540,8 +548,6 @@ */ devc->mode = 0; - if (devc->shared_irq == 0) - snd_release_irq (devc->irq); devc->inputintr = NULL; if (midi_devs[dev]->coproc) @@ -559,33 +565,24 @@ devc = &dev_conf[dev]; -#if 0 - /* - * Test for input since pending input seems to block the output. - */ - - if (input_avail (devc->base)) - { - mpu401_input_loop (devc); - } -#endif /* * Sometimes it takes about 13000 loops before the output becomes ready * (After reset). Normally it takes just about 10 loops. */ - for (timeout = 3000; timeout > 0 && !output_ready (devc->base); timeout--); + for (timeout = 3000; timeout > 0 && !output_ready (devc); timeout--); - DISABLE_INTR (flags); - if (!output_ready (devc->base)) + save_flags (flags); + cli (); + if (!output_ready (devc)) { printk ("MPU-401: Send data timeout\n"); - RESTORE_INTR (flags); + restore_flags (flags); return 0; } - write_data (devc->base, midi_byte); - RESTORE_INTR (flags); + write_data (devc, midi_byte); + restore_flags (flags); return 1; } @@ -604,13 +601,13 @@ */ { printk ("MPU-401 commands not possible in the UART mode\n"); - return RET_ERROR (EINVAL); + return -EINVAL; } /* * Test for input since pending input seems to block the output. */ - if (input_avail (devc->base)) + if (input_avail (devc)) mpu401_input_loop (devc); /* @@ -623,49 +620,50 @@ if (timeout-- <= 0) { printk ("MPU-401: Command (0x%x) timeout\n", (int) cmd->cmd); - return RET_ERROR (EIO); + return -EIO; } - DISABLE_INTR (flags); + save_flags (flags); + cli (); - if (!output_ready (devc->base)) + if (!output_ready (devc)) { - RESTORE_INTR (flags); + restore_flags (flags); goto retry; } - write_command (devc->base, cmd->cmd); + write_command (devc, cmd->cmd); ok = 0; for (timeout = 50000; timeout > 0 && !ok; timeout--) - if (input_avail (devc->base)) + if (input_avail (devc)) if (devc->opened && devc->mode == MODE_SYNTH) { - if (mpu_input_scanner (devc, read_data (devc->base)) == MPU_ACK) + if (mpu_input_scanner (devc, read_data (devc)) == MPU_ACK) ok = 1; } else { /* Device is not currently open. Use simplier method */ - if (read_data (devc->base) == MPU_ACK) + if (read_data (devc) == MPU_ACK) ok = 1; } if (!ok) { - RESTORE_INTR (flags); + restore_flags (flags); /* printk ("MPU: No ACK to command (0x%x)\n", (int) cmd->cmd); */ - return RET_ERROR (EIO); + return -EIO; } if (cmd->nr_args) for (i = 0; i < cmd->nr_args; i++) { - for (timeout = 3000; timeout > 0 && !output_ready (devc->base); timeout--); + for (timeout = 3000; timeout > 0 && !output_ready (devc); timeout--); if (!mpu401_out (dev, cmd->data[i])) { - RESTORE_INTR (flags); + restore_flags (flags); printk ("MPU: Command (0x%x), parm send failed.\n", (int) cmd->cmd); - return RET_ERROR (EIO); + return -EIO; } } @@ -677,27 +675,27 @@ { ok = 0; for (timeout = 5000; timeout > 0 && !ok; timeout--) - if (input_avail (devc->base)) + if (input_avail (devc)) { - cmd->data[i] = read_data (devc->base); + cmd->data[i] = read_data (devc); ok = 1; } if (!ok) { - RESTORE_INTR (flags); + restore_flags (flags); /* printk ("MPU: No response(%d) to command (0x%x)\n", i, (int) cmd->cmd); */ - return RET_ERROR (EIO); + return -EIO; } } - RESTORE_INTR (flags); + restore_flags (flags); return ret; } static int -exec_cmd (int dev, int cmd, int data) +mpu_cmd (int dev, int cmd, int data) { int ret; @@ -709,7 +707,9 @@ rec.data[0] = data & 0xff; if ((ret = mpu401_command (dev, &rec)) < 0) - return ret; + { + return ret; + } return (unsigned char) rec.data[0]; } @@ -723,8 +723,10 @@ if (status < 0xf0) { - if (exec_cmd (dev, 0xD0, 0) < 0) - return 0; + if (mpu_cmd (dev, 0xD0, 0) < 0) + { + return 0; + } return 1; } @@ -732,8 +734,10 @@ switch (status) { case 0xF0: - if (exec_cmd (dev, 0xDF, 0) < 0) - return 0; + if (mpu_cmd (dev, 0xDF, 0) < 0) + { + return 0; + } return 1; break; @@ -742,7 +746,6 @@ return 0; } - return 0; } static int @@ -758,7 +761,7 @@ } static int -mpu401_ioctl (int dev, unsigned cmd, unsigned arg) +mpu401_ioctl (int dev, unsigned cmd, ioctl_arg arg) { struct mpu_config *devc; @@ -767,17 +770,17 @@ switch (cmd) { case 1: - IOCTL_FROM_USER ((char *) &init_sequence, (char *) arg, 0, sizeof (init_sequence)); + memcpy_fromfs (((char *) init_sequence), &(((char *) arg)[0]), (sizeof (init_sequence))); return 0; break; case SNDCTL_MIDI_MPUMODE: - if (devc->version == 0) + if (!(devc->capabilities & MPU_CAP_INTLG)) /* No intelligent mode */ { printk ("MPU-401: Intelligent mode not supported by the HW\n"); - return RET_ERROR (EINVAL); + return -EINVAL; } - set_uart_mode (dev, devc, !IOCTL_IN (arg)); + set_uart_mode (dev, devc, !get_fs_long ((long *) arg)); return 0; break; @@ -786,18 +789,18 @@ int ret; mpu_command_rec rec; - IOCTL_FROM_USER ((char *) &rec, (char *) arg, 0, sizeof (rec)); + memcpy_fromfs (((char *) &rec), &(((char *) arg)[0]), (sizeof (rec))); if ((ret = mpu401_command (dev, &rec)) < 0) return ret; - IOCTL_TO_USER ((char *) arg, 0, (char *) &rec, sizeof (rec)); + memcpy_tofs (&(((char *) arg)[0]), ((char *) &rec), (sizeof (rec))); return 0; } break; default: - return RET_ERROR (EINVAL); + return -EINVAL; } } @@ -816,7 +819,7 @@ static int mpu_synth_ioctl (int dev, - unsigned int cmd, unsigned int arg) + unsigned int cmd, ioctl_arg arg) { int midi_dev; struct mpu_config *devc; @@ -824,7 +827,7 @@ midi_dev = synth_devs[dev]->midi_dev; if (midi_dev < 0 || midi_dev > num_midis) - return RET_ERROR (ENXIO); + return -ENXIO; devc = &dev_conf[midi_dev]; @@ -832,8 +835,7 @@ { case SNDCTL_SYNTH_INFO: - IOCTL_TO_USER ((char *) arg, 0, &mpu_synth_info[midi_dev], - sizeof (struct synth_info)); + memcpy_tofs (&(((char *) arg)[0]), (&mpu_synth_info[midi_dev]), (sizeof (struct synth_info))); return 0; break; @@ -843,7 +845,7 @@ break; default: - return RET_ERROR (EINVAL); + return -EINVAL; } } @@ -857,7 +859,7 @@ if (midi_dev < 0 || midi_dev > num_midis) { - return RET_ERROR (ENXIO); + return -ENXIO; } devc = &dev_conf[midi_dev]; @@ -871,10 +873,10 @@ if (!devc->initialized) { - if (mpu401_status (devc->base) == 0xff) /* Bus float */ + if (mpu401_status (devc) == 0xff) /* Bus float */ { printk ("MPU-401: Device not initialized properly\n"); - return RET_ERROR (EIO); + return -EIO; } reset_mpu401 (devc); } @@ -882,7 +884,7 @@ if (devc->opened) { printk ("MPU-401: Midi busy\n"); - return RET_ERROR (EBUSY); + return -EBUSY; } devc->mode = MODE_SYNTH; @@ -890,18 +892,11 @@ devc->inputintr = NULL; irq2dev[devc->irq] = midi_dev; - if (devc->shared_irq == 0) - if ((err = snd_set_irq_handler (devc->irq, mpuintr, midi_devs[midi_dev]->info.name) < 0)) - { - return err; - } if (midi_devs[midi_dev]->coproc) if ((err = midi_devs[midi_dev]->coproc-> open (midi_devs[midi_dev]->coproc->devc, COPR_MIDI)) < 0) { - if (devc->shared_irq == 0) - snd_release_irq (devc->irq); printk ("MPU-401: Can't access coprocessor device\n"); return err; @@ -912,8 +907,8 @@ if (mode & OPEN_READ) { - exec_cmd (midi_dev, 0x8B, 0); /* Enable data in stop mode */ - exec_cmd (midi_dev, 0x34, 0); /* Return timing bytes in stop mode */ + mpu_cmd (midi_dev, 0x8B, 0); /* Enable data in stop mode */ + mpu_cmd (midi_dev, 0x34, 0); /* Return timing bytes in stop mode */ } return 0; @@ -928,11 +923,9 @@ midi_dev = synth_devs[dev]->midi_dev; devc = &dev_conf[midi_dev]; - exec_cmd (midi_dev, 0x15, 0); /* Stop recording, playback and MIDI */ - exec_cmd (midi_dev, 0x8a, 0); /* Disable data in stopped mode */ + mpu_cmd (midi_dev, 0x15, 0); /* Stop recording, playback and MIDI */ + mpu_cmd (midi_dev, 0x8a, 0); /* Disable data in stopped mode */ - if (devc->shared_irq == 0) - snd_release_irq (devc->irq); devc->inputintr = NULL; if (midi_devs[midi_dev]->coproc) @@ -967,7 +960,8 @@ midi_synth_patchmgr, midi_synth_bender, NULL, /* alloc */ - midi_synth_setup_voice + midi_synth_setup_voice, + midi_synth_send_sysex }; static struct synth_operations mpu401_synth_operations[MAX_MIDI_DEV]; @@ -998,7 +992,7 @@ devc->version = devc->revision = 0; - if ((tmp = exec_cmd (num_midis, 0xAC, 0)) < 0) + if ((tmp = mpu_cmd (num_midis, 0xAC, 0)) < 0) return; if ((tmp & 0xf0) > 0x20) /* Why it's larger than 2.x ??? */ @@ -1006,7 +1000,7 @@ devc->version = tmp; - if ((tmp = exec_cmd (num_midis, 0xAD, 0)) < 0) + if ((tmp = mpu_cmd (num_midis, 0xAD, 0)) < 0) { devc->version = 0; return; @@ -1031,6 +1025,7 @@ devc = &dev_conf[num_midis]; devc->base = hw_config->io_base; + devc->osp = hw_config->osp; devc->irq = hw_config->irq; devc->opened = 0; devc->uart_mode = 0; @@ -1042,6 +1037,14 @@ devc->m_busy = 0; devc->m_state = ST_INIT; devc->shared_irq = hw_config->always_detect; + devc->irq = hw_config->irq; + + if (devc->irq < 0) + { + devc->irq *= -1; + devc->shared_irq = 1; + } + irq2dev[devc->irq] = num_midis; if (!hw_config->always_detect) { @@ -1049,14 +1052,28 @@ if (!reset_mpu401 (devc)) return mem_start; - DISABLE_INTR (flags); + if (!devc->shared_irq) + if (snd_set_irq_handler (devc->irq, mpuintr, "mpu401", devc->osp) < 0) + { + return mem_start; + } + + save_flags (flags); + cli (); mpu401_chk_version (devc); if (devc->version == 0) mpu401_chk_version (devc); - RESTORE_INTR (flags); + restore_flags (flags); } - if (devc->version == 0) + request_region (hw_config->io_base, 2, "mpu401"); + + if (devc->version != 0) + if (mpu_cmd (num_midis, 0xC5, 0) >= 0) /* Set timebase OK */ + if (mpu_cmd (num_midis, 0xE0, 120) >= 0) /* Set tempo OK */ + devc->capabilities |= MPU_CAP_INTLG; /* Supports intelligent mode */ + + if (!(devc->capabilities & MPU_CAP_INTLG)) /* No intelligent mode */ { memcpy ((char *) &mpu401_synth_operations[num_midis], (char *) &std_midi_synth, @@ -1064,7 +1081,6 @@ } else { - devc->capabilities |= MPU_CAP_INTLG; /* Supports intelligent mode */ memcpy ((char *) &mpu401_synth_operations[num_midis], (char *) &mpu401_synth_proto, sizeof (struct synth_operations)); @@ -1104,18 +1120,18 @@ { revision_char = devc->revision ? devc->revision + '@' : ' '; - if (devc->revision > ('Z' - '@')) + if ((int) devc->revision > ('Z' - '@')) revision_char = '+'; devc->capabilities |= MPU_CAP_SYNC | MPU_CAP_FSK; printk (" ", - (devc->version & 0xf0) >> 4, + (int) (devc->version & 0xf0) >> 4, devc->version & 0x0f, revision_char); sprintf (mpu_synth_info[num_midis].name, "MPU-401 %d.%d%c Midi interface #%d", - (devc->version & 0xf0) >> 4, + (int) (devc->version & 0xf0) >> 4, devc->version & 0x0f, revision_char, n_mpu_devs); @@ -1128,7 +1144,7 @@ mpu401_synth_operations[devc->devno].info = &mpu_synth_info[devc->devno]; - if (devc->capabilities & MPU_CAP_INTLG) /* Has timer */ + if (devc->capabilities & MPU_CAP_INTLG) /* Intelligent mode */ mpu_timer_init (num_midis); irq2dev[devc->irq] = num_midis; @@ -1156,11 +1172,11 @@ for (n = 0; n < 2 && !ok; n++) { for (timeout = timeout_limit; timeout > 0 && !ok; timeout--) - ok = output_ready (devc->base); + ok = output_ready (devc); - write_command (devc->base, MPU_RESET); /* - * Send MPU-401 RESET Command - */ + write_command (devc, MPU_RESET); /* + * Send MPU-401 RESET Command + */ /* * Wait at least 25 msec. This method is not accurate so let's make the @@ -1169,11 +1185,12 @@ for (timeout = timeout_limit * 2; timeout > 0 && !ok; timeout--) { - DISABLE_INTR (flags); - if (input_avail (devc->base)) - if (read_data (devc->base) == MPU_ACK) + save_flags (flags); + cli (); + if (input_avail (devc)) + if (read_data (devc) == MPU_ACK) ok = 1; - RESTORE_INTR (flags); + restore_flags (flags); } } @@ -1190,8 +1207,7 @@ static void set_uart_mode (int dev, struct mpu_config *devc, int arg) { - - if (!arg && devc->version == 0) + if (!arg && (devc->capabilities & MPU_CAP_INTLG)) { return; } @@ -1205,7 +1221,7 @@ if (arg) { - if (exec_cmd (dev, UART_MODE_ON, 0) < 0) + if (mpu_cmd (dev, UART_MODE_ON, 0) < 0) { printk ("MPU%d: Can't enter UART mode\n", devc->devno); devc->uart_mode = 0; @@ -1222,10 +1238,18 @@ int ok = 0; struct mpu_config tmp_devc; + if (check_region (hw_config->io_base, 2)) + { + printk ("\n\nmpu401.c: I/O port %x already in use\n\n", + hw_config->io_base); + return 0; + } + tmp_devc.base = hw_config->io_base; tmp_devc.irq = hw_config->irq; tmp_devc.initialized = 0; tmp_devc.opened = 0; + tmp_devc.osp = hw_config->osp; #if !defined(EXCLUDE_AEDSP16) && defined(AEDSP16_MPU401) /* @@ -1237,7 +1261,7 @@ if (hw_config->always_detect) return 1; - if (INB (hw_config->io_base + 1) == 0xff) + if (inb (hw_config->io_base + 1) == 0xff) return 0; /* Just bus float? */ ok = reset_mpu401 (&tmp_devc); @@ -1245,6 +1269,14 @@ return ok; } +void +unload_mpu401 (struct address_info *hw_config) +{ + release_region (hw_config->io_base, 2); + if (hw_config->always_detect == 0 && hw_config->irq > 0) + snd_release_irq (hw_config->irq); +} + /***************************************************** * Timer stuff ****************************************************/ @@ -1283,11 +1315,11 @@ val = 1000; hw_val = val; - hw_val = (hw_val + 23) / 24; + hw_val = (hw_val + 12) / 24; if (hw_val > max_timebase) hw_val = max_timebase; - if (exec_cmd (midi_dev, 0xC0 | (hw_val & 0x0f), 0) < 0) + if (mpu_cmd (midi_dev, 0xC0 | (hw_val & 0x0f), 0) < 0) { printk ("MPU: Can't set HW timebase to %d\n", hw_val * 24); return; @@ -1302,41 +1334,42 @@ { unsigned long flags; - DISABLE_INTR (flags); + save_flags (flags); + cli (); next_event_time = 0xffffffff; prev_event_time = 0; curr_ticks = curr_clocks = 0; - RESTORE_INTR (flags); + restore_flags (flags); } static void set_timer_mode (int midi_dev) { if (timer_mode & TMR_MODE_CLS) - exec_cmd (midi_dev, 0x3c, 0); /* Use CLS sync */ + mpu_cmd (midi_dev, 0x3c, 0); /* Use CLS sync */ else if (timer_mode & TMR_MODE_SMPTE) - exec_cmd (midi_dev, 0x3d, 0); /* Use SMPTE sync */ + mpu_cmd (midi_dev, 0x3d, 0); /* Use SMPTE sync */ if (timer_mode & TMR_INTERNAL) { - exec_cmd (midi_dev, 0x80, 0); /* Use MIDI sync */ + mpu_cmd (midi_dev, 0x80, 0); /* Use MIDI sync */ } else { if (timer_mode & (TMR_MODE_MIDI | TMR_MODE_CLS)) { - exec_cmd (midi_dev, 0x82, 0); /* Use MIDI sync */ - exec_cmd (midi_dev, 0x91, 0); /* Enable ext MIDI ctrl */ + mpu_cmd (midi_dev, 0x82, 0); /* Use MIDI sync */ + mpu_cmd (midi_dev, 0x91, 0); /* Enable ext MIDI ctrl */ } else if (timer_mode & TMR_MODE_FSK) - exec_cmd (midi_dev, 0x81, 0); /* Use FSK sync */ + mpu_cmd (midi_dev, 0x81, 0); /* Use FSK sync */ } } static void stop_metronome (int midi_dev) { - exec_cmd (midi_dev, 0x84, 0); /* Disable metronome */ + mpu_cmd (midi_dev, 0x84, 0); /* Disable metronome */ } static void @@ -1353,17 +1386,17 @@ beats_per_measure = (numerator * 4) >> denominator; if (!metronome_mode) - exec_cmd (midi_dev, 0x84, 0); /* Disable metronome */ + mpu_cmd (midi_dev, 0x84, 0); /* Disable metronome */ else { - exec_cmd (midi_dev, 0xE4, clks_per_click); - exec_cmd (midi_dev, 0xE6, beats_per_measure); - exec_cmd (midi_dev, 0x83, 0); /* Enable metronome without accents */ + mpu_cmd (midi_dev, 0xE4, clks_per_click); + mpu_cmd (midi_dev, 0xE6, beats_per_measure); + mpu_cmd (midi_dev, 0x83, 0); /* Enable metronome without accents */ } } static int -start_timer (int midi_dev) +mpu_start_timer (int midi_dev) { tmr_reset (); set_timer_mode (midi_dev); @@ -1373,16 +1406,16 @@ if (timer_mode & TMR_INTERNAL) { - exec_cmd (midi_dev, 0x02, 0); /* Send MIDI start */ + mpu_cmd (midi_dev, 0x02, 0); /* Send MIDI start */ tmr_running = 1; return TIMER_NOT_ARMED; } else { - exec_cmd (midi_dev, 0x35, 0); /* Enable mode messages to PC */ - exec_cmd (midi_dev, 0x38, 0); /* Enable sys common messages to PC */ - exec_cmd (midi_dev, 0x39, 0); /* Enable real time messages to PC */ - exec_cmd (midi_dev, 0x97, 0); /* Enable system exclusive messages to PC */ + mpu_cmd (midi_dev, 0x35, 0); /* Enable mode messages to PC */ + mpu_cmd (midi_dev, 0x38, 0); /* Enable sys common messages to PC */ + mpu_cmd (midi_dev, 0x39, 0); /* Enable real time messages to PC */ + mpu_cmd (midi_dev, 0x97, 0); /* Enable system exclusive messages to PC */ } return TIMER_ARMED; @@ -1394,19 +1427,19 @@ int midi_dev = sound_timer_devs[dev]->devlink; if (timer_open) - return RET_ERROR (EBUSY); + return -EBUSY; tmr_reset (); curr_tempo = 50; - exec_cmd (midi_dev, 0xE0, 50); + mpu_cmd (midi_dev, 0xE0, 50); curr_timebase = hw_timebase = 120; set_timebase (midi_dev, 120); timer_open = 1; metronome_mode = 0; set_timer_mode (midi_dev); - exec_cmd (midi_dev, 0xe7, 0x04); /* Send all clocks to host */ - exec_cmd (midi_dev, 0x95, 0); /* Enable clock to host */ + mpu_cmd (midi_dev, 0xe7, 0x04); /* Send all clocks to host */ + mpu_cmd (midi_dev, 0x95, 0); /* Enable clock to host */ return 0; } @@ -1417,9 +1450,9 @@ int midi_dev = sound_timer_devs[dev]->devlink; timer_open = tmr_running = 0; - exec_cmd (midi_dev, 0x15, 0); /* Stop all */ - exec_cmd (midi_dev, 0x94, 0); /* Disable clock to host */ - exec_cmd (midi_dev, 0x8c, 0); /* Disable measure end messages to host */ + mpu_cmd (midi_dev, 0x15, 0); /* Stop all */ + mpu_cmd (midi_dev, 0x94, 0); /* Disable clock to host */ + mpu_cmd (midi_dev, 0x8c, 0); /* Disable measure end messages to host */ stop_metronome (midi_dev); } @@ -1452,11 +1485,11 @@ case TMR_START: if (tmr_running) break; - return start_timer (midi_dev); + return mpu_start_timer (midi_dev); break; case TMR_STOP: - exec_cmd (midi_dev, 0x01, 0); /* Send MIDI stop */ + mpu_cmd (midi_dev, 0x01, 0); /* Send MIDI stop */ stop_metronome (midi_dev); tmr_running = 0; break; @@ -1464,7 +1497,7 @@ case TMR_CONTINUE: if (tmr_running) break; - exec_cmd (midi_dev, 0x03, 0); /* Send MIDI continue */ + mpu_cmd (midi_dev, 0x03, 0); /* Send MIDI continue */ setup_metronome (midi_dev); tmr_running = 1; break; @@ -1477,7 +1510,7 @@ if (parm > 250) parm = 250; - if (exec_cmd (midi_dev, 0xE0, parm) < 0) + if (mpu_cmd (midi_dev, 0xE0, parm) < 0) printk ("MPU: Can't set tempo to %d\n", (int) parm); curr_tempo = parm; } @@ -1512,7 +1545,7 @@ static int mpu_timer_ioctl (int dev, - unsigned int command, unsigned int arg) + unsigned int command, ioctl_arg arg) { int midi_dev = sound_timer_devs[dev]->devlink; @@ -1520,30 +1553,30 @@ { case SNDCTL_TMR_SOURCE: { - int parm = IOCTL_IN (arg) & timer_caps; + int parm = (int) get_fs_long ((long *) arg) & timer_caps; if (parm != 0) { timer_mode = parm; if (timer_mode & TMR_MODE_CLS) - exec_cmd (midi_dev, 0x3c, 0); /* Use CLS sync */ + mpu_cmd (midi_dev, 0x3c, 0); /* Use CLS sync */ else if (timer_mode & TMR_MODE_SMPTE) - exec_cmd (midi_dev, 0x3d, 0); /* Use SMPTE sync */ + mpu_cmd (midi_dev, 0x3d, 0); /* Use SMPTE sync */ } - return IOCTL_OUT (arg, timer_mode); + return snd_ioctl_return ((int *) arg, timer_mode); } break; case SNDCTL_TMR_START: - start_timer (midi_dev); + mpu_start_timer (midi_dev); return 0; break; case SNDCTL_TMR_STOP: tmr_running = 0; - exec_cmd (midi_dev, 0x01, 0); /* Send MIDI stop */ + mpu_cmd (midi_dev, 0x01, 0); /* Send MIDI stop */ stop_metronome (midi_dev); return 0; break; @@ -1552,24 +1585,24 @@ if (tmr_running) return 0; tmr_running = 1; - exec_cmd (midi_dev, 0x03, 0); /* Send MIDI continue */ + mpu_cmd (midi_dev, 0x03, 0); /* Send MIDI continue */ return 0; break; case SNDCTL_TMR_TIMEBASE: { - int val = IOCTL_IN (arg); + int val = (int) get_fs_long ((long *) arg); if (val) set_timebase (midi_dev, val); - return IOCTL_OUT (arg, curr_timebase); + return snd_ioctl_return ((int *) arg, curr_timebase); } break; case SNDCTL_TMR_TEMPO: { - int val = IOCTL_IN (arg); + int val = (int) get_fs_long ((long *) arg); int ret; if (val) @@ -1578,7 +1611,7 @@ val = 8; if (val > 250) val = 250; - if ((ret = exec_cmd (midi_dev, 0xE0, val)) < 0) + if ((ret = mpu_cmd (midi_dev, 0xE0, val)) < 0) { printk ("MPU: Can't set tempo to %d\n", (int) val); return ret; @@ -1587,27 +1620,27 @@ curr_tempo = val; } - return IOCTL_OUT (arg, curr_tempo); + return snd_ioctl_return ((int *) arg, curr_tempo); } break; case SNDCTL_SEQ_CTRLRATE: - if (IOCTL_IN (arg) != 0) /* Can't change */ - return RET_ERROR (EINVAL); + if (get_fs_long ((long *) arg) != 0) /* Can't change */ + return -EINVAL; - return IOCTL_OUT (arg, ((curr_tempo * curr_timebase) + 30) / 60); + return snd_ioctl_return ((int *) arg, ((curr_tempo * curr_timebase) + 30) / 60); break; case SNDCTL_TMR_METRONOME: - metronome_mode = IOCTL_IN (arg); + metronome_mode = (int) get_fs_long ((long *) arg); setup_metronome (midi_dev); return 0; break; - default: + default:; } - return RET_ERROR (EINVAL); + return -EINVAL; } static void @@ -1728,14 +1761,10 @@ mpu_timer.devlink = midi_dev; dev_conf[midi_dev].timer_flag = 1; -#if 1 if (num_sound_timers >= MAX_TIMER_DEV) n = 0; /* Overwrite the system timer */ else n = num_sound_timers++; -#else - n = 0; -#endif sound_timer_devs[n] = &mpu_timer; if (devc->version < 0x20) /* Original MPU-401 */ @@ -1756,10 +1785,6 @@ if (devc->revision & 0x02) timer_caps |= TMR_MODE_CLS; -#if 0 - if (devc->revision & 0x04) - timer_caps |= TMR_MODE_SMPTE; -#endif if (devc->revision & 0x40) max_timebase = 10; /* Has the 216 and 240 ppqn modes */ diff -u --recursive --new-file v1.3.33/linux/drivers/sound/opl3.c linux/drivers/sound/opl3.c --- v1.3.33/linux/drivers/sound/opl3.c Sun Aug 13 14:45:33 1995 +++ linux/drivers/sound/opl3.c Wed Oct 11 07:55:40 1995 @@ -41,17 +41,7 @@ #include "opl3.h" #define MAX_VOICE 18 -#define OFFS_4OP 11 /* - * * * Definitions for the operators OP3 and - * * OP4 * * begin here */ - -static int opl3_enabled = 0; -static int opl4_enabled = 0; -static int left_address = 0x388, right_address = 0x388, both_address = 0; - -static int nr_voices = 9; -static int logical_voices[MAX_VOICE] = -{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}; +#define OFFS_4OP 11 struct voice_info { @@ -60,78 +50,78 @@ long bender_range; unsigned long orig_freq; unsigned long current_freq; + int volume; int mode; }; -static struct voice_info voices[MAX_VOICE]; -static struct voice_alloc_info *voice_alloc; -static struct channel_info *chn_info; +typedef struct opl_devinfo + { + int left_io, right_io; + int nr_voice; + int lv_map[MAX_VOICE]; + + struct voice_info voc[MAX_VOICE]; + struct voice_alloc_info *v_alloc; + struct channel_info *chn_info; + + struct sbi_instrument i_map[SBFM_MAXINSTR]; + struct sbi_instrument *act_i[MAX_VOICE]; -static struct sbi_instrument *instrmap; -static struct sbi_instrument *active_instrument[MAX_VOICE] = -{NULL}; + struct synth_info fm_info; -static struct synth_info fm_info = -{"OPL-2", 0, SYNTH_TYPE_FM, FM_TYPE_ADLIB, 0, 9, 0, SBFM_MAXINSTR, 0}; + int busy; + int model; + unsigned char cmask; -static int already_initialized = 0; + int is_opl4; + sound_os_info *osp; + } +opl_devinfo; -static int opl3_ok = 0; -static int opl3_busy = 0; -static int fm_model = 0; /* +static struct opl_devinfo *devc = NULL; - * * * * 0=no fm, 1=mono, 2=SB Pro 1, 3=SB - * Pro 2 * * */ +static int detected_model; static int store_instr (int instr_no, struct sbi_instrument *instr); static void freq_to_fnum (int freq, int *block, int *fnum); static void opl3_command (int io_addr, unsigned int addr, unsigned int val); static int opl3_kill_note (int dev, int voice, int note, int velocity); -static unsigned char connection_mask = 0x00; void enable_opl3_mode (int left, int right, int both) { - if (opl3_enabled) - return; - - opl3_enabled = 1; - left_address = left; - right_address = right; - both_address = both; - fm_info.capabilities = SYNTH_CAP_OPL3; - fm_info.synth_subtype = FM_TYPE_OPL3; + /* NOP */ } static void enter_4op_mode (void) { int i; - static int voices_4op[MAX_VOICE] = + static int v4op[MAX_VOICE] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 15, 16, 17}; - connection_mask = 0x3f; /* Connect all possible 4 OP voices */ - opl3_command (right_address, CONNECTION_SELECT_REGISTER, 0x3f); + devc->cmask = 0x3f; /* Connect all possible 4 OP voice operators */ + opl3_command (devc->right_io, CONNECTION_SELECT_REGISTER, 0x3f); for (i = 0; i < 3; i++) - physical_voices[i].voice_mode = 4; + pv_map[i].voice_mode = 4; for (i = 3; i < 6; i++) - physical_voices[i].voice_mode = 0; + pv_map[i].voice_mode = 0; for (i = 9; i < 12; i++) - physical_voices[i].voice_mode = 4; + pv_map[i].voice_mode = 4; for (i = 12; i < 15; i++) - physical_voices[i].voice_mode = 0; + pv_map[i].voice_mode = 0; for (i = 0; i < 12; i++) - logical_voices[i] = voices_4op[i]; - voice_alloc->max_voice = nr_voices = 12; + devc->lv_map[i] = v4op[i]; + devc->v_alloc->max_voice = devc->nr_voice = 12; } static int opl3_ioctl (int dev, - unsigned int cmd, unsigned int arg) + unsigned int cmd, ioctl_arg arg) { switch (cmd) { @@ -140,12 +130,12 @@ { struct sbi_instrument ins; - IOCTL_FROM_USER ((char *) &ins, (char *) arg, 0, sizeof (ins)); + memcpy_fromfs (((char *) &ins), &(((char *) arg)[0]), (sizeof (ins))); if (ins.channel < 0 || ins.channel >= SBFM_MAXINSTR) { printk ("FM Error: Invalid instrument number %d\n", ins.channel); - return RET_ERROR (EINVAL); + return -EINVAL; } pmgr_inform (dev, PM_E_PATCH_LOADED, ins.channel, 0, 0, 0); @@ -154,9 +144,9 @@ break; case SNDCTL_SYNTH_INFO: - fm_info.nr_voices = (nr_voices == 12) ? 6 : nr_voices; + devc->fm_info.nr_voices = (devc->nr_voice == 12) ? 6 : devc->nr_voice; - IOCTL_TO_USER ((char *) arg, 0, &fm_info, sizeof (fm_info)); + memcpy_tofs (&(((char *) arg)[0]), (&devc->fm_info), (sizeof (devc->fm_info))); return 0; break; @@ -165,19 +155,19 @@ break; case SNDCTL_FM_4OP_ENABLE: - if (opl3_enabled) + if (devc->model == 2) enter_4op_mode (); return 0; break; default: - return RET_ERROR (EINVAL); + return -EINVAL; } } int -opl3_detect (int ioaddr) +opl3_detect (int ioaddr, sound_os_info * osp) { /* * This function returns 1 if the FM chicp is present at the given I/O port @@ -193,15 +183,10 @@ unsigned char stat1, stat2, signature; int i; - if (already_initialized) - { - return 0; /* - * Do avoid duplicate initializations - */ - } + if (devc != NULL) + return 0; - if (opl3_enabled) - ioaddr = left_address; + devc->osp = osp; /* Reset timers 1 and 2 */ opl3_command (ioaddr, TIMER_CONTROL_REGISTER, TIMER1_MASK | TIMER2_MASK); @@ -209,7 +194,7 @@ /* Reset the IRQ of the FM chip */ opl3_command (ioaddr, TIMER_CONTROL_REGISTER, IRQ_RESET); - signature = stat1 = INB (ioaddr); /* Status register */ + signature = stat1 = inb (ioaddr); /* Status register */ if ((stat1 & 0xE0) != 0x00) { @@ -232,7 +217,7 @@ for (i = 0; i < 50; i++) tenmicrosec (); - stat2 = INB (ioaddr); /* + stat2 = inb (ioaddr); /* * Read status after timers have expired */ @@ -258,18 +243,13 @@ if (signature == 0x06) /* OPL2 */ { - opl3_enabled = 0; + detected_model = 2; } else if (signature == 0x00) /* OPL3 or OPL4 */ { unsigned char tmp; - if (!opl3_enabled) /* Was not already enabled */ - { - left_address = ioaddr; - right_address = ioaddr + 2; - opl3_enabled = 1; - } + detected_model = 3; /* * Detect availability of OPL4 (_experimental_). Works propably @@ -277,14 +257,37 @@ * of the chip may not be connected to the PC bus at all. */ - opl3_command (right_address, OPL3_MODE_REGISTER, 0x00); - opl3_command (right_address, OPL3_MODE_REGISTER, OPL3_ENABLE | OPL4_ENABLE); + opl3_command (ioaddr + 2, OPL3_MODE_REGISTER, 0x00); + opl3_command (ioaddr + 2, OPL3_MODE_REGISTER, OPL3_ENABLE | OPL4_ENABLE); - if ((tmp = INB (ioaddr)) == 0x02) /* Have a OPL4 */ + if ((tmp = inb (ioaddr)) == 0x02) /* Have a OPL4 */ { - opl4_enabled = 1; + detected_model = 4; } - opl3_command (right_address, OPL3_MODE_REGISTER, 0); + + if (!check_region (ioaddr - 8, 2)) /* OPL4 port is free */ + { + int tmp; + + outb (0x02, ioaddr - 8); /* Select OPL4 ID register */ + tenmicrosec (); + tmp = inb (ioaddr - 7); /* Read it */ + tenmicrosec (); + + if (tmp == 0x20) /* OPL4 should return 0x20 here */ + { + detected_model = 4; + + outb (0xF8, ioaddr - 8); /* Select OPL4 FM mixer control */ + tenmicrosec (); + outb (0x1B, ioaddr - 7); /* Write value */ + tenmicrosec (); + } + else + detected_model = 3; + } + + opl3_command (ioaddr + 2, OPL3_MODE_REGISTER, 0); } @@ -306,28 +309,29 @@ { struct physical_voice_info *map; - if (voice < 0 || voice >= nr_voices) + if (voice < 0 || voice >= devc->nr_voice) return 0; - voice_alloc->map[voice] = 0; + devc->v_alloc->map[voice] = 0; - map = &physical_voices[logical_voices[voice]]; + map = &pv_map[devc->lv_map[voice]]; DEB (printk ("Kill note %d\n", voice)); if (map->voice_mode == 0) return 0; - opl3_command (map->ioaddr, KEYON_BLOCK + map->voice_num, voices[voice].keyon_byte & ~0x20); + opl3_command (map->ioaddr, KEYON_BLOCK + map->voice_num, devc->voc[voice].keyon_byte & ~0x20); - voices[voice].keyon_byte = 0; - voices[voice].bender = 0; - voices[voice].bender_range = 200; /* + devc->voc[voice].keyon_byte = 0; + devc->voc[voice].bender = 0; + devc->voc[voice].volume = 64; + devc->voc[voice].bender_range = 200; /* * 200 cents = 2 semitones */ - voices[voice].orig_freq = 0; - voices[voice].current_freq = 0; - voices[voice].mode = 0; + devc->voc[voice].orig_freq = 0; + devc->voc[voice].current_freq = 0; + devc->voc[voice].mode = 0; return 0; } @@ -344,9 +348,9 @@ store_instr (int instr_no, struct sbi_instrument *instr) { - if (instr->key != FM_PATCH && (instr->key != OPL3_PATCH || !opl3_enabled)) + if (instr->key != FM_PATCH && (instr->key != OPL3_PATCH || devc->model != 2)) printk ("FM warning: Invalid patch format field (key) 0x%x\n", instr->key); - memcpy ((char *) &(instrmap[instr_no]), (char *) instr, sizeof (*instr)); + memcpy ((char *) &(devc->i_map[instr_no]), (char *) instr, sizeof (*instr)); return 0; } @@ -354,13 +358,13 @@ static int opl3_set_instr (int dev, int voice, int instr_no) { - if (voice < 0 || voice >= nr_voices) + if (voice < 0 || voice >= devc->nr_voice) return 0; if (instr_no < 0 || instr_no >= SBFM_MAXINSTR) return 0; - active_instrument[voice] = &instrmap[instr_no]; + devc->act_i[voice] = &devc->i_map[instr_no]; return 0; } @@ -374,61 +378,33 @@ * it saves a lot of log() calculations. (RH) */ char fm_volume_table[128] = -{-64, -48, -40, -35, -32, -29, -27, -26, /* - * 0 - 7 - */ - -24, -23, -21, -20, -19, -18, -18, -17, /* - * 8 - 15 - */ - -16, -15, -15, -14, -13, -13, -12, -12, /* - * 16 - 23 - */ - -11, -11, -10, -10, -10, -9, -9, -8, /* - * 24 - 31 - */ - -8, -8, -7, -7, -7, -6, -6, -6, /* - * 32 - 39 - */ - -5, -5, -5, -5, -4, -4, -4, -4, /* - * 40 - 47 - */ - -3, -3, -3, -3, -2, -2, -2, -2, /* - * 48 - 55 - */ - -2, -1, -1, -1, -1, 0, 0, 0, /* - * 56 - 63 - */ - 0, 0, 0, 1, 1, 1, 1, 1, /* - * 64 - 71 - */ - 1, 2, 2, 2, 2, 2, 2, 2, /* - * 72 - 79 - */ - 3, 3, 3, 3, 3, 3, 3, 4, /* - * 80 - 87 - */ - 4, 4, 4, 4, 4, 4, 4, 5, /* - * 88 - 95 - */ - 5, 5, 5, 5, 5, 5, 5, 5, /* - * 96 - 103 - */ - 6, 6, 6, 6, 6, 6, 6, 6, /* - * 104 - 111 - */ - 6, 7, 7, 7, 7, 7, 7, 7, /* - * 112 - 119 - */ - 7, 7, 7, 8, 8, 8, 8, 8}; /* - - - * * * * 120 - 127 */ +{-64, -48, -40, -35, -32, -29, -27, -26, + -24, -23, -21, -20, -19, -18, -18, -17, + -16, -15, -15, -14, -13, -13, -12, -12, + -11, -11, -10, -10, -10, -9, -9, -8, + -8, -8, -7, -7, -7, -6, -6, -6, + -5, -5, -5, -5, -4, -4, -4, -4, + -3, -3, -3, -3, -2, -2, -2, -2, + -2, -1, -1, -1, -1, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 4, + 4, 4, 4, 4, 4, 4, 4, 5, + 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 8, 8, 8, 8, 8}; static void -calc_vol (unsigned char *regbyte, int volume) +calc_vol (unsigned char *regbyte, int volume, int main_vol) { int level = (~*regbyte & 0x3f); + if (main_vol > 127) + main_vol = 127; + + volume = (volume * main_vol) / 127; + if (level) level += fm_volume_table[volume]; @@ -441,58 +417,46 @@ } static void -set_voice_volume (int voice, int volume) +set_voice_volume (int voice, int volume, int main_vol) { unsigned char vol1, vol2, vol3, vol4; struct sbi_instrument *instr; struct physical_voice_info *map; - if (voice < 0 || voice >= nr_voices) + if (voice < 0 || voice >= devc->nr_voice) return; - map = &physical_voices[logical_voices[voice]]; + map = &pv_map[devc->lv_map[voice]]; - instr = active_instrument[voice]; + instr = devc->act_i[voice]; if (!instr) - instr = &instrmap[0]; + instr = &devc->i_map[0]; if (instr->channel < 0) return; - if (voices[voice].mode == 0) + if (devc->voc[voice].mode == 0) return; - if (voices[voice].mode == 2) - { /* - * 2 OP voice - */ + if (devc->voc[voice].mode == 2) + { vol1 = instr->operators[2]; vol2 = instr->operators[3]; if ((instr->operators[10] & 0x01)) - { /* - * Additive synthesis - */ - calc_vol (&vol1, volume); - calc_vol (&vol2, volume); + { + calc_vol (&vol1, volume, main_vol); + calc_vol (&vol2, volume, main_vol); } else - { /* - * FM synthesis - */ - calc_vol (&vol2, volume); + { + calc_vol (&vol2, volume, main_vol); } - opl3_command (map->ioaddr, KSL_LEVEL + map->op[0], vol1); /* - * Modulator - * volume - */ - opl3_command (map->ioaddr, KSL_LEVEL + map->op[1], vol2); /* - * Carrier - * volume - */ + opl3_command (map->ioaddr, KSL_LEVEL + map->op[0], vol1); + opl3_command (map->ioaddr, KSL_LEVEL + map->op[1], vol2); } else { /* @@ -506,7 +470,7 @@ vol4 = instr->operators[OFFS_4OP + 3]; /* - * The connection method for 4 OP voices is defined by the rightmost + * The connection method for 4 OP devc->voc is defined by the rightmost * bits at the offsets 10 and 10+OFFS_4OP */ @@ -515,30 +479,26 @@ switch (connection) { case 0: - calc_vol (&vol4, volume); /* - * Just the OP 4 is carrier - */ + calc_vol (&vol4, volume, main_vol); break; case 1: - calc_vol (&vol2, volume); - calc_vol (&vol4, volume); + calc_vol (&vol2, volume, main_vol); + calc_vol (&vol4, volume, main_vol); break; case 2: - calc_vol (&vol1, volume); - calc_vol (&vol4, volume); + calc_vol (&vol1, volume, main_vol); + calc_vol (&vol4, volume, main_vol); break; case 3: - calc_vol (&vol1, volume); - calc_vol (&vol3, volume); - calc_vol (&vol4, volume); + calc_vol (&vol1, volume, main_vol); + calc_vol (&vol3, volume, main_vol); + calc_vol (&vol4, volume, main_vol); break; - default: /* - * Why ?? - */ ; + default:; } opl3_command (map->ioaddr, KSL_LEVEL + map->op[0], vol1); @@ -556,10 +516,10 @@ struct sbi_instrument *instr; struct physical_voice_info *map; - if (voice < 0 || voice >= nr_voices) + if (voice < 0 || voice >= devc->nr_voice) return 0; - map = &physical_voices[logical_voices[voice]]; + map = &pv_map[devc->lv_map[voice]]; if (map->voice_mode == 0) return 0; @@ -568,7 +528,7 @@ * Just change the volume */ { - set_voice_volume (voice, volume); + set_voice_volume (voice, volume, devc->voc[voice].volume); return 0; } @@ -596,10 +556,10 @@ * off */ - instr = active_instrument[voice]; + instr = devc->act_i[voice]; if (!instr) - instr = &instrmap[0]; + instr = &devc->i_map[0]; if (instr->channel < 0) { @@ -620,7 +580,7 @@ { int voice_shift; - voice_shift = (map->ioaddr == left_address) ? 0 : 3; + voice_shift = (map->ioaddr == devc->left_io) ? 0 : 3; voice_shift += map->voice_num; if (instr->key != OPL3_PATCH) /* @@ -628,14 +588,14 @@ */ { voice_mode = 2; - connection_mask &= ~(1 << voice_shift); + devc->cmask &= ~(1 << voice_shift); } else { - connection_mask |= (1 << voice_shift); + devc->cmask |= (1 << voice_shift); } - opl3_command (right_address, CONNECTION_SELECT_REGISTER, connection_mask); + opl3_command (devc->right_io, CONNECTION_SELECT_REGISTER, devc->cmask); } /* @@ -715,19 +675,19 @@ opl3_command (map->ioaddr, FEEDBACK_CONNECTION + map->voice_num + 3, fpc); } - voices[voice].mode = voice_mode; + devc->voc[voice].mode = voice_mode; - set_voice_volume (voice, volume); + set_voice_volume (voice, volume, devc->voc[voice].volume); - freq = voices[voice].orig_freq = note_to_freq (note) / 1000; + freq = devc->voc[voice].orig_freq = note_to_freq (note) / 1000; /* * Since the pitch bender may have been set before playing the note, we * have to calculate the bending now. */ - freq = compute_finetune (voices[voice].orig_freq, voices[voice].bender, voices[voice].bender_range); - voices[voice].current_freq = freq; + freq = compute_finetune (devc->voc[voice].orig_freq, devc->voc[voice].bender, devc->voc[voice].bender_range); + devc->voc[voice].current_freq = freq; freq_to_fnum (freq, &block, &fnum); @@ -741,7 +701,7 @@ opl3_command (map->ioaddr, FNUM_LOW + map->voice_num, data); data = 0x20 | ((block & 0x7) << 2) | ((fnum >> 8) & 0x3); - voices[voice].keyon_byte = data; + devc->voc[voice].keyon_byte = data; opl3_command (map->ioaddr, KEYON_BLOCK + map->voice_num, data); if (voice_mode == 4) opl3_command (map->ioaddr, KEYON_BLOCK + map->voice_num + 3, data); @@ -801,23 +761,17 @@ * register. The OPL-3 survives with just two INBs */ - OUTB ((unsigned char) (addr & 0xff), io_addr); /* - * Select register - * - */ + outb ((unsigned char) (addr & 0xff), io_addr); - if (!opl3_enabled) + if (!devc->model != 2) tenmicrosec (); else for (i = 0; i < 2; i++) - INB (io_addr); + inb (io_addr); - OUTB ((unsigned char) (val & 0xff), io_addr + 1); /* - * Write to register - * - */ + outb ((unsigned char) (val & 0xff), io_addr + 1); - if (!opl3_enabled) + if (devc->model != 2) { tenmicrosec (); tenmicrosec (); @@ -825,7 +779,7 @@ } else for (i = 0; i < 2; i++) - INB (io_addr); + inb (io_addr); } static void @@ -833,35 +787,35 @@ { int i; - for (i = 0; i < nr_voices; i++) + for (i = 0; i < 18; i++) + devc->lv_map[i] = i; + + for (i = 0; i < devc->nr_voice; i++) { - opl3_command (physical_voices[logical_voices[i]].ioaddr, - KSL_LEVEL + physical_voices[logical_voices[i]].op[0], 0xff); + opl3_command (pv_map[devc->lv_map[i]].ioaddr, + KSL_LEVEL + pv_map[devc->lv_map[i]].op[0], 0xff); - opl3_command (physical_voices[logical_voices[i]].ioaddr, - KSL_LEVEL + physical_voices[logical_voices[i]].op[1], 0xff); + opl3_command (pv_map[devc->lv_map[i]].ioaddr, + KSL_LEVEL + pv_map[devc->lv_map[i]].op[1], 0xff); - if (physical_voices[logical_voices[i]].voice_mode == 4) + if (pv_map[devc->lv_map[i]].voice_mode == 4) { - opl3_command (physical_voices[logical_voices[i]].ioaddr, - KSL_LEVEL + physical_voices[logical_voices[i]].op[2], 0xff); + opl3_command (pv_map[devc->lv_map[i]].ioaddr, + KSL_LEVEL + pv_map[devc->lv_map[i]].op[2], 0xff); - opl3_command (physical_voices[logical_voices[i]].ioaddr, - KSL_LEVEL + physical_voices[logical_voices[i]].op[3], 0xff); + opl3_command (pv_map[devc->lv_map[i]].ioaddr, + KSL_LEVEL + pv_map[devc->lv_map[i]].op[3], 0xff); } opl3_kill_note (dev, i, 0, 64); } - if (opl3_enabled) + if (devc->model == 2) { - voice_alloc->max_voice = nr_voices = 18; + devc->v_alloc->max_voice = devc->nr_voice = 18; for (i = 0; i < 18; i++) - logical_voices[i] = i; - - for (i = 0; i < 18; i++) - physical_voices[i].voice_mode = 2; + pv_map[i].voice_mode = 2; } @@ -872,37 +826,35 @@ { int i; - if (!opl3_ok) - return RET_ERROR (ENXIO); - if (opl3_busy) - return RET_ERROR (EBUSY); - opl3_busy = 1; + if (devc->busy) + return -EBUSY; + devc->busy = 1; - voice_alloc->max_voice = nr_voices = opl3_enabled ? 18 : 9; - voice_alloc->timestamp = 0; + devc->v_alloc->max_voice = devc->nr_voice = (devc->model == 2) ? 18 : 9; + devc->v_alloc->timestamp = 0; for (i = 0; i < 18; i++) { - voice_alloc->map[i] = 0; - voice_alloc->alloc_times[i] = 0; + devc->v_alloc->map[i] = 0; + devc->v_alloc->alloc_times[i] = 0; } - connection_mask = 0x00; /* - * Just 2 OP voices + devc->cmask = 0x00; /* + * Just 2 OP mode */ - if (opl3_enabled) - opl3_command (right_address, CONNECTION_SELECT_REGISTER, connection_mask); + if (devc->model == 2) + opl3_command (devc->right_io, CONNECTION_SELECT_REGISTER, devc->cmask); return 0; } static void opl3_close (int dev) { - opl3_busy = 0; - voice_alloc->max_voice = nr_voices = opl3_enabled ? 18 : 9; + devc->busy = 0; + devc->v_alloc->max_voice = devc->nr_voice = (devc->model == 2) ? 18 : 9; - fm_info.nr_drums = 0; - fm_info.perc_mode = 0; + devc->fm_info.nr_drums = 0; + devc->fm_info.perc_mode = 0; opl3_reset (dev); } @@ -913,7 +865,7 @@ } static int -opl3_load_patch (int dev, int format, snd_rw_buf * addr, +opl3_load_patch (int dev, int format, const snd_rw_buf * addr, int offs, int count, int pmgr_flag) { struct sbi_instrument ins; @@ -921,15 +873,15 @@ if (count < sizeof (ins)) { printk ("FM Error: Patch record too short\n"); - return RET_ERROR (EINVAL); + return -EINVAL; } - COPY_FROM_USER (&((char *) &ins)[offs], (char *) addr, offs, sizeof (ins) - offs); + memcpy_fromfs ((&((char *) &ins)[offs]), &(((char *) addr)[offs]), (sizeof (ins) - offs)); if (ins.channel < 0 || ins.channel >= SBFM_MAXINSTR) { printk ("FM Error: Invalid instrument number %d\n", ins.channel); - return RET_ERROR (EINVAL); + return -EINVAL; } ins.key = format; @@ -959,10 +911,10 @@ struct sbi_instrument *instr; struct physical_voice_info *map; - if (voice < 0 || voice >= nr_voices) + if (voice < 0 || voice >= devc->nr_voice) return; - map = &physical_voices[logical_voices[voice]]; + map = &pv_map[devc->lv_map[voice]]; DEB (printk ("Aftertouch %d\n", voice)); @@ -973,12 +925,12 @@ * Adjust the amount of vibrato depending the pressure */ - instr = active_instrument[voice]; + instr = devc->act_i[voice]; if (!instr) - instr = &instrmap[0]; + instr = &devc->i_map[0]; - if (voices[voice].mode == 4) + if (devc->voc[voice].mode == 4) { int connection = ((instr->operators[10] & 0x01) << 1) | (instr->operators[10 + OFFS_4OP] & 0x01); @@ -1029,21 +981,21 @@ int block, fnum, freq; struct physical_voice_info *map; - map = &physical_voices[logical_voices[voice]]; + map = &pv_map[devc->lv_map[voice]]; if (map->voice_mode == 0) return; - voices[voice].bender = value; + devc->voc[voice].bender = value; if (!value) return; - if (!(voices[voice].keyon_byte & 0x20)) + if (!(devc->voc[voice].keyon_byte & 0x20)) return; /* * Not keyed on */ - freq = compute_finetune (voices[voice].orig_freq, voices[voice].bender, voices[voice].bender_range); - voices[voice].current_freq = freq; + freq = compute_finetune (devc->voc[voice].orig_freq, devc->voc[voice].bender, devc->voc[voice].bender_range); + devc->voc[voice].current_freq = freq; freq_to_fnum (freq, &block, &fnum); @@ -1060,14 +1012,14 @@ * of * f-num * */ - voices[voice].keyon_byte = data; + devc->voc[voice].keyon_byte = data; opl3_command (map->ioaddr, KEYON_BLOCK + map->voice_num, data); } static void opl3_controller (int dev, int voice, int ctrl_num, int value) { - if (voice < 0 || voice >= nr_voices) + if (voice < 0 || voice >= devc->nr_voice) return; switch (ctrl_num) @@ -1077,7 +1029,11 @@ break; case CTRL_PITCH_BENDER_RANGE: - voices[voice].bender_range = value; + devc->voc[voice].bender_range = value; + break; + + case CTL_MAIN_VOLUME: + devc->voc[voice].volume = value / 128; break; } } @@ -1085,13 +1041,13 @@ static int opl3_patchmgr (int dev, struct patmgr_info *rec) { - return RET_ERROR (EINVAL); + return -EINVAL; } static void opl3_bender (int dev, int voice, int value) { - if (voice < 0 || voice >= nr_voices) + if (voice < 0 || voice >= devc->nr_voice) return; bend_pitch (dev, voice, value - 8192); @@ -1100,7 +1056,7 @@ static int opl3_alloc_voice (int dev, int chn, int note, struct voice_alloc_info *alloc) { - int i, p, best, first, avail_voices, best_time = 0x7fffffff; + int i, p, best, first, avail, best_time = 0x7fffffff; struct sbi_instrument *instr; int is4op; int instr_no; @@ -1108,13 +1064,13 @@ if (chn < 0 || chn > 15) instr_no = 0; else - instr_no = chn_info[chn].pgm_num; + instr_no = devc->chn_info[chn].pgm_num; - instr = &instrmap[instr_no]; + instr = &devc->i_map[instr_no]; if (instr->channel < 0 || /* Instrument not loaded */ - nr_voices != 12) /* Not in 4 OP mode */ + devc->nr_voice != 12) /* Not in 4 OP mode */ is4op = 0; - else if (nr_voices == 12) /* 4 OP mode */ + else if (devc->nr_voice == 12) /* 4 OP mode */ is4op = (instr->key == OPL3_PATCH); else is4op = 0; @@ -1122,15 +1078,15 @@ if (is4op) { first = p = 0; - avail_voices = 6; + avail = 6; } else { - if (nr_voices == 12) /* 4 OP mode. Use the '2 OP only' voices first */ + if (devc->nr_voice == 12) /* 4 OP mode. Use the '2 OP only' operators first */ first = p = 6; else first = p = 0; - avail_voices = nr_voices; + avail = devc->nr_voice; } /* @@ -1138,7 +1094,7 @@ */ best = first; - for (i = 0; i < avail_voices; i++) + for (i = 0; i < avail; i++) { if (alloc->map[p] == 0) { @@ -1149,7 +1105,7 @@ best_time = alloc->alloc_times[p]; best = p; } - p = (p + 1) % avail_voices; + p = (p + 1) % avail; } /* @@ -1158,10 +1114,10 @@ if (best < 0) best = 0; - if (best > nr_voices) - best -= nr_voices; + if (best > devc->nr_voice) + best -= devc->nr_voice; - return best; /* All voices in use. Select the first one. */ + return best; /* All devc->voc in use. Select the first one. */ } static void @@ -1173,12 +1129,14 @@ opl3_set_instr (dev, voice, info->pgm_num); - voices[voice].bender = info->bender_value; + devc->voc[voice].bender = info->bender_value; + devc->voc[voice].volume = + info->controllers[CTL_MAIN_VOLUME]; } static struct synth_operations opl3_operations = { - &fm_info, + NULL, 0, SYNTH_TYPE_FM, FM_TYPE_ADLIB, @@ -1202,71 +1160,97 @@ }; long -opl3_init (long mem_start) +opl3_init (long mem_start, int ioaddr, sound_os_info * osp) { int i; - PERMANENT_MALLOC (struct sbi_instrument *, instrmap, - SBFM_MAXINSTR * sizeof (*instrmap), mem_start); - if (num_synths >= MAX_SYNTH_DEV) - printk ("OPL3 Error: Too many synthesizers\n"); + { + printk ("OPL3 Error: Too many synthesizers\n"); + return mem_start; + } + + + { + caddr_t ptr; + + ptr = sound_mem_blocks[sound_num_blocks] = kmalloc (sizeof (*devc), GFP_KERNEL); + if (sound_num_blocks < 1024) + sound_num_blocks++; + devc = (struct opl_devinfo *) ptr; + }; + + if (devc == NULL) + { + printk ("OPL3: Can't allocate memory for the device control structure\n"); + return mem_start; + } + + memset ((char *) devc, 0x00, sizeof (*devc)); + devc->osp = osp; + + devc->nr_voice = 9; + strcpy (devc->fm_info.name, "OPL2-"); + + devc->fm_info.device = 0; + devc->fm_info.synth_type = SYNTH_TYPE_FM; + devc->fm_info.synth_subtype = FM_TYPE_ADLIB; + devc->fm_info.perc_mode = 0; + devc->fm_info.nr_voices = 9; + devc->fm_info.nr_drums = 0; + devc->fm_info.instr_bank_size = SBFM_MAXINSTR; + devc->fm_info.capabilities = 0; + devc->left_io = ioaddr; + devc->right_io = ioaddr + 2; + + if (detected_model <= 2) + devc->model = 1; else { - synth_devs[num_synths++] = &opl3_operations; - voice_alloc = &opl3_operations.alloc; - chn_info = &opl3_operations.chn_info[0]; + devc->model = 2; + if (detected_model == 4) + devc->is_opl4 = 1; } - fm_model = 0; - opl3_ok = 1; - if (opl3_enabled) + opl3_operations.info = &devc->fm_info; + + synth_devs[num_synths++] = &opl3_operations; + devc->v_alloc = &opl3_operations.alloc; + devc->chn_info = &opl3_operations.chn_info[0]; + + if (devc->model == 2) { - if (opl4_enabled) + if (devc->is_opl4) printk (" "); else printk (" "); - fm_model = 2; - voice_alloc->max_voice = nr_voices = 18; - fm_info.nr_drums = 0; - fm_info.capabilities |= SYNTH_CAP_OPL3; - strcpy (fm_info.name, "Yamaha OPL-3"); + devc->v_alloc->max_voice = devc->nr_voice = 18; + devc->fm_info.nr_drums = 0; + devc->fm_info.capabilities |= SYNTH_CAP_OPL3; + strcpy (devc->fm_info.name, "Yamaha OPL-3"); for (i = 0; i < 18; i++) - if (physical_voices[i].ioaddr == USE_LEFT) - physical_voices[i].ioaddr = left_address; + if (pv_map[i].ioaddr == USE_LEFT) + pv_map[i].ioaddr = devc->left_io; else - physical_voices[i].ioaddr = right_address; - + pv_map[i].ioaddr = devc->right_io; - opl3_command (right_address, OPL3_MODE_REGISTER, OPL3_ENABLE); /* - * Enable - * OPL-3 - * mode - */ - opl3_command (right_address, CONNECTION_SELECT_REGISTER, 0x00); /* - * Select - * all - * 2-OP - * * - * voices - */ + opl3_command (devc->right_io, OPL3_MODE_REGISTER, OPL3_ENABLE); + opl3_command (devc->right_io, CONNECTION_SELECT_REGISTER, 0x00); } else { printk (" "); - fm_model = 1; - voice_alloc->max_voice = nr_voices = 9; - fm_info.nr_drums = 0; + devc->v_alloc->max_voice = devc->nr_voice = 9; + devc->fm_info.nr_drums = 0; for (i = 0; i < 18; i++) - physical_voices[i].ioaddr = left_address; + pv_map[i].ioaddr = devc->left_io; }; - already_initialized = 1; for (i = 0; i < SBFM_MAXINSTR; i++) - instrmap[i].channel = -1; + devc->i_map[i].channel = -1; return mem_start; } diff -u --recursive --new-file v1.3.33/linux/drivers/sound/opl3.h linux/drivers/sound/opl3.h --- v1.3.33/linux/drivers/sound/opl3.h Tue Jul 11 10:02:53 1995 +++ linux/drivers/sound/opl3.h Wed Oct 11 07:55:36 1995 @@ -102,12 +102,12 @@ * * AM/VIB/EG/KSR/Multiple (0x20 to 0x35) */ - #define AM_VIB 0x20 - #define TREMOLO_ON 0x80 - #define VIBRATO_ON 0x40 - #define SUSTAIN_ON 0x20 - #define KSR 0x10 /* Key scaling rate */ - #define MULTIPLE_MASK 0x0f /* Frequency multiplier */ +#define AM_VIB 0x20 +#define TREMOLO_ON 0x80 +#define VIBRATO_ON 0x40 +#define SUSTAIN_ON 0x20 +#define KSR 0x10 /* Key scaling rate */ +#define MULTIPLE_MASK 0x0f /* Frequency multiplier */ /* * KSL/Total level (0x40 to 0x55) @@ -231,7 +231,7 @@ #define USE_LEFT 0 #define USE_RIGHT 1 -static struct physical_voice_info physical_voices[18] = +static struct physical_voice_info pv_map[18] = { /* No Mode Side OP1 OP2 OP3 OP4 */ /* --------------------------------------------------- */ diff -u --recursive --new-file v1.3.33/linux/drivers/sound/os.h linux/drivers/sound/os.h --- v1.3.33/linux/drivers/sound/os.h Wed Sep 13 12:45:31 1995 +++ linux/drivers/sound/os.h Wed Oct 11 13:15:59 1995 @@ -1,32 +1,6 @@ -/* - * OS Specific settings for Linux - * - * Copyright by Hannu Savolainen 1993 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ #define ALLOW_SELECT +#define ALLOW_BUFFER_MAPPING #ifdef MODULE #include @@ -51,136 +25,30 @@ #include #include #include +#include #include typedef char snd_rw_buf; +typedef caddr_t ioctl_arg; #define FALSE 0 #define TRUE 1 -#define COPY_FROM_USER(d, s, o, c) memcpy_fromfs((d), &((s)[o]), (c)) -#define COPY_TO_USER(d, o, s, c) memcpy_tofs(&((d)[o]), (s), (c)) -#define IOCTL_FROM_USER(d, s, o, c) memcpy_fromfs((d), &((s)[o]), (c)) -#define IOCTL_TO_USER(d, o, s, c) memcpy_tofs(&((d)[o]), (s), (c)) - -#define GET_BYTE_FROM_USER(target, addr, offs) target = get_fs_byte(&((addr)[offs])) -#define GET_SHORT_FROM_USER(target, addr, offs) target = get_fs_word(&((addr)[offs])) -#define GET_WORD_FROM_USER(target, addr, offs) target = get_fs_long((long*)&((addr)[offs])) -#define PUT_WORD_TO_USER(addr, offs, data) put_fs_long(data, (long*)&((addr)[offs])) -#define IOCTL_IN(arg) get_fs_long((long *)(arg)) -#define IOCTL_OUT(arg, ret) snd_ioctl_return((int *)arg, ret) - struct snd_wait { int mode; int aborting; }; -#define DEFINE_WAIT_QUEUE(name, flag) static struct wait_queue *name = NULL; \ - static volatile struct snd_wait flag = {0} -#define DEFINE_WAIT_QUEUES(name, flag) static struct wait_queue *name = {NULL}; \ - static volatile struct snd_wait flag = {{0}} -#define RESET_WAIT_QUEUE(q, f) {f.aborting = 0;f.mode = WK_NONE;} -#define PROCESS_ABORTING(q, f) (/*f.aborting | */(current->signal & ~current->blocked)) -#define SET_ABORT_FLAG(q, f) f.aborting = 1 -#define TIMED_OUT(q, f) (f.mode & WK_TIMEOUT) -#define DO_SLEEP(q, f, time_limit) \ - { unsigned long tl;\ - if (time_limit) tl = current->timeout = jiffies + (time_limit); \ - else tl = 0xffffffff; \ - f.mode = WK_SLEEP;interruptible_sleep_on(&q); \ - if (!(f.mode & WK_WAKEUP)) \ - { \ - if (current->signal & ~current->blocked) \ - f.aborting = 1; \ - else \ - if (jiffies >= tl) f.mode |= WK_TIMEOUT; \ - } \ - f.mode &= ~WK_SLEEP; \ - } -#define SOMEONE_WAITING(q, f) (f.mode & WK_SLEEP) -#define WAKE_UP(q, f) {f.mode = WK_WAKEUP;wake_up(&q);} - -#define ALLOC_DMA_CHN(chn,deviceID) request_dma(chn, deviceID) -#define RELEASE_DMA_CHN(chn) free_dma(chn) - -#define GET_TIME() jiffies -#define RELEASE_IRQ free_irq -#define RET_ERROR(err) -err - -/* DISABLE_INTR is used to disable interrupts. - These macros store the current flags to the (unsigned long) variable given - as a parameter. RESTORE_INTR returns the interrupt ebable bit to state - before DISABLE_INTR or ENABLE_INTR */ - -#define DISABLE_INTR(flags) __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags)); -#define RESTORE_INTR(flags) __asm__ __volatile__("pushl %0 ; popfl": \ - :"r" (flags)); -/* - KERNEL_MALLOC() allocates requested number of memory and - KERNEL_FREE is used to free it. - These macros are never called from interrupt, in addition the - nbytes will never be more than 4096 bytes. Generally the driver - will allocate memory in blocks of 4k. If the kernel has just a - page level memory allocation, 4K can be safely used as the size - (the nbytes parameter can be ignored). -*/ -#define KERNEL_MALLOC(nbytes) kmalloc(nbytes, GFP_KERNEL) -#define KERNEL_FREE(addr) kfree(addr) - -/* - * The macro PERMANENT_MALLOC(typecast, mem_ptr, size, linux_ptr) - * returns size bytes of - * (kernel virtual) memory which will never get freed by the driver. - * This macro is called only during boot. The linux_ptr is a linux specific - * parameter which should be ignored in other operating systems. - * The mem_ptr is a pointer variable where the macro assigns pointer to the - * memory area. The type is the type of the mem_ptr. - */ -#define PERMANENT_MALLOC(typecast, mem_ptr, size, linux_ptr) \ - {mem_ptr = (typecast)linux_ptr; \ - linux_ptr += (size);} - -/* - * The macro DEFINE_TIMER defines variables for the ACTIVATE_TIMER if - * required. The name is the variable/name to be used and the proc is - * the procedure to be called when the timer expires. - */ - -#define DEFINE_TIMER(name, proc) \ - static struct timer_list name = \ - {NULL, NULL, 0, 0, proc} - -/* - * The ACTIVATE_TIMER requests system to call 'proc' after 'time' ticks. - */ - -#define ACTIVATE_TIMER(name, proc, time) \ - {name.expires = (time)+jiffies; \ - add_timer (&name);} - -#define INB inb -#define INW inw -#define OUTB outb -#define OUTW outw - -/* - * SND_SA_INTERRUPT is required. Otherwise the IRQ number is not passed - * the handler. - */ +extern int sound_alloc_dma(int chn, char *deviceID); +extern int sound_open_dma(int chn, char *deviceID); +extern void sound_free_dma(int chn); +extern void sound_close_dma(int chn); + +#define RUNTIME_DMA_ALLOC + +extern caddr_t sound_mem_blocks[1024]; +extern int sound_num_blocks; + #define SND_SA_INTERRUPT -/* - * The macro DECLARE_FILE() adds an entry to struct fileinfo referencing the - * connected filestructure. - * This entry must be initialized in sound_open() in soundcard.c - * - * ISSET_FILE_FLAG() allows checking of flags like O_NONBLOCK on files - * - */ - -#define DECLARE_FILE() struct file *filp -#define ISSET_FILE_FLAG(fileinfo, flag) (fileinfo->filp->f_flags & (flag) ? \ - 1 : 0) -#define INT_HANDLER_PROTO() void(*hndlr)(int, struct pt_regs *) -#define INT_HANDLER_PARMS(irq, parms) int irq, struct pt_regs *parms -#define INT_HANDLER_CALL(irq) irq, NULL +typedef int sound_os_info; diff -u --recursive --new-file v1.3.33/linux/drivers/sound/pas.h linux/drivers/sound/pas.h --- v1.3.33/linux/drivers/sound/pas.h Tue Jul 11 10:02:53 1995 +++ linux/drivers/sound/pas.h Wed Oct 11 07:55:36 1995 @@ -45,91 +45,74 @@ #define CHIP_REV 0xFF88 /* R 0=PAS, 1=PAS+, 2=CDPC, 3=PAS16C, 4=PAS16D */ #define SYSTEM_CONFIGURATION_1 0x8388 /* R W Control */ - #define S_C_1_PCS_ENABLE 0x01 /* R W PC speaker 1=enable, 0=disable PC speaker emulation */ - #define S_C_1_PCM_CLOCK_SELECT 0x02 /* R W PCM 1=14.31818Mhz/12, 0=28.224Mhz master clock */ - #define S_C_1_FM_EMULATE_CLOCK 0x04 /* R W FM 1=use 28.224Mhz/2, 0=use 14.31818Mhz clock */ - #define S_C_1_PCS_STEREO 0x10 /* R W PC speaker 1=enable PC speaker stereo effect, 0=disable */ - #define S_C_1_PCS_REALSOUND 0x20 /* R W PC speaker 1=enable RealSound enhancement, 0=disable */ - #define S_C_1_FORCE_EXT_RESET 0x40 /* R W Control Force external reset */ - #define S_C_1_FORCE_INT_RESET 0x80 /* R W Control Force internal reset */ +# define S_C_1_PCS_ENABLE 0x01 /* R W PC speaker 1=enable, 0=disable PC speaker emulation */ +# define S_C_1_PCM_CLOCK_SELECT 0x02 /* R W PCM 1=14.31818Mhz/12, 0=28.224Mhz master clock */ +# define S_C_1_FM_EMULATE_CLOCK 0x04 /* R W FM 1=use 28.224Mhz/2, 0=use 14.31818Mhz clock */ +# define S_C_1_PCS_STEREO 0x10 /* R W PC speaker 1=enable PC speaker stereo effect, 0=disable */ +# define S_C_1_PCS_REALSOUND 0x20 /* R W PC speaker 1=enable RealSound enhancement, 0=disable */ +# define S_C_1_FORCE_EXT_RESET 0x40 /* R W Control Force external reset */ +# define S_C_1_FORCE_INT_RESET 0x80 /* R W Control Force internal reset */ #define SYSTEM_CONFIGURATION_2 0x8389 /* R W Control */ - #define S_C_2_PCM_OVERSAMPLING 0x03 /* R W PCM 00=0x, 01=2x, 10=4x, 11=reserved */ - #define S_C_2_PCM_16_BIT 0x04 /* R W PCM 1=16-bit, 0=8-bit samples */ +# define S_C_2_PCM_OVERSAMPLING 0x03 /* R W PCM 00=0x, 01=2x, 10=4x, 11=reserved */ +# define S_C_2_PCM_16_BIT 0x04 /* R W PCM 1=16-bit, 0=8-bit samples */ #define SYSTEM_CONFIGURATION_3 0x838A /* R W Control */ - #define S_C_3_PCM_CLOCK_SELECT 0x02 /* R W PCM 1=use 1.008Mhz clock for PCM, 0=don't */ +# define S_C_3_PCM_CLOCK_SELECT 0x02 /* R W PCM 1=use 1.008Mhz clock for PCM, 0=don't */ #define SYSTEM_CONFIGURATION_4 0x838B /* R W Control CD-ROM interface controls */ #define IO_CONFIGURATION_1 0xF388 /* R W Control */ - #define I_C_1_BOOT_RESET_ENABLE 0x80 /* R W Control 1=reset board on warm boot, 0=don't */ - #define I_C_1_JOYSTICK_ENABLE 0x40 /* R W Control 1=enable joystick port, 0=don't */ +# define I_C_1_BOOT_RESET_ENABLE 0x80 /* R W Control 1=reset board on warm boot, 0=don't */ +# define I_C_1_JOYSTICK_ENABLE 0x40 /* R W Control 1=enable joystick port, 0=don't */ #define IO_CONFIGURATION_2 0xF389 /* R W Control */ - #define I_C_2_PCM_DMA_DISABLED 0x00 /* R W PCM PCM DMA disabled */ +# define I_C_2_PCM_DMA_DISABLED 0x00 /* R W PCM PCM DMA disabled */ #define IO_CONFIGURATION_3 0xF38A /* R W Control */ - #define I_C_3_PCM_IRQ_DISABLED 0x00 /* R W PCM PCM IRQ disabled */ +# define I_C_3_PCM_IRQ_DISABLED 0x00 /* R W PCM PCM IRQ disabled */ #define COMPATIBILITY_ENABLE 0xF788 /* R W Control */ - #define C_E_MPU401_ENABLE 0x01 /* R W MIDI 1=enable, 0=disable MPU401 MIDI emulation */ - #define C_E_SB_ENABLE 0x02 /* R W PCM 1=enable, 0=disable Sound Blaster emulation */ - #define C_E_SB_ACTIVE 0x04 /* R PCM "Sound Blaster Interrupt active" */ - #define C_E_MPU401_ACTIVE 0x08 /* R MIDI "MPU UART mode active" */ - #define C_E_PCM_COMPRESSION 0x10 /* R W PCM 1=enable, 0=disabled compression */ +# define C_E_MPU401_ENABLE 0x01 /* R W MIDI 1=enable, 0=disable MPU401 MIDI emulation */ +# define C_E_SB_ENABLE 0x02 /* R W PCM 1=enable, 0=disable Sound Blaster emulation */ +# define C_E_SB_ACTIVE 0x04 /* R PCM "Sound Blaster Interrupt active" */ +# define C_E_MPU401_ACTIVE 0x08 /* R MIDI "MPU UART mode active" */ +# define C_E_PCM_COMPRESSION 0x10 /* R W PCM 1=enable, 0=disabled compression */ #define EMULATION_ADDRESS 0xF789 /* R W Control */ - #define E_A_SB_BASE 0x0f /* R W PCM bits A4-A7 for SB base port */ - #define E_A_MPU401_BASE 0xf0 /* R W MIDI bits A4-A7 for MPU401 base port */ +# define E_A_SB_BASE 0x0f /* R W PCM bits A4-A7 for SB base port */ +# define E_A_MPU401_BASE 0xf0 /* R W MIDI bits A4-A7 for MPU401 base port */ #define EMULATION_CONFIGURATION 0xFB8A /* R W ***** Only valid on newer PAS2 cards (?) ***** */ - #define E_C_MPU401_IRQ 0x07 /* R W MIDI MPU401 emulation IRQ */ - #define E_C_SB_IRQ 0x38 /* R W PCM SB emulation IRQ */ - #define E_C_SB_DMA 0xC0 /* R W PCM SB emulation DMA */ +# define E_C_MPU401_IRQ 0x07 /* R W MIDI MPU401 emulation IRQ */ +# define E_C_SB_IRQ 0x38 /* R W PCM SB emulation IRQ */ +# define E_C_SB_DMA 0xC0 /* R W PCM SB emulation DMA */ #define OPERATION_MODE_1 0xEF8B /* R Control */ - #define O_M_1_CDROM_TYPE 0x03 /* R CD-ROM 3=SCSI, 2=Sony, 0=no CD-ROM interface */ - #define O_M_1_FM_TYPE 0x04 /* R FM 1=sterero, 0=mono FM chip */ - #define O_M_1_PCM_TYPE 0x08 /* R PCM 1=16-bit Codec, 0=8-bit DAC */ +# define O_M_1_CDROM_TYPE 0x03 /* R CD-ROM 3=SCSI, 2=Sony, 0=no CD-ROM interface */ +# define O_M_1_FM_TYPE 0x04 /* R FM 1=sterero, 0=mono FM chip */ +# define O_M_1_PCM_TYPE 0x08 /* R PCM 1=16-bit Codec, 0=8-bit DAC */ #define OPERATION_MODE_2 0xFF8B /* R Control */ - #define O_M_2_PCS_ENABLED 0x02 /* R PC speaker PC speaker emulation 1=enabled, 0=disabled */ - #define O_M_2_BUS_TIMING 0x10 /* R Control 1=AT bus timing, 0=XT bus timing */ - #define O_M_2_BOARD_REVISION 0xe0 /* R Control Board revision */ +# define O_M_2_PCS_ENABLED 0x02 /* R PC speaker PC speaker emulation 1=enabled, 0=disabled */ +# define O_M_2_BUS_TIMING 0x10 /* R Control 1=AT bus timing, 0=XT bus timing */ +# define O_M_2_BOARD_REVISION 0xe0 /* R Control Board revision */ #define INTERRUPT_MASK 0x0B8B /* R W Control */ - #define I_M_FM_LEFT_IRQ_ENABLE 0x01 /* R W FM Enable FM left interrupt */ - #define I_M_FM_RIGHT_IRQ_ENABLE 0x02 /* R W FM Enable FM right interrupt */ - #define I_M_PCM_RATE_IRQ_ENABLE 0x04 /* R W PCM Enable Sample Rate interrupt */ - #define I_M_PCM_BUFFER_IRQ_ENABLE 0x08 /* R W PCM Enable Sample Buffer interrupt */ - #define I_M_MIDI_IRQ_ENABLE 0x10 /* R W MIDI Enable MIDI interrupt */ - #define I_M_BOARD_REV 0xE0 /* R Control Board revision */ +# define I_M_FM_LEFT_IRQ_ENABLE 0x01 /* R W FM Enable FM left interrupt */ +# define I_M_FM_RIGHT_IRQ_ENABLE 0x02 /* R W FM Enable FM right interrupt */ +# define I_M_PCM_RATE_IRQ_ENABLE 0x04 /* R W PCM Enable Sample Rate interrupt */ +# define I_M_PCM_BUFFER_IRQ_ENABLE 0x08 /* R W PCM Enable Sample Buffer interrupt */ +# define I_M_MIDI_IRQ_ENABLE 0x10 /* R W MIDI Enable MIDI interrupt */ +# define I_M_BOARD_REV 0xE0 /* R Control Board revision */ #define INTERRUPT_STATUS 0x0B89 /* R W Control */ - #define I_S_FM_LEFT_IRQ 0x01 /* R W FM Left FM Interrupt Pending */ - #define I_S_FM_RIGHT_IRQ 0x02 /* R W FM Right FM Interrupt Pending */ - #define I_S_PCM_SAMPLE_RATE_IRQ 0x04 /* R W PCM Sample Rate Interrupt Pending */ - #define I_S_PCM_SAMPLE_BUFFER_IRQ 0x08 /* R W PCM Sample Buffer Interrupt Pending */ - #define I_S_MIDI_IRQ 0x10 /* R W MIDI MIDI Interrupt Pending */ - #define I_S_PCM_CHANNEL 0x20 /* R W PCM 1=right, 0=left */ - #define I_S_RESET_ACTIVE 0x40 /* R W Control Reset is active (Timed pulse not finished) */ - #define I_S_PCM_CLIPPING 0x80 /* R W PCM Clipping has occurred */ +# define I_S_FM_LEFT_IRQ 0x01 /* R W FM Left FM Interrupt Pending */ +# define I_S_FM_RIGHT_IRQ 0x02 /* R W FM Right FM Interrupt Pending */ +# define I_S_PCM_SAMPLE_RATE_IRQ 0x04 /* R W PCM Sample Rate Interrupt Pending */ +# define I_S_PCM_SAMPLE_BUFFER_IRQ 0x08 /* R W PCM Sample Buffer Interrupt Pending */ +# define I_S_MIDI_IRQ 0x10 /* R W MIDI MIDI Interrupt Pending */ +# define I_S_PCM_CHANNEL 0x20 /* R W PCM 1=right, 0=left */ +# define I_S_RESET_ACTIVE 0x40 /* R W Control Reset is active (Timed pulse not finished) */ +# define I_S_PCM_CLIPPING 0x80 /* R W PCM Clipping has occurred */ #define FILTER_FREQUENCY 0x0B8A /* R W Control */ - #define F_F_FILTER_DISABLED 0x00 /* R W Mixer No filter */ -#if 0 - struct { /* R W Mixer Filter translation */ - unsigned int freq:24; - unsigned int value:8; - } F_F_FILTER_translate[] = - { { 73500, 0x01 }, /* 73500Hz - divide by 16 */ - { 65333, 0x02 }, /* 65333Hz - divide by 18 */ - { 49000, 0x09 }, /* 49000Hz - divide by 24 */ - { 36750, 0x11 }, /* 36750Hz - divide by 32 */ - { 24500, 0x19 }, /* 24500Hz - divide by 48 */ - { 18375, 0x07 }, /* 18375Hz - divide by 64 */ - { 12783, 0x0f }, /* 12783Hz - divide by 92 */ - { 12250, 0x04 }, /* 12250Hz - divide by 96 */ - { 9188, 0x17 }, /* 9188Hz - divide by 128 */ - { 6125, 0x1f }, /* 6125Hz - divide by 192 */ - }; -#endif - #define F_F_MIXER_UNMUTE 0x20 /* R W Mixer 1=disable, 0=enable board mute */ - #define F_F_PCM_RATE_COUNTER 0x40 /* R W PCM 1=enable, 0=disable sample rate counter */ - #define F_F_PCM_BUFFER_COUNTER 0x80 /* R W PCM 1=enable, 0=disable sample buffer counter */ +# define F_F_FILTER_DISABLED 0x00 /* R W Mixer No filter */ +# define F_F_MIXER_UNMUTE 0x20 /* R W Mixer 1=disable, 0=enable board mute */ +# define F_F_PCM_RATE_COUNTER 0x40 /* R W PCM 1=enable, 0=disable sample rate counter */ +# define F_F_PCM_BUFFER_COUNTER 0x80 /* R W PCM 1=enable, 0=disable sample buffer counter */ #define PAS_NONE 0 #define PAS_PLUS 1 @@ -160,93 +143,93 @@ #endif #define PARALLEL_MIXER 0x078B /* W Mixer Documented for MVD101 as FM Mono Right decode?? */ - #define P_M_MV508_ADDRESS 0x80 /* W Mixer MVD508 Address/mixer select */ - #define P_M_MV508_DATA 0x00 - #define P_M_MV508_LEFT 0x20 /* W Mixer MVD508 Left channel select */ - #define P_M_MV508_RIGHT 0x40 /* W Mixer MVD508 Right channel select */ - #define P_M_MV508_BOTH 0x00 /* W Mixer MVD508 Both channel select */ - #define P_M_MV508_MIXER 0x10 /* W Mixer MVD508 Select a mixer (rather than a volume) */ - #define P_M_MV508_VOLUME 0x00 - - #define P_M_MV508_INPUTMIX 0x20 /* W Mixer MVD508 Select mixer A */ - #define P_M_MV508_OUTPUTMIX 0x00 /* W Mixer MVD508 Select mixer B */ - - #define P_M_MV508_MASTER_A 0x01 /* W Mixer MVD508 Master volume control A (output) */ - #define P_M_MV508_MASTER_B 0x02 /* W Mixer MVD508 Master volume control B (DSP input) */ - #define P_M_MV508_BASS 0x03 /* W Mixer MVD508 Bass control */ - #define P_M_MV508_TREBLE 0x04 /* W Mixer MVD508 Treble control */ - #define P_M_MV508_MODE 0x05 /* W Mixer MVD508 Master mode control */ - - #define P_M_MV508_LOUDNESS 0x04 /* W Mixer MVD508 Mode control - Loudness filter */ - #define P_M_MV508_ENHANCE_BITS 0x03 - #define P_M_MV508_ENHANCE_NONE 0x00 /* W Mixer MVD508 Mode control - No stereo enhancement */ - #define P_M_MV508_ENHANCE_40 0x01 /* W Mixer MVD508 Mode control - 40% stereo enhancement */ - #define P_M_MV508_ENHANCE_60 0x02 /* W Mixer MVD508 Mode control - 60% stereo enhancement */ - #define P_M_MV508_ENHANCE_80 0x03 /* W Mixer MVD508 Mode control - 80% stereo enhancement */ - - #define P_M_MV508_FM 0x00 /* W Mixer MVD508 Channel 0 - FM */ - #define P_M_MV508_IMIXER 0x01 /* W Mixer MVD508 Channel 1 - Input mixer (rec monitor) */ - #define P_M_MV508_LINE 0x02 /* W Mixer MVD508 Channel 2 - Line in */ - #define P_M_MV508_CDROM 0x03 /* W Mixer MVD508 Channel 3 - CD-ROM */ - #define P_M_MV508_MIC 0x04 /* W Mixer MVD508 Channel 4 - Microphone */ - #define P_M_MV508_PCM 0x05 /* W Mixer MVD508 Channel 5 - PCM */ - #define P_M_MV508_SPEAKER 0x06 /* W Mixer MVD508 Channel 6 - PC Speaker */ - #define P_M_MV508_SB 0x07 /* W Mixer MVD508 Channel 7 - SB DSP */ +# define P_M_MV508_ADDRESS 0x80 /* W Mixer MVD508 Address/mixer select */ +# define P_M_MV508_DATA 0x00 +# define P_M_MV508_LEFT 0x20 /* W Mixer MVD508 Left channel select */ +# define P_M_MV508_RIGHT 0x40 /* W Mixer MVD508 Right channel select */ +# define P_M_MV508_BOTH 0x00 /* W Mixer MVD508 Both channel select */ +# define P_M_MV508_MIXER 0x10 /* W Mixer MVD508 Select a mixer (rather than a volume) */ +# define P_M_MV508_VOLUME 0x00 + +# define P_M_MV508_INPUTMIX 0x20 /* W Mixer MVD508 Select mixer A */ +# define P_M_MV508_OUTPUTMIX 0x00 /* W Mixer MVD508 Select mixer B */ + +# define P_M_MV508_MASTER_A 0x01 /* W Mixer MVD508 Master volume control A (output) */ +# define P_M_MV508_MASTER_B 0x02 /* W Mixer MVD508 Master volume control B (DSP input) */ +# define P_M_MV508_BASS 0x03 /* W Mixer MVD508 Bass control */ +# define P_M_MV508_TREBLE 0x04 /* W Mixer MVD508 Treble control */ +# define P_M_MV508_MODE 0x05 /* W Mixer MVD508 Master mode control */ + +# define P_M_MV508_LOUDNESS 0x04 /* W Mixer MVD508 Mode control - Loudness filter */ +# define P_M_MV508_ENHANCE_BITS 0x03 +# define P_M_MV508_ENHANCE_NONE 0x00 /* W Mixer MVD508 Mode control - No stereo enhancement */ +# define P_M_MV508_ENHANCE_40 0x01 /* W Mixer MVD508 Mode control - 40% stereo enhancement */ +# define P_M_MV508_ENHANCE_60 0x02 /* W Mixer MVD508 Mode control - 60% stereo enhancement */ +# define P_M_MV508_ENHANCE_80 0x03 /* W Mixer MVD508 Mode control - 80% stereo enhancement */ + +# define P_M_MV508_FM 0x00 /* W Mixer MVD508 Channel 0 - FM */ +# define P_M_MV508_IMIXER 0x01 /* W Mixer MVD508 Channel 1 - Input mixer (rec monitor) */ +# define P_M_MV508_LINE 0x02 /* W Mixer MVD508 Channel 2 - Line in */ +# define P_M_MV508_CDROM 0x03 /* W Mixer MVD508 Channel 3 - CD-ROM */ +# define P_M_MV508_MIC 0x04 /* W Mixer MVD508 Channel 4 - Microphone */ +# define P_M_MV508_PCM 0x05 /* W Mixer MVD508 Channel 5 - PCM */ +# define P_M_MV508_SPEAKER 0x06 /* W Mixer MVD508 Channel 6 - PC Speaker */ +# define P_M_MV508_SB 0x07 /* W Mixer MVD508 Channel 7 - SB DSP */ #define SERIAL_MIXER 0xB88 /* R W Control Serial mixer control (used other ways) */ - #define S_M_PCM_RESET 0x01 /* R W PCM Codec/DSP reset */ - #define S_M_FM_RESET 0x02 /* R W FM FM chip reset */ - #define S_M_SB_RESET 0x04 /* R W PCM SB emulation chip reset */ - #define S_M_MIXER_RESET 0x10 /* R W Mixer Mixer chip reset */ - #define S_M_INTEGRATOR_ENABLE 0x40 /* R W Speaker Enable PC speaker integrator (FORCE RealSound) */ - #define S_M_OPL3_DUAL_MONO 0x80 /* R W FM Set the OPL-3 to dual mono mode */ +# define S_M_PCM_RESET 0x01 /* R W PCM Codec/DSP reset */ +# define S_M_FM_RESET 0x02 /* R W FM FM chip reset */ +# define S_M_SB_RESET 0x04 /* R W PCM SB emulation chip reset */ +# define S_M_MIXER_RESET 0x10 /* R W Mixer Mixer chip reset */ +# define S_M_INTEGRATOR_ENABLE 0x40 /* R W Speaker Enable PC speaker integrator (FORCE RealSound) */ +# define S_M_OPL3_DUAL_MONO 0x80 /* R W FM Set the OPL-3 to dual mono mode */ #define PCM_CONTROL 0xF8A /* R W PCM PCM Control Register */ - #define P_C_MIXER_CROSS_FIELD 0x0f - #define P_C_MIXER_CROSS_R_TO_R 0x01 /* R W Mixer Connect Right to Right */ - #define P_C_MIXER_CROSS_L_TO_R 0x02 /* R W Mixer Connect Left to Right */ - #define P_C_MIXER_CROSS_R_TO_L 0x04 /* R W Mixer Connect Right to Left */ - #define P_C_MIXER_CROSS_L_TO_L 0x08 /* R W Mixer Connect Left to Left */ - #define P_C_PCM_DAC_MODE 0x10 /* R W PCM Playback (DAC) mode */ - #define P_C_PCM_ADC_MODE 0x00 /* R W PCM Record (ADC) mode */ - #define P_C_PCM_MONO 0x20 /* R W PCM Mono mode */ - #define P_C_PCM_STEREO 0x00 /* R W PCM Stereo mode */ - #define P_C_PCM_ENABLE 0x40 /* R W PCM Enable PCM engine */ - #define P_C_PCM_DMA_ENABLE 0x80 /* R W PCM Enable DRQ */ +# define P_C_MIXER_CROSS_FIELD 0x0f +# define P_C_MIXER_CROSS_R_TO_R 0x01 /* R W Mixer Connect Right to Right */ +# define P_C_MIXER_CROSS_L_TO_R 0x02 /* R W Mixer Connect Left to Right */ +# define P_C_MIXER_CROSS_R_TO_L 0x04 /* R W Mixer Connect Right to Left */ +# define P_C_MIXER_CROSS_L_TO_L 0x08 /* R W Mixer Connect Left to Left */ +# define P_C_PCM_DAC_MODE 0x10 /* R W PCM Playback (DAC) mode */ +# define P_C_PCM_ADC_MODE 0x00 /* R W PCM Record (ADC) mode */ +# define P_C_PCM_MONO 0x20 /* R W PCM Mono mode */ +# define P_C_PCM_STEREO 0x00 /* R W PCM Stereo mode */ +# define P_C_PCM_ENABLE 0x40 /* R W PCM Enable PCM engine */ +# define P_C_PCM_DMA_ENABLE 0x80 /* R W PCM Enable DRQ */ #define SAMPLE_COUNTER_CONTROL 0x138B /* R W PCM Sample counter control register */ - #define S_C_C_SQUARE_WAVE 0x04 /* R W PCM Square wave generator (use for sample rate) */ - #define S_C_C_RATE 0x06 /* R W PCM Rate generator (use for sample buffer count) */ - #define S_C_C_LSB_THEN_MSB 0x30 /* R W PCM Change all 16 bits, LSB first, then MSB */ +# define S_C_C_SQUARE_WAVE 0x04 /* R W PCM Square wave generator (use for sample rate) */ +# define S_C_C_RATE 0x06 /* R W PCM Rate generator (use for sample buffer count) */ +# define S_C_C_LSB_THEN_MSB 0x30 /* R W PCM Change all 16 bits, LSB first, then MSB */ /* MVD101 and SDK documentations have S_C_C_SAMPLE_RATE and S_C_C_SAMPLE_BUFFER transposed. Only one works :-) */ - #define S_C_C_SAMPLE_RATE 0x00 /* R W PCM Select sample rate timer */ - #define S_C_C_SAMPLE_BUFFER 0x40 /* R W PCM Select sample buffer counter */ +# define S_C_C_SAMPLE_RATE 0x00 /* R W PCM Select sample rate timer */ +# define S_C_C_SAMPLE_BUFFER 0x40 /* R W PCM Select sample buffer counter */ - #define S_C_C_PC_SPEAKER 0x80 /* R W PCM Select PC speaker counter */ +# define S_C_C_PC_SPEAKER 0x80 /* R W PCM Select PC speaker counter */ #define SAMPLE_RATE_TIMER 0x1388 /* W PCM Sample rate timer register (PCM wait interval) */ #define SAMPLE_BUFFER_COUNTER 0x1389 /* R W PCM Sample buffer counter (DMA buffer size) */ #define MIDI_CONTROL 0x178b /* R W MIDI Midi control register */ - #define M_C_ENA_TSTAMP_IRQ 0x01 /* R W MIDI Enable Time Stamp Interrupts */ - #define M_C_ENA_TME_COMP_IRQ 0x02 /* R W MIDI Enable time compare interrupts */ - #define M_C_ENA_INPUT_IRQ 0x04 /* R W MIDI Enable input FIFO interrupts */ - #define M_C_ENA_OUTPUT_IRQ 0x08 /* R W MIDI Enable output FIFO interrupts */ - #define M_C_ENA_OUTPUT_HALF_IRQ 0x10 /* R W MIDI Enable output FIFO half full interrupts */ - #define M_C_RESET_INPUT_FIFO 0x20 /* R W MIDI Reset input FIFO pointer */ - #define M_C_RESET_OUTPUT_FIFO 0x40 /* R W MIDI Reset output FIFO pointer */ - #define M_C_ENA_THRU_MODE 0x80 /* R W MIDI Echo input to output (THRU) */ +# define M_C_ENA_TSTAMP_IRQ 0x01 /* R W MIDI Enable Time Stamp Interrupts */ +# define M_C_ENA_TME_COMP_IRQ 0x02 /* R W MIDI Enable time compare interrupts */ +# define M_C_ENA_INPUT_IRQ 0x04 /* R W MIDI Enable input FIFO interrupts */ +# define M_C_ENA_OUTPUT_IRQ 0x08 /* R W MIDI Enable output FIFO interrupts */ +# define M_C_ENA_OUTPUT_HALF_IRQ 0x10 /* R W MIDI Enable output FIFO half full interrupts */ +# define M_C_RESET_INPUT_FIFO 0x20 /* R W MIDI Reset input FIFO pointer */ +# define M_C_RESET_OUTPUT_FIFO 0x40 /* R W MIDI Reset output FIFO pointer */ +# define M_C_ENA_THRU_MODE 0x80 /* R W MIDI Echo input to output (THRU) */ #define MIDI_STATUS 0x1B88 /* R W MIDI Midi (interrupt) status register */ - #define M_S_TIMESTAMP 0x01 /* R W MIDI Midi time stamp interrupt occurred */ - #define M_S_COMPARE 0x02 /* R W MIDI Midi compare time interrupt occurred */ - #define M_S_INPUT_AVAIL 0x04 /* R W MIDI Midi input data available interrupt occurred */ - #define M_S_OUTPUT_EMPTY 0x08 /* R W MIDI Midi output FIFO empty interrupt occurred */ - #define M_S_OUTPUT_HALF_EMPTY 0x10 /* R W MIDI Midi output FIFO half empty interrupt occurred */ - #define M_S_INPUT_OVERRUN 0x20 /* R W MIDI Midi input overrun error occurred */ - #define M_S_OUTPUT_OVERRUN 0x40 /* R W MIDI Midi output overrun error occurred */ - #define M_S_FRAMING_ERROR 0x80 /* R W MIDI Midi input framing error occurred */ +# define M_S_TIMESTAMP 0x01 /* R W MIDI Midi time stamp interrupt occurred */ +# define M_S_COMPARE 0x02 /* R W MIDI Midi compare time interrupt occurred */ +# define M_S_INPUT_AVAIL 0x04 /* R W MIDI Midi input data available interrupt occurred */ +# define M_S_OUTPUT_EMPTY 0x08 /* R W MIDI Midi output FIFO empty interrupt occurred */ +# define M_S_OUTPUT_HALF_EMPTY 0x10 /* R W MIDI Midi output FIFO half empty interrupt occurred */ +# define M_S_INPUT_OVERRUN 0x20 /* R W MIDI Midi input overrun error occurred */ +# define M_S_OUTPUT_OVERRUN 0x40 /* R W MIDI Midi output overrun error occurred */ +# define M_S_FRAMING_ERROR 0x80 /* R W MIDI Midi input framing error occurred */ #define MIDI_FIFO_STATUS 0x1B89 /* R W MIDI Midi fifo status */ #define MIDI_DATA 0x178A /* R W MIDI Midi data register */ diff -u --recursive --new-file v1.3.33/linux/drivers/sound/pas2_card.c linux/drivers/sound/pas2_card.c --- v1.3.33/linux/drivers/sound/pas2_card.c Sun Aug 13 14:45:34 1995 +++ linux/drivers/sound/pas2_card.c Wed Oct 11 07:55:40 1995 @@ -44,12 +44,14 @@ static int pas_intr_mask = 0; static int pas_irq = 0; +sound_os_info *pas_osp; + char pas_model; static char *pas_model_names[] = {"", "Pro AudioSpectrum+", "CDPC", "Pro AudioSpectrum 16", "Pro AudioSpectrum 16D"}; /* - * pas_read() and pas_write() are equivalents of INB() and OUTB() + * pas_read() and pas_write() are equivalents of inb and outb */ /* * These routines perform the I/O address translation required @@ -62,13 +64,13 @@ unsigned char pas_read (int ioaddr) { - return INB (ioaddr ^ translat_code); + return inb (ioaddr ^ translat_code); } void pas_write (unsigned char data, int ioaddr) { - OUTB (data, ioaddr ^ translat_code); + outb (data, ioaddr ^ translat_code); } void @@ -80,7 +82,7 @@ /******************* Begin of the Interrupt Handler ********************/ void -pasintr (INT_HANDLER_PARMS (irq, dummy)) +pasintr (int irq, struct pt_regs *dummy) { int status; @@ -109,16 +111,9 @@ int pas_set_intr (int mask) { - int err; - if (!mask) return 0; - if (!pas_intr_mask) - { - if ((err = snd_set_irq_handler (pas_irq, pasintr, "PAS16")) < 0) - return err; - } pas_intr_mask |= mask; pas_write (pas_intr_mask, INTERRUPT_MASK); @@ -134,10 +129,6 @@ pas_intr_mask &= ~mask; pas_write (pas_intr_mask, INTERRUPT_MASK); - if (!pas_intr_mask) - { - snd_release_irq (pas_irq); - } return 0; } @@ -204,6 +195,11 @@ printk ("PAS2: Invalid IRQ %d", pas_irq); ok = 0; } + else + { + if (snd_set_irq_handler (pas_irq, pasintr, "PAS16", hw_config->osp) < 0) + ok = 0; + } } if (hw_config->dma < 0 || hw_config->dma > 7) @@ -219,6 +215,14 @@ printk ("PAS2: Invalid DMA selection %d", hw_config->dma); ok = 0; } + else + { + if (sound_alloc_dma (hw_config->dma, "PAS16")) + { + printk ("pas2_card.c: Can't allocate DMA channel\n"); + ok = 0; + } + } } /* @@ -226,8 +230,8 @@ * as per Media Vision. Only define this if your PAS doesn't work correctly. */ #ifdef SYMPHONY_PAS - OUTB (0x05, 0xa8); - OUTB (0x60, 0xa9); + outb (0x05, 0xa8); + outb (0x60, 0xa9); #endif #ifdef BROKEN_BUS_CLOCK @@ -250,14 +254,7 @@ * rate * of * 17.897 kHz */ -#if 1 pas_write (8, PRESCALE_DIVIDER); -#else - if (pas_model == PAS_16 || pas_model == PAS_16D) - pas_write (8, PRESCALE_DIVIDER); - else - pas_write (0, PRESCALE_DIVIDER); -#endif mix_write (P_M_MV508_ADDRESS | 5, PARALLEL_MIXER); mix_write (5, PARALLEL_MIXER); @@ -323,10 +320,10 @@ * you have something on base port 0x388. SO be forewarned. */ - OUTB (0xBC, MASTER_DECODE); /* + outb (0xBC, MASTER_DECODE); /* * Talk to first board */ - OUTB (hw_config->io_base >> 2, MASTER_DECODE); /* + outb (hw_config->io_base >> 2, MASTER_DECODE); /* * Set base address */ translat_code = PAS_DEFAULT_BASE ^ hw_config->io_base; @@ -348,7 +345,7 @@ foo = board_id ^ 0xe0; pas_write (foo, INTERRUPT_MASK); - foo = INB (INTERRUPT_MASK); + foo = inb (INTERRUPT_MASK); pas_write (board_id, INTERRUPT_MASK); if (board_id != foo) /* @@ -365,6 +362,7 @@ attach_pas_card (long mem_start, struct address_info *hw_config) { pas_irq = hw_config->irq; + pas_osp = hw_config->osp; if (detect_pas_hw (hw_config)) { @@ -407,7 +405,15 @@ int probe_pas (struct address_info *hw_config) { + pas_osp = hw_config->osp; return detect_pas_hw (hw_config); +} + +void +unload_pas (struct address_info *hw_config) +{ + sound_free_dma (hw_config->dma); + snd_release_irq (hw_config->irq); } #endif diff -u --recursive --new-file v1.3.33/linux/drivers/sound/pas2_midi.c linux/drivers/sound/pas2_midi.c --- v1.3.33/linux/drivers/sound/pas2_midi.c Tue Jul 25 18:21:22 1995 +++ linux/drivers/sound/pas2_midi.c Wed Oct 11 07:55:41 1995 @@ -59,7 +59,7 @@ if (midi_busy) { printk ("PAS2: Midi busy\n"); - return RET_ERROR (EBUSY); + return -EBUSY; } /* @@ -68,7 +68,8 @@ pas_write (M_C_RESET_INPUT_FIFO | M_C_RESET_OUTPUT_FIFO, MIDI_CONTROL); - DISABLE_INTR (flags); + save_flags (flags); + cli (); if ((err = pas_set_intr (I_M_MIDI_IRQ_ENABLE)) < 0) return err; @@ -107,7 +108,7 @@ pas_write (0xff, MIDI_STATUS); ofifo_bytes = 0; - RESTORE_INTR (flags); + restore_flags (flags); midi_busy = 1; qlen = qhead = qtail = 0; @@ -161,7 +162,8 @@ * Drain the local queue first */ - DISABLE_INTR (flags); + save_flags (flags); + cli (); while (qlen && dump_to_midi (tmp_queue[qhead])) { @@ -169,7 +171,7 @@ qhead++; } - RESTORE_INTR (flags); + restore_flags (flags); /* * Output the byte if the local queue is empty. @@ -190,13 +192,14 @@ * Local queue full */ - DISABLE_INTR (flags); + save_flags (flags); + cli (); tmp_queue[qtail] = midi_byte; qlen++; qtail++; - RESTORE_INTR (flags); + restore_flags (flags); return 1; } @@ -214,9 +217,9 @@ } static int -pas_midi_ioctl (int dev, unsigned cmd, unsigned arg) +pas_midi_ioctl (int dev, unsigned cmd, ioctl_arg arg) { - return RET_ERROR (EINVAL); + return -EINVAL; } static void @@ -228,7 +231,7 @@ static int pas_buffer_status (int dev) { - return !qlen; + return qlen; } #define MIDI_SYNTH_NAME "Pro Audio Spectrum Midi" @@ -309,7 +312,8 @@ ofifo_bytes = 0; } - DISABLE_INTR (flags); + save_flags (flags); + cli (); while (qlen && dump_to_midi (tmp_queue[qhead])) { @@ -317,13 +321,9 @@ qhead++; } - RESTORE_INTR (flags); + restore_flags (flags); } -#if 0 - if (stat & M_S_FRAMING_ERROR) - printk ("MIDI framing error\n"); -#endif if (stat & M_S_OUTPUT_OVERRUN) { diff -u --recursive --new-file v1.3.33/linux/drivers/sound/pas2_mixer.c linux/drivers/sound/pas2_mixer.c --- v1.3.33/linux/drivers/sound/pas2_mixer.c Tue Jul 11 10:02:53 1995 +++ linux/drivers/sound/pas2_mixer.c Wed Oct 11 07:55:41 1995 @@ -39,6 +39,7 @@ extern int translat_code; extern char pas_model; +extern sound_os_info *pas_osp; static int rec_devices = (SOUND_MASK_MIC); /* Default recording source */ static int mode_control = 0; @@ -80,8 +81,8 @@ if (pas_model == PAS_16D) { - OUTW (data | (data << 8), (ioaddr ^ translat_code) - 1); - OUTB (0x80, 0); + outw (data | (data << 8), (ioaddr ^ translat_code) - 1); + outb (0x80, 0); } else pas_write (data, ioaddr); @@ -235,7 +236,7 @@ break; default: - return RET_ERROR (EINVAL); + return -EINVAL; } return (levels[whichDev]); @@ -257,14 +258,14 @@ } int -pas_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg) +pas_mixer_ioctl (int dev, unsigned int cmd, ioctl_arg arg) { TRACE (printk ("pas2_mixer.c: int pas_mixer_ioctl(unsigned int cmd = %X, unsigned int arg = %X)\n", cmd, arg)); if (((cmd >> 8) & 0xff) == 'M') { if (cmd & IOC_IN) - return IOCTL_OUT (arg, pas_mixer_set (cmd & 0xff, IOCTL_IN (arg))); + return snd_ioctl_return ((int *) arg, pas_mixer_set (cmd & 0xff, get_fs_long ((long *) arg))); else { /* * Read parameters @@ -274,47 +275,47 @@ { case SOUND_MIXER_RECSRC: - return IOCTL_OUT (arg, rec_devices); + return snd_ioctl_return ((int *) arg, rec_devices); break; case SOUND_MIXER_STEREODEVS: - return IOCTL_OUT (arg, SUPPORTED_MIXER_DEVICES & ~(SOUND_MASK_BASS | SOUND_MASK_TREBLE)); + return snd_ioctl_return ((int *) arg, SUPPORTED_MIXER_DEVICES & ~(SOUND_MASK_BASS | SOUND_MASK_TREBLE)); break; case SOUND_MIXER_DEVMASK: - return IOCTL_OUT (arg, SUPPORTED_MIXER_DEVICES); + return snd_ioctl_return ((int *) arg, SUPPORTED_MIXER_DEVICES); break; case SOUND_MIXER_RECMASK: - return IOCTL_OUT (arg, POSSIBLE_RECORDING_DEVICES & SUPPORTED_MIXER_DEVICES); + return snd_ioctl_return ((int *) arg, POSSIBLE_RECORDING_DEVICES & SUPPORTED_MIXER_DEVICES); break; case SOUND_MIXER_CAPS: - return IOCTL_OUT (arg, 0); /* No special capabilities */ + return snd_ioctl_return ((int *) arg, 0); /* No special capabilities */ break; case SOUND_MIXER_MUTE: - return IOCTL_OUT (arg, 0); /* No mute yet */ + return snd_ioctl_return ((int *) arg, 0); /* No mute yet */ break; case SOUND_MIXER_ENHANCE: if (!(mode_control & P_M_MV508_ENHANCE_BITS)) - return IOCTL_OUT (arg, 0); - return IOCTL_OUT (arg, ((mode_control & P_M_MV508_ENHANCE_BITS) + 1) * 20); + return snd_ioctl_return ((int *) arg, 0); + return snd_ioctl_return ((int *) arg, ((mode_control & P_M_MV508_ENHANCE_BITS) + 1) * 20); break; case SOUND_MIXER_LOUD: if (mode_control & P_M_MV508_LOUDNESS) - return IOCTL_OUT (arg, 1); - return IOCTL_OUT (arg, 0); + return snd_ioctl_return ((int *) arg, 1); + return snd_ioctl_return ((int *) arg, 0); break; default: - return IOCTL_OUT (arg, levels[cmd & 0xff]); + return snd_ioctl_return ((int *) arg, levels[cmd & 0xff]); } } } - return RET_ERROR (EINVAL); + return -EINVAL; } static struct mixer_operations pas_mixer_operations = diff -u --recursive --new-file v1.3.33/linux/drivers/sound/pas2_pcm.c linux/drivers/sound/pas2_pcm.c --- v1.3.33/linux/drivers/sound/pas2_pcm.c Tue Jul 11 10:02:53 1995 +++ linux/drivers/sound/pas2_pcm.c Wed Oct 11 07:55:41 1995 @@ -103,7 +103,8 @@ pcm_filter = tmp; #endif - DISABLE_INTR (flags); + save_flags (flags); + cli (); pas_write (tmp & ~(F_F_PCM_RATE_COUNTER | F_F_PCM_BUFFER_COUNTER), FILTER_FREQUENCY); pas_write (S_C_C_SAMPLE_RATE | S_C_C_LSB_THEN_MSB | S_C_C_SQUARE_WAVE, SAMPLE_COUNTER_CONTROL); @@ -111,7 +112,7 @@ pas_write ((foo >> 8) & 0xff, SAMPLE_RATE_TIMER); pas_write (tmp, FILTER_FREQUENCY); - RESTORE_INTR (flags); + restore_flags (flags); return pcm_speed; } @@ -153,7 +154,7 @@ } static int -pas_pcm_ioctl (int dev, unsigned int cmd, unsigned int arg, int local) +pas_pcm_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local) { TRACE (printk ("pas2_pcm.c: static int pas_pcm_ioctl(unsigned int cmd = %X, unsigned int arg = %X)\n", cmd, arg)); @@ -161,62 +162,62 @@ { case SOUND_PCM_WRITE_RATE: if (local) - return pcm_set_speed (arg); - return IOCTL_OUT (arg, pcm_set_speed (IOCTL_IN (arg))); + return pcm_set_speed ((int) arg); + return snd_ioctl_return ((int *) arg, pcm_set_speed (get_fs_long ((long *) arg))); break; case SOUND_PCM_READ_RATE: if (local) return pcm_speed; - return IOCTL_OUT (arg, pcm_speed); + return snd_ioctl_return ((int *) arg, pcm_speed); break; case SNDCTL_DSP_STEREO: if (local) - return pcm_set_channels (arg + 1) - 1; - return IOCTL_OUT (arg, pcm_set_channels (IOCTL_IN (arg) + 1) - 1); + return pcm_set_channels ((int) arg + 1) - 1; + return snd_ioctl_return ((int *) arg, pcm_set_channels (get_fs_long ((long *) arg) + 1) - 1); break; case SOUND_PCM_WRITE_CHANNELS: if (local) - return pcm_set_channels (arg); - return IOCTL_OUT (arg, pcm_set_channels (IOCTL_IN (arg))); + return pcm_set_channels ((int) arg); + return snd_ioctl_return ((int *) arg, pcm_set_channels (get_fs_long ((long *) arg))); break; case SOUND_PCM_READ_CHANNELS: if (local) return pcm_channels; - return IOCTL_OUT (arg, pcm_channels); + return snd_ioctl_return ((int *) arg, pcm_channels); break; case SNDCTL_DSP_SETFMT: if (local) - return pcm_set_bits (arg); - return IOCTL_OUT (arg, pcm_set_bits (IOCTL_IN (arg))); + return pcm_set_bits ((int) arg); + return snd_ioctl_return ((int *) arg, pcm_set_bits (get_fs_long ((long *) arg))); break; case SOUND_PCM_READ_BITS: if (local) return pcm_bits; - return IOCTL_OUT (arg, pcm_bits); + return snd_ioctl_return ((int *) arg, pcm_bits); case SOUND_PCM_WRITE_FILTER: /* * NOT YET IMPLEMENTED */ - if (IOCTL_IN (arg) > 1) - return IOCTL_OUT (arg, RET_ERROR (EINVAL)); + if (get_fs_long ((long *) arg) > 1) + return -EINVAL; + pcm_filter = get_fs_long ((long *) arg); break; - pcm_filter = IOCTL_IN (arg); case SOUND_PCM_READ_FILTER: - return IOCTL_OUT (arg, pcm_filter); + return snd_ioctl_return ((int *) arg, pcm_filter); break; default: - return RET_ERROR (EINVAL); + return -EINVAL; } - return RET_ERROR (EINVAL); + return -EINVAL; } static void @@ -237,11 +238,6 @@ if ((err = pas_set_intr (PAS_PCM_INTRBITS)) < 0) return err; - if (DMAbuf_open_dma (dev) < 0) - { - pas_remove_intr (PAS_PCM_INTRBITS); - return RET_ERROR (EBUSY); - } pcm_count = 0; @@ -255,14 +251,14 @@ TRACE (printk ("pas2_pcm.c: static void pas_pcm_close(void)\n")); - DISABLE_INTR (flags); + save_flags (flags); + cli (); pas_pcm_reset (dev); - DMAbuf_close_dma (dev); pas_remove_intr (PAS_PCM_INTRBITS); pcm_mode = PCM_NON; - RESTORE_INTR (flags); + restore_flags (flags); } static void @@ -274,7 +270,7 @@ TRACE (printk ("pas2_pcm.c: static void pas_pcm_output_block(char *buf = %P, int count = %X)\n", buf, count)); cnt = count; - if (audio_devs[dev]->dmachan > 3) + if (audio_devs[dev]->dmachan1 > 3) cnt >>= 1; if (audio_devs[dev]->flags & DMA_AUTOMODE && @@ -284,7 +280,8 @@ * Auto mode on. No need to react */ - DISABLE_INTR (flags); + save_flags (flags); + cli (); pas_write (pas_read (PCM_CONTROL) & ~P_C_PCM_ENABLE, PCM_CONTROL); @@ -292,7 +289,7 @@ if (restart_dma) DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE); - if (audio_devs[dev]->dmachan > 3) + if (audio_devs[dev]->dmachan1 > 3) count >>= 1; if (count != pcm_count) @@ -310,7 +307,7 @@ pcm_mode = PCM_DAC; - RESTORE_INTR (flags); + restore_flags (flags); } static void @@ -323,7 +320,7 @@ TRACE (printk ("pas2_pcm.c: static void pas_pcm_start_input(char *buf = %P, int count = %X)\n", buf, count)); cnt = count; - if (audio_devs[dev]->dmachan > 3) + if (audio_devs[dev]->dmachan1 > 3) cnt >>= 1; if (audio_devs[my_devnum]->flags & DMA_AUTOMODE && @@ -333,12 +330,13 @@ * Auto mode on. No need to react */ - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (restart_dma) DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ); - if (audio_devs[dev]->dmachan > 3) + if (audio_devs[dev]->dmachan1 > 3) count >>= 1; if (count != pcm_count) @@ -356,7 +354,7 @@ pcm_mode = PCM_ADC; - RESTORE_INTR (flags); + restore_flags (flags); } static int @@ -403,9 +401,8 @@ if (num_audiodevs < MAX_AUDIO_DEV) { audio_devs[my_devnum = num_audiodevs++] = &pas_pcm_operations; - audio_devs[my_devnum]->dmachan = hw_config->dma; - audio_devs[my_devnum]->buffcount = 1; - audio_devs[my_devnum]->buffsize = 2 * DSP_BUFFSIZE; + audio_devs[my_devnum]->dmachan1 = hw_config->dma; + audio_devs[my_devnum]->buffsize = DSP_BUFFSIZE; } else printk ("PAS2: Too many PCM devices available\n"); diff -u --recursive --new-file v1.3.33/linux/drivers/sound/patmgr.c linux/drivers/sound/patmgr.c --- v1.3.33/linux/drivers/sound/patmgr.c Tue Jul 11 10:02:53 1995 +++ linux/drivers/sound/patmgr.c Wed Oct 11 07:55:41 1995 @@ -32,8 +32,11 @@ #if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SEQUENCER) -DEFINE_WAIT_QUEUES (server_procs[MAX_SYNTH_DEV], - server_wait_flag[MAX_SYNTH_DEV]); +static struct wait_queue *server_procs[MAX_SYNTH_DEV] = +{NULL}; +static volatile struct snd_wait server_wait_flag[MAX_SYNTH_DEV] = +{ + {0}}; static struct patmgr_info *mbox[MAX_SYNTH_DEV] = {NULL}; @@ -46,19 +49,24 @@ #define A_TO_S 1 #define S_TO_A 2 -DEFINE_WAIT_QUEUE (appl_proc, appl_wait_flag); +static struct wait_queue *appl_proc = NULL; +static volatile struct snd_wait appl_wait_flag = +{0}; int pmgr_open (int dev) { if (dev < 0 || dev >= num_synths) - return RET_ERROR (ENXIO); + return -ENXIO; if (pmgr_opened[dev]) - return RET_ERROR (EBUSY); + return -EBUSY; pmgr_opened[dev] = 1; - RESET_WAIT_QUEUE (server_procs[dev], server_wait_flag[dev]); + { + server_wait_flag[dev].aborting = 0; + server_wait_flag[dev].mode = WK_NONE; + }; return 0; } @@ -73,10 +81,13 @@ { mbox[dev]->key = PM_ERROR; - mbox[dev]->parm1 = RET_ERROR (EIO); + mbox[dev]->parm1 = -EIO; - if (SOMEONE_WAITING (appl_proc, appl_wait_flag)) - WAKE_UP (appl_proc, appl_wait_flag); + if ((appl_wait_flag.mode & WK_SLEEP)) + { + appl_wait_flag.mode = WK_WAKEUP; + wake_up (&appl_proc); + }; } pmgr_opened[dev] = 0; @@ -91,47 +102,66 @@ if (count != sizeof (struct patmgr_info)) { printk ("PATMGR%d: Invalid read count\n", dev); - return RET_ERROR (EIO); + return -EIO; } - while (!ok && !PROCESS_ABORTING (server_procs[dev], server_wait_flag[dev])) + while (!ok && !((current->signal & ~current->blocked))) { - DISABLE_INTR (flags); + save_flags (flags); + cli (); while (!(mbox[dev] && msg_direction[dev] == A_TO_S) && - !PROCESS_ABORTING (server_procs[dev], server_wait_flag[dev])) + !((current->signal & ~current->blocked))) { - DO_SLEEP (server_procs[dev], server_wait_flag[dev], 0); + + { + unsigned long tl; + + if (0) + tl = current->timeout = jiffies + (0); + else + tl = 0xffffffff; + server_wait_flag[dev].mode = WK_SLEEP; + interruptible_sleep_on (&server_procs[dev]); + if (!(server_wait_flag[dev].mode & WK_WAKEUP)) + { + if (current->signal & ~current->blocked) + server_wait_flag[dev].aborting = 1; + else if (jiffies >= tl) + server_wait_flag[dev].mode |= WK_TIMEOUT; + } + server_wait_flag[dev].mode &= ~WK_SLEEP; + }; } if (mbox[dev] && msg_direction[dev] == A_TO_S) { - COPY_TO_USER (buf, 0, (char *) mbox[dev], count); + memcpy_tofs (&((buf)[0]), ((char *) mbox[dev]), (count)); msg_direction[dev] = 0; ok = 1; } - RESTORE_INTR (flags); + restore_flags (flags); } if (!ok) - return RET_ERROR (EINTR); + return -EINTR; return count; } int -pmgr_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) +pmgr_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count) { unsigned long flags; if (count < 4) { printk ("PATMGR%d: Write count < 4\n", dev); - return RET_ERROR (EIO); + return -EIO; } - COPY_FROM_USER (mbox[dev], buf, 0, 4); + memcpy_fromfs ((mbox[dev]), &((buf)[0]), (4)); if (*(unsigned char *) mbox[dev] == SEQ_FULLSIZE) { @@ -139,7 +169,7 @@ tmp_dev = ((unsigned short *) mbox[dev])[2]; if (tmp_dev != dev) - return RET_ERROR (ENXIO); + return -ENXIO; return synth_devs[dev]->load_patch (dev, *(unsigned short *) mbox[dev], buf, 4, count, 1); @@ -148,7 +178,7 @@ if (count != sizeof (struct patmgr_info)) { printk ("PATMGR%d: Invalid write count\n", dev); - return RET_ERROR (EIO); + return -EIO; } /* @@ -156,20 +186,24 @@ * mailbox and a client waiting. */ - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (mbox[dev] && !msg_direction[dev]) { - COPY_FROM_USER (&((char *) mbox[dev])[4], buf, 4, count - 4); + memcpy_fromfs ((&((char *) mbox[dev])[4]), &((buf)[4]), (count - 4)); msg_direction[dev] = S_TO_A; - if (SOMEONE_WAITING (appl_proc, appl_wait_flag)) + if ((appl_wait_flag.mode & WK_SLEEP)) { - WAKE_UP (appl_proc, appl_wait_flag); + { + appl_wait_flag.mode = WK_WAKEUP; + wake_up (&appl_proc); + }; } } - RESTORE_INTR (flags); + restore_flags (flags); return count; } @@ -180,7 +214,8 @@ unsigned long flags; int err = 0; - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (mbox[dev]) printk (" PATMGR: Server %d mbox full. Why?\n", dev); @@ -190,17 +225,38 @@ mbox[dev] = rec; msg_direction[dev] = A_TO_S; - if (SOMEONE_WAITING (server_procs[dev], server_wait_flag[dev])) + if ((server_wait_flag[dev].mode & WK_SLEEP)) { - WAKE_UP (server_procs[dev], server_wait_flag[dev]); + { + server_wait_flag[dev].mode = WK_WAKEUP; + wake_up (&server_procs[dev]); + }; } - DO_SLEEP (appl_proc, appl_wait_flag, 0); + + { + unsigned long tl; + + if (0) + tl = current->timeout = jiffies + (0); + else + tl = 0xffffffff; + appl_wait_flag.mode = WK_SLEEP; + interruptible_sleep_on (&appl_proc); + if (!(appl_wait_flag.mode & WK_WAKEUP)) + { + if (current->signal & ~current->blocked) + appl_wait_flag.aborting = 1; + else if (jiffies >= tl) + appl_wait_flag.mode |= WK_TIMEOUT; + } + appl_wait_flag.mode &= ~WK_SLEEP; + }; if (msg_direction[dev] != S_TO_A) { rec->key = PM_ERROR; - rec->parm1 = RET_ERROR (EIO); + rec->parm1 = -EIO; } else if (rec->key == PM_ERROR) { @@ -213,7 +269,7 @@ msg_direction[dev] = 0; } - RESTORE_INTR (flags); + restore_flags (flags); return err; } @@ -228,14 +284,19 @@ if (!pmgr_opened[dev]) return 0; - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (mbox[dev]) printk (" PATMGR: Server %d mbox full. Why?\n", dev); else { if ((mbox[dev] = - (struct patmgr_info *) KERNEL_MALLOC (sizeof (struct patmgr_info))) == NULL) + (struct patmgr_info *) ( + { + caddr_t x; x = kmalloc (sizeof (struct patmgr_info), GFP_KERNEL); x; + } + )) == NULL) { printk ("pmgr: Couldn't allocate memory for a message\n"); return 0; @@ -248,19 +309,40 @@ mbox[dev]->parm3 = p3; msg_direction[dev] = A_TO_S; - if (SOMEONE_WAITING (server_procs[dev], server_wait_flag[dev])) + if ((server_wait_flag[dev].mode & WK_SLEEP)) { - WAKE_UP (server_procs[dev], server_wait_flag[dev]); + { + server_wait_flag[dev].mode = WK_WAKEUP; + wake_up (&server_procs[dev]); + }; } - DO_SLEEP (appl_proc, appl_wait_flag, 0); + + { + unsigned long tl; + + if (0) + tl = current->timeout = jiffies + (0); + else + tl = 0xffffffff; + appl_wait_flag.mode = WK_SLEEP; + interruptible_sleep_on (&appl_proc); + if (!(appl_wait_flag.mode & WK_WAKEUP)) + { + if (current->signal & ~current->blocked) + appl_wait_flag.aborting = 1; + else if (jiffies >= tl) + appl_wait_flag.mode |= WK_TIMEOUT; + } + appl_wait_flag.mode &= ~WK_SLEEP; + }; if (mbox[dev]) - KERNEL_FREE (mbox[dev]); + kfree (mbox[dev]); mbox[dev] = NULL; msg_direction[dev] = 0; } - RESTORE_INTR (flags); + restore_flags (flags); return err; } diff -u --recursive --new-file v1.3.33/linux/drivers/sound/pss.c linux/drivers/sound/pss.c --- v1.3.33/linux/drivers/sound/pss.c Sun Aug 13 14:45:34 1995 +++ linux/drivers/sound/pss.c Wed Oct 11 07:55:42 1995 @@ -62,13 +62,22 @@ #define PSS_READ_FULL 0x4000 #include "coproc.h" + +#ifdef PSS_HAVE_LD #include "synth-ld.h" +#else +static int pss_synthLen = 0; +static unsigned char pss_synth[1] = +{0}; + +#endif typedef struct pss_config { int base; int irq; int dma; + sound_os_info *osp; } pss_config; @@ -88,11 +97,18 @@ devc->base = hw_config->io_base; irq = devc->irq = hw_config->irq; dma = devc->dma = hw_config->dma; + devc->osp = hw_config->osp; if (devc->base != 0x220 && devc->base != 0x240) if (devc->base != 0x230 && devc->base != 0x250) /* Some cards use these */ return 0; + if (check_region (devc->base, 16)) + { + printk ("PSS: I/O port conflict\n"); + return 0; + } + if (irq != 3 && irq != 5 && irq != 7 && irq != 9 && irq != 10 && irq != 11 && irq != 12) return 0; @@ -100,10 +116,10 @@ if (dma != 5 && dma != 6 && dma != 7) return 0; - id = INW (REG (PSS_ID)); + id = inw (REG (PSS_ID)); if ((id >> 8) != 'E') { - printk ("No PSS signature detected at 0x%x (0x%x)\n", devc->base, id); + /* printk ("No PSS signature detected at 0x%x (0x%x)\n", devc->base, id); */ return 0; } @@ -123,28 +139,28 @@ unsigned short tmp, bits; - if (irq < 1 || irq > 15) + if (irq < 0 || irq > 15) return 0; - tmp = INW (REG (dev)) & ~0x38; /* Load confreg, mask IRQ bits out */ + tmp = inw (REG (dev)) & ~0x38; /* Load confreg, mask IRQ bits out */ - if ((bits = irq_bits[irq]) == 0) + if ((bits = irq_bits[irq]) == 0 && irq != 0) { printk ("PSS: Invalid IRQ %d\n", irq); return 0; } - OUTW (tmp | bits, REG (dev)); + outw (tmp | bits, REG (dev)); return 1; } static int set_io_base (pss_config * devc, int dev, int base) { - unsigned short tmp = INW (REG (dev)) & 0x003f; + unsigned short tmp = inw (REG (dev)) & 0x003f; unsigned short bits = (base & 0x0ffc) << 4; - OUTW (bits | tmp, REG (dev)); + outw (bits | tmp, REG (dev)); return 1; } @@ -163,29 +179,29 @@ if (dma < 0 || dma > 7) return 0; - tmp = INW (REG (dev)) & ~0x07; /* Load confreg, mask DMA bits out */ + tmp = inw (REG (dev)) & ~0x07; /* Load confreg, mask DMA bits out */ - if ((bits = dma_bits[dma]) == 0) + if ((bits = dma_bits[dma]) == 0 && dma != 4) { printk ("PSS: Invalid DMA %d\n", dma); return 0; } - OUTW (tmp | bits, REG (dev)); + outw (tmp | bits, REG (dev)); return 1; } static int pss_reset_dsp (pss_config * devc) { - unsigned long i, limit = GET_TIME () + 10; + unsigned long i, limit = jiffies + 10; - OUTW (0x2000, REG (PSS_CONTROL)); + outw (0x2000, REG (PSS_CONTROL)); - for (i = 0; i < 32768 && GET_TIME () < limit; i++) - INW (REG (PSS_CONTROL)); + for (i = 0; i < 32768 && jiffies < limit; i++) + inw (REG (PSS_CONTROL)); - OUTW (0x0000, REG (PSS_CONTROL)); + outw (0x0000, REG (PSS_CONTROL)); return 1; } @@ -197,10 +213,10 @@ for (i = 0; i < 327680; i++) { - val = INW (REG (PSS_STATUS)); + val = inw (REG (PSS_STATUS)); if (val & PSS_WRITE_EMPTY) { - OUTW (word, REG (PSS_DATA)); + outw (word, REG (PSS_DATA)); return 1; } } @@ -214,10 +230,10 @@ for (i = 0; i < 327680; i++) { - val = INW (REG (PSS_STATUS)); + val = inw (REG (PSS_STATUS)); if (val & PSS_READ_FULL) { - *word = INW (REG (PSS_DATA)); + *word = inw (REG (PSS_DATA)); return 1; } } @@ -233,15 +249,15 @@ if (flags & CPF_FIRST) { /*_____ Warn DSP software that a boot is coming */ - OUTW (0x00fe, REG (PSS_DATA)); + outw (0x00fe, REG (PSS_DATA)); - limit = GET_TIME () + 10; + limit = jiffies + 10; - for (i = 0; i < 32768 && GET_TIME () < limit; i++) - if (INW (REG (PSS_DATA)) == 0x5500) + for (i = 0; i < 32768 && jiffies < limit; i++) + if (inw (REG (PSS_DATA)) == 0x5500) break; - OUTW (*block++, REG (PSS_DATA)); + outw (*block++, REG (PSS_DATA)); pss_reset_dsp (devc); } @@ -254,7 +270,7 @@ for (j = 0; j < 327670; j++) { /*_____ Wait for BG to appear */ - if (INW (REG (PSS_STATUS)) & PSS_FLAG3) + if (inw (REG (PSS_STATUS)) & PSS_FLAG3) break; } @@ -271,23 +287,23 @@ } } /*_____ Send the next byte */ - OUTW (*block++, REG (PSS_DATA)); + outw (*block++, REG (PSS_DATA)); count++; } if (flags & CPF_LAST) { /*_____ Why */ - OUTW (0, REG (PSS_DATA)); + outw (0, REG (PSS_DATA)); - limit = GET_TIME () + 10; - for (i = 0; i < 32768 && GET_TIME () < limit; i++) - val = INW (REG (PSS_STATUS)); + limit = jiffies + 10; + for (i = 0; i < 32768 && jiffies < limit; i++) + val = inw (REG (PSS_STATUS)); - limit = GET_TIME () + 10; - for (i = 0; i < 32768 && GET_TIME () < limit; i++) + limit = jiffies + 10; + for (i = 0; i < 32768 && jiffies < limit; i++) { - val = INW (REG (PSS_STATUS)); + val = inw (REG (PSS_STATUS)); if (val & 0x4000) break; } @@ -295,14 +311,14 @@ /* now read the version */ for (i = 0; i < 32000; i++) { - val = INW (REG (PSS_STATUS)); + val = inw (REG (PSS_STATUS)); if (val & PSS_READ_FULL) break; } if (i == 32000) return 0; - val = INW (REG (PSS_DATA)); + val = inw (REG (PSS_DATA)); /* printk("", val/16, val % 16); */ } @@ -317,20 +333,28 @@ devc->base = hw_config->io_base; devc->irq = hw_config->irq; devc->dma = hw_config->dma; + devc->osp = hw_config->osp; if (!probe_pss (hw_config)) return mem_start; - id = INW (REG (PSS_ID)) & 0x00ff; + id = inw (REG (PSS_ID)) & 0x00ff; /* * Disable all emulations. Will be enabled later (if required). */ - OUTW (0x0000, REG (CONF_PSS)); - OUTW (0x0000, REG (CONF_WSS)); - OUTW (0x0000, REG (CONF_SB)); - OUTW (0x0000, REG (CONF_MIDI)); - OUTW (0x0000, REG (CONF_CDROM)); + outw (0x0000, REG (CONF_PSS)); + outw (0x0000, REG (CONF_WSS)); + outw (0x0000, REG (CONF_SB)); + outw (0x0000, REG (CONF_MIDI)); + outw (0x0000, REG (CONF_CDROM)); + +#if YOU_REALLY_WANT_TO_ALLOCATE_THESE_RESOURCES + if (sound_alloc_dma (hw_config->dma, "PSS")) + { + printk ("pss.c: Can't allocate DMA channel\n"); + return mem_start; + } if (!set_irq (devc, CONF_PSS, devc->irq)) { @@ -343,6 +367,7 @@ printk ("PSS: DRQ error\n"); return mem_start; } +#endif pss_initialized = 1; printk (" ", id); @@ -358,6 +383,12 @@ if (!pss_initialized) return 0; + if (check_region (hw_config->io_base, 2)) + { + printk ("PSS: MPU I/O port conflict\n"); + return 0; + } + if (!set_io_base (devc, CONF_MIDI, hw_config->io_base)) { printk ("PSS: MIDI base error.\n"); @@ -389,8 +420,8 @@ for (timeout = 900000; timeout > 0; timeout--) { - if ((INB (hw_config->io_base + 1) & 0x80) == 0) /* Input data avail */ - INB (hw_config->io_base); /* Discard it */ + if ((inb (hw_config->io_base + 1) & 0x80) == 0) /* Input data avail */ + inb (hw_config->io_base); /* Discard it */ else break; /* No more input */ } @@ -412,14 +443,14 @@ if (pss_synthLen == 0) { printk ("PSS: MIDI synth microcode not available.\n"); - return RET_ERROR (EIO); + return -EIO; } if (nonstandard_microcode) if (!pss_download_boot (devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST)) { printk ("PSS: Unable to load MIDI synth microcode to DSP.\n"); - return RET_ERROR (EIO); + return -EIO; } nonstandard_microcode = 0; break; @@ -450,12 +481,12 @@ download_boot_block (void *dev_info, copr_buffer * buf) { if (buf->len <= 0 || buf->len > sizeof (buf->data)) - return RET_ERROR (EINVAL); + return -EINVAL; if (!pss_download_boot (devc, buf->data, buf->len, buf->flags)) { printk ("PSS: Unable to load microcode block to DSP.\n"); - return RET_ERROR (EIO); + return -EIO; } nonstandard_microcode = 1; /* The MIDI microcode has been overwritten */ @@ -463,7 +494,7 @@ } static int -pss_coproc_ioctl (void *dev_info, unsigned int cmd, unsigned int arg, int local) +pss_coproc_ioctl (void *dev_info, unsigned int cmd, ioctl_arg arg, int local) { /* printk("PSS coproc ioctl %x %x %d\n", cmd, arg, local); */ @@ -479,10 +510,19 @@ copr_buffer *buf; int err; - buf = (copr_buffer *) KERNEL_MALLOC (sizeof (copr_buffer)); - IOCTL_FROM_USER ((char *) buf, (char *) arg, 0, sizeof (*buf)); + buf = (copr_buffer *) ( + { + caddr_t x; + x = kmalloc (sizeof (copr_buffer), GFP_KERNEL); + x; + } + ); + if (buf == NULL) + return -ENOSPC; + + memcpy_fromfs (((char *) buf), &(((char *) arg)[0]), (sizeof (*buf))); err = download_boot_block (dev_info, buf); - KERNEL_FREE (buf); + kfree (buf); return err; } break; @@ -493,31 +533,32 @@ unsigned long flags; unsigned short tmp; - IOCTL_FROM_USER ((char *) &buf, (char *) arg, 0, sizeof (buf)); + memcpy_fromfs (((char *) &buf), &(((char *) arg)[0]), (sizeof (buf))); - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (!pss_put_dspword (devc, 0x00d0)) { - RESTORE_INTR (flags); - return RET_ERROR (EIO); + restore_flags (flags); + return -EIO; } if (!pss_put_dspword (devc, (unsigned short) (buf.parm1 & 0xffff))) { - RESTORE_INTR (flags); - return RET_ERROR (EIO); + restore_flags (flags); + return -EIO; } if (!pss_get_dspword (devc, &tmp)) { - RESTORE_INTR (flags); - return RET_ERROR (EIO); + restore_flags (flags); + return -EIO; } buf.parm1 = tmp; - RESTORE_INTR (flags); + restore_flags (flags); - IOCTL_TO_USER ((char *) arg, 0, &buf, sizeof (buf)); + memcpy_tofs (&(((char *) arg)[0]), (&buf), (sizeof (buf))); return 0; } break; @@ -528,29 +569,30 @@ unsigned long flags; unsigned short tmp; - IOCTL_FROM_USER ((char *) &buf, (char *) arg, 0, sizeof (buf)); + memcpy_fromfs (((char *) &buf), &(((char *) arg)[0]), (sizeof (buf))); - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (!pss_put_dspword (devc, 0x00d1)) { - RESTORE_INTR (flags); - return RET_ERROR (EIO); + restore_flags (flags); + return -EIO; } if (!pss_put_dspword (devc, (unsigned short) (buf.parm1 & 0xffff))) { - RESTORE_INTR (flags); - return RET_ERROR (EIO); + restore_flags (flags); + return -EIO; } tmp = (unsigned int) buf.parm2 & 0xffff; if (!pss_put_dspword (devc, tmp)) { - RESTORE_INTR (flags); - return RET_ERROR (EIO); + restore_flags (flags); + return -EIO; } - RESTORE_INTR (flags); + restore_flags (flags); return 0; } break; @@ -561,36 +603,37 @@ unsigned long flags; unsigned short tmp; - IOCTL_FROM_USER ((char *) &buf, (char *) arg, 0, sizeof (buf)); + memcpy_fromfs (((char *) &buf), &(((char *) arg)[0]), (sizeof (buf))); - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (!pss_put_dspword (devc, 0x00d3)) { - RESTORE_INTR (flags); - return RET_ERROR (EIO); + restore_flags (flags); + return -EIO; } if (!pss_put_dspword (devc, (unsigned short) (buf.parm1 & 0xffff))) { - RESTORE_INTR (flags); - return RET_ERROR (EIO); + restore_flags (flags); + return -EIO; } tmp = ((unsigned int) buf.parm2 >> 8) & 0xffff; if (!pss_put_dspword (devc, tmp)) { - RESTORE_INTR (flags); - return RET_ERROR (EIO); + restore_flags (flags); + return -EIO; } tmp = (unsigned int) buf.parm2 & 0x00ff; if (!pss_put_dspword (devc, tmp)) { - RESTORE_INTR (flags); - return RET_ERROR (EIO); + restore_flags (flags); + return -EIO; } - RESTORE_INTR (flags); + restore_flags (flags); return 0; } break; @@ -601,49 +644,50 @@ unsigned long flags; unsigned short tmp; - IOCTL_FROM_USER ((char *) &buf, (char *) arg, 0, sizeof (buf)); + memcpy_fromfs (((char *) &buf), &(((char *) arg)[0]), (sizeof (buf))); - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (!pss_put_dspword (devc, 0x00d2)) { - RESTORE_INTR (flags); - return RET_ERROR (EIO); + restore_flags (flags); + return -EIO; } if (!pss_put_dspword (devc, (unsigned short) (buf.parm1 & 0xffff))) { - RESTORE_INTR (flags); - return RET_ERROR (EIO); + restore_flags (flags); + return -EIO; } if (!pss_get_dspword (devc, &tmp)) /* Read msb */ { - RESTORE_INTR (flags); - return RET_ERROR (EIO); + restore_flags (flags); + return -EIO; } buf.parm1 = tmp << 8; if (!pss_get_dspword (devc, &tmp)) /* Read lsb */ { - RESTORE_INTR (flags); - return RET_ERROR (EIO); + restore_flags (flags); + return -EIO; } buf.parm1 |= tmp & 0x00ff; - RESTORE_INTR (flags); + restore_flags (flags); - IOCTL_TO_USER ((char *) arg, 0, &buf, sizeof (buf)); + memcpy_tofs (&(((char *) arg)[0]), (&buf), (sizeof (buf))); return 0; } break; default: - return RET_ERROR (EINVAL); + return -EINVAL; } - return RET_ERROR (EINVAL); + return -EINVAL; } static coproc_operations pss_coproc_operations = @@ -680,6 +724,12 @@ if (!pss_initialized) return 0; + if (check_region (hw_config->io_base, 8)) + { + printk ("PSS: WSS I/O port conflict\n"); + return 0; + } + if (!set_io_base (devc, CONF_WSS, hw_config->io_base)) { printk ("PSS: WSS base error.\n"); @@ -705,7 +755,7 @@ * Let's try to wait until it finishes this task. */ for (timeout = 0; - timeout < 100000 && (INB (hw_config->io_base + 3) & 0x3f) != 0x04; + timeout < 100000 && (inb (hw_config->io_base + 3) & 0x3f) != 0x04; timeout++); return probe_ms_sound (hw_config); @@ -724,6 +774,23 @@ audio_devs[prev_devs]->coproc = &pss_coproc_operations; return ret; +} + +void +unload_pss (struct address_info *hw_config) +{ +} + +void +unload_pss_mpu (struct address_info *hw_config) +{ + unload_mpu401 (hw_config); +} + +void +unload_pss_mss (struct address_info *hw_config) +{ + unload_ms_sound (hw_config); } #endif diff -u --recursive --new-file v1.3.33/linux/drivers/sound/sb.h linux/drivers/sound/sb.h --- v1.3.33/linux/drivers/sound/sb.h Mon Jul 18 09:50:55 1994 +++ linux/drivers/sound/sb.h Wed Oct 11 07:55:36 1995 @@ -18,8 +18,8 @@ #define DSP_CMD_DMAOFF 0xD4 #define IMODE_NONE 0 -#define IMODE_OUTPUT 1 -#define IMODE_INPUT 2 +#define IMODE_OUTPUT PCM_ENABLE_OUTPUT +#define IMODE_INPUT PCM_ENABLE_INPUT #define IMODE_INIT 3 #define IMODE_MIDI 4 diff -u --recursive --new-file v1.3.33/linux/drivers/sound/sb16_dsp.c linux/drivers/sound/sb16_dsp.c --- v1.3.33/linux/drivers/sound/sb16_dsp.c Sun Aug 13 14:45:34 1995 +++ linux/drivers/sound/sb16_dsp.c Wed Oct 11 07:55:42 1995 @@ -41,27 +41,17 @@ #if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB16) && !defined(EXCLUDE_SB) && !defined(EXCLUDE_AUDIO) && !defined(EXCLUDE_SBPRO) extern int sbc_base; +extern sound_os_info *sb_osp; -static int sb16_dsp_ok = 0; /* - - - * * * * Set to 1 after successful * - * * initialization */ +static int sb16_dsp_ok = 0; static int dsp_16bit = 0; static int dsp_stereo = 0; -static int dsp_current_speed = 8000; /* - - - * * * * DSP_DEFAULT_SPEED; */ +static int dsp_current_speed = 8000; static int dsp_busy = 0; static int dma16, dma8; static unsigned long dsp_count = 0; -static int irq_mode = IMODE_NONE; /* - - - * * * * IMODE_INPUT, IMODE_OUTPUT - * or * * IMODE_NONE */ +static int irq_mode = IMODE_NONE; static int my_dev = 0; static volatile int intr_active = 0; @@ -70,11 +60,12 @@ static void sb16_dsp_close (int dev); static void sb16_dsp_output_block (int dev, unsigned long buf, int count, int intrflag, int dma_restart); static void sb16_dsp_start_input (int dev, unsigned long buf, int count, int intrflag, int dma_restart); -static int sb16_dsp_ioctl (int dev, unsigned int cmd, unsigned int arg, int local); +static int sb16_dsp_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local); static int sb16_dsp_prepare_for_input (int dev, int bsize, int bcount); static int sb16_dsp_prepare_for_output (int dev, int bsize, int bcount); static void sb16_dsp_reset (int dev); static void sb16_dsp_halt (int dev); +static void sb16_dsp_trigger (int dev, int bits); static int dsp_set_speed (int); static int dsp_set_stereo (int); static void dsp_cleanup (void); @@ -96,7 +87,10 @@ sb16_dsp_reset, sb16_dsp_halt, NULL, - NULL + NULL, + NULL, + NULL, + sb16_dsp_trigger }; static int @@ -104,7 +98,7 @@ { int i = 1 << 16; - while (--i & (!INB (DSP_STATUS) & 0x80)); + while (--i & (!inb (DSP_STATUS) & 0x80)); if (!i) printk ("SB16 sb_dsp_command01 Timeout\n"); return sb_dsp_command (val); @@ -156,55 +150,55 @@ } static int -sb16_dsp_ioctl (int dev, unsigned int cmd, unsigned int arg, int local) +sb16_dsp_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local) { switch (cmd) { case SOUND_PCM_WRITE_RATE: if (local) - return dsp_set_speed (arg); - return IOCTL_OUT (arg, dsp_set_speed (IOCTL_IN (arg))); + return dsp_set_speed ((int) arg); + return snd_ioctl_return ((int *) arg, dsp_set_speed (get_fs_long ((long *) arg))); case SOUND_PCM_READ_RATE: if (local) return dsp_current_speed; - return IOCTL_OUT (arg, dsp_current_speed); + return snd_ioctl_return ((int *) arg, dsp_current_speed); case SNDCTL_DSP_STEREO: if (local) - return dsp_set_stereo (arg); - return IOCTL_OUT (arg, dsp_set_stereo (IOCTL_IN (arg))); + return dsp_set_stereo ((int) arg); + return snd_ioctl_return ((int *) arg, dsp_set_stereo (get_fs_long ((long *) arg))); case SOUND_PCM_WRITE_CHANNELS: if (local) - return dsp_set_stereo (arg - 1) + 1; - return IOCTL_OUT (arg, dsp_set_stereo (IOCTL_IN (arg) - 1) + 1); + return dsp_set_stereo ((int) arg - 1) + 1; + return snd_ioctl_return ((int *) arg, dsp_set_stereo (get_fs_long ((long *) arg) - 1) + 1); case SOUND_PCM_READ_CHANNELS: if (local) return dsp_stereo + 1; - return IOCTL_OUT (arg, dsp_stereo + 1); + return snd_ioctl_return ((int *) arg, dsp_stereo + 1); case SNDCTL_DSP_SETFMT: if (local) - return dsp_set_bits (arg); - return IOCTL_OUT (arg, dsp_set_bits (IOCTL_IN (arg))); + return dsp_set_bits ((int) arg); + return snd_ioctl_return ((int *) arg, dsp_set_bits (get_fs_long ((long *) arg))); case SOUND_PCM_READ_BITS: if (local) return dsp_16bit ? 16 : 8; - return IOCTL_OUT (arg, dsp_16bit ? 16 : 8); + return snd_ioctl_return ((int *) arg, dsp_16bit ? 16 : 8); case SOUND_PCM_WRITE_FILTER: /* * NOT YET IMPLEMENTED */ - if (IOCTL_IN (arg) > 1) - return IOCTL_OUT (arg, RET_ERROR (EINVAL)); + if (get_fs_long ((long *) arg) > 1) + return snd_ioctl_return ((int *) arg, -EINVAL); default: - return RET_ERROR (EINVAL); + return -EINVAL; } - return RET_ERROR (EINVAL); + return -EINVAL; } static int @@ -216,11 +210,11 @@ if (!sb16_dsp_ok) { printk ("SB16 Error: SoundBlaster board not installed\n"); - return RET_ERROR (ENXIO); + return -ENXIO; } if (intr_active) - return RET_ERROR (EBUSY); + return -EBUSY; retval = sb_get_irq (); if (retval < 0) @@ -228,20 +222,12 @@ sb_reset_dsp (); - if (ALLOC_DMA_CHN (dma8, "SB16 (8bit)")) - { - printk ("SB16: Unable to grab DMA%d\n", dma8); - sb_free_irq (); - return RET_ERROR (EBUSY); - } - if (dma16 != dma8) - if (ALLOC_DMA_CHN (dma16, "SB16 (16bit)")) + if (sound_open_dma (dma16, "SB16 (16bit)")) { printk ("SB16: Unable to grab DMA%d\n", dma16); sb_free_irq (); - RELEASE_DMA_CHN (dma8); - return RET_ERROR (EBUSY); + return -EBUSY; } irq_mode = IMODE_NONE; @@ -259,15 +245,17 @@ sb_dsp_command01 (0xd9); sb_dsp_command01 (0xd5); - DISABLE_INTR (flags); - RELEASE_DMA_CHN (dma8); + save_flags (flags); + cli (); + + audio_devs[dev]->dmachan1 = dma8; if (dma16 != dma8) - RELEASE_DMA_CHN (dma16); + sound_close_dma (dma16); sb_free_irq (); dsp_cleanup (); dsp_busy = 0; - RESTORE_INTR (flags); + restore_flags (flags); } static void @@ -286,12 +274,13 @@ { int pos, chan = audio_devs[dev]->dmachan; - DISABLE_INTR (flags); + save_flags (flags); + cli (); clear_dma_ff (chan); disable_dma (chan); pos = get_dma_residue (chan); enable_dma (chan); - RESTORE_INTR (flags); + restore_flags (flags); printk ("dmapos=%d %x\n", pos, pos); } #endif @@ -305,7 +294,8 @@ * Auto mode on. No need to react */ } - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (dma_restart) { @@ -316,15 +306,15 @@ sb_dsp_command ((unsigned char) ((dsp_current_speed >> 8) & 0xff)); sb_dsp_command ((unsigned char) (dsp_current_speed & 0xff)); sb_dsp_command ((unsigned char) (dsp_16bit ? 0xb6 : 0xc6)); + dsp_count = cnt; sb_dsp_command ((unsigned char) ((dsp_stereo ? 0x20 : 0) + (dsp_16bit ? 0x10 : 0))); sb_dsp_command01 ((unsigned char) (cnt & 0xff)); sb_dsp_command ((unsigned char) (cnt >> 8)); - dsp_count = cnt; irq_mode = IMODE_OUTPUT; intr_active = 1; - RESTORE_INTR (flags); + restore_flags (flags); } static void @@ -343,12 +333,13 @@ { int pos, chan = audio_devs[dev]->dmachan; - DISABLE_INTR (flags); + save_flags (flags); + cli (); clear_dma_ff (chan); disable_dma (chan); pos = get_dma_residue (chan); enable_dma (chan); - RESTORE_INTR (flags); + restore_flags (flags); printk ("dmapos=%d %x\n", pos, pos); } #endif @@ -362,7 +353,8 @@ * Auto mode on. No need to react */ } - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (dma_restart) { @@ -374,21 +366,21 @@ sb_dsp_command ((unsigned char) ((dsp_current_speed >> 8) & 0xff)); sb_dsp_command ((unsigned char) (dsp_current_speed & 0xff)); sb_dsp_command ((unsigned char) (dsp_16bit ? 0xbe : 0xce)); + dsp_count = cnt; sb_dsp_command ((unsigned char) ((dsp_stereo ? 0x20 : 0) + (dsp_16bit ? 0x10 : 0))); sb_dsp_command01 ((unsigned char) (cnt & 0xff)); sb_dsp_command ((unsigned char) (cnt >> 8)); - dsp_count = cnt; irq_mode = IMODE_INPUT; intr_active = 1; - RESTORE_INTR (flags); + restore_flags (flags); } static int sb16_dsp_prepare_for_input (int dev, int bsize, int bcount) { - audio_devs[my_dev]->dmachan = dsp_16bit ? dma16 : dma8; + audio_devs[my_dev]->dmachan1 = dsp_16bit ? dma16 : dma8; dsp_count = 0; dsp_cleanup (); return 0; @@ -397,13 +389,22 @@ static int sb16_dsp_prepare_for_output (int dev, int bsize, int bcount) { - audio_devs[my_dev]->dmachan = dsp_16bit ? dma16 : dma8; + audio_devs[my_dev]->dmachan1 = dsp_16bit ? dma16 : dma8; dsp_count = 0; dsp_cleanup (); return 0; } static void +sb16_dsp_trigger (int dev, int bits) +{ + if (!bits) + sb_dsp_command (0xd0); /* Halt DMA */ + else if (bits & irq_mode) + sb_dsp_command (0xd4); /* Continue DMA */ +} + +static void dsp_cleanup (void) { irq_mode = IMODE_NONE; @@ -415,12 +416,13 @@ { unsigned long flags; - DISABLE_INTR (flags); + save_flags (flags); + cli (); sb_reset_dsp (); dsp_cleanup (); - RESTORE_INTR (flags); + restore_flags (flags); } static void @@ -480,9 +482,19 @@ if (num_audiodevs < MAX_AUDIO_DEV) { audio_devs[my_dev = num_audiodevs++] = &sb16_dsp_operations; - audio_devs[my_dev]->dmachan = hw_config->dma; - audio_devs[my_dev]->buffcount = 1; + audio_devs[my_dev]->dmachan1 = dma8; audio_devs[my_dev]->buffsize = DSP_BUFFSIZE; + + if (sound_alloc_dma (dma8, "SB16 (8bit)")) + { + printk ("SB16: Unable to grab DMA%d\n", dma8); + } + + if (dma16 != dma8) + if (sound_alloc_dma (dma16, "SB16 (16bit)")) + { + printk ("SB16: Unable to grab DMA%d\n", dma16); + } } else printk ("SB: Too many DSP devices available\n"); @@ -538,11 +550,21 @@ } void +unload_sb16 (struct address_info *hw_config) +{ + + sound_free_dma (dma8); + + if (dma16 != dma8) + sound_free_dma (dma16); +} + +void sb16_dsp_interrupt (int unused) { int data; - data = INB (DSP_DATA_AVL16); /* + data = inb (DSP_DATA_AVL16); /* * Interrupt acknowledge */ diff -u --recursive --new-file v1.3.33/linux/drivers/sound/sb16_midi.c linux/drivers/sound/sb16_midi.c --- v1.3.33/linux/drivers/sound/sb16_midi.c Tue Jul 11 10:02:54 1995 +++ linux/drivers/sound/sb16_midi.c Wed Oct 11 07:55:42 1995 @@ -39,12 +39,14 @@ #define COMDPORT (sb16midi_base+1) #define STATPORT (sb16midi_base+1) -#define sb16midi_status() INB(STATPORT) +extern sound_os_info *sb_osp; + +#define sb16midi_status() inb( STATPORT) #define input_avail() (!(sb16midi_status()&INPUT_AVAIL)) #define output_ready() (!(sb16midi_status()&OUTPUT_READY)) -#define sb16midi_cmd(cmd) OUTB(cmd, COMDPORT) -#define sb16midi_read() INB(DATAPORT) -#define sb16midi_write(byte) OUTB(byte, DATAPORT) +#define sb16midi_cmd(cmd) outb( cmd, COMDPORT) +#define sb16midi_read() inb( DATAPORT) +#define sb16midi_write(byte) outb( byte, DATAPORT) #define OUTPUT_READY 0x40 #define INPUT_AVAIL 0x80 @@ -88,7 +90,7 @@ { if (sb16midi_opened) { - return RET_ERROR (EBUSY); + return -EBUSY; } sb16midi_input_loop (); @@ -115,12 +117,13 @@ * Test for input since pending input seems to block the output. */ - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (input_avail ()) sb16midi_input_loop (); - RESTORE_INTR (flags); + restore_flags (flags); /* * Sometimes it takes about 13000 loops before the output becomes ready @@ -154,9 +157,9 @@ } static int -sb16midi_ioctl (int dev, unsigned cmd, unsigned arg) +sb16midi_ioctl (int dev, unsigned cmd, ioctl_arg arg) { - return RET_ERROR (EINVAL); + return -EINVAL; } static void @@ -203,9 +206,10 @@ sb16midi_base = hw_config->io_base; if (!sb16midi_detected) - return RET_ERROR (EIO); + return -EIO; - DISABLE_INTR (flags); + save_flags (flags); + cli (); for (timeout = 30000; timeout < 0 && !output_ready (); timeout--); /* * Wait */ @@ -217,7 +221,7 @@ if (sb16midi_read () == MPU_ACK) ok = 1; - RESTORE_INTR (flags); + restore_flags (flags); if (num_midis >= MAX_MIDI_DEV) { @@ -244,7 +248,8 @@ ok = 0; - DISABLE_INTR (flags); + save_flags (flags); + cli (); for (n = 0; n < 2 && !ok; n++) { @@ -273,7 +278,7 @@ * Flush input before enabling interrupts */ - RESTORE_INTR (flags); + restore_flags (flags); return ok; } @@ -297,6 +302,11 @@ sb16midi_detected = ok; return ok; +} + +void +unload_sb16midi (struct address_info *hw_config) +{ } #endif diff -u --recursive --new-file v1.3.33/linux/drivers/sound/sb_card.c linux/drivers/sound/sb_card.c --- v1.3.33/linux/drivers/sound/sb_card.c Tue Jul 11 10:02:54 1995 +++ linux/drivers/sound/sb_card.c Wed Oct 11 07:55:42 1995 @@ -41,6 +41,7 @@ if (!sb_dsp_detect (hw_config)) return mem_start; mem_start = sb_dsp_init (mem_start, hw_config); + request_region (hw_config->io_base, 16, "SB"); #endif return mem_start; @@ -49,6 +50,13 @@ int probe_sb (struct address_info *hw_config) { + if (check_region (hw_config->io_base, 16)) + { + printk ("\n\nsb_dsp.c: I/O port %x already in use\n\n", + hw_config->io_base); + return 0; + } + #if !defined(EXCLUDE_AEDSP16) && defined(AEDSP16_SBPRO) /* * Initialize Audio Excel DSP 16 to SBPRO. @@ -56,6 +64,13 @@ InitAEDSP16_SBPRO (hw_config); #endif return sb_dsp_detect (hw_config); +} + +void +unload_sb (struct address_info *hw_config) +{ + release_region (hw_config->io_base, 16); + sb_dsp_unload (); } #endif diff -u --recursive --new-file v1.3.33/linux/drivers/sound/sb_dsp.c linux/drivers/sound/sb_dsp.c --- v1.3.33/linux/drivers/sound/sb_dsp.c Sun Aug 13 14:45:34 1995 +++ linux/drivers/sound/sb_dsp.c Wed Oct 11 07:55:42 1995 @@ -37,6 +37,10 @@ #if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB) +#ifdef SM_WAVE +#define JAZZ16 +#endif + #include "sb.h" #include "sb_mixer.h" #undef SB_TEST_IRQ @@ -46,6 +50,7 @@ static int open_mode = 0; /* Read, write or both */ int Jazz16_detected = 0; int sb_no_recording = 0; +static int dsp_count = 0; /* * The DSP channel can be used either for input or output. Variable @@ -87,12 +92,13 @@ * IMODE_NONE */ static volatile int irq_ok = 0; +static int dma8 = 1; + #ifdef JAZZ16 /* 16 bit support */ static int dsp_16bit = 0; -static int dma8 = 1; static int dma16 = 5; static int dsp_set_bits (int arg); @@ -110,6 +116,8 @@ static int dsp_speed (int); static int dsp_set_stereo (int mode); int sb_dsp_command (unsigned char val); +static void sb_dsp_reset (int dev); +sound_os_info *sb_osp = NULL; #if !defined(EXCLUDE_MIDI) || !defined(EXCLUDE_AUDIO) @@ -123,9 +131,9 @@ int i; unsigned long limit; - limit = GET_TIME () + HZ / 10; /* - * The timeout is 0.1 secods - */ + limit = jiffies + HZ / 10; /* + * The timeout is 0.1 secods + */ /* * Note! the i<500000 is an emergency exit. The sb_dsp_command() is sometimes @@ -135,11 +143,11 @@ * loops. */ - for (i = 0; i < 500000 && GET_TIME () < limit; i++) + for (i = 0; i < 500000 && jiffies < limit; i++) { - if ((INB (DSP_STATUS) & 0x80) == 0) + if ((inb (DSP_STATUS) & 0x80) == 0) { - OUTB (val, DSP_COMMAND); + outb (val, DSP_COMMAND); return 1; } } @@ -150,7 +158,7 @@ } void -sbintr (INT_HANDLER_PARMS (irq, dummy)) +sbintr (int irq, struct pt_regs *dummy) { int status; @@ -179,7 +187,7 @@ } #endif - status = INB (DSP_DATA_AVAIL); /* + status = inb (DSP_DATA_AVAIL); /* * Clear interrupt */ @@ -215,32 +223,15 @@ } } -static int sb_irq_usecount = 0; - int sb_get_irq (void) { - int ok; - - if (!sb_irq_usecount) - if ((ok = snd_set_irq_handler (sbc_irq, sbintr, "SoundBlaster")) < 0) - return ok; - - sb_irq_usecount++; - return 0; } void sb_free_irq (void) { - if (!sb_irq_usecount) - return; - - sb_irq_usecount--; - - if (!sb_irq_usecount) - snd_release_irq (sbc_irq); } int @@ -248,26 +239,17 @@ { int loopc; - OUTB (1, DSP_RESET); + outb (1, DSP_RESET); tenmicrosec (); - OUTB (0, DSP_RESET); + outb (0, DSP_RESET); tenmicrosec (); tenmicrosec (); tenmicrosec (); - for (loopc = 0; loopc < 1000 && !(INB (DSP_DATA_AVAIL) & 0x80); loopc++); /* - * Wait - * for - * data - * * - * available - * status - */ + for (loopc = 0; loopc < 1000 && !(inb (DSP_DATA_AVAIL) & 0x80); loopc++); - if (INB (DSP_READ) != 0xAA) - return 0; /* - * Sorry - */ + if (inb (DSP_READ) != 0xAA) + return 0; /* Sorry */ return 1; } @@ -350,10 +332,11 @@ ((256000000 + speed / 2) / speed)) >> 8); sb_dsp_highspeed = 1; - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (sb_dsp_command (0x40)) sb_dsp_command (tconst); - RESTORE_INTR (flags); + restore_flags (flags); tmp = 65536 - (tconst << 8); speed = (256000000 + tmp / 2) / tmp; @@ -365,12 +348,13 @@ sb_dsp_highspeed = 0; tconst = (256 - ((1000000 + speed / 2) / speed)) & 0xff; - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (sb_dsp_command (0x40)) /* * Set time constant */ sb_dsp_command (tconst); - RESTORE_INTR (flags); + restore_flags (flags); tmp = 256 - tconst; speed = (1000000 + tmp / 2) / tmp; @@ -416,43 +400,48 @@ if (!sb_irq_mode) dsp_speaker (ON); - sb_irq_mode = IMODE_OUTPUT; DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE); - if (audio_devs[dev]->dmachan > 3) + sb_irq_mode = 0; + + if (audio_devs[dev]->dmachan1 > 3) count >>= 1; count--; + dsp_count = count; + sb_irq_mode = IMODE_OUTPUT; if (sb_dsp_highspeed) { - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (sb_dsp_command (0x48)) /* * High speed size */ { - sb_dsp_command ((unsigned char) (count & 0xff)); - sb_dsp_command ((unsigned char) ((count >> 8) & 0xff)); + sb_dsp_command ((unsigned char) (dsp_count & 0xff)); + sb_dsp_command ((unsigned char) ((dsp_count >> 8) & 0xff)); sb_dsp_command (0x91); /* * High speed 8 bit DAC */ } else printk ("SB Error: Unable to start (high speed) DAC\n"); - RESTORE_INTR (flags); + restore_flags (flags); } else { - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (sb_dsp_command (0x14)) /* * 8-bit DAC (DMA) */ { - sb_dsp_command ((unsigned char) (count & 0xff)); - sb_dsp_command ((unsigned char) ((count >> 8) & 0xff)); + sb_dsp_command ((unsigned char) (dsp_count & 0xff)); + sb_dsp_command ((unsigned char) ((dsp_count >> 8) & 0xff)); } else printk ("SB Error: Unable to start DAC\n"); - RESTORE_INTR (flags); + restore_flags (flags); } sb_intr_active = 1; } @@ -461,58 +450,77 @@ sb_dsp_start_input (int dev, unsigned long buf, int count, int intrflag, int restart_dma) { + unsigned long flags; + + if (sb_no_recording) + { + printk ("SB Error: This device doesn't support recording\n"); + return; + } + /* * Start a DMA input to the buffer pointed by dmaqtail */ - unsigned long flags; - if (!sb_irq_mode) dsp_speaker (OFF); - sb_irq_mode = IMODE_INPUT; DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ); + sb_irq_mode = 0; - if (audio_devs[dev]->dmachan > 3) + if (audio_devs[dev]->dmachan1 > 3) count >>= 1; count--; + dsp_count = count; + sb_irq_mode = IMODE_INPUT; if (sb_dsp_highspeed) { - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (sb_dsp_command (0x48)) /* * High speed size */ { - sb_dsp_command ((unsigned char) (count & 0xff)); - sb_dsp_command ((unsigned char) ((count >> 8) & 0xff)); + sb_dsp_command ((unsigned char) (dsp_count & 0xff)); + sb_dsp_command ((unsigned char) ((dsp_count >> 8) & 0xff)); sb_dsp_command (0x99); /* * High speed 8 bit ADC */ } else printk ("SB Error: Unable to start (high speed) ADC\n"); - RESTORE_INTR (flags); + restore_flags (flags); } else { - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (sb_dsp_command (0x24)) /* * 8-bit ADC (DMA) */ { - sb_dsp_command ((unsigned char) (count & 0xff)); - sb_dsp_command ((unsigned char) ((count >> 8) & 0xff)); + sb_dsp_command ((unsigned char) (dsp_count & 0xff)); + sb_dsp_command ((unsigned char) ((dsp_count >> 8) & 0xff)); } else printk ("SB Error: Unable to start ADC\n"); - RESTORE_INTR (flags); + restore_flags (flags); } sb_intr_active = 1; } static void +sb_dsp_trigger (int dev, int bits) +{ + if (!bits) + sb_dsp_command (0xd0); /* Halt DMA */ + else if (bits & sb_irq_mode) + sb_dsp_command (0xd4); /* Continue DMA */ +} + +static void dsp_cleanup (void) { sb_intr_active = 0; @@ -532,7 +540,7 @@ /* Select correct dma channel * for 16/8 bit acccess */ - audio_devs[my_dev]->dmachan = dsp_16bit ? dma16 : dma8; + audio_devs[my_dev]->dmachan1 = dsp_16bit ? dma16 : dma8; if (dsp_stereo) sb_dsp_command (dsp_16bit ? 0xac : 0xa8); else @@ -567,7 +575,7 @@ #ifdef JAZZ16 /* 16 bit specific instructions */ - audio_devs[my_dev]->dmachan = dsp_16bit ? dma16 : dma8; + audio_devs[my_dev]->dmachan1 = dsp_16bit ? dma16 : dma8; if (Jazz16_detected != 2) /* SM Wave */ sb_mixer_set_stereo (dsp_stereo); if (dsp_stereo) @@ -594,36 +602,7 @@ static int verify_irq (void) { -#if 0 - DEFINE_WAIT_QUEUE (testq, testf); - - irq_ok = 0; - - if (sb_get_irq () == -1) - { - printk ("*** SB Error: Irq %d already in use\n", sbc_irq); - return 0; - } - - - sb_irq_mode = IMODE_INIT; - - sb_dsp_command (0xf2); /* - * This should cause immediate interrupt - */ - - DO_SLEEP (testq, testf, HZ / 5); - - sb_free_irq (); - - if (!irq_ok) - { - printk ("SB Warning: IRQ%d test not passed!", sbc_irq); - irq_ok = 1; - } -#else irq_ok = 1; -#endif return irq_ok; } @@ -635,19 +614,18 @@ if (!sb_dsp_ok) { printk ("SB Error: SoundBlaster board not installed\n"); - return RET_ERROR (ENXIO); + return -ENXIO; } if (sb_no_recording && mode & OPEN_READ) { - printk ("SB Error: Recording not supported by this device\n"); - return RET_ERROR (ENOTTY); + printk ("SB Warning: Recording not supported by this device\n"); } if (sb_intr_active || (sb_midi_busy && sb_midi_mode == UART_MIDI)) { printk ("SB: PCM not possible during MIDI input\n"); - return RET_ERROR (EBUSY); + return -EBUSY; } if (!irq_verified) @@ -666,26 +644,19 @@ /* Allocate 8 bit dma */ #ifdef JAZZ16 - audio_devs[my_dev]->dmachan = dma8; + audio_devs[my_dev]->dmachan1 = dma8; #endif - - if (DMAbuf_open_dma (dev) < 0) - { - sb_free_irq (); - printk ("SB: DMA Busy\n"); - return RET_ERROR (EBUSY); - } #ifdef JAZZ16 /* Allocate 16 bit dma */ if (Jazz16_detected != 0) if (dma16 != dma8) { - if (ALLOC_DMA_CHN (dma16, "Jazz16 16 bit")) + if (sound_open_dma (dma16, "Jazz16 16 bit")) { sb_free_irq (); - DMAbuf_close_dma (dev); - return RET_ERROR (EBUSY); + /* DMAbuf_close_dma (dev); */ + return -EBUSY; } } #endif @@ -706,15 +677,14 @@ */ if (Jazz16_detected) { - if (audio_devs[my_dev]->dmachan == dma8) - RELEASE_DMA_CHN (dma16); - else - RELEASE_DMA_CHN (dma8); + audio_devs[my_dev]->dmachan1 = dma8; + if (dma16 != dma8) + sound_close_dma (dma16); } #endif - DMAbuf_close_dma (dev); + /* DMAbuf_close_dma (dev); */ sb_free_irq (); dsp_cleanup (); dsp_speaker (OFF); @@ -750,38 +720,38 @@ #endif /* ifdef JAZZ16 */ static int -sb_dsp_ioctl (int dev, unsigned int cmd, unsigned int arg, int local) +sb_dsp_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local) { switch (cmd) { case SOUND_PCM_WRITE_RATE: if (local) - return dsp_speed (arg); - return IOCTL_OUT (arg, dsp_speed (IOCTL_IN (arg))); + return dsp_speed ((int) arg); + return snd_ioctl_return ((int *) arg, dsp_speed (get_fs_long ((long *) arg))); break; case SOUND_PCM_READ_RATE: if (local) return dsp_current_speed; - return IOCTL_OUT (arg, dsp_current_speed); + return snd_ioctl_return ((int *) arg, dsp_current_speed); break; case SOUND_PCM_WRITE_CHANNELS: if (local) - return dsp_set_stereo (arg - 1) + 1; - return IOCTL_OUT (arg, dsp_set_stereo (IOCTL_IN (arg) - 1) + 1); + return dsp_set_stereo ((int) arg - 1) + 1; + return snd_ioctl_return ((int *) arg, dsp_set_stereo (get_fs_long ((long *) arg) - 1) + 1); break; case SOUND_PCM_READ_CHANNELS: if (local) return dsp_stereo + 1; - return IOCTL_OUT (arg, dsp_stereo + 1); + return snd_ioctl_return ((int *) arg, dsp_stereo + 1); break; case SNDCTL_DSP_STEREO: if (local) - return dsp_set_stereo (arg); - return IOCTL_OUT (arg, dsp_set_stereo (IOCTL_IN (arg))); + return dsp_set_stereo ((int) arg); + return snd_ioctl_return ((int *) arg, dsp_set_stereo (get_fs_long ((long *) arg))); break; #ifdef JAZZ16 @@ -790,36 +760,35 @@ */ case SNDCTL_DSP_SETFMT: if (local) - return dsp_set_bits (arg); - return IOCTL_OUT (arg, dsp_set_bits (IOCTL_IN (arg))); + return dsp_set_bits ((int) arg); + return snd_ioctl_return ((int *) arg, dsp_set_bits (get_fs_long ((long *) arg))); break; case SOUND_PCM_READ_BITS: if (local) return dsp_16bit ? 16 : 8; - return IOCTL_OUT (arg, dsp_16bit ? 16 : 8); + return snd_ioctl_return ((int *) arg, dsp_16bit ? 16 : 8); break; #else case SOUND_PCM_WRITE_BITS: case SOUND_PCM_READ_BITS: if (local) return 8; - return IOCTL_OUT (arg, 8); /* - * Only 8 bits/sample supported - */ + return snd_ioctl_return ((int *) (int) arg, 8); /* + * Only 8 bits/sample supported + */ break; #endif /* ifdef JAZZ16 */ case SOUND_PCM_WRITE_FILTER: case SOUND_PCM_READ_FILTER: - return RET_ERROR (EINVAL); + return -EINVAL; break; - default: - return RET_ERROR (EINVAL); + default:; } - return RET_ERROR (EINVAL); + return -EINVAL; } static void @@ -827,13 +796,14 @@ { unsigned long flags; - DISABLE_INTR (flags); + save_flags (flags); + cli (); sb_reset_dsp (); dsp_speed (dsp_current_speed); dsp_cleanup (); - RESTORE_INTR (flags); + restore_flags (flags); } #endif @@ -866,9 +836,9 @@ int i; for (i = 1000; i; i--) - if (INB (DSP_DATA_AVAIL) & 0x80) + if (inb (DSP_DATA_AVAIL) & 0x80) { - return INB (DSP_READ); + return inb (DSP_READ); } return 0xffff; @@ -890,13 +860,14 @@ { unsigned long flags; - DISABLE_INTR (flags); + save_flags (flags); + cli (); - OUTB (addr & 0xff, base + 1); /* Low address bits */ - OUTB (addr >> 8, base + 2); /* High address bits */ - OUTB (val, base); /* Data */ + outb (addr & 0xff, base + 1); /* Low address bits */ + outb (addr >> 8, base + 2); /* High address bits */ + outb (val, base); /* Data */ - RESTORE_INTR (flags); + restore_flags (flags); } static unsigned char @@ -905,13 +876,14 @@ unsigned long flags; unsigned char val; - DISABLE_INTR (flags); + save_flags (flags); + cli (); - OUTB (addr & 0xff, base + 1); /* Low address bits */ - OUTB (addr >> 8, base + 2); /* High address bits */ - val = INB (base); /* Data */ + outb (addr & 0xff, base + 1); /* Low address bits */ + outb (addr >> 8, base + 2); /* High address bits */ + val = inb (base); /* Data */ - RESTORE_INTR (flags); + restore_flags (flags); return val; } @@ -934,14 +906,14 @@ * Reset the microcontroller so that the RAM can be accessed */ - control = INB (MPU_BASE + 7); - OUTB (control | 3, MPU_BASE + 7); /* Set last two bits to 1 (?) */ - OUTB ((control & 0xfe) | 2, MPU_BASE + 7); /* xxxxxxx0 resets the mc */ + control = inb (MPU_BASE + 7); + outb (control | 3, MPU_BASE + 7); /* Set last two bits to 1 (?) */ + outb ((control & 0xfe) | 2, MPU_BASE + 7); /* xxxxxxx0 resets the mc */ for (i = 0; i < 300; i++) /* Wait at least 1ms */ tenmicrosec (); - OUTB (control & 0xfc, MPU_BASE + 7); /* xxxxxx00 enables RAM */ + outb (control & 0xfc, MPU_BASE + 7); /* xxxxxx00 enables RAM */ /* * Detect microcontroller by probing the 8k RAM area @@ -967,7 +939,6 @@ printk ("\nSM Wave: Invalid microcode (MIDI0001.BIN) length\n"); return 1; } -#endif /* * Download microcode @@ -987,6 +958,8 @@ return 0; } +#endif + control = 0; #ifdef SMW_SCSI_IRQ /* @@ -1015,7 +988,7 @@ /* control |= 0x20; Uncomment this if you want to use IRQ7 */ #endif - OUTB (control | 0x03, MPU_BASE + 7); /* xxxxxx11 restarts */ + outb (control | 0x03, MPU_BASE + 7); /* xxxxxx11 restarts */ return 1; } @@ -1029,11 +1002,11 @@ {0, 0, 2, 3, 0, 1, 0, 4, 0, 2, 5, 0, 0, 0, 0, 6}, dma_translat[8] = {0, 1, 0, 2, 0, 3, 0, 4}; - OUTB (0xAF, 0x201); /* ProSonic/Jazz16 wakeup */ + outb (0xAF, 0x201); /* ProSonic/Jazz16 wakeup */ for (x = 0; x < 1000; ++x) /* wait 10 milliseconds */ tenmicrosec (); - OUTB (0x50, 0x201); - OUTB ((sbc_base & 0x70) | ((MPU_BASE & 0x30) >> 4), 0x201); + outb (0x50, 0x201); + outb ((sbc_base & 0x70) | ((MPU_BASE & 0x30) >> 4), 0x201); if (sb_reset_dsp ()) { /* OK. We have at least a SB */ @@ -1069,13 +1042,15 @@ { sbc_base = hw_config->io_base; sbc_irq = hw_config->irq; + sb_osp = hw_config->osp; if (sb_dsp_ok) return 0; /* * Already initialized */ -#ifdef JAZZ16 dma8 = hw_config->dma; + +#ifdef JAZZ16 dma16 = JAZZ_DMA16; if (!initialize_ProSonic16 ()) @@ -1107,7 +1082,10 @@ sb_dsp_reset, sb_dsp_halt_xfer, NULL, /* local_qlen */ - NULL /* copy_from_user */ + NULL, /* copy_from_user */ + NULL, + NULL, + sb_dsp_trigger }; #endif @@ -1116,8 +1094,13 @@ sb_dsp_init (long mem_start, struct address_info *hw_config) { int i; + +#ifndef EXCLUDE_SBPRO int mixer_type = 0; +#endif + + sb_osp = hw_config->osp; sbc_major = sbc_minor = 0; sb_dsp_command (0xe1); /* * Get version @@ -1125,15 +1108,15 @@ for (i = 1000; i; i--) { - if (INB (DSP_DATA_AVAIL) & 0x80) + if (inb (DSP_DATA_AVAIL) & 0x80) { /* * wait for Data Ready */ if (sbc_major == 0) - sbc_major = INB (DSP_READ); + sbc_major = inb (DSP_READ); else { - sbc_minor = INB (DSP_READ); + sbc_minor = inb (DSP_READ); break; } } @@ -1142,7 +1125,7 @@ if (sbc_major == 0) { printk ("\n\nFailed to get SB version (%x) - possible I/O conflict\n\n", - INB (DSP_DATA_AVAIL)); + inb (DSP_DATA_AVAIL)); sbc_major = 1; } @@ -1152,6 +1135,42 @@ if (sbc_major == 4) sb16 = 1; + if (sbc_major == 3 && sbc_minor == 1) + { + int ess_major = 0, ess_minor = 0; + +/* + * Try to detect ESS chips. + */ + + sb_dsp_command (0xe7); /* + * Return identification bytes. + */ + + for (i = 1000; i; i--) + { + if (inb (DSP_DATA_AVAIL) & 0x80) + { /* + * wait for Data Ready + */ + if (ess_major == 0) + ess_major = inb (DSP_READ); + else + { + ess_minor = inb (DSP_READ); + break; + } + } + } + + if (ess_major == 0x48 && (ess_minor & 0xf0) == 0x80) + printk ("Hmm... Could this be an ESS488 based card (rev %d)\n", + ess_minor & 0x0f); + else if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80) + printk ("Hmm... Could this be an ESS688 based card (rev %d)\n", + ess_minor & 0x0f); + } + #ifndef EXCLUDE_SBPRO if (sbc_major >= 3) mixer_type = sb_mixer_init (sbc_major); @@ -1163,7 +1182,7 @@ #ifndef EXCLUDE_YM3812 if (sbc_major > 3 || - (sbc_major == 3 && INB (0x388) == 0x00)) /* Should be 0x06 if not OPL-3 */ + (sbc_major == 3 && inb (0x388) == 0x00)) /* Should be 0x06 if not OPL-3 */ enable_opl3_mode (OPL3_LEFT, OPL3_RIGHT, OPL3_BOTH); #endif @@ -1211,9 +1230,25 @@ if (num_audiodevs < MAX_AUDIO_DEV) { audio_devs[my_dev = num_audiodevs++] = &sb_dsp_operations; - audio_devs[my_dev]->buffcount = DSP_BUFFCOUNT; audio_devs[my_dev]->buffsize = DSP_BUFFSIZE; - audio_devs[my_dev]->dmachan = hw_config->dma; + dma8 = audio_devs[my_dev]->dmachan1 = hw_config->dma; + audio_devs[my_dev]->dmachan2 = -1; + if (sound_alloc_dma (hw_config->dma, "soundblaster")) + printk ("sb_dsp.c: Can't allocate DMA channel\n"); +#ifdef JAZZ16 + /* Allocate 16 bit dma + */ + if (Jazz16_detected != 0) + if (dma16 != dma8) + { + if (sound_alloc_dma (dma16, "Jazz16 16 bit")) + { + printk ("Jazz16: Can't allocate 16 bit DMA channel\n"); + } + } +#endif + if (snd_set_irq_handler (sbc_irq, sbintr, "SoundBlaster", sb_osp) < 0) + printk ("sb_dsp: Can't allocate IRQ\n");; } else printk ("SB: Too many DSP devices available\n"); @@ -1231,6 +1266,22 @@ sb_dsp_ok = 1; return mem_start; +} + +void +sb_dsp_unload (void) +{ + sound_free_dma (dma8); +#ifdef JAZZ16 + /* Allocate 16 bit dma + */ + if (Jazz16_detected != 0) + if (dma16 != dma8) + { + sound_free_dma (dma16); + } +#endif + snd_release_irq (sbc_irq); } void diff -u --recursive --new-file v1.3.33/linux/drivers/sound/sb_midi.c linux/drivers/sound/sb_midi.c --- v1.3.33/linux/drivers/sound/sb_midi.c Tue Jul 11 10:02:54 1995 +++ linux/drivers/sound/sb_midi.c Wed Oct 11 07:55:42 1995 @@ -61,6 +61,8 @@ int input_opened = 0; static int my_dev; +extern sound_os_info *sb_osp; + void (*midi_input_intr) (int dev, unsigned char data); static int @@ -74,31 +76,31 @@ if (!sb_dsp_ok) { printk ("SB Error: MIDI hardware not installed\n"); - return RET_ERROR (ENXIO); + return -ENXIO; } if (sb_midi_busy) - return RET_ERROR (EBUSY); + return -EBUSY; if (mode != OPEN_WRITE && !sb_duplex_midi) { if (num_midis == 1) printk ("SoundBlaster: Midi input not currently supported\n"); - return RET_ERROR (EPERM); + return -EPERM; } sb_midi_mode = NORMAL_MIDI; if (mode != OPEN_WRITE) { if (sb_dsp_busy || sb_intr_active) - return RET_ERROR (EBUSY); + return -EBUSY; sb_midi_mode = UART_MIDI; } if (sb_dsp_highspeed) { printk ("SB Error: Midi output not possible during stereo or high speed audio\n"); - return RET_ERROR (EBUSY); + return -EBUSY; } if (sb_midi_mode == UART_MIDI) @@ -108,8 +110,8 @@ sb_reset_dsp (); if (!sb_dsp_command (0x35)) - return RET_ERROR (EIO); /* - * Enter the UART mode + return -EIO; /* + * Enter the UART mode */ sb_intr_active = 1; @@ -151,12 +153,13 @@ if (sb_midi_mode == NORMAL_MIDI) { - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (sb_dsp_command (0x38)) sb_dsp_command (midi_byte); else printk ("SB Error: Unable to send a MIDI byte\n"); - RESTORE_INTR (flags); + restore_flags (flags); } else sb_dsp_command (midi_byte); /* @@ -172,7 +175,7 @@ if (sb_midi_mode != UART_MIDI) { printk ("SoundBlaster: MIDI input not implemented.\n"); - return RET_ERROR (EPERM); + return -EPERM; } return 0; } @@ -189,9 +192,9 @@ } static int -sb_midi_ioctl (int dev, unsigned cmd, unsigned arg) +sb_midi_ioctl (int dev, unsigned cmd, ioctl_arg arg) { - return RET_ERROR (EPERM); + return -EPERM; } void @@ -200,13 +203,14 @@ unsigned long flags; unsigned char data; - DISABLE_INTR (flags); + save_flags (flags); + cli (); - data = INB (DSP_READ); + data = inb (DSP_READ); if (input_opened) midi_input_intr (my_dev, data); - RESTORE_INTR (flags); + restore_flags (flags); } #define MIDI_SYNTH_NAME "SoundBlaster Midi" diff -u --recursive --new-file v1.3.33/linux/drivers/sound/sb_mixer.c linux/drivers/sound/sb_mixer.c --- v1.3.33/linux/drivers/sound/sb_mixer.c Tue Jul 11 10:02:54 1995 +++ linux/drivers/sound/sb_mixer.c Wed Oct 11 07:55:42 1995 @@ -43,6 +43,7 @@ extern int sbc_base; extern int Jazz16_detected; +extern sound_os_info *sb_osp; static int mixer_initialized = 0; @@ -58,14 +59,15 @@ { unsigned long flags; - DISABLE_INTR (flags); - OUTB ((unsigned char) (port & 0xff), MIXER_ADDR); /* + save_flags (flags); + cli (); + outb ((unsigned char) (port & 0xff), MIXER_ADDR); /* * Select register */ tenmicrosec (); - OUTB ((unsigned char) (value & 0xff), MIXER_DATA); + outb ((unsigned char) (value & 0xff), MIXER_DATA); tenmicrosec (); - RESTORE_INTR (flags); + restore_flags (flags); } int @@ -74,14 +76,15 @@ int val; unsigned long flags; - DISABLE_INTR (flags); - OUTB ((unsigned char) (port & 0xff), MIXER_ADDR); /* + save_flags (flags); + cli (); + outb ((unsigned char) (port & 0xff), MIXER_ADDR); /* * Select register */ tenmicrosec (); - val = INB (MIXER_DATA); + val = inb (MIXER_DATA); tenmicrosec (); - RESTORE_INTR (flags); + restore_flags (flags); return val; } @@ -107,10 +110,10 @@ { #ifdef __SGNXPRO__ int oldbass, oldtreble; + extern int sbc_major; #endif int retcode = 1; - extern int sbc_major; /* * Detect the mixer by changing parameters of two volume channels. If the @@ -160,8 +163,8 @@ */ if (sbc_major == 3) { - OUTB (0x01, sbc_base + 0x1c); - OUTB (0x00, sbc_base + 0x1a); + outb (0x01, sbc_base + 0x1c); + outb (0x00, sbc_base + 0x1a); } #endif @@ -193,7 +196,7 @@ sb_mixer_get (int dev) { if (!((1 << dev) & supported_devices)) - return RET_ERROR (EINVAL); + return -EINVAL; return levels[dev]; } @@ -251,10 +254,10 @@ right = 100; if (dev > 31) - return RET_ERROR (EINVAL); + return -EINVAL; if (!(supported_devices & (1 << dev))) /* Not supported */ - return RET_ERROR (EINVAL); + return -EINVAL; switch (dev) { @@ -281,7 +284,7 @@ default: reg = smw_mix_regs[dev]; if (reg == 0) - return RET_ERROR (EINVAL); + return -EINVAL; sb_setmixer (reg, (24 - (24 * left / 100)) | 0x20); /* 24=mute, 0=max */ sb_setmixer (reg + 1, (24 - (24 * right / 100)) | 0x40); } @@ -312,17 +315,17 @@ right = 100; if (dev > 31) - return RET_ERROR (EINVAL); + return -EINVAL; if (!(supported_devices & (1 << dev))) /* * Not supported */ - return RET_ERROR (EINVAL); + return -EINVAL; regoffs = (*iomap)[dev][LEFT_CHN].regno; if (regoffs == 0) - return RET_ERROR (EINVAL); + return -EINVAL; val = sb_getmixer (regoffs); change_bits (&val, dev, LEFT_CHN, left); @@ -442,7 +445,7 @@ } static int -sb_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg) +sb_mixer_ioctl (int dev, unsigned int cmd, ioctl_arg arg) { if (((cmd >> 8) & 0xff) == 'M') { @@ -450,12 +453,12 @@ switch (cmd & 0xff) { case SOUND_MIXER_RECSRC: - return IOCTL_OUT (arg, set_recmask (IOCTL_IN (arg))); + return snd_ioctl_return ((int *) arg, set_recmask (get_fs_long ((long *) arg))); break; default: - return IOCTL_OUT (arg, sb_mixer_set (cmd & 0xff, IOCTL_IN (arg))); + return snd_ioctl_return ((int *) arg, sb_mixer_set (cmd & 0xff, get_fs_long ((long *) arg))); } else switch (cmd & 0xff) /* @@ -464,35 +467,34 @@ { case SOUND_MIXER_RECSRC: - return IOCTL_OUT (arg, recmask); + return snd_ioctl_return ((int *) arg, recmask); break; case SOUND_MIXER_DEVMASK: - return IOCTL_OUT (arg, supported_devices); + return snd_ioctl_return ((int *) arg, supported_devices); break; case SOUND_MIXER_STEREODEVS: if (Jazz16_detected) - return IOCTL_OUT (arg, supported_devices); + return snd_ioctl_return ((int *) arg, supported_devices); else - return IOCTL_OUT (arg, supported_devices & - ~(SOUND_MASK_MIC | SOUND_MASK_SPEAKER)); + return snd_ioctl_return ((int *) arg, supported_devices & ~(SOUND_MASK_MIC | SOUND_MASK_SPEAKER)); break; case SOUND_MIXER_RECMASK: - return IOCTL_OUT (arg, supported_rec_devices); + return snd_ioctl_return ((int *) arg, supported_rec_devices); break; case SOUND_MIXER_CAPS: - return IOCTL_OUT (arg, mixer_caps); + return snd_ioctl_return ((int *) arg, mixer_caps); break; default: - return IOCTL_OUT (arg, sb_mixer_get (cmd & 0xff)); + return snd_ioctl_return ((int *) arg, sb_mixer_get (cmd & 0xff)); } } else - return RET_ERROR (EINVAL); + return -EINVAL; } static struct mixer_operations sb_mixer_operations = @@ -553,7 +555,7 @@ { supported_devices = SGNXPRO_MIXER_DEVICES; supported_rec_devices = SGNXPRO_RECORDING_DEVICES; - iomap = &sgnxpro_mix; + iomap = &sgnxpro_mix[0][0]; } else #endif diff -u --recursive --new-file v1.3.33/linux/drivers/sound/sequencer.c linux/drivers/sound/sequencer.c --- v1.3.33/linux/drivers/sound/sequencer.c Sun Aug 13 14:45:34 1995 +++ linux/drivers/sound/sequencer.c Wed Oct 11 07:55:42 1995 @@ -57,8 +57,12 @@ #define SEQ_2 2 static int seq_mode = SEQ_1; -DEFINE_WAIT_QUEUE (seq_sleeper, seq_sleep_flag); -DEFINE_WAIT_QUEUE (midi_sleeper, midi_sleep_flag); +static struct wait_queue *seq_sleeper = NULL; +static volatile struct snd_wait seq_sleep_flag = +{0}; +static struct wait_queue *midi_sleeper = NULL; +static volatile struct snd_wait midi_sleep_flag = +{0}; static int midi_opened[MAX_MIDI_DEV] = {0}; @@ -111,20 +115,40 @@ */ return pmgr_read (dev - 1, file, buf, count); - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (!iqlen) { - if (ISSET_FILE_FLAG (file, O_NONBLOCK)) + if ((file->filp->f_flags & (O_NONBLOCK) ? + 1 : 0)) { - RESTORE_INTR (flags); - return RET_ERROR (EAGAIN); + restore_flags (flags); + return -EAGAIN; } - DO_SLEEP (midi_sleeper, midi_sleep_flag, pre_event_timeout); + + { + unsigned long tl; + + if (pre_event_timeout) + tl = current->timeout = jiffies + (pre_event_timeout); + else + tl = 0xffffffff; + midi_sleep_flag.mode = WK_SLEEP; + interruptible_sleep_on (&midi_sleeper); + if (!(midi_sleep_flag.mode & WK_WAKEUP)) + { + if (current->signal & ~current->blocked) + midi_sleep_flag.aborting = 1; + else if (jiffies >= tl) + midi_sleep_flag.mode |= WK_TIMEOUT; + } + midi_sleep_flag.mode &= ~WK_SLEEP; + }; if (!iqlen) { - RESTORE_INTR (flags); + restore_flags (flags); return 0; } } @@ -132,14 +156,14 @@ while (iqlen && c >= ev_len) { - COPY_TO_USER (buf, p, &iqueue[iqhead * IEV_SZ], ev_len); + memcpy_tofs (&((buf)[p]), (&iqueue[iqhead * IEV_SZ]), (ev_len)); p += ev_len; c -= ev_len; iqhead = (iqhead + 1) % SEQ_MAX_QUEUE; iqlen--; } - RESTORE_INTR (flags); + restore_flags (flags); return count - c; } @@ -169,16 +193,20 @@ if (iqlen >= (SEQ_MAX_QUEUE - 1)) return; /* Overflow */ - DISABLE_INTR (flags); + save_flags (flags); + cli (); memcpy (&iqueue[iqtail * IEV_SZ], event, len); iqlen++; iqtail = (iqtail + 1) % SEQ_MAX_QUEUE; - if (SOMEONE_WAITING (midi_sleeper, midi_sleep_flag)) + if ((midi_sleep_flag.mode & WK_SLEEP)) { - WAKE_UP (midi_sleeper, midi_sleep_flag); + { + midi_sleep_flag.mode = WK_WAKEUP; + wake_up (&midi_sleeper); + }; } - RESTORE_INTR (flags); + restore_flags (flags); } static void @@ -190,7 +218,7 @@ if (data == 0xfe) /* Ignore active sensing */ return; - tstamp = GET_TIME () - seq_time; + tstamp = jiffies - seq_time; if (tstamp != prev_input_time) { tstamp = (tstamp << 8) | SEQ_WAIT; @@ -215,7 +243,7 @@ if (seq_mode == SEQ_2) this_time = tmr->get_time (tmr_no); else - this_time = GET_TIME () - seq_time; + this_time = jiffies - seq_time; if (this_time != prev_input_time) { @@ -235,7 +263,7 @@ } int -sequencer_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) +sequencer_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count) { unsigned char event[EV_SZ], ev_code; int p = 0, c, ev_size; @@ -247,7 +275,7 @@ DEB (printk ("sequencer_write(dev=%d, count=%d)\n", dev, count)); if (mode == OPEN_READ) - return RET_ERROR (EIO); + return -EIO; if (dev) /* * Patch manager device @@ -258,7 +286,7 @@ while (c >= 4) { - COPY_FROM_USER (event, buf, p, 4); + memcpy_fromfs ((event), &((buf)[p]), (4)); ev_code = event[0]; if (ev_code == SEQ_FULLSIZE) @@ -267,10 +295,10 @@ dev = *(unsigned short *) &event[2]; if (dev < 0 || dev >= max_synthdev) - return RET_ERROR (ENXIO); + return -ENXIO; if (!(synth_open_mask & (1 << dev))) - return RET_ERROR (ENXIO); + return -ENXIO; err = synth_devs[dev]->load_patch (dev, *(short *) &event[0], buf, p + 4, c, 0); if (err < 0) @@ -284,7 +312,7 @@ if (seq_mode == SEQ_2 && ev_code == SEQ_EXTENDED) { printk ("Sequencer: Invalid level 2 event %x\n", ev_code); - return RET_ERROR (EINVAL); + return -EINVAL; } ev_size = 8; @@ -296,7 +324,7 @@ return count - c; } - COPY_FROM_USER (&event[4], buf, p + 4, 4); + memcpy_fromfs ((&event[4]), &((buf)[p + 4]), (4)); } else @@ -304,7 +332,7 @@ if (seq_mode == SEQ_2) { printk ("Sequencer: 4 byte event in level 2 mode\n"); - return RET_ERROR (EINVAL); + return -EINVAL; } ev_size = 4; } @@ -320,7 +348,7 @@ if (dev >= max_mididev) { printk ("Sequencer Error: Nonexistent MIDI device %d\n", dev); - return RET_ERROR (ENXIO); + return -ENXIO; } mode = file->mode & O_ACCMODE; @@ -338,15 +366,17 @@ } - if (!seq_queue (event, ISSET_FILE_FLAG (file, O_NONBLOCK))) + if (!seq_queue (event, (file->filp->f_flags & (O_NONBLOCK) ? + 1 : 0))) { int processed = count - c; if (!seq_playing) seq_startplay (); - if (!processed && ISSET_FILE_FLAG (file, O_NONBLOCK)) - return RET_ERROR (EAGAIN); + if (!processed && (file->filp->f_flags & (O_NONBLOCK) ? + 1 : 0)) + return -EAGAIN; else return processed; } @@ -377,12 +407,30 @@ * Give chance to drain the queue */ - if (!nonblock && qlen >= SEQ_MAX_QUEUE && !SOMEONE_WAITING (seq_sleeper, seq_sleep_flag)) + if (!nonblock && qlen >= SEQ_MAX_QUEUE && !(seq_sleep_flag.mode & WK_SLEEP)) { /* * Sleep until there is enough space on the queue */ - DO_SLEEP (seq_sleeper, seq_sleep_flag, 0); + + { + unsigned long tl; + + if (0) + tl = current->timeout = jiffies + (0); + else + tl = 0xffffffff; + seq_sleep_flag.mode = WK_SLEEP; + interruptible_sleep_on (&seq_sleeper); + if (!(seq_sleep_flag.mode & WK_WAKEUP)) + { + if (current->signal & ~current->blocked) + seq_sleep_flag.aborting = 1; + else if (jiffies >= tl) + seq_sleep_flag.mode |= WK_TIMEOUT; + } + seq_sleep_flag.mode &= ~WK_SLEEP; + }; } if (qlen >= SEQ_MAX_QUEUE) @@ -405,10 +453,10 @@ int dev = q[2]; if (dev < 0 || dev >= max_synthdev) - return RET_ERROR (ENXIO); + return -ENXIO; if (!(synth_open_mask & (1 << dev))) - return RET_ERROR (ENXIO); + return -ENXIO; switch (q[1]) { @@ -445,7 +493,7 @@ break; default: - return RET_ERROR (EINVAL); + return -EINVAL; } return 0; @@ -525,7 +573,7 @@ if (voice == -1) voice = chn; - if (seq_mode == SEQ_2 && dev < num_synths) + if (seq_mode == SEQ_2 && (int) dev < num_synths) { /* * The MIDI channel 10 is a percussive channel. Use the note @@ -588,7 +636,7 @@ if (seq_mode == SEQ_2) { synth_devs[dev]->chn_info[chn].pgm_num = p1; - if (dev >= num_synths) + if ((int) dev >= num_synths) synth_devs[dev]->set_instr (dev, chn, p1); } else @@ -597,7 +645,6 @@ break; case MIDI_CTL_CHANGE: - if (seq_mode == SEQ_2) { if (chn > 15 || p1 > 127) @@ -605,7 +652,10 @@ synth_devs[dev]->chn_info[chn].controllers[p1] = w14 & 0x7f; - if (dev < num_synths) + if (p1 < 32) /* Setting MSB should clear LSB to 0 */ + synth_devs[dev]->chn_info[chn].controllers[p1 + 32] = 0; + + if ((int) dev < num_synths) { int val = w14 & 0x7f; int i, key; @@ -621,7 +671,7 @@ /* Handle all playing notes on this channel */ - key = (chn << 8); + key = ((int) chn << 8); for (i = 0; i < synth_devs[dev]->alloc.max_voice; i++) if ((synth_devs[dev]->alloc.map[i] & 0xff00) == key) @@ -639,7 +689,7 @@ { synth_devs[dev]->chn_info[chn].bender_value = w14; - if (dev < num_synths) + if ((int) dev < num_synths) { /* Handle all playing notes on this channel */ int i, key; @@ -676,12 +726,16 @@ { unsigned long flags; - DISABLE_INTR (flags); - if (SOMEONE_WAITING (seq_sleeper, seq_sleep_flag)) + save_flags (flags); + cli (); + if ((seq_sleep_flag.mode & WK_SLEEP)) { - WAKE_UP (seq_sleeper, seq_sleep_flag); + { + seq_sleep_flag.mode = WK_WAKEUP; + wake_up (&seq_sleeper); + }; } - RESTORE_INTR (flags); + restore_flags (flags); } } return ret; @@ -712,12 +766,16 @@ { unsigned long flags; - DISABLE_INTR (flags); - if (SOMEONE_WAITING (seq_sleeper, seq_sleep_flag)) + save_flags (flags); + cli (); + if ((seq_sleep_flag.mode & WK_SLEEP)) { - WAKE_UP (seq_sleeper, seq_sleep_flag); + { + seq_sleep_flag.mode = WK_WAKEUP; + wake_up (&seq_sleeper); + }; } - RESTORE_INTR (flags); + restore_flags (flags); } return TIMER_ARMED; @@ -725,7 +783,7 @@ break; case TMR_START: - seq_time = GET_TIME (); + seq_time = jiffies; prev_input_time = 0; prev_event_time = 0; break; @@ -758,9 +816,43 @@ static void seq_local_event (unsigned char *event) { - /* unsigned char cmd = event[1]; */ + unsigned char cmd = event[1]; + unsigned int parm = *((unsigned int *) &event[4]); + + switch (cmd) + { + case LOCL_STARTAUDIO: +#ifndef EXCLUDE_AUDIO + DMAbuf_start_devices (parm); +#endif + break; + + default:; + } +} + +static void +seq_sysex_message (unsigned char *event) +{ + int dev = event[1]; + int i, l = 0; + unsigned char *buf = &event[2]; - printk ("seq_local_event() called. WHY????????\n"); + if ((int) dev > max_synthdev) + return; + if (!(synth_open_mask & (1 << dev))) + return; + if (!synth_devs[dev]) + return; + if (!synth_devs[dev]->send_sysex) + return; + + l = 0; + for (i = 0; i < 6 && buf[i] != 0xff; i++) + l = i + 1; + + if (l > 0) + synth_devs[dev]->send_sysex (dev, buf, l); } static int @@ -792,7 +884,7 @@ case SEQ_WAIT: delay = (unsigned long *) q; /* * Bytes 1 to 3 are containing the * - * delay in GET_TIME() + * delay in jiffies */ *delay = (*delay >> 8) & 0xffffff; @@ -810,12 +902,16 @@ { unsigned long flags; - DISABLE_INTR (flags); - if (SOMEONE_WAITING (seq_sleeper, seq_sleep_flag)) + save_flags (flags); + cli (); + if ((seq_sleep_flag.mode & WK_SLEEP)) { - WAKE_UP (seq_sleeper, seq_sleep_flag); + { + seq_sleep_flag.mode = WK_WAKEUP; + wake_up (&seq_sleeper); + }; } - RESTORE_INTR (flags); + restore_flags (flags); } /* * The timer is now active and will reinvoke this function @@ -834,7 +930,7 @@ case SEQ_SYNCTIMER: /* * Reset timer */ - seq_time = GET_TIME (); + seq_time = jiffies; prev_input_time = 0; prev_event_time = 0; break; @@ -897,6 +993,10 @@ seq_local_event (q); break; + case EV_SYSEX: + seq_sysex_message (q); + break; + default:; } @@ -912,10 +1012,11 @@ while (qlen > 0) { - DISABLE_INTR (flags); + save_flags (flags); + cli (); qhead = ((this_one = qhead) + 1) % SEQ_MAX_QUEUE; qlen--; - RESTORE_INTR (flags); + restore_flags (flags); seq_playing = 1; @@ -937,12 +1038,16 @@ { unsigned long flags; - DISABLE_INTR (flags); - if (SOMEONE_WAITING (seq_sleeper, seq_sleep_flag)) + save_flags (flags); + cli (); + if ((seq_sleep_flag.mode & WK_SLEEP)) { - WAKE_UP (seq_sleeper, seq_sleep_flag); + { + seq_sleep_flag.mode = WK_WAKEUP; + wake_up (&seq_sleeper); + }; } - RESTORE_INTR (flags); + restore_flags (flags); } } @@ -1004,7 +1109,7 @@ if (!sequencer_ok) { printk ("Soundcard: Sequencer not initialized\n"); - return RET_ERROR (ENXIO); + return -ENXIO; } if (dev) /* @@ -1013,12 +1118,15 @@ { int err; + printk ("Patch manager interface is currently broken. Sorry\n"); + return -ENXIO; + dev--; if (dev >= MAX_SYNTH_DEV) - return RET_ERROR (ENXIO); + return -ENXIO; if (pmgr_present[dev]) - return RET_ERROR (EBUSY); + return -EBUSY; if ((err = pmgr_open (dev)) < 0) return err; /* * Failed @@ -1031,7 +1139,7 @@ if (sequencer_busy) { printk ("Sequencer busy\n"); - return RET_ERROR (EBUSY); + return -EBUSY; } max_mididev = num_midis; @@ -1068,7 +1176,7 @@ if (tmr == NULL) { printk ("sequencer: No timer for level 2\n"); - return RET_ERROR (ENXIO); + return -ENXIO; } setup_mode2 (); } @@ -1077,11 +1185,11 @@ if (!max_mididev) { printk ("Sequencer: No Midi devices. Input not possible\n"); - return RET_ERROR (ENXIO); + return -ENXIO; } if (!max_synthdev && !max_mididev) - return RET_ERROR (ENXIO); + return -ENXIO; synth_open_mask = 0; @@ -1112,7 +1220,7 @@ midi_opened[synth_devs[i]->midi_dev] = 1; } - seq_time = GET_TIME (); + seq_time = jiffies; prev_input_time = 0; prev_event_time = 0; @@ -1135,8 +1243,14 @@ } sequencer_busy = 1; - RESET_WAIT_QUEUE (seq_sleeper, seq_sleep_flag); - RESET_WAIT_QUEUE (midi_sleeper, midi_sleep_flag); + { + seq_sleep_flag.aborting = 0; + seq_sleep_flag.mode = WK_NONE; + }; + { + midi_sleep_flag.aborting = 0; + midi_sleep_flag.mode = WK_NONE; + }; output_treshold = SEQ_MAX_QUEUE / 2; for (i = 0; i < num_synths; i++) @@ -1157,7 +1271,7 @@ n = 1; - while (!PROCESS_ABORTING (seq_sleeper, seq_sleep_flag) && n) + while (!((current->signal & ~current->blocked)) && n) { n = 0; @@ -1172,7 +1286,25 @@ */ if (n) { - DO_SLEEP (seq_sleeper, seq_sleep_flag, HZ / 10); + + { + unsigned long tl; + + if (HZ / 10) + tl = current->timeout = jiffies + (HZ / 10); + else + tl = 0xffffffff; + seq_sleep_flag.mode = WK_SLEEP; + interruptible_sleep_on (&seq_sleeper); + if (!(seq_sleep_flag.mode & WK_WAKEUP)) + { + if (current->signal & ~current->blocked) + seq_sleep_flag.aborting = 1; + else if (jiffies >= tl) + seq_sleep_flag.mode |= WK_TIMEOUT; + } + seq_sleep_flag.mode &= ~WK_SLEEP; + }; } } } @@ -1201,8 +1333,9 @@ * * Wait until the queue is empty (if we don't have nonblock) */ - if (mode != OPEN_READ && !ISSET_FILE_FLAG (file, O_NONBLOCK)) - while (!PROCESS_ABORTING (seq_sleeper, seq_sleep_flag) && qlen) + if (mode != OPEN_READ && !(file->filp->f_flags & (O_NONBLOCK) ? + 1 : 0)) + while (!((current->signal & ~current->blocked)) && qlen) { seq_sync (); } @@ -1248,15 +1381,34 @@ { unsigned long flags; - if (qlen && !seq_playing && !PROCESS_ABORTING (seq_sleeper, seq_sleep_flag)) + if (qlen && !seq_playing && !((current->signal & ~current->blocked))) seq_startplay (); - DISABLE_INTR (flags); - if (qlen && !SOMEONE_WAITING (seq_sleeper, seq_sleep_flag)) + save_flags (flags); + cli (); + if (qlen && !(seq_sleep_flag.mode & WK_SLEEP)) { - DO_SLEEP (seq_sleeper, seq_sleep_flag, 0); + + { + unsigned long tl; + + if (0) + tl = current->timeout = jiffies + (0); + else + tl = 0xffffffff; + seq_sleep_flag.mode = WK_SLEEP; + interruptible_sleep_on (&seq_sleeper); + if (!(seq_sleep_flag.mode & WK_WAKEUP)) + { + if (current->signal & ~current->blocked) + seq_sleep_flag.aborting = 1; + else if (jiffies >= tl) + seq_sleep_flag.mode |= WK_TIMEOUT; + } + seq_sleep_flag.mode &= ~WK_SLEEP; + }; } - RESTORE_INTR (flags); + restore_flags (flags); return qlen; } @@ -1279,13 +1431,32 @@ n = 3 * HZ; /* Timeout */ - DISABLE_INTR (flags); + save_flags (flags); + cli (); while (n && !midi_devs[dev]->putc (dev, data)) { - DO_SLEEP (seq_sleeper, seq_sleep_flag, 4); + + { + unsigned long tl; + + if (4) + tl = current->timeout = jiffies + (4); + else + tl = 0xffffffff; + seq_sleep_flag.mode = WK_SLEEP; + interruptible_sleep_on (&seq_sleeper); + if (!(seq_sleep_flag.mode & WK_WAKEUP)) + { + if (current->signal & ~current->blocked) + seq_sleep_flag.aborting = 1; + else if (jiffies >= tl) + seq_sleep_flag.mode |= WK_TIMEOUT; + } + seq_sleep_flag.mode &= ~WK_SLEEP; + }; n--; } - RESTORE_INTR (flags); + restore_flags (flags); } static void @@ -1300,7 +1471,7 @@ unsigned long flags; sound_stop_timer (); - seq_time = GET_TIME (); + seq_time = jiffies; prev_input_time = 0; prev_event_time = 0; @@ -1358,13 +1529,17 @@ seq_playing = 0; - DISABLE_INTR (flags); - if (SOMEONE_WAITING (seq_sleeper, seq_sleep_flag)) + save_flags (flags); + cli (); + if ((seq_sleep_flag.mode & WK_SLEEP)) { /* printk ("Sequencer Warning: Unexpected sleeping process - Waking up\n"); */ - WAKE_UP (seq_sleeper, seq_sleep_flag); + { + seq_sleep_flag.mode = WK_WAKEUP; + wake_up (&seq_sleeper); + }; } - RESTORE_INTR (flags); + restore_flags (flags); } @@ -1392,7 +1567,7 @@ int sequencer_ioctl (int dev, struct fileinfo *file, - unsigned int cmd, unsigned int arg) + unsigned int cmd, ioctl_arg arg) { int midi_dev, orig_dev; int mode = file->mode & O_ACCMODE; @@ -1409,28 +1584,28 @@ case SNDCTL_TMR_METRONOME: case SNDCTL_TMR_SOURCE: if (dev) /* Patch manager */ - return RET_ERROR (EIO); + return -EIO; if (seq_mode != SEQ_2) - return RET_ERROR (EINVAL); + return -EINVAL; return tmr->ioctl (tmr_no, cmd, arg); break; case SNDCTL_TMR_SELECT: if (dev) /* Patch manager */ - return RET_ERROR (EIO); + return -EIO; if (seq_mode != SEQ_2) - return RET_ERROR (EINVAL); - pending_timer = IOCTL_IN (arg); + return -EINVAL; + pending_timer = get_fs_long ((long *) arg); if (pending_timer < 0 || pending_timer >= num_sound_timers) { pending_timer = -1; - return RET_ERROR (EINVAL); + return -EINVAL; } - return IOCTL_OUT (arg, pending_timer); + return snd_ioctl_return ((int *) arg, pending_timer); break; case SNDCTL_SEQ_PANIC: @@ -1441,14 +1616,14 @@ if (dev) /* * Patch manager */ - return RET_ERROR (EIO); + return -EIO; if (mode == OPEN_READ) return 0; - while (qlen && !PROCESS_ABORTING (seq_sleeper, seq_sleep_flag)) + while (qlen && !((current->signal & ~current->blocked))) seq_sync (); if (qlen) - return RET_ERROR (EINTR); + return -EINTR; else return 0; break; @@ -1457,7 +1632,7 @@ if (dev) /* * Patch manager */ - return RET_ERROR (EIO); + return -EIO; seq_reset (); return 0; @@ -1467,11 +1642,11 @@ if (dev) /* * Patch manager */ - return RET_ERROR (EIO); + return -EIO; - midi_dev = IOCTL_IN (arg); + midi_dev = get_fs_long ((long *) arg); if (midi_dev >= max_mididev) - return RET_ERROR (ENXIO); + return -ENXIO; if (!midi_opened[midi_dev]) { @@ -1493,23 +1668,23 @@ if (dev) /* * Patch manager */ - return RET_ERROR (EIO); + return -EIO; if (mode == OPEN_WRITE) return 0; - return IOCTL_OUT (arg, iqlen); + return snd_ioctl_return ((int *) arg, iqlen); break; case SNDCTL_SEQ_GETOUTCOUNT: if (mode == OPEN_READ) return 0; - return IOCTL_OUT (arg, SEQ_MAX_QUEUE - qlen); + return snd_ioctl_return ((int *) arg, SEQ_MAX_QUEUE - qlen); break; case SNDCTL_SEQ_CTRLRATE: if (dev) /* Patch manager */ - return RET_ERROR (EIO); + return -EIO; /* * If *arg == 0, just return the current rate @@ -1517,57 +1692,66 @@ if (seq_mode == SEQ_2) return tmr->ioctl (tmr_no, cmd, arg); - if (IOCTL_IN (arg) != 0) - return RET_ERROR (EINVAL); + if (get_fs_long ((long *) arg) != 0) + return -EINVAL; - return IOCTL_OUT (arg, HZ); + return snd_ioctl_return ((int *) arg, HZ); break; case SNDCTL_SEQ_RESETSAMPLES: - dev = IOCTL_IN (arg); - if (dev < 0 || dev >= num_synths) - return RET_ERROR (ENXIO); + { + int err; + + dev = get_fs_long ((long *) arg); + if (dev < 0 || dev >= num_synths) + { + return -ENXIO; + } - if (!(synth_open_mask & (1 << dev)) && !orig_dev) - return RET_ERROR (EBUSY); + if (!(synth_open_mask & (1 << dev)) && !orig_dev) + { + return -EBUSY; + } - if (!orig_dev && pmgr_present[dev]) - pmgr_inform (dev, PM_E_PATCH_RESET, 0, 0, 0, 0); + if (!orig_dev && pmgr_present[dev]) + pmgr_inform (dev, PM_E_PATCH_RESET, 0, 0, 0, 0); - return synth_devs[dev]->ioctl (dev, cmd, arg); + err = synth_devs[dev]->ioctl (dev, cmd, arg); + return err; + } break; case SNDCTL_SEQ_NRSYNTHS: - return IOCTL_OUT (arg, max_synthdev); + return snd_ioctl_return ((int *) arg, max_synthdev); break; case SNDCTL_SEQ_NRMIDIS: - return IOCTL_OUT (arg, max_mididev); + return snd_ioctl_return ((int *) arg, max_mididev); break; case SNDCTL_SYNTH_MEMAVL: { - int dev = IOCTL_IN (arg); + int dev = get_fs_long ((long *) arg); if (dev < 0 || dev >= num_synths) - return RET_ERROR (ENXIO); + return -ENXIO; if (!(synth_open_mask & (1 << dev)) && !orig_dev) - return RET_ERROR (EBUSY); + return -EBUSY; - return IOCTL_OUT (arg, synth_devs[dev]->ioctl (dev, cmd, arg)); + return snd_ioctl_return ((int *) arg, synth_devs[dev]->ioctl (dev, cmd, arg)); } break; case SNDCTL_FM_4OP_ENABLE: { - int dev = IOCTL_IN (arg); + int dev = get_fs_long ((long *) arg); if (dev < 0 || dev >= num_synths) - return RET_ERROR (ENXIO); + return -ENXIO; if (!(synth_open_mask & (1 << dev))) - return RET_ERROR (ENXIO); + return -ENXIO; synth_devs[dev]->ioctl (dev, cmd, arg); return 0; @@ -1579,14 +1763,14 @@ struct synth_info inf; int dev; - IOCTL_FROM_USER ((char *) &inf, (char *) arg, 0, sizeof (inf)); + memcpy_fromfs (((char *) &inf), &(((char *) arg)[0]), (sizeof (inf))); dev = inf.device; if (dev < 0 || dev >= max_synthdev) - return RET_ERROR (ENXIO); + return -ENXIO; if (!(synth_open_mask & (1 << dev)) && !orig_dev) - return RET_ERROR (EBUSY); + return -EBUSY; return synth_devs[dev]->ioctl (dev, cmd, arg); } @@ -1597,11 +1781,12 @@ struct seq_event_rec event; unsigned long flags; - IOCTL_FROM_USER ((char *) &event, (char *) arg, 0, sizeof (event)); + memcpy_fromfs (((char *) &event), &(((char *) arg)[0]), (sizeof (event))); - DISABLE_INTR (flags); + save_flags (flags); + cli (); play_event (event.arr); - RESTORE_INTR (flags); + restore_flags (flags); return 0; } @@ -1612,13 +1797,13 @@ struct midi_info inf; int dev; - IOCTL_FROM_USER ((char *) &inf, (char *) arg, 0, sizeof (inf)); + memcpy_fromfs (((char *) &inf), &(((char *) arg)[0]), (sizeof (inf))); dev = inf.device; if (dev < 0 || dev >= max_mididev) - return RET_ERROR (ENXIO); + return -ENXIO; - IOCTL_TO_USER ((char *) arg, 0, (char *) &(midi_devs[dev]->info), sizeof (inf)); + memcpy_tofs (&(((char *) arg)[0]), ((char *) &(midi_devs[dev]->info)), (sizeof (inf))); return 0; } break; @@ -1628,35 +1813,39 @@ struct patmgr_info *inf; int dev, err; - if ((inf = (struct patmgr_info *) KERNEL_MALLOC (sizeof (*inf))) == NULL) + if ((inf = (struct patmgr_info *) ( + { + caddr_t x; x = kmalloc (sizeof (*inf), GFP_KERNEL); x; + } + )) == NULL) { printk ("patmgr: Can't allocate memory for a message\n"); - return RET_ERROR (EIO); + return -EIO; } - IOCTL_FROM_USER ((char *) inf, (char *) arg, 0, sizeof (*inf)); + memcpy_fromfs (((char *) inf), &(((char *) arg)[0]), (sizeof (*inf))); dev = inf->device; if (dev < 0 || dev >= num_synths) { - KERNEL_FREE (inf); - return RET_ERROR (ENXIO); + kfree (inf); + return -ENXIO; } if (!synth_devs[dev]->pmgr_interface) { - KERNEL_FREE (inf); - return RET_ERROR (ENXIO); + kfree (inf); + return -ENXIO; } if ((err = synth_devs[dev]->pmgr_interface (dev, inf)) == -1) { - KERNEL_FREE (inf); + kfree (inf); return err; } - IOCTL_TO_USER ((char *) arg, 0, (char *) inf, sizeof (*inf)); - KERNEL_FREE (inf); + memcpy_tofs (&(((char *) arg)[0]), ((char *) inf), (sizeof (*inf))); + kfree (inf); return 0; } break; @@ -1666,47 +1855,51 @@ struct patmgr_info *inf; int dev, err; - if ((inf = (struct patmgr_info *) KERNEL_MALLOC (sizeof (*inf))) == NULL) + if ((inf = (struct patmgr_info *) ( + { + caddr_t x; x = kmalloc (sizeof (*inf), GFP_KERNEL); x; + } + )) == NULL) { printk ("patmgr: Can't allocate memory for a message\n"); - return RET_ERROR (EIO); + return -EIO; } - IOCTL_FROM_USER ((char *) inf, (char *) arg, 0, sizeof (*inf)); + memcpy_fromfs (((char *) inf), &(((char *) arg)[0]), (sizeof (*inf))); dev = inf->device; if (dev < 0 || dev >= num_synths) { - KERNEL_FREE (inf); - return RET_ERROR (ENXIO); + kfree (inf); + return -ENXIO; } if (!pmgr_present[dev]) { - KERNEL_FREE (inf); - return RET_ERROR (ESRCH); + kfree (inf); + return -ESRCH; } if ((err = pmgr_access (dev, inf)) < 0) { - KERNEL_FREE (inf); + kfree (inf); return err; } - IOCTL_TO_USER ((char *) arg, 0, (char *) inf, sizeof (*inf)); - KERNEL_FREE (inf); + memcpy_tofs (&(((char *) arg)[0]), ((char *) inf), (sizeof (*inf))); + kfree (inf); return 0; } break; case SNDCTL_SEQ_THRESHOLD: { - int tmp = IOCTL_IN (arg); + int tmp = get_fs_long ((long *) arg); if (dev) /* * Patch manager */ - return RET_ERROR (EIO); + return -EIO; if (tmp < 1) tmp = 1; @@ -1719,14 +1912,14 @@ case SNDCTL_MIDI_PRETIME: { - int val = IOCTL_IN (arg); + int val = get_fs_long ((long *) arg); if (val < 0) val = 0; val = (HZ * val) / 10; pre_event_timeout = val; - return IOCTL_OUT (arg, val); + return snd_ioctl_return ((int *) arg, val); } break; @@ -1734,23 +1927,22 @@ if (dev) /* * Patch manager */ - return RET_ERROR (EIO); + return -EIO; if (mode == OPEN_READ) - return RET_ERROR (EIO); + return -EIO; if (!synth_devs[0]) - return RET_ERROR (ENXIO); + return -ENXIO; if (!(synth_open_mask & (1 << 0))) - return RET_ERROR (ENXIO); + return -ENXIO; return synth_devs[0]->ioctl (0, cmd, arg); break; } - return RET_ERROR (EINVAL); + return -EINVAL; } -#ifdef ALLOW_SELECT int sequencer_select (int dev, struct fileinfo *file, int sel_type, select_table * wait) { @@ -1761,30 +1953,32 @@ switch (sel_type) { case SEL_IN: - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (!iqlen) { midi_sleep_flag.mode = WK_SLEEP; select_wait (&midi_sleeper, wait); - RESTORE_INTR (flags); + restore_flags (flags); return 0; } midi_sleep_flag.mode &= ~WK_SLEEP; - RESTORE_INTR (flags); + restore_flags (flags); return 1; break; case SEL_OUT: - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (qlen >= SEQ_MAX_QUEUE) { seq_sleep_flag.mode = WK_SLEEP; select_wait (&seq_sleeper, wait); - RESTORE_INTR (flags); + restore_flags (flags); return 0; } seq_sleep_flag.mode &= ~WK_SLEEP; - RESTORE_INTR (flags); + restore_flags (flags); return 1; break; @@ -1795,7 +1989,6 @@ return 0; } -#endif void sequencer_timer (void) @@ -1852,7 +2045,7 @@ return base_freq; if (range >= 8192) - range = 8191; + range = 8192; bend = bend * range / 8192; if (!bend) @@ -1882,13 +2075,9 @@ / 10000; if (negative) - return (base_freq * 10000) / amount; /* - * Bend down - */ + return (base_freq * 10000) / amount; /* Bend down */ else - return (base_freq * amount) / 10000; /* - * Bend up - */ + return (base_freq * amount) / 10000; /* Bend up */ } @@ -1897,8 +2086,24 @@ { sequencer_ok = 1; - PERMANENT_MALLOC (unsigned char *, queue, SEQ_MAX_QUEUE * EV_SZ, mem_start); - PERMANENT_MALLOC (unsigned char *, iqueue, SEQ_MAX_QUEUE * IEV_SZ, mem_start); + + { + caddr_t ptr; + + ptr = sound_mem_blocks[sound_num_blocks] = kmalloc (SEQ_MAX_QUEUE * EV_SZ, GFP_KERNEL); + if (sound_num_blocks < 1024) + sound_num_blocks++; + queue = (unsigned char *) ptr; + }; + + { + caddr_t ptr; + + ptr = sound_mem_blocks[sound_num_blocks] = kmalloc (SEQ_MAX_QUEUE * IEV_SZ, GFP_KERNEL); + if (sound_num_blocks < 1024) + sound_num_blocks++; + iqueue = (unsigned char *) ptr; + }; return mem_start; } @@ -1910,19 +2115,19 @@ int sequencer_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) { - return RET_ERROR (EIO); + return -EIO; } int sequencer_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) { - return RET_ERROR (EIO); + return -EIO; } int sequencer_open (int dev, struct fileinfo *file) { - return RET_ERROR (ENXIO); + return -ENXIO; } void @@ -1933,13 +2138,13 @@ sequencer_ioctl (int dev, struct fileinfo *file, unsigned int cmd, unsigned int arg) { - return RET_ERROR (EIO); + return -EIO; } int sequencer_lseek (int dev, struct fileinfo *file, off_t offset, int orig) { - return RET_ERROR (EIO); + return -EIO; } long @@ -1948,14 +2153,12 @@ return mem_start; } -#ifdef ALLOW_SELECT int sequencer_select (int dev, struct fileinfo *file, int sel_type, select_table * wait) { - return RET_ERROR (EIO); + return -EIO; } -#endif #endif diff -u --recursive --new-file v1.3.33/linux/drivers/sound/sound_calls.h linux/drivers/sound/sound_calls.h --- v1.3.33/linux/drivers/sound/sound_calls.h Tue Jul 11 10:02:54 1995 +++ linux/drivers/sound/sound_calls.h Wed Oct 11 07:55:37 1995 @@ -8,7 +8,7 @@ int DMAbuf_getrdbuffer(int dev, char **buf, int *len, int dontblock); int DMAbuf_rmchars(int dev, int buff_no, int c); int DMAbuf_start_output(int dev, int buff_no, int l); -int DMAbuf_ioctl(int dev, unsigned int cmd, unsigned int arg, int local); +int DMAbuf_ioctl(int dev, unsigned int cmd, ioctl_arg arg, int local); long DMAbuf_init(long mem_start); int DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode); int DMAbuf_open_dma (int dev); @@ -16,37 +16,34 @@ void DMAbuf_reset_dma (int dev); void DMAbuf_inputintr(int dev); void DMAbuf_outputintr(int dev, int underflow_flag); -#ifdef ALLOW_SELECT int DMAbuf_select(int dev, struct fileinfo *file, int sel_type, select_table * wait); -#endif +void DMAbuf_start_devices(unsigned int devmask); /* * System calls for /dev/dsp and /dev/audio */ int audio_read (int dev, struct fileinfo *file, snd_rw_buf *buf, int count); -int audio_write (int dev, struct fileinfo *file, snd_rw_buf *buf, int count); +int audio_write (int dev, struct fileinfo *file, const snd_rw_buf *buf, int count); int audio_open (int dev, struct fileinfo *file); void audio_release (int dev, struct fileinfo *file); int audio_ioctl (int dev, struct fileinfo *file, - unsigned int cmd, unsigned int arg); + unsigned int cmd, ioctl_arg arg); int audio_lseek (int dev, struct fileinfo *file, off_t offset, int orig); long audio_init (long mem_start); -#ifdef ALLOW_SELECT int audio_select(int dev, struct fileinfo *file, int sel_type, select_table * wait); -#endif /* * System calls for the /dev/sequencer */ int sequencer_read (int dev, struct fileinfo *file, snd_rw_buf *buf, int count); -int sequencer_write (int dev, struct fileinfo *file, snd_rw_buf *buf, int count); +int sequencer_write (int dev, struct fileinfo *file, const snd_rw_buf *buf, int count); int sequencer_open (int dev, struct fileinfo *file); void sequencer_release (int dev, struct fileinfo *file); int sequencer_ioctl (int dev, struct fileinfo *file, - unsigned int cmd, unsigned int arg); + unsigned int cmd, ioctl_arg arg); int sequencer_lseek (int dev, struct fileinfo *file, off_t offset, int orig); long sequencer_init (long mem_start); void sequencer_timer(void); @@ -55,38 +52,23 @@ void seq_input_event(unsigned char *event, int len); void seq_copy_to_input (unsigned char *event, int len); -#ifdef ALLOW_SELECT int sequencer_select(int dev, struct fileinfo *file, int sel_type, select_table * wait); -#endif /* * System calls for the /dev/midi */ int MIDIbuf_read (int dev, struct fileinfo *file, snd_rw_buf *buf, int count); -int MIDIbuf_write (int dev, struct fileinfo *file, snd_rw_buf *buf, int count); +int MIDIbuf_write (int dev, struct fileinfo *file, const snd_rw_buf *buf, int count); int MIDIbuf_open (int dev, struct fileinfo *file); void MIDIbuf_release (int dev, struct fileinfo *file); int MIDIbuf_ioctl (int dev, struct fileinfo *file, - unsigned int cmd, unsigned int arg); + unsigned int cmd, ioctl_arg arg); int MIDIbuf_lseek (int dev, struct fileinfo *file, off_t offset, int orig); void MIDIbuf_bytes_received(int dev, unsigned char *buf, int count); long MIDIbuf_init(long mem_start); -#ifdef ALLOW_SELECT int MIDIbuf_select(int dev, struct fileinfo *file, int sel_type, select_table * wait); -#endif - -/* - * System calls for the generic midi interface. - * - */ - -long CMIDI_init (long mem_start); -int CMIDI_open (int dev, struct fileinfo *file); -int CMIDI_write (int dev, struct fileinfo *file, snd_rw_buf *buf, int count); -int CMIDI_read (int dev, struct fileinfo *file, snd_rw_buf *buf, int count); -int CMIDI_close (int dev, struct fileinfo *file); /* * @@ -94,23 +76,23 @@ */ /* From soundcard.c */ -long soundcard_init(long mem_start); +void soundcard_init(void); void tenmicrosec(void); void request_sound_timer (int count); void sound_stop_timer(void); int snd_ioctl_return(int *addr, int value); -int snd_set_irq_handler (int interrupt_level, INT_HANDLER_PROTO(), char *name); +int snd_set_irq_handler (int interrupt_level, void(*hndlr)(int, struct pt_regs *), char *name, sound_os_info *osp); void snd_release_irq(int vect); void sound_dma_malloc(int dev); void sound_dma_free(int dev); /* From sound_switch.c */ int sound_read_sw (int dev, struct fileinfo *file, snd_rw_buf *buf, int count); -int sound_write_sw (int dev, struct fileinfo *file, snd_rw_buf *buf, int count); +int sound_write_sw (int dev, struct fileinfo *file, const snd_rw_buf *buf, int count); int sound_open_sw (int dev, struct fileinfo *file); void sound_release_sw (int dev, struct fileinfo *file); int sound_ioctl_sw (int dev, struct fileinfo *file, - unsigned int cmd, unsigned long arg); + unsigned int cmd, ioctl_arg arg); /* From sb_dsp.c */ int sb_dsp_detect (struct address_info *hw_config); @@ -120,6 +102,7 @@ void sb_free_irq(void); int sb_dsp_command (unsigned char val); int sb_reset_dsp (void); +void sb_dsp_unload(void); /* From sb16_dsp.c */ void sb16_dsp_interrupt (int irq); @@ -142,8 +125,8 @@ int sb_mixer_init(int major_model); /* From opl3.c */ -int opl3_detect (int ioaddr); -long opl3_init(long mem_start); +int opl3_detect (int ioaddr, sound_os_info *osp); +long opl3_init(long mem_start, int ioaddr, sound_os_info *osp); /* From sb_card.c */ long attach_sb_card(long mem_start, struct address_info *hw_config); @@ -176,19 +159,21 @@ long attach_gus_card(long mem_start, struct address_info * hw_config); int probe_gus(struct address_info *hw_config); int gus_set_midi_irq(int num); -void gusintr(INT_HANDLER_PARMS(irq, dummy)); +void gusintr(int irq, struct pt_regs * dummy); long attach_gus_db16(long mem_start, struct address_info * hw_config); int probe_gus_db16(struct address_info *hw_config); /* From gus_wave.c */ int gus_wave_detect(int baseaddr); -long gus_wave_init(long mem_start, int irq, int dma); +long gus_wave_init(long mem_start, struct address_info *hw_config); +void gus_wave_unload (void); void gus_voice_irq(void); unsigned char gus_read8 (int reg); void gus_write8(int reg, unsigned int data); void guswave_dma_irq(void); void gus_delay(void); -int gus_default_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg); +int gus_default_mixer_ioctl (int dev, unsigned int cmd, ioctl_arg arg); +void gus_timer_command (unsigned int addr, unsigned int val); /* From gus_midi.c */ long gus_midi_init(long mem_start); @@ -197,7 +182,7 @@ /* From mpu401.c */ long attach_mpu401(long mem_start, struct address_info * hw_config); int probe_mpu401(struct address_info *hw_config); -void mpuintr(INT_HANDLER_PARMS(irq, dummy)); +void mpuintr(int irq, struct pt_regs * dummy); /* From uart6850.c */ long attach_uart6850(long mem_start, struct address_info * hw_config); @@ -210,7 +195,7 @@ int pmgr_open(int dev); void pmgr_release(int dev); int pmgr_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count); -int pmgr_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count); +int pmgr_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count); int pmgr_access(int dev, struct patmgr_info *rec); int pmgr_inform(int dev, int event, unsigned long parm1, unsigned long parm2, unsigned long parm3, unsigned long parm4); @@ -219,15 +204,23 @@ long ics2101_mixer_init(long mem_start); /* From sound_timer.c */ -void sound_timer_init(int io_base); void sound_timer_interrupt(void); +void sound_timer_syncinterval(unsigned int new_usecs); /* From ad1848.c */ -void ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture); -int ad1848_detect (int io_base); -void ad1848_interrupt (INT_HANDLER_PARMS(irq, dummy)); +void ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture, int share_dma, sound_os_info *osp); +void ad1848_unload (int io_base, int irq, int dma_playback, int dma_capture, int share_dma); + +int ad1848_detect (int io_base, int *flags, sound_os_info *osp); +#define AD_F_CS4231 0x0001 /* Returned if a CS4232 (or compatible) detected */ +#define AD_F_CS4248 0x0001 /* Returned if a CS4248 (or compatible) detected */ + +void ad1848_interrupt (int irq, struct pt_regs * dummy); long attach_ms_sound(long mem_start, struct address_info * hw_config); int probe_ms_sound(struct address_info *hw_config); +long attach_pnp_ad1848(long mem_start, struct address_info * hw_config); +int probe_pnp_ad1848(struct address_info *hw_config); +void unload_pnp_ad1848(struct address_info *hw_info); /* From pss.c */ int probe_pss (struct address_info *hw_config); @@ -248,7 +241,7 @@ int pss_open (int dev, struct fileinfo *file); void pss_release (int dev, struct fileinfo *file); int pss_ioctl (int dev, struct fileinfo *file, - unsigned int cmd, unsigned int arg); + unsigned int cmd, ioctl_arg arg); int pss_lseek (int dev, struct fileinfo *file, off_t offset, int orig); long pss_init(long mem_start); @@ -273,3 +266,45 @@ int probe_mad16 (struct address_info *hw_config); long attach_mad16_mpu (long mem_start, struct address_info *hw_config); int probe_mad16_mpu (struct address_info *hw_config); +int mad16_sb_dsp_detect (struct address_info *hw_config); +long mad16_sb_dsp_init (long mem_start, struct address_info *hw_config); + +/* Unload routines from various source files*/ +void unload_pss(struct address_info *hw_info); +void unload_pss_mpu(struct address_info *hw_info); +void unload_pss_mss(struct address_info *hw_info); +void unload_mad16(struct address_info *hw_info); +void unload_mad16_mpu(struct address_info *hw_info); +void unload_adlib(struct address_info *hw_info); +void unload_pas(struct address_info *hw_info); +void unload_mpu401(struct address_info *hw_info); +void unload_maui(struct address_info *hw_info); +void unload_uart6850(struct address_info *hw_info); +void unload_sb(struct address_info *hw_info); +void unload_sb16(struct address_info *hw_info); +void unload_sb16midi(struct address_info *hw_info); +void unload_gus_db16(struct address_info *hw_info); +void unload_ms_sound(struct address_info *hw_info); +void unload_gus(struct address_info *hw_info); +void unload_sscape(struct address_info *hw_info); +void unload_ss_ms_sound(struct address_info *hw_info); +void unload_trix_wss(struct address_info *hw_info); +void unload_trix_sb(struct address_info *hw_info); +void unload_trix_mpu(struct address_info *hw_info); +void unload_cs4232(struct address_info *hw_info); +void unload_cs4232_mpu(struct address_info *hw_info); + +/* From cs4232.c */ + +int probe_cs4232 (struct address_info *hw_config); +long attach_cs4232 (long mem_start, struct address_info *hw_config); +int probe_cs4232_mpu (struct address_info *hw_config); +long attach_cs4232_mpu (long mem_start, struct address_info *hw_config); + +/* From maui.c */ +long attach_maui(long mem_start, struct address_info * hw_config); +int probe_maui(struct address_info *hw_config); + +/* From sound_pnp.c */ +void sound_pnp_init(void); +void sound_pnp_disconnect(void); diff -u --recursive --new-file v1.3.33/linux/drivers/sound/sound_config.h linux/drivers/sound/sound_config.h --- v1.3.33/linux/drivers/sound/sound_config.h Sun Aug 13 14:45:34 1995 +++ linux/drivers/sound/sound_config.h Wed Oct 11 13:15:59 1995 @@ -3,7 +3,7 @@ * A driver for Soundcards, misc configuration parameters. * * - * Copyright by Hannu Savolainen 1993 + * Copyright by Hannu Savolainen 1995 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,12 +28,23 @@ * */ +#undef CONFIGURE_SOUNDCARD +#undef DYNAMIC_BUFFER + #include "local.h" + +#ifdef KERNEL_SOUNDCARD +#define CONFIGURE_SOUNDCARD +#define DYNAMIC_BUFFER +#undef LOADABLE_SOUNDCARD +#endif + #include "os.h" #include "soundvers.h" #if !defined(PSS_MPU_BASE) && defined(EXCLUDE_SSCAPE) && \ - defined(EXCLUDE_TRIX) && !defined(MAD16_MPU_BASE) + defined(EXCLUDE_TRIX) && !defined(MAD16_MPU_BASE) && \ + defined(EXCLUDE_CS4232) && defined(EXCLUDE_MAUI) #define EXCLUDE_MPU_EMU #endif @@ -47,7 +58,8 @@ #if defined(EXCLUDE_GUS16) && defined(EXCLUDE_MSS) && \ defined(EXCLUDE_PSS) && defined(EXCLUDE_GUSMAX) && \ - defined(EXCLUDE_SSCAPE) && defined(EXCLUDE_TRIX) && defined(EXCLUDE_MAD16) + defined(EXCLUDE_SSCAPE) && defined(EXCLUDE_TRIX) && defined(EXCLUDE_MAD16) && \ + defined(EXCLUDE_CS4232) && defined(EXCLUDE_PNP) #define EXCLUDE_AD1848 #endif @@ -55,15 +67,6 @@ #undef EXCLUDE_AD1848 #endif -#undef CONFIGURE_SOUNDCARD -#undef DYNAMIC_BUFFER - -#ifdef KERNEL_SOUNDCARD -#define CONFIGURE_SOUNDCARD -#define DYNAMIC_BUFFER -#undef LOADABLE_SOUNDCARD -#endif - #ifdef EXCLUDE_SEQUENCER #define EXCLUDE_MIDI #define EXCLUDE_YM3812 @@ -96,7 +99,7 @@ #endif #ifndef DSP_BUFFCOUNT -#define DSP_BUFFCOUNT 2 /* 2 is recommended. */ +#define DSP_BUFFCOUNT 1 /* 1 is recommended. */ #endif #define DMA_AUTOINIT 0x10 @@ -107,6 +110,12 @@ #define PAS_BASE 0x388 #endif +#ifdef JAZZ16 +#ifndef JAZZ_DMA16 +#define JAZZ_DMA16 5 +#endif +#endif + /* SEQ_MAX_QUEUE is the maximum number of sequencer events buffered by the driver. (There is no need to alter this) */ #define SEQ_MAX_QUEUE 1024 @@ -150,14 +159,19 @@ struct fileinfo { int mode; /* Open mode */ - DECLARE_FILE(); /* Reference to file-flags. OS-dependent. */ + struct file *filp; /* Reference to file-flags. OS-dependent. */ }; struct address_info { int io_base; int irq; int dma; + int dma2; int always_detect; /* 1=Trust me, it's there */ + char *name; + int driver_use_1; /* Driver defined field 1 */ + int driver_use_2; /* Driver defined field 2 */ + sound_os_info *osp; /* OS spesific info */ }; #define SYNTH_MAX_VOICES 32 @@ -186,9 +200,9 @@ #define WK_SIGNAL 0x04 #define WK_SLEEP 0x08 -#define OPEN_READ 1 -#define OPEN_WRITE 2 -#define OPEN_READWRITE 3 +#define OPEN_READ PCM_ENABLE_INPUT +#define OPEN_WRITE PCM_ENABLE_OUTPUT +#define OPEN_READWRITE (OPEN_READ|OPEN_WRITE) #include "sound_calls.h" #include "dev_table.h" diff -u --recursive --new-file v1.3.33/linux/drivers/sound/sound_pnp.c linux/drivers/sound/sound_pnp.c --- v1.3.33/linux/drivers/sound/sound_pnp.c Thu Jan 1 02:00:00 1970 +++ linux/drivers/sound/sound_pnp.c Wed Oct 11 07:55:42 1995 @@ -0,0 +1,201 @@ +/* + * sound/sound_pnp.c + * + * PnP soundcard support (Linux spesific) + * + * Copyright by Hannu Savolainen 1995 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. 2. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#include "sound_config.h" + +#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_PNP) + +#include + +static struct pnp_sounddev *pnp_devs[20] = +{ + NULL +}; + +static int max_pnpdevs = 20; +static int nr_pnpdevs = 0; +static int pnp_sig = 0; + +void +install_pnp_sounddrv (struct pnp_sounddev *drv) +{ + if (nr_pnpdevs < max_pnpdevs) + { + pnp_devs[nr_pnpdevs++] = drv; + } + else + printk ("Sound: More than 20 PnP drivers defined\n"); +} + +void +cs4232_pnp (void *parm) +{ + struct pnp_dev *dev = (struct pnp_dev *) parm; + char *name; + + int portmask = 0x00, irqmask = 0x01, dmamask = 0x03; + int opl3_driver, wss_driver; + + printk ("CS4232 driver waking up\n"); + + if (dev->card && dev->card->name) + name = dev->card->name; + else + name = "PnP WSS"; + + if ((wss_driver = sndtable_identify_card ("AD1848"))) + portmask |= 0x01; /* MSS */ + else + printk ("Sound: MSS/WSS device detected but no driver enabled\n"); + + if ((opl3_driver = sndtable_identify_card ("OPL3"))) + portmask |= 0x02; /* OPL3 */ + else + printk ("Sound: OPL3/4 device detected but no driver enabled\n"); + + printk ("WSS driver %d, OPL3 driver %d\n", wss_driver, opl3_driver); + + if (!portmask) /* No drivers available */ + return; + + if (!pnp_allocate_device (pnp_sig, dev, portmask, irqmask, dmamask, 0x00)) + printk ("Device activation failed\n"); + else + { + struct address_info hw_config; + int wss_base, opl3_base; + int irq; + int dma1, dma2; + + printk ("Device activation OK\n"); + wss_base = pnp_get_port (dev, 0); + opl3_base = pnp_get_port (dev, 1); + irq = pnp_get_irq (dev, 0); + dma1 = pnp_get_dma (dev, 0); + dma2 = pnp_get_dma (dev, 1); + + printk ("I/O0 %03x\n", wss_base); + printk ("I/O1 %03x\n", opl3_base); + printk ("IRQ %d\n", irq); + printk ("DMA0 %d\n", dma1); + printk ("DMA1 %d\n", dma2); + + if (opl3_base && opl3_driver) + { + hw_config.io_base = opl3_base; + hw_config.irq = 0; + hw_config.dma = -1; + hw_config.dma2 = -1; + hw_config.always_detect = 0; + hw_config.name = ""; + hw_config.driver_use_1 = 0; + hw_config.driver_use_2 = 0; + hw_config.osp = NULL; + + if (sndtable_probe (opl3_driver, &hw_config)) + sndtable_init_card (opl3_driver, &hw_config); + + } + + if (wss_base && wss_driver) + { + hw_config.io_base = wss_base; + hw_config.irq = irq; + hw_config.dma = dma1; + hw_config.dma2 = (dma2 == NO_DMA) ? dma1 : dma2; + hw_config.always_detect = 0; + hw_config.name = name; + hw_config.driver_use_1 = 0; + hw_config.driver_use_2 = 0; + hw_config.osp = NULL; + + if (sndtable_probe (wss_driver, &hw_config)) + sndtable_init_card (wss_driver, &hw_config); + + } + } +} + +static int +pnp_activate (int id, struct pnp_dev *dev) +{ + int i; + + for (i = 0; i < nr_pnpdevs; i++) + if (pnp_devs[i]->id == id) + { + + printk ("PnP dev: %08x, %s\n", id, + pnp_devid2asc (id)); + + pnp_devs[i]->setup ((void *) dev); + return 1; + } + + return 0; +} + +void +sound_pnp_init (void) +{ + static struct pnp_sounddev cs4232_dev = + {PNP_DEVID ('C', 'S', 'C', 0x0000), cs4232_pnp, "CS4232"}; + + struct pnp_dev *dev; + + install_pnp_sounddrv (&cs4232_dev); + + dev = NULL; + + if ((pnp_sig = pnp_connect ("sound")) == -1) + { + printk ("Sound: Can't connect to kernel PnP services.\n"); + return; + } + + while ((dev = pnp_get_next_device (pnp_sig, dev)) != NULL) + { + if (!pnp_activate (dev->key, dev)) + { + /* Scan all compatible devices */ + + int i; + + for (i = 0; i < dev->ncompat; i++) + if (pnp_activate (dev->compat_keys[i], dev)) + break; + } + } +} + +void +sound_pnp_disconnect (void) +{ + pnp_disconnect (pnp_sig); +} +#endif diff -u --recursive --new-file v1.3.33/linux/drivers/sound/sound_switch.c linux/drivers/sound/sound_switch.c --- v1.3.33/linux/drivers/sound/sound_switch.c Wed Oct 4 14:14:32 1995 +++ linux/drivers/sound/sound_switch.c Wed Oct 11 07:55:42 1995 @@ -56,9 +56,7 @@ static int put_status (char *s) { - int l; - - l = strnlen(s, 256); + int l = strnlen (s, 256); if (status_len + l >= 4000) return 0; @@ -153,7 +151,7 @@ for (i = 0; i < (num_sound_cards - 1); i++) { - int drv; + int drv, tmp; if (!snd_installed_cards[i].enabled) if (!put_status ("(")) @@ -172,14 +170,29 @@ return; if (!put_status_int (snd_installed_cards[i].config.io_base, 16)) return; + if (!put_status (" irq ")) return; - if (!put_status_int (snd_installed_cards[i].config.irq, 10)) - return; - if (!put_status (" drq ")) - return; - if (!put_status_int (snd_installed_cards[i].config.dma, 10)) - return; + tmp = snd_installed_cards[i].config.irq; + if (tmp < 0) + tmp = -tmp; + if (!put_status_int (tmp, 10)) + return; + + if (snd_installed_cards[i].config.dma != -1) + { + if (!put_status (" drq ")) + return; + if (!put_status_int (snd_installed_cards[i].config.dma, 10)) + return; + if (snd_installed_cards[i].config.dma2 != -1) + { + if (!put_status (",")) + return; + if (!put_status_int (snd_installed_cards[i].config.dma2, 10)) + return; + } + } if (!snd_installed_cards[i].enabled) if (!put_status (")")) @@ -204,6 +217,11 @@ return; if (!put_status (audio_devs[i]->name)) return; + + if (audio_devs[i]->flags & DMA_DUPLEX) + if (!put_status (" (DUPLEX)")) + return; + if (!put_status ("\n")) return; } @@ -296,7 +314,7 @@ if (l <= 0) return 0; - COPY_TO_USER (buf, 0, &status_buf[status_ptr], l); + memcpy_tofs (&((buf)[0]), (&status_buf[status_ptr]), (l)); status_ptr += l; return l; @@ -333,11 +351,11 @@ printk ("Sound: Undefined minor device %d\n", dev); } - return RET_ERROR (EPERM); + return -EPERM; } int -sound_write_sw (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) +sound_write_sw (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count) { DEB (printk ("sound_write_sw(dev=%d, count=%d)\n", dev, count)); @@ -362,7 +380,7 @@ #endif default: - return RET_ERROR (EPERM); + return -EPERM; } return count; @@ -378,17 +396,21 @@ if ((dev >= SND_NDEVS) || (dev < 0)) { printk ("Invalid minor device %d\n", dev); - return RET_ERROR (ENXIO); + return -ENXIO; } switch (dev & 0x0f) { case SND_DEV_STATUS: if (status_busy) - return RET_ERROR (EBUSY); + return -EBUSY; status_busy = 1; - if ((status_buf = (char *) KERNEL_MALLOC (4000)) == NULL) - return RET_ERROR (EIO); + if ((status_buf = (char *) ( + { + caddr_t x; x = kmalloc (4000, GFP_KERNEL); x; + } + )) == NULL) + return -EIO; status_len = status_ptr = 0; init_status (); break; @@ -419,7 +441,7 @@ default: printk ("Invalid minor device %d\n", dev); - return RET_ERROR (ENXIO); + return -ENXIO; } sbc_devices[dev].usecount++; @@ -438,7 +460,7 @@ { case SND_DEV_STATUS: if (status_buf) - KERNEL_FREE (status_buf); + kfree (status_buf); status_buf = NULL; status_busy = 0; break; @@ -473,7 +495,7 @@ int sound_ioctl_sw (int dev, struct fileinfo *file, - unsigned int cmd, unsigned long arg) + unsigned int cmd, ioctl_arg arg) { DEB (printk ("sound_ioctl_sw(dev=%d, cmd=0x%x, arg=0x%x)\n", dev, cmd, arg)); @@ -490,7 +512,7 @@ case SND_DEV_AUDIO: mixdev = audio_devs[dev >> 4]->mixer_dev; if (mixdev < 0 || mixdev >= num_mixers) - return RET_ERROR (ENXIO); + return -ENXIO; return mixer_devs[mixdev]->ioctl (mixdev, cmd, arg); break; @@ -505,12 +527,12 @@ case SND_DEV_CTL: if (!num_mixers) - return RET_ERROR (ENXIO); + return -ENXIO; dev = dev >> 4; if (dev >= num_mixers) - return RET_ERROR (ENXIO); + return -ENXIO; return mixer_devs[dev]->ioctl (dev, cmd, arg); break; @@ -533,11 +555,11 @@ #endif default: - return RET_ERROR (EPERM); + return -EPERM; break; } - return RET_ERROR (EPERM); + return -EPERM; } #endif diff -u --recursive --new-file v1.3.33/linux/drivers/sound/sound_timer.c linux/drivers/sound/sound_timer.c --- v1.3.33/linux/drivers/sound/sound_timer.c Tue Jul 11 10:02:54 1995 +++ linux/drivers/sound/sound_timer.c Wed Oct 11 07:55:42 1995 @@ -1,9 +1,6 @@ /* * sound/sound_timer.c * - * Timer for the level 2 interface of the /dev/sequencer. Uses the - * 80 and 320 usec timers of OPL-3 (PAS16 only) and GUS. - * * Copyright by Hannu Savolainen 1993 * * Redistribution and use in source and binary forms, with or without @@ -33,7 +30,7 @@ #ifdef CONFIGURE_SOUNDCARD -#if !defined(EXCLUDE_SEQUENCER) && (!defined(EXCLUDE_GUS) || (!defined(EXCLUDE_PAS) && !defined(EXCLUDE_YM3812))) +#if !defined(EXCLUDE_SEQUENCER) static volatile int initialized = 0, opened = 0, tmr_running = 0; static volatile time_t tmr_offs, tmr_ctr; @@ -42,46 +39,9 @@ static volatile unsigned long curr_ticks; static volatile unsigned long next_event_time; static unsigned long prev_event_time; -static volatile int select_addr, data_addr; -static volatile int curr_timer = 0; static volatile unsigned long usecs_per_tmr; /* Length of the current interval */ - -static void -timer_command (unsigned int addr, unsigned int val) -{ - int i; - - OUTB ((unsigned char) (addr & 0xff), select_addr); - - for (i = 0; i < 2; i++) - INB (select_addr); - - OUTB ((unsigned char) (val & 0xff), data_addr); - - for (i = 0; i < 2; i++) - INB (select_addr); -} - -static void -arm_timer (int timer, unsigned int interval) -{ - - curr_timer = timer; - - if (timer == 1) - { - gus_write8 (0x46, 256 - interval); /* Set counter for timer 1 */ - gus_write8 (0x45, 0x04); /* Enable timer 1 IRQ */ - timer_command (0x04, 0x01); /* Start timer 1 */ - } - else - { - gus_write8 (0x47, 256 - interval); /* Set counter for timer 2 */ - gus_write8 (0x45, 0x08); /* Enable timer 2 IRQ */ - timer_command (0x04, 0x02); /* Start timer 2 */ - } -} +static struct sound_lowlev_timer *tmr = NULL; static unsigned long tmr2ticks (int tmr_value) @@ -104,8 +64,6 @@ reprogram_timer (void) { unsigned long usecs_per_tick; - int timer_no, resolution; - int divisor; usecs_per_tick = (60 * 1000000) / (curr_tempo * curr_timebase); @@ -115,21 +73,21 @@ if (usecs_per_tick < 2000) usecs_per_tick = 2000; - if (usecs_per_tick > (256 * 80)) - { - timer_no = 2; - resolution = 320; /* usec */ - } - else - { - timer_no = 1; - resolution = 80; /* usec */ - } + usecs_per_tmr = tmr->tmr_start (tmr->dev, usecs_per_tick); +} - divisor = (usecs_per_tick + (resolution / 2)) / resolution; - usecs_per_tmr = divisor * resolution; +void +sound_timer_syncinterval (unsigned int new_usecs) +{ +/* + * This routine is called by the hardware level if + * the clock frequency has changed for some reason. + */ + tmr_offs = tmr_ctr; + ticks_offs += tmr2ticks (tmr_ctr); + tmr_ctr = 0; - arm_timer (timer_no, divisor); + usecs_per_tmr = new_usecs; } static void @@ -137,21 +95,22 @@ { unsigned long flags; - DISABLE_INTR (flags); + save_flags (flags); + cli (); tmr_offs = 0; ticks_offs = 0; tmr_ctr = 0; next_event_time = 0xffffffff; prev_event_time = 0; curr_ticks = 0; - RESTORE_INTR (flags); + restore_flags (flags); } static int timer_open (int dev, int mode) { if (opened) - return RET_ERROR (EBUSY); + return -EBUSY; tmr_reset (); curr_tempo = 60; @@ -166,7 +125,7 @@ timer_close (int dev) { opened = tmr_running = 0; - gus_write8 (0x45, 0); /* Disable both timers */ + tmr->tmr_disable (tmr->dev); } static int @@ -245,12 +204,12 @@ static int timer_ioctl (int dev, - unsigned int cmd, unsigned int arg) + unsigned int cmd, ioctl_arg arg) { switch (cmd) { case SNDCTL_TMR_SOURCE: - return IOCTL_OUT (arg, TMR_INTERNAL); + return snd_ioctl_return ((int *) arg, TMR_INTERNAL); break; case SNDCTL_TMR_START: @@ -271,7 +230,7 @@ case SNDCTL_TMR_TIMEBASE: { - int val = IOCTL_IN (arg); + int val = get_fs_long ((long *) arg); if (val) { @@ -282,13 +241,13 @@ curr_timebase = val; } - return IOCTL_OUT (arg, curr_timebase); + return snd_ioctl_return ((int *) arg, curr_timebase); } break; case SNDCTL_TMR_TEMPO: { - int val = IOCTL_IN (arg); + int val = get_fs_long ((long *) arg); if (val) { @@ -303,25 +262,25 @@ reprogram_timer (); } - return IOCTL_OUT (arg, curr_tempo); + return snd_ioctl_return ((int *) arg, curr_tempo); } break; case SNDCTL_SEQ_CTRLRATE: - if (IOCTL_IN (arg) != 0) /* Can't change */ - return RET_ERROR (EINVAL); + if (get_fs_long ((long *) arg) != 0) /* Can't change */ + return -EINVAL; - return IOCTL_OUT (arg, ((curr_tempo * curr_timebase) + 30) / 60); + return snd_ioctl_return ((int *) arg, ((curr_tempo * curr_timebase) + 30) / 60); break; case SNDCTL_TMR_METRONOME: /* NOP */ break; - default: + default:; } - return RET_ERROR (EINVAL); + return -EINVAL; } static void @@ -339,7 +298,7 @@ static struct sound_timer_operations sound_timer = { - {"OPL-3/GUS Timer", 0}, + {"GUS Timer", 0}, 1, /* Priority */ 0, /* Local device link */ timer_open, @@ -353,16 +312,10 @@ void sound_timer_interrupt (void) { - gus_write8 (0x45, 0); /* Ack IRQ */ - timer_command (4, 0x80); /* Reset IRQ flags */ - if (!opened) return; - if (curr_timer == 1) - gus_write8 (0x45, 0x04); /* Start timer 1 again */ - else - gus_write8 (0x45, 0x08); /* Start timer 2 again */ + tmr->tmr_restart (tmr->dev); if (!tmr_running) return; @@ -378,26 +331,22 @@ } void -sound_timer_init (int io_base) +sound_timer_init (struct sound_lowlev_timer *t, char *name) { int n; - if (initialized) + if (initialized || t == NULL) return; /* There is already a similar timer */ - select_addr = io_base; - data_addr = io_base + 1; - initialized = 1; + tmr = t; -#if 1 if (num_sound_timers >= MAX_TIMER_DEV) n = 0; /* Overwrite the system timer */ else n = num_sound_timers++; -#else - n = 0; -#endif + + strcpy (sound_timer.info.name, name); sound_timer_devs[n] = &sound_timer; } diff -u --recursive --new-file v1.3.33/linux/drivers/sound/soundcard.c linux/drivers/sound/soundcard.c --- v1.3.33/linux/drivers/sound/soundcard.c Tue Oct 10 18:46:37 1995 +++ linux/drivers/sound/soundcard.c Wed Oct 11 07:55:42 1995 @@ -36,20 +36,36 @@ #include -static int soundcards_installed = 0; /* Number of installed +#ifndef EXCLUDE_PNP +#include +#endif + +static int soundcards_installed = 0; /* Number of installed cards */ + +/* + * Table for permanently allocated memory (used when unloading the module) + */ +caddr_t sound_mem_blocks[1024]; +int sound_num_blocks = 0; - * soundcards */ static int soundcard_configured = 0; static struct fileinfo files[SND_NDEVS]; +static char dma_alloc_map[8] = +{0}; + +#define DMA_MAP_UNAVAIL 0 +#define DMA_MAP_FREE 1 +#define DMA_MAP_BUSY 2 + int snd_ioctl_return (int *addr, int value) { if (value < 0) return value; - PUT_WORD_TO_USER (addr, 0, value); + put_fs_long (value, (long *) &((addr)[0])); return 0; } @@ -58,7 +74,8 @@ { int dev; - dev = MINOR(inode->i_rdev); + dev = inode->i_rdev; + dev = MINOR (dev); return sound_read_sw (dev, &files[dev], buf, count); } @@ -68,12 +85,8 @@ { int dev; -#ifdef MODULE - int err; - -#endif - - dev = MINOR(inode->i_rdev); + dev = inode->i_rdev; + dev = MINOR (dev); return sound_write_sw (dev, &files[dev], buf, count); } @@ -81,7 +94,7 @@ static int sound_lseek (struct inode *inode, struct file *file, off_t offset, int orig) { - return RET_ERROR (EPERM); + return -EPERM; } static int @@ -90,12 +103,13 @@ int dev, retval; struct fileinfo tmp_file; - dev = MINOR(inode->i_rdev); + dev = inode->i_rdev; + dev = MINOR (dev); if (!soundcard_configured && dev != SND_DEV_CTL && dev != SND_DEV_STATUS) { printk ("SoundCard Error: The soundcard system has not been configured\n"); - return RET_ERROR (ENXIO); + return -ENXIO; } tmp_file.mode = 0; @@ -124,7 +138,8 @@ { int dev; - dev = MINOR(inode->i_rdev); + dev = inode->i_rdev; + dev = MINOR (dev); sound_release_sw (dev, &files[dev]); #ifdef MODULE @@ -136,16 +151,37 @@ sound_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - int dev; + int dev, err; + + dev = inode->i_rdev; + dev = MINOR (dev); + + if (cmd == 1) + { + int i; - dev = MINOR(inode->i_rdev); + unsigned char *p; + + + if (!audio_devs[dev >> 4]->dmap_out) + return 0; + if (!audio_devs[dev >> 4]->dmap_out->raw_buf) + return 0; + + p = audio_devs[dev >> 4]->dmap_out->raw_buf; + + for (i = 0; i < 256; i++) + printk ("%02x ", p[i]); + printk ("\n"); + return 0; + } if (cmd & IOC_INOUT) { /* * Have to validate the address given by the process. */ - int len, err; + int len; len = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT; @@ -163,7 +199,9 @@ } - return sound_ioctl_sw (dev, &files[dev], cmd, arg); + err = sound_ioctl_sw (dev, &files[dev], cmd, (caddr_t) arg); + + return err; } static int @@ -171,7 +209,8 @@ { int dev; - dev = MINOR(inode->i_rdev); + dev = inode->i_rdev; + dev = MINOR (dev); DEB (printk ("sound_select(dev=%d, type=0x%x)\n", dev, sel_type)); @@ -205,6 +244,92 @@ return 0; } +static int +sound_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma) +{ + int dev, dev_class; + unsigned long size; + struct dma_buffparms *dmap = NULL; + + dev = inode->i_rdev; + dev = MINOR (dev); + + dev_class = dev & 0x0f; + dev >>= 4; + + if (dev_class != SND_DEV_DSP && dev_class != SND_DEV_DSP16 && dev_class != SND_DEV_AUDIO) + { + printk ("Sound: mmap() not supported for other than audio devices\n"); + return -EINVAL; + } + + if ((vma->vm_flags & (VM_READ | VM_WRITE)) == (VM_READ | VM_WRITE)) + { + printk ("Sound: Cannot do read/write mmap()\n"); + return -EINVAL; + } + + if (vma->vm_flags & VM_READ) + { + dmap = audio_devs[dev]->dmap_in; + } + else if (vma->vm_flags & VM_WRITE) + { + dmap = audio_devs[dev]->dmap_out; + } + else + { + printk ("Sound: Undefined mmap() access\n"); + return -EINVAL; + } + + if (dmap == NULL) + { + printk ("Sound: mmap() error. dmap == NULL\n"); + return -EIO; + } + + if (dmap->raw_buf == NULL) + { + printk ("Sound: mmap() called when raw_buf == NULL\n"); + return -EIO; + } + + if (dmap->mapping_flags) + { + printk ("Sound: mmap() called twice for the same DMA buffer\n"); + return -EIO; + } + + if (vma->vm_offset != 0) + { + printk ("Sound: mmap() offset must be 0.\n"); + return -EINVAL; + } + + size = vma->vm_end - vma->vm_start; + + if (size != dmap->bytes_in_use) + { + printk ("Sound: mmap() size = %ld. Should be %d\n", + size, dmap->bytes_in_use); + } + + if (remap_page_range (vma->vm_start, dmap->raw_buf_phys, vma->vm_end - vma->vm_start, vma->vm_page_prot)) + return -EAGAIN; + + + vma->vm_inode = inode; + inode->i_count++; + + dmap->mapping_flags |= DMA_MAP_MAPPED; + + memset (dmap->raw_buf, + dmap->neutral_byte, + dmap->bytes_in_use); + return 0; +} + static struct file_operations sound_fops = { sound_lseek, @@ -213,12 +338,12 @@ NULL, /* sound_readdir */ sound_select, sound_ioctl, - NULL, + sound_mmap, sound_open, sound_release }; -int +void soundcard_init (void) { #ifndef MODULE @@ -227,39 +352,38 @@ soundcard_configured = 1; - sndtable_init (); /* Initialize call tables and - * detect cards */ + sndtable_init (0); /* Initialize call tables and + * detect cards */ +#ifndef EXCLUDE_PNP + sound_pnp_init (); +#endif if (!(soundcards_installed = sndtable_get_cardcount ())) - return 0; /* No cards detected */ + return; /* No cards detected */ #ifndef EXCLUDE_AUDIO if (num_audiodevs) /* Audio devices present */ { - DMAbuf_init (); - audio_init (); + DMAbuf_init (0); + audio_init (0); } #endif #ifndef EXCLUDE_MIDI if (num_midis) - MIDIbuf_init (); + MIDIbuf_init (0); #endif #ifndef EXCLUDE_SEQUENCER if (num_midis + num_synths) - sequencer_init (); + sequencer_init (0); #endif - return 0; } -#ifdef MODULE static unsigned long irqs = 0; -void snd_release_irq (int); -static int module_sound_mem_init (void); -static void module_sound_mem_release (void); +#ifdef MODULE static void free_all_irqs (void) { @@ -267,60 +391,56 @@ for (i = 0; i < 31; i++) if (irqs & (1ul << i)) - snd_release_irq (i); + { + printk ("Sound warning: IRQ%d was left allocated. Fixed.\n", i); + snd_release_irq (i); + } irqs = 0; } char kernel_version[] = UTS_RELEASE; -static long memory_pool = 0; -static int memsize = 70 * 1024; +#endif + static int debugmem = 0; /* switched off by default */ +static int sound[20] = +{0}; + int init_module (void) { - long lastbyte; int err; + int ints[21]; + int i; + + /* + * "sound=" command line handling by Harald Milz. + */ + i = 0; + while (i < 20 && sound[i]) + ints[i + 1] = sound[i++]; + ints[0] = i; + + if (i) + sound_setup ("sound=", ints); - printk ("sound: made modular by Peter Trattler (peter@sbox.tu-graz.ac.at)\n"); err = register_chrdev (SOUND_MAJOR, "sound", &sound_fops); if (err) { printk ("sound: driver already loaded/included in kernel\n"); return err; } - memory_pool = (long) kmalloc (memsize, GFP_KERNEL); - if (memory_pool == 0l) - { - unregister_chrdev (SOUND_MAJOR, "sound"); - return -ENOMEM; - } - lastbyte = soundcard_init (memory_pool); - if (lastbyte > memory_pool + memsize) - { - printk ("sound: Not enough memory; use : 'insmod sound.o memsize=%ld'\n", - lastbyte - memory_pool); - kfree ((void *) memory_pool); - unregister_chrdev (SOUND_MAJOR, "sound"); - free_all_irqs (); - return -ENOMEM; - } - err = module_sound_mem_init (); - if (err) - { - module_sound_mem_release (); - kfree ((void *) memory_pool); - unregister_chrdev (SOUND_MAJOR, "sound"); - free_all_irqs (); - return err; - } - if (lastbyte < memory_pool + memsize) - printk ("sound: (Suggestion) too much memory; use : 'insmod sound.o memsize=%ld'\n", - lastbyte - memory_pool); + + soundcard_init (); + + if (sound_num_blocks >= 1024) + printk ("Sound warning: Deallocation table was too small.\n"); + return 0; } +#ifdef MODULE void cleanup_module (void) { @@ -328,13 +448,31 @@ printk ("sound: module busy -- remove delayed\n"); else { - kfree ((void *) memory_pool); + int i; + unregister_chrdev (SOUND_MAJOR, "sound"); - free_all_irqs (); - module_sound_mem_release (); + + sound_stop_timer (); + sound_unload_drivers (); + + for (i = 0; i < sound_num_blocks; i++) + kfree (sound_mem_blocks[i]); + + free_all_irqs (); /* If something was left allocated by accident */ + + for (i = 0; i < 8; i++) + if (dma_alloc_map[i] != DMA_MAP_UNAVAIL) + { + printk ("Sound: Hmm, DMA%d was left allocated\n", i); + sound_free_dma (i); + } + +#ifndef EXCLUDE_PNP + sound_pnp_disconnect (); +#endif + } } - #endif void @@ -347,19 +485,17 @@ } int -snd_set_irq_handler (int interrupt_level, INT_HANDLER_PROTO (), char *name) +snd_set_irq_handler (int interrupt_level, void (*hndlr) (int, struct pt_regs *), char *name, sound_os_info * osp) { int retcode; - retcode = request_irq (interrupt_level, hndlr, SA_INTERRUPT, name); + retcode = request_irq (interrupt_level, hndlr, 0 /* SA_INTERRUPT */ , name); if (retcode < 0) { printk ("Sound: IRQ%d already in use\n", interrupt_level); } -#ifdef MODULE else irqs |= (1ul << interrupt_level); -#endif return retcode; } @@ -367,19 +503,79 @@ void snd_release_irq (int vect) { -#ifdef MODULE irqs &= ~(1ul << vect); -#endif free_irq (vect); } +int +sound_alloc_dma (int chn, char *deviceID) +{ + int err; + + if ((err = request_dma (chn, deviceID)) != 0) + return err; + + dma_alloc_map[chn] = DMA_MAP_FREE; + + return 0; +} + +int +sound_open_dma (int chn, char *deviceID) +{ + unsigned long flags; + + save_flags (flags); + cli (); + + if (dma_alloc_map[chn] != DMA_MAP_FREE) + { + printk ("sound_open_dma: DMA channel %d busy or not allocated\n", chn); + restore_flags (flags); + return 1; + } + + dma_alloc_map[chn] = DMA_MAP_BUSY; + restore_flags (flags); + return 0; +} + +void +sound_free_dma (int chn) +{ + if (dma_alloc_map[chn] != DMA_MAP_FREE) + { + printk ("sound_free_dma: Bad access to DMA channel %d\n", chn); + return; + } + free_dma (chn); + dma_alloc_map[chn] = DMA_MAP_UNAVAIL; +} + +void +sound_close_dma (int chn) +{ + unsigned long flags; + + save_flags (flags); + cli (); + + if (dma_alloc_map[chn] != DMA_MAP_BUSY) + { + printk ("sound_close_dma: Bad access to DMA channel %d\n", chn); + restore_flags (flags); + return; + } + dma_alloc_map[chn] = DMA_MAP_FREE; + restore_flags (flags); +} + #ifndef EXCLUDE_SEQUENCER void request_sound_timer (int count) { extern unsigned long seq_time; -#if 1 if (count < 0) count = jiffies + (-count); else @@ -387,7 +583,6 @@ timer_table[SOUND_TIMER].fn = sequencer_timer; timer_table[SOUND_TIMER].expires = count; timer_active |= 1 << SOUND_TIMER; -#endif } #endif @@ -395,264 +590,150 @@ void sound_stop_timer (void) { -#if 1 timer_table[SOUND_TIMER].expires = 0; timer_active &= ~(1 << SOUND_TIMER); -#endif } #ifndef EXCLUDE_AUDIO -static int -valid_dma_page (unsigned long addr, unsigned long dev_buffsize, unsigned long dma_pagesize) -{ - if (((addr & (dma_pagesize - 1)) + dev_buffsize) <= dma_pagesize) - return 1; - else - return 0; -} - -#ifdef MODULE #ifdef KMALLOC_DMA_BROKEN -#define KMALLOC_MEM_REGIONS 20 - -static char *dma_list[KMALLOC_MEM_REGIONS]; -static int dma_last = 0; -inline void -add_to_dma_list (char *adr) -{ - dma_list[dma_last++] = adr; -} - +fatal_error__This_version_is_not_compatible_with_this_kernel; #endif -static int -module_sound_mem_init (void) +static int dma_buffsize = DSP_BUFFSIZE; + +int +sound_alloc_dmap (int dev, struct dma_buffparms *dmap, int chan) { - int dev, ret = 0; - unsigned long dma_pagesize; char *start_addr, *end_addr; - int order, size; - struct dma_buffparms *dmap; - - for (dev = 0; dev < num_audiodevs; dev++) - if (audio_devs[dev]->buffcount > 0 && audio_devs[dev]->dmachan >= 0) - { - dmap = audio_devs[dev]->dmap; - if (audio_devs[dev]->flags & DMA_AUTOMODE) - audio_devs[dev]->buffcount = 1; - - if (audio_devs[dev]->dmachan > 3) - dma_pagesize = 131072; /* 16bit dma: 128k */ - else - dma_pagesize = 65536; /* 8bit dma: 64k */ - if (debugmem) - printk ("sound: dma-page-size %lu\n", dma_pagesize); - /* More sanity checks */ - - if (audio_devs[dev]->buffsize > dma_pagesize) - audio_devs[dev]->buffsize = dma_pagesize; - audio_devs[dev]->buffsize &= 0xfffff000; /* Truncate to n*4k */ - if (audio_devs[dev]->buffsize < 4096) - audio_devs[dev]->buffsize = 4096; - if (debugmem) - printk ("sound: buffsize %lu\n", audio_devs[dev]->buffsize); - /* Now allocate the buffers */ - for (dmap->raw_count = 0; dmap->raw_count < audio_devs[dev]->buffcount; - dmap->raw_count++) - { -#ifdef KMALLOC_DMA_BROKEN - start_addr = kmalloc (audio_devs[dev]->buffsize, GFP_KERNEL); - if (start_addr) - { - if (debugmem) - printk ("sound: trying 0x%lx for DMA\n", (long) start_addr); - if (valid_dma_page ((unsigned long) start_addr, - audio_devs[dev]->buffsize, - dma_pagesize)) - add_to_dma_list (start_addr); - else - { - kfree (start_addr); - start_addr = kmalloc (audio_devs[dev]->buffsize * 2, - GFP_KERNEL); /* what a waste :-( */ - if (start_addr) - { - if (debugmem) - printk ("sound: failed; trying 0x%lx aligned to", - (long) start_addr); - add_to_dma_list (start_addr); - /* now align it to the next dma-page boundary */ - start_addr = (char *) (((long) start_addr - + dma_pagesize - 1) - & ~(dma_pagesize - 1)); - if (debugmem) - printk (" 0x%lx\n", (long) start_addr); - } - } - } -#else - for (order = 0, size = PAGE_SIZE; - size < audio_devs[dev]->buffsize; - order++, size <<= 1); - start_addr = (char *) __get_free_pages(GFP_KERNEL, order, MAX_DMA_ADDRESS); -#endif - if (start_addr == NULL) - ret = -ENOMEM; /* Can't stop the loop in this case, because - * ...->raw_buf [...] must be initilized - * to valid values (at least to NULL) - */ - else - { - /* make some checks */ - end_addr = start_addr + audio_devs[dev]->buffsize - 1; - if (debugmem) - printk ("sound: start 0x%lx, end 0x%lx\n", - (long) start_addr, (long) end_addr); - /* now check if it fits into the same dma-pagesize */ - if (((long) start_addr & ~(dma_pagesize - 1)) - != ((long) end_addr & ~(dma_pagesize - 1)) - || end_addr >= (char *) (16 * 1024 * 1024)) - { - printk ( - "sound: kmalloc returned invalid address 0x%lx for %ld Bytes DMA-buffer\n", - (long) start_addr, - audio_devs[dev]->buffsize); - ret = -EFAULT; - } - } - dmap->raw_buf[dmap->raw_count] = start_addr; - dmap->raw_buf_phys[dmap->raw_count] = (unsigned long) start_addr; - } - } - return ret; -} + int i, dma_pagesize; -static void -module_sound_mem_release (void) -{ -#ifdef KMALLOC_DMA_BROKEN - int i; + if (dmap->raw_buf != NULL) + return 0; /* Already done */ - for (i = 0; i < dma_last; i++) - { - if (debugmem) - printk ("sound: freeing 0x%lx\n", (long) dma_list[i]); - kfree (dma_list[i]); - } -#else - int dev, i; - int order, size; + if (dma_buffsize < 4096) + dma_buffsize = 4096; - for (dev = 0; dev < num_audiodevs; dev++) { - for (order = 0, size = PAGE_SIZE; - size < audio_devs[dev]->buffsize; - order++, size <<= 1); - if (audio_devs[dev]->buffcount > 0 && audio_devs[dev]->dmachan >= 0) - { - for (i = 0; i < audio_devs[dev]->buffcount; i++) - if (audio_devs[dev]->dmap->raw_buf[i]) - { - if (debugmem) - printk ("sound: freeing 0x%lx\n", - (long) (audio_devs[dev]->dmap->raw_buf[i])); - free_pages((unsigned long) audio_devs[dev]->dmap->raw_buf[i], - order); - } - } - } -#endif -} + if (chan < 4) + dma_pagesize = 64 * 1024; + else + dma_pagesize = 128 * 1024; -#else /* !MODULE */ + dmap->raw_buf = NULL; -void -sound_mem_init (void) -{ - int i, dev; - unsigned long start_addr, end_addr, mem_ptr, dma_pagesize; - struct dma_buffparms *dmap; + if (debugmem) + printk ("sound: buffsize%d %lu\n", dev, audio_devs[dev]->buffsize); - mem_ptr = high_memory; + audio_devs[dev]->buffsize = dma_buffsize; - /* Some sanity checks */ + if (audio_devs[dev]->buffsize > dma_pagesize) + audio_devs[dev]->buffsize = dma_pagesize; - if (mem_ptr > (16 * 1024 * 1024)) - mem_ptr = 16 * 1024 * 1024; /* Limit to 16M */ + start_addr = NULL; - for (dev = 0; dev < num_audiodevs; dev++) /* Enumerate devices */ - if (audio_devs[dev]->buffcount > 0 && audio_devs[dev]->dmachan >= 0) - { - dmap = audio_devs[dev]->dmap; +/* + * Now loop until we get a free buffer. Try to get smaller buffer if + * it fails. + */ - if (audio_devs[dev]->flags & DMA_AUTOMODE) - audio_devs[dev]->buffcount = 1; + while (start_addr == NULL && audio_devs[dev]->buffsize > PAGE_SIZE) + { + int sz, size; - if (audio_devs[dev]->dmachan > 3 && audio_devs[dev]->buffsize > 65536) - dma_pagesize = 131072; /* 128k */ - else - dma_pagesize = 65536; + for (sz = 0, size = PAGE_SIZE; + size < audio_devs[dev]->buffsize; + sz++, size <<= 1); - /* More sanity checks */ + audio_devs[dev]->buffsize = PAGE_SIZE * (1 << sz); - if (audio_devs[dev]->buffsize > dma_pagesize) - audio_devs[dev]->buffsize = dma_pagesize; - audio_devs[dev]->buffsize &= 0xfffff000; /* Truncate to n*4k */ - if (audio_devs[dev]->buffsize < 4096) - audio_devs[dev]->buffsize = 4096; + if ((start_addr = (char *) __get_free_pages (GFP_ATOMIC, sz, MAX_DMA_ADDRESS)) == NULL) + audio_devs[dev]->buffsize /= 2; + } - /* Now allocate the buffers */ + if (start_addr == NULL) + { + printk ("Sound error: Couldn't allocate DMA buffer\n"); + return -ENOMEM; + } + else + { + /* make some checks */ + end_addr = start_addr + audio_devs[dev]->buffsize - 1; - for (dmap->raw_count = 0; dmap->raw_count < audio_devs[dev]->buffcount; dmap->raw_count++) - { - start_addr = mem_ptr - audio_devs[dev]->buffsize; - if (!valid_dma_page (start_addr, audio_devs[dev]->buffsize, dma_pagesize)) - start_addr &= ~(dma_pagesize - 1); /* Align address to - * dma_pagesize */ - - end_addr = start_addr + audio_devs[dev]->buffsize - 1; - - dmap->raw_buf[dmap->raw_count] = (char *) start_addr; - dmap->raw_buf_phys[dmap->raw_count] = start_addr; - mem_ptr = start_addr; - - for (i = MAP_NR (start_addr); i <= MAP_NR (end_addr); i++) - { - if (mem_map[i].reserved || mem_map[i].count) - panic ("sound_mem_init: Page not free (driver incompatible with kernel).\n"); + if (debugmem) + printk ("sound: start 0x%lx, end 0x%lx\n", + (long) start_addr, (long) end_addr); - mem_map[i].reserved = 1; - } - } - } /* for dev */ -} + /* now check if it fits into the same dma-pagesize */ -#endif /* !MODULE */ + if (((long) start_addr & ~(dma_pagesize - 1)) + != ((long) end_addr & ~(dma_pagesize - 1)) + || end_addr >= (char *) (16 * 1024 * 1024)) + { + printk ( + "sound: kmalloc returned invalid address 0x%lx for %ld Bytes DMA-buffer\n", + (long) start_addr, + audio_devs[dev]->buffsize); + return -EFAULT; + } + } + dmap->raw_buf = start_addr; + dmap->raw_buf_phys = (unsigned long) start_addr; + for (i = MAP_NR (start_addr); i <= MAP_NR (end_addr); i++) + { +#ifdef MAP_PAGE_RESERVED + mem_map[i] |= MAP_PAGE_RESERVED; +#else + mem_map[i].reserved = 1; #endif + } -#else + return 0; +} -long -soundcard_init (long mem_start) /* Dummy version */ +void +sound_free_dmap (int dev, struct dma_buffparms *dmap) { - return mem_start; -} + if (dmap->raw_buf == NULL) + return; + { + int sz, size, i; + unsigned long start_addr, end_addr; + + for (sz = 0, size = PAGE_SIZE; + size < audio_devs[dev]->buffsize; + sz++, size <<= 1); + start_addr = (unsigned long) dmap->raw_buf; + end_addr = start_addr + audio_devs[dev]->buffsize; + + for (i = MAP_NR (start_addr); i <= MAP_NR (end_addr); i++) + { +#ifdef MAP_PAGE_RESERVED + mem_map[i] &= ~MAP_PAGE_RESERVED; +#else + mem_map[i].reserved = 0; #endif + } + free_pages ((unsigned long) dmap->raw_buf, sz); + } + dmap->raw_buf = NULL; +} -#if !defined(CONFIGURE_SOUNDCARD) || defined(EXCLUDE_AUDIO) -void -sound_mem_init (void) +int +soud_map_buffer (int dev, struct dma_buffparms *dmap, buffmem_desc * info) { - /* Dummy version */ + printk ("Entered sound_map_buffer()\n"); + printk ("Exited sound_map_buffer()\n"); + return -EINVAL; } -#ifdef MODULE -static int -module_sound_mem_init (void) +#else + +void +soundcard_init (void) /* Dummy version */ { - return 0; /* no error */ } #endif diff -u --recursive --new-file v1.3.33/linux/drivers/sound/soundvers.h linux/drivers/sound/soundvers.h --- v1.3.33/linux/drivers/sound/soundvers.h Sun Aug 13 14:45:34 1995 +++ linux/drivers/sound/soundvers.h Wed Oct 11 07:55:37 1995 @@ -1 +1 @@ -#define SOUND_VERSION_STRING "3.0.1-950812" +#define SOUND_VERSION_STRING "3.5-alpha1-951002" diff -u --recursive --new-file v1.3.33/linux/drivers/sound/sscape.c linux/drivers/sound/sscape.c --- v1.3.33/linux/drivers/sound/sscape.c Tue Jul 11 10:02:55 1995 +++ linux/drivers/sound/sscape.c Wed Oct 11 07:55:42 1995 @@ -75,6 +75,10 @@ #define CMD_GET_BOARD_TYPE 0x82 #define CMD_SET_CONTROL 0x88 #define CMD_GET_CONTROL 0x89 +#define CTL_MASTER_VOL 0 +#define CTL_MIC_MODE 2 +#define CTL_SYNTH_VOL 4 +#define CTL_WAVE_VOL 7 #define CMD_SET_MT32 0x96 #define CMD_GET_MT32 0x97 #define CMD_SET_EXTMIDI 0x9b @@ -86,9 +90,11 @@ { int base, irq, dma; int ok; /* Properly detected */ + int failed; int dma_allocated; int my_audiodev; int opened; + sound_os_info *osp; } sscape_info; @@ -96,7 +102,9 @@ {0}; static struct sscape_info *devc = &dev_info; -DEFINE_WAIT_QUEUE (sscape_sleeper, sscape_sleep_flag); +static struct wait_queue *sscape_sleeper = NULL; +static volatile struct snd_wait sscape_sleep_flag = +{0}; /* Some older cards have assigned interrupt bits differently than new ones */ static char valid_interrupts_old[] = @@ -121,10 +129,11 @@ unsigned long flags; unsigned char val; - DISABLE_INTR (flags); - OUTB (reg, PORT (ODIE_ADDR)); - val = INB (PORT (ODIE_DATA)); - RESTORE_INTR (flags); + save_flags (flags); + cli (); + outb (reg, PORT (ODIE_ADDR)); + val = inb (PORT (ODIE_DATA)); + restore_flags (flags); return val; } @@ -133,31 +142,33 @@ { unsigned long flags; - DISABLE_INTR (flags); - OUTB (reg, PORT (ODIE_ADDR)); - OUTB (data, PORT (ODIE_DATA)); - RESTORE_INTR (flags); + save_flags (flags); + cli (); + outb (reg, PORT (ODIE_ADDR)); + outb (data, PORT (ODIE_DATA)); + restore_flags (flags); } static void host_open (struct sscape_info *devc) { - OUTB (0x00, PORT (HOST_CTRL)); /* Put the board to the host mode */ + outb (0x00, PORT (HOST_CTRL)); /* Put the board to the host mode */ } static void host_close (struct sscape_info *devc) { - OUTB (0x03, PORT (HOST_CTRL)); /* Put the board to the MIDI mode */ + outb (0x03, PORT (HOST_CTRL)); /* Put the board to the MIDI mode */ } static int host_write (struct sscape_info *devc, unsigned char *data, int count) { unsigned long flags; - int i, timeout; + int i, timeout_val; - DISABLE_INTR (flags); + save_flags (flags); + cli (); /* * Send the command and data bytes @@ -165,21 +176,21 @@ for (i = 0; i < count; i++) { - for (timeout = 10000; timeout > 0; timeout--) - if (INB (PORT (HOST_CTRL)) & TX_READY) + for (timeout_val = 10000; timeout_val > 0; timeout_val--) + if (inb (PORT (HOST_CTRL)) & TX_READY) break; - if (timeout <= 0) + if (timeout_val <= 0) { - RESTORE_INTR (flags); + restore_flags (flags); return 0; } - OUTB (data[i], PORT (HOST_DATA)); + outb (data[i], PORT (HOST_DATA)); } - RESTORE_INTR (flags); + restore_flags (flags); return 1; } @@ -188,28 +199,29 @@ host_read (struct sscape_info *devc) { unsigned long flags; - int timeout; + int timeout_val; unsigned char data; - DISABLE_INTR (flags); + save_flags (flags); + cli (); /* * Read a byte */ - for (timeout = 10000; timeout > 0; timeout--) - if (INB (PORT (HOST_CTRL)) & RX_READY) + for (timeout_val = 10000; timeout_val > 0; timeout_val--) + if (inb (PORT (HOST_CTRL)) & RX_READY) break; - if (timeout <= 0) + if (timeout_val <= 0) { - RESTORE_INTR (flags); + restore_flags (flags); return -1; } - data = INB (PORT (HOST_DATA)); + data = inb (PORT (HOST_DATA)); - RESTORE_INTR (flags); + restore_flags (flags); return data; } @@ -260,6 +272,18 @@ host_close (devc); } +static void +set_control (struct sscape_info *devc, int ctrl, int value) +{ + host_open (devc); + host_command3 (devc, CMD_SET_CONTROL, ctrl, value); + if (host_read (devc) != CMD_ACK) + { + printk ("SNDSCAPE: Setting control (%d) failed\n", ctrl); + } + host_close (devc); +} + static int get_board_type (struct sscape_info *devc) { @@ -275,15 +299,18 @@ } void -sscapeintr (INT_HANDLER_PARMS (irq, dummy)) +sscapeintr (int irq, struct pt_regs *dummy) { unsigned char bits, tmp; static int debug = 0; printk ("sscapeintr(0x%02x)\n", (bits = sscape_read (devc, GA_INTSTAT_REG))); - if (SOMEONE_WAITING (sscape_sleeper, sscape_sleep_flag)) + if ((sscape_sleep_flag.mode & WK_SLEEP)) { - WAKE_UP (sscape_sleeper, sscape_sleep_flag); + { + sscape_sleep_flag.mode = WK_WAKEUP; + wake_up (&sscape_sleeper); + }; } if (bits & 0x02) /* Host interface interrupt */ @@ -294,7 +321,7 @@ #if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI) if (bits & 0x01) { - mpuintr (INT_HANDLER_CALL (irq)); + mpuintr (irq, NULL); if (debug++ > 10) /* Temporary debugging hack */ { sscape_write (devc, GA_INTENA_REG, 0x00); /* Disable all interrupts */ @@ -383,10 +410,10 @@ for (i = 0; i < 10; i++) { - if (INB (devc->base + HOST_CTRL) & 0x80) + if (inb (devc->base + HOST_CTRL) & 0x80) return 1; - if (INB (devc->base) != 0x00) + if (inb (devc->base) != 0x00) return 1; } @@ -401,7 +428,7 @@ { set_mt32 (devc, 0); if (!verify_mpu (devc)) - return RET_ERROR (EIO); + return -EIO; } return 0; @@ -413,17 +440,20 @@ struct sscape_info *devc = dev_info; unsigned long flags; - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (devc->dma_allocated) { sscape_write (devc, GA_DMAA_REG, 0x20); /* DMA channel disabled */ #ifndef EXCLUDE_NATIVE_PCM - DMAbuf_close_dma (devc->my_audiodev); #endif devc->dma_allocated = 0; } - RESET_WAIT_QUEUE (sscape_sleeper, sscape_sleep_flag); - RESTORE_INTR (flags); + { + sscape_sleep_flag.aborting = 0; + sscape_sleep_flag.mode = WK_NONE; + }; + restore_flags (flags); return; } @@ -438,7 +468,7 @@ { unsigned long flags; unsigned char temp; - int done, timeout; + int done, timeout_val; if (flag & CPF_FIRST) { @@ -447,25 +477,21 @@ * before continuing. */ - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (devc->dma_allocated == 0) { #ifndef EXCLUDE_NATIVE_PCM - if (DMAbuf_open_dma (devc->my_audiodev) < 0) - { - RESTORE_INTR (flags); - return 0; - } #endif devc->dma_allocated = 1; } - RESTORE_INTR (flags); + restore_flags (flags); sscape_write (devc, GA_HMCTL_REG, (temp = sscape_read (devc, GA_HMCTL_REG)) & 0x3f); /*Reset */ - for (timeout = 10000; timeout > 0; timeout--) + for (timeout_val = 10000; timeout_val > 0; timeout_val--) sscape_read (devc, GA_HMCTL_REG); /* Delay */ /* Take board out of reset */ @@ -476,31 +502,53 @@ /* * Transfer one code block using DMA */ - memcpy (audio_devs[devc->my_audiodev]->dmap->raw_buf[0], block, size); + memcpy (audio_devs[devc->my_audiodev]->dmap_out->raw_buf, block, size); - DISABLE_INTR (flags); + save_flags (flags); + cli (); /******** INTERRUPTS DISABLED NOW ********/ do_dma (devc, SSCAPE_DMA_A, - audio_devs[devc->my_audiodev]->dmap->raw_buf_phys[0], + audio_devs[devc->my_audiodev]->dmap_out->raw_buf_phys, size, DMA_MODE_WRITE); /* * Wait until transfer completes. */ - RESET_WAIT_QUEUE (sscape_sleeper, sscape_sleep_flag); + { + sscape_sleep_flag.aborting = 0; + sscape_sleep_flag.mode = WK_NONE; + }; done = 0; - timeout = 100; - while (!done && timeout-- > 0) + timeout_val = 100; + while (!done && timeout_val-- > 0) { int resid; - DO_SLEEP (sscape_sleeper, sscape_sleep_flag, 1); + + { + unsigned long tl; + + if (1) + tl = current->timeout = jiffies + (1); + else + tl = 0xffffffff; + sscape_sleep_flag.mode = WK_SLEEP; + interruptible_sleep_on (&sscape_sleeper); + if (!(sscape_sleep_flag.mode & WK_WAKEUP)) + { + if (current->signal & ~current->blocked) + sscape_sleep_flag.aborting = 1; + else if (jiffies >= tl) + sscape_sleep_flag.mode |= WK_TIMEOUT; + } + sscape_sleep_flag.mode &= ~WK_SLEEP; + }; clear_dma_ff (devc->dma); if ((resid = get_dma_residue (devc->dma)) == 0) done = 1; } - RESTORE_INTR (flags); + restore_flags (flags); if (!done) return 0; @@ -509,8 +557,8 @@ /* * Take the board out of reset */ - OUTB (0x00, PORT (HOST_CTRL)); - OUTB (0x00, PORT (MIDI_CTRL)); + outb (0x00, PORT (HOST_CTRL)); + outb (0x00, PORT (MIDI_CTRL)); temp = sscape_read (devc, GA_HMCTL_REG); temp |= 0x40; @@ -520,32 +568,70 @@ * Wait until the ODB wakes up */ - DISABLE_INTR (flags); + save_flags (flags); + cli (); done = 0; - timeout = 5 * HZ; - while (!done && timeout-- > 0) + timeout_val = 5 * HZ; + while (!done && timeout_val-- > 0) { - DO_SLEEP (sscape_sleeper, sscape_sleep_flag, 1); - if (INB (PORT (HOST_DATA)) == 0xff) /* OBP startup acknowledge */ + + { + unsigned long tl; + + if (1) + tl = current->timeout = jiffies + (1); + else + tl = 0xffffffff; + sscape_sleep_flag.mode = WK_SLEEP; + interruptible_sleep_on (&sscape_sleeper); + if (!(sscape_sleep_flag.mode & WK_WAKEUP)) + { + if (current->signal & ~current->blocked) + sscape_sleep_flag.aborting = 1; + else if (jiffies >= tl) + sscape_sleep_flag.mode |= WK_TIMEOUT; + } + sscape_sleep_flag.mode &= ~WK_SLEEP; + }; + if (inb (PORT (HOST_DATA)) == 0xff) /* OBP startup acknowledge */ done = 1; } - RESTORE_INTR (flags); + restore_flags (flags); if (!done) { printk ("SoundScape: The OBP didn't respond after code download\n"); return 0; } - DISABLE_INTR (flags); + save_flags (flags); + cli (); done = 0; - timeout = 5 * HZ; - while (!done && timeout-- > 0) + timeout_val = 5 * HZ; + while (!done && timeout_val-- > 0) { - DO_SLEEP (sscape_sleeper, sscape_sleep_flag, 1); - if (INB (PORT (HOST_DATA)) == 0xfe) /* Host startup acknowledge */ + + { + unsigned long tl; + + if (1) + tl = current->timeout = jiffies + (1); + else + tl = 0xffffffff; + sscape_sleep_flag.mode = WK_SLEEP; + interruptible_sleep_on (&sscape_sleeper); + if (!(sscape_sleep_flag.mode & WK_WAKEUP)) + { + if (current->signal & ~current->blocked) + sscape_sleep_flag.aborting = 1; + else if (jiffies >= tl) + sscape_sleep_flag.mode |= WK_TIMEOUT; + } + sscape_sleep_flag.mode &= ~WK_SLEEP; + }; + if (inb (PORT (HOST_DATA)) == 0xfe) /* Host startup acknowledge */ done = 1; } - RESTORE_INTR (flags); + restore_flags (flags); if (!done) { printk ("SoundScape: OBP Initialization failed.\n"); @@ -555,6 +641,9 @@ printk ("SoundScape board of type %d initialized OK\n", get_board_type (devc)); + set_control (devc, CTL_MASTER_VOL, 100); + set_control (devc, CTL_SYNTH_VOL, 100); + #ifdef SSCAPE_DEBUG3 /* * Temporary debugging aid. Print contents of the registers after @@ -577,19 +666,19 @@ download_boot_block (void *dev_info, copr_buffer * buf) { if (buf->len <= 0 || buf->len > sizeof (buf->data)) - return RET_ERROR (EINVAL); + return -EINVAL; if (!sscape_download_boot (devc, buf->data, buf->len, buf->flags)) { printk ("SSCAPE: Unable to load microcode block to the OBP.\n"); - return RET_ERROR (EIO); + return -EIO; } return 0; } static int -sscape_coproc_ioctl (void *dev_info, unsigned int cmd, unsigned int arg, int local) +sscape_coproc_ioctl (void *dev_info, unsigned int cmd, ioctl_arg arg, int local) { switch (cmd) @@ -604,19 +693,26 @@ copr_buffer *buf; int err; - buf = (copr_buffer *) KERNEL_MALLOC (sizeof (copr_buffer)); - IOCTL_FROM_USER ((char *) buf, (char *) arg, 0, sizeof (*buf)); + buf = (copr_buffer *) ( + { + caddr_t x; + x = kmalloc (sizeof (copr_buffer), GFP_KERNEL); + x; + } + ); + if (buf == NULL) + return -ENOSPC; + memcpy_fromfs (((char *) buf), &(((char *) arg)[0]), (sizeof (*buf))); err = download_boot_block (dev_info, buf); - KERNEL_FREE (buf); + kfree (buf); return err; } break; default: - return RET_ERROR (EINVAL); + return -EINVAL; } - return RET_ERROR (EINVAL); } static coproc_operations sscape_coproc_operations = @@ -635,28 +731,15 @@ unsigned long flags; sscape_info *devc = (sscape_info *) audio_devs[dev]->devc; - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (devc->opened) { - RESTORE_INTR (flags); - return RET_ERROR (EBUSY); - } - - if (devc->dma_allocated == 0) - { - int err; - - if ((err = DMAbuf_open_dma (devc->my_audiodev)) < 0) - { - RESTORE_INTR (flags); - return err; - } - - devc->dma_allocated = 1; + restore_flags (flags); + return -EBUSY; } - devc->opened = 1; - RESTORE_INTR (flags); + restore_flags (flags); #ifdef SSCAPE_DEBUG4 /* * Temporary debugging aid. Print contents of the registers @@ -681,17 +764,12 @@ DEB (printk ("sscape_audio_close(void)\n")); - DISABLE_INTR (flags); + save_flags (flags); + cli (); - if (devc->dma_allocated) - { - sscape_write (devc, GA_DMAA_REG, 0x20); /* DMA channel disabled */ - DMAbuf_close_dma (dev); - devc->dma_allocated = 0; - } devc->opened = 0; - RESTORE_INTR (flags); + restore_flags (flags); } static int @@ -713,7 +791,7 @@ } static int -sscape_audio_ioctl (int dev, unsigned int cmd, unsigned int arg, int local) +sscape_audio_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local) { sscape_info *devc = (sscape_info *) audio_devs[dev]->devc; @@ -721,42 +799,42 @@ { case SOUND_PCM_WRITE_RATE: if (local) - return set_speed (devc, arg); - return IOCTL_OUT (arg, set_speed (devc, IOCTL_IN (arg))); + return set_speed (devc, (int) arg); + return snd_ioctl_return ((int *) arg, set_speed (devc, get_fs_long ((long *) arg))); case SOUND_PCM_READ_RATE: if (local) return 8000; - return IOCTL_OUT (arg, 8000); + return snd_ioctl_return ((int *) arg, 8000); case SNDCTL_DSP_STEREO: if (local) - return set_channels (devc, arg + 1) - 1; - return IOCTL_OUT (arg, set_channels (devc, IOCTL_IN (arg) + 1) - 1); + return set_channels (devc, (int) arg + 1) - 1; + return snd_ioctl_return ((int *) arg, set_channels (devc, get_fs_long ((long *) arg) + 1) - 1); case SOUND_PCM_WRITE_CHANNELS: if (local) - return set_channels (devc, arg); - return IOCTL_OUT (arg, set_channels (devc, IOCTL_IN (arg))); + return set_channels (devc, (int) arg); + return snd_ioctl_return ((int *) arg, set_channels (devc, get_fs_long ((long *) arg))); case SOUND_PCM_READ_CHANNELS: if (local) return 1; - return IOCTL_OUT (arg, 1); + return snd_ioctl_return ((int *) arg, 1); case SNDCTL_DSP_SAMPLESIZE: if (local) - return set_format (devc, arg); - return IOCTL_OUT (arg, set_format (devc, IOCTL_IN (arg))); + return set_format (devc, (int) arg); + return snd_ioctl_return ((int *) arg, set_format (devc, get_fs_long ((long *) arg))); case SOUND_PCM_READ_BITS: if (local) return 8; - return IOCTL_OUT (arg, 8); + return snd_ioctl_return ((int *) arg, 8); default:; } - return RET_ERROR (EINVAL); + return -EINVAL; } static void @@ -811,6 +889,8 @@ NULL }; +static int sscape_detected = 0; + long attach_sscape (long mem_start, struct address_info *hw_config) { @@ -849,7 +929,7 @@ int i, irq_bits = 0xff; - if (!probe_sscape (hw_config)) + if (sscape_detected != hw_config->io_base) return mem_start; if (old_hardware) @@ -873,7 +953,8 @@ return mem_start; } - DISABLE_INTR (flags); + save_flags (flags); + cli (); for (i = 1; i < 10; i++) switch (i) @@ -908,7 +989,7 @@ sscape_write (devc, i, regs[i]); } - RESTORE_INTR (flags); + restore_flags (flags); #ifdef SSCAPE_DEBUG2 /* @@ -924,17 +1005,17 @@ #endif #if !defined(EXCLUDE_MIDI) && !defined(EXCLUDE_MPU_EMU) - hw_config->always_detect = 1; if (probe_mpu401 (hw_config)) - { - int prev_devs; + hw_config->always_detect = 1; + { + int prev_devs; - prev_devs = num_midis; - mem_start = attach_mpu401 (mem_start, hw_config); + prev_devs = num_midis; + mem_start = attach_mpu401 (mem_start, hw_config); - if (num_midis == (prev_devs + 1)) /* The MPU driver installed itself */ - midi_devs[prev_devs]->coproc = &sscape_coproc_operations; - } + if (num_midis == (prev_devs + 1)) /* The MPU driver installed itself */ + midi_devs[prev_devs]->coproc = &sscape_coproc_operations; + } #endif #ifndef EXCLUDE_NATIVE_PCM @@ -944,14 +1025,13 @@ if (num_audiodevs < MAX_AUDIO_DEV) { audio_devs[my_dev = num_audiodevs++] = &sscape_audio_operations; - audio_devs[my_dev]->dmachan = hw_config->dma; - audio_devs[my_dev]->buffcount = 1; + audio_devs[my_dev]->dmachan1 = hw_config->dma; audio_devs[my_dev]->buffsize = DSP_BUFFSIZE; audio_devs[my_dev]->devc = devc; devc->my_audiodev = my_dev; devc->opened = 0; audio_devs[my_dev]->coproc = &sscape_coproc_operations; - if (snd_set_irq_handler (hw_config->irq, sscapeintr, "SoundScape") < 0) + if (snd_set_irq_handler (hw_config->irq, sscapeintr, "SoundScape", devc->osp) < 0) printk ("Error: Can't allocate IRQ for SoundScape\n"); sscape_write (devc, GA_INTENA_REG, 0x80); /* Master IRQ enable */ @@ -961,6 +1041,7 @@ #endif #endif devc->ok = 1; + devc->failed = 0; return mem_start; } @@ -969,27 +1050,32 @@ { unsigned char save; + devc->failed = 1; devc->base = hw_config->io_base; devc->irq = hw_config->irq; devc->dma = hw_config->dma; + devc->osp = hw_config->osp; + + if (sscape_detected != 0 && sscape_detected != hw_config->io_base) + return 0; /* * First check that the address register of "ODIE" is * there and that it has exactly 4 writeable bits. * First 4 bits */ - if ((save = INB (PORT (ODIE_ADDR))) & 0xf0) + if ((save = inb (PORT (ODIE_ADDR))) & 0xf0) return 0; - OUTB (0x00, PORT (ODIE_ADDR)); - if (INB (PORT (ODIE_ADDR)) != 0x00) + outb (0x00, PORT (ODIE_ADDR)); + if (inb (PORT (ODIE_ADDR)) != 0x00) return 0; - OUTB (0xff, PORT (ODIE_ADDR)); - if (INB (PORT (ODIE_ADDR)) != 0x0f) + outb (0xff, PORT (ODIE_ADDR)); + if (inb (PORT (ODIE_ADDR)) != 0x0f) return 0; - OUTB (save, PORT (ODIE_ADDR)); + outb (save, PORT (ODIE_ADDR)); /* * Now verify that some indirect registers return zero on some bits. @@ -1020,19 +1106,27 @@ if (old_hardware) /* Check that it's really an old Spea/Reveal card. */ { - int tmp, status = 0; + int status = 0; + unsigned char tmp; int cc; if (!((tmp = sscape_read (devc, GA_HMCTL_REG)) & 0xc0)) { sscape_write (devc, GA_HMCTL_REG, tmp | 0x80); for (cc = 0; cc < 200000; ++cc) - INB (devc->base + ODIE_ADDR); + inb (devc->base + ODIE_ADDR); } else old_hardware = 0; } + if (sound_alloc_dma (hw_config->dma, "soundscape")) + { + printk ("sscape.c: Can't allocate DMA channel\n"); + return 0; + } + + sscape_detected = hw_config->io_base; return 1; } @@ -1042,6 +1136,9 @@ { int i, irq_bits = 0xff; + if (devc->failed) + return 0; + if (devc->ok == 0) { printk ("SoundScape: Invalid initialization order.\n"); @@ -1060,7 +1157,7 @@ return 0; } - return ad1848_detect (hw_config->io_base); + return ad1848_detect (hw_config->io_base, NULL, hw_config->osp); } long @@ -1109,7 +1206,9 @@ ad1848_init ("SoundScape", hw_config->io_base, hw_config->irq, hw_config->dma, - hw_config->dma); + hw_config->dma, + 0, + devc->osp); #ifdef EXCLUDE_NATIVE_PCM if (num_audiodevs == (prev_devs + 1)) /* The AD1848 driver installed itself */ @@ -1129,6 +1228,24 @@ #endif return mem_start; +} + +void +unload_sscape (struct address_info *hw_config) +{ + unload_mpu401 (hw_config); + snd_release_irq (hw_config->irq); + sound_free_dma (hw_config->dma); +} + +void +unload_ss_ms_sound (struct address_info *hw_config) +{ + ad1848_unload (hw_config->io_base, + hw_config->irq, + hw_config->dma, + hw_config->dma, + 0); } #endif diff -u --recursive --new-file v1.3.33/linux/drivers/sound/sys_timer.c linux/drivers/sound/sys_timer.c --- v1.3.33/linux/drivers/sound/sys_timer.c Tue Jul 11 10:02:55 1995 +++ linux/drivers/sound/sys_timer.c Wed Oct 11 07:55:42 1995 @@ -45,29 +45,19 @@ static void poll_def_tmr (unsigned long dummy); -DEFINE_TIMER (def_tmr, poll_def_tmr); + +static struct timer_list def_tmr = +{NULL, NULL, 0, 0, poll_def_tmr}; static unsigned long tmr2ticks (int tmr_value) { /* - * Convert system timer ticks (HZ) to MIDI ticks + * Convert system timer ticks (HZ) to MIDI ticks + * (divide # of MIDI ticks/minute by # of system ticks/minute). */ - unsigned long tmp; - unsigned long scale; - - tmp = (tmr_value * 1000) / HZ; /* Convert to msecs */ - - if (curr_tempo == 0 || curr_timebase == 0) /* Error? */ - scale = 1; - else - scale = (60 * 1000) / (curr_tempo * curr_timebase); /* msecs per MIDI tick */ - - if (scale == 0) /* Error? */ - scale = 1; - - return (tmp + (scale >> 1)) / scale; + return ((tmr_value * curr_tempo * curr_timebase) + (30 * HZ)) / (60 * HZ); } static void @@ -76,7 +66,11 @@ if (opened) { - ACTIVATE_TIMER (def_tmr, poll_def_tmr, 1); + + { + def_tmr.expires = (1) + jiffies; + add_timer (&def_tmr); + }; if (tmr_running) { @@ -97,28 +91,33 @@ { unsigned long flags; - DISABLE_INTR (flags); + save_flags (flags); + cli (); tmr_offs = 0; ticks_offs = 0; tmr_ctr = 0; next_event_time = 0xffffffff; prev_event_time = 0; curr_ticks = 0; - RESTORE_INTR (flags); + restore_flags (flags); } static int def_tmr_open (int dev, int mode) { if (opened) - return RET_ERROR (EBUSY); + return -EBUSY; tmr_reset (); curr_tempo = 60; curr_timebase = HZ; opened = 1; - ACTIVATE_TIMER (def_tmr, poll_def_tmr, 1); + + { + def_tmr.expires = (1) + jiffies; + add_timer (&def_tmr); + }; return 0; } @@ -127,6 +126,7 @@ def_tmr_close (int dev) { opened = tmr_running = 0; + del_timer (&def_tmr);; } static int @@ -172,8 +172,8 @@ { if (parm < 8) parm = 8; - if (parm > 250) - parm = 250; + if (parm > 360) + parm = 360; tmr_offs = tmr_ctr; ticks_offs += tmr2ticks (tmr_ctr); tmr_ctr = 0; @@ -202,12 +202,12 @@ static int def_tmr_ioctl (int dev, - unsigned int cmd, unsigned int arg) + unsigned int cmd, ioctl_arg arg) { switch (cmd) { case SNDCTL_TMR_SOURCE: - return IOCTL_OUT (arg, TMR_INTERNAL); + return snd_ioctl_return ((int *) arg, TMR_INTERNAL); break; case SNDCTL_TMR_START: @@ -228,7 +228,7 @@ case SNDCTL_TMR_TIMEBASE: { - int val = IOCTL_IN (arg); + int val = get_fs_long ((long *) arg); if (val) { @@ -239,13 +239,13 @@ curr_timebase = val; } - return IOCTL_OUT (arg, curr_timebase); + return snd_ioctl_return ((int *) arg, curr_timebase); } break; case SNDCTL_TMR_TEMPO: { - int val = IOCTL_IN (arg); + int val = get_fs_long ((long *) arg); if (val) { @@ -259,15 +259,15 @@ curr_tempo = val; } - return IOCTL_OUT (arg, curr_tempo); + return snd_ioctl_return ((int *) arg, curr_tempo); } break; case SNDCTL_SEQ_CTRLRATE: - if (IOCTL_IN (arg) != 0) /* Can't change */ - return RET_ERROR (EINVAL); + if (get_fs_long ((long *) arg) != 0) /* Can't change */ + return -EINVAL; - return IOCTL_OUT (arg, ((curr_tempo * curr_timebase) + 30) / 60); + return snd_ioctl_return ((int *) arg, ((curr_tempo * curr_timebase) + 30) / 60); break; case SNDCTL_TMR_METRONOME: @@ -277,7 +277,7 @@ default:; } - return RET_ERROR (EINVAL); + return -EINVAL; } static void @@ -295,7 +295,7 @@ struct sound_timer_operations default_sound_timer = { - {"System Timer", 0}, + {"System clock", 0}, 0, /* Priority */ 0, /* Local device link */ def_tmr_open, diff -u --recursive --new-file v1.3.33/linux/drivers/sound/trix.c linux/drivers/sound/trix.c --- v1.3.33/linux/drivers/sound/trix.c Sun Aug 13 14:45:34 1995 +++ linux/drivers/sound/trix.c Wed Oct 11 07:55:42 1995 @@ -40,18 +40,20 @@ static int sb_initialized = 0; static int mpu_initialized = 0; +static sound_os_info *trix_osp = NULL; + static unsigned char trix_read (int addr) { - OUTB ((unsigned char) addr, 0x390); /* MT-0002-PC ASIC address */ - return INB (0x391); /* MT-0002-PC ASIC data */ + outb ((unsigned char) addr, 0x390); /* MT-0002-PC ASIC address */ + return inb (0x391); /* MT-0002-PC ASIC data */ } static void trix_write (int addr, int data) { - OUTB ((unsigned char) addr, 0x390); /* MT-0002-PC ASIC address */ - OUTB ((unsigned char) data, 0x391); /* MT-0002-PC ASIC data */ + outb ((unsigned char) addr, 0x390); /* MT-0002-PC ASIC address */ + outb ((unsigned char) data, 0x391); /* MT-0002-PC ASIC data */ } static void @@ -61,22 +63,22 @@ int i = 0, n = sizeof (trix_boot); trix_write (0xf8, 0x00); /* ??????? */ - OUTB (0x01, base + 6); /* Clear the internal data pointer */ - OUTB (0x00, base + 6); /* Restart */ + outb (0x01, base + 6); /* Clear the internal data pointer */ + outb (0x00, base + 6); /* Restart */ /* * Write the boot code to the RAM upload/download register. * Each write increments the internal data pointer. */ - OUTB (0x01, base + 6); /* Clear the internal data pointer */ - OUTB (0x1A, 0x390); /* Select RAM download/upload port */ + outb (0x01, base + 6); /* Clear the internal data pointer */ + outb (0x1A, 0x390); /* Select RAM download/upload port */ for (i = 0; i < n; i++) - OUTB (trix_boot[i], 0x391); + outb (trix_boot[i], 0x391); for (i = n; i < 10016; i++) /* Clear up to first 16 bytes of data RAM */ - OUTB (0x00, 0x391); - OUTB (0x00, base + 6); /* Reset */ - OUTB (0x50, 0x390); /* ?????? */ + outb (0x00, 0x391); + outb (0x00, base + 6); /* Reset */ + outb (0x50, 0x390); /* ?????? */ #endif } @@ -85,21 +87,31 @@ { unsigned char addr_bits; + if (check_region (0x390, 2)) + { + printk ("AudioTriX: Config port I/O conflict\n"); + return 0; + } + if (kilroy_was_here) /* Already initialized */ return 0; if (trix_read (0x15) != 0x71) /* No asic signature */ - return 0; + { + DDB (printk ("No AudioTriX ASIC signature found\n")); + return 0; + } + + request_region (0x390, 2, "AudioTriX"); kilroy_was_here = 1; /* - * Disable separate wave playback and recording DMA channels since - * the driver doesn't support duplex mode yet. + * Reset some registers. */ - trix_write (0x13, trix_read (0x13) & ~0x80); - trix_write (0x14, trix_read (0x14) & ~0x80); + trix_write (0x13, 0); + trix_write (0x14, 0); /* * Configure the ASIC to place the codec to the proper I/O location @@ -140,10 +152,18 @@ * system returns 0x04 while some cards (AudioTriX Pro for example) * return 0x00. */ + if (check_region (hw_config->io_base, 8)) + { + printk ("AudioTriX: MSS I/O port conflict\n"); + return 0; + } + + trix_osp = hw_config->osp; + if (!trix_set_wss_port (hw_config)) return 0; - if ((INB (hw_config->io_base + 3) & 0x3f) != 0x00) + if ((inb (hw_config->io_base + 3) & 0x3f) != 0x00) { DDB (printk ("No MSS signature detected on port 0x%x\n", hw_config->io_base)); return 0; @@ -161,23 +181,30 @@ return 0; } + if (hw_config->dma2 != -1) + if (hw_config->dma2 != 0 && hw_config->dma2 != 1 && hw_config->dma2 != 3) + { + printk ("AudioTriX: Bad capture DMA %d\n", hw_config->dma2); + return 0; + } + /* * Check that DMA0 is not in use with a 8 bit board. */ - if (hw_config->dma == 0 && INB (hw_config->io_base + 3) & 0x80) + if (hw_config->dma == 0 && inb (hw_config->io_base + 3) & 0x80) { printk ("AudioTriX: Can't use DMA0 with a 8 bit card\n"); return 0; } - if (hw_config->irq > 7 && hw_config->irq != 9 && INB (hw_config->io_base + 3) & 0x80) + if (hw_config->irq > 7 && hw_config->irq != 9 && inb (hw_config->io_base + 3) & 0x80) { printk ("AudioTriX: Can't use IRQ%d with a 8 bit card\n", hw_config->irq); return 0; } - return ad1848_detect (hw_config->io_base + 4); + return ad1848_detect (hw_config->io_base + 4, NULL, hw_config->osp); } long @@ -191,9 +218,15 @@ {1, 2, 0, 3}; int config_port = hw_config->io_base + 0, version_port = hw_config->io_base + 3; + int dma1 = hw_config->dma, dma2 = hw_config->dma2; + + trix_osp = hw_config->osp; if (!kilroy_was_here) - return mem_start; + { + DDB (printk ("AudioTriX: Attach called but not probed yet???\n")); + return mem_start; + } /* * Set the IRQ and DMA addresses. @@ -201,18 +234,40 @@ bits = interrupt_bits[hw_config->irq]; if (bits == -1) - return mem_start; + { + printk ("AudioTriX: Bad IRQ (%d)\n", hw_config->irq); + return mem_start; + } - OUTB (bits | 0x40, config_port); - if ((INB (version_port) & 0x40) == 0) + outb (bits | 0x40, config_port); + if ((inb (version_port) & 0x40) == 0) printk ("[IRQ Conflict?]"); - OUTB (bits | dma_bits[hw_config->dma], config_port); /* Write IRQ+DMA setup */ + if (hw_config->dma2 == -1) /* Single DMA mode */ + { + bits |= dma_bits[dma1]; + dma2 = dma1; + } + else + { + unsigned char tmp; + + tmp = trix_read (0x13) & ~30; + trix_write (0x13, tmp | 0x80 | (dma1 << 4)); + + tmp = trix_read (0x14) & ~30; + trix_write (0x14, tmp | 0x80 | (dma2 << 4)); + } + + outb (bits, config_port); /* Write IRQ+DMA setup */ ad1848_init ("AudioTriX Pro", hw_config->io_base + 4, hw_config->irq, - hw_config->dma, - hw_config->dma); + dma1, + dma2, + 0, + hw_config->osp); + request_region (hw_config->io_base, 4, "MSS config"); return mem_start; } @@ -234,6 +289,12 @@ if (sb_initialized) return 0; + if (check_region (hw_config->io_base, 16)) + { + printk ("AudioTriX: SB I/O port conflict\n"); + return 0; + } + if (hw_config->io_base & 0xffffff8f != 0x200) return 0; @@ -300,6 +361,12 @@ if (mpu_initialized) return 0; + if (check_region (hw_config->io_base, 4)) + { + printk ("AudioTriX: MPU I/O port conflict\n"); + return 0; + } + if (hw_config->irq > 9) return 0; @@ -335,5 +402,36 @@ return 0; #endif } + +void +unload_trix_wss (struct address_info *hw_config) +{ + int dma2 = hw_config->dma2; + + if (dma2 == -1) + dma2 = hw_config->dma; + + release_region (0x390, 2); + release_region (hw_config->io_base, 4); + + ad1848_unload (hw_config->io_base + 4, + hw_config->irq, + hw_config->dma, + dma2, + 0); +} + +void +unload_trix_mpu (struct address_info *hw_config) +{ +#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI) + unload_mpu401 (hw_config); +#endif +} +void +unload_trix_sb (struct address_info *hw_config) +{ +} + #endif diff -u --recursive --new-file v1.3.33/linux/drivers/sound/uart6850.c linux/drivers/sound/uart6850.c --- v1.3.33/linux/drivers/sound/uart6850.c Tue Jul 11 10:02:55 1995 +++ linux/drivers/sound/uart6850.c Wed Oct 11 07:55:42 1995 @@ -42,12 +42,12 @@ #define STATPORT (uart6850_base+1) /* * * * Midi6850 Status Port on IBM */ -#define uart6850_status() INB(STATPORT) -#define input_avail() ((uart6850_status()&INPUT_AVAIL)) -#define output_ready() ((uart6850_status()&OUTPUT_READY)) -#define uart6850_cmd(cmd) OUTB(cmd, COMDPORT) -#define uart6850_read() INB(DATAPORT) -#define uart6850_write(byte) OUTB(byte, DATAPORT) +#define uart6850_status() inb( STATPORT) +#define input_avail() (uart6850_status()&INPUT_AVAIL) +#define output_ready() (uart6850_status()&OUTPUT_READY) +#define uart6850_cmd(cmd) outb( cmd, COMDPORT) +#define uart6850_read() inb( DATAPORT) +#define uart6850_write(byte) outb( byte, DATAPORT) #define OUTPUT_READY 0x02 /* * * * Mask for Data Read Ready Bit */ @@ -67,6 +67,13 @@ static int reset_uart6850 (void); static void (*midi_input_intr) (int dev, unsigned char data); +static void poll_uart6850 (unsigned long dummy); + +static sound_os_info *uart6850_osp; + + +static struct timer_list uart6850_timer = +{NULL, NULL, 0, 0, poll_uart6850}; static void uart6850_input_loop (void) @@ -93,7 +100,7 @@ } void -m6850intr (INTR_HANDLER_PARMS (irq, dummy)) +m6850intr (int irq, struct pt_regs *dummy) { if (input_avail ()) uart6850_input_loop (); @@ -109,23 +116,26 @@ { unsigned long flags; - DEFINE_TIMER (uart6850_timer, poll_uart6850); - if (!(uart6850_opened & OPEN_READ)) return; /* * No longer required */ - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (input_avail ()) uart6850_input_loop (); - ACTIVATE_TIMER (uart6850_timer, poll_uart6850, 1); /* - * Come back later - */ - RESTORE_INTR (flags); + { + uart6850_timer.expires = (1) + jiffies; + add_timer (&uart6850_timer); + }; /* + * Come back later + */ + + restore_flags (flags); } static int @@ -137,7 +147,7 @@ if (uart6850_opened) { printk ("Midi6850: Midi busy\n"); - return RET_ERROR (EBUSY); + return -EBUSY; } uart6850_cmd (UART_RESET); @@ -158,6 +168,7 @@ { uart6850_cmd (UART_MODE_ON); + del_timer (&uart6850_timer);; uart6850_opened = 0; } @@ -171,12 +182,13 @@ * Test for input since pending input seems to block the output. */ - DISABLE_INTR (flags); + save_flags (flags); + cli (); if (input_avail ()) uart6850_input_loop (); - RESTORE_INTR (flags); + restore_flags (flags); /* * Sometimes it takes about 13000 loops before the output becomes ready @@ -216,9 +228,9 @@ } static int -uart6850_ioctl (int dev, unsigned cmd, unsigned arg) +uart6850_ioctl (int dev, unsigned cmd, ioctl_arg arg) { - return RET_ERROR (EINVAL); + return -EINVAL; } static void @@ -268,12 +280,14 @@ } uart6850_base = hw_config->io_base; + uart6850_osp = hw_config->osp; uart6850_irq = hw_config->irq; if (!uart6850_detected) - return RET_ERROR (EIO); + return -EIO; - DISABLE_INTR (flags); + save_flags (flags); + cli (); for (timeout = 30000; timeout < 0 && !output_ready (); timeout--); /* * Wait @@ -282,7 +296,7 @@ ok = 1; - RESTORE_INTR (flags); + restore_flags (flags); printk (" <6850 Midi Interface>"); @@ -306,16 +320,23 @@ { int ok = 0; + uart6850_osp = hw_config->osp; uart6850_base = hw_config->io_base; uart6850_irq = hw_config->irq; - if (snd_set_irq_handler (uart6850_irq, m6850intr, "MIDI6850") < 0) + if (snd_set_irq_handler (uart6850_irq, m6850intr, "MIDI6850", uart6850_osp) < 0) return 0; ok = reset_uart6850 (); uart6850_detected = ok; return ok; +} + +void +unload_uart6850 (struct address_info *hw_config) +{ + snd_release_irq (hw_config->irq); } #endif diff -u --recursive --new-file v1.3.33/linux/fs/buffer.c linux/fs/buffer.c --- v1.3.33/linux/fs/buffer.c Mon Sep 25 12:26:23 1995 +++ linux/fs/buffer.c Thu Oct 12 16:00:04 1995 @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -43,6 +44,10 @@ static struct buffer_head ** hash_table; struct buffer_head ** buffer_pages; static struct buffer_head * lru_list[NR_LIST] = {NULL, }; +/* next_to_age is an array of pointers into the lru lists, used to + cycle through the buffers aging their contents when deciding which + buffers to discard when more memory is needed */ +static struct buffer_head * next_to_age[NR_LIST] = {NULL, }; static struct buffer_head * free_list[NR_SIZES] = {NULL, }; static struct buffer_head * unused_list = NULL; static struct wait_queue * buffer_wait = NULL; @@ -177,9 +182,6 @@ if (wait && bh->b_req && !bh->b_lock && !bh->b_dirt && !bh->b_uptodate) { err = 1; - printk("Weird - unlocked, clean and not " - "uptodate buffer on list %d %s %lu\n", - nlist, kdevname(bh->b_dev), bh->b_blocknr); continue; } /* Don't write clean buffers. Don't write ANY buffers @@ -302,8 +304,13 @@ if (lru_list[bh->b_list] == bh) lru_list[bh->b_list] = bh->b_next_free; - if(lru_list[bh->b_list] == bh) + if (lru_list[bh->b_list] == bh) lru_list[bh->b_list] = NULL; + if (next_to_age[bh->b_list] == bh) + next_to_age[bh->b_list] = bh->b_next_free; + if (next_to_age[bh->b_list] == bh) + next_to_age[bh->b_list] = NULL; + bh->b_next_free = bh->b_prev_free = NULL; } @@ -347,6 +354,8 @@ return; if (bh == lru_list[bh->b_list]) { lru_list[bh->b_list] = bh->b_next_free; + if (next_to_age[bh->b_list] == bh) + next_to_age[bh->b_list] = bh->b_next_free; return; } if(bh->b_dev == B_FREE) @@ -358,6 +367,8 @@ lru_list[bh->b_list] = bh; lru_list[bh->b_list]->b_prev_free = bh; }; + if (!next_to_age[bh->b_list]) + next_to_age[bh->b_list] = bh; bh->b_next_free = lru_list[bh->b_list]; bh->b_prev_free = lru_list[bh->b_list]->b_prev_free; @@ -373,8 +384,7 @@ isize = BUFSIZE_INDEX(bh->b_size); bh->b_dev = B_FREE; /* So it is obvious we are on the free list */ -/* add to back of free list */ - + /* add to back of free list */ if(!free_list[isize]) { free_list[isize] = bh; bh->b_prev_free = bh; @@ -389,16 +399,17 @@ static inline void insert_into_queues(struct buffer_head * bh) { -/* put at end of free list */ - + /* put at end of free list */ if(bh->b_dev == B_FREE) { put_last_free(bh); return; - }; + } if(!lru_list[bh->b_list]) { lru_list[bh->b_list] = bh; bh->b_prev_free = bh; - }; + } + if (!next_to_age[bh->b_list]) + next_to_age[bh->b_list] = bh; if (bh->b_next_free) panic("VFS: buffer LRU pointers corrupted"); bh->b_next_free = lru_list[bh->b_list]; bh->b_prev_free = lru_list[bh->b_list]->b_prev_free; @@ -672,7 +683,7 @@ /* Too bad, that was not enough. Try a little harder to grow some. */ - if (nr_free_pages > 5) { + if (nr_free_pages > min_free_pages + 5) { if (grow_buffers(GFP_BUFFER, size)) { needed -= PAGE_SIZE; goto repeat0; @@ -713,6 +724,7 @@ if (bh->b_uptodate && !bh->b_dirt) put_last_lru(bh); if(!bh->b_dirt) bh->b_flushtime = 0; + bh->b_touched = 1; return bh; } @@ -733,6 +745,8 @@ bh->b_flushtime=0; bh->b_req=0; bh->b_reuse=0; + bh->b_touched = 1; + bh->b_has_aged = 0; bh->b_dev=dev; bh->b_blocknr=block; insert_into_queues(bh); @@ -800,10 +814,10 @@ if (--buf->b_count) return; wake_up(&buffer_wait); -#if 0 if (buf->b_reuse) { buf->b_reuse = 0; - if (!buf->b_lock && !buf->b_dirt && !buf->b_wait) { + if (!buf->b_lock && !buf->b_dirt && + !buf->b_wait && buf->b_uptodate) { if(buf->b_dev == B_FREE) panic("brelse: Wrong list"); remove_from_queues(buf); @@ -811,7 +825,6 @@ put_last_free(buf); } } -#endif return; } printk("VFS: brelse: Trying to free free buffer\n"); @@ -1273,7 +1286,8 @@ * try_to_free() checks if all the buffers on this particular page * are unused, and free's the page if so. */ -static int try_to_free(struct buffer_head * bh, struct buffer_head ** bhp) +static int try_to_free(struct buffer_head * bh, struct buffer_head ** bhp, + int priority) { unsigned long page; struct buffer_head * tmp, * p; @@ -1288,6 +1302,8 @@ return 0; if (tmp->b_count || tmp->b_dirt || tmp->b_lock || tmp->b_wait) return 0; + if (priority && tmp->b_touched) + return 0; tmp = tmp->b_this_page; } while (tmp != bh); tmp = bh; @@ -1311,6 +1327,38 @@ return !mem_map[MAP_NR(page)].count; } +/* Age buffers on a given page, according to whether they have been + visited recently or not. */ +static inline void age_buffer(struct buffer_head *bh) +{ + struct buffer_head *tmp = bh; + int touched = 0; + + /* + * When we age a page, we mark all other buffers in the page + * with the "has_aged" flag. Then, when these aliased buffers + * come up for aging, we skip them until next pass. This + * ensures that a page full of multiple buffers only gets aged + * once per pass through the lru lists. + */ + if (bh->b_has_aged) { + bh->b_has_aged = 0; + return; + } + + do { + touched |= tmp->b_touched; + tmp->b_touched = 0; + tmp = tmp->b_this_page; + tmp->b_has_aged = 1; + } while (tmp != bh); + bh->b_has_aged = 0; + + if (touched) + touch_page((unsigned long) bh->b_data); + else + age_page((unsigned long) bh->b_data); +} /* * Consult the load average for buffers and decide whether or not @@ -1361,11 +1409,12 @@ } return 0; } + /* * Try to free up some pages by shrinking the buffer-cache * * Priority tells the routine how hard to try to shrink the - * buffers: 3 means "don't bother too much", while a value + * buffers: 6 means "don't bother too much", while a value * of 0 means "we'd better get some free pages now". * * "limit" is meant to limit the shrink-action only to pages @@ -1406,10 +1455,12 @@ for (i=0 ; !i || bh != free_list[isize]; bh = bh->b_next_free, i++) { if (bh->b_count || !bh->b_this_page) continue; - if (try_to_free(bh, &bh)) + if (!age_of((unsigned long) bh->b_data) && + try_to_free(bh, &bh, 6)) return 1; - if(!bh) break; /* Some interrupt must have used it after we - freed the page. No big deal - keep looking */ + if(!bh) break; + /* Some interrupt must have used it after we + freed the page. No big deal - keep looking */ } } @@ -1417,12 +1468,19 @@ for(nlist = 0; nlist < NR_LIST; nlist++) { repeat1: - if(priority > 3 && nlist == BUF_SHARED) continue; - bh = lru_list[nlist]; - if(!bh) continue; - i = 2*nr_buffers_type[nlist] >> priority; - for ( ; i-- > 0 ; bh = bh->b_next_free) { - /* We may have stalled while waiting for I/O to complete. */ + if(priority > 2 && nlist == BUF_SHARED) continue; + i = nr_buffers_type[nlist]; + i = ((BUFFEROUT_WEIGHT * i) >> 10) >> priority; + for ( ; i > 0; i-- ) { + bh = next_to_age[nlist]; + if (!bh) + break; + next_to_age[nlist] = bh->b_next_free; + + /* First, age the buffer. */ + age_buffer(bh); + /* We may have stalled while waiting for I/O + to complete. */ if(bh->b_list != nlist) goto repeat1; if (bh->b_count || !bh->b_this_page) continue; @@ -1439,7 +1497,13 @@ bh->b_count--; continue; } - if (try_to_free(bh, &bh)) + /* At priority 6, only consider really old + (age==0) buffers for reclaiming. At + priority 0, consider any buffers. */ + if ((age_of((unsigned long) bh->b_data) >> + (6-priority)) > 0) + continue; + if (try_to_free(bh, &bh, 0)) return 1; if(!bh) break; } diff -u --recursive --new-file v1.3.33/linux/fs/proc/link.c linux/fs/proc/link.c --- v1.3.33/linux/fs/proc/link.c Mon Sep 25 12:26:23 1995 +++ linux/fs/proc/link.c Wed Oct 11 09:12:40 1995 @@ -18,9 +18,12 @@ static int proc_readlink(struct inode *, char *, int); static int proc_follow_link(struct inode *, struct inode *, int, int, struct inode **); -static int proc_fd_dupf(struct inode * inode, struct file * f); -#define PLAN9_SEMANTICS +/* + * PLAN9_SEMANTICS won't work any more: it used an ugly hack that broke + * when the files[] array was updated only after the open code + */ +#undef PLAN9_SEMANTICS /* * links can't do much... @@ -33,7 +36,7 @@ NULL, /* select - default */ NULL, /* ioctl - default */ NULL, /* mmap */ - proc_fd_dupf, /* very special open code */ + NULL, /* very special open code */ NULL, /* no special release code */ NULL /* can't fsync */ }; @@ -56,47 +59,6 @@ NULL /* permission */ }; -/* - * This open routine is somewhat of a hack.... what we are doing is - * looking up the file structure of the newly opened proc fd file, and - * replacing it with the actual file structure of the process's file - * descriptor. This allows plan 9 semantics, so that the returned - * file descriptor is a dup of the target file descriptor. - */ -static int proc_fd_dupf(struct inode * inode, struct file * f) -{ - unsigned int pid, ino; - int i, fd; - struct task_struct * p; - struct file *new_f; - - for(fd=0 ; fdfiles->fd[fd] == f) - break; - if (fd>=NR_OPEN) - return -ENOENT; /* should never happen */ - - ino = inode->i_ino; - pid = ino >> 16; - ino &= 0x0000ffff; - - for (i = 0 ; i < NR_TASKS ; i++) - if ((p = task[i]) && p->pid == pid) - break; - - if ((i >= NR_TASKS) || - ((ino >> 8) != 1) || !(new_f = p->files->fd[ino & 0x0ff])) - return -ENOENT; - - if (new_f->f_mode && !f->f_mode && 3) - return -EPERM; - - new_f->f_count++; - current->files->fd[fd] = new_f; - if (!--f->f_count) - iput(f->f_inode); - return 0; -} static int proc_follow_link(struct inode * dir, struct inode * inode, int flag, int mode, struct inode ** res_inode) @@ -158,12 +120,6 @@ break; ino &= 0xff; if (ino < NR_OPEN && p->files->fd[ino]) { -#ifdef PLAN9_SEMANTICS - if (dir) { - *res_inode = inode; - return 0; - } -#endif new_inode = p->files->fd[ino]->f_inode; } break; diff -u --recursive --new-file v1.3.33/linux/include/asm-alpha/page.h linux/include/asm-alpha/page.h --- v1.3.33/linux/include/asm-alpha/page.h Mon Sep 25 12:26:23 1995 +++ linux/include/asm-alpha/page.h Thu Oct 12 16:00:04 1995 @@ -73,7 +73,8 @@ #define MAP_NR(addr) ((((unsigned long) (addr)) - PAGE_OFFSET) >> PAGE_SHIFT) typedef struct { - unsigned count:30, + unsigned count:24, + age:6, dirty:1, reserved:1; } mem_map_t; diff -u --recursive --new-file v1.3.33/linux/include/asm-alpha/unistd.h linux/include/asm-alpha/unistd.h --- v1.3.33/linux/include/asm-alpha/unistd.h Wed Oct 4 14:14:33 1995 +++ linux/include/asm-alpha/unistd.h Thu Oct 12 18:23:55 1995 @@ -177,16 +177,11 @@ #include #include -extern unsigned long kernel_clone(unsigned long clone_flags, void * stack); +extern long __kernel_thread(unsigned long, int (*)(void *), void *); -static inline long clone(unsigned long clone_flags, void * stack) +static inline long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) { - return kernel_clone(clone_flags, stack); -} - -static inline long fork(void) -{ - return kernel_clone(SIGCHLD, NULL); + return __kernel_thread(flags | CLONE_VM, fn, arg); } extern void sys_idle(void); diff -u --recursive --new-file v1.3.33/linux/include/asm-i386/page.h linux/include/asm-i386/page.h --- v1.3.33/linux/include/asm-i386/page.h Wed Oct 4 14:14:33 1995 +++ linux/include/asm-i386/page.h Thu Oct 12 16:00:04 1995 @@ -93,7 +93,8 @@ #define MAP_NR(addr) (((unsigned long)(addr)) >> PAGE_SHIFT) typedef struct { - unsigned count:30, + unsigned count:24, + age:6, dirty:1, reserved:1; } mem_map_t; diff -u --recursive --new-file v1.3.33/linux/include/asm-i386/unistd.h linux/include/asm-i386/unistd.h --- v1.3.33/linux/include/asm-i386/unistd.h Tue Oct 10 18:46:38 1995 +++ linux/include/asm-i386/unistd.h Tue Oct 10 18:58:49 1995 @@ -284,9 +284,10 @@ long retval; __asm__ __volatile__( + "movl %%esp,%%esi\n\t" "int $0x80\n\t" /* Linux/i386 system call */ - "testl %0,%0\n\t" /* child or parent? */ - "jne 1f\n\t" /* parent - jump */ + "cmpl %%esp,%%esi\n\t" /* child or parent? */ + "je 1f\n\t" /* parent - jump */ "pushl %3\n\t" /* push argument */ "call *%4\n\t" /* call fn */ "movl %2,%0\n\t" /* exit */ @@ -295,7 +296,8 @@ :"=a" (retval) :"0" (__NR_clone), "i" (__NR_exit), "r" (arg), "r" (fn), - "b" (flags | CLONE_VM)); + "b" (flags | CLONE_VM) + :"si"); return retval; } diff -u --recursive --new-file v1.3.33/linux/include/linux/fd.h linux/include/linux/fd.h --- v1.3.33/linux/include/linux/fd.h Mon Sep 18 14:54:09 1995 +++ linux/include/linux/fd.h Wed Oct 11 13:06:46 1995 @@ -1,43 +1,53 @@ #ifndef _LINUX_FD_H #define _LINUX_FD_H -#define FDCLRPRM 0 /* clear user-defined parameters */ -#define FDSETPRM 1 /* set user-defined parameters for current media */ -#define FDSETMEDIAPRM 1 -#define FDDEFPRM 2 /* set user-defined parameters until explicitly cleared */ -#define FDDEFMEDIAPRM 2 -#define FDGETPRM 3 /* get disk parameters */ -#define FDGETMEDIAPRM 3 -#define FDMSGON 4 /* issue kernel messages on media type change */ -#define FDMSGOFF 5 /* don't issue kernel messages on media type change */ -#define FDFMTBEG 6 /* begin formatting a disk */ -#define FDFMTTRK 7 /* format the specified track */ -#define FDFMTEND 8 /* end formatting a disk */ -#define FDSETEMSGTRESH 10 /* set fdc error reporting threshold */ -#define FDFLUSH 11 /* flush buffers for media; either for verifying media, or for +/* new interface flag */ +#define FDHAVEBATCHEDRAWCMD + +/* commands needing write access have 0x40 set */ +/* commands needing super user access have 0x80 set */ + +#define FDCLRPRM 0x0241 /* clear user-defined parameters */ +#define FDSETPRM 0x0242 /* set user-defined parameters for current media */ +#define FDSETMEDIAPRM 0x0242 +#define FDDEFPRM 0x0243 /* set user-defined parameters until explicitly + * cleared */ +#define FDDEFMEDIAPRM 0x0243 +#define FDGETPRM 0x0204 /* get disk parameters */ +#define FDGETMEDIAPRM 0x0204 +#define FDMSGON 0x0205 /* issue kernel messages on media type change */ +#define FDMSGOFF 0x0206 /* don't issue kernel messages on media type change */ +#define FDFMTBEG 0x0247 /* begin formatting a disk */ +#define FDFMTTRK 0x0248 /* format the specified track */ +#define FDFMTEND 0x0249 /* end formatting a disk */ +#define FDSETEMSGTRESH 0x024a /* set fdc error reporting threshold */ +#define FDFLUSH 0x024b /* flush buffers for media; either for verifying media, or for handling a media change without closing the file descriptor */ -#define FDSETMAXERRS 12 /* set abortion and read_track threshold */ -#define FDGETMAXERRS 14 /* get abortion and read_track threshold */ -#define FDGETDRVTYP 16 /* get drive type: 5 1/4 or 3 1/2 */ - -#define FDSETDRVPRM 20 /* set drive parameters */ -#define FDGETDRVPRM 21 /* get drive parameters */ -#define FDGETDRVSTAT 22 /* get drive state */ -#define FDPOLLDRVSTAT 23 /* get drive state */ -#define FDRESET 24 /* reset FDC */ - -#define FD_RESET_IF_NEEDED 0 -#define FD_RESET_IF_RAWCMD 1 -#define FD_RESET_ALWAYS 2 - -#define FDGETFDCSTAT 25 /* get fdc state */ -#define FDWERRORCLR 27 /* clear write error and badness information */ -#define FDWERRORGET 28 /* get write error and badness information */ +#define FDSETMAXERRS 0x024c /* set abortion and read_track threshold */ +#define FDGETMAXERRS 0x020e /* get abortion and read_track threshold */ +#define FDGETDRVTYP 0x020f /* get drive type: 5 1/4 or 3 1/2 */ + +#define FDSETDRVPRM 0x0250 /* set drive parameters */ +#define FDGETDRVPRM 0x0211 /* get drive parameters */ +#define FDGETDRVSTAT 0x0212 /* get drive state */ +#define FDPOLLDRVSTAT 0x0213 /* get drive state */ +#define FDRESET 0x0254 /* reset FDC */ + +#ifndef __ASSEMBLY__ +enum reset_mode { + FD_RESET_IF_NEEDED , + FD_RESET_IF_RAWCMD , + FD_RESET_ALWAYS }; +#endif + +#define FDGETFDCSTAT 0x0215 /* get fdc state */ +#define FDWERRORCLR 0x0256 /* clear write error and badness information */ +#define FDWERRORGET 0x0217 /* get write error and badness information */ -#define FDRAWCMD 30 /* send a raw command to the fdc */ +#define FDRAWCMD 0x0258 /* send a raw command to the fdc */ -#define FDTWADDLE 40 /* flicker motor-on bit before reading a sector */ +#define FDTWADDLE 0x0259 /* flicker motor-on bit before reading a sector */ /* * Maximum number of sectors in a track buffer. Track buffering is disabled @@ -69,7 +79,7 @@ rate, /* data rate. |= 0x40 for perpendicular */ spec1, /* stepping rate, head unload time */ fmt_gap; /* gap2 size */ - const char * name; /* used only for predefined formats */ + const char * name; /* used only for predefined formats */ }; struct format_descr { @@ -77,7 +87,7 @@ }; struct floppy_max_errors { - unsigned int + unsigned int abort, /* number of errors to be reached before aborting */ read_track, /* maximal number of errors permitted to read an * entire track at once */ @@ -96,30 +106,33 @@ /* the following structure is used by FDSETDRVPRM and FDGETDRVPRM */ struct floppy_drive_params { - char cmos; /* cmos type */ - - /* Spec2 is (HLD<<1 | ND), where HLD is head load time (1=2ms, 2=4 ms etc) - * and ND is set means no DMA. Hardcoded to 6 (HLD=6ms, use DMA). - */ - unsigned long max_dtr; /* Step rate, usec */ - unsigned long hlt; /* Head load/settle time, msec */ - unsigned long hut; /* Head unload time (remnant of 8" drives) */ - unsigned long srt; /* Step rate, usec */ - - unsigned long spinup; /* time needed for spinup ( in jiffies) */ - unsigned long spindown; /* timeout needed for spindown */ - unsigned char spindown_offset;/* decides in which position the disk - * will stop */ - unsigned char select_delay; /* delay to wait after select */ - unsigned char rps; /* rotations per second */ - unsigned char tracks; /* maximum number of tracks */ - unsigned long timeout; /* timeout for interrupt requests */ - - unsigned char interleave_sect;/* if there are more sectors, use interleave */ - - struct floppy_max_errors max_errors; - - char flags; /* various flags, including ftd_msg */ + char cmos; /* cmos type */ + + /* Spec2 is (HLD<<1 | ND), where HLD is head load time (1=2ms, 2=4 ms + * etc) and ND is set means no DMA. Hardcoded to 6 (HLD=6ms, use DMA). + */ + unsigned long max_dtr; /* Step rate, usec */ + unsigned long hlt; /* Head load/settle time, msec */ + unsigned long hut; /* Head unload time (remnant of + * 8" drives) */ + unsigned long srt; /* Step rate, usec */ + + unsigned long spinup; /* time needed for spinup (expressed + * in jiffies) */ + unsigned long spindown; /* timeout needed for spindown */ + unsigned char spindown_offset; /* decides in which position the disk + * will stop */ + unsigned char select_delay; /* delay to wait after select */ + unsigned char rps; /* rotations per second */ + unsigned char tracks; /* maximum number of tracks */ + unsigned long timeout; /* timeout for interrupt requests */ + + unsigned char interleave_sect; /* if there are more sectors, use + * interleave */ + + struct floppy_max_errors max_errors; + + char flags; /* various flags, including ftd_msg */ /* * Announce successful media type detection and media information loss after * disk changes. @@ -132,27 +145,28 @@ #define FD_SILENT_DCL_CLEAR 0x4 #define FD_INVERTED_DCL 0x80 - char read_track; /* use readtrack during probing? */ + char read_track; /* use readtrack during probing? */ /* * Auto-detection. Each drive type has eight formats which are * used in succession to try to read the disk. If the FDC cannot lock onto * the disk, the next format is tried. This uses the variable 'probing'. */ - short autodetect[8]; /* autodetected formats */ - - int checkfreq; /* how often should the drive be checked for disk changes */ - int native_format; /* native format of this drive */ + short autodetect[8]; /* autodetected formats */ + + int checkfreq; /* how often should the drive be checked for disk + * changes */ + int native_format; /* native format of this drive */ }; enum { -FD_NEED_TWADDLE_BIT, /* more magic */ -FD_VERIFY_BIT, /* inquire for write protection */ -FD_DISK_NEWCHANGE_BIT, /* change detected, and no action undertaken yet to - clear media change status */ -FD_UNUSED_BIT, -FD_DISK_CHANGED_BIT, /* disk has been changed since last i/o */ -FD_DISK_WRITABLE_BIT /* disk is writable */ + FD_NEED_TWADDLE_BIT, /* more magic */ + FD_VERIFY_BIT, /* inquire for write protection */ + FD_DISK_NEWCHANGE_BIT, /* change detected, and no action undertaken yet + * to clear media change status */ + FD_UNUSED_BIT, + FD_DISK_CHANGED_BIT, /* disk has been changed since last i/o */ + FD_DISK_WRITABLE_BIT /* disk is writable */ }; /* values for these flags */ @@ -165,77 +179,117 @@ #define FD_DRIVE_PRESENT 0 /* keep fdpatch utils compiling */ struct floppy_drive_struct { - signed char flags; - unsigned long spinup_date; - unsigned long select_date; - unsigned long first_read_date; - short probed_format; - short track; /* current track */ - short maxblock; /* id of highest block read */ - short maxtrack; /* id of highest half track read */ - int generation; /* how many diskchanges? */ + signed char flags; + unsigned long spinup_date; + unsigned long select_date; + unsigned long first_read_date; + short probed_format; + short track; /* current track */ + short maxblock; /* id of highest block read */ + short maxtrack; /* id of highest half track read */ + int generation; /* how many diskchanges? */ /* * (User-provided) media information is _not_ discarded after a media change * if the corresponding keep_data flag is non-zero. Positive values are * decremented after each probe. */ - int keep_data; - - /* Prevent "aliased" accesses. */ - int fd_ref; - int fd_device; /* should be a kdev_t but is externally visible */ - int last_checked; /* when was the drive last checked for a disk change? */ - - char *dmabuf; - int bufblocks; + int keep_data; + + /* Prevent "aliased" accesses. */ + int fd_ref; + int fd_device; + int last_checked; /* when was the drive last checked for a disk + * change? */ + + char *dmabuf; + int bufblocks; }; struct floppy_write_errors { - /* Write error logging. - * - * These fields can be cleared with the FDWERRORCLR ioctl. - * Only writes that were attempted but failed due to a physical media - * error are logged. write(2) calls that fail and return an error code - * to the user process are not counted. - */ - - unsigned int write_errors; /* number of physical write errors encountered */ - - /* position of first and last write errors */ - unsigned long first_error_sector; - int first_error_generation; - unsigned long last_error_sector; - int last_error_generation; - - unsigned int badness; /* highest retry count for a read or write operation */ + /* Write error logging. + * + * These fields can be cleared with the FDWERRORCLR ioctl. + * Only writes that were attempted but failed due to a physical media + * error are logged. write(2) calls that fail and return an error code + * to the user process are not counted. + */ + + unsigned int write_errors; /* number of physical write errors + * encountered */ + + /* position of first and last write errors */ + unsigned long first_error_sector; + int first_error_generation; + unsigned long last_error_sector; + int last_error_generation; + + unsigned int badness; /* highest retry count for a read or write + * operation */ }; struct floppy_fdc_state { - int spec1; /* spec1 value last used */ - int spec2; /* spec2 value last used */ + int spec1; /* spec1 value last used */ + int spec2; /* spec2 value last used */ int dtr; unsigned char version; /* FDC version code */ unsigned char dor; - int address; /* io address */ + int address; /* io address */ unsigned int rawcmd:2; unsigned int reset:1; unsigned int need_configure:1; unsigned int perp_mode:2; unsigned int has_fifo:1; + unsigned int driver_version; /* version code for floppy driver */ + + unsigned char track[4]; /* Position of the heads of the 4 + * units attached to this FDC, as + * stored on the FDC. In the future, + * the position as stored on the FDC + * might not agree with the actual + * physical position of these drive + * heads. By allowing such + * disagreement, it will be possible + * to reset the FDC without incurring + * the expensive cost of repositioning + * all heads. + * Right now, these positions are + * hard wired to 0. */ + + unsigned int reserved1; + unsigned int reserved2; }; + +#define FD_DRIVER_VERSION 0x100 +/* user programs using the floppy API should use floppy_fdc_state to + * get the version number of the floppy driver that they are running + * on. If this version number is bigger than the one compiled into the + * user program (the FD_DRIVER_VERSION define), it should be prepared + * to bigger structures + */ + + struct floppy_raw_cmd { - void *data; - long length; + unsigned int flags; + void *data; + char *kernel_data; /* location of data buffer in the kernel */ + struct floppy_raw_cmd *next; /* used for chaining of raw cmd's + * withing the kernel */ + long length; /* in: length of dma transfer. out: remaining bytes */ + long phys_length; /* physical length, if different from dma length */ + int buffer_length; /* length of allocated buffer */ + + unsigned char rate; + unsigned char cmd_count; + unsigned char cmd[16]; + unsigned char reply_count; + unsigned char reply[16]; + int track; + int resultcode; - unsigned char rate; - unsigned char flags; - unsigned char cmd_count; - unsigned char cmd[9]; - unsigned char reply_count; - unsigned char reply[7]; - int track; + int reserved1; + int reserved2; }; #endif @@ -245,11 +299,22 @@ #define FD_RAW_READ 1 #define FD_RAW_WRITE 2 #define FD_RAW_NO_MOTOR 4 -#define FD_RAW_DISK_CHANGE 4 -#define FD_RAW_INTR 8 -#define FD_RAW_SPIN 16 -#define FD_RAW_NO_MOTOR_AFTER 32 -#define FD_RAW_NEED_DISK 64 -#define FD_RAW_NEED_SEEK 128 - +#define FD_RAW_DISK_CHANGE 4 /* out: disk change flag was set */ +#define FD_RAW_INTR 8 /* wait for an interrupt */ +#define FD_RAW_SPIN 0x10 /* spin up the disk for this command */ +#define FD_RAW_NO_MOTOR_AFTER 0x20 /* switch the motor off after command + * completion */ +#define FD_RAW_NEED_DISK 0x40 /* this command needs a disk to be present */ +#define FD_RAW_NEED_SEEK 0x80 /* this command uses an implied seek (soft) */ + +/* more "in" flags */ +#define FD_RAW_MORE 0x100 /* more records follow */ +#define FD_RAW_STOP_IF_FAILURE 0x200 /* stop if we encounter a failure */ +#define FD_RAW_STOP_IF_SUCCESS 0x400 /* stop if command successful */ +#define FD_RAW_SOFTFAILURE 0x800 /* consider the return value for failure + * detection too */ + +/* more "out" flags */ +#define FD_RAW_FAILURE 0x10000 /* command sent to fdc, fdc returned error */ +#define FD_RAW_HARDFAILURE 0x20000 /* fdc had to be reset, or timed out */ #endif diff -u --recursive --new-file v1.3.33/linux/include/linux/fs.h linux/include/linux/fs.h --- v1.3.33/linux/include/linux/fs.h Mon Sep 18 14:54:09 1995 +++ linux/include/linux/fs.h Thu Oct 12 16:00:04 1995 @@ -124,11 +124,22 @@ unsigned char b_uptodate; unsigned char b_dirt; /* 0-clean,1-dirty */ unsigned char b_lock; /* 0 - ok, 1 -locked */ - unsigned char b_req; /* 0 if the buffer has been invalidated */ + unsigned char b_req; /* 0 if the buffer has been + * invalidated */ unsigned char b_list; /* List that this buffer appears */ - unsigned char b_reuse; /* 0 - normal, 1 - better reused for something else */ - unsigned long b_flushtime; /* Time when this (dirty) buffer should be written */ - unsigned long b_lru_time; /* Time when this buffer was last used. */ + unsigned char b_reuse; /* 0 - normal, + * 1 - better reused for something + * else */ + unsigned char b_touched:1; /* True if the buffer has been + * accessed since it was last aged */ + unsigned char b_has_aged:1; /* True if the buffer has aged + * (by alias to another buffer + * on the same page) since it + * was last scanned for aging */ + unsigned long b_flushtime; /* Time when this (dirty) buffer + * should be written */ + unsigned long b_lru_time; /* Time when this buffer was + * last used. */ struct wait_queue * b_wait; struct buffer_head * b_prev; /* doubly linked list of hash-queue */ struct buffer_head * b_next; diff -u --recursive --new-file v1.3.33/linux/include/linux/mm.h linux/include/linux/mm.h --- v1.3.33/linux/include/linux/mm.h Wed Sep 13 12:45:32 1995 +++ linux/include/linux/mm.h Fri Oct 13 11:02:29 1995 @@ -75,6 +75,8 @@ #define VM_DENYWRITE 0x0800 /* ETXTBSY on write attempts.. */ #define VM_EXECUTABLE 0x1000 +#define VM_DONTSWAP 0x2000 /* Some vm types have their own + * hard-coded swap mechanism */ #define VM_STACK_FLAGS 0x0177 @@ -106,6 +108,7 @@ }; extern mem_map_t * mem_map; +extern unsigned char *age_map; /* planning stage.. */ #define P_DIRTY 0x0001 diff -u --recursive --new-file v1.3.33/linux/include/linux/sched.h linux/include/linux/sched.h --- v1.3.33/linux/include/linux/sched.h Tue Oct 10 18:46:38 1995 +++ linux/include/linux/sched.h Fri Oct 13 11:02:29 1995 @@ -192,7 +192,7 @@ struct timer_list real_timer; long utime, stime, cutime, cstime, start_time; /* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */ - unsigned long min_flt, maj_flt, cmin_flt, cmaj_flt; + unsigned long min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap; int swappable:1; unsigned long swap_address; unsigned long old_maj_flt; /* old value of maj_flt */ @@ -264,7 +264,7 @@ /* timeout */ 0,0,0,0,0,0,0, \ /* timer */ { NULL, NULL, 0, 0, it_real_fn }, \ /* utime */ 0,0,0,0,0, \ -/* flt */ 0,0,0,0, \ +/* flt */ 0,0,0,0,0,0, \ /* swp */ 0,0,0,0,0, \ /* rlimits */ { {LONG_MAX, LONG_MAX}, {LONG_MAX, LONG_MAX}, \ {LONG_MAX, LONG_MAX}, {_STK_LIM, _STK_LIM}, \ diff -u --recursive --new-file v1.3.33/linux/include/linux/soundcard.h linux/include/linux/soundcard.h --- v1.3.33/linux/include/linux/soundcard.h Mon Jul 31 15:59:03 1995 +++ linux/include/linux/soundcard.h Wed Oct 11 07:55:37 1995 @@ -75,6 +75,9 @@ #define SNDCARD_TRXPRO_MPU 18 #define SNDCARD_MAD16 19 #define SNDCARD_MAD16_MPU 20 +#define SNDCARD_CS4232 21 +#define SNDCARD_CS4232_MPU 22 +#define SNDCARD_MAUI 23 /*********************************** * IOCTL Commands for /dev/sequencer @@ -230,7 +233,6 @@ char data[1]; /* The waveform data starts here */ }; - struct sysex_info { short key; /* Use GUS_PATCH here */ #define SYSEX_PATCH 0x05fd @@ -519,7 +521,7 @@ }; struct sound_timer_info { - char name[30]; + char name[32]; int caps; }; @@ -582,6 +584,7 @@ */ typedef struct audio_buf_info { int fragments; /* # of available fragments (partially usend ones not counted) */ + int fragstotal; /* Total # of fragments allocated */ int fragsize; /* Size of a fragment in bytes */ int bytes; /* Available space in bytes (includes partially used fragments) */ @@ -591,6 +594,39 @@ #define SNDCTL_DSP_GETOSPACE _IOR ('P',12, audio_buf_info) #define SNDCTL_DSP_GETISPACE _IOR ('P',13, audio_buf_info) #define SNDCTL_DSP_NONBLOCK _IO ('P',14) +#define SNDCTL_DSP_GETCAPS _IOR ('P',15, int) +# define DSP_CAP_REVISION 0x000000ff /* Bits for revision level (0 to 255) */ +# define DSP_CAP_DUPLEX 0x00000100 /* Full duplex record/playback */ +# define DSP_CAP_REALTIME 0x00000200 /* Real time capability */ +# define DSP_CAP_BATCH 0x00000400 /* Device has some kind of */ + /* internal buffers which may */ + /* cause some delays and */ + /* decrease precision of timing */ +# define DSP_CAP_COPROC 0x00000800 /* Has a coprocessor */ + /* Sometimes it's a DSP */ + /* but usually not */ +# define DSP_CAP_TRIGGER 0x00001000 /* Supports SETTRIGGER */ + +#define SNDCTL_DSP_GETTRIGGER _IOR ('P',16, int) +#define SNDCTL_DSP_SETTRIGGER _IOW ('P',16, int) +# define PCM_ENABLE_INPUT 0x00000001 +# define PCM_ENABLE_OUTPUT 0x00000002 + +typedef struct count_info { + int bytes; /* Total # of bytes processed */ + int blocks; /* # of fragment transitions since last time */ + int ptr; /* Current DMA pointer value */ + } count_info; + +#define SNDCTL_DSP_GETIPTR _IOR ('P',17, count_info) +#define SNDCTL_DSP_GETOPTR _IOR ('P',18, count_info) + +typedef struct buffmem_desc { + caddr_t buffer; + int size; + } buffmem_desc; +#define SNDCTL_DSP_MAPINBUF _IOR ('P', 19, buffmem_desc) +#define SNDCTL_DSP_MAPOUTBUF _IOR ('P', 20, buffmem_desc) #define SOUND_PCM_READ_RATE _IOR ('P', 2, int) #define SOUND_PCM_READ_CHANNELS _IOR ('P', 6, int) @@ -610,6 +646,13 @@ #define SOUND_PCM_GETOSPACE SNDCTL_DSP_GETOSPACE #define SOUND_PCM_GETISPACE SNDCTL_DSP_GETISPACE #define SOUND_PCM_NONBLOCK SNDCTL_DSP_NONBLOCK +#define SOUND_PCM_GETCAPS SNDCTL_DSP_GETCAPS +#define SOUND_PCM_GETTRIGGER SNDCTL_DSP_GETTRIGGER +#define SOUND_PCM_SETTRIGGER SNDCTL_DSP_SETTRIGGER +#define SOUND_PCM_GETIPTR SNDCTL_DSP_GETIPTR +#define SOUND_PCM_GETOPTR SNDCTL_DSP_GETOPTR +#define SOUND_PCM_MAPINBUF SNDCTL_DSP_MAPINBUF +#define SOUND_PCM_MAPOUTBUF SNDCTL_DSP_MAPOUTBUF /* * ioctl calls to be used in communication with coprocessors and @@ -714,7 +757,7 @@ #define SOUND_MIXER_DEVMASK 0xfe /* Arg contains a bit for each supported device */ #define SOUND_MIXER_RECMASK 0xfd /* Arg contains a bit for each supported recording source */ #define SOUND_MIXER_CAPS 0xfc - #define SOUND_CAP_EXCL_INPUT 0x00000001 /* Only one recording source at a time */ +# define SOUND_CAP_EXCL_INPUT 0x00000001 /* Only one recording source at a time */ #define SOUND_MIXER_STEREODEVS 0xfb /* Mixer channels supporting stereo */ /* Device mask bits */ @@ -815,6 +858,7 @@ #define EV_TIMING 0x81 #define EV_CHN_COMMON 0x92 #define EV_CHN_VOICE 0x93 +#define EV_SYSEX 0x94 /* * Event types 200 to 220 are reserved for application use. * These numbers will not be used by the driver. @@ -853,6 +897,11 @@ #define TMR_SPP 10 /* Song position pointer */ #define TMR_TIMESIG 11 /* Time signature */ +/* + * Local event types + */ +#define LOCL_STARTAUDIO 1 + #if (!defined(__KERNEL__) && !defined(KERNEL) && !defined(INKERNEL) && !defined(_KERNEL)) || defined(USE_SEQ_MACROS) /* * Some convenience macros to simplify programming of the @@ -967,6 +1016,28 @@ _seqbuf[_seqbufptr+5] = (p2);\ *(short *)&_seqbuf[_seqbufptr+6] = (w14);\ _SEQ_ADVBUF(8);} +/* + * SEQ_SYSEX permits sending of sysex messages. (It may look that it permits + * sending any MIDI bytes but it's absolutely not possible. Trying to do + * so _will_ cause problems with MPU401 intelligent mode). + * + * Sysex messages are sent in blocks of 1 to 6 bytes. Longer messages must be + * sent by calling SEQ_SYSEX() several times (there must be no other events + * between them). First sysex fragment must have 0xf0 in the first byte + * and the last byte (buf[len-1] of the last fragment must be 0xf7. No byte + * between these sysex start and end markers cannot be larger than 0x7f. Also + * lengths of each fragments (except the last one) must be 6. + * + * Breaking the above rules may work with some MIDI ports but is likely to + * cause fatal problems with some other devices (such as MPU401). + */ +#define SEQ_SYSEX(dev, buf, len) \ + {int i, l=(len); if (l>6)l=6;\ + _SEQ_NEEDBUF(8);\ + _seqbuf[_seqbufptr] = EV_SYSEX;\ + for(i=0;i +#include + +/* Swap tuning control */ + +/* First, enumerate the different reclaim policies */ +enum RCL_POLICY {RCL_ROUND_ROBIN, RCL_BUFF_FIRST, RCL_PERSIST}; + +typedef struct swap_control_v5 +{ + int sc_max_page_age; + int sc_page_advance; + int sc_page_decline; + int sc_page_initial_age; + int sc_max_buff_age; + int sc_buff_advance; + int sc_buff_decline; + int sc_buff_initial_age; + int sc_age_cluster_fract; + int sc_age_cluster_min; + int sc_pageout_weight; + int sc_bufferout_weight; + int sc_buffer_grace; + int sc_nr_buffs_to_free; + int sc_nr_pages_to_free; + enum RCL_POLICY sc_policy; +} swap_control_v5; + +typedef struct swap_control_v5 swap_control_t; + +extern swap_control_t swap_control; + +#define SC_VERSION 1 +#define SC_MAX_VERSION 1 + +#ifdef __KERNEL__ + +/* Define the maximum (least urgent) priority for the page reclaim code */ +#define RCL_MAXPRI 6 +/* We use an extra priority in the swap accounting code to represent + failure to free a resource at any priority */ +#define RCL_FAILURE (RCL_MAXPRI + 1) + +#define RCL_POLICY (swap_control.sc_policy) +#define AGE_CLUSTER_FRACT (swap_control.sc_age_cluster_fract) +#define AGE_CLUSTER_MIN (swap_control.sc_age_cluster_min) +#define PAGEOUT_WEIGHT (swap_control.sc_pageout_weight) +#define BUFFEROUT_WEIGHT (swap_control.sc_bufferout_weight) + +#define NR_BUFFS_TO_FREE (swap_control.sc_nr_buffs_to_free) +#define NR_PAGES_TO_FREE (swap_control.sc_nr_pages_to_free) + +#define BUFFERMEM_GRACE (swap_control.sc_buffer_grace) + +/* Page aging (see mm/swap.c) */ + +#define MAX_PAGE_AGE (swap_control.sc_max_page_age) +#define PAGE_ADVANCE (swap_control.sc_page_advance) +#define PAGE_DECLINE (swap_control.sc_page_decline) +#define PAGE_INITIAL_AGE (swap_control.sc_page_initial_age) + +#define MAX_BUFF_AGE (swap_control.sc_max_buff_age) +#define BUFF_ADVANCE (swap_control.sc_buff_advance) +#define BUFF_DECLINE (swap_control.sc_buff_decline) +#define BUFF_INITIAL_AGE (swap_control.sc_buff_initial_age) + +/* Given a resource of N units (pages or buffers etc), we only try to + * age and reclaim AGE_CLUSTER_FRACT per 1024 resources each time we + * scan the resource list. */ +static inline int AGE_CLUSTER_SIZE(int resources) +{ + int n = (resources * AGE_CLUSTER_FRACT) >> 10; + if (n < AGE_CLUSTER_MIN) + return AGE_CLUSTER_MIN; + else + return n; +} + +static inline void touch_page(unsigned long addr) +{ + unsigned char age = mem_map[MAP_NR(addr)].age; + if (age < (MAX_PAGE_AGE - PAGE_ADVANCE)) + age += PAGE_ADVANCE; + else + age = MAX_PAGE_AGE; + mem_map[MAP_NR(addr)].age = age; +} + +static inline void age_page(unsigned long addr) +{ + unsigned char age = mem_map[MAP_NR(addr)].age; + if (age > PAGE_DECLINE) + age -= PAGE_DECLINE; + else + age = 0; + mem_map[MAP_NR(addr)].age = age; +} + +static inline int age_of(unsigned long addr) +{ + return mem_map[MAP_NR(addr)].age; +} + +static inline void set_page_new(unsigned long addr) +{ + mem_map[MAP_NR(addr)].age = PAGE_INITIAL_AGE; +} + +#endif /* __KERNEL */ + +#endif /* _LINUX_SWAPCTL_H */ diff -u --recursive --new-file v1.3.33/linux/init/main.c linux/init/main.c --- v1.3.33/linux/init/main.c Tue Oct 10 18:46:39 1995 +++ linux/init/main.c Thu Oct 12 16:00:05 1995 @@ -46,6 +46,8 @@ extern long rd_init(long mem_start, int length); extern long pci_init(long, long); +extern void swap_setup(char *str, int *ints); +extern void buff_setup(char *str, int *ints); extern void bmouse_setup(char *str, int *ints); extern void eth_setup(char *str, int *ints); extern void xd_setup(char *str, int *ints); @@ -158,6 +160,8 @@ { "reserve=", reserve_setup }, { "profile=", profile_setup }, { "ramdisk=", ramdisk_setup }, + { "swap=", swap_setup }, + { "buff=", buff_setup }, #ifdef CONFIG_BUGi386 { "no-hlt", no_halt }, { "no387", no_387 }, @@ -560,12 +564,22 @@ return i; } -static int do_shell(void * input) +static int do_rc(void * rc) { close(0); - if (open("/etc/rc",O_RDONLY,0)) + if (open(rc,O_RDONLY,0)) return -1; - return execve("/bin/sh",argv_rc,envp_rc); + return execve("/bin/sh", argv_rc, envp_rc); +} + +static int do_shell(void * shell) +{ + close(0);close(1);close(2); + setsid(); + (void) open("/dev/tty1",O_RDWR,0); + (void) dup(0); + (void) dup(0); + return execve(shell, argv, envp); } static int init(void * unused) @@ -598,22 +612,15 @@ execve("/sbin/init",argv_init,envp_init); /* if this fails, fall through to original stuff */ - pid = kernel_thread(do_shell, "/etc/rc", 0); + pid = kernel_thread(do_rc, "/etc/rc", SIGCHLD); if (pid>0) while (pid != wait(&i)) /* nothing */; while (1) { - if ((pid = fork()) < 0) { + pid = kernel_thread(do_shell, "/bin/sh", SIGCHLD); + if (pid < 0) { printf("Fork failed in init\n\r"); continue; - } - if (!pid) { - close(0);close(1);close(2); - setsid(); - (void) open("/dev/tty1",O_RDWR,0); - (void) dup(0); - (void) dup(0); - _exit(execve("/bin/sh",argv,envp)); } while (1) if (pid == wait(&i)) diff -u --recursive --new-file v1.3.33/linux/ipc/shm.c linux/ipc/shm.c --- v1.3.33/linux/ipc/shm.c Mon Sep 25 12:26:23 1995 +++ linux/ipc/shm.c Thu Oct 12 16:00:05 1995 @@ -516,7 +516,7 @@ shmd->vm_end = addr + shp->shm_npages * PAGE_SIZE; shmd->vm_mm = current->mm; shmd->vm_page_prot = (shmflg & SHM_RDONLY) ? PAGE_READONLY : PAGE_SHARED; - shmd->vm_flags = VM_SHM | VM_MAYSHARE | VM_SHARED + shmd->vm_flags = VM_SHM | VM_MAYSHARE | VM_SHARED | VM_DONTSWAP | VM_MAYREAD | VM_MAYEXEC | VM_READ | VM_EXEC | ((shmflg & SHM_RDONLY) ? 0 : VM_MAYWRITE | VM_WRITE); shmd->vm_next_share = shmd->vm_prev_share = NULL; @@ -683,7 +683,7 @@ unsigned long id, idx; int loop = 0, invalid = 0; int counter; - + counter = shm_rss >> prio; if (!counter || !(swap_nr = get_swap_page())) return 0; diff -u --recursive --new-file v1.3.33/linux/kernel/exit.c linux/kernel/exit.c --- v1.3.33/linux/kernel/exit.c Fri Oct 6 14:35:16 1995 +++ linux/kernel/exit.c Thu Oct 12 16:00:05 1995 @@ -100,6 +100,7 @@ free_page(p->kernel_stack_page); current->cmin_flt += p->min_flt + p->cmin_flt; current->cmaj_flt += p->maj_flt + p->cmaj_flt; + current->cnswap += p->nswap + p->cnswap; kfree(p); return; } diff -u --recursive --new-file v1.3.33/linux/kernel/fork.c linux/kernel/fork.c --- v1.3.33/linux/kernel/fork.c Tue Oct 10 18:46:39 1995 +++ linux/kernel/fork.c Thu Oct 12 16:00:05 1995 @@ -125,6 +125,7 @@ tsk->mm->count = 1; tsk->min_flt = tsk->maj_flt = 0; tsk->cmin_flt = tsk->cmaj_flt = 0; + tsk->nswap = tsk->cnswap = 0; if (new_page_tables(tsk)) return -1; if (dup_mmap(tsk->mm)) { diff -u --recursive --new-file v1.3.33/linux/kernel/ksyms.c linux/kernel/ksyms.c --- v1.3.33/linux/kernel/ksyms.c Tue Oct 10 18:46:39 1995 +++ linux/kernel/ksyms.c Wed Oct 11 12:44:18 1995 @@ -74,10 +74,6 @@ extern void *sys_call_table; -#ifdef CONFIG_FTAPE -extern char * ftape_big_buffer; -#endif - #ifdef CONFIG_SCSI #include "../drivers/scsi/scsi.h" #include "../drivers/scsi/scsi_ioctl.h" @@ -154,6 +150,7 @@ X(vremap), X(vfree), X(mem_map), + X(remap_page_range), /* filesystem internal functions */ X(getname), @@ -339,10 +336,6 @@ X(unregister_netdevice_notifier), #endif -#ifdef CONFIG_FTAPE - /* The next labels are needed for ftape driver. */ - X(ftape_big_buffer), -#endif #ifdef CONFIG_INET /* support for loadable net drivers */ X(register_netdev), diff -u --recursive --new-file v1.3.33/linux/kernel/sys.c linux/kernel/sys.c --- v1.3.33/linux/kernel/sys.c Wed Oct 4 14:14:34 1995 +++ linux/kernel/sys.c Thu Oct 12 16:00:05 1995 @@ -766,6 +766,7 @@ r.ru_stime.tv_usec = CT_TO_USECS(p->stime); r.ru_minflt = p->min_flt; r.ru_majflt = p->maj_flt; + r.ru_nswap = p->nswap; break; case RUSAGE_CHILDREN: r.ru_utime.tv_sec = CT_TO_SECS(p->cutime); @@ -774,6 +775,7 @@ r.ru_stime.tv_usec = CT_TO_USECS(p->cstime); r.ru_minflt = p->cmin_flt; r.ru_majflt = p->cmaj_flt; + r.ru_nswap = p->cnswap; break; default: r.ru_utime.tv_sec = CT_TO_SECS(p->utime + p->cutime); @@ -782,6 +784,7 @@ r.ru_stime.tv_usec = CT_TO_USECS(p->stime + p->cstime); r.ru_minflt = p->min_flt + p->cmin_flt; r.ru_majflt = p->maj_flt + p->cmaj_flt; + r.ru_nswap = p->nswap + p->cnswap; break; } memcpy_tofs(ru, &r, sizeof(r)); diff -u --recursive --new-file v1.3.33/linux/mm/swap.c linux/mm/swap.c --- v1.3.33/linux/mm/swap.c Mon Sep 25 12:26:23 1995 +++ linux/mm/swap.c Thu Oct 12 16:00:05 1995 @@ -7,6 +7,8 @@ /* * This file should contain most things doing the swapping from/to disk. * Started 18.12.91 + * + * Swap aging added 23.2.95, Stephen Tweedie. */ #include @@ -19,9 +21,11 @@ #include #include #include +#include #include #include /* for cli()/sti() */ +#include /* for memcpy_to/fromfs */ #include #include @@ -32,6 +36,22 @@ int min_free_pages = 20; +/* + * Constants for the page aging mechanism: the maximum age (actually, + * the maximum "youthfulness"); the quanta by which pages rejuvinate + * and age; and the initial age for new pages. + */ + +swap_control_t swap_control = { + 20, 3, 1, 3, /* Page aging */ + 10, 2, 2, 0, /* Buffer aging */ + 32, 4, /* Aging cluster */ + 8192, 4096, /* Pageout and bufferout weights */ + -200, /* Buffer grace */ + 1, 1, /* Buffs/pages to free */ + RCL_ROUND_ROBIN /* Balancing policy */ +}; + static int nr_swapfiles = 0; static struct wait_queue * lock_queue = NULL; static struct { @@ -113,6 +133,48 @@ return (unsigned long) (swap_cache + swap_cache_size); } +/* General swap control */ + +/* Parse the kernel command line "swap=" option at load time: */ +void swap_setup(char *str, int *ints) +{ + int * swap_vars[8] = { + &MAX_PAGE_AGE, + &PAGE_ADVANCE, + &PAGE_DECLINE, + &PAGE_INITIAL_AGE, + &AGE_CLUSTER_FRACT, + &AGE_CLUSTER_MIN, + &PAGEOUT_WEIGHT, + &BUFFEROUT_WEIGHT + }; + int i; + for (i=0; i < ints[0] && i < 8; i++) { + if (ints[i+1]) + *(swap_vars[i]) = ints[i+1]; + } +} + +/* Parse the kernel command line "buff=" option at load time: */ +void buff_setup(char *str, int *ints) +{ + int * buff_vars[6] = { + &MAX_BUFF_AGE, + &BUFF_ADVANCE, + &BUFF_DECLINE, + &BUFF_INITIAL_AGE, + &BUFFEROUT_WEIGHT, + &BUFFERMEM_GRACE + }; + int i; + for (i=0; i < ints[0] && i < 6; i++) { + if (ints[i+1]) + *(buff_vars[i]) = ints[i+1]; + } +} + +/* Page aging */ + void rw_swap_page(int rw, unsigned long entry, char * buf) { unsigned long type, offset; @@ -367,12 +429,21 @@ return 0; if (page >= limit) return 0; + if (mem_map[MAP_NR(page)].reserved) return 0; - if ((pte_dirty(pte) && delete_from_swap_cache(page)) || pte_young(pte)) { + /* Deal with page aging. Pages age from being unused; they + * rejuvinate on being accessed. Only swap old pages (age==0 + * is oldest). */ + if ((pte_dirty(pte) && delete_from_swap_cache(page)) + || pte_young(pte)) { set_pte(page_table, pte_mkold(pte)); + touch_page(page); return 0; } + age_page(page); + if (age_of(page)) + return 0; if (pte_dirty(pte)) { if (vma->vm_ops && vma->vm_ops->swapout) { pid_t pid = tsk->pid; @@ -387,6 +458,7 @@ vma->vm_mm->rss--; set_pte(page_table, __pte(entry)); invalidate(); + tsk->nswap++; write_swap_page(entry, (char *) page); } free_page(page); @@ -426,19 +498,6 @@ * (C) 1993 Kai Petzke, wpp@marie.physik.tu-berlin.de */ -/* - * These are the minimum and maximum number of pages to swap from one process, - * before proceeding to the next: - */ -#define SWAP_MIN 4 -#define SWAP_MAX 32 - -/* - * The actual number of pages to swap is determined as: - * SWAP_RATIO / (number of recent major page faults) - */ -#define SWAP_RATIO 128 - static inline int swap_out_pmd(struct task_struct * tsk, struct vm_area_struct * vma, pmd_t *dir, unsigned long address, unsigned long end, unsigned long limit) { @@ -511,6 +570,11 @@ if (vma->vm_flags & VM_SHM) return 0; + /* Don't swap out areas like shared memory which have their + own separate swapping mechanism. */ + if (vma->vm_flags & VM_DONTSWAP) + return 0; + end = vma->vm_end; while (start < end) { int result = swap_out_pgd(tsk, vma, pgdir, start, end, limit); @@ -561,7 +625,7 @@ int loop, counter; struct task_struct *p; - counter = 6*nr_tasks >> priority; + counter = ((PAGEOUT_WEIGHT * nr_tasks) >> 10) >> priority; for(; counter >= 0; counter--) { /* * Check that swap_task is suitable for swapping. If not, look for @@ -588,16 +652,9 @@ * Determine the number of pages to swap from this process. */ if (!p->swap_cnt) { - p->dec_flt = (p->dec_flt * 3) / 4 + p->maj_flt - p->old_maj_flt; - p->old_maj_flt = p->maj_flt; - - if (p->dec_flt >= SWAP_RATIO / SWAP_MIN) { - p->dec_flt = SWAP_RATIO / SWAP_MIN; - p->swap_cnt = SWAP_MIN; - } else if (p->dec_flt <= SWAP_RATIO / SWAP_MAX) - p->swap_cnt = SWAP_MAX; - else - p->swap_cnt = SWAP_RATIO / p->dec_flt; + /* Normalise the number of pages swapped by + multiplying by (RSS / 1MB) */ + p->swap_cnt = AGE_CLUSTER_SIZE(p->mm->rss); } if (!--p->swap_cnt) swap_task++; @@ -616,13 +673,9 @@ } /* - * we keep on shrinking one resource until it's considered "too hard", - * and then switch to the next one (priority being an indication on how - * hard we should try with the resource). - * - * This should automatically find the resource that can most easily be - * free'd, so hopefully we'll get reasonable behaviour even under very - * different circumstances. + * We are much more aggressive about trying to swap out than we used + * to be. This works out OK, because we now do proper aging on page + * contents. */ static int try_to_free_page(int priority, unsigned long limit) { @@ -776,6 +829,7 @@ restore_flags(flags); \ addr = (struct mem_list *) (size + (unsigned long) addr); \ } mem_map[MAP_NR((unsigned long) addr)].count = 1; \ + mem_map[MAP_NR((unsigned long) addr)].age = PAGE_INITIAL_AGE; \ } while (0) unsigned long __get_free_pages(int priority, unsigned long order, unsigned long limit) diff -u --recursive --new-file v1.3.33/linux/net/ipv4/icmp.c linux/net/ipv4/icmp.c --- v1.3.33/linux/net/ipv4/icmp.c Wed Oct 4 14:14:35 1995 +++ linux/net/ipv4/icmp.c Thu Oct 12 15:42:49 1995 @@ -15,6 +15,7 @@ * * Fixes: * Mike Shaver : RFC1122 checks. + * Alan Cox : Multicast ping reply as self. * * * @@ -455,7 +456,11 @@ ip_rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_GATEWAY), ip, 0, icmph->un.gateway, dev,0, 0, 0); #endif - break; + /* + * As per RFC recommendations now handle it as + * a host redirect. + */ + case ICMP_REDIR_HOST: /* * Add better route to host. @@ -632,7 +637,7 @@ * Parse the ICMP message */ - if (daddr!=dev->pa_addr && ip_chk_addr(daddr) == IS_BROADCAST) + if (daddr!=dev->pa_addr && ip_chk_addr(daddr) != IS_MYADDR) { /* * RFC 1122: 3.2.2.6 An ICMP_ECHO to broadcast MAY be silently ignored (we don't as it is used @@ -645,6 +650,11 @@ kfree_skb(skb, FREE_READ); return(0); } + /* + * Reply the multicast/broadcast using a legal + * interface - in this case the device we got + * it from. + */ daddr=dev->pa_addr; } diff -u --recursive --new-file v1.3.33/linux/net/ipv4/ipmr.c linux/net/ipv4/ipmr.c --- v1.3.33/linux/net/ipv4/ipmr.c Tue Oct 10 18:46:39 1995 +++ linux/net/ipv4/ipmr.c Thu Oct 12 15:42:49 1995 @@ -374,6 +374,7 @@ sti(); return 0; } + sti(); return -ENOENT; } if(cache) @@ -398,16 +399,21 @@ /* * Unsolicited update - thats ok add anyway. */ - sti(); - cache=ipmr_cache_alloc(GFP_KERNEL); + + + cache=ipmr_cache_alloc(GFP_ATOMIC); if(cache==NULL) + { + sti(); return -ENOMEM; + } cache->mfc_flags=MFC_RESOLVED; cache->mfc_origin=mfc->mfcc_origin.s_addr; cache->mfc_mcastgrp=mfc->mfcc_mcastgrp.s_addr; cache->mfc_parent=mfc->mfcc_parent; memcpy(cache->mfc_ttls, mfc->mfcc_ttls,sizeof(cache->mfc_ttls)); ipmr_cache_insert(cache); + sti(); return 0; }