diff -u --recursive --new-file v1.3.57/linux/CREDITS linux/CREDITS --- v1.3.57/linux/CREDITS Sat Jan 6 19:10:37 1996 +++ linux/CREDITS Thu Jan 18 06:37:57 1996 @@ -149,7 +149,7 @@ N: Andries Brouwer E: aeb@cwi.nl -D: International character handling for keyboard and console +D: random Linux hacker S: Bessemerstraat 21 S: Amsterdam S: The Netherlands @@ -601,7 +601,7 @@ S: USA N: H.J. Lu -E: hjl@nynexst.com +E: hjl@gnu.ai.mit.edu D: GCC + libraries hacker N: Tuomas J. Lukka @@ -722,7 +722,7 @@ S: USA N: Harald Milz -E: hm@ix.de +E: hm@seneca.linux.de D: Linux Projects Map, Linux Commercial-HOWTO D: general Linux publicity in Germany, vacation port D: UUCP and CNEWS binary packages for LST @@ -894,7 +894,8 @@ S: Belgium N: Martin Schulze -E: joey@infodrom.north.de +E: joey@linux.de +W: http://home.pages.de/~joey/ D: Random Linux Hacker, Linux Promoter D: CD-List, Books-List, Ex-FAQ D: Linux-Support, -Mailbox, -Stammtisch diff -u --recursive --new-file v1.3.57/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v1.3.57/linux/Documentation/Configure.help Sun Jan 14 16:30:09 1996 +++ linux/Documentation/Configure.help Wed Jan 17 09:21:51 1996 @@ -221,7 +221,7 @@ This is for some buggy motherboards which cannot properly deal with the memory above 16MB. If you have more than 16MB of RAM and experience weird problems, you might want to try Y, everyone else - says N. Note for machines with more that 64MB of RAM: in order for the + says N. Note for machines with more than 64MB of RAM: in order for the kernel to be able to use the memory above 64MB, pass the command line option "mem=XXXM" (where XXX is the memory size in megabytes) to your kernel. See the documentation of your boot loader @@ -379,7 +379,7 @@ Kernel daemon support CONFIG_KERNELD - Normally when you have seleceted some drivers and/or filesystems + Normally when you have selected some drivers and/or filesystems to be created as loadable modules, you also have the responsibility to load the corresponding module (via insmod/modprobe) before you use it. If you select Y here, the kernel will take care of this @@ -1861,7 +1861,7 @@ ext2 filesystem; you need the software available via ftp (user: anonymous) from sunsite.unc.edu:/pub/Linux/systm/Admin/quota_acct.tar.gz in order to - use it. Obviously, this is only useful for multi user systems. If + use it. Probably this is only useful for multi user systems. If unsure, say N. Standard (minix) fs support diff -u --recursive --new-file v1.3.57/linux/Documentation/cdrom/optcd linux/Documentation/cdrom/optcd --- v1.3.57/linux/Documentation/cdrom/optcd Mon Oct 23 18:02:00 1995 +++ linux/Documentation/cdrom/optcd Thu Jan 18 06:22:13 1996 @@ -43,4 +43,8 @@ changed into #defines (you'll find them in .../include/linux/optcd.h) and include the messages generated in your bug report. Good luck. +I have inserted code to support multisession. It works for me, although +it is very slow during disk detection. At this time multisession support +is to be considered experimental. Please mail me your experiences. + Leo Spiekman (spiekman@dutette.et.tudelft.nl) diff -u --recursive --new-file v1.3.57/linux/MAGIC linux/MAGIC --- v1.3.57/linux/MAGIC Mon Dec 11 15:41:59 1995 +++ linux/MAGIC Mon Jan 15 07:59:08 1996 @@ -74,6 +74,7 @@ 0x06 linux/lp.h 0x12 linux/fs.h 0x20 linux/cm206.h +0x22 linux/scc.h 'A' linux/apm_bios.h 'C' linux/soundcard.h 'K' linux/kd.h @@ -83,7 +84,6 @@ 'S' linux/cdrom.h conflict! 'S' linux/scsi.h conflict! 'T' linux/soundcard.h conflict! -'T' linux/scc.h conflict! 'T' asm/termios.h conflict! 'V' linux/vt.h 'Y' linux/cyclades.h codes in 0x004359NN diff -u --recursive --new-file v1.3.57/linux/Makefile linux/Makefile --- v1.3.57/linux/Makefile Sun Jan 14 16:30:09 1996 +++ linux/Makefile Sun Jan 14 16:27:34 1996 @@ -1,6 +1,6 @@ VERSION = 1 PATCHLEVEL = 3 -SUBLEVEL = 57 +SUBLEVEL = 58 ARCH = i386 diff -u --recursive --new-file v1.3.57/linux/Rules.make linux/Rules.make --- v1.3.57/linux/Rules.make Sun Jan 14 16:30:09 1996 +++ linux/Rules.make Mon Jan 15 07:59:14 1996 @@ -146,7 +146,7 @@ $(SYMTAB_OBJS:.o=.ver): $(TOPDIR)/include/linux/autoconf.h -$(TOPDIR)/include/linux/modversions.h: $(join $(MODINCL)/,$(SYMTAB_OBJS:.o=.ver)) +$(TOPDIR)/include/linux/modversions.h: $(addprefix $(MODINCL)/,$(SYMTAB_OBJS:.o=.ver)) @echo updating $(TOPDIR)/include/linux/modversions.h @(echo "#ifdef MODVERSIONS";\ echo "#undef CONFIG_MODVERSIONS";\ diff -u --recursive --new-file v1.3.57/linux/arch/alpha/config.in linux/arch/alpha/config.in --- v1.3.57/linux/arch/alpha/config.in Sun Jan 14 16:30:09 1996 +++ linux/arch/alpha/config.in Sun Jan 14 16:22:16 1996 @@ -16,6 +16,7 @@ MODULES=y bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS fi +endmenu mainmenu_option next_comment comment 'General setup' @@ -57,6 +58,7 @@ bool 'Networking support' CONFIG_NET bool 'System V IPC' CONFIG_SYSVIPC tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF +endmenu source drivers/block/Config.in @@ -72,6 +74,7 @@ if [ "$CONFIG_SCSI" != "n" ]; then source drivers/scsi/Config.in fi +endmenu if [ "$CONFIG_NET" = "y" ]; then mainmenu_option next_comment @@ -81,6 +84,7 @@ if [ "$CONFIG_NETDEVICES" = "y" ]; then source drivers/net/Config.in fi + endmenu fi mainmenu_option next_comment @@ -90,6 +94,7 @@ if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then source drivers/cdrom/Config.in fi +endmenu source fs/Config.in @@ -102,6 +107,7 @@ if [ "$CONFIG_SOUND" != "n" ]; then source drivers/sound/Config.in fi +endmenu mainmenu_option next_comment comment 'Kernel hacking' @@ -111,3 +117,4 @@ if [ "$CONFIG_PROFILE" = "y" ]; then int ' Profile shift count' CONFIG_PROFILE_SHIFT 2 fi +endmenu diff -u --recursive --new-file v1.3.57/linux/arch/alpha/kernel/Makefile linux/arch/alpha/kernel/Makefile --- v1.3.57/linux/arch/alpha/kernel/Makefile Tue Dec 26 04:45:34 1995 +++ linux/arch/alpha/kernel/Makefile Mon Jan 15 09:22:57 1996 @@ -12,8 +12,11 @@ .S.o: $(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o -OBJS = entry.o traps.o process.o osf_sys.o irq.o signal.o setup.o \ - bios32.o ptrace.o time.o apecs.o lca.o +all: kernel.o head.o + +O_TARGET := kernel.o +O_OBJS := entry.o traps.o process.o osf_sys.o irq.o signal.o setup.o \ + bios32.o ptrace.o time.o apecs.o lca.o ksyms.c all: kernel.o head.o @@ -21,11 +24,5 @@ head.s: head.S $(TOPDIR)/include/asm-alpha/system.h $(CPP) -traditional -o $*.s $< - -kernel.o: $(OBJS) - $(LD) -r -o kernel.o $(OBJS) - -dep: - $(CPP) -M *.c > .depend include $(TOPDIR)/Rules.make diff -u --recursive --new-file v1.3.57/linux/arch/alpha/kernel/ksyms.c linux/arch/alpha/kernel/ksyms.c --- v1.3.57/linux/arch/alpha/kernel/ksyms.c Thu Jan 1 02:00:00 1970 +++ linux/arch/alpha/kernel/ksyms.c Thu Jan 18 10:35:20 1996 @@ -0,0 +1,55 @@ +/* + * linux/arch/alpha/kernel/ksyms.c + * + * Export the alpha-specific functions that are needed for loadable + * modules. + */ + +#include +#include +# include +# include + +extern void bcopy (const char *src, char *dst, int len); +extern struct hwrpb_struct *hwrpb; + +/* these are C runtime functions with special calling conventions: */ +extern void __divl (void); +extern void __reml (void); +extern void __divq (void); +extern void __remq (void); +extern void __divlu (void); +extern void __remlu (void); +extern void __divqu (void); +extern void __remqu (void); + +static struct symbol_table arch_symbol_table = { +#include + /* platform dependent support */ + X(_inb), + X(_inw), + X(_inl), + X(_outb), + X(_outw), + X(_outl), + X(bcopy), /* generated by gcc-2.7.0 for string assignments */ + X(hwrpb), + X(__divl), + X(__reml), + X(__divq), + X(__remq), + X(__divlu), + X(__remlu), + X(__divqu), + X(__remqu), + X(strlen), /* used by ftape */ + X(memcmp), + X(memmove), + X(__constant_c_memset), +#include +}; + +void arch_syms_export(void) +{ + register_symtab(&arch_symbol_table); +} diff -u --recursive --new-file v1.3.57/linux/arch/i386/config.in linux/arch/i386/config.in --- v1.3.57/linux/arch/i386/config.in Sun Jan 14 16:30:09 1996 +++ linux/arch/i386/config.in Sun Jan 14 16:22:16 1996 @@ -12,6 +12,7 @@ bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS bool 'Kernel daemon support (e.g. autoload of modules)' CONFIG_KERNELD fi +endmenu mainmenu_option next_comment comment 'General setup' @@ -32,6 +33,7 @@ "386 CONFIG_M386 \ 486 CONFIG_M486 \ Pentium CONFIG_M586" Pentium +endmenu source drivers/block/Config.in @@ -47,6 +49,7 @@ if [ "$CONFIG_SCSI" != "n" ]; then source drivers/scsi/Config.in fi +endmenu if [ "$CONFIG_NET" = "y" ]; then mainmenu_option next_comment @@ -56,6 +59,7 @@ if [ "$CONFIG_NETDEVICES" = "y" ]; then source drivers/net/Config.in fi + endmenu fi mainmenu_option next_comment @@ -65,6 +69,7 @@ if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then source drivers/cdrom/Config.in fi +endmenu source fs/Config.in @@ -77,6 +82,7 @@ if [ "$CONFIG_SOUND" != "n" ]; then source drivers/sound/Config.in fi +endmenu mainmenu_option next_comment comment 'Kernel hacking' @@ -86,3 +92,4 @@ if [ "$CONFIG_PROFILE" = "y" ]; then int ' Profile shift count' CONFIG_PROFILE_SHIFT 2 fi +endmenu diff -u --recursive --new-file v1.3.57/linux/arch/i386/defconfig linux/arch/i386/defconfig --- v1.3.57/linux/arch/i386/defconfig Sun Jan 14 16:30:09 1996 +++ linux/arch/i386/defconfig Mon Jan 15 08:59:59 1996 @@ -6,7 +6,7 @@ # Loadable module support # CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set +CONFIG_MODVERSIONS=y # CONFIG_KERNELD is not set # @@ -36,9 +36,9 @@ # # CONFIG_BLK_DEV_HD is not set CONFIG_BLK_DEV_IDE=y -CONFIG_BLK_DEV_IDEATAPI=y CONFIG_BLK_DEV_IDECD=y # CONFIG_BLK_DEV_IDETAPE is not set +CONFIG_BLK_DEV_CMD640=y # CONFIG_BLK_DEV_TRITON is not set # CONFIG_BLK_DEV_XD is not set diff -u --recursive --new-file v1.3.57/linux/arch/i386/kernel/Makefile linux/arch/i386/kernel/Makefile --- v1.3.57/linux/arch/i386/kernel/Makefile Fri Nov 17 08:42:24 1995 +++ linux/arch/i386/kernel/Makefile Mon Jan 15 08:09:28 1996 @@ -28,7 +28,7 @@ O_TARGET := kernel.o O_OBJS := process.o signal.o entry.o traps.o irq.o vm86.o bios32.o \ - ptrace.o ioport.o ldt.o setup.o time.o sys_i386.o + ptrace.o ioport.o ldt.o setup.o time.o sys_i386.o ksyms.o ifdef SMP diff -u --recursive --new-file v1.3.57/linux/arch/i386/kernel/ksyms.c linux/arch/i386/kernel/ksyms.c --- v1.3.57/linux/arch/i386/kernel/ksyms.c Thu Jan 1 02:00:00 1970 +++ linux/arch/i386/kernel/ksyms.c Thu Jan 18 10:34:55 1996 @@ -0,0 +1,17 @@ +#include +#include + + +static struct symbol_table arch_symbol_table = { +#include + /* platform dependent support */ +#ifdef __SMP__ + X(apic_reg), /* Needed internally for the I386 inlines */ +#endif +#include +}; + +void arch_syms_export(void) +{ + register_symtab(&arch_symbol_table); +} diff -u --recursive --new-file v1.3.57/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c --- v1.3.57/linux/arch/i386/kernel/setup.c Tue Dec 26 04:45:35 1995 +++ linux/arch/i386/kernel/setup.c Wed Jan 17 07:32:08 1996 @@ -196,7 +196,7 @@ static const char * i586model(unsigned int nr) { static const char *model[] = { - "0", "Pentium 60/66","Pentium 75+" + "0", "Pentium 60/66","Pentium 75+","OverDrive PODP5V83" }; if (nr < sizeof(model)/sizeof(char *)) return model[nr]; diff -u --recursive --new-file v1.3.57/linux/arch/mips/config.in linux/arch/mips/config.in --- v1.3.57/linux/arch/mips/config.in Sun Jan 14 16:30:10 1996 +++ linux/arch/mips/config.in Sun Jan 14 16:22:16 1996 @@ -47,10 +47,12 @@ # bool ' PCI bridge optimization (experimental)' CONFIG_PCI_OPTIMIZE #fi bool 'System V IPC' CONFIG_SYSVIPC +endmenu mainmenu_option next_comment comment 'Loadable module support' bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS +endmenu source drivers/block/Config.in @@ -66,6 +68,7 @@ if [ "$CONFIG_SCSI" != "n" ]; then source drivers/scsi/Config.in fi +endmenu if [ "$CONFIG_NET" = "y" ]; then mainmenu_option next_comment @@ -75,6 +78,7 @@ if [ "$CONFIG_NETDEVICES" = "y" ]; then source drivers/net/Config.in fi + endmenu fi mainmenu_option next_comment @@ -84,6 +88,7 @@ if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then source drivers/cdrom/Config.in fi +endmenu source fs/Config.in @@ -97,6 +102,7 @@ if [ "$CONFIG_SOUND" != "n" ]; then source drivers/sound/Config.in fi +endmenu mainmenu_option next_comment comment 'Kernel hacking' @@ -106,3 +112,4 @@ if [ "$CONFIG_PROFILE" = "y" ]; then int ' Profile shift count' CONFIG_PROFILE_SHIFT 2 fi +endmenu diff -u --recursive --new-file v1.3.57/linux/arch/sparc/config.in linux/arch/sparc/config.in --- v1.3.57/linux/arch/sparc/config.in Sat Nov 25 19:04:36 1995 +++ linux/arch/sparc/config.in Sun Jan 14 16:22:16 1996 @@ -17,6 +17,7 @@ bool 'Networking support' CONFIG_NET bool 'System V IPC' CONFIG_SYSVIPC tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF +endmenu source drivers/block/Config.in @@ -32,6 +33,7 @@ if [ "$CONFIG_SCSI" != "n" ]; then source drivers/scsi/Config.in fi +endmenu if [ "$CONFIG_NET" = "y" ]; then mainmenu_option next_comment @@ -41,6 +43,7 @@ if [ "$CONFIG_NETDEVICES" = "y" ]; then source drivers/net/Config.in fi + endmenu fi source fs/Config.in diff -u --recursive --new-file v1.3.57/linux/drivers/block/Config.in linux/drivers/block/Config.in --- v1.3.57/linux/drivers/block/Config.in Tue Jan 2 16:46:24 1996 +++ linux/drivers/block/Config.in Sun Jan 14 16:22:16 1996 @@ -16,11 +16,9 @@ bool ' Use new IDE driver for primary/secondary i/f' CONFIG_BLK_DEV_IDE fi if [ "$CONFIG_BLK_DEV_IDE" = "y" ]; then - bool ' Include support for IDE/ATAPI CDROM or TAPE' CONFIG_BLK_DEV_IDEATAPI - if [ "$CONFIG_BLK_DEV_IDEATAPI" = "y" ]; then - bool ' Include support for IDE/ATAPI CDROM' CONFIG_BLK_DEV_IDECD - bool ' Include ALPHA support for IDE/ATAPI TAPE' CONFIG_BLK_DEV_IDETAPE - fi + bool ' Include IDE/ATAPI CDROM support' CONFIG_BLK_DEV_IDECD + bool ' Include (ALPHA) IDE/ATAPI TAPE support' CONFIG_BLK_DEV_IDETAPE + bool ' Special CMD640 chipset support' CONFIG_BLK_DEV_CMD640 if [ "$CONFIG_PCI" = "y" ]; then bool ' PCI Triton IDE Bus Master DMA support' CONFIG_BLK_DEV_TRITON fi @@ -28,3 +26,4 @@ fi bool 'XT harddisk support' CONFIG_BLK_DEV_XD +endmenu diff -u --recursive --new-file v1.3.57/linux/drivers/block/Makefile linux/drivers/block/Makefile --- v1.3.57/linux/drivers/block/Makefile Tue Jan 2 16:46:24 1996 +++ linux/drivers/block/Makefile Sun Jan 14 16:22:14 1996 @@ -48,6 +48,10 @@ L_OBJS += triton.o endif +ifeq ($(CONFIG_BLK_DEV_CMD640),y) +L_OBJS += cmd640.o +endif + ifeq ($(CONFIG_BLK_DEV_IDECD),y) L_OBJS += ide-cd.o endif diff -u --recursive --new-file v1.3.57/linux/drivers/block/README.ide linux/drivers/block/README.ide --- v1.3.57/linux/drivers/block/README.ide Thu Jan 4 21:54:53 1996 +++ linux/drivers/block/README.ide Sun Jan 14 16:22:14 1996 @@ -350,13 +350,19 @@ as in: hda=525,64,63 If the BIOS does not support this form of drive translation, then several -options remain, listed below in inverse order of popularity: +options remain, listed below in order of popularity: - - boot from a floppy disk instead of the hard drive (takes 10 seconds). - use a partition below the 1024 cyl boundary to hold the linux boot files (kernel images and /boot directory), and place the rest of linux anywhere else on the drive. These files can reside in a DOS partition, or in a tailor-made linux boot partition. + - use DiskManager software from OnTrack, supplied free with + many new hard drive purchases. + - use EZ-Drive software (similar to DiskManager). Note though, + that LILO must *not* use the MBR when EZ-Drive is present. + Instead, install LILO on the first sector of your linux partition, + and mark it as "active" or "bootable" with fdisk. + - boot from a floppy disk instead of the hard drive (takes 10 seconds). If you cannot use drive translation, *and* your BIOS also restricts you to entering no more than 1024 cylinders in the geometry field in the CMOS setup, diff -u --recursive --new-file v1.3.57/linux/drivers/block/cmd640.c linux/drivers/block/cmd640.c --- v1.3.57/linux/drivers/block/cmd640.c Sun Dec 17 11:43:12 1995 +++ linux/drivers/block/cmd640.c Sun Jan 14 16:41:39 1996 @@ -1,7 +1,7 @@ /* - * linux/drivers/block/cmd640.c Version 0.02 Nov 30, 1995 + * linux/drivers/block/cmd640.c Version 0.04 Jan 11, 1996 * - * Copyright (C) 1995 Linus Torvalds & author (see below) + * Copyright (C) 1995-1996 Linus Torvalds & author (see below) */ /* @@ -18,8 +18,49 @@ * read-ahead for versions 'B' and 'C' of chip by * default, some code cleanup. * + * Version 0.03 Added reset of secondary interface, + * and black list for devices which are not compatible + * with read ahead mode. Separate function for setting + * readahead is added, possibly it will be called some + * day from ioctl processing code. + * + * Version 0.04 Now configs/compiles separate from ide.c -ml + */ + +/* + * There is a known problem with current version of this driver. + * If the only device on secondary interface is CD-ROM, at some + * computers it is not recognized. In all reported cases CD-ROM + * was 2x or 4x speed Mitsumi drive. + * + * The following workarounds could work: + * + * 1. put CD-ROM as slave on primary interface + * + * 2. or define symbol at next line as 0 + * */ +#define CMD640_NORMAL_INIT 1 + +#undef REALLY_SLOW_IO /* most systems can safely undef this */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ide.h" + +extern ide_hwif_t ide_hwifs[]; + +int cmd640_vlb = 0; + /* * CMD640 specific registers definition. */ @@ -76,7 +117,7 @@ /* * For some unknown reasons pcibios functions which read and write registers - * do not work with cmd640. We use direct io instead. + * do not always work with cmd640. We use direct io instead. */ /* PCI method 1 access */ @@ -230,6 +271,35 @@ } /* + * Low level reset for controller, actually it has nothing specific for + * CMD640, but I don't know how to use standard reset routine before + * we recognized any drives. + */ + +static void cmd640_reset_controller(int iface_no) +{ + int retry_count = 600; + int base_port = iface_no ? 0x170 : 0x1f0; + + outb_p(4, base_port + 7); + udelay(5); + outb_p(0, base_port + 7); + + do { + udelay(5); + retry_count -= 1; + } while ((inb_p(base_port + 7) & 0x80) && retry_count); + + if (retry_count == 0) + printk("cmd640: failed to reset controller %d\n", iface_no); +#if 0 + else + printk("cmd640: controller %d reset [%d]\n", + iface_no, retry_count); +#endif +} + +/* * Probe for Cmd640x and initialize it if found */ @@ -282,31 +352,34 @@ /* * Set the maximum allowed bus speed (it is safest until we - * find how detect bus speed) + * find how to detect bus speed) * Normally PCI bus runs at 33MHz, but often works overclocked to 40 */ bus_speed = (bus_type == vlb) ? 50 : 40; -#if 1 /* don't know if this is reliable yet */ /* * Enable readahead for versions above 'A' */ cmd_read_ahead = (cmd640_chip_version > 1); -#else - cmd_read_ahead = 0; -#endif + /* * Setup Control Register */ b = get_cmd640_reg(cmd640_key, CNTRL); + +#if CMD640_NORMAL_INIT if (second_port) b |= CNTRL_ENA_2ND; else b &= ~CNTRL_ENA_2ND; +#endif + if (cmd_read_ahead) b &= ~(CNTRL_DIS_RA0 | CNTRL_DIS_RA1); else b |= (CNTRL_DIS_RA0 | CNTRL_DIS_RA1); + + put_cmd640_reg(cmd640_key, CNTRL, b); /* @@ -317,9 +390,11 @@ b = cmd_read_ahead ? 0 : (DIS_RA2 | DIS_RA3); put_cmd640_reg(cmd640_key, ARTTIM23, b); put_cmd640_reg(cmd640_key, DRWTIM23, 0); + + cmd640_reset_controller(1); } - serialized = 1; + ide_hwifs[0].serialized = 1; printk("ide: buggy CMD640%c interface at ", 'A' - 1 + cmd640_chip_version); @@ -360,6 +435,48 @@ } /* + * Sets readahead mode for specific drive + * in the future it could be called from ioctl + */ + +static void set_readahead_mode(int mode, int if_num, int dr_num) +{ + static int masks[2][2] = + { + {CNTRL_DIS_RA0, CNTRL_DIS_RA1}, + {DIS_RA2, DIS_RA3} + }; + + int port = (if_num == 0) ? CNTRL : ARTTIM23; + int mask = masks[if_num][dr_num]; + byte b; + + b = get_cmd640_reg(cmd640_key, port); + if (mode) + b &= mask; /* Enable readahead for specific drive */ + else + b |= mask; /* Disable readahed for specific drive */ + put_cmd640_reg(cmd640_key, port, b); +} + +static struct readahead_black_list { + const char* name; + int mode; +} drives_ra[] = { + { "ST3655A", 0 }, + { NULL, 0 } +}; + +static int known_drive_readahead(char* name) { + int i; + + for (i = 0; drives_ra[i].name != NULL; i++) + if (strcmp(name, drives_ra[i].name) == 0) + return drives_ra[i].mode; + return -1; +} + +/* * Tuning of drive parameters */ @@ -400,7 +517,7 @@ } } -struct pio_timing { +static struct pio_timing { int mc_time; /* Minimal cycle time (ns) */ int av_time; /* Address valid to DIOR-/DIOW- setup (ns) */ int ds_time; /* DIOR data setup (ns) */ @@ -413,7 +530,7 @@ { 20, 50, 100 } /* PIO Mode ? */ }; -struct drive_pio_info { +static struct drive_pio_info { const char *name; int pio; } drive_pios[] = { @@ -426,6 +543,7 @@ { "QUANTUM LPS240A", 0 }, { "QUANTUM LPS270A", 3 }, { "QUANTUM LPS540A", 3 }, + { "QUANTUM FIREBALL1080A", 3 }, { NULL, 0 } }; @@ -480,7 +598,7 @@ outb_p((drv_num | 0xa) << 4, p_base + 6); outb_p(0xef, p_base + 7); for (i = 0; (i < 100) && (inb (p_base + 7) & 0x80); i++) - delay_10ms(); + udelay(10000); } void cmd640_tune_drive(ide_drive_t* drive) { @@ -491,6 +609,7 @@ int mc_time, av_time, ds_time; struct hd_driveid* id; int r1, r2; + int mode; /* * Determine if drive is under cmd640 control @@ -530,6 +649,13 @@ &r1, &r2); set_pio_mode(interface_number, drive_number, max_pio); cmd640_set_timing(interface_number, drive_number, r1, r2); + + /* + * Disable (or set) readahead mode for known drive + */ + if ((mode = known_drive_readahead(id->model)) != -1) { + set_readahead_mode(mode, interface_number, drive_number); + printk("Readahead %s,", mode ? "enabled" : "disabled"); + } printk ("Mode and Timing set to PIO%d (0x%x 0x%x)\n", max_pio, r1, r2); } - diff -u --recursive --new-file v1.3.57/linux/drivers/block/ide-cd.c linux/drivers/block/ide-cd.c --- v1.3.57/linux/drivers/block/ide-cd.c Sat Dec 30 15:50:53 1995 +++ linux/drivers/block/ide-cd.c Sun Jan 14 16:22:15 1996 @@ -108,7 +108,6 @@ #include #include -#define _IDE_CD_C /* used in blk.h */ #include "ide.h" diff -u --recursive --new-file v1.3.57/linux/drivers/block/ide-tape.c linux/drivers/block/ide-tape.c --- v1.3.57/linux/drivers/block/ide-tape.c Thu Jan 4 21:54:54 1996 +++ linux/drivers/block/ide-tape.c Sun Jan 14 16:22:15 1996 @@ -300,8 +300,6 @@ #include #include -#define _IDE_TAPE_C /* For ide_end_request in blk.h */ - /* * Main Linux ide driver include file * diff -u --recursive --new-file v1.3.57/linux/drivers/block/ide.c linux/drivers/block/ide.c --- v1.3.57/linux/drivers/block/ide.c Thu Jan 4 21:54:54 1996 +++ linux/drivers/block/ide.c Sun Jan 14 16:22:15 1996 @@ -1,8 +1,9 @@ /* - * linux/drivers/block/ide.c Version 5.24 Jan 4, 1996 + * linux/drivers/block/ide.c Version 5.25 Jan 11, 1996 * * Copyright (C) 1994-1996 Linus Torvalds & authors (see below) */ +#define _IDE_C /* needed by */ /* * This is the multiple IDE interface driver, as evolved from hd.c. @@ -109,7 +110,7 @@ * assembly syntax tweak to vlb_sync * removeable drive support from scuba@cs.tu-berlin.de * add transparent support for DiskManager-6.0x "Dynamic - * Disk Overlay" (DDO), most of this in in genhd.c + * Disk Overlay" (DDO), most of this is in genhd.c * eliminate "multiple mode turned off" message at boot * Version 4.10 fix bug in ioctl for "hdparm -c3" * fix DM6:DDO support -- now works with LILO, fdisk, ... @@ -180,11 +181,13 @@ * Version 5.22 fix ide_xlate_1024() to work with/without drive->id * Version 5.23 miscellaneous touch-ups * Version 5.24 fix #if's for SUPPORT_CMD640 + * Version 5.25 more touch-ups, fix cdrom resets, ... + * cmd640.c now configs/compiles separate from ide.c * * Driver compile-time options are in ide.h * * To do, in likely order of completion: - * - make cmd640.c and umc8672.c compile separately from ide.c + * - make umc8672.c compile separately from ide.c * - add ALI M1443/1445 chipset support from derekn@vw.ece.cmu.edu * - add ioctls to get/set interface timings on various interfaces * - add Promise Caching controller support from peterd@pnd-pc.demon.co.uk @@ -222,18 +225,12 @@ #include "ide.h" -#if SUPPORT_CMD640 -void cmd640_tune_drive(ide_drive_t *); -static int cmd640_vlb = 0; -#endif - ide_hwif_t ide_hwifs[MAX_HWIFS]; /* hwif info */ static ide_hwgroup_t *irq_to_hwgroup [16]; static const byte ide_hwif_to_major[MAX_HWIFS] = {IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR}; static const unsigned short default_io_base[MAX_HWIFS] = {0x1f0, 0x170, 0x1e8, 0x168}; static const byte default_irqs[MAX_HWIFS] = {14, 15, 11, 10}; -static int serialized = 0; /* "serialize" option */ static int disallow_unmask = 0; /* for buggy hardware */ #if (DISK_RECOVERY_TIME > 0) @@ -881,7 +878,8 @@ err = ide_dump_status(drive, msg, stat); if ((rq = HWGROUP(drive)->rq) == NULL || drive == NULL) return; - if (rq->cmd != READ && rq->cmd != WRITE) { /* retry only "normal" i/o */ + /* retry only "normal" I/O: */ + if (rq->cmd != READ && rq->cmd != WRITE && drive->media != ide_cdrom) { rq->errors = 1; ide_end_drive_cmd(drive, stat, err); return; @@ -1346,7 +1344,7 @@ #if FAKE_FDISK_FOR_EZDRIVE if (block == 0 && drive->ezdrive) { block = 1; - printk("%s: [EZD] accessing sector 1 instead of sector 0\n", drive->name); + printk("%s: [EZD] accessing sector 1 in place of sector 0\n", drive->name); } #endif /* FAKE_FDISK_FOR_EZDRIVE */ ((ide_hwgroup_t *)hwif->hwgroup)->drive = drive; @@ -2210,8 +2208,11 @@ printk(", DMA"); } printk("\n"); -#if SUPPORT_CMD640 - cmd640_tune_drive(drive); /* but can we tune a fish? */ +#ifdef CONFIG_BLK_DEV_CMD640 + { + extern void cmd640_tune_drive (ide_drive_t *); + cmd640_tune_drive(drive); /* but can we tune a fish? */ + } #endif } @@ -2527,10 +2528,6 @@ #include "umc8672.c" /* until we tidy up the interface some more */ #endif -#if SUPPORT_CMD640 -#include "cmd640.c" /* until we tidy up the interface some more */ -#endif - /* * stridx() returns the offset of c within s, * or -1 if c is '\0' or not found within s. @@ -2699,12 +2696,15 @@ init_qd6580(); goto done; #endif /* SUPPORT_QD6580 */ -#if SUPPORT_CMD640 +#ifdef CONFIG_BLK_DEV_CMD640 case -5: /* "cmd640_vlb" */ + { + extern int cmd640_vlb; if (hw > 1) goto bad_hwif; - cmd640_vlb = 1; + cmd640_vlb = 1; + } break; -#endif /* SUPPORT_CMD640 */ +#endif /* CONFIG_BLK_DEV_CMD640 */ #if SUPPORT_HT6560B case -4: /* "ht6560b" */ if (hw > 1) goto bad_hwif; @@ -2736,7 +2736,7 @@ case -2: /* "serialize" */ do_serialize: if (hw > 1) goto bad_hwif; - serialized = 1; + ide_hwifs[0].serialized = 1; goto done; case -1: /* "noprobe" */ hwif->noprobe = 1; @@ -2890,7 +2890,7 @@ * Check for serialization with ide1. * This code depends on us having already taken care of ide1. */ - if (serialized && hwif->name[3] == '0' && ide_hwifs[1].present) + if (hwif->serialized && hwif->name[3] == '0' && ide_hwifs[1].present) hwgroup = ide_hwifs[1].hwgroup; /* * If this is the first interface in a group, @@ -2941,23 +2941,14 @@ #ifdef CONFIG_PCI -void ide_pci_access_error (int rc) -{ - printk("ide: pcibios access failed - %s\n", pcibios_strerror(rc)); -} +#if SUPPORT_RZ1000 -#if SUPPORT_RZ1000 || SUPPORT_CMD640 -void buggy_interface_fallback (int rc) +static void ide_pci_access_error (int rc) { - ide_pci_access_error (rc); - serialized = 1; - disallow_unmask = 1; - printk("serialized, disabled unmasking\n"); + printk("ide: pcibios access failed - %s\n", pcibios_strerror(rc)); } -#endif /* SUPPORT_RZ1000 || SUPPORT_CMD640 */ -#if SUPPORT_RZ1000 -void init_rz1000 (byte bus, byte fn) +static void init_rz1000 (byte bus, byte fn) { int rc; unsigned short reg; @@ -2970,8 +2961,12 @@ } else { if ((rc = pcibios_read_config_word(bus, fn, 0x40, ®)) || (rc = pcibios_write_config_word(bus, fn, 0x40, reg & 0xdfff))) - buggy_interface_fallback (rc); - else + { + ide_pci_access_error (rc); + ide_hwifs[0].serialized = 1; + disallow_unmask = 1; + printk("serialized, disabled unmasking\n"); + } else printk("disabled read-ahead\n"); } } @@ -3012,7 +3007,7 @@ /* * Apparently the BIOS32 services on Intel motherboards are buggy, * and won't find the PCI_DEVICE_ID_INTEL_82371_1 for us. - * So we instead search for PCI_DEVICE_ID_INTEL_82371_0, and then add 1. + * So instead, we search for PCI_DEVICE_ID_INTEL_82371_0, and then add 1. */ ide_probe_pci (PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371_0, &ide_init_triton, 1); #endif @@ -3038,8 +3033,11 @@ if (pcibios_present()) ide_init_pci (); #endif /* CONFIG_PCI */ -#if SUPPORT_CMD640 - ide_probe_for_cmd640x(); +#ifdef CONFIG_BLK_DEV_CMD640 + { + extern void ide_probe_for_cmd640x (void); + ide_probe_for_cmd640x(); + } #endif /* diff -u --recursive --new-file v1.3.57/linux/drivers/block/ide.h linux/drivers/block/ide.h --- v1.3.57/linux/drivers/block/ide.h Thu Jan 4 21:54:54 1996 +++ linux/drivers/block/ide.h Thu Jan 18 10:17:35 1996 @@ -37,9 +37,6 @@ #ifndef SUPPORT_RZ1000 /* 1 to support RZ1000 chipset */ #define SUPPORT_RZ1000 1 /* 0 to reduce kernel size */ #endif -#ifndef SUPPORT_CMD640 /* 1 to support CMD640 chipset */ -#define SUPPORT_CMD640 1 /* 0 to reduce kernel size */ -#endif #ifndef SUPPORT_UMC8672 /* 1 to support UMC8672 chipset */ #define SUPPORT_UMC8672 1 /* 0 to reduce kernel size */ #endif @@ -59,6 +56,10 @@ #define FANCY_STATUS_DUMPS 1 /* 0 to reduce kernel size */ #endif +#if defined(CONFIG_BLK_DEV_IDECD) || defined(CONFIG_BLK_DEV_IDETAPE) +#define CONFIG_BLK_DEV_IDEATAPI 1 +#endif + /* * IDE_DRIVE_CMD is used to implement many features of the hdparm utility */ @@ -393,6 +394,7 @@ char name[5]; /* name of interface, eg. "ide0" */ unsigned noprobe : 1; /* don't probe for this interface */ unsigned present : 1; /* this interface exists */ + unsigned serialized : 1; /* valid only for ide_hwifs[0] */ #if (DISK_RECOVERY_TIME > 0) unsigned long last_time; /* time when previous rq was done */ #endif @@ -603,4 +605,3 @@ #ifdef CONFIG_BLK_DEV_TRITON void ide_init_triton (byte, byte); #endif /* CONFIG_BLK_DEV_TRITON */ - diff -u --recursive --new-file v1.3.57/linux/drivers/block/triton.c linux/drivers/block/triton.c --- v1.3.57/linux/drivers/block/triton.c Sun Dec 17 11:43:13 1995 +++ linux/drivers/block/triton.c Sun Jan 14 16:42:13 1996 @@ -1,7 +1,7 @@ /* - * linux/drivers/block/triton.c Version 1.04 Dec 1, 1995 + * linux/drivers/block/triton.c Version 1.05 Jan 11, 1996 * - * Copyright (c) 1995 Mark Lord + * Copyright (c) 1995-1996 Mark Lord * May be copied or modified under the terms of the GNU General Public License */ @@ -95,11 +95,6 @@ * * And, yes, Intel Zappa boards really *do* use the Triton IDE ports. */ -#define _TRITON_C -#include -#ifndef CONFIG_BLK_DEV_TRITON -#define CONFIG_BLK_DEV_TRITON y -#endif #include #include #include @@ -127,15 +122,15 @@ * Our Physical Region Descriptor (PRD) table should be large enough * to handle the biggest I/O request we are likely to see. Since requests * can have no more than 256 sectors, and since the typical blocksize is - * two sectors, we can get by with a limit of 128 entries here for the + * two sectors, we could get by with a limit of 128 entries here for the * usual worst case. Most requests seem to include some contiguous blocks, * further reducing the number of table entries required. * - * Note that the driver reverts to PIO mode for individual requests that exceed + * The driver reverts to PIO mode for individual requests that exceed * this limit (possible with 512 byte blocksizes, eg. MSDOS f/s), so handling * 100% of all crazy scenarios here is not necessary. * - * As it turns out, though, we must allocate a full 4KB page for this, + * As it turns out though, we must allocate a full 4KB page for this, * so the two PRD tables (ide0 & ide1) will each get half of that, * allowing each to have about 256 entries (8 bytes each) from this. */ @@ -288,7 +283,7 @@ outl(virt_to_bus (HWIF(drive)->dmatable), dma_base + 4); /* PRD table */ outb(reading, dma_base); /* specify r/w */ outb(0x26, dma_base+2); /* clear status bits */ - ide_set_handler (drive, &dma_intr, WAIT_CMD); /* issue cmd to drive */ + ide_set_handler(drive, &dma_intr, WAIT_CMD); /* issue cmd to drive */ OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); outb(inb(dma_base)|1, dma_base); /* begin DMA */ return 0; @@ -316,6 +311,48 @@ printk(" fastPIO=%s\n", ((flags&9)==1) ? "on " : "off"); } +static void init_triton_dma (ide_hwif_t *hwif, unsigned short base) +{ + static unsigned long dmatable = 0; + + printk(" %s: BusMaster DMA at 0x%04x-0x%04x", hwif->name, base, base+7); + if (check_region(base, 8)) { + printk(" -- ERROR, PORTS ALREADY IN USE"); + } else { + request_region(base, 8, hwif->name); + hwif->dma_base = base; + if (!dmatable) { + /* + * Since we know we are on a PCI bus, we could + * actually use __get_free_pages() here instead + * of __get_dma_pages() -- no ISA limitations. + */ + dmatable = __get_dma_pages(GFP_KERNEL, 0); + } + if (dmatable) { + hwif->dmatable = (unsigned long *) dmatable; + dmatable += (PRD_ENTRIES * PRD_BYTES); + outl(virt_to_bus(hwif->dmatable), base + 4); + hwif->dmaproc = &triton_dmaproc; + } + } + printk("\n"); +} + +/* + * calc_mode() returns the ATA PIO mode number, based on the number + * of cycle clks passed in. Assumes 33Mhz bus operation (30ns per clk). + */ +byte calc_mode (byte clks) +{ + if (clks == 3) return 5; + if (clks == 4) return 4; + if (clks < 6) return 3; + if (clks < 8) return 2; + if (clks < 13) return 1; + return 0; +} + /* * ide_init_triton() prepares the IDE driver for DMA operation. * This routine is called once, from ide.c during driver initialization, @@ -324,26 +361,33 @@ void ide_init_triton (byte bus, byte fn) { int rc = 0, h; + int dma_enabled = 0; unsigned short bmiba, pcicmd; unsigned int timings; - unsigned long dmatable = 0; extern ide_hwif_t ide_hwifs[]; + printk("ide: Triton BM-IDE on PCI bus %d function %d\n", bus, fn); /* * See if IDE and BM-DMA features are enabled: */ if ((rc = pcibios_read_config_word(bus, fn, 0x04, &pcicmd))) goto quit; - if ((pcicmd & 5) != 5) { - if ((pcicmd & 1) == 0) - printk("ide: Triton IDE ports are not enabled\n"); - else - printk("ide: Triton BM-DMA feature is not enabled\n"); + if ((pcicmd & 1) == 0) { + printk("ide: Triton IDE ports are not enabled\n"); goto quit; } -#if 0 - (void) pcibios_write_config_word(bus, fn, 0x42, 0x8037); /* for my MC2112A */ -#endif + if ((pcicmd & 4) == 0) { + printk("ide: Triton BM-DMA feature is not enabled -- upgrade your BIOS\n"); + } else { + /* + * Get the bmiba base address + */ + if ((rc = pcibios_read_config_word(bus, fn, 0x20, &bmiba))) + goto quit; + bmiba &= 0xfff0; /* extract port base address */ + dma_enabled = 1; + } + /* * See if ide port(s) are enabled */ @@ -353,52 +397,32 @@ printk("ide: neither Triton IDE port is enabled\n"); goto quit; } - printk("ide: Triton BM-IDE on PCI bus %d function %d\n", bus, fn); - - /* - * Get the bmiba base address - */ - if ((rc = pcibios_read_config_word(bus, fn, 0x20, &bmiba))) - goto quit; - bmiba &= 0xfff0; /* extract port base address */ /* * Save the dma_base port addr for each interface */ for (h = 0; h < MAX_HWIFS; ++h) { + byte s_clks, r_clks; ide_hwif_t *hwif = &ide_hwifs[h]; - unsigned short base, time; - if (hwif->io_base == 0x1f0 && (timings & 0x8000)) { + unsigned short time; + if (hwif->io_base == 0x1f0) { time = timings & 0xffff; - base = bmiba; - } else if (hwif->io_base == 0x170 && (timings & 0x80000000)) { + if ((timings & 0x8000) == 0) /* interface enabled? */ + continue; + if (dma_enabled) + init_triton_dma(hwif, bmiba); + } else if (hwif->io_base == 0x170) { time = timings >> 16; - base = bmiba + 8; + if ((timings & 0x8000) == 0) /* interface enabled? */ + continue; + if (dma_enabled) + init_triton_dma(hwif, bmiba + 8); } else continue; - printk(" %s: BusMaster DMA at 0x%04x-0x%04x", hwif->name, base, base+7); - if (check_region(base, 8)) { - printk(" -- ERROR, PORTS ALREADY IN USE"); - } else { - request_region(base, 8, hwif->name); - hwif->dma_base = base; - if (!dmatable) { - /* - * Since we know we are on a PCI bus, we could - * actually use __get_free_pages() here instead - * of __get_dma_pages() -- no ISA limitations. - */ - dmatable = __get_dma_pages(GFP_KERNEL, 0); - } - if (dmatable) { - hwif->dmatable = (unsigned long *) dmatable; - dmatable += (PRD_ENTRIES * PRD_BYTES); - outl(virt_to_bus(hwif->dmatable), base + 4); - hwif->dmaproc = &triton_dmaproc; - } - } - printk("\n %s timing: (0x%04x) sample_CLKs=%d, recovery_CLKs=%d\n", - hwif->name, time, ((~time>>12)&3)+2, ((~time>>8)&3)+1); + s_clks = ((~time >> 12) & 3) + 2; + r_clks = ((~time >> 8) & 3) + 1; + printk(" %s timing: (0x%04x) sample_CLKs=%d, recovery_CLKs=%d (PIO mode%d)\n", + hwif->name, time, s_clks, r_clks, calc_mode(s_clks+r_clks)); print_triton_drive_flags (0, time & 0xf); print_triton_drive_flags (1, (time >> 4) & 0xf); } diff -u --recursive --new-file v1.3.57/linux/drivers/cdrom/mcdx.c linux/drivers/cdrom/mcdx.c --- v1.3.57/linux/drivers/cdrom/mcdx.c Tue Nov 21 13:22:08 1995 +++ linux/drivers/cdrom/mcdx.c Sun Jan 14 16:22:16 1996 @@ -1,7 +1,7 @@ /* * The Mitsumi CDROM interface * Copyright (C) 1995 Heiko Schlittermann - * VERSION: 1.5 + * VERSION: 1.5a * * 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 @@ -34,7 +34,7 @@ #if RCS static const char *mcdx_c_version - = "mcdx.c,v 1.19 1995/11/20 17:06:25 heiko Exp"; + = "mcdx.c,v 1.19.2.1 1996/01/13 21:25:55 heiko Exp"; #endif #include @@ -768,8 +768,10 @@ /* invalidate_inodes(ip->i_rdev); */ invalidate_buffers(ip->i_rdev); +#if !MCDX_QUIET if (-1 == mcdx_lockdoor(stuffp, 0, 3)) INFO(("close() Cannot unlock the door\n")); +#endif /* eject if wished */ if (stuffp->eject_sw) mcdx_eject(stuffp, 1); @@ -794,10 +796,8 @@ void mcdx_setup(char *str, int *pi) { -#if MCDX_DEBUG - printk(MCDX ":: setup(%s, %d) called\n", - str, pi[0]); -#endif + if (pi[0] > 0) mcdx_drive_map[0][0] = pi[1]; + if (pi[0] > 1) mcdx_drive_map[0][1] = pi[2]; } /* DIRTY PART ******************************************************/ @@ -1051,10 +1051,10 @@ { int drive; - WARN(("Version 1.5 " - "mcdx.c,v 1.19 1995/11/20 17:06:25 heiko Exp\n")); - INFO((": Version 1.5 " - "mcdx.c,v 1.19 1995/11/20 17:06:25 heiko Exp\n")); + WARN(("Version 1.5a " + "mcdx.c,v 1.19.2.1 1996/01/13 21:25:55 heiko Exp\n")); + INFO((": Version 1.5a " + "mcdx.c,v 1.19.2.1 1996/01/13 21:25:55 heiko Exp\n")); /* zero the pointer array */ for (drive = 0; drive < MCDX_NDRIVES; drive++) @@ -1245,7 +1245,7 @@ stuffp->lock = current->pid; do { - int sig = 0; + /* int sig = 0; */ int to = 0; /* wait for the drive become idle */ diff -u --recursive --new-file v1.3.57/linux/drivers/cdrom/optcd.c linux/drivers/cdrom/optcd.c --- v1.3.57/linux/drivers/cdrom/optcd.c Mon Nov 27 12:48:29 1995 +++ linux/drivers/cdrom/optcd.c Thu Jan 18 06:22:13 1996 @@ -1,12 +1,13 @@ -/* $Id: optcd.c,v 1.3 1995/08/24 19:54:27 root Exp root $ - linux/drivers/block/optcd.c - Optics Storage 8000 AT CDROM driver +/* linux/drivers/cdrom/optcd.c - Optics Storage 8000 AT CDROM driver + $Id: optcd.c,v 1.20 1996/01/17 19:44:39 root Exp root $ Copyright (C) 1995 Leo Spiekman (spiekman@dutette.et.tudelft.nl) + Based on Aztech CD268 CDROM driver by Werner Zimmermann and preworks by Eberhard Moenkeberg (emoenke@gwdg.de). ISP16 detection and - configuration by Eric van der Maarel (maarel@marin.nl), with some data - communicated by Vadim V. Model (vadim@rbrf.msk.su). + configuration by Eric van der Maarel (maarel@marin.nl) and + Vadim Model (vadim@cecmow.enet.dec.com). 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 @@ -21,8 +22,11 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* Revision history + - History 14-5-95 v0.0 Plays sound tracks. No reading of data CDs yet. Detection of disk change doesn't work. 21-5-95 v0.1 First ALPHA version. CD can be mounted. The @@ -47,308 +51,379 @@ Updated README.optcd. Submitted for inclusion in 1.3.21 29-9-95 v0.4a Fixed bug that prevented compilation as module + 25-10-95 v0.5 Started multisession code. Implementation + copied from Werner Zimmermann, who copied it + from Heiko Schlittermann's mcdx. + 17-1-96 v0.6 Multisession works; some cleanup too. */ + +/* Includes */ -#include -#include +#include #include -#include -#include -#include -#include #include -#include - #include #define MAJOR_NR OPTICS_CDROM_MAJOR +#include -# include -#define optcd_port optcd /* Needed for the modutils. */ -# include - - -/* Some (Media)Magic */ -/* define types of drive the interface on an ISP16 card may be looking at */ -#define ISP16_DRIVE_X 0x00 -#define ISP16_SONY 0x02 -#define ISP16_PANASONIC0 0x02 -#define ISP16_SANYO0 0x02 -#define ISP16_MITSUMI 0x04 -#define ISP16_PANASONIC1 0x06 -#define ISP16_SANYO1 0x06 -#define ISP16_DRIVE_NOT_USED 0x08 /* not used */ -#define ISP16_DRIVE_SET_MASK 0xF1 /* don't change 0-bit or 4-7-bits*/ -/* ...for port */ -#define ISP16_DRIVE_SET_PORT 0xF8D -/* set io parameters */ -#define ISP16_BASE_340 0x00 -#define ISP16_BASE_330 0x40 -#define ISP16_BASE_360 0x80 -#define ISP16_BASE_320 0xC0 -#define ISP16_IRQ_X 0x00 -#define ISP16_IRQ_5 0x04 /* shouldn't be used due to soundcard conflicts */ -#define ISP16_IRQ_7 0x08 /* shouldn't be used due to soundcard conflicts */ -#define ISP16_IRQ_3 0x0C -#define ISP16_IRQ_9 0x10 -#define ISP16_IRQ_10 0x14 -#define ISP16_IRQ_11 0x18 -#define ISP16_DMA_X 0x03 -#define ISP16_DMA_3 0x00 -#define ISP16_DMA_5 0x00 -#define ISP16_DMA_6 0x01 -#define ISP16_DMA_7 0x02 -#define ISP16_IO_SET_MASK 0x20 /* don't change 5-bit */ -/* ...for port */ -#define ISP16_IO_SET_PORT 0xF8E -/* enable the drive */ -#define ISP16_NO_IDE__ENABLE_CDROM_PORT 0xF90 /* ISP16 without IDE interface */ -#define ISP16_IDE__ENABLE_CDROM_PORT 0xF91 /* ISP16 with IDE interface */ -#define ISP16_ENABLE_CDROM 0x80 /* seven bit */ - -/* the magic stuff */ -#define ISP16_CTRL_PORT 0xF8F -#define ISP16_NO_IDE__CTRL 0xE2 /* ISP16 without IDE interface */ -#define ISP16_IDE__CTRL 0xE3 /* ISP16 with IDE interface */ - -static short isp16_detect(void); -static short isp16_no_ide__detect(void); -static short isp16_with_ide__detect(void); -static short isp16_config( int base, u_char drive_type, int irq, int dma ); -static short isp16_type; /* dependent on type of interface card */ -static u_char isp16_ctrl; -static u_short isp16_enable_cdrom_port; +#include +#include +#ifdef PROBE_ISP16 +#include "optcd_isp16.h" /* optional ISP16 detection/configuration */ +#endif + +/* Debug support */ -static short optcd_port = OPTCD_PORTBASE; -/* Read current status/data availability flags */ -inline static int optFlags(void) { - return inb(STATUS_PORT) & FL_STDT; -} +/* Don't forget to add new debug flags here. */ +#if DEBUG_DRIVE_IF | DEBUG_VFS | DEBUG_CONV | DEBUG_TOC | \ + DEBUG_BUFFERS | DEBUG_REQUEST | DEBUG_STATE | DEBUG_MULTIS +#define DEBUG(x) debug x +static void debug(int debug_this, const char* fmt, ...) +{ + char s[1024]; + va_list args; -/* Wait for status available; return TRUE on timeout */ -static int sten_low(void) { - int no_status; - unsigned long count = 0; - while ((no_status = (optFlags() & FL_STEN))) - if (++count >= BUSY_TIMEOUT) - break; -#ifdef DEBUG_DRIVE_IF - if (no_status) - printk("optcd: timeout waiting for STEN low\n"); - else - printk("optcd: STEN low after %ld\n", count); -#endif - return no_status; -} + if (!debug_this) + return; + + va_start(args, fmt); + vsprintf(s, fmt, args); + printk("optcd: %s\n", s); + va_end(args); +} +#else +#define DEBUG(x) +#endif + +/* Drive hardware/firmware characteristics + Identifiers in accordance with Optics Storage documentation */ + + +#define optcd_port optcd /* Needed for the modutils. */ +static short optcd_port = OPTCD_PORTBASE; /* I/O base of drive. */ + +/* Drive registers, read */ +#define DATA_PORT optcd_port /* Read data/status */ +#define STATUS_PORT optcd_port+1 /* Indicate data/status availability */ + +/* Drive registers, write */ +#define COMIN_PORT optcd_port /* For passing command/parameter */ +#define RESET_PORT optcd_port+1 /* Write anything and wait 0.5 sec */ +#define HCON_PORT optcd_port+2 /* Host Xfer Configuration */ + + +/* Command completion/status read from DATA register */ +#define ST_DRVERR 0x80 +#define ST_DOOR_OPEN 0x40 +#define ST_MIXEDMODE_DISK 0x20 +#define ST_MODE_BITS 0x1c +#define ST_M_STOP 0x00 +#define ST_M_READ 0x04 +#define ST_M_AUDIO 0x04 +#define ST_M_PAUSE 0x08 +#define ST_M_INITIAL 0x0c +#define ST_M_ERROR 0x10 +#define ST_M_OTHERS 0x14 +#define ST_MODE2TRACK 0x02 +#define ST_DSK_CHG 0x01 +#define ST_L_LOCK 0x01 +#define ST_CMD_OK 0x00 +#define ST_OP_OK 0x01 +#define ST_PA_OK 0x02 +#define ST_OP_ERROR 0x05 +#define ST_PA_ERROR 0x06 + + +/* Error codes (appear as command completion code from DATA register) */ +/* Player related errors */ +#define ERR_ILLCMD 0x11 /* Illegal command to player module */ +#define ERR_ILLPARM 0x12 /* Illegal parameter to player module */ +#define ERR_SLEDGE 0x13 +#define ERR_FOCUS 0x14 +#define ERR_MOTOR 0x15 +#define ERR_RADIAL 0x16 +#define ERR_PLL 0x17 /* PLL lock error */ +#define ERR_SUB_TIM 0x18 /* Subcode timeout error */ +#define ERR_SUB_NF 0x19 /* Subcode not found error */ +#define ERR_TRAY 0x1a +#define ERR_TOC 0x1b /* Table of Contents read error */ +#define ERR_JUMP 0x1c +/* Data errors */ +#define ERR_MODE 0x21 +#define ERR_FORM 0x22 +#define ERR_HEADADDR 0x23 /* Header Address not found */ +#define ERR_CRC 0x24 +#define ERR_ECC 0x25 /* Uncorrectable ECC error */ +#define ERR_CRC_UNC 0x26 /* CRC error and uncorrectable error */ +#define ERR_ILLBSYNC 0x27 /* Illegal block sync error */ +#define ERR_VDST 0x28 /* VDST not found */ +/* Timeout errors */ +#define ERR_READ_TIM 0x31 /* Read timeout error */ +#define ERR_DEC_STP 0x32 /* Decoder stopped */ +#define ERR_DEC_TIM 0x33 /* Decoder interrupt timeout error */ +/* Function abort codes */ +#define ERR_KEY 0x41 /* Key -Detected abort */ +#define ERR_READ_FINISH 0x42 /* Read Finish */ +/* Second Byte diagnostic codes */ +#define ERR_NOBSYNC 0x01 /* No block sync */ +#define ERR_SHORTB 0x02 /* Short block */ +#define ERR_LONGB 0x03 /* Long block */ +#define ERR_SHORTDSP 0x04 /* Short DSP word */ +#define ERR_LONGDSP 0x05 /* Long DSP word */ + + +/* Status availability flags read from STATUS register */ +#define FL_EJECT 0x20 +#define FL_WAIT 0x10 /* active low */ +#define FL_EOP 0x08 /* active low */ +#define FL_STEN 0x04 /* Status available when low */ +#define FL_DTEN 0x02 /* Data available when low */ +#define FL_DRQ 0x01 /* active low */ +#define FL_RESET 0xde /* These bits are high after a reset */ +#define FL_STDT (FL_STEN|FL_DTEN) + + +/* Transfer mode, written to HCON register */ +#define HCON_DTS 0x08 +#define HCON_SDRQB 0x04 +#define HCON_LOHI 0x02 +#define HCON_DMA16 0x01 + + +/* Drive command set, written to COMIN register */ +/* Quick response commands */ +#define COMDRVST 0x20 /* Drive Status Read */ +#define COMERRST 0x21 /* Error Status Read */ +#define COMIOCTLISTAT 0x22 /* Status Read; reset disk changed bit */ +#define COMINITSINGLE 0x28 /* Initialize Single Speed */ +#define COMINITDOUBLE 0x29 /* Initialize Double Speed */ +#define COMUNLOCK 0x30 /* Unlock */ +#define COMLOCK 0x31 /* Lock */ +#define COMLOCKST 0x32 /* Lock/Unlock Status */ +#define COMVERSION 0x40 /* Get Firmware Revision */ +#define COMVOIDREADMODE 0x50 /* Void Data Read Mode */ +/* Read commands */ +#define COMFETCH 0x60 /* Prefetch Data */ +#define COMREAD 0x61 /* Read */ +#define COMREADRAW 0x62 /* Read Raw Data */ +#define COMREADALL 0x63 /* Read All 2646 Bytes */ +/* Player control commands */ +#define COMLEADIN 0x70 /* Seek To Lead-in */ +#define COMSEEK 0x71 /* Seek */ +#define COMPAUSEON 0x80 /* Pause On */ +#define COMPAUSEOFF 0x81 /* Pause Off */ +#define COMSTOP 0x82 /* Stop */ +#define COMOPEN 0x90 /* Open Tray Door */ +#define COMCLOSE 0x91 /* Close Tray Door */ +#define COMPLAY 0xa0 /* Audio Play */ +#define COMPLAY_TNO 0xa2 /* Audio Play By Track Number */ +#define COMSUBQ 0xb0 /* Read Sub-q Code */ +#define COMLOCATION 0xb1 /* Read Head Position */ +/* Audio control commands */ +#define COMCHCTRL 0xc0 /* Audio Channel Control */ +/* Miscellaneous (test) commands */ +#define COMDRVTEST 0xd0 /* Write Test Bytes */ +#define COMTEST 0xd1 /* Diagnostic Test */ + +/* Low level drive interface. Only here we do actual I/O + Waiting for status / data available */ -/* Wait for data available; return TRUE on timeout */ -static int dten_low(void) { - int no_data; + +/* Busy wait until FLAG goes low. Return 0 on timeout. */ +inline static int flag_low(int flag, unsigned long timeout) +{ + int flag_high; unsigned long count = 0; - while ((no_data = (optFlags() & FL_DTEN))) - if (++count >= BUSY_TIMEOUT) + + while ((flag_high = (inb(STATUS_PORT) & flag))) + if (++count >= timeout) break; -#ifdef DEBUG_DRIVE_IF - if (no_data) - printk("optcd: timeout waiting for DTEN low\n"); - else - printk("optcd: DTEN low after %ld\n", count); -#endif - return no_data; + + DEBUG((DEBUG_DRIVE_IF, "flag_low 0x%x count %ld%s", + flag, count, flag_high ? " timeout" : "")); + return !flag_high; } -/* Facilities for polled waiting for status or data */ -static int sleep_timeout; /* Max amount of time still to sleep */ -static unsigned char sleep_flags; /* Flags read last time around */ + +/* Timed waiting for status or data */ +static int sleep_timeout; /* max # of ticks to sleep */ static struct wait_queue *waitq = NULL; static struct timer_list delay_timer = {NULL, NULL, 0, 0, NULL}; -/* Timer routine: wake up when either of FL_STEN or FL_DTEN goes down, - * or when timeout expires. Otherwise wait some more. - */ -static void sleep_timer(void) { - if ((sleep_flags = optFlags()) != FL_STDT) { - wake_up(&waitq); - return; - } - if (--sleep_timeout <= 0) { +#define SET_TIMER(func, jifs) \ + delay_timer.expires = jiffies+(jifs); \ + delay_timer.function = (void *) (func); \ + add_timer(&delay_timer); +#define CLEAR_TIMER del_timer(&delay_timer) + + +/* Timer routine: wake up when desired flag goes low, + or when timeout expires. */ +static void sleep_timer(void) +{ + int flags = inb(STATUS_PORT) & FL_STDT; + + if (flags == FL_STDT && --sleep_timeout > 0) { + SET_TIMER(sleep_timer, HZ/100); /* multi-statement macro */ + } else wake_up(&waitq); - return; - } - SET_TIMER(sleep_timer, 1); } -/* Sleep until any of FL_STEN or FL_DTEN go down, or until timeout. - * sleep_timeout must be set first. - */ -static int sleep_status(void) { -#ifdef DEBUG_DRIVE_IF - printk("optcd: sleeping %d on status\n", sleep_timeout); -#endif - if (sleep_timeout <= 0) /* timeout immediately */ - return FL_STDT; - if ((sleep_flags = optFlags()) == FL_STDT) { - SET_TIMER(sleep_timer, 1); + +/* Sleep until FLAG goes low. Return 0 on timeout or wrong flag low. */ +static int sleep_flag_low(int flag, unsigned long timeout) +{ + int flag_high; + + DEBUG((DEBUG_DRIVE_IF, "sleep_flag_low")); + + sleep_timeout = timeout; + flag_high = inb(STATUS_PORT) & flag; + if (flag_high && sleep_timeout > 0) { + SET_TIMER(sleep_timer, HZ/100); sleep_on(&waitq); + flag_high = inb(STATUS_PORT) & flag; } -#ifdef DEBUG_DRIVE_IF - printk("optcd: woken up with %d to go, flags %d\n", - sleep_timeout, sleep_flags); -#endif - return sleep_flags; -} -/* Sleep until status available; return TRUE on timeout */ -inline static int sleep_sten_low(void) { - int flags; - sleep_timeout = SLEEP_TIMEOUT; - flags = sleep_status(); -#ifdef DEBUG_DRIVE_IF - if (!(flags & FL_DTEN)) - printk("optcd: DTEN while waiting for STEN\n"); -#endif - return flags & FL_STEN; + DEBUG((DEBUG_DRIVE_IF, "flag 0x%x count %ld%s", + flag, timeout, flag_high ? " timeout" : "")); + return !flag_high; } + +/* Low level drive interface. Only here we do actual I/O + Sending commands and parameters */ + + +/* Errors in the command protocol */ +#define ERR_IF_CMD_TIMEOUT 0x100 +#define ERR_IF_ERR_TIMEOUT 0x101 +#define ERR_IF_RESP_TIMEOUT 0x102 +#define ERR_IF_DATA_TIMEOUT 0x103 +#define ERR_IF_NOSTAT 0x104 -/* Sleep until data available; return TRUE on timeout */ -inline static int sleep_dten_low(void) { - int flags; - sleep_timeout = SLEEP_TIMEOUT; - flags = sleep_status(); -#ifdef DEBUG_DRIVE_IF - if (!(flags & FL_STEN)) - printk("optcd: STEN while waiting for DTEN\n"); -#endif - return flags & FL_DTEN; -} /* Send command code. Return <0 indicates error */ -static int optSendCmd(int cmd) { +static int send_cmd(int cmd) +{ unsigned char ack; -#if defined(DEBUG_DRIVE_IF)||defined(DEBUG_COMMANDS) - printk("optcd: executing command 0x%02x\n", cmd); -#endif + + DEBUG((DEBUG_DRIVE_IF, "sending command 0x%02x\n", cmd)); + outb(HCON_DTS, HCON_PORT); /* Enable Suspend Data Transfer */ outb(cmd, COMIN_PORT); /* Send command code */ - if (sten_low()) /* Wait for status available */ + if (!flag_low(FL_STEN, BUSY_TIMEOUT)) /* Wait for status */ return -ERR_IF_CMD_TIMEOUT; ack = inb(DATA_PORT); /* read command acknowledge */ -#ifdef DEBUG_DRIVE_IF - printk("optcd: acknowledge code 0x%02x\n", ack); -#endif outb(HCON_SDRQB, HCON_PORT); /* Disable Suspend Data Transfer */ return ack==ST_OP_OK ? 0 : -ack; } + /* Send command parameters. Return <0 indicates error */ -static int optSendParams(struct opt_Play_msf *params) { +static int send_params(struct cdrom_msf *params) +{ unsigned char ack; -#if defined(DEBUG_DRIVE_IF)||defined(DEBUG_COMMANDS) - printk("optcd: params %02x:%02x:%02x %02x:%02x:%02x\n", - params->start.min, params->start.sec, params->start.frame, - params->end.min, params->end.sec, params->end.frame); -#endif - outb(params -> start.min, COMIN_PORT); - outb(params -> start.sec, COMIN_PORT); - outb(params -> start.frame, COMIN_PORT); - outb(params -> end.min, COMIN_PORT); - outb(params -> end.sec, COMIN_PORT); - outb(params -> end.frame, COMIN_PORT); - if (sten_low()) /* Wait for status available */ + + DEBUG((DEBUG_DRIVE_IF, "sending parameters" + " %02x:%02x:%02x" + " %02x:%02x:%02x", + params->cdmsf_min0, + params->cdmsf_sec0, + params->cdmsf_frame0, + params->cdmsf_min1, + params->cdmsf_sec1, + params->cdmsf_frame1)); + + outb(params->cdmsf_min0, COMIN_PORT); + outb(params->cdmsf_sec0, COMIN_PORT); + outb(params->cdmsf_frame0, COMIN_PORT); + outb(params->cdmsf_min1, COMIN_PORT); + outb(params->cdmsf_sec1, COMIN_PORT); + outb(params->cdmsf_frame1, COMIN_PORT); + if (!flag_low(FL_STEN, BUSY_TIMEOUT)) /* Wait for status */ return -ERR_IF_CMD_TIMEOUT; ack = inb(DATA_PORT); /* read command acknowledge */ -#ifdef DEBUG_DRIVE_IF - printk("optcd: acknowledge code 0x%02x\n", ack); -#endif return ack==ST_PA_OK ? 0 : -ack; } -/* Return execution status for quick response commands, i.e. busy wait. - * Return value <0 indicates timeout. - */ -static int optGetExecStatus(void) { - unsigned char exec_status; - if (sten_low()) /* Wait for status available */ + +/* Send parameters for SEEK command. Return <0 indicates error */ +static int send_seek_params(struct cdrom_msf *params) +{ + unsigned char ack; + + DEBUG((DEBUG_DRIVE_IF, "sending seek parameters" + " %02x:%02x:%02x", + params->cdmsf_min0, + params->cdmsf_sec0, + params->cdmsf_frame0)); + + outb(params->cdmsf_min0, COMIN_PORT); + outb(params->cdmsf_sec0, COMIN_PORT); + outb(params->cdmsf_frame0, COMIN_PORT); + if (!flag_low(FL_STEN, BUSY_TIMEOUT)) /* Wait for status */ return -ERR_IF_CMD_TIMEOUT; - exec_status = inb(DATA_PORT); /* read command execution status */ -#ifdef DEBUG_DRIVE_IF - printk("optcd: returned execution status: 0x%02x\n", exec_status); -#endif - return exec_status; + ack = inb(DATA_PORT); /* read command acknowledge */ + return ack==ST_PA_OK ? 0 : -ack; } -/* Return execution status for slow commands. Only use when no data is - * expected. Return value <0 indicates timeout. - */ -static int optSleepTillExecStatus(void) { + +/* Wait for command execution status. Choice between busy waiting + and sleeping. Return value <0 indicates timeout. */ +inline static int get_exec_status(int busy_waiting) +{ unsigned char exec_status; - if (sleep_sten_low()) /* Wait for status available */ + + if (busy_waiting + ? !flag_low(FL_STEN, BUSY_TIMEOUT) + : !sleep_flag_low(FL_STEN, SLEEP_TIMEOUT)) return -ERR_IF_CMD_TIMEOUT; - exec_status = inb(DATA_PORT); /* read command execution status */ -#ifdef DEBUG_DRIVE_IF - printk("optcd: returned execution status: 0x%02x\n", exec_status); -#endif + + exec_status = inb(DATA_PORT); + DEBUG((DEBUG_DRIVE_IF, "returned exec status 0x%02x", exec_status)); return exec_status; } -/* Fetch status that has previously been waited for. <0 means not available */ -inline static int optStatus(void) { - unsigned char status; - if (optFlags() & FL_STEN) - return -ERR_IF_NOSTAT; - status = inb(DATA_PORT); -#ifdef DEBUG_DRIVE_IF - printk("optcd: read status: 0x%02x\n", status); -#endif - return status; -} -/* Wait for extra byte of data that a command returns */ -static int optGetData(void) { +/* Wait busy for extra byte of data that a command returns. + Return value <0 indicates timeout. */ +inline static int get_data(int short_timeout) +{ unsigned char data; - if (sten_low()) + + if (!flag_low(FL_STEN, short_timeout ? FAST_TIMEOUT : BUSY_TIMEOUT)) return -ERR_IF_DATA_TIMEOUT; + data = inb(DATA_PORT); -#ifdef DEBUG_DRIVE_IF - printk("optcd: read data: 0x%02x\n", data); -#endif + DEBUG((DEBUG_DRIVE_IF, "returned data 0x%02x", data)); return data; } -/* Read data that has previously been waited for. */ -inline static void optReadData(char *buf, int n) { - insb(DATA_PORT, buf, n); -} - -/* Flush status and data fifos */ -inline static void optFlushData(void) { - while (optFlags() != FL_STDT) - inb(DATA_PORT); -} -/* Write something to RESET_PORT and wait. Return TRUE upon success. */ -static int optResetDrive(void) { +/* Returns 0 if failed */ +static int reset_drive(void) +{ unsigned long count = 0; int flags; -#ifdef DEBUG_DRIVE_IF - printk("optcd: reset drive\n"); -#endif + + DEBUG((DEBUG_DRIVE_IF, "reset drive")); + outb(0, RESET_PORT); while (++count < RESET_WAIT) inb(DATA_PORT); + count = 0; while ((flags = (inb(STATUS_PORT) & FL_RESET)) != FL_RESET) if (++count >= BUSY_TIMEOUT) break; -#ifdef DEBUG_DRIVE_IF - if (flags == FL_RESET) - printk("optcd: drive reset\n"); - else - printk("optcd: reset failed\n"); -#endif + + DEBUG((DEBUG_DRIVE_IF, "reset %s", + flags == FL_RESET ? "succeeded" : "failed")); + if (flags != FL_RESET) return 0; /* Reset failed */ outb(HCON_SDRQB, HCON_PORT); /* Disable Suspend Data Transfer */ @@ -356,345 +431,620 @@ } +/* Facilities for asynchronous operation */ + +/* Read status/data availability flags FL_STEN and FL_DTEN */ +inline static int stdt_flags(void) +{ + return inb(STATUS_PORT) & FL_STDT; +} + + +/* Fetch status that has previously been waited for. <0 means not available */ +inline static int fetch_status(void) +{ + unsigned char status; + + if (inb(STATUS_PORT) & FL_STEN) + return -ERR_IF_NOSTAT; + + status = inb(DATA_PORT); + DEBUG((DEBUG_DRIVE_IF, "fetched exec status 0x%02x", status)); + return status; +} + + +/* Fetch data that has previously been waited for. */ +inline static void fetch_data(char *buf, int n) +{ + insb(DATA_PORT, buf, n); + DEBUG((DEBUG_DRIVE_IF, "fetched 0x%x bytes", n)); +} + + +/* Flush status and data fifos */ +inline static void flush_data(void) +{ + while ((inb(STATUS_PORT) & FL_STDT) != FL_STDT) + inb(DATA_PORT); + DEBUG((DEBUG_DRIVE_IF, "flushed fifos")); +} + /* Command protocol */ -/* Send a simple command and wait for response */ -inline static int optCmd(int cmd) { - int ack = optSendCmd(cmd); + +/* Send a simple command and wait for response. Command codes < COMFETCH + are quick response commands */ +inline static int exec_cmd(int cmd) +{ + int ack = send_cmd(cmd); if (ack < 0) return ack; - if (cmd < COMFETCH) /* Quick response command */ - return optGetExecStatus(); - else /* Slow command */ - return optSleepTillExecStatus(); + return get_exec_status(cmd < COMFETCH); } -/* Send a command with parameters and wait for response */ -inline static int optPlayCmd(int cmd, struct opt_Play_msf *params) { - int ack = optSendCmd(cmd); + +/* Send a command with parameters. Don't wait for the response, + * which consists of data blocks read from the CD. */ +inline static int exec_read_cmd(int cmd, struct cdrom_msf *params) +{ + int ack = send_cmd(cmd); if (ack < 0) return ack; - if ((ack = optSendParams(params)) < 0) - return ack; - return optSleepTillExecStatus(); + return send_params(params); } -/* Send a command with parameters. Don't wait for the response, - * which consists of the data blocks read. */ -inline static int optReadCmd(int cmd, struct opt_Play_msf *params) { - int ack = optSendCmd(cmd); + +/* Send a seek command with parameters and wait for response */ +inline static int exec_seek_cmd(int cmd, struct cdrom_msf *params) +{ + int ack = send_cmd(cmd); + if (ack < 0) + return ack; + ack = send_seek_params(params); if (ack < 0) return ack; - return optSendParams(params); + return 0; } +/* Send a command with parameters and wait for response */ +inline static int exec_long_cmd(int cmd, struct cdrom_msf *params) +{ + int ack = exec_read_cmd(cmd, params); + if (ack < 0) + return ack; + return get_exec_status(0); +} + /* Address conversion routines */ + /* Binary to BCD (2 digits) */ -inline static unsigned char bin2bcd(unsigned char p) { -#ifdef DEBUG_CONV - if (p > 99) - printk("optcd: error bin2bcd %d\n", p); -#endif - return (p % 10) | ((p / 10) << 4); +inline static void single_bin2bcd(u_char *p) +{ + DEBUG((DEBUG_CONV, "bin2bcd %02d", *p)); + *p = (*p % 10) | ((*p / 10) << 4); } -/* Linear address to minute, second, frame form */ -static void hsg2msf(long hsg, struct msf *msf) { - hsg += 150; - msf -> min = hsg / 4500; - hsg %= 4500; - msf -> sec = hsg / 75; - msf -> frame = hsg % 75; -#ifdef DEBUG_CONV - if (msf -> min >= 70) - printk("optcd: Error hsg2msf address Minutes\n"); - if (msf -> sec >= 60) - printk("optcd: Error hsg2msf address Seconds\n"); - if (msf -> frame >= 75) - printk("optcd: Error hsg2msf address Frames\n"); -#endif - msf -> min = bin2bcd(msf -> min); /* convert to BCD */ - msf -> sec = bin2bcd(msf -> sec); - msf -> frame = bin2bcd(msf -> frame); + +/* Convert entire msf struct */ +static void bin2bcd(struct cdrom_msf *msf) +{ + single_bin2bcd(&msf->cdmsf_min0); + single_bin2bcd(&msf->cdmsf_sec0); + single_bin2bcd(&msf->cdmsf_frame0); + single_bin2bcd(&msf->cdmsf_min1); + single_bin2bcd(&msf->cdmsf_sec1); + single_bin2bcd(&msf->cdmsf_frame1); +} + + +/* Linear block address to minute, second, frame form */ +static void lba2msf(int lba, struct cdrom_msf *msf) +{ + DEBUG((DEBUG_CONV, "lba2msf %d", lba)); + lba += CD_MSF_OFFSET; + msf->cdmsf_min0 = lba / 4500; lba %= 4500; + msf->cdmsf_sec0 = lba / 75; + msf->cdmsf_frame0 = lba % 75; + msf->cdmsf_min1 = 0; + msf->cdmsf_sec1 = 0; + msf->cdmsf_frame1 = 0; + bin2bcd(msf); } + /* Two BCD digits to binary */ -inline static int bcd2bin(unsigned char bcd) { +inline static u_char bcd2bin(u_char bcd) +{ + DEBUG((DEBUG_CONV, "bcd2bin %x%02x", bcd)); return (bcd >> 4) * 10 + (bcd & 0x0f); } -/* Minute, second, frame address to linear address */ -static long msf2hsg(struct msf *mp) { -#ifdef DEBUG_CONV - if (mp -> min >= 70) - printk("optcd: Error msf2hsg address Minutes\n"); - if (mp -> sec >= 60) - printk("optcd: Error msf2hsg address Seconds\n"); - if (mp -> frame >= 75) - printk("optcd: Error msf2hsg address Frames\n"); -#endif - return bcd2bin(mp -> frame) - + bcd2bin(mp -> sec) * 75 - + bcd2bin(mp -> min) * 4500 - - 150; + +union cd_addr { + struct { + u_char minute; + u_char second; + u_char frame; + } msf; + int lba; +}; + + +static void msf2lba(union cd_addr *addr) +{ + addr->lba = addr->msf.minute * 4500 + + addr->msf.second * 75 + + addr->msf.frame - CD_MSF_OFFSET; +} + + +/* Minute, second, frame address BCD to binary or to linear address, + depending on MODE */ +static void msf_bcd2bin(union cd_addr *addr) +{ + addr->msf.minute = bcd2bin(addr->msf.minute); + addr->msf.second = bcd2bin(addr->msf.second); + addr->msf.frame = bcd2bin(addr->msf.frame); } + +/* High level drive commands */ + +static int audio_status = CDROM_AUDIO_NO_STATUS; +static char toc_uptodate = 0; -/* Drive status and table of contents */ - -static int optAudioStatus = CDROM_AUDIO_NO_STATUS; -static char optDiskChanged = 1; -static char optTocUpToDate = 0; -static struct opt_DiskInfo DiskInfo; -static struct opt_Toc Toc[MAX_TRACKS]; - -/* Get CDROM status, flagging completion of audio play and disk changes. */ -static int optGetStatus(void) { - int st; - if ((st = optCmd(COMIOCTLISTAT)) < 0) - return st; - if (st == 0xff) +/* Get drive status, flagging completion of audio play and disk changes. */ +static int drive_status(void) +{ + int status; + + status = exec_cmd(COMIOCTLISTAT); + DEBUG((DEBUG_DRIVE_IF, "IOCTLISTAT: %03x", status)); + if (status < 0) + return status; + if (status == 0xff) /* No status available */ return -ERR_IF_NOSTAT; - if (((st & ST_MODE_BITS) != ST_M_AUDIO) && - (optAudioStatus == CDROM_AUDIO_PLAY)) { - optAudioStatus = CDROM_AUDIO_COMPLETED; - } - if (st & ST_DSK_CHG) { - optDiskChanged = 1; - optTocUpToDate = 0; - optAudioStatus = CDROM_AUDIO_NO_STATUS; - } - return st; -} - -/* - * Read the current Q-channel info. Also used for reading the - * table of contents. - */ -static int optGetQChannelInfo(struct opt_Toc *qp) { - int st; -#ifdef DEBUG_TOC - printk("optcd: starting optGetQChannelInfo\n"); -#endif - if ((st = optGetStatus()) < 0) - return st; - if ((st = optCmd(COMSUBQ)) < 0) - return st; - if ((qp -> ctrl_addr = st = optGetData()), st < 0) return st; - if ((qp -> track = st = optGetData()), st < 0) return st; - if ((qp -> pointIndex = st = optGetData()), st < 0) return st; - if ((qp -> trackTime.min = st = optGetData()), st < 0) return st; - if ((qp -> trackTime.sec = st = optGetData()), st < 0) return st; - if ((qp -> trackTime.frame = st = optGetData()), st < 0) return st; - if ((st = optGetData()) < 0) return st; /* byte not used */ - if ((qp -> diskTime.min = st = optGetData()), st < 0) return st; - if ((qp -> diskTime.sec = st = optGetData()), st < 0) return st; - if ((qp -> diskTime.frame = st = optGetData()), st < 0) return st; -#ifdef DEBUG_TOC - printk("optcd: exiting optGetQChannelInfo\n"); -#endif + + if (((status & ST_MODE_BITS) != ST_M_AUDIO) && + (audio_status == CDROM_AUDIO_PLAY)) { + audio_status = CDROM_AUDIO_COMPLETED; + } + + if (status & ST_DSK_CHG) { + toc_uptodate = 0; + audio_status = CDROM_AUDIO_NO_STATUS; + } + + return status; +} + + +/* Read the current Q-channel info. Also used for reading the + table of contents. qp->cdsc_format must be set on entry to + indicate the desired address format */ +static int get_q_channel(struct cdrom_subchnl *qp) +{ + int status, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10; + + status = drive_status(); + if (status < 0) + return status; + qp->cdsc_audiostatus = audio_status; + + status = exec_cmd(COMSUBQ); + if (status < 0) + return status; + + d1 = get_data(0); + if (d1 < 0) + return d1; + qp->cdsc_adr = d1; + qp->cdsc_ctrl = d1 >> 4; + + d2 = get_data(0); + if (d2 < 0) + return d2; + qp->cdsc_trk = bcd2bin(d2); + + d3 = get_data(0); + if (d3 < 0) + return d3; + qp->cdsc_ind = bcd2bin(d3); + + d4 = get_data(0); + if (d4 < 0) + return d4; + qp->cdsc_reladdr.msf.minute = d4; + + d5 = get_data(0); + if (d5 < 0) + return d5; + qp->cdsc_reladdr.msf.second = d5; + + d6 = get_data(0); + if (d6 < 0) + return d6; + qp->cdsc_reladdr.msf.frame = d6; + + d7 = get_data(0); + if (d7 < 0) + return d7; + /* byte not used */ + + d8 = get_data(0); + if (d8 < 0) + return d8; + qp->cdsc_absaddr.msf.minute = d8; + + d9 = get_data(0); + if (d9 < 0) + return d9; + qp->cdsc_absaddr.msf.second = d9; + + d10 = get_data(0); + if (d10 < 0) + return d10; + qp->cdsc_absaddr.msf.frame = d10; + + DEBUG((DEBUG_TOC, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", + d1, d2, d3, d4, d5, d6, d7, d8, d9, d10)); + + msf_bcd2bin((union cd_addr *)/*%%*/&qp->cdsc_absaddr); + msf_bcd2bin((union cd_addr *)/*%%*/&qp->cdsc_reladdr); + if (qp->cdsc_format == CDROM_LBA) { + msf2lba((union cd_addr *)/*%%*/&qp->cdsc_absaddr); + msf2lba((union cd_addr *)/*%%*/&qp->cdsc_reladdr); + } + return 0; } + +/* Table of contents handling */ -#define QINFO_FIRSTTRACK 0xa0 -#define QINFO_LASTTRACK 0xa1 -#define QINFO_DISKLENGTH 0xa2 - -static int optGetDiskInfo(void) { - int st, limit; - unsigned char test = 0; - struct opt_Toc qInfo; -#ifdef DEBUG_TOC - printk("optcd: starting optGetDiskInfo\n"); -#endif - optDiskChanged = 0; - if ((st = optCmd(COMLEADIN)) < 0) - return st; - for (limit = 300; (limit > 0) && (test != 0x0f); limit--) { - if ((st = optGetQChannelInfo(&qInfo)) < 0) - return st; - switch (qInfo.pointIndex) { - case QINFO_FIRSTTRACK: - DiskInfo.first = bcd2bin(qInfo.diskTime.min); -#ifdef DEBUG_TOC - printk("optcd: got first: %d\n", DiskInfo.first); -#endif - test |= 0x01; - break; - case QINFO_LASTTRACK: - DiskInfo.last = bcd2bin(qInfo.diskTime.min); -#ifdef DEBUG_TOC - printk("optcd: got last: %d\n", DiskInfo.last); -#endif - test |= 0x02; - break; - case QINFO_DISKLENGTH: - DiskInfo.diskLength.min = qInfo.diskTime.min; - DiskInfo.diskLength.sec = qInfo.diskTime.sec-2; - DiskInfo.diskLength.frame = qInfo.diskTime.frame; -#ifdef DEBUG_TOC - printk("optcd: got length: %x:%x.%x\n", - DiskInfo.diskLength.min, - DiskInfo.diskLength.sec, - DiskInfo.diskLength.frame); + +/* Errors in table of contents */ +#define ERR_TOC_MISSINGINFO 0x120 +#define ERR_TOC_MISSINGENTRY 0x121 + + +struct msf { + u_char minute; + u_char second; + u_char frame; +}; + +struct cdrom_disk_info { + unsigned char first; + unsigned char last; + struct msf disk_length; + struct msf first_track; + /* Multisession info: */ + unsigned char next; + struct msf next_session; + struct msf last_session; + unsigned char multi; + unsigned char xa; + unsigned char audio; +}; +static struct cdrom_disk_info disk_info; + +#define MAX_TRACKS 111 +static struct cdrom_subchnl toc[MAX_TRACKS]; + +#define QINFO_FIRSTTRACK 100 /* bcd2bin(0xa0) */ +#define QINFO_LASTTRACK 101 /* bcd2bin(0xa1) */ +#define QINFO_DISKLENGTH 102 /* bcd2bin(0xa2) */ +#define QINFO_NEXTSESSION 110 /* bcd2bin(0xb0) */ + +#define I_FIRSTTRACK 0x01 +#define I_LASTTRACK 0x02 +#define I_DISKLENGTH 0x04 +#define I_NEXTSESSION 0x08 +#define I_ALL (I_FIRSTTRACK | I_LASTTRACK | I_DISKLENGTH) + + +#if DEBUG_TOC +void toc_debug_info(int i) +{ + printk("#%3d ctl %1x, adr %1x, track %2d index %3d" + " %2d:%02d.%02d %2d:%02d.%02d\n", + i, toc[i].cdsc_ctrl, toc[i].cdsc_adr, + toc[i].cdsc_trk, toc[i].cdsc_ind, + toc[i].cdsc_reladdr.msf.minute, + toc[i].cdsc_reladdr.msf.second, + toc[i].cdsc_reladdr.msf.frame, + toc[i].cdsc_absaddr.msf.minute, + toc[i].cdsc_absaddr.msf.second, + toc[i].cdsc_absaddr.msf.frame); +} #endif - test |= 0x04; - break; - default: - if ((test & 0x01) /* Got no of first track */ - && (qInfo.pointIndex == DiskInfo.first)) { - /* StartTime of First Track */ - DiskInfo.firstTrack.min = qInfo.diskTime.min; - DiskInfo.firstTrack.sec = qInfo.diskTime.sec; - DiskInfo.firstTrack.frame = qInfo.diskTime.frame; -#ifdef DEBUG_TOC - printk("optcd: got start: %x:%x.%x\n", - DiskInfo.firstTrack.min, - DiskInfo.firstTrack.sec, - DiskInfo.firstTrack.frame); + + +static int read_toc(void) +{ + int status, limit, count; + unsigned char got_info = 0; + struct cdrom_subchnl q_info; +#if DEBUG_TOC + int i; #endif - test |= 0x08; + + DEBUG((DEBUG_TOC, "starting read_toc")); + + count = 0; + for (limit = 60; limit > 0; limit--) { + int index; + + q_info.cdsc_format = CDROM_MSF; + status = get_q_channel(&q_info); + if (status < 0) + return status; + + index = q_info.cdsc_ind; + if (index > 0 && index < MAX_TRACKS + && q_info.cdsc_trk == 0 && toc[index].cdsc_ind == 0) { + toc[index] = q_info; + DEBUG((DEBUG_TOC, "got %d", index)); + if (index < 100) + count++; + + switch (q_info.cdsc_ind) { + case QINFO_FIRSTTRACK: + got_info |= I_FIRSTTRACK; + break; + case QINFO_LASTTRACK: + got_info |= I_LASTTRACK; + break; + case QINFO_DISKLENGTH: + got_info |= I_DISKLENGTH; + break; + case QINFO_NEXTSESSION: + got_info |= I_NEXTSESSION; + break; } } + + if ((got_info & I_ALL) == I_ALL + && toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute + count + >= toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute + 1) + break; } -#ifdef DEBUG_TOC - printk("optcd: exiting optGetDiskInfo\n"); -#endif - if (test != 0x0f) + + /* Construct disk_info from TOC */ + if (disk_info.first == 0) { + disk_info.first = toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute; + disk_info.first_track.minute = + toc[disk_info.first].cdsc_absaddr.msf.minute; + disk_info.first_track.second = + toc[disk_info.first].cdsc_absaddr.msf.second; + disk_info.first_track.frame = + toc[disk_info.first].cdsc_absaddr.msf.frame; + } + disk_info.last = toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute; + disk_info.disk_length.minute = + toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.minute; + disk_info.disk_length.second = + toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.second-2; + disk_info.disk_length.frame = + toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.frame; + disk_info.next_session.minute = + toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.minute; + disk_info.next_session.second = + toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.second; + disk_info.next_session.frame = + toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.frame; + disk_info.next = toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute; + disk_info.last_session.minute = + toc[disk_info.next].cdsc_absaddr.msf.minute; + disk_info.last_session.second = + toc[disk_info.next].cdsc_absaddr.msf.second; + disk_info.last_session.frame = + toc[disk_info.next].cdsc_absaddr.msf.frame; + toc[disk_info.last + 1].cdsc_absaddr.msf.minute = + disk_info.disk_length.minute; + toc[disk_info.last + 1].cdsc_absaddr.msf.second = + disk_info.disk_length.second; + toc[disk_info.last + 1].cdsc_absaddr.msf.frame = + disk_info.disk_length.frame; +#if DEBUG_TOC + for (i = 1; i <= disk_info.last + 1; i++) + toc_debug_info(i); + toc_debug_info(QINFO_FIRSTTRACK); + toc_debug_info(QINFO_LASTTRACK); + toc_debug_info(QINFO_DISKLENGTH); + toc_debug_info(QINFO_NEXTSESSION); +#endif + + DEBUG((DEBUG_TOC, "exiting read_toc, got_info %x, count %d", + got_info, count)); + if ((got_info & I_ALL) != I_ALL + || toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute + count + < toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute + 1) return -ERR_TOC_MISSINGINFO; return 0; } -static int optGetToc(void) { /* Presumes we have got DiskInfo */ - int st, count, px, limit; - struct opt_Toc qInfo; -#ifdef DEBUG_TOC - int i; - printk("optcd: starting optGetToc\n"); -#endif - for (count = 0; count < MAX_TRACKS; count++) - Toc[count].pointIndex = 0; - if ((st = optCmd(COMLEADIN)) < 0) - return st; - st = 0; - count = DiskInfo.last + 3; - for (limit = 300; (limit > 0) && (count > 0); limit--) { - if ((st = optGetQChannelInfo(&qInfo)) < 0) + +#ifdef MULTISESSION +static int get_multi_disk_info(void) +{ + int sessions, status; + struct cdrom_msf multi_index; + + + for (sessions = 2; sessions < 10 /* %%for now */; sessions++) { + int count; + + for (count = 100; count < MAX_TRACKS; count++) + toc[count].cdsc_ind = 0; + + multi_index.cdmsf_min0 = disk_info.next_session.minute; + multi_index.cdmsf_sec0 = disk_info.next_session.second; + multi_index.cdmsf_frame0 = disk_info.next_session.frame; + if (multi_index.cdmsf_sec0 >= 20) + multi_index.cdmsf_sec0 -= 20; + else { + multi_index.cdmsf_sec0 += 40; + multi_index.cdmsf_min0--; + } + DEBUG((DEBUG_MULTIS, "Try %d: %2d:%02d.%02d", sessions, + multi_index.cdmsf_min0, + multi_index.cdmsf_sec0, + multi_index.cdmsf_frame0)); + bin2bcd(&multi_index); + multi_index.cdmsf_min1 = 0; + multi_index.cdmsf_sec1 = 0; + multi_index.cdmsf_frame1 = 1; + + status = exec_read_cmd(COMREAD, &multi_index); + if (status < 0) { + DEBUG((DEBUG_TOC, "exec_read_cmd COMREAD: %02x", + -status)); break; - px = bcd2bin(qInfo.pointIndex); - if (px > 0 && px < MAX_TRACKS && qInfo.track == 0) - if (Toc[px].pointIndex == 0) { - Toc[px] = qInfo; - count--; - } + } + status = sleep_flag_low(FL_DTEN, MULTI_SEEK_TIMEOUT) ? + 0 : -ERR_TOC_MISSINGINFO; + flush_data(); + if (status < 0) { + DEBUG((DEBUG_TOC, "sleep_flag_low: %02x", -status)); + break; + } + + status = read_toc(); + if (status < 0) { + DEBUG((DEBUG_TOC, "read_toc: %02x", -status)); + break; + } + + disk_info.multi = 1; } - Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength; -#ifdef DEBUG_TOC - printk("optcd: exiting optGetToc\n"); - for (i = 1; i <= DiskInfo.last + 1; i++) - printk("i = %3d ctl-adr = %02x track %2d px " - "%02x %02x:%02x.%02x %02x:%02x.%02x\n", - i, Toc[i].ctrl_addr, - Toc[i].track, - Toc[i].pointIndex, - Toc[i].trackTime.min, - Toc[i].trackTime.sec, - Toc[i].trackTime.frame, - Toc[i].diskTime.min, - Toc[i].diskTime.sec, - Toc[i].diskTime.frame); - for (i = 100; i < 103; i++) - printk("i = %3d ctl-adr = %02x track %2d px " - "%02x %02x:%02x.%02x %02x:%02x.%02x\n", - i, Toc[i].ctrl_addr, - Toc[i].track, - Toc[i].pointIndex, - Toc[i].trackTime.min, - Toc[i].trackTime.sec, - Toc[i].trackTime.frame, - Toc[i].diskTime.min, - Toc[i].diskTime.sec, - Toc[i].diskTime.frame); -#endif - return count ? -ERR_TOC_MISSINGENTRY : 0; + + exec_cmd(COMSTOP); + + if (status < 0) + return -EIO; + return 0; } +#endif MULTISESSION -static int optUpdateToc(void) { -#ifdef DEBUG_TOC - printk("optcd: starting optUpdateToc\n"); -#endif - if (optTocUpToDate) + +static int update_toc(void) +{ + int status, count; + + if (toc_uptodate) return 0; - if (optGetDiskInfo() < 0) + + DEBUG((DEBUG_TOC, "starting update_toc")); + + disk_info.first = 0; + for (count = 0; count < MAX_TRACKS; count++) + toc[count].cdsc_ind = 0; + + status = exec_cmd(COMLEADIN); + if (status < 0) return -EIO; - if (optGetToc() < 0) + + status = read_toc(); + if (status < 0) { + DEBUG((DEBUG_TOC, "read_toc: %02x", -status)); return -EIO; - optTocUpToDate = 1; -#ifdef DEBUG_TOC - printk("optcd: exiting optUpdateToc\n"); -#endif + } + + /* Audio disk detection. Look at first track. */ + disk_info.audio = + (toc[disk_info.first].cdsc_ctrl & CDROM_DATA_TRACK) ? 0 : 1; + + /* XA detection */ + disk_info.xa = drive_status() & ST_MODE2TRACK; + + /* Multisession detection: if we want this, define MULTISESSION */ + disk_info.multi = 0; +#ifdef MULTISESSION + if (disk_info.xa) + get_multi_disk_info(); /* Here disk_info.multi is set */ +#endif MULTISESSION + if (disk_info.multi) + printk("optcd: Multisession support experimental, " + "see linux/Documentation/cdrom/optcd\n"); + + DEBUG((DEBUG_TOC, "exiting update_toc")); + + toc_uptodate = 1; return 0; } + +/* Request handling */ + + +#define CURRENT_VALID \ + (CURRENT && MAJOR(CURRENT -> rq_dev) == MAJOR_NR \ + && CURRENT -> cmd == READ && CURRENT -> sector != -1) -/* Buffers */ +#define BLOCKSIZE 2048 +#define BLOCKSIZE_RAW 2336 +#define BLOCKSIZE_ALL 2646 +#define N_BUFS 16 +#define NOBUF -1 -#define OPT_BUF_SIZ 16 -#define OPT_BLOCKSIZE 2048 -#define OPT_BLOCKSIZE_RAW 2336 -#define OPT_BLOCKSIZE_ALL 2646 -#define OPT_NOBUF -1 /* Buffer for block size conversion. */ -static char opt_buf[OPT_BLOCKSIZE*OPT_BUF_SIZ]; -static volatile int opt_buf_bn[OPT_BUF_SIZ], opt_next_bn; -static volatile int opt_buf_in = 0, opt_buf_out = OPT_NOBUF; +static char buf[BLOCKSIZE * N_BUFS]; +static volatile int buf_bn[N_BUFS], next_bn; +static volatile int buf_in = 0, buf_out = NOBUF; -inline static void opt_invalidate_buffers(void) { +inline static void opt_invalidate_buffers(void) +{ int i; -#ifdef DEBUG_BUFFERS - printk("optcd: executing opt_invalidate_buffers\n"); -#endif - for (i = 0; i < OPT_BUF_SIZ; i++) - opt_buf_bn[i] = OPT_NOBUF; - opt_buf_out = OPT_NOBUF; + + DEBUG((DEBUG_BUFFERS, "executing opt_invalidate_buffers")); + + for (i = 0; i < N_BUFS; i++) + buf_bn[i] = NOBUF; + buf_out = NOBUF; } -/* - * Take care of the different block sizes between cdrom and Linux. - * When Linux gets variable block sizes this will probably go away. - */ -static void opt_transfer(void) { -#if (defined DEBUG_BUFFERS) || (defined DEBUG_REQUEST) - printk("optcd: executing opt_transfer\n"); + +/* Take care of the different block sizes between cdrom and Linux. + When Linux gets variable block sizes this will probably go away. */ +static void transfer(void) +{ +#if DEBUG_BUFFERS | DEBUG_REQUEST + printk("optcd: executing transfer\n"); #endif + if (!CURRENT_VALID) return; while (CURRENT -> nr_sectors) { int bn = CURRENT -> sector / 4; int i, offs, nr_sectors; - for (i = 0; i < OPT_BUF_SIZ && opt_buf_bn[i] != bn; ++i); -#ifdef DEBUG_REQUEST - printk("optcd: found %d\n", i); -#endif - if (i >= OPT_BUF_SIZ) { - opt_buf_out = OPT_NOBUF; + for (i = 0; i < N_BUFS && buf_bn[i] != bn; ++i); + + DEBUG((DEBUG_REQUEST, "found %d", i)); + + if (i >= N_BUFS) { + buf_out = NOBUF; break; } + offs = (i * 4 + (CURRENT -> sector & 3)) * 512; nr_sectors = 4 - (CURRENT -> sector & 3); - if (opt_buf_out != i) { - opt_buf_out = i; - if (opt_buf_bn[i] != bn) { - opt_buf_out = OPT_NOBUF; + + if (buf_out != i) { + buf_out = i; + if (buf_bn[i] != bn) { + buf_out = NOBUF; continue; } } + if (nr_sectors > CURRENT -> nr_sectors) nr_sectors = CURRENT -> nr_sectors; - memcpy(CURRENT -> buffer, opt_buf + offs, nr_sectors * 512); + memcpy(CURRENT -> buffer, buf + offs, nr_sectors * 512); CURRENT -> nr_sectors -= nr_sectors; CURRENT -> sector += nr_sectors; CURRENT -> buffer += nr_sectors * 512; @@ -704,216 +1054,219 @@ /* State machine for reading disk blocks */ -enum opt_state_e { - OPT_S_IDLE, /* 0 */ - OPT_S_START, /* 1 */ - OPT_S_READ, /* 2 */ - OPT_S_DATA, /* 3 */ - OPT_S_STOP, /* 4 */ - OPT_S_STOPPING /* 5 */ +enum state_e { + S_IDLE, /* 0 */ + S_START, /* 1 */ + S_READ, /* 2 */ + S_DATA, /* 3 */ + S_STOP, /* 4 */ + S_STOPPING /* 5 */ }; -static volatile enum opt_state_e opt_state = OPT_S_IDLE; -#ifdef DEBUG_STATE -static volatile enum opt_state_e opt_state_old = OPT_S_STOP; -static volatile int opt_st_old = 0; -static volatile long opt_state_n = 0; +static volatile enum state_e state = S_IDLE; +#if DEBUG_STATE +static volatile enum state_e state_old = S_STOP; +static volatile int flags_old = 0; +static volatile long state_n = 0; #endif -static volatile int opt_transfer_is_active = 0; -static volatile int opt_error = 0; /* do something with this?? */ -static int optTries; /* ibid?? */ - -static void opt_poll(void) { - static int optTimeout; - static volatile int opt_read_count = 1; - int st = 0; - int loop_ctl = 1; + +static volatile int transfer_is_active = 0; +static volatile int error = 0; /* %% do something with this?? */ +static int tries; /* ibid?? */ + +static void poll(void) +{ + static int timeout; + static volatile int read_count = 1; + int flags; + int loop_again = 1; + int status = 0; int skip = 0; - if (opt_error) { - printk("optcd: I/O error 0x%02x\n", opt_error); + if (error) { + printk("optcd: I/O error 0x%02x\n", error); opt_invalidate_buffers(); -#ifdef WARN_IF_READ_FAILURE - if (optTries == 5) - printk("optcd: read block %d failed; audio disk?\n", - opt_next_bn); -#endif - if (!optTries--) { + if (!tries--) { printk("optcd: read block %d failed; Giving up\n", - opt_next_bn); - if (opt_transfer_is_active) { - optTries = 0; - loop_ctl = 0; - } + next_bn); + if (transfer_is_active) + loop_again = 0; if (CURRENT_VALID) end_request(0); - optTries = 5; + tries = 5; } - opt_error = 0; - opt_state = OPT_S_STOP; + error = 0; + state = S_STOP; } - while (loop_ctl) + while (loop_again) { - loop_ctl = 0; /* each case must flip this back to 1 if we want + loop_again = 0; /* each case must flip this back to 1 if we want to come back up here */ -#ifdef DEBUG_STATE - if (opt_state == opt_state_old) - opt_state_n++; + +#if DEBUG_STATE + if (state == state_old) + state_n++; else { - opt_state_old = opt_state; - if (++opt_state_n > 1) + state_old = state; + if (++state_n > 1) printk("optcd: %ld times in previous state\n", - opt_state_n); - printk("optcd: state %d\n", opt_state); - opt_state_n = 0; + state_n); + printk("optcd: state %d\n", state); + state_n = 0; } #endif - switch (opt_state) { - case OPT_S_IDLE: + + switch (state) { + case S_IDLE: return; - case OPT_S_START: - if (optSendCmd(COMDRVST)) + case S_START: + if (send_cmd(COMDRVST)) return; - opt_state = OPT_S_READ; - optTimeout = 3000; + state = S_READ; + timeout = READ_TIMEOUT; break; - case OPT_S_READ: { - struct opt_Play_msf msf; + case S_READ: { + struct cdrom_msf msf; if (!skip) { - if ((st = optStatus()) < 0) + status = fetch_status(); + if (status < 0) break; - if (st & ST_DSK_CHG) { - optDiskChanged = 1; - optTocUpToDate = 0; + if (status & ST_DSK_CHG) { + toc_uptodate = 0; opt_invalidate_buffers(); } } skip = 0; - if ((st & ST_DOOR_OPEN) || (st & ST_DRVERR)) { - optDiskChanged = 1; - optTocUpToDate = 0; - printk((st & ST_DOOR_OPEN) + if ((status & ST_DOOR_OPEN) || (status & ST_DRVERR)) { + toc_uptodate = 0; + printk((status & ST_DOOR_OPEN) ? "optcd: door open\n" : "optcd: disk removed\n"); - if (opt_transfer_is_active) { - opt_state = OPT_S_START; - loop_ctl = 1; + if (transfer_is_active) { + state = S_START; + loop_again = 1; break; } - opt_state = OPT_S_IDLE; + state = S_IDLE; while (CURRENT_VALID) end_request(0); return; } if (!CURRENT_VALID) { - opt_state = OPT_S_STOP; - loop_ctl = 1; + state = S_STOP; + loop_again = 1; break; } - opt_next_bn = CURRENT -> sector / 4; - hsg2msf(opt_next_bn, &msf.start); - opt_read_count = OPT_BUF_SIZ; - msf.end.min = 0; - msf.end.sec = 0; - msf.end.frame = opt_read_count; -#ifdef DEBUG_REQUEST - printk("optcd: reading %x:%x.%x %x:%x.%x\n", - msf.start.min, - msf.start.sec, - msf.start.frame, - msf.end.min, - msf.end.sec, - msf.end.frame); - printk("optcd: opt_next_bn:%d opt_buf_in:%d opt_buf_out:%d opt_buf_bn:%d\n", - opt_next_bn, - opt_buf_in, - opt_buf_out, - opt_buf_bn[opt_buf_in]); -#endif - optReadCmd(COMREAD, &msf); - opt_state = OPT_S_DATA; - optTimeout = READ_TIMEOUT; + next_bn = CURRENT -> sector / 4; + lba2msf(next_bn, &msf); + read_count = N_BUFS; + msf.cdmsf_frame1 = read_count; /* Not BCD! */ + + DEBUG((DEBUG_REQUEST, "reading %x:%x.%x %x:%x.%x", + msf.cdmsf_min0, + msf.cdmsf_sec0, + msf.cdmsf_frame0, + msf.cdmsf_min1, + msf.cdmsf_sec1, + msf.cdmsf_frame1)); + DEBUG((DEBUG_REQUEST, "next_bn:%d buf_in:%d" + " buf_out:%d buf_bn:%d", + next_bn, + buf_in, + buf_out, + buf_bn[buf_in])); + + exec_read_cmd(COMREAD, &msf); + state = S_DATA; + timeout = READ_TIMEOUT; break; } - case OPT_S_DATA: - st = optFlags() & (FL_STEN|FL_DTEN); -#ifdef DEBUG_STATE - if (st != opt_st_old) { - opt_st_old = st; - printk("optcd: st:%x\n", st); + case S_DATA: + flags = stdt_flags() & (FL_STEN|FL_DTEN); + +#if DEBUG_STATE + if (flags != flags_old) { + flags_old = flags; + printk("optcd: flags:%x\n", flags); } - if (st == FL_STEN) - printk("timeout cnt: %d\n", optTimeout); -#endif - switch (st) { - case FL_DTEN: -#ifdef WARN_IF_READ_FAILURE - if (optTries == 5) - printk("optcd: read block %d failed; audio disk?\n", - opt_next_bn); + if (flags == FL_STEN) + printk("timeout cnt: %d\n", timeout); #endif - if (!optTries--) { - printk("optcd: read block %d failed; Giving up\n", - opt_next_bn); - if (opt_transfer_is_active) { - optTries = 0; + + switch (flags) { + case FL_DTEN: /* only STEN low */ + if (!tries--) { + printk("optcd: read block %d failed; " + "Giving up\n", next_bn); + if (transfer_is_active) { + tries = 0; break; } if (CURRENT_VALID) end_request(0); - optTries = 5; + tries = 5; } - opt_state = OPT_S_START; - optTimeout = READ_TIMEOUT; - loop_ctl = 1; - case (FL_STEN|FL_DTEN): + state = S_START; + timeout = READ_TIMEOUT; + loop_again = 1; + case (FL_STEN|FL_DTEN): /* both high */ break; - default: - optTries = 5; - if (!CURRENT_VALID && opt_buf_in == opt_buf_out) { - opt_state = OPT_S_STOP; - loop_ctl = 1; + default: /* DTEN low */ + tries = 5; + if (!CURRENT_VALID && buf_in == buf_out) { + state = S_STOP; + loop_again = 1; break; } - if (opt_read_count<=0) - printk("optcd: warning - try to read 0 frames\n"); - while (opt_read_count) { - opt_buf_bn[opt_buf_in] = OPT_NOBUF; - if (dten_low()) { /* should be no waiting here!?? */ - printk("read_count:%d CURRENT->nr_sectors:%ld opt_buf_in:%d\n", - opt_read_count, + if (read_count<=0) + printk("optcd: warning - try to read" + " 0 frames\n"); + while (read_count) { + buf_bn[buf_in] = NOBUF; + if (!flag_low(FL_DTEN, BUSY_TIMEOUT)) { + /* should be no waiting here!?? */ + printk("read_count:%d " + "CURRENT->nr_sectors:%ld " + "buf_in:%d\n", + read_count, CURRENT->nr_sectors, - opt_buf_in); - printk("opt_transfer_is_active:%x\n", - opt_transfer_is_active); - opt_read_count = 0; - opt_state = OPT_S_STOP; - loop_ctl = 1; + buf_in); + printk("transfer active: %x\n", + transfer_is_active); + read_count = 0; + state = S_STOP; + loop_again = 1; end_request(0); break; } - optReadData(opt_buf+OPT_BLOCKSIZE*opt_buf_in, OPT_BLOCKSIZE); - opt_read_count--; -#ifdef DEBUG_REQUEST - printk("OPT_S_DATA; ---I've read data- read_count: %d\n", - opt_read_count); - printk("opt_next_bn:%d opt_buf_in:%d opt_buf_out:%d opt_buf_bn:%d\n", - opt_next_bn, - opt_buf_in, - opt_buf_out, - opt_buf_bn[opt_buf_in]); -#endif - opt_buf_bn[opt_buf_in] = opt_next_bn++; - if (opt_buf_out == OPT_NOBUF) - opt_buf_out = opt_buf_in; - opt_buf_in = opt_buf_in + 1 == - OPT_BUF_SIZ ? 0 : opt_buf_in + 1; + fetch_data(buf+ + BLOCKSIZE*buf_in, + BLOCKSIZE); + read_count--; + + DEBUG((DEBUG_REQUEST, + "S_DATA; ---I've read data- " + "read_count: %d", + read_count)); + DEBUG((DEBUG_REQUEST, + "next_bn:%d buf_in:%d " + "buf_out:%d buf_bn:%d", + next_bn, + buf_in, + buf_out, + buf_bn[buf_in])); + + buf_bn[buf_in] = next_bn++; + if (buf_out == NOBUF) + buf_out = buf_in; + buf_in = buf_in + 1 == + N_BUFS ? 0 : buf_in + 1; } - if (!opt_transfer_is_active) { + if (!transfer_is_active) { while (CURRENT_VALID) { - opt_transfer(); + transfer(); if (CURRENT -> nr_sectors == 0) end_request(1); else @@ -922,442 +1275,663 @@ } if (CURRENT_VALID - && (CURRENT -> sector / 4 < opt_next_bn || + && (CURRENT -> sector / 4 < next_bn || CURRENT -> sector / 4 > - opt_next_bn + OPT_BUF_SIZ)) { - opt_state = OPT_S_STOP; - loop_ctl = 1; + next_bn + N_BUFS)) { + state = S_STOP; + loop_again = 1; break; } - optTimeout = READ_TIMEOUT; - if (opt_read_count == 0) { - opt_state = OPT_S_STOP; - loop_ctl = 1; + timeout = READ_TIMEOUT; + if (read_count == 0) { + state = S_STOP; + loop_again = 1; break; } } break; - case OPT_S_STOP: - if (opt_read_count != 0) + case S_STOP: + if (read_count != 0) printk("optcd: discard data=%x frames\n", - opt_read_count); - while (opt_read_count != 0) { - optFlushData(); - opt_read_count--; - } - if (optSendCmd(COMDRVST)) + read_count); + flush_data(); + if (send_cmd(COMDRVST)) return; - opt_state = OPT_S_STOPPING; - optTimeout = 1000; + state = S_STOPPING; + timeout = STOP_TIMEOUT; break; - case OPT_S_STOPPING: - if ((st = optStatus()) < 0 && optTimeout) + case S_STOPPING: + status = fetch_status(); + if (status < 0 && timeout) break; - if ((st != -1) && (st & ST_DSK_CHG)) { - optDiskChanged = 1; - optTocUpToDate = 0; + if ((status >= 0) && (status & ST_DSK_CHG)) { + toc_uptodate = 0; opt_invalidate_buffers(); } if (CURRENT_VALID) { - if (st != -1) { - opt_state = OPT_S_READ; - loop_ctl = 1; + if (status >= 0) { + state = S_READ; + loop_again = 1; skip = 1; break; } else { - opt_state = OPT_S_START; - optTimeout = 1; + state = S_START; + timeout = 1; } } else { - opt_state = OPT_S_IDLE; + state = S_IDLE; return; } break; default: - printk("optcd: invalid state %d\n", opt_state); + printk("optcd: invalid state %d\n", state); return; } /* case */ } /* while */ - if (!optTimeout--) { - printk("optcd: timeout in state %d\n", opt_state); - opt_state = OPT_S_STOP; - if (optCmd(COMSTOP) < 0) + if (!timeout--) { + printk("optcd: timeout in state %d\n", state); + state = S_STOP; + if (exec_cmd(COMSTOP) < 0) return; } - SET_TIMER(opt_poll, 1); + SET_TIMER(poll, HZ/100); } -static void do_optcd_request(void) { -#ifdef DEBUG_REQUEST - printk("optcd: do_optcd_request(%ld+%ld)\n", - CURRENT -> sector, CURRENT -> nr_sectors); -#endif - opt_transfer_is_active = 1; +static void do_optcd_request(void) +{ + DEBUG((DEBUG_REQUEST, "do_optcd_request(%ld+%ld)", + CURRENT -> sector, CURRENT -> nr_sectors)); + + if (disk_info.audio) { + printk("optcd: Error: tried to mount an Audio CD\n"); + end_request(0); + return; + } + + transfer_is_active = 1; while (CURRENT_VALID) { if (CURRENT->bh) { if (!buffer_locked(CURRENT->bh)) panic(DEVICE_NAME ": block not locked"); } - opt_transfer(); /* First try to transfer block from buffers */ + transfer(); /* First try to transfer block from buffers */ if (CURRENT -> nr_sectors == 0) { end_request(1); } else { /* Want to read a block not in buffer */ - opt_buf_out = OPT_NOBUF; - if (opt_state == OPT_S_IDLE) { - /* Should this block the request queue?? */ - if (optUpdateToc() < 0) { + buf_out = NOBUF; + if (state == S_IDLE) { + /* %% Should this block the request queue?? */ + if (update_toc() < 0) { while (CURRENT_VALID) end_request(0); break; } /* Start state machine */ - opt_state = OPT_S_START; - optTries = 5; - SET_TIMER(opt_poll, 1); /* why not start right away?? */ + state = S_START; + tries = 5; + /* %% why not start right away?? */ + SET_TIMER(poll, HZ/100); } break; } } - opt_transfer_is_active = 0; -#ifdef DEBUG_REQUEST - printk("opt_next_bn:%d opt_buf_in:%d opt_buf_out:%d opt_buf_bn:%d\n", - opt_next_bn, opt_buf_in, opt_buf_out, opt_buf_bn[opt_buf_in]); - printk("optcd: do_optcd_request ends\n"); -#endif + transfer_is_active = 0; + + DEBUG((DEBUG_REQUEST, "next_bn:%d buf_in:%d buf_out:%d buf_bn:%d", + next_bn, buf_in, buf_out, buf_bn[buf_in])); + DEBUG((DEBUG_REQUEST, "do_optcd_request ends")); } + +/* IOCTLs */ -/* VFS calls */ +static char auto_eject = 0; -static int opt_ioctl(struct inode *ip, struct file *fp, - unsigned int cmd, unsigned long arg) { - static struct opt_Play_msf opt_Play; /* pause position */ - int err; -#ifdef DEBUG_VFS - printk("optcd: starting opt_ioctl, command 0x%x\n", cmd); -#endif - if (!ip) +static int cdrompause(void) +{ + int status; + + if (audio_status != CDROM_AUDIO_PLAY) return -EINVAL; - if (optGetStatus() < 0) + + status = exec_cmd(COMPAUSEON); + if (status < 0) { + DEBUG((DEBUG_VFS, "exec_cmd COMPAUSEON: %02x", -status)); return -EIO; - if ((err = optUpdateToc()) < 0) - return err; + } + audio_status = CDROM_AUDIO_PAUSED; + return 0; +} - switch (cmd) { - case CDROMPAUSE: { - struct opt_Toc qInfo; - if (optAudioStatus != CDROM_AUDIO_PLAY) - return -EINVAL; - if (optGetQChannelInfo(&qInfo) < 0) { - /* didn't get q channel info */ - optAudioStatus = CDROM_AUDIO_NO_STATUS; - return 0; - } - opt_Play.start = qInfo.diskTime; /* restart point */ - if (optCmd(COMPAUSEON) < 0) - return -EIO; - optAudioStatus = CDROM_AUDIO_PAUSED; - break; - } - case CDROMRESUME: - if (optAudioStatus != CDROM_AUDIO_PAUSED) - return -EINVAL; - if (optPlayCmd(COMPLAY, &opt_Play) < 0) { - optAudioStatus = CDROM_AUDIO_ERROR; - return -EIO; - } - optAudioStatus = CDROM_AUDIO_PLAY; - break; - case CDROMPLAYMSF: { - int st; - struct cdrom_msf msf; - - if ((st = verify_area(VERIFY_READ, (void *) arg, sizeof msf))) - return st; - memcpy_fromfs(&msf, (void *) arg, sizeof msf); - opt_Play.start.min = bin2bcd(msf.cdmsf_min0); - opt_Play.start.sec = bin2bcd(msf.cdmsf_sec0); - opt_Play.start.frame = bin2bcd(msf.cdmsf_frame0); - opt_Play.end.min = bin2bcd(msf.cdmsf_min1); - opt_Play.end.sec = bin2bcd(msf.cdmsf_sec1); - opt_Play.end.frame = bin2bcd(msf.cdmsf_frame1); - if (optPlayCmd(COMPLAY, &opt_Play) < 0) { - optAudioStatus = CDROM_AUDIO_ERROR; - return -EIO; - } - optAudioStatus = CDROM_AUDIO_PLAY; - break; +static int cdromresume(void) +{ + int status; + + if (audio_status != CDROM_AUDIO_PAUSED) + return -EINVAL; + + status = exec_cmd(COMPAUSEOFF); + if (status < 0) { + DEBUG((DEBUG_VFS, "exec_cmd COMPAUSEOFF: %02x", -status)); + audio_status = CDROM_AUDIO_ERROR; + return -EIO; } - case CDROMPLAYTRKIND: { - int st; - struct cdrom_ti ti; - - if ((st = verify_area(VERIFY_READ, (void *) arg, sizeof ti))) - return st; - memcpy_fromfs(&ti, (void *) arg, sizeof ti); - if (ti.cdti_trk0 < DiskInfo.first - || ti.cdti_trk0 > DiskInfo.last - || ti.cdti_trk1 < ti.cdti_trk0) - return -EINVAL; - if (ti.cdti_trk1 > DiskInfo.last) - ti.cdti_trk1 = DiskInfo.last; - opt_Play.start = Toc[ti.cdti_trk0].diskTime; - opt_Play.end = Toc[ti.cdti_trk1 + 1].diskTime; -#ifdef DEBUG_VFS - printk("optcd: play %02x:%02x.%02x to %02x:%02x.%02x\n", - opt_Play.start.min, - opt_Play.start.sec, - opt_Play.start.frame, - opt_Play.end.min, - opt_Play.end.sec, - opt_Play.end.frame); -#endif - if (optPlayCmd(COMPLAY, &opt_Play) < 0) { - optAudioStatus = CDROM_AUDIO_ERROR; - return -EIO; - } - optAudioStatus = CDROM_AUDIO_PLAY; - break; + audio_status = CDROM_AUDIO_PLAY; + return 0; +} + + +static int cdromplaymsf(unsigned long arg) +{ + int status; + struct cdrom_msf msf; + + status = verify_area(VERIFY_READ, (void *) arg, sizeof msf); + if (status) + return status; + memcpy_fromfs(&msf, (void *) arg, sizeof msf); + + bin2bcd(&msf); + status = exec_long_cmd(COMPLAY, &msf); + if (status < 0) { + DEBUG((DEBUG_VFS, "exec_long_cmd COMPLAY: %02x", -status)); + audio_status = CDROM_AUDIO_ERROR; + return -EIO; } - case CDROMREADTOCHDR: { /* Read the table of contents header. */ - int st; - struct cdrom_tochdr tocHdr; - - if ((st = verify_area(VERIFY_WRITE,(void *)arg,sizeof tocHdr))) - return st; - if (!optTocUpToDate) - optGetDiskInfo(); - tocHdr.cdth_trk0 = DiskInfo.first; - tocHdr.cdth_trk1 = DiskInfo.last; - memcpy_tofs((void *) arg, &tocHdr, sizeof tocHdr); - break; - } - case CDROMREADTOCENTRY: { /* Read a table of contents entry. */ - int st; - struct cdrom_tocentry entry; - struct opt_Toc *tocPtr; - - if ((st = verify_area(VERIFY_READ, (void *) arg, sizeof entry))) - return st; - if ((st = verify_area(VERIFY_WRITE, (void *) arg, sizeof entry))) - return st; - memcpy_fromfs(&entry, (void *) arg, sizeof entry); - if (!optTocUpToDate) - optGetDiskInfo(); - if (entry.cdte_track == CDROM_LEADOUT) - tocPtr = &Toc[DiskInfo.last + 1]; - else if (entry.cdte_track > DiskInfo.last - || entry.cdte_track < DiskInfo.first) - return -EINVAL; - else - tocPtr = &Toc[entry.cdte_track]; - entry.cdte_adr = tocPtr -> ctrl_addr; - entry.cdte_ctrl = tocPtr -> ctrl_addr >> 4; - switch (entry.cdte_format) { - case CDROM_LBA: - entry.cdte_addr.lba = msf2hsg(&tocPtr -> diskTime); - break; - case CDROM_MSF: - entry.cdte_addr.msf.minute = - bcd2bin(tocPtr -> diskTime.min); - entry.cdte_addr.msf.second = - bcd2bin(tocPtr -> diskTime.sec); - entry.cdte_addr.msf.frame = - bcd2bin(tocPtr -> diskTime.frame); - break; - default: - return -EINVAL; - } - memcpy_tofs((void *) arg, &entry, sizeof entry); - break; + + audio_status = CDROM_AUDIO_PLAY; + return 0; +} + + +static int cdromplaytrkind(unsigned long arg) +{ + int status; + struct cdrom_ti ti; + struct cdrom_msf msf; + + status = verify_area(VERIFY_READ, (void *) arg, sizeof ti); + if (status) + return status; + memcpy_fromfs(&ti, (void *) arg, sizeof ti); + + if (ti.cdti_trk0 < disk_info.first + || ti.cdti_trk0 > disk_info.last + || ti.cdti_trk1 < ti.cdti_trk0) + return -EINVAL; + if (ti.cdti_trk1 > disk_info.last) + ti.cdti_trk1 = disk_info.last; + + msf.cdmsf_min0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.minute; + msf.cdmsf_sec0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.second; + msf.cdmsf_frame0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.frame; + msf.cdmsf_min1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.minute; + msf.cdmsf_sec1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.second; + msf.cdmsf_frame1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.frame; + + DEBUG((DEBUG_VFS, "play %02d:%02d.%02d to %02d:%02d.%02d", + msf.cdmsf_min0, + msf.cdmsf_sec0, + msf.cdmsf_frame0, + msf.cdmsf_min1, + msf.cdmsf_sec1, + msf.cdmsf_frame1)); + + bin2bcd(&msf); + status = exec_long_cmd(COMPLAY, &msf); + if (status < 0) { + DEBUG((DEBUG_VFS, "exec_long_cmd COMPLAY: %02x", -status)); + audio_status = CDROM_AUDIO_ERROR; + return -EIO; } - case CDROMSTOP: - optCmd(COMSTOP); - optAudioStatus = CDROM_AUDIO_NO_STATUS; - break; - case CDROMSTART: - optCmd(COMCLOSE); /* What else can we do? */ - break; - case CDROMEJECT: - optCmd(COMUNLOCK); - optCmd(COMOPEN); - break; - case CDROMVOLCTRL: { - int st; - struct cdrom_volctrl volctrl; - - if ((st = verify_area(VERIFY_READ, (void *) arg, - sizeof(volctrl)))) - return st; - memcpy_fromfs(&volctrl, (char *) arg, sizeof(volctrl)); - opt_Play.start.min = 0x10; - opt_Play.start.sec = 0x32; - opt_Play.start.frame = volctrl.channel0; - opt_Play.end.min = volctrl.channel1; - opt_Play.end.sec = volctrl.channel2; - opt_Play.end.frame = volctrl.channel3; - if (optPlayCmd(COMCHCTRL, &opt_Play) < 0) - return -EIO; - break; + + audio_status = CDROM_AUDIO_PLAY; + return 0; +} + + +static int cdromreadtochdr(unsigned long arg) +{ + int status; + struct cdrom_tochdr tochdr; + + status = verify_area(VERIFY_WRITE, (void *) arg, sizeof tochdr); + if (status) + return status; + + tochdr.cdth_trk0 = disk_info.first; + tochdr.cdth_trk1 = disk_info.last; + + memcpy_tofs((void *) arg, &tochdr, sizeof tochdr); + return 0; +} + + +static int cdromreadtocentry(unsigned long arg) +{ + int status; + struct cdrom_tocentry entry; + struct cdrom_subchnl *tocptr; + + status = verify_area(VERIFY_READ, (void *) arg, sizeof entry); + if (status) + return status; + status = verify_area(VERIFY_WRITE, (void *) arg, sizeof entry); + if (status) + return status; + memcpy_fromfs(&entry, (void *) arg, sizeof entry); + + if (entry.cdte_track == CDROM_LEADOUT) + tocptr = &toc[disk_info.last + 1]; + else if (entry.cdte_track > disk_info.last + || entry.cdte_track < disk_info.first) + return -EINVAL; + else + tocptr = &toc[entry.cdte_track]; + + entry.cdte_adr = tocptr->cdsc_adr; + entry.cdte_ctrl = tocptr->cdsc_ctrl; + entry.cdte_addr.msf.minute = tocptr->cdsc_absaddr.msf.minute; + entry.cdte_addr.msf.second = tocptr->cdsc_absaddr.msf.second; + entry.cdte_addr.msf.frame = tocptr->cdsc_absaddr.msf.frame; + /* %% What should go into entry.cdte_datamode? */ + + if (entry.cdte_format == CDROM_LBA) + msf2lba((union cd_addr *)/*%%*/&entry.cdte_addr); + else if (entry.cdte_format != CDROM_MSF) + return -EINVAL; + + memcpy_tofs((void *) arg, &entry, sizeof entry); + return 0; +} + + +static int cdromvolctrl(unsigned long arg) +{ + int status; + struct cdrom_volctrl volctrl; + struct cdrom_msf msf; + + status = verify_area(VERIFY_READ, (void *) arg, sizeof volctrl); + if (status) + return status; + memcpy_fromfs(&volctrl, (char *) arg, sizeof volctrl); + + msf.cdmsf_min0 = 0x10; + msf.cdmsf_sec0 = 0x32; + msf.cdmsf_frame0 = volctrl.channel0; + msf.cdmsf_min1 = volctrl.channel1; + msf.cdmsf_sec1 = volctrl.channel2; + msf.cdmsf_frame1 = volctrl.channel3; + + status = exec_long_cmd(COMCHCTRL, &msf); + if (status < 0) { + DEBUG((DEBUG_VFS, "exec_long_cmd COMCHCTRL: %02x", -status)); + return -EIO; } - case CDROMSUBCHNL: { /* Get subchannel info */ - int st; - struct cdrom_subchnl subchnl; - struct opt_Toc qInfo; - - if ((st = verify_area(VERIFY_READ, - (void *) arg, sizeof subchnl))) - return st; - if ((st = verify_area(VERIFY_WRITE, - (void *) arg, sizeof subchnl))) - return st; - memcpy_fromfs(&subchnl, (void *) arg, sizeof subchnl); - if (optGetQChannelInfo(&qInfo) < 0) - return -EIO; - subchnl.cdsc_audiostatus = optAudioStatus; - subchnl.cdsc_adr = qInfo.ctrl_addr; - subchnl.cdsc_ctrl = qInfo.ctrl_addr >> 4; - subchnl.cdsc_trk = bcd2bin(qInfo.track); - subchnl.cdsc_ind = bcd2bin(qInfo.pointIndex); - switch (subchnl.cdsc_format) { - case CDROM_LBA: - subchnl.cdsc_absaddr.lba = msf2hsg(&qInfo.diskTime); - subchnl.cdsc_reladdr.lba = msf2hsg(&qInfo.trackTime); - break; - case CDROM_MSF: - subchnl.cdsc_absaddr.msf.minute = - bcd2bin(qInfo.diskTime.min); - subchnl.cdsc_absaddr.msf.second = - bcd2bin(qInfo.diskTime.sec); - subchnl.cdsc_absaddr.msf.frame = - bcd2bin(qInfo.diskTime.frame); - subchnl.cdsc_reladdr.msf.minute = - bcd2bin(qInfo.trackTime.min); - subchnl.cdsc_reladdr.msf.second = - bcd2bin(qInfo.trackTime.sec); - subchnl.cdsc_reladdr.msf.frame = - bcd2bin(qInfo.trackTime.frame); - break; - default: - return -EINVAL; - } - memcpy_tofs((void *) arg, &subchnl, sizeof subchnl); - break; + return 0; +} + + +static int cdromsubchnl(unsigned long arg) +{ + int status; + struct cdrom_subchnl subchnl; + + status = verify_area(VERIFY_READ, (void *) arg, sizeof subchnl); + if (status) + return status; + status = verify_area(VERIFY_WRITE, (void *) arg, sizeof subchnl); + if (status) + return status; + memcpy_fromfs(&subchnl, (void *) arg, sizeof subchnl); + + if (subchnl.cdsc_format != CDROM_LBA + && subchnl.cdsc_format != CDROM_MSF) + return -EINVAL; + + status = get_q_channel(&subchnl); + if (status < 0) { + DEBUG((DEBUG_VFS, "get_q_channel: %02x", -status)); + return -EIO; } - case CDROMREADMODE1: { - int st; - struct cdrom_msf msf; - char buf[OPT_BLOCKSIZE]; - - if ((st = verify_area(VERIFY_READ, (void *) arg, sizeof msf))) - return st; - if ((st = verify_area(VERIFY_WRITE,(void *)arg,OPT_BLOCKSIZE))) - return st; - memcpy_fromfs(&msf, (void *) arg, sizeof msf); - opt_Play.start.min = bin2bcd(msf.cdmsf_min0); - opt_Play.start.sec = bin2bcd(msf.cdmsf_sec0); - opt_Play.start.frame = bin2bcd(msf.cdmsf_frame0); - opt_Play.end.min = 0; - opt_Play.end.sec = 0; - opt_Play.end.frame = 1; /* read only one frame */ - st = optReadCmd(COMREAD, &opt_Play); -#ifdef DEBUG_VFS - printk("optcd: COMREAD status 0x%x\n", st); -#endif - sleep_dten_low(); /* error checking here?? */ - optReadData(buf, OPT_BLOCKSIZE); - memcpy_tofs((void *) arg, &buf, OPT_BLOCKSIZE); - break; + + memcpy_tofs((void *) arg, &subchnl, sizeof subchnl); + return 0; +} + + +static int cdromread(unsigned long arg, int blocksize, int cmd) +{ + int status; + struct cdrom_msf msf; + char buf[BLOCKSIZE_ALL]; + + status = verify_area(VERIFY_READ, (void *) arg, sizeof msf); + if (status) + return status; + status = verify_area(VERIFY_WRITE, (void *) arg, blocksize); + if (status) + return status; + memcpy_fromfs(&msf, (void *) arg, sizeof msf); + + bin2bcd(&msf); + msf.cdmsf_min1 = 0; + msf.cdmsf_sec1 = 0; + msf.cdmsf_frame1 = 1; /* read only one frame */ + status = exec_read_cmd(cmd, &msf); + + DEBUG((DEBUG_VFS, "read cmd status 0x%x", status)); + + if (!sleep_flag_low(FL_DTEN, SLEEP_TIMEOUT)) + return -EIO; + fetch_data(buf, blocksize); + + memcpy_tofs((void *) arg, &buf, blocksize); + return 0; +} + + +static int cdromseek(unsigned long arg) +{ + int status; + struct cdrom_msf msf; + + status = verify_area(VERIFY_READ, (void *) arg, sizeof msf); + if (status) + return status; + memcpy_fromfs(&msf, (void *) arg, sizeof msf); + + bin2bcd(&msf); + status = exec_seek_cmd(COMSEEK, &msf); + + DEBUG((DEBUG_VFS, "COMSEEK status 0x%x", status)); + + if (status < 0) + return -EIO; + return 0; +} + + +#ifdef MULTISESSION +static int cdrommultisession(unsigned long arg) +{ + int status; + struct cdrom_multisession ms; + + status = verify_area(VERIFY_READ, (void*) arg, sizeof ms); + if (status) + return status; + status = verify_area(VERIFY_WRITE, (void*) arg, sizeof ms); + if (status) + return status; + memcpy_fromfs(&ms, (void*) arg, sizeof ms); + + ms.addr.msf.minute = disk_info.last_session.minute; + ms.addr.msf.second = disk_info.last_session.second; + ms.addr.msf.frame = disk_info.last_session.frame; + + if (ms.addr_format != CDROM_LBA + && ms.addr_format != CDROM_MSF) + return -EINVAL; + if (ms.addr_format == CDROM_LBA) + msf2lba((union cd_addr *)/*%%*/&ms.addr); + + ms.xa_flag = disk_info.xa; + + memcpy_tofs((void*) arg, &ms, + sizeof(struct cdrom_multisession)); + +#if DEBUG_MULTIS + if (ms.addr_format == CDROM_MSF) + printk("optcd: multisession xa:%d, msf:%02d:%02d.%02d\n", + ms.xa_flag, + ms.addr.msf.minute, + ms.addr.msf.second, + ms.addr.msf.frame); + else + printk("optcd: multisession %d, lba:0x%08x [%02d:%02d.%02d])\n", + ms.xa_flag, + ms.addr.lba, + disk_info.last_session.minute, + disk_info.last_session.second, + disk_info.last_session.frame); +#endif DEBUG_MULTIS + + return 0; +} +#endif MULTISESSION + + +static int cdromreset(void) +{ + if (state != S_IDLE) { + error = 1; + tries = 0; } - case CDROMMULTISESSION: - return -EINVAL; /* unluckily, not implemented yet */ - default: + toc_uptodate = 0; + opt_invalidate_buffers(); + audio_status = CDROM_AUDIO_NO_STATUS; + + if (!reset_drive()) + return -EIO; + return 0; +} + +/* VFS calls */ + + +static int opt_ioctl(struct inode *ip, struct file *fp, + unsigned int cmd, unsigned long arg) +{ + int err; + + DEBUG((DEBUG_VFS, "starting opt_ioctl")); + + if (!ip) return -EINVAL; + + if (cmd == CDROMRESET) + return cdromreset(); + + if (state != S_IDLE) + return -EBUSY; + + err = drive_status(); + if (err < 0) { + DEBUG((DEBUG_VFS, "drive_status: %02x", -err)); + return -EIO; + } + err = update_toc(); + if (err < 0) { + DEBUG((DEBUG_VFS, "update_toc: %02x", -err)); + return -EIO; } -#ifdef DEBUG_VFS - printk("optcd: exiting opt_ioctl\n"); + + DEBUG((DEBUG_VFS, "ioctl cmd 0x%x", cmd)); + + switch (cmd) { + case CDROMPAUSE: return cdrompause(); + case CDROMRESUME: return cdromresume(); + case CDROMPLAYMSF: return cdromplaymsf(arg); + case CDROMPLAYTRKIND: return cdromplaytrkind(arg); + case CDROMREADTOCHDR: return cdromreadtochdr(arg); + case CDROMREADTOCENTRY: return cdromreadtocentry(arg); + + case CDROMSTOP: err = exec_cmd(COMSTOP); + if (err < 0) { + DEBUG((DEBUG_VFS, + "exec_cmd COMSTOP: %02x", + -err)); + return -EIO; + } + audio_status = CDROM_AUDIO_NO_STATUS; + break; + case CDROMSTART: err = exec_cmd(COMCLOSE); /* What else? */ + if (err < 0) { + DEBUG((DEBUG_VFS, + "exec_cmd COMCLOSE: %02x", + -err)); + return -EIO; + } + break; + case CDROMEJECT: err = exec_cmd(COMUNLOCK); + if (err < 0) { + DEBUG((DEBUG_VFS, + "exec_cmd COMUNLOCK: %02x", + -err)); + return -EIO; + } + err = exec_cmd(COMOPEN); + if (err < 0) { + DEBUG((DEBUG_VFS, + "exec_cmd COMOPEN: %02x", + -err)); + return -EIO; + } + break; + + case CDROMVOLCTRL: return cdromvolctrl(arg); + case CDROMSUBCHNL: return cdromsubchnl(arg); + + case CDROMREADAUDIO: return -EINVAL; /* not implemented */ + case CDROMEJECT_SW: auto_eject = (char) arg; + break; + +#ifdef MULTISESSION + case CDROMMULTISESSION: return cdrommultisession(arg); #endif + + case CDROM_GET_UPC: return -EINVAL; /* not implemented */ + case CDROMVOLREAD: return -EINVAL; /* not implemented */ + + case CDROMREADRAW: + return cdromread(arg, BLOCKSIZE_RAW, COMREADRAW); + case CDROMREADCOOKED: + return cdromread(arg, BLOCKSIZE, COMREAD); + case CDROMSEEK: return cdromseek(arg); + case CDROMPLAYBLK: return -EINVAL; /* not implemented */ + default: return -EINVAL; + } return 0; } -static int optPresent = 0; -static int opt_open_count = 0; + +static int open_count = 0; /* Open device special file; check that a disk is in. */ -static int opt_open(struct inode *ip, struct file *fp) { -#ifdef DEBUG_VFS - printk("optcd: starting opt_open\n"); -#endif - if (!optPresent) - return -ENXIO; /* no hardware */ - if (!opt_open_count && opt_state == OPT_S_IDLE) { - int st; +static int opt_open(struct inode *ip, struct file *fp) +{ + DEBUG((DEBUG_VFS, "starting opt_open")); + + if (!open_count++ && state == S_IDLE) { + int status; + opt_invalidate_buffers(); - if ((st = optGetStatus()) < 0) + status = drive_status(); + if (status < 0) { + DEBUG((DEBUG_VFS, "drive_status: %02x", -status)); return -EIO; - if (st & ST_DOOR_OPEN) { - optCmd(COMCLOSE); /* close door */ - if ((st = optGetStatus()) < 0) /* try again */ + } + DEBUG((DEBUG_VFS, "status: %02x", status)); + if (status & ST_DOOR_OPEN) { + status = exec_cmd(COMCLOSE); /* close door */ + if (status < 0) { + DEBUG((DEBUG_VFS, + "exec_cmd COMCLOSE: %02x", -status)); + } + status = drive_status(); /* try again */ + if (status < 0) { + DEBUG((DEBUG_VFS, + "drive_status: %02x", -status)); return -EIO; + } + DEBUG((DEBUG_VFS, "status: %02x", status)); } - if (st & (ST_DOOR_OPEN|ST_DRVERR)) { + if (status & (ST_DOOR_OPEN|ST_DRVERR)) { printk("optcd: no disk or door open\n"); return -EIO; } - if (optUpdateToc() < 0) + status = exec_cmd(COMLOCK); /* Lock door */ + if (status < 0) { + DEBUG((DEBUG_VFS, "exec_cmd COMLOCK: %02x", -status)); + } + status = update_toc(); /* Read table of contents */ + if (status < 0) { + DEBUG((DEBUG_VFS, "update_toc: %02x", -status)); return -EIO; + } } - opt_open_count++; MOD_INC_USE_COUNT; - optCmd(COMLOCK); /* Lock door */ -#ifdef DEBUG_VFS - printk("optcd: exiting opt_open\n"); -#endif + + DEBUG((DEBUG_VFS, "exiting opt_open")); + return 0; } + /* Release device special file; flush all blocks from the buffer cache */ -static void opt_release(struct inode *ip, struct file *fp) { -#ifdef DEBUG_VFS - printk("optcd: executing opt_release\n"); - printk("inode: %p, inode -> i_rdev: 0x%x, file: %p\n", - ip, ip -> i_rdev, fp); -#endif - if (!--opt_open_count) { +static void opt_release(struct inode *ip, struct file *fp) +{ + int status; + + DEBUG((DEBUG_VFS, "executing opt_release")); + DEBUG((DEBUG_VFS, "inode: %p, inode -> i_rdev: 0x%x, file: %p\n", + ip, ip -> i_rdev, fp)); + + if (!--open_count) { opt_invalidate_buffers(); sync_dev(ip -> i_rdev); invalidate_buffers(ip -> i_rdev); + status = exec_cmd(COMUNLOCK); /* Unlock door */ + if (status < 0) { + DEBUG((DEBUG_VFS, "exec_cmd COMUNLOCK: %02x", -status)); + } + if (auto_eject) { + status = exec_cmd(COMOPEN); + DEBUG((DEBUG_VFS, "exec_cmd COMOPEN: %02x", -status)); + } CLEAR_TIMER; - optCmd(COMUNLOCK); /* Unlock door */ } MOD_DEC_USE_COUNT; } + +/* Driver initialisation */ -/* Initialisation */ - -static int version_ok(void) { +/* Returns 1 if a drive is detected with a version string + starting with "DOLPHIN". Otherwise 0. */ +static int version_ok(void) +{ char devname[100]; - int count, i, ch; + int count, i, ch, status; - if (optCmd(COMVERSION) < 0) + status = exec_cmd(COMVERSION); + if (status < 0) { + DEBUG((DEBUG_VFS, "exec_cmd COMVERSION: %02x", -status)); return 0; - if ((count = optGetData()) < 0) + } + if ((count = get_data(1)) < 0) { + DEBUG((DEBUG_VFS, "get_data(1): %02x", -count)); return 0; + } for (i = 0, ch = -1; count > 0; count--) { - if ((ch = optGetData()) < 0) + if ((ch = get_data(1)) < 0) { + DEBUG((DEBUG_VFS, "get_data(1): %02x", -ch)); break; + } if (i < 99) devname[i++] = ch; } devname[i] = '\0'; if (ch < 0) return 0; + printk("optcd: Device %s detected\n", devname); return ((devname[0] == 'D') && (devname[1] == 'O') @@ -1386,17 +1960,57 @@ }; +/* Flag indicates if ISP16 detection and initialisation should be skipped */ +#define skip_isp16_init noisp16 /* Needed for the modutils. */ +static int skip_isp16_init = 0; + /* Get kernel parameter when used as a kernel driver */ -void optcd_setup(char *str, int *ints) { +void optcd_setup(char *str, int *ints) +{ if (ints[0] > 0) optcd_port = ints[1]; + if (!strcmp(str ,"noisp16")) + skip_isp16_init = 1; } -/* - * Test for presence of drive and initialize it. Called at boot time. - */ -int optcd_init(void) { +#ifdef PROBE_ISP16 +/* If ISP16 I/O ports not already reserved, probe for an ISP16 interface card, + and enable SONY mode with no interrupts and no DMA. + (As far as I know, all Optics 8000 AT drives come with a SONY interface. + Interrupts and DMA are not supported). + Returns false only if ISP16 detected but couldn't be initialised. */ +static int probe_isp16(void) +{ + if (skip_isp16_init) + return 1; + + if (check_region(ISP16_DRIVE_SET_PORT, 5)) + return 1; + + if (isp16_detect() < 0 ) { + printk( "No ISP16 cdrom interface found.\n" ); + return 1; + } + + isp16_sound_config(); /* Enable playing through speakers */ + + printk( "ISP16 cdrom interface detected.\n"); + if (isp16_cdi_config(optcd_port, ISP16_SONY, 0, 0) < 0) { + printk( "ISP16 configure error.\n" ); + return 0; + } + return 1; +} +#endif PROBE_ISP16 + + +/* Test for presence of drive and initialize it. Called at boot time + or during module initialisation. */ +int optcd_init(void) +{ + int status; + if (optcd_port <= 0) { printk("optcd: no Optics Storage CDROM Initialization\n"); return -EIO; @@ -1407,29 +2021,12 @@ return -EIO; } - if (!check_region(ISP16_DRIVE_SET_PORT, 5)) { - /* If someone else has'nt already reserved these ports, - probe for an ISP16 interface card, and enable SONY mode - with no interrupts and no DMA. (As far as I know, all optics - drives come with a SONY interface.) */ - if ( (isp16_type=isp16_detect()) < 0 ) - printk( "No ISP16 cdrom interface found.\n" ); - else { - u_char expected_drive; - - printk( "ISP16 cdrom interface (%s optional IDE) detected.\n", - (isp16_type==2)?"with":"without" ); - - expected_drive = (isp16_type?ISP16_SANYO1:ISP16_SANYO0); - - if ( isp16_config( optcd_port, ISP16_SONY, 0, 0 ) < 0 ) { - printk( "ISP16 cdrom interface has not been properly configured.\n" ); - return -EIO; - } - } - } +#ifdef PROBE_ISP16 + if (!probe_isp16()) + return -EIO; +#endif - if (!optResetDrive()) { + if (!reset_drive()) { printk("optcd: drive at 0x%x not ready\n", optcd_port); return -EIO; } @@ -1437,8 +2034,10 @@ printk("optcd: unknown drive detected; aborting\n"); return -EIO; } - if (optCmd(COMINITDOUBLE) < 0) { + status = exec_cmd(COMINITDOUBLE); + if (status < 0) { printk("optcd: cannot init double speed mode\n"); + DEBUG((DEBUG_VFS, "exec_cmd COMINITDOUBLE: %02x", -status)); return -EIO; } if (register_blkdev(MAJOR_NR, "optcd", &opt_fops) != 0) @@ -1446,22 +2045,26 @@ printk("optcd: unable to get major %d\n", MAJOR_NR); return -EIO; } + blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; read_ahead[MAJOR_NR] = 4; request_region(optcd_port, 4, "optcd"); - optPresent = 1; - printk("optcd: 8000 AT CDROM at 0x%x\n", optcd_port); + + printk("optcd: DOLPHIN 8000 AT CDROM at 0x%x\n", optcd_port); return 0; } + #ifdef MODULE int init_module(void) { return optcd_init(); } -void cleanup_module(void) { - if ((unregister_blkdev(MAJOR_NR, "optcd") == -EINVAL)) { + +void cleanup_module(void) +{ + if (unregister_blkdev(MAJOR_NR, "optcd") == -EINVAL) { printk("optcd: what's that: can't unregister\n"); return; } @@ -1469,191 +2072,3 @@ printk("optcd: module released.\n"); } #endif MODULE - - -/* - * -- ISP16 detection and configuration - * - * Copyright (c) 1995, Eric van der Maarel - * - * Version 0.5 - * - * Detect cdrom interface on ISP16 soundcard. - * Configure cdrom interface. - * - * Algorithm for the card with no IDE support option taken - * from the CDSETUP.SYS driver for MSDOS, - * by OPTi Computers, version 2.03. - * Algorithm for the IDE supporting ISP16 as communicated - * to me by Vadim Model and Leo Spiekman. - * - * Use, modifification or redistribution of this software is - * allowed under the terms of the GPL. - * - */ - - -#define ISP16_IN(p) (outb(isp16_ctrl,ISP16_CTRL_PORT), inb(p)) -#define ISP16_OUT(p,b) (outb(isp16_ctrl,ISP16_CTRL_PORT), outb(b,p)) - -static short -isp16_detect(void) -{ - - if ( !( isp16_with_ide__detect() < 0 ) ) - return(2); - else - return( isp16_no_ide__detect() ); -} - -static short -isp16_no_ide__detect(void) -{ - u_char ctrl; - u_char enable_cdrom; - u_char io; - short i = -1; - - isp16_ctrl = ISP16_NO_IDE__CTRL; - isp16_enable_cdrom_port = ISP16_NO_IDE__ENABLE_CDROM_PORT; - - /* read' and write' are a special read and write, respectively */ - - /* read' ISP16_CTRL_PORT, clear last two bits and write' back the result */ - ctrl = ISP16_IN( ISP16_CTRL_PORT ) & 0xFC; - ISP16_OUT( ISP16_CTRL_PORT, ctrl ); - - /* read' 3,4 and 5-bit from the cdrom enable port */ - enable_cdrom = ISP16_IN( ISP16_NO_IDE__ENABLE_CDROM_PORT ) & 0x38; - - if ( !(enable_cdrom & 0x20) ) { /* 5-bit not set */ - /* read' last 2 bits of ISP16_IO_SET_PORT */ - io = ISP16_IN( ISP16_IO_SET_PORT ) & 0x03; - if ( ((io&0x01)<<1) == (io&0x02) ) { /* bits are the same */ - if ( io == 0 ) { /* ...the same and 0 */ - i = 0; - enable_cdrom |= 0x20; - } - else { /* ...the same and 1 */ /* my card, first time 'round */ - i = 1; - enable_cdrom |= 0x28; - } - ISP16_OUT( ISP16_NO_IDE__ENABLE_CDROM_PORT, enable_cdrom ); - } - else { /* bits are not the same */ - ISP16_OUT( ISP16_CTRL_PORT, ctrl ); - return(i); /* -> not detected: possibly incorrect conclusion */ - } - } - else if ( enable_cdrom == 0x20 ) - i = 0; - else if ( enable_cdrom == 0x28 ) /* my card, already initialised */ - i = 1; - - ISP16_OUT( ISP16_CTRL_PORT, ctrl ); - - return(i); -} - -static short -isp16_with_ide__detect(void) -{ - u_char ctrl; - u_char tmp; - - isp16_ctrl = ISP16_IDE__CTRL; - isp16_enable_cdrom_port = ISP16_IDE__ENABLE_CDROM_PORT; - - /* read' and write' are a special read and write, respectively */ - - /* read' ISP16_CTRL_PORT and save */ - ctrl = ISP16_IN( ISP16_CTRL_PORT ); - - /* write' zero to the ctrl port and get response */ - ISP16_OUT( ISP16_CTRL_PORT, 0 ); - tmp = ISP16_IN( ISP16_CTRL_PORT ); - - if ( tmp != 2 ) /* isp16 with ide option not detected */ - return(-1); - - /* restore ctrl port value */ - ISP16_OUT( ISP16_CTRL_PORT, ctrl ); - - return(2); -} - -static short -isp16_config( int base, u_char drive_type, int irq, int dma ) -{ - u_char base_code; - u_char irq_code; - u_char dma_code; - u_char i; - - if ( (drive_type == ISP16_MITSUMI) && (dma != 0) ) - printk( "Mitsumi cdrom drive has no dma support.\n" ); - - switch (base) { - case 0x340: base_code = ISP16_BASE_340; break; - case 0x330: base_code = ISP16_BASE_330; break; - case 0x360: base_code = ISP16_BASE_360; break; - case 0x320: base_code = ISP16_BASE_320; break; - default: - printk( "Base address 0x%03X not supported by cdrom interface on ISP16.\n", base ); - return(-1); - } - switch (irq) { - case 0: irq_code = ISP16_IRQ_X; break; /* disable irq */ - case 5: irq_code = ISP16_IRQ_5; - printk( "Irq 5 shouldn't be used by cdrom interface on ISP16," - " due to possible conflicts with the soundcard.\n"); - break; - case 7: irq_code = ISP16_IRQ_7; - printk( "Irq 7 shouldn't be used by cdrom interface on ISP16," - " due to possible conflicts with the soundcard.\n"); - break; - case 3: irq_code = ISP16_IRQ_3; break; - case 9: irq_code = ISP16_IRQ_9; break; - case 10: irq_code = ISP16_IRQ_10; break; - case 11: irq_code = ISP16_IRQ_11; break; - default: - printk( "Irq %d not supported by cdrom interface on ISP16.\n", irq ); - return(-1); - } - switch (dma) { - case 0: dma_code = ISP16_DMA_X; break; /* disable dma */ - case 1: printk( "Dma 1 cannot be used by cdrom interface on ISP16," - " due to conflict with the soundcard.\n"); - return(-1); break; - case 3: dma_code = ISP16_DMA_3; break; - case 5: dma_code = ISP16_DMA_5; break; - case 6: dma_code = ISP16_DMA_6; break; - case 7: dma_code = ISP16_DMA_7; break; - default: - printk( "Dma %d not supported by cdrom interface on ISP16.\n", dma ); - return(-1); - } - - if ( drive_type != ISP16_SONY && drive_type != ISP16_PANASONIC0 && - drive_type != ISP16_PANASONIC1 && drive_type != ISP16_SANYO0 && - drive_type != ISP16_SANYO1 && drive_type != ISP16_MITSUMI && - drive_type != ISP16_DRIVE_X ) { - printk( "Drive type (code 0x%02X) not supported by cdrom" - " interface on ISP16.\n", drive_type ); - return(-1); - } - - /* set type of interface */ - i = ISP16_IN(ISP16_DRIVE_SET_PORT) & ISP16_DRIVE_SET_MASK; /* clear some bits */ - ISP16_OUT( ISP16_DRIVE_SET_PORT, i|drive_type ); - - /* enable cdrom on interface with ide support */ - if ( isp16_type > 1 ) - ISP16_OUT( isp16_enable_cdrom_port, ISP16_ENABLE_CDROM ); - - /* set base address, irq and dma */ - i = ISP16_IN(ISP16_IO_SET_PORT) & ISP16_IO_SET_MASK; /* keep some bits */ - ISP16_OUT( ISP16_IO_SET_PORT, i|base_code|irq_code|dma_code ); - - return(0); -} diff -u --recursive --new-file v1.3.57/linux/drivers/cdrom/optcd_isp16.h linux/drivers/cdrom/optcd_isp16.h --- v1.3.57/linux/drivers/cdrom/optcd_isp16.h Thu Jan 1 02:00:00 1970 +++ linux/drivers/cdrom/optcd_isp16.h Thu Jan 18 06:22:13 1996 @@ -0,0 +1,337 @@ +/* linux/drivers/cdrom/optcd_isp16.h - ISP16 CDROM interface configuration + $Id: optcd_isp16.h,v 1.3 1996/01/15 18:43:11 root Exp root $ + + Extracts from linux/drivers/cdrom/sjcd.c + For copyrights see linux/drivers/cdrom/optcd.c +*/ + + +/* Some (Media)Magic */ +/* define types of drive the interface on an ISP16 card may be looking at */ +#define ISP16_DRIVE_X 0x00 +#define ISP16_SONY 0x02 +#define ISP16_PANASONIC0 0x02 +#define ISP16_SANYO0 0x02 +#define ISP16_MITSUMI 0x04 +#define ISP16_PANASONIC1 0x06 +#define ISP16_SANYO1 0x06 +#define ISP16_DRIVE_NOT_USED 0x08 /* not used */ +#define ISP16_DRIVE_SET_MASK 0xF1 /* don't change 0-bit or 4-7-bits*/ +/* ...for port */ +#define ISP16_DRIVE_SET_PORT 0xF8D +/* set io parameters */ +#define ISP16_BASE_340 0x00 +#define ISP16_BASE_330 0x40 +#define ISP16_BASE_360 0x80 +#define ISP16_BASE_320 0xC0 +#define ISP16_IRQ_X 0x00 +#define ISP16_IRQ_5 0x04 /* shouldn't be used due to soundcard conflicts */ +#define ISP16_IRQ_7 0x08 /* shouldn't be used due to soundcard conflicts */ +#define ISP16_IRQ_3 0x0C +#define ISP16_IRQ_9 0x10 +#define ISP16_IRQ_10 0x14 +#define ISP16_IRQ_11 0x18 +#define ISP16_DMA_X 0x03 +#define ISP16_DMA_3 0x00 +#define ISP16_DMA_5 0x00 +#define ISP16_DMA_6 0x01 +#define ISP16_DMA_7 0x02 +#define ISP16_IO_SET_MASK 0x20 /* don't change 5-bit */ +/* ...for port */ +#define ISP16_IO_SET_PORT 0xF8E +/* enable the card */ +#define ISP16_C928__ENABLE_PORT 0xF90 /* ISP16 with OPTi 82C928 chip */ +#define ISP16_C929__ENABLE_PORT 0xF91 /* ISP16 with OPTi 82C929 chip */ +#define ISP16_ENABLE_CDROM 0x80 /* seven bit */ + +/* the magic stuff */ +#define ISP16_CTRL_PORT 0xF8F +#define ISP16_C928__CTRL 0xE2 /* ISP16 with OPTi 82C928 chip */ +#define ISP16_C929__CTRL 0xE3 /* ISP16 with OPTi 82C929 chip */ + +static short isp16_detect(void); +static short isp16_c928__detect(void); +static short isp16_c929__detect(void); +static short isp16_cdi_config( int base, u_char drive_type, int irq, int dma ); +static void isp16_sound_config( void ); +static short isp16_type; /* dependent on type of interface card */ +static u_char isp16_ctrl; +static u_short isp16_enable_port; + +/*static int sjcd_present = 0;*/ +static u_char special_mask = 0; + +static unsigned char defaults[ 16 ] = { + 0xA8, 0xA8, 0x18, 0x18, 0x18, 0x18, 0x8E, 0x8E, + 0x03, 0x00, 0x02, 0x00, 0x0A, 0x00, 0x00, 0x00 +}; +/* ------------- */ +/* + * -- ISP16 detection and configuration + * + * Copyright (c) 1995, Eric van der Maarel + * + * Version 0.5 + * + * Detect cdrom interface on ISP16 soundcard. + * Configure cdrom interface. + * Configure sound interface. + * + * Algorithm for the card with OPTi 82C928 taken + * from the CDSETUP.SYS driver for MSDOS, + * by OPTi Computers, version 2.03. + * Algorithm for the card with OPTi 82C929 as communicated + * to me by Vadim Model and Leo Spiekman. + * + * Use, modifification or redistribution of this software is + * allowed under the terms of the GPL. + * + */ + + +#define ISP16_IN(p) (outb(isp16_ctrl,ISP16_CTRL_PORT), inb(p)) +#define ISP16_OUT(p,b) (outb(isp16_ctrl,ISP16_CTRL_PORT), outb(b,p)) + +static short +isp16_detect(void) +{ + + if ( !( isp16_c929__detect() < 0 ) ) + return(2); + else + return( isp16_c928__detect() ); +} + +static short +isp16_c928__detect(void) +{ + u_char ctrl; + u_char enable_cdrom; + u_char io; + short i = -1; + + isp16_ctrl = ISP16_C928__CTRL; + isp16_enable_port = ISP16_C928__ENABLE_PORT; + + /* read' and write' are a special read and write, respectively */ + + /* read' ISP16_CTRL_PORT, clear last two bits and write' back the result */ + ctrl = ISP16_IN( ISP16_CTRL_PORT ) & 0xFC; + ISP16_OUT( ISP16_CTRL_PORT, ctrl ); + + /* read' 3,4 and 5-bit from the cdrom enable port */ + enable_cdrom = ISP16_IN( ISP16_C928__ENABLE_PORT ) & 0x38; + + if ( !(enable_cdrom & 0x20) ) { /* 5-bit not set */ + /* read' last 2 bits of ISP16_IO_SET_PORT */ + io = ISP16_IN( ISP16_IO_SET_PORT ) & 0x03; + if ( ((io&0x01)<<1) == (io&0x02) ) { /* bits are the same */ + if ( io == 0 ) { /* ...the same and 0 */ + i = 0; + enable_cdrom |= 0x20; + } + else { /* ...the same and 1 */ /* my card, first time 'round */ + i = 1; + enable_cdrom |= 0x28; + } + ISP16_OUT( ISP16_C928__ENABLE_PORT, enable_cdrom ); + } + else { /* bits are not the same */ + ISP16_OUT( ISP16_CTRL_PORT, ctrl ); + return(i); /* -> not detected: possibly incorrect conclusion */ + } + } + else if ( enable_cdrom == 0x20 ) + i = 0; + else if ( enable_cdrom == 0x28 ) /* my card, already initialised */ + i = 1; + + ISP16_OUT( ISP16_CTRL_PORT, ctrl ); + + return(i); +} + +static short +isp16_c929__detect(void) +{ + u_char ctrl; + u_char tmp; + + isp16_ctrl = ISP16_C929__CTRL; + isp16_enable_port = ISP16_C929__ENABLE_PORT; + + /* read' and write' are a special read and write, respectively */ + + /* read' ISP16_CTRL_PORT and save */ + ctrl = ISP16_IN( ISP16_CTRL_PORT ); + + /* write' zero to the ctrl port and get response */ + ISP16_OUT( ISP16_CTRL_PORT, 0 ); + tmp = ISP16_IN( ISP16_CTRL_PORT ); + + if ( tmp != 2 ) /* isp16 with 82C929 not detected */ + return(-1); + + /* restore ctrl port value */ + ISP16_OUT( ISP16_CTRL_PORT, ctrl ); + + return(2); +} + +static short +isp16_cdi_config( int base, u_char drive_type, int irq, int dma ) +{ + u_char base_code; + u_char irq_code; + u_char dma_code; + u_char i; + + if ( (drive_type == ISP16_MITSUMI) && (dma != 0) ) + printk( "Mitsumi cdrom drive has no dma support.\n" ); + + switch (base) { + case 0x340: base_code = ISP16_BASE_340; break; + case 0x330: base_code = ISP16_BASE_330; break; + case 0x360: base_code = ISP16_BASE_360; break; + case 0x320: base_code = ISP16_BASE_320; break; + default: + printk( "Base address 0x%03X not supported by cdrom interface on ISP16.\n", base ); + return(-1); + } + switch (irq) { + case 0: irq_code = ISP16_IRQ_X; break; /* disable irq */ + case 5: irq_code = ISP16_IRQ_5; + printk( "Irq 5 shouldn't be used by cdrom interface on ISP16," + " due to possible conflicts with the soundcard.\n"); + break; + case 7: irq_code = ISP16_IRQ_7; + printk( "Irq 7 shouldn't be used by cdrom interface on ISP16," + " due to possible conflicts with the soundcard.\n"); + break; + case 3: irq_code = ISP16_IRQ_3; break; + case 9: irq_code = ISP16_IRQ_9; break; + case 10: irq_code = ISP16_IRQ_10; break; + case 11: irq_code = ISP16_IRQ_11; break; + default: + printk( "Irq %d not supported by cdrom interface on ISP16.\n", irq ); + return(-1); + } + switch (dma) { + case 0: dma_code = ISP16_DMA_X; break; /* disable dma */ + case 1: printk( "Dma 1 cannot be used by cdrom interface on ISP16," + " due to conflict with the soundcard.\n"); + return(-1); break; + case 3: dma_code = ISP16_DMA_3; break; + case 5: dma_code = ISP16_DMA_5; break; + case 6: dma_code = ISP16_DMA_6; break; + case 7: dma_code = ISP16_DMA_7; break; + default: + printk( "Dma %d not supported by cdrom interface on ISP16.\n", dma ); + return(-1); + } + + if ( drive_type != ISP16_SONY && drive_type != ISP16_PANASONIC0 && + drive_type != ISP16_PANASONIC1 && drive_type != ISP16_SANYO0 && + drive_type != ISP16_SANYO1 && drive_type != ISP16_MITSUMI && + drive_type != ISP16_DRIVE_X ) { + printk( "Drive type (code 0x%02X) not supported by cdrom" + " interface on ISP16.\n", drive_type ); + return(-1); + } + + /* set type of interface */ + i = ISP16_IN(ISP16_DRIVE_SET_PORT) & ISP16_DRIVE_SET_MASK; /* clear some bits */ + ISP16_OUT( ISP16_DRIVE_SET_PORT, i|drive_type ); + + /* enable cdrom on interface with 82C929 chip */ + if ( isp16_type > 1 ) + ISP16_OUT( isp16_enable_port, ISP16_ENABLE_CDROM ); + + /* set base address, irq and dma */ + i = ISP16_IN(ISP16_IO_SET_PORT) & ISP16_IO_SET_MASK; /* keep some bits */ + ISP16_OUT( ISP16_IO_SET_PORT, i|base_code|irq_code|dma_code ); + + return(0); +} + +static void isp16_sound_config( void ) +{ + int i; + u_char saved; + + saved = ISP16_IN( 0xF8D ) & 0x8F; + + ISP16_OUT( 0xF8D, 0x40 ); + + /* + * Now we should wait for a while... + */ + for( i = 16*1024; i--; ); + + ISP16_OUT( 0xF8D, saved ); + + ISP16_OUT( 0xF91, 0x1B ); + + for( i = 5*64*1024; i != 0; i-- ) + if( !( inb( 0x534 ) & 0x80 ) ) break; + + if( i > 0 ) { + saved = ( inb( 0x534 ) & 0xE0 ) | 0x0A; + outb( saved, 0x534 ); + + special_mask = ( inb( 0x535 ) >> 4 ) & 0x08; + + saved = ( inb( 0x534 ) & 0xE0 ) | 0x0C; + outb( saved, 0x534 ); + + switch( inb( 0x535 ) ) { + case 0x09: + case 0x0A: + special_mask |= 0x05; + break; + case 0x8A: + special_mask = 0x0F; + break; + default: + i = 0; + } + } + if ( i == 0 ) { + printk( "Strange MediaMagic, but\n" ); + } + else { + printk( "Conf:" ); + saved = inb( 0x534 ) & 0xE0; + for( i = 0; i < 16; i++ ) { + outb( 0x20 | ( u_char )i, 0x534 ); + outb( defaults[i], 0x535 ); + } + for ( i = 0; i < 16; i++ ) { + outb( 0x20 | ( u_char )i, 0x534 ); + saved = inb( 0x535 ); + printk( " %02X", saved ); + } + printk( "\n" ); + } + + ISP16_OUT( 0xF91, 0xA0 | special_mask ); + + /* + * The following have no explaination yet. + */ + ISP16_OUT( 0xF90, 0xA2 ); + ISP16_OUT( 0xF92, 0x03 ); + + /* + * Turn general sound on and set total volume. + */ + ISP16_OUT( 0xF93, 0x0A ); + +/* + outb( 0x04, 0x224 ); + saved = inb( 0x225 ); + outb( 0x04, 0x224 ); + outb( saved, 0x225 ); +*/ + +} diff -u --recursive --new-file v1.3.57/linux/drivers/char/Config.in linux/drivers/char/Config.in --- v1.3.57/linux/drivers/char/Config.in Sun Jan 14 16:30:10 1996 +++ linux/drivers/char/Config.in Sun Jan 14 16:22:16 1996 @@ -48,3 +48,4 @@ bool ' Software Watchdog' CONFIG_SOFT_WATCHDOG fi fi +endmenu diff -u --recursive --new-file v1.3.57/linux/drivers/char/Makefile linux/drivers/char/Makefile --- v1.3.57/linux/drivers/char/Makefile Wed Dec 27 09:12:13 1995 +++ linux/drivers/char/Makefile Mon Jan 15 07:59:13 1996 @@ -95,6 +95,7 @@ ifdef CONFIG_SOFT_WATCHDOG L_OBJS += softdog.o M = y +# This is not modularized, so if configured then "mouse.c" will be resident endif ifdef CONFIG_QIC02_TAPE @@ -106,16 +107,20 @@ endif ifdef M -L_OBJS += mouse.o +LX_OBJS += mouse.o else ifdef MM - M_OBJS += mouse.o + MX_OBJS += mouse.o endif endif - -ifdef CONFIG_SCC + +ifeq ($(CONFIG_SCC),y) L_OBJS += scc.o -endif +else + ifeq ($(CONFIG_SCC),m) + M_OBJS += scc.o + endif +endif ifdef CONFIG_TGA_CONSOLE L_OBJS += tga.o diff -u --recursive --new-file v1.3.57/linux/drivers/char/apm_bios.c linux/drivers/char/apm_bios.c --- v1.3.57/linux/drivers/char/apm_bios.c Mon Dec 11 15:42:02 1995 +++ linux/drivers/char/apm_bios.c Sun Jan 14 19:08:31 1996 @@ -1,4 +1,4 @@ -/* +/* -*- linux-c -*- * APM BIOS driver for Linux * Copyright 1994, 1995 Stephen Rothwell (Stephen.Rothwell@pd.necisa.oz.au) * @@ -16,6 +16,10 @@ * * October 1995, Rik Faith (faith@cs.unc.edu): * Minor enhancements and updates (to the patch set) for 1.3.x + * Documentation + * January 1996, Rik Faith (faith@cs.unc.edu): + * Make /proc/apm easy to format (bump driver version) + * * * Reference: * @@ -24,9 +28,9 @@ * Intel Order Number 241704-001. Microsoft Part Number 781-110-X01. * * [This document is available free from Intel by calling 800.628.8686 (fax - * 916.356.6100) or 800.548.4725. It is also available from Microsoft by - * calling 206.882.8080; and is ftpable from - * ftp://ftp.intel.com/pub/IAL/software_specs/apmv11.doc] + * 916.356.6100) or 800.548.4725; or via anonymous ftp from + * ftp://ftp.intel.com/pub/IAL/software_specs/apmv11.doc. It is also + * available from Microsoft by calling 206.882.8080.] * */ @@ -288,7 +292,7 @@ static struct timer_list apm_timer; -static char driver_version[] = "0.6b"; +static char driver_version[] = "0.7";/* no spaces */ #ifdef APM_DEBUG static char * apm_event_name[] = { @@ -882,69 +886,91 @@ int apm_proc(char *buf) { char * p; - char * power_stat; - char * bat_stat; unsigned short bx; unsigned short cx; unsigned short dx; unsigned short error; + unsigned short ac_line_status = 0xff; + unsigned short battery_status = 0xff; + unsigned short battery_flag = 0xff; + unsigned short percentage = -1; + int time_units = -1; + char *units = "?"; if (apm_bios_info.version == 0) return 0; p = buf; - p += sprintf(p, "BIOS version: %d.%d\nFlags: 0x%02x\n", - (apm_bios_info.version >> 8) & 0xff, - apm_bios_info.version & 0xff, - apm_bios_info.flags); - if ((apm_bios_info.flags & APM_32_BIT_SUPPORT) == 0) - return p - buf; - p += sprintf(p, "Entry %x:%lx cseg16 %x dseg %x", - apm_bios_info.cseg, apm_bios_info.offset, - apm_bios_info.cseg_16, apm_bios_info.dseg); - if (apm_bios_info.version > 0x100) - p += sprintf(p, " cseg len %x, dseg len %x", - apm_bios_info.cseg_len, apm_bios_info.dseg_len); - *p++ = '\n'; - error = apm_get_power_status(&bx, &cx, &dx); - if (error) { - strcpy(p, "Power status not available\n"); - p += strlen(p); - return p - buf; - } - switch ((bx >> 8) & 0xff) { - case 0: power_stat = "off line"; break; - case 1: power_stat = "on line"; break; - case 2: power_stat = "on backup power"; break; - default: power_stat = "unknown"; break; - } - switch (bx & 0xff) { - case 0: bat_stat = "high"; break; - case 1: bat_stat = "low"; break; - case 2: bat_stat = "critical"; break; - case 3: bat_stat = "charging"; break; - default: bat_stat = "unknown"; break; - } - p += sprintf(p, "AC: %s\nBattery status: %s\nBattery life: ", - power_stat, bat_stat); - if ((cx & 0xff) == 0xff) { - strcpy(p, "unknown"); - p += strlen(p); - } else - p += sprintf(p, "%d%%", cx & 0xff); - *p++ = '\n'; - if (apm_bios_info.version > 0x100) { - p += sprintf(p, "Battery flag: 0x%02x\nBattery life: ", - (cx >> 8) & 0xff); - if (dx == 0xffff) { - strcpy(p, "unknown"); - p += strlen(p); + + if ((apm_bios_info.flags & APM_32_BIT_SUPPORT) != 0) { + if (!(error = apm_get_power_status(&bx, &cx, &dx))) { + ac_line_status = (bx >> 8) & 0xff; + battery_status = bx & 0xff; + if ((cx & 0xff) != 0xff) + percentage = cx & 0xff; + + if (apm_bios_info.version > 0x100) { + battery_flag = (cx >> 8) & 0xff; + if (dx != 0xffff) { + if ((dx & 0x8000) == 0x8000) { + units = "min"; + time_units = dx & 0x7ffe; + } else { + units = "sec"; + time_units = dx & 0x7fff; + } + } + } } - else - p += sprintf(p, "%d %s", dx & 0x7fff, - ((dx & 0x8000) == 0) - ? "seconds" : "minutes"); - *p++ = '\n'; } + /* Arguments, with symbols from linux/apm_bios.h. Information is + from the Get Power Status (0x0a) call unless otherwise noted. + + 0) Linux driver version (this will change if format changes) + 1) APM BIOS Version. Usually 1.0 or 1.1. + 2) APM flags from APM Installation Check (0x00): + bit 0: APM_16_BIT_SUPPORT + bit 1: APM_32_BIT_SUPPORT + bit 2: APM_IDLE_SLOWS_CLOCK + bit 3: APM_BIOS_DISABLED + bit 4: APM_BIOS_DISENGAGED + 3) AC line status + 0x00: Off-line + 0x01: On-line + 0x02: On backup power (APM BIOS 1.1 only) + 0xff: Unknown + 4) Battery status + 0x00: High + 0x01: Low + 0x02: Critical + 0x03: Charging + 0xff: Unknown + 5) Battery flag + bit 0: High + bit 1: Low + bit 2: Critical + bit 3: Charging + bit 7: No system battery + 0xff: Unknown + 6) Remaining battery life (percentage of charge): + 0-100: valid + -1: Unknown + 7) Remaining battery life (time units): + Number of remaining minutes or seconds + -1: Unknown + 8) min = minutes; sec = seconds */ + + p += sprintf(p, "%s %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n", + driver_version, + (apm_bios_info.version >> 8) & 0xff, + apm_bios_info.version & 0xff, + apm_bios_info.flags, + ac_line_status, + battery_status, + battery_flag, + percentage, + time_units, + units ); + return p - buf; } @@ -1000,12 +1026,12 @@ set_limit(gdt[APM_DS >> 3], 64 * 1024); } else { set_limit(gdt[APM_CS >> 3], apm_bios_info.cseg_len); - /* - * This is not clear from the spec, but at least one - * machine needs this to be a 64k segment. - */ + /* This is not clear from the spec, but at least one + machine needs CS_16 to be a 64k segment, and the DEC + Hinote Ultra CT475 (and others?) needs DS to be a 64k + segment. */ set_limit(gdt[APM_CS_16 >> 3], 64 * 1024); - set_limit(gdt[APM_DS >> 3], apm_bios_info.dseg_len); + set_limit(gdt[APM_DS >> 3], 64 * 1024); apm_bios_info.version = 0x0101; error = apm_driver_version(&apm_bios_info.version); if (error != 0) @@ -1047,10 +1073,12 @@ (cx >> 8) & 0xff); if (dx == 0xffff) printk("unknown\n"); - else - printk("%d %s\n", dx & 0x7fff, - ((dx & 0x8000) == 0) - ? "seconds" : "minutes"); + else { + if ((dx & 0x8000)) + printk("%d minutes\n", dx & 0x7ffe ); + else + printk("%d seconds\n", dx & 0x7fff ); + } } } diff -u --recursive --new-file v1.3.57/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c --- v1.3.57/linux/drivers/char/keyboard.c Sat Nov 11 17:41:32 1995 +++ linux/drivers/char/keyboard.c Sun Jan 14 16:22:17 1996 @@ -87,12 +87,6 @@ extern void scrollback(int); extern void scrollfront(int); -#ifdef __i386__ -#define fake_keyboard_interrupt() __asm__ __volatile__("int $0x21") -#else -#define fake_keyboard_interrupt() do ; while (0) -#endif - unsigned char kbd_read_mask = 0x01; /* modified by psaux.c */ /* @@ -128,6 +122,8 @@ static volatile unsigned char reply_expected = 0; static volatile unsigned char acknowledge = 0; static volatile unsigned char resend = 0; +/* used by kbd_bh - set by keyboard_interrupt */ +static volatile unsigned char do_poke_blanked_console = 0; extern void compute_shiftstate(void); @@ -384,6 +380,7 @@ prev_scancode = 0; goto end_kbd_intr; } + do_poke_blanked_console = 1; add_keyboard_randomness(scancode); tty = ttytab[fg_console]; @@ -1178,11 +1175,10 @@ } want_console = -1; } - poke_blanked_console(); - cli(); - if ((inb_p(0x64) & kbd_read_mask) == 0x01) - fake_keyboard_interrupt(); - sti(); + if (do_poke_blanked_console) { /* do not unblank for a LED change */ + do_poke_blanked_console = 0; + poke_blanked_console(); + } } int kbd_init(void) diff -u --recursive --new-file v1.3.57/linux/drivers/char/mouse.c linux/drivers/char/mouse.c --- v1.3.57/linux/drivers/char/mouse.c Wed Dec 27 09:12:13 1995 +++ linux/drivers/char/mouse.c Mon Jan 15 07:59:13 1996 @@ -104,6 +104,14 @@ #endif +static struct symbol_table mouse_syms = { +/* Should this be surrounded with "#ifdef CONFIG_MODULES" ? */ +#include + X(mouse_register), + X(mouse_deregister), +#include +}; + int mouse_init(void) { #ifndef MODULE @@ -128,5 +136,6 @@ MOUSE_MAJOR); return -EIO; } - return 0; + + return register_symtab(&mouse_syms); } diff -u --recursive --new-file v1.3.57/linux/drivers/char/tga.c linux/drivers/char/tga.c --- v1.3.57/linux/drivers/char/tga.c Tue Nov 21 13:22:09 1995 +++ linux/drivers/char/tga.c Sat Jan 13 11:09:51 1996 @@ -421,6 +421,9 @@ * dummy routines for the VESA blanking code, which is VGA only, * so we don't have to carry that stuff around for the TGA... */ +void vesa_powerdown(void) +{ +} void vesa_blank(void) { } diff -u --recursive --new-file v1.3.57/linux/drivers/char/tpqic02.c linux/drivers/char/tpqic02.c --- v1.3.57/linux/drivers/char/tpqic02.c Tue Nov 21 13:22:10 1995 +++ linux/drivers/char/tpqic02.c Sun Jan 14 16:49:08 1996 @@ -193,8 +193,6 @@ * Also, be careful to avoid IO conflicts with other devices! */ -#include - /* #define TDEBUG diff -u --recursive --new-file v1.3.57/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c --- v1.3.57/linux/drivers/char/tty_io.c Wed Dec 13 09:02:45 1995 +++ linux/drivers/char/tty_io.c Sun Jan 14 16:26:56 1996 @@ -73,6 +73,10 @@ #include "vt_kern.h" #include "selection.h" +#ifdef CONFIG_KERNELD +#include +#endif + #define CONSOLE_DEV MKDEV(TTY_MAJOR,0) #define TTY_DEV MKDEV(TTYAUX_MAJOR,0) @@ -211,8 +215,17 @@ int retval = 0; struct tty_ldisc o_ldisc; - if ((ldisc < N_TTY) || (ldisc >= NR_LDISCS) || - !(ldiscs[ldisc].flags & LDISC_FLAG_DEFINED)) + if ((ldisc < N_TTY) || (ldisc >= NR_LDISCS)) + return -EINVAL; +#ifdef CONFIG_KERNELD + /* Eduardo Blanco */ + if (!(ldiscs[ldisc].flags & LDISC_FLAG_DEFINED)) { + char modname [20]; + sprintf(modname, "tty-ldisc-%d", ldisc); + request_module (modname); + } +#endif + if (!(ldiscs[ldisc].flags & LDISC_FLAG_DEFINED)) return -EINVAL; if (tty->ldisc.num == ldisc) diff -u --recursive --new-file v1.3.57/linux/drivers/char/wd501p.h linux/drivers/char/wd501p.h --- v1.3.57/linux/drivers/char/wd501p.h Sun Jan 14 16:30:10 1996 +++ linux/drivers/char/wd501p.h Sun Jan 14 16:50:12 1996 @@ -18,6 +18,8 @@ * Release 0.04. * */ + +#include #define WATCHDOG_MINOR 130 /* Watchdog timer */ #define TEMP_MINOR 131 /* Temperature Sensor */ diff -u --recursive --new-file v1.3.57/linux/drivers/net/Config.in linux/drivers/net/Config.in --- v1.3.57/linux/drivers/net/Config.in Wed Dec 27 09:12:13 1995 +++ linux/drivers/net/Config.in Mon Jan 15 07:59:08 1996 @@ -10,7 +10,7 @@ if [ ! "$CONFIG_PPP" = "n" ]; then comment 'CCP compressors for PPP are only built as modules.' fi -bool 'Z8530 SCC kiss emulation driver for AX.25' CONFIG_SCC +tristate 'Z8530 SCC kiss emulation driver for AX.25' CONFIG_SCC tristate 'PLIP (parallel port) support' CONFIG_PLIP tristate 'EQL (serial line load balancing) support' CONFIG_EQUALIZER bool 'Do you want to be offered ALPHA test drivers' CONFIG_NET_ALPHA diff -u --recursive --new-file v1.3.57/linux/drivers/net/Makefile linux/drivers/net/Makefile --- v1.3.57/linux/drivers/net/Makefile Wed Dec 27 09:12:13 1995 +++ linux/drivers/net/Makefile Mon Jan 15 07:59:13 1996 @@ -352,10 +352,10 @@ # If anything built-in uses slhc, then build it into the kernel also. # If not, but a module uses it, build as a module. ifdef CONFIG_SLHC_BUILTIN -L_OBJS += slhc.o +LX_OBJS += slhc.o else ifdef CONFIG_SLHC_MODULE - M_OBJS += slhc.o + MX_OBJS += slhc.o endif endif diff -u --recursive --new-file v1.3.57/linux/drivers/net/README.tunnel linux/drivers/net/README.tunnel --- v1.3.57/linux/drivers/net/README.tunnel Tue Jun 6 11:22:07 1995 +++ linux/drivers/net/README.tunnel Sun Jan 14 16:22:17 1996 @@ -113,9 +113,9 @@ for machine A. Machine A needs it's tunnel address to be on network B so that when packets from machine B are unwrapped, the Linux routing system knows that the address is a local one. Due to a -feature of Linux, any packets recieved locally, bound for another +feature of Linux, any packets received locally, bound for another local address, are simply routed through the loopback interface. -This means that the tunnel device should never recieve packets. Even +This means that the tunnel device should never receive packets. Even on machine B, it is the ethernet interface that is receiving wrapped packets, and once they are unwrapped they go back out the ethernet interface. This could cause Linux to generate ICMP redirect messages diff -u --recursive --new-file v1.3.57/linux/drivers/net/ne.c linux/drivers/net/ne.c --- v1.3.57/linux/drivers/net/ne.c Fri Nov 17 08:42:26 1995 +++ linux/drivers/net/ne.c Wed Jan 17 09:11:43 1996 @@ -22,6 +22,7 @@ sanity checks and bad clone support optional. Paul Gortmaker : new reset code, reset card after probe at boot. Paul Gortmaker : multiple card support for module users. + Paul Gortmaker : Support for PCI ne2k clones, similar to lance.c */ @@ -32,10 +33,12 @@ #include - +#include #include #include #include +#include +#include #include #include @@ -90,6 +93,9 @@ #define NESM_START_PG 0x40 /* First page of TX buffer */ #define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */ +/* Non-zero only if the current card is a PCI with BIOS-set IRQ. */ +static unsigned char pci_irq_line = 0; + int ne_probe(struct device *dev); static int ne_probe1(struct device *dev, int ioaddr); @@ -131,16 +137,56 @@ {"ne", ne_probe1, NE_IO_EXTENT, netcard_portlist}; #else +/* Note that this probe only picks up one card at a time, even for multiple + PCI ne2k cards. Use "ether=0,0,eth1" if you have a second PCI ne2k card. + This keeps things consistent regardless of the bus type of the card. */ + int ne_probe(struct device *dev) { int i; int base_addr = dev ? dev->base_addr : 0; + /* First check any supplied i/o locations. User knows best. */ if (base_addr > 0x1ff) /* Check a single specified location. */ return ne_probe1(dev, base_addr); else if (base_addr != 0) /* Don't probe at all. */ return ENXIO; + /* Then look for any installed PCI clones */ +#if defined(CONFIG_PCI) + if (pcibios_present()) { + int pci_index; + for (pci_index = 0; pci_index < 8; pci_index++) { + unsigned char pci_bus, pci_device_fn; + unsigned int pci_ioaddr; + + /* Currently only Realtek are making PCI ne2k clones. */ + if (pcibios_find_device (PCI_VENDOR_ID_REALTEK, + PCI_DEVICE_ID_REALTEK_8029, pci_index, + &pci_bus, &pci_device_fn) != 0) + break; /* OK, now try to probe for std. ISA card */ + pcibios_read_config_byte(pci_bus, pci_device_fn, + PCI_INTERRUPT_LINE, &pci_irq_line); + pcibios_read_config_dword(pci_bus, pci_device_fn, + PCI_BASE_ADDRESS_0, &pci_ioaddr); + /* Strip the I/O address out of the returned value */ + pci_ioaddr &= PCI_BASE_ADDRESS_IO_MASK; + /* Avoid already found cards from previous ne_probe() calls */ + if (check_region(pci_ioaddr, NE_IO_EXTENT)) + continue; + printk("ne.c: PCI BIOS reports ne2000 clone at i/o %#x, irq %d.\n", + pci_ioaddr, pci_irq_line); + if (ne_probe1(dev, pci_ioaddr) != 0) { /* Shouldn't happen. */ + printk(KERN_ERR "ne.c: Probe of PCI card at %#x failed.\n", pci_ioaddr); + break; /* Hrmm, try to probe for ISA card... */ + } + pci_irq_line = 0; + return 0; + } + } +#endif /* defined(CONFIG_PCI) */ + + /* Last resort. The semi-risky ISA auto-probe. */ for (i = 0; netcard_portlist[i]; i++) { int ioaddr = netcard_portlist[i]; if (check_region(ioaddr, NE_IO_EXTENT)) @@ -289,6 +335,10 @@ if (dev == NULL) { printk("ne.c: Passed a NULL device.\n"); dev = init_etherdev(0, 0); + } + + if (pci_irq_line) { + dev->irq = pci_irq_line; } if (dev->irq < 2) { diff -u --recursive --new-file v1.3.57/linux/drivers/net/seeq8005.h linux/drivers/net/seeq8005.h --- v1.3.57/linux/drivers/net/seeq8005.h Tue Jul 11 10:02:49 1995 +++ linux/drivers/net/seeq8005.h Sun Jan 14 16:22:17 1996 @@ -118,7 +118,7 @@ #define SEEQCFG2_SLOTSEL (0x0040) /* 0= standard IEEE802.3, 1= smaller,faster, non-standard */ #define SEEQCFG2_NO_PREAM (0x0080) /* 1= user supplies Xmit preamble bytes */ #define SEEQCFG2_ADDR_LEN (0x0100) /* 1= 2byte addresses */ -#define SEEQCFG2_REC_CRC (0x0200) /* 0= recieved packets will have CRC stripped from them */ +#define SEEQCFG2_REC_CRC (0x0200) /* 0= received packets will have CRC stripped from them */ #define SEEQCFG2_XMIT_NO_CRC (0x0400) /* dont xmit CRC with each packet (user supplies it) */ #define SEEQCFG2_LOOPBACK (0x0800) #define SEEQCFG2_CTRLO (0x1000) @@ -133,7 +133,7 @@ unused:1, data_follows:1, /* if not set, process this as a header and pointer only */ chain_cont:1, /* if set, more headers in chain only cmd bit valid in recv header */ - xmit_recv:1; /* if set, a xmit packet, else a recieve packet.*/ + xmit_recv:1; /* if set, a xmit packet, else a receive packet.*/ unsigned char status; }; diff -u --recursive --new-file v1.3.57/linux/drivers/net/slhc.c linux/drivers/net/slhc.c --- v1.3.57/linux/drivers/net/slhc.c Mon Dec 11 15:42:03 1995 +++ linux/drivers/net/slhc.c Mon Jan 15 07:59:13 1996 @@ -90,6 +90,8 @@ static long decode(unsigned char **cpp); static unsigned char * put16(unsigned char *cp, unsigned short x); static unsigned short pull16(unsigned char **cpp); +static void export_slhc_syms(void); +static has_exported = 0; /* Initialize compression data structure * slots must be in range 0 to 255 (zero meaning no compression) @@ -101,6 +103,9 @@ register struct cstate *ts; struct slcompress *comp; + if (!has_exported) + export_slhc_syms(); + comp = (struct slcompress *)kmalloc(sizeof(struct slcompress), GFP_KERNEL); if (! comp) @@ -727,11 +732,31 @@ } } +static struct symbol_table slhc_syms = { +/* Should this be surrounded with "#ifdef CONFIG_MODULES" ? */ +#include + /* VJ header compression */ + X(slhc_init), + X(slhc_free), + X(slhc_remember), + X(slhc_compress), + X(slhc_uncompress), + X(slhc_toss), +#include +}; + +static void export_slhc_syms(void) +{ + register_symtab(&slhc_syms); + has_exported = 1; +} + #ifdef MODULE int init_module(void) { printk("CSLIP: code copyright 1989 Regents of the University of California\n"); + export_slhc_syms(); return 0; } diff -u --recursive --new-file v1.3.57/linux/drivers/pci/pci.c linux/drivers/pci/pci.c --- v1.3.57/linux/drivers/pci/pci.c Sat Dec 30 15:50:53 1995 +++ linux/drivers/pci/pci.c Sun Jan 14 16:22:16 1996 @@ -85,6 +85,7 @@ DEVICE( MATROX, MATROX_MGA_IMP, "MGA Impression"), DEVICE( CT, CT_65545, "65545"), DEVICE( FD, FD_36C70, "TMC-18C30"), + DEVICE( SI, SI_6201, "6201"), DEVICE( SI, SI_6202, "6202"), DEVICE( SI, SI_503, "85C503"), DEVICE( SI, SI_501, "85C501"), diff -u --recursive --new-file v1.3.57/linux/drivers/scsi/Config.in linux/drivers/scsi/Config.in --- v1.3.57/linux/drivers/scsi/Config.in Thu Jan 4 21:54:55 1996 +++ linux/drivers/scsi/Config.in Wed Jan 17 07:27:35 1996 @@ -14,11 +14,12 @@ mainmenu_option next_comment comment 'SCSI low-level drivers' +dep_tristate 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS $CONFIG_SCSI dep_tristate 'Adaptec AHA152X support' CONFIG_SCSI_AHA152X $CONFIG_SCSI dep_tristate 'Adaptec AHA1542 support' CONFIG_SCSI_AHA1542 $CONFIG_SCSI dep_tristate 'Adaptec AHA1740 support' CONFIG_SCSI_AHA1740 $CONFIG_SCSI dep_tristate 'Adaptec AHA274X/284X/294X support' CONFIG_SCSI_AIC7XXX $CONFIG_SCSI -dep_tristate 'BusLogic SCSI support' CONFIG_SCSI_BUSLOGIC +dep_tristate 'BusLogic SCSI support' CONFIG_SCSI_BUSLOGIC $CONFIG.SCSI dep_tristate 'EATA-DMA (DPT, NEC, ATT, Olivetti) support' CONFIG_SCSI_EATA_DMA $CONFIG_SCSI dep_tristate 'EATA-PIO (old DPT PM2001, PM2012A) support' CONFIG_SCSI_EATA_PIO $CONFIG_SCSI dep_tristate 'UltraStor 14F/34F support' CONFIG_SCSI_U14_34F $CONFIG_SCSI @@ -37,3 +38,4 @@ dep_tristate 'EATA ISA/EISA (DPT PM2011/021/012/022/122/322) support' CONFIG_SCSI_EATA $CONFIG_SCSI dep_tristate 'NCR53c406a SCSI support' CONFIG_SCSI_NCR53C406A $CONFIG_SCSI #dep_tristate 'SCSI debugging host adapter' CONFIG_SCSI_DEBUG $CONFIG_SCSI +endmenu diff -u --recursive --new-file v1.3.57/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile --- v1.3.57/linux/drivers/scsi/Makefile Tue Dec 26 04:45:36 1995 +++ linux/drivers/scsi/Makefile Wed Jan 17 07:27:35 1996 @@ -33,6 +33,7 @@ ifeq ($(CONFIG_SCSI),y) L_OBJS += hosts.o scsi.o scsi_ioctl.o constants.o scsicam.o scsi_proc.o +LX_OBJS += scsi_syms.o else ifeq ($(CONFIG_SCSI),m) MX_OBJS += scsi_syms.o @@ -70,6 +71,14 @@ ifeq ($(CONFIG_CHR_DEV_SG),m) M_OBJS += sg.o endif +endif + +ifeq ($(CONFIG_SCSI_ADVANSYS),y) +L_OBJS += advansys.o +else + ifeq ($(CONFIG_SCSI_ADVANSYS),m) + M_OBJS += advansys.o + endif endif ifeq ($(CONFIG_SCSI_QLOGIC),y) diff -u --recursive --new-file v1.3.57/linux/drivers/scsi/advansys.c linux/drivers/scsi/advansys.c --- v1.3.57/linux/drivers/scsi/advansys.c Thu Jan 1 02:00:00 1970 +++ linux/drivers/scsi/advansys.c Wed Jan 17 07:27:36 1996 @@ -0,0 +1,9061 @@ +/* $Id: advansys.c,v 1.11 1996/01/16 22:39:19 bobf Exp bobf $ */ +/* + * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters + * + * Copyright (c) 1995-1996 Advanced System Products, Inc. + * All Rights Reserved. + * + * This driver may be modified and freely distributed provided that + * the above copyright message and this comment are included in the + * distribution. The latest version of this driver is available at + * the AdvanSys FTP and BBS sites listed below. + * + * Please send questions, comments, bug reports to: + * bobf@advansys.com (Bob Frey) + */ + +/* The driver has been tested with Linux 1.2.1 and 1.3.57 kernels. */ +#define ASC_VERSION "1.2" /* AdvanSys Driver Version */ + +/* + + Documentation for the AdvanSys Driver + + A. Adapters Supported by this Driver + B. Linux 1.2.X - Directions for Adding the AdvanSys Driver + C. Linux 1.3.X - Directions for Adding the AdvanSys Driver + D. Source Comments + E. Driver Compile Time Options and Debugging + F. Driver LILO Option + G. Release History + H. Known Problems or Issues + I. Credits + J. AdvanSys Contact Information + + + A. Adapters Supported by this Driver + + AdvanSys (Advanced System Products, Inc.) manufactures the following + Bus-Mastering SCSI-2 Host Adapters for the ISA, EISA, VL, and PCI + buses. This Linux driver supports all of these adapters. + + The CDB counts below indicate the number of SCSI CDB (Command + Descriptor Block) requests that can be stored in the RISC chip + cache and board LRAM. The driver detect routine will display the + number of CDBs available for each adapter detected. This value + can be lowered in the BIOS by changing the 'Host Queue Size' + adapter setting. + + Connectivity Products: + ABP920 - Bus-Master PCI 16 CDB + ABP930 - Bus-Master PCI 16 CDB + ABP5140 - Bus-Master PnP ISA 16 CDB + + Single Channel Products: + ABP542 - Bus-Master ISA 240 CDB + ABP5150 - Bus-Master ISA 240 CDB * + ABP742 - Bus-Master EISA 240 CDB + ABP842 - Bus-Master VL 240 CDB + ABP940 - Bus-Master PCI 240 CDB + + Dual Channel Products: + ABP950 - Dual Channel Bus-Master PCI 240 CDB Per Channel + ABP852 - Dual Channel Bus-Master VL 240 CDB Per Channel + ABP752 - Dual Channel Bus-Master EISA 240 CDB Per Channel + + * This board is shipped by HP with the 4020i CD-R drive. It has + no BIOS so it cannot control a boot device, but it can control + any secondary devices. + + B. Linux 1.2.X - Directions for Adding the AdvanSys Driver + + There are two source files: advansys.h and advansys.c. Copy + both of these files to the directory /usr/src/linux/drivers/scsi. + + 1. Add the following line to /usr/src/linux/arch/i386/config.in + after "comment 'SCSI low-level drivers'": + + bool 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS y + + 2. Add the following lines to /usr/src/linux/drivers/scsi/hosts.c + after "#include "hosts.h"": + + #ifdef CONFIG_SCSI_ADVANSYS + #include "advansys.h" + #endif + + and after "static Scsi_Host_Template builtin_scsi_hosts[] =": + + #ifdef CONFIG_SCSI_ADVANSYS + ADVANSYS, + #endif + + 3. Add the following lines to /usr/src/linux/drivers/scsi/Makefile: + + ifdef CONFIG_SCSI_ADVANSYS + SCSI_SRCS := $(SCSI_SRCS) advansys.c + SCSI_OBJS := $(SCSI_OBJS) advansys.o + else + SCSI_MODULE_OBJS := $(SCSI_MODULE_OBJS) advansys.o + endif + + 4. (Optional) If you would like to enable the LILO command line + and /etc/lilo.conf 'advansys' option, make the following changes. + This option can be used to disable I/O port scanning or to limit + I/O port scanning to specific addresses. Refer to the 'Driver + LILO Option' section below. Add the following lines to + /usr/src/linux/init/main.c in the prototype section: + + extern void advansys_setup(char *str, int *ints); + + and add the following lines to the bootsetups[] array. + + #ifdef CONFIG_SCSI_ADVANSYS + { "advansys=", advansys_setup }, + #endif + + 5. If you have the HP 4020i CD-R driver and Linux 1.2.X you should + add a fix to the CD-ROM target driver. This fix will allow + you to mount CDs with the iso9660 file system. Linux 1.3.X + already has this fix. In the file /usr/src/linux/drivers/scsi/sr.c + and function get_sectorsize() after the line: + + if(scsi_CDs[i].sector_size == 0) scsi_CDs[i].sector_size = 2048; + + add the following line: + + if(scsi_CDs[i].sector_size == 2340) scsi_CDs[i].sector_size = 2048; + + 6. In the directory /usr/src/linux run 'make config' to configure + the AdvanSys driver, then run 'make vmlinux' or 'make zlilo' to + make the kernel. If the AdvanSys driver is not configured, then + a loadable module can be built by running 'make modules' and + 'make modules_install'. Use 'insmod' and 'rmmod' to install + and remove advansys.o. + + C. Linux 1.3.X - Directions for Adding the AdvanSys Driver + + There are two source files: advansys.h and advansys.c. Copy + both of these files to the directory /usr/src/linux/drivers/scsi. + + 1. Add the following line to /usr/src/linux/drivers/scsi/Config.in + after "comment 'SCSI low-level drivers'": + + dep_tristate 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS $CONFIG_SCSI + + 2. Add the following lines to /usr/src/linux/drivers/scsi/hosts.c + after "#include "hosts.h"": + + #ifdef CONFIG_SCSI_ADVANSYS + #include "advansys.h" + #endif + + and after "static Scsi_Host_Template builtin_scsi_hosts[] =": + + #ifdef CONFIG_SCSI_ADVANSYS + ADVANSYS, + #endif + + 3. Add the following lines to /usr/src/linux/drivers/scsi/Makefile: + + ifeq ($(CONFIG_SCSI_ADVANSYS),y) + L_OBJS += advansys.o + else + ifeq ($(CONFIG_SCSI_ADVANSYS),m) + M_OBJS += advansys.o + endif + endif + + 4. Add the following line to /usr/src/linux/include/linux/proc_fs.h + in the enum scsi_directory_inos array: + + PROC_SCSI_ADVANSYS, + + 5. (Optional) If you would like to enable the LILO command line + and /etc/lilo.conf 'advansys' option, make the following changes. + This option can be used to disable I/O port scanning or to limit + I/O port scanning to specific addresses. Refer to the 'Driver + LILO Option' section below. Add the following lines to + /usr/src/linux/init/main.c in the prototype section: + + extern void advansys_setup(char *str, int *ints); + + and add the following lines to the bootsetups[] array. + + #ifdef CONFIG_SCSI_ADVANSYS + { "advansys=", advansys_setup }, + #endif + + 6. In the directory /usr/src/linux run 'make config' to configure + the AdvanSys driver, then run 'make vmlinux' or 'make zlilo' to + make the kernel. If the AdvanSys driver is not configured, then + a loadable module can be built by running 'make modules' and + 'make modules_install'. Use 'insmod' and 'rmmod' to install + and remove advansys.o. + + D. Source Comments + + 1. Use tab stops set to 4 for the source files. For vi use 'se tabstops=4'. + + 2. This driver should be maintained in multiple files. But to make + it easier to include with Linux and to follow Linux conventions, + the whole driver is maintained in the source files advansys.h and + advansys.c. In this file logical sections of the driver begin with + a comment that contains '---'. The following are the logical sections + of the driver below. + + --- Linux Version + --- Linux Include Files + --- Driver Options + --- Asc Library Constants and Macros + --- Debugging Header + --- Driver Constants + --- Driver Macros + --- Driver Structures + --- Driver Data + --- Driver Function Prototypes + --- Linux 'Scsi_Host_Template' and advansys_setup() Functions + --- Loadable Driver Support + --- Miscellaneous Driver Functions + --- Functions Required by the Asc Library + --- Tracing and Debugging Functions + --- Asc Library Functions + + 3. The string 'XXX' is used to flag code that needs to be re-written + or that contains a problem that needs to be addressed. + + 4. I have stripped comments from and reformatted the source for the + Asc Library which is included in this file. I haven't done this + to obfuscate the code. Actually I have done this to deobfuscate + the code. The Asc Library source can be found under the following + headings. + + --- Asc Library Constants and Macros + --- Asc Library Functions + + E. Driver Compile Time Options and Debugging + + In this source file the following constants can be defined. They are + defined in the source below. Both of these options are enabled by + default. + + 1. ADVANSYS_DEBUG - enable for debugging and assertions + + The amount of debugging output can be controlled with the global + variable 'asc_dbglvl'. The higher the number the more output. By + default the debug level is 0. + + If the driver is loaded at boot time and the LILO Driver Option + is included in the system, the debug level can be changed by + specifying a 5th (ASC_NUM_BOARD_SUPPORTED + 1) I/O Port. The + first three hex digits of the pseudo I/O Port must be set to + 'deb' and the fourth hex digit specifies the debug level: 0 - F. + The following command line will look for an adapter at 0x330 + and set the debug level to 2. + + linux advansys=0x330,0x0,0x0,0x0,0xdeb2 + + If the driver is built as a loadable module this variable can be + defined when the driver is loaded. The following insmod command + will set the debug level to one. + + insmod advansys.o asc_dbglvl=1 + + + Debugging Message Levels: + 0: Errors Only + 1: High-Level Tracing + 2-N: Verbose Tracing + + I don't know the approved way for turning on printk()s to the + console. Here's a program I use to do this. Debug output is + logged in /var/adm/messages. + + main() + { + syscall(103, 7, 0, 0); + } + + I found that increasing LOG_BUF_LEN to 40960 in kernel/printk.c + prevents most level 1 debug messages from being lost. + + 2. ADVANSYS_STATS - enable statistics and tracing + + For Linux 1.2.X if ADVANSYS_STATS_1_2_PRINT is defined every + 10,000 I/O operations the driver will print statistics to the + console. This value can be changed by modifying the constant + used in advansys_queuecommand(). ADVANSYS_STATS_1_2_PRINT is + off by default. + + For Linux 1.3.X statistics can be accessed by reading the + /proc/scsi/advansys/[0-9] files. + + Note: these statistics are currently maintained on a global driver + basis and not per board. + + F. Driver LILO Option + + If init/main.c is modified as described in the 'Directions for Adding + the AdvanSys Driver to Linux' section (B.4.) above, the driver will + recognize the 'advansys' LILO command line and /etc/lilo.conf option. + This option can be used to either disable I/O port scanning or to limit + scanning to 1 - 4 I/O ports. Regardless of the option setting EISA and + PCI boards will still be searched for and detected. This option only + affects searching for ISA and VL boards. + + Examples: + 1. Eliminate I/O port scanning: + boot: linux advansys= + or + boot: linux advansys=0x0 + 2. Limit I/O port scanning to one I/O port: + boot: linux advansys=0x110 + 3. Limit I/O port scanning to four I/O ports: + boot: linux advansys=0x110,0x210,0x230,0x330 + + For a loadable module the same effect can be achieved by setting + the 'asc_iopflag' variable and 'asc_ioport' array when loading + the driver, e.g. + + insmod advansys.o asc_iopflag=1 asc_ioport=0x110,0x330 + + If ADVANSYS_DEBUG is defined a 5th (ASC_NUM_BOARD_SUPPORTED + 1) + I/O Port may be added to specify the driver debug level. Refer to + the 'Driver Compile Time Options and Debugging' section above for + more information. + + G. Release History + + 12/23/95 BETA-1.0: + First Release + + 12/28/95 BETA-1.1: + 1. Prevent advansys_detect() from being called twice. + 2. Add LILO 0xdeb[0-f] option to set 'asc_dbglvl'. + + 1/12/96 1.2: + 1. Prevent re-entrancy in the interrupt handler which + resulted in the driver hanging Linux. + 2. Fix problem that prevented ABP-940 cards from being + recognized on some PCI motherboards. + 3. Add support for the ABP-5140 PnP ISA card. + 4. Fix check condition return status. + 5. Add conditionally compiled code for Linux 1.3.X. + + H. Known Problems or Issues + + 1. The setting for 'cmd_per_lun' needs to be changed. It is currently + less then what the AdvanSys boards can queue. Because the target and + mid-level Linux drivers base memory allocation on 'cmd_per_lun' (as + well as 'sg_tablesize') memory use gets out of hand with a large + 'cmd_per_lun'. 'cmd_per_lun' should be per device instead of per + adapter. When the driver is compiled as a loadable module both + 'cmd_per_lun' and 'sg_tablesize' are tuned down to try to prevent + memory allocation errors. + + 2. For the first scsi command sent to a device the driver increases + the timeout value. This gives the driver more time to perform + its own initialization for the board and each device. The timeout + value is only changed on the first scsi command for each device + and never thereafter. + + I. Credits + + Nathan Hartwell (mage@cdc3.cdc.net) provided the directions and + and basis for the Linux 1.3.X changes which were included in the + 1.2 release. + + J. AdvanSys Contact Information + + Mail: Advanced System Products, Inc. + 1150 Ringwood Court + San Jose, CA 95131 USA + Operator: 1-408-383-9400 + FAX: 1-408-383-9612 + Tech Support: 1-800-525-7440 + BBS: 1-408-383-9540 (9600,N,8,1) + Interactive FAX: 1-408-383-9753 + Customer Direct Sales: 1-800-883-1099 + Tech Support E-Mail: support@advansys.com + Linux Support E-Mail: bobf@advansys.com + FTP Site: ftp.advansys.com (login: anonymous) + Web Site: http://www.advansys.com + +*/ + + +/* + * --- Linux Version + */ + +/* + * The driver can be used in Linux 1.2.X or 1.3.X. + */ +#if !defined(LINUX_1_2) && !defined(LINUX_1_3) +#ifndef LINUX_VERSION_CODE +#include +#endif /* LINUX_VERSION_CODE */ +#if LINUX_VERSION_CODE > 65536 + 3 * 256 +#define LINUX_1_3 +#else /* LINUX_VERSION_CODE */ +#define LINUX_1_2 +#endif /* LINUX_VERSION_CODE */ +#endif /* !defined(LINUX_1_2) && !defined(LINUX_1_3) */ + + +/* + * --- Linux Include Files + */ + +#ifdef MODULE +#ifdef LINUX_1_3 +#include +#endif /* LINUX_1_3 */ +#include +#endif /* MODULE */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef LINUX_1_3 +#include +#endif /* LINUX_1_3 */ +#include +#include +#include +#ifdef LINUX_1_2 +#include "../block/blk.h" +#else /* LINUX_1_3 */ +#include +#include +#endif /* LINUX_1_3 */ +#include "scsi.h" +#include "hosts.h" +#include "sd.h" +#include "advansys.h" + + +/* + * --- Driver Options + */ +#define ADVANSYS_DEBUG /* Enable for debugging and assertions. */ +#define ADVANSYS_STATS /* Enable for statistics and tracing. */ +#ifdef LINUX_1_2 +#undef ADVANSYS_STATS_1_2_PRINT /* Enable to print statistics to console. */ +#endif /* LINUX_1_2 */ + + +/* + * --- Asc Library Constants and Macros + */ + +#define ASC_LIB_VERSION_MAJOR 1 +#define ASC_LIB_VERSION_MINOR 16 +#define ASC_LIB_SERIAL_NUMBER 53 + +typedef unsigned char uchar; +typedef unsigned char BYTE; +typedef unsigned short WORD; +typedef unsigned long DWORD; + +typedef int BOOL; + +#ifndef NULL +#define NULL (0) +#endif + +#ifndef TRUE +#define TRUE (1) +#endif + +#ifndef FALSE +#define FALSE (0) +#endif + +#define REG register + +#define rchar REG char +#define rshort REG short +#define rint REG int +#define rlong REG long + +#define ruchar REG uchar +#define rushort REG ushort +#define ruint REG uint +#define rulong REG ulong + +#define NULLPTR ( void *)0 +#define FNULLPTR ( void dosfar *)0UL +#define EOF (-1) +#define EOS '\0' +#define ERR (-1) +#define UB_ERR (uchar)(0xFF) +#define UW_ERR (uint)(0xFFFF) +#define UL_ERR (ulong)(0xFFFFFFFFUL) + +#define iseven_word( val ) ( ( ( ( uint )val) & ( uint )0x0001 ) == 0 ) +#define isodd_word( val ) ( ( ( ( uint )val) & ( uint )0x0001 ) != 0 ) +#define toeven_word( val ) ( ( ( uint )val ) & ( uint )0xFFFE ) + +#define biton( val, bits ) ((( uint )( val >> bits ) & (uint)0x0001 ) != 0 ) +#define bitoff( val, bits ) ((( uint )( val >> bits ) & (uint)0x0001 ) == 0 ) +#define lbiton( val, bits ) ((( ulong )( val >> bits ) & (ulong)0x00000001UL ) != 0 ) +#define lbitoff( val, bits ) ((( ulong )( val >> bits ) & (ulong)0x00000001UL ) == 0 ) + +#define absh( val ) ( ( val ) < 0 ? -( val ) : ( val ) ) + +#define swapbyte( ch ) ( ( ( (ch) << 4 ) | ( (ch) >> 4 ) ) ) + +#ifndef GBYTE +#define GBYTE (0x40000000UL) +#endif + +#ifndef MBYTE +#define MBYTE (0x100000UL) +#endif + +#ifndef KBYTE +#define KBYTE (0x400) +#endif + +#define HI_BYTE(x) ( *( ( BYTE *)(&x)+1 ) ) +#define LO_BYTE(x) ( *( ( BYTE *)&x ) ) + +#define HI_WORD(x) ( *( ( WORD *)(&x)+1 ) ) +#define LO_WORD(x) ( *( ( WORD *)&x ) ) + +#ifndef MAKEWORD +#define MAKEWORD(lo, hi) ((WORD) (((WORD) lo) | ((WORD) hi << 8))) +#endif + +#ifndef MAKELONG +#define MAKELONG(lo, hi) ((DWORD) (((DWORD) lo) | ((DWORD) hi << 16))) +#endif + +#define SwapWords(dWord) ((DWORD) ((dWord >> 16) | (dWord << 16))) +#define SwapBytes(word) ((WORD) ((word >> 8) | (word << 8))) + +#define BigToLittle(dWord) \ + ((DWORD) (SwapWords(MAKELONG(SwapBytes(LO_WORD(dWord)), SwapBytes(HI_WORD(dWord)))))) +#define LittleToBig(dWord) BigToLittle(dWord) + +#define Lptr +#define dosfar +#define far +#define PortAddr unsigned short +#define Ptr2Func ulong + +#define inp(port) inb(port) +#define inpw(port) inw(port) +#define outp(port, byte) outb((byte), (port)) +#define outpw(port, word) outw((word), (port)) + +#define ASC_MAX_SG_QUEUE 5 +#define ASC_MAX_SG_LIST (1 + ((ASC_SG_LIST_PER_Q) * (ASC_MAX_SG_QUEUE))) + +#define CC_INIT_INQ_DISPLAY FALSE + +#define CC_CLEAR_LRAM_SRB_PTR FALSE +#define CC_VERIFY_LRAM_COPY FALSE + +#define CC_DEBUG_SG_LIST FALSE +#define CC_FAST_STRING_IO FALSE + +#define CC_WRITE_IO_COUNT FALSE +#define CC_CLEAR_DMA_REMAIN FALSE + +#define CC_DISABLE_PCI_PARITY_INT TRUE + +#define CC_LINK_BUSY_Q FALSE + +#define CC_TARGET_MODE FALSE + +#define CC_SCAM FALSE + +#define CC_LITTLE_ENDIAN_HOST TRUE + +#ifndef CC_TEST_LRAM_ENDIAN + +#if CC_LITTLE_ENDIAN_HOST +#define CC_TEST_LRAM_ENDIAN FALSE +#else +#define CC_TEST_LRAM_ENDIAN TRUE +#endif + +#endif + +#define CC_STRUCT_ALIGNED TRUE + +#define CC_MEMORY_MAPPED_IO FALSE + +#ifndef CC_TARGET_MODE +#define CC_TARGET_MODE FALSE +#endif + +#ifndef CC_STRUCT_ALIGNED +#define CC_STRUCT_ALIGNED FALSE +#endif + +#ifndef CC_LITTLE_ENDIAN_HOST +#define CC_LITTLE_ENDIAN_HOST TRUE +#endif + +#if !CC_LITTLE_ENDIAN_HOST + +#ifndef CC_TEST_LRAM_ENDIAN +#define CC_TEST_LRAM_ENDIAN TRUE +#endif + +#endif + +#ifndef CC_MEMORY_MAPPED_IO +#define CC_MEMORY_MAPPED_IO FALSE +#endif + +#ifndef CC_WRITE_IO_COUNT +#define CC_WRITE_IO_COUNT FALSE +#endif + +#ifndef CC_CLEAR_DMA_REMAIN +#define CC_CLEAR_DMA_REMAIN FALSE +#endif + +#define ASC_CS_TYPE unsigned short + +#ifndef asc_ptr_type +#define asc_ptr_type +#endif + +#ifndef CC_SCAM +#define CC_SCAM FALSE +#endif + +#ifndef ASC_GET_PTR2FUNC +#define ASC_GET_PTR2FUNC( fun ) ( Ptr2Func )( fun ) +#endif + +#define FLIP_BYTE_NIBBLE( x ) ( ((x<<4)& 0xFF) | (x>>4) ) + +#define ASC_IS_ISA (0x0001) +#define ASC_IS_ISAPNP (0x0081) +#define ASC_IS_EISA (0x0002) +#define ASC_IS_PCI (0x0004) +#define ASC_IS_PCMCIA (0x0008) +#define ASC_IS_PNP (0x0010) +#define ASC_IS_MCA (0x0020) +#define ASC_IS_VL (0x0040) + +#define ASC_ISA_PNP_PORT_ADDR (0x279) +#define ASC_ISA_PNP_PORT_WRITE (ASC_ISA_PNP_PORT_ADDR+0x800) + +#define ASC_IS_WIDESCSI_16 (0x0100) +#define ASC_IS_WIDESCSI_32 (0x0200) + +#define ASC_IS_BIG_ENDIAN (0x8000) + +#define ASC_CHIP_MIN_VER_VL (0x01) +#define ASC_CHIP_MAX_VER_VL (0x07) + +#define ASC_CHIP_MIN_VER_PCI (0x09) +#define ASC_CHIP_MAX_VER_PCI (0x0F) +#define ASC_CHIP_VER_PCI_BIT (0x08) + +#define ASC_CHIP_MIN_VER_ISA (0x11) +#define ASC_CHIP_MIN_VER_ISA_PNP (0x21) +#define ASC_CHIP_MAX_VER_ISA (0x27) +#define ASC_CHIP_VER_ISA_BIT (0x30) +#define ASC_CHIP_VER_ISAPNP_BIT (0x20) + +#define ASC_CHIP_VER_ASYN_BUG (0x21) + +#define ASC_CHIP_MIN_VER_EISA (0x41) +#define ASC_CHIP_MAX_VER_EISA (0x47) +#define ASC_CHIP_VER_EISA_BIT (0x40) + +#define ASC_MAX_VL_DMA_ADDR (0x07FFFFFFL) +#define ASC_MAX_VL_DMA_COUNT (0x07FFFFFFL) + +#define ASC_MAX_PCI_DMA_ADDR (0xFFFFFFFFL) +#define ASC_MAX_PCI_DMA_COUNT (0xFFFFFFFFL) + +#define ASC_MAX_ISA_DMA_ADDR (0x00FFFFFFL) +#define ASC_MAX_ISA_DMA_COUNT (0x00FFFFFFL) + +#define ASC_MAX_EISA_DMA_ADDR (0x07FFFFFFL) +#define ASC_MAX_EISA_DMA_COUNT (0x07FFFFFFL) + +#if !CC_STRUCT_ALIGNED + +#define DvcGetQinfo( iop_base, s_addr, outbuf, words) \ + AscMemWordCopyFromLram( iop_base, s_addr, outbuf, words) + +#define DvcPutScsiQ( iop_base, s_addr, outbuf, words) \ + AscMemWordCopyToLram( iop_base, s_addr, outbuf, words) + +#endif + +#define ASC_SCSI_ID_BITS 3 +#define ASC_SCSI_TIX_TYPE uchar +#define ASC_ALL_DEVICE_BIT_SET 0xFF + +#ifdef ASC_WIDESCSI_16 + +#undef ASC_SCSI_ID_BITS +#define ASC_SCSI_ID_BITS 4 +#define ASC_ALL_DEVICE_BIT_SET 0xFFFF + +#endif + +#ifdef ASC_WIDESCSI_32 + +#undef ASC_SCSI_ID_BITS +#define ASC_SCSI_ID_BITS 5 +#define ASC_ALL_DEVICE_BIT_SET 0xFFFFFFFFL + +#endif + +#if ASC_SCSI_ID_BITS == 3 + +#define ASC_SCSI_BIT_ID_TYPE uchar +#define ASC_MAX_TID 7 +#define ASC_MAX_LUN 7 +#define ASC_SCSI_WIDTH_BIT_SET 0xFF + +#elif ASC_SCSI_ID_BITS == 4 + +#define ASC_SCSI_BIT_ID_TYPE ushort +#define ASC_MAX_TID 15 +#define ASC_MAX_LUN 7 +#define ASC_SCSI_WIDTH_BIT_SET 0xFFFF + +#elif ASC_SCSI_ID_BITS == 5 + +#define ASC_SCSI_BIT_ID_TYPE ulong +#define ASC_MAX_TID 31 +#define ASC_MAX_LUN 7 +#define ASC_SCSI_WIDTH_BIT_SET 0xFFFFFFFF + +#else + +#error ASC_SCSI_ID_BITS definition is wrong + +#endif + +#define ASC_MAX_SENSE_LEN 32 +#define ASC_MIN_SENSE_LEN 14 + +#define ASC_MAX_CDB_LEN 12 + +#define SCSICMD_TestUnitReady 0x00 +#define SCSICMD_Rewind 0x01 +#define SCSICMD_Rezero 0x01 +#define SCSICMD_RequestSense 0x03 +#define SCSICMD_Format 0x04 +#define SCSICMD_FormatUnit 0x04 +#define SCSICMD_Read6 0x08 +#define SCSICMD_Write6 0x0A +#define SCSICMD_Seek6 0x0B +#define SCSICMD_Inquiry 0x12 +#define SCSICMD_Verify6 0x13 +#define SCSICMD_ModeSelect6 0x15 +#define SCSICMD_ModeSense6 0x1A + +#define SCSICMD_StartStopUnit 0x1B +#define SCSICMD_LoadUnloadTape 0x1B +#define SCSICMD_ReadCapacity 0x25 +#define SCSICMD_Read10 0x28 +#define SCSICMD_Write10 0x2A +#define SCSICMD_Seek10 0x2B +#define SCSICMD_Erase10 0x2C +#define SCSICMD_WriteAndVerify10 0x2E +#define SCSICMD_Verify10 0x2F + +#define SCSICMD_ModeSelect10 0x55 +#define SCSICMD_ModeSense10 0x5A + +#define SCSI_TYPE_DASD 0x00 +#define SCSI_TYPE_SASD 0x01 +#define SCSI_TYPE_PRN 0x02 +#define SCSI_TYPE_PROC 0x03 + +#define SCSI_TYPE_WORM 0x04 +#define SCSI_TYPE_CDROM 0x05 +#define SCSI_TYPE_SCANNER 0x06 +#define SCSI_TYPE_OPTMEM 0x07 +#define SCSI_TYPE_MED_CHG 0x08 +#define SCSI_TYPE_COMM 0x09 +#define SCSI_TYPE_UNKNOWN 0x1F +#define SCSI_TYPE_NO_DVC 0xFF + +#define ASC_SCSIDIR_NOCHK 0x00 + +#define ASC_SCSIDIR_T2H 0x08 + +#define ASC_SCSIDIR_H2T 0x10 + +#define ASC_SCSIDIR_NODATA 0x18 + +#define SCSI_SENKEY_NO_SENSE 0x00 +#define SCSI_SENKEY_UNDEFINED 0x01 +#define SCSI_SENKEY_NOT_READY 0x02 +#define SCSI_SENKEY_MEDIUM_ERR 0x03 +#define SCSI_SENKEY_HW_ERR 0x04 +#define SCSI_SENKEY_ILLEGAL 0x05 +#define SCSI_SENKEY_ATTENSION 0x06 +#define SCSI_SENKEY_PROTECTED 0x07 +#define SCSI_SENKEY_BLANK 0x08 +#define SCSI_SENKEY_V_UNIQUE 0x09 +#define SCSI_SENKEY_CPY_ABORT 0x0A +#define SCSI_SENKEY_ABORT 0x0B +#define SCSI_SENKEY_EQUAL 0x0C +#define SCSI_SENKEY_VOL_OVERFLOW 0x0D +#define SCSI_SENKEY_MISCOMP 0x0E +#define SCSI_SENKEY_RESERVED 0x0F + +#define ASC_SRB_HOST( x ) ( ( uchar )( ( uchar )( x ) >> 4 ) ) +#define ASC_SRB_TID( x ) ( ( uchar )( ( uchar )( x ) & ( uchar )0x0F ) ) + +#define ASC_SRB_LUN( x ) ( ( uchar )( ( uint )( x ) >> 13 ) ) + +#define PUT_CDB1( x ) ( ( uchar )( ( uint )( x ) >> 8 ) ) + +#define SS_GOOD 0x00 +#define SS_CHK_CONDITION 0x02 +#define SS_CONDITION_MET 0x04 +#define SS_TARGET_BUSY 0x08 +#define SS_INTERMID 0x10 +#define SS_INTERMID_COND_MET 0x14 + +#define SS_RSERV_CONFLICT 0x18 +#define SS_CMD_TERMINATED 0x22 + +#define SS_QUEUE_FULL 0x28 + +#define MS_CMD_DONE 0x00 +#define MS_EXTEND 0x01 +#define MS_SDTR_LEN 0x03 +#define MS_SDTR_CODE 0x01 + +#define M1_SAVE_DATA_PTR 0x02 +#define M1_RESTORE_PTRS 0x03 +#define M1_DISCONNECT 0x04 +#define M1_INIT_DETECTED_ERR 0x05 +#define M1_ABORT 0x06 +#define M1_MSG_REJECT 0x07 +#define M1_NO_OP 0x08 +#define M1_MSG_PARITY_ERR 0x09 +#define M1_LINK_CMD_DONE 0x0A +#define M1_LINK_CMD_DONE_WFLAG 0x0B +#define M1_BUS_DVC_RESET 0x0C +#define M1_ABORT_TAG 0x0D +#define M1_CLR_QUEUE 0x0E +#define M1_INIT_RECOVERY 0x0F +#define M1_RELEASE_RECOVERY 0x10 +#define M1_KILL_IO_PROC 0x11 + +#define M2_QTAG_MSG_SIMPLE 0x20 +#define M2_QTAG_MSG_HEAD 0x21 +#define M2_QTAG_MSG_ORDERED 0x22 +#define M2_IGNORE_WIDE_RESIDUE 0x23 + +typedef struct { + uchar peri_dvc_type:5; + uchar peri_qualifier:3; +} ASC_SCSI_INQ0; + +typedef struct { + uchar dvc_type_modifier:7; + uchar rmb:1; +} ASC_SCSI_INQ1; + +typedef struct { + uchar ansi_apr_ver:3; + uchar ecma_ver:3; + uchar iso_ver:2; +} ASC_SCSI_INQ2; + +typedef struct { + uchar rsp_data_fmt:4; + + uchar res:2; + uchar TemIOP:1; + uchar aenc:1; +} ASC_SCSI_INQ3; + +typedef struct { + uchar StfRe:1; + uchar CmdQue:1; + uchar Reserved:1; + uchar Linked:1; + uchar Sync:1; + uchar WBus16:1; + uchar WBus32:1; + uchar RelAdr:1; +} ASC_SCSI_INQ7; + +typedef struct { + ASC_SCSI_INQ0 byte0; + ASC_SCSI_INQ1 byte1; + ASC_SCSI_INQ2 byte2; + ASC_SCSI_INQ3 byte3; + uchar add_len; + uchar res1; + uchar res2; + ASC_SCSI_INQ7 byte7; + uchar vendor_id[8]; + uchar product_id[16]; + uchar product_rev_level[4]; +} ASC_SCSI_INQUIRY; + +typedef struct asc_req_sense { + uchar err_code:7; + uchar info_valid:1; + uchar segment_no; + uchar sense_key:4; + uchar reserved_bit:1; + uchar sense_ILI:1; + uchar sense_EOM:1; + uchar file_mark:1; + uchar info1[4]; + uchar add_sense_len; + uchar cmd_sp_info[4]; + uchar asc; + uchar ascq; + + uchar fruc; + uchar sks_byte0:7; + uchar sks_valid:1; + uchar sks_bytes[2]; + uchar notused[2]; + uchar ex_sense_code; + uchar info2[4]; +} ASC_REQ_SENSE; + +#define ASC_SG_LIST_PER_Q 7 + +#define QS_FREE 0x00 +#define QS_READY 0x01 +#define QS_DISC1 0x02 +#define QS_DISC2 0x04 +#define QS_BUSY 0x08 + +#define QS_ABORTED 0x40 +#define QS_DONE 0x80 + +#define QC_NO_CALLBACK 0x01 + +#define QC_SG_SWAP_QUEUE 0x02 +#define QC_SG_HEAD 0x04 +#define QC_DATA_IN 0x08 +#define QC_DATA_OUT 0x10 + +#define QC_URGENT 0x20 +#define QC_MSG_OUT 0x40 +#define QC_REQ_SENSE 0x80 + +#define QCSG_SG_XFER_LIST 0x02 +#define QCSG_SG_XFER_MORE 0x04 +#define QCSG_SG_XFER_END 0x08 + +#define QD_IN_PROGRESS 0x00 +#define QD_NO_ERROR 0x01 +#define QD_ABORTED_BY_HOST 0x02 +#define QD_WITH_ERROR 0x04 +#define QD_INVALID_REQUEST 0x80 +#define QD_INVALID_HOST_NUM 0x81 +#define QD_INVALID_DEVICE 0x82 +#define QD_ERR_INTERNAL 0xFF + +#define QHSTA_NO_ERROR 0x00 +#define QHSTA_M_SEL_TIMEOUT 0x11 +#define QHSTA_M_DATA_OVER_RUN 0x12 +#define QHSTA_M_DATA_UNDER_RUN 0x12 +#define QHSTA_M_UNEXPECTED_BUS_FREE 0x13 +#define QHSTA_M_BAD_BUS_PHASE_SEQ 0x14 + +#define QHSTA_D_QDONE_SG_LIST_CORRUPTED 0x21 +#define QHSTA_D_ASC_DVC_ERROR_CODE_SET 0x22 +#define QHSTA_D_HOST_ABORT_FAILED 0x23 +#define QHSTA_D_EXE_SCSI_Q_FAILED 0x24 +#define QHSTA_D_EXE_SCSI_Q_BUSY_TIMEOUT 0x25 + +#define QHSTA_D_ASPI_NO_BUF_POOL 0x26 + +#define QHSTA_M_WTM_TIMEOUT 0x41 +#define QHSTA_M_BAD_CMPL_STATUS_IN 0x42 +#define QHSTA_M_NO_AUTO_REQ_SENSE 0x43 +#define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44 +#define QHSTA_M_TARGET_STATUS_BUSY 0x45 +#define QHSTA_M_BAD_TAG_CODE 0x46 + +#define QHSTA_M_BAD_QUEUE_FULL_OR_BUSY 0x47 + +#define QHSTA_D_LRAM_CMP_ERROR 0x81 +#define QHSTA_M_MICRO_CODE_ERROR_HALT 0xA1 + +#define ASC_FLAG_SCSIQ_REQ 0x01 +#define ASC_FLAG_BIOS_SCSIQ_REQ 0x02 +#define ASC_FLAG_BIOS_ASYNC_IO 0x04 +#define ASC_FLAG_SRB_LINEAR_ADDR 0x08 + +#define ASC_FLAG_WIN16 0x10 +#define ASC_FLAG_WIN32 0x20 + +#define ASC_FLAG_DOS_VM_CALLBACK 0x80 + +#define ASC_TAG_FLAG_ADD_ONE_BYTE 0x10 +#define ASC_TAG_FLAG_ISAPNP_ADD_BYTES 0x40 + +#define ASC_SCSIQ_CPY_BEG 4 +#define ASC_SCSIQ_SGHD_CPY_BEG 2 + +#define ASC_SCSIQ_B_FWD 0 +#define ASC_SCSIQ_B_BWD 1 + +#define ASC_SCSIQ_B_STATUS 2 +#define ASC_SCSIQ_B_QNO 3 + +#define ASC_SCSIQ_B_CNTL 4 +#define ASC_SCSIQ_B_SG_QUEUE_CNT 5 + +#define ASC_SCSIQ_D_DATA_ADDR 8 +#define ASC_SCSIQ_D_DATA_CNT 12 +#define ASC_SCSIQ_B_SENSE_LEN 20 +#define ASC_SCSIQ_DONE_INFO_BEG 22 +#define ASC_SCSIQ_D_SRBPTR 22 +#define ASC_SCSIQ_B_TARGET_IX 26 +#define ASC_SCSIQ_B_CDB_LEN 28 +#define ASC_SCSIQ_B_TAG_CODE 29 +#define ASC_SCSIQ_W_VM_ID 30 +#define ASC_SCSIQ_DONE_STATUS 32 +#define ASC_SCSIQ_HOST_STATUS 33 +#define ASC_SCSIQ_SCSI_STATUS 34 +#define ASC_SCSIQ_CDB_BEG 36 +#define ASC_SCSIQ_DW_REMAIN_XFER_ADDR 56 +#define ASC_SCSIQ_DW_REMAIN_XFER_CNT 60 +#define ASC_SCSIQ_B_SG_WK_QP 49 +#define ASC_SCSIQ_B_SG_WK_IX 50 +#define ASC_SCSIQ_W_REQ_COUNT 52 +#define ASC_SCSIQ_B_LIST_CNT 6 +#define ASC_SCSIQ_B_CUR_LIST_CNT 7 + +#define ASC_SGQ_B_SG_CNTL 4 +#define ASC_SGQ_B_SG_HEAD_QP 5 +#define ASC_SGQ_B_SG_LIST_CNT 6 +#define ASC_SGQ_B_SG_CUR_LIST_CNT 7 +#define ASC_SGQ_LIST_BEG 8 + +#define ASC_DEF_SCSI1_QNG 2 +#define ASC_MAX_SCSI1_QNG 2 +#define ASC_DEF_SCSI2_QNG 16 +#define ASC_MAX_SCSI2_QNG 32 + +#define ASC_TAG_CODE_MASK 0x23 + +#define ASC_STOP_REQ_RISC_STOP 0x01 + +#define ASC_STOP_ACK_RISC_STOP 0x03 + +#define ASC_STOP_CLEAN_UP_BUSY_Q 0x10 +#define ASC_STOP_CLEAN_UP_DISC_Q 0x20 +#define ASC_STOP_HOST_REQ_RISC_HALT 0x40 +#define ASC_STOP_SEND_INT_TO_HOST 0x80 + +#define ASC_TIDLUN_TO_IX( tid, lun ) ( ASC_SCSI_TIX_TYPE )( (tid) + ((lun)<> ASC_SCSI_ID_BITS ) & ASC_MAX_LUN ) + +#define ASC_QNO_TO_QADDR( q_no ) ( (ASC_QADR_BEG)+( ( int )(q_no) << 6 ) ) + +typedef struct asc_scisq_1 { + uchar status; + uchar q_no; + uchar cntl; + uchar sg_queue_cnt; + + uchar target_id; + uchar target_lun; + + ulong data_addr; + ulong data_cnt; + ulong sense_addr; + uchar sense_len; + uchar user_def; +} ASC_SCSIQ_1; + +typedef struct asc_scisq_2 { + ulong srb_ptr; + uchar target_ix; + + uchar flag; + uchar cdb_len; + uchar tag_code; + + ushort vm_id; +} ASC_SCSIQ_2; + +typedef struct asc_scsiq_3 { + uchar done_stat; + uchar host_stat; + uchar scsi_stat; + uchar scsi_msg; +} ASC_SCSIQ_3; + +typedef struct asc_scsiq_4 { + uchar cdb[ASC_MAX_CDB_LEN]; + uchar y_first_sg_list_qp; + uchar y_working_sg_qp; + uchar y_working_sg_ix; + uchar y_cntl; + ushort x_req_count; + ushort x_reconnect_rtn; + ulong x_saved_data_addr; + ulong x_saved_data_cnt; +} ASC_SCSIQ_4; + +typedef struct asc_q_done_info { + ASC_SCSIQ_2 d2; + ASC_SCSIQ_3 d3; + uchar q_status; + uchar q_no; + uchar cntl; + uchar sense_len; + uchar user_def; + uchar res; + ulong remain_bytes; +} ASC_QDONE_INFO; + +typedef struct asc_sg_list { + ulong addr; + ulong bytes; +} ASC_SG_LIST; + +typedef struct asc_sg_head { + uchar entry_cnt; + + uchar queue_cnt; + + uchar entry_to_copy; + uchar res; + ASC_SG_LIST sg_list[ASC_MAX_SG_LIST]; +} ASC_SG_HEAD; + +#define ASC_MIN_SG_LIST 2 + +typedef struct asc_min_sg_head { + uchar entry_cnt; + + uchar queue_cnt; + + uchar entry_to_copy; + uchar res; + ASC_SG_LIST sg_list[ASC_MIN_SG_LIST]; +} ASC_MIN_SG_HEAD; + +#define QCX_SORT (0x0001) +#define QCX_COALEASE (0x0002) + +#if CC_LINK_BUSY_Q +typedef struct asc_ext_scsi_q { + ulong lba; + ushort lba_len; + struct asc_scsi_q dosfar *next; + struct asc_scsi_q dosfar *join; + ushort cntl; + ushort buffer_id; + uchar q_required; + uchar res; +} ASC_EXT_SCSI_Q; + +#endif + +typedef struct asc_scsi_q { + ASC_SCSIQ_1 q1; + ASC_SCSIQ_2 q2; + uchar dosfar *cdbptr; + + ASC_SG_HEAD dosfar *sg_head; + +#if CC_LINK_BUSY_Q + ASC_EXT_SCSI_Q ext; +#endif + +} ASC_SCSI_Q; + +typedef struct asc_scsi_req_q { + ASC_SCSIQ_1 r1; + ASC_SCSIQ_2 r2; + uchar dosfar *cdbptr; + ASC_SG_HEAD dosfar *sg_head; + +#if CC_LINK_BUSY_Q + ASC_EXT_SCSI_Q ext; +#endif + + uchar dosfar *sense_ptr; + + ASC_SCSIQ_3 r3; + uchar cdb[ASC_MAX_CDB_LEN]; + uchar sense[ASC_MIN_SENSE_LEN]; +} ASC_SCSI_REQ_Q; + +typedef struct asc_risc_q { + uchar fwd; + uchar bwd; + ASC_SCSIQ_1 i1; + ASC_SCSIQ_2 i2; + ASC_SCSIQ_3 i3; + ASC_SCSIQ_4 i4; +} ASC_RISC_Q; + +typedef struct asc_sg_list_q { + + uchar seq_no; + uchar q_no; + uchar cntl; + uchar sg_head_qp; + uchar sg_list_cnt; + uchar sg_cur_list_cnt; + +} ASC_SG_LIST_Q; + +typedef struct asc_risc_sg_list_q { + uchar fwd; + uchar bwd; + ASC_SG_LIST_Q sg; + ASC_SG_LIST sg_list[7]; +} ASC_RISC_SG_LIST_Q; + +#define ASC_EXE_SCSI_IO_MAX_IDLE_LOOP 0x1000000UL +#define ASC_EXE_SCSI_IO_MAX_WAIT_LOOP 1024 + +#define ASCQ_ERR_NO_ERROR 0 +#define ASCQ_ERR_IO_NOT_FOUND 1 +#define ASCQ_ERR_LOCAL_MEM 2 +#define ASCQ_ERR_CHKSUM 3 +#define ASCQ_ERR_START_CHIP 4 +#define ASCQ_ERR_INT_TARGET_ID 5 +#define ASCQ_ERR_INT_LOCAL_MEM 6 +#define ASCQ_ERR_HALT_RISC 7 +#define ASCQ_ERR_GET_ASPI_ENTRY 8 +#define ASCQ_ERR_CLOSE_ASPI 9 +#define ASCQ_ERR_HOST_INQUIRY 0x0A +#define ASCQ_ERR_SAVED_SRB_BAD 0x0B +#define ASCQ_ERR_QCNTL_SG_LIST 0x0C +#define ASCQ_ERR_Q_STATUS 0x0D +#define ASCQ_ERR_WR_SCSIQ 0x0E +#define ASCQ_ERR_PC_ADDR 0x0F +#define ASCQ_ERR_SYN_OFFSET 0x10 +#define ASCQ_ERR_SYN_XFER_TIME 0x11 +#define ASCQ_ERR_LOCK_DMA 0x12 +#define ASCQ_ERR_UNLOCK_DMA 0x13 +#define ASCQ_ERR_VDS_CHK_INSTALL 0x14 +#define ASCQ_ERR_MICRO_CODE_HALT 0x15 +#define ASCQ_ERR_SET_LRAM_ADDR 0x16 +#define ASCQ_ERR_CUR_QNG 0x17 +#define ASCQ_ERR_SG_Q_LINKS 0x18 +#define ASCQ_ERR_SCSIQ_PTR 0x19 +#define ASCQ_ERR_ISR_RE_ENTRY 0x1A +#define ASCQ_ERR_CRITICAL_RE_ENTRY 0x1B +#define ASCQ_ERR_ISR_ON_CRITICAL 0x1C +#define ASCQ_ERR_SG_LIST_ODD_ADDRESS 0x1D +#define ASCQ_ERR_XFER_ADDRESS_TOO_BIG 0x1E +#define ASCQ_ERR_SCSIQ_NULL_PTR 0x1F +#define ASCQ_ERR_SCSIQ_BAD_NEXT_PTR 0x20 +#define ASCQ_ERR_GET_NUM_OF_FREE_Q 0x21 +#define ASCQ_ERR_SEND_SCSI_Q 0x22 +#define ASCQ_ERR_HOST_REQ_RISC_HALT 0x23 +#define ASCQ_ERR_RESET_SDTR 0x24 + +#define ASC_WARN_NO_ERROR 0x0000 +#define ASC_WARN_IO_PORT_ROTATE 0x0001 +#define ASC_WARN_EEPROM_CHKSUM 0x0002 +#define ASC_WARN_IRQ_MODIFIED 0x0004 +#define ASC_WARN_AUTO_CONFIG 0x0008 +#define ASC_WARN_CMD_QNG_CONFLICT 0x0010 + +#define ASC_WARN_EEPROM_RECOVER 0x0020 +#define ASC_WARN_CFG_MSW_RECOVER 0x0040 + +#define ASC_IERR_WRITE_EEPROM 0x0001 +#define ASC_IERR_MCODE_CHKSUM 0x0002 +#define ASC_IERR_SET_PC_ADDR 0x0004 +#define ASC_IERR_START_STOP_CHIP 0x0008 + +#define ASC_IERR_IRQ_NO 0x0010 + +#define ASC_IERR_SET_IRQ_NO 0x0020 +#define ASC_IERR_CHIP_VERSION 0x0040 +#define ASC_IERR_SET_SCSI_ID 0x0080 +#define ASC_IERR_GET_PHY_ADDR 0x0100 +#define ASC_IERR_BAD_SIGNATURE 0x0200 +#define ASC_IERR_NO_BUS_TYPE 0x0400 +#define ASC_IERR_SCAM 0x0800 +#define ASC_IERR_SET_SDTR 0x1000 +#define ASC_IERR_RW_LRAM 0x8000 + +#define ASC_DEF_IRQ_NO 10 +#define ASC_MAX_IRQ_NO 15 +#define ASC_MIN_IRQ_NO 10 + +#define ASC_MIN_REMAIN_Q (0x02) +#define ASC_DEF_MAX_TOTAL_QNG (0x40) + +#define ASC_MIN_TAG_Q_PER_DVC (0x04) +#define ASC_DEF_TAG_Q_PER_DVC (0x04) + +#define ASC_MIN_FREE_Q ASC_MIN_REMAIN_Q + +#define ASC_MIN_TOTAL_QNG (( ASC_MAX_SG_QUEUE )+( ASC_MIN_FREE_Q )) + +#define ASC_MAX_TOTAL_QNG 240 +#define ASC_MAX_PCI_INRAM_TOTAL_QNG 20 + +#define ASC_MAX_INRAM_TAG_QNG 16 + +typedef struct asc_dvc_cfg { + ASC_SCSI_BIT_ID_TYPE can_tagged_qng; + + ASC_SCSI_BIT_ID_TYPE cmd_qng_enabled; + ASC_SCSI_BIT_ID_TYPE disc_enable; + uchar res; + uchar chip_scsi_id:4; + + uchar isa_dma_speed:4; + + uchar isa_dma_channel; + uchar chip_version; + ushort pci_device_id; + ushort lib_serial_no; + ushort lib_version; + ushort mcode_date; + ushort mcode_version; + uchar sdtr_data[ASC_MAX_TID + 1]; + uchar max_tag_qng[ASC_MAX_TID + 1]; + uchar dosfar *overrun_buf; + +} ASC_DVC_CFG; + +#define ASC_DEF_DVC_CNTL 0xFFFF +#define ASC_DEF_CHIP_SCSI_ID 7 +#define ASC_DEF_ISA_DMA_SPEED 4 + +#define ASC_INIT_STATE_NULL 0x0000 +#define ASC_INIT_STATE_BEG_GET_CFG 0x0001 +#define ASC_INIT_STATE_END_GET_CFG 0x0002 +#define ASC_INIT_STATE_BEG_SET_CFG 0x0004 +#define ASC_INIT_STATE_END_SET_CFG 0x0008 +#define ASC_INIT_STATE_BEG_LOAD_MC 0x0010 +#define ASC_INIT_STATE_END_LOAD_MC 0x0020 +#define ASC_INIT_STATE_BEG_INQUIRY 0x0040 +#define ASC_INIT_STATE_END_INQUIRY 0x0080 +#define ASC_INIT_RESET_SCSI_DONE 0x0100 + +#define ASC_PCI_DEVICE_ID_REV_A 0x1100 +#define ASC_PCI_DEVICE_ID_REV_B 0x1200 + +#define ASC_BUG_FIX_ADD_ONE_BYTE 0x0001 + +#define ASYN_SDTR_DATA_FIX_PCI_REV_AB 0x41 + +#define ASC_MIN_TAGGED_CMD 7 + +typedef struct asc_dvc_var { + PortAddr iop_base; + ushort err_code; + ushort dvc_cntl; + ushort bug_fix_cntl; + ushort bus_type; + Ptr2Func isr_callback; + Ptr2Func exe_callback; + + ASC_SCSI_BIT_ID_TYPE init_sdtr; + + ASC_SCSI_BIT_ID_TYPE sdtr_done; + + ASC_SCSI_BIT_ID_TYPE use_tagged_qng; + + ASC_SCSI_BIT_ID_TYPE unit_not_ready; + + ASC_SCSI_BIT_ID_TYPE queue_full_or_busy; + + ASC_SCSI_BIT_ID_TYPE start_motor; + uchar scsi_reset_wait; + uchar chip_no; + + char is_in_int; + uchar max_total_qng; + + uchar cur_total_qng; + + uchar in_critical_cnt; + + uchar irq_no; + uchar last_q_shortage; + + ushort init_state; + uchar cur_dvc_qng[ASC_MAX_TID + 1]; + uchar max_dvc_qng[ASC_MAX_TID + 1]; + + ASC_SCSI_Q dosfar *scsiq_busy_head[ASC_MAX_TID + 1]; + ASC_SCSI_Q dosfar *scsiq_busy_tail[ASC_MAX_TID + 1]; + + ulong int_count; + ulong req_count; + ulong busy_count; + + ASC_DVC_CFG dosfar *cfg; + Ptr2Func saved_ptr2func; + ulong reserved2; + ulong reserved3; + ulong max_dma_count; + ASC_SCSI_BIT_ID_TYPE no_scam; + ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer; +} ASC_DVC_VAR; + +typedef int (dosfar * ASC_ISR_CALLBACK) (ASC_DVC_VAR asc_ptr_type *, ASC_QDONE_INFO dosfar *); +typedef int (dosfar * ASC_EXE_CALLBACK) (ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q dosfar *); + +typedef struct asc_dvc_inq_info { + uchar type[ASC_MAX_TID + 1][ASC_MAX_LUN + 1]; +} ASC_DVC_INQ_INFO; + +typedef struct asc_cap_info { + ulong lba; + ulong blk_size; +} ASC_CAP_INFO; + +typedef struct asc_cap_info_array { + ASC_CAP_INFO cap_info[ASC_MAX_TID + 1][ASC_MAX_LUN + 1]; +} ASC_CAP_INFO_ARRAY; + +#define ASC_IOADR_TABLE_MAX_IX 11 +#define ASC_IOADR_GAP 0x10 +#define ASC_SEARCH_IOP_GAP 0x10 +#define ASC_MIN_IOP_ADDR ( PortAddr )0x0100 +#define ASC_MAX_IOP_ADDR ( PortAddr )0x3F0 + +#define ASC_IOADR_1 ( PortAddr )0x0110 +#define ASC_IOADR_2 ( PortAddr )0x0130 +#define ASC_IOADR_3 ( PortAddr )0x0150 +#define ASC_IOADR_4 ( PortAddr )0x0190 +#define ASC_IOADR_5 ( PortAddr )0x0210 +#define ASC_IOADR_6 ( PortAddr )0x0230 +#define ASC_IOADR_7 ( PortAddr )0x0250 +#define ASC_IOADR_8 ( PortAddr )0x0330 +#define ASC_IOADR_DEF ASC_IOADR_8 + +#define ASC_SYN_XFER_NO 8 +#define ASC_MAX_SDTR_PERIOD_INDEX 7 +#define ASC_SYN_MAX_OFFSET 0x0F +#define ASC_DEF_SDTR_OFFSET 0x0F +#define ASC_DEF_SDTR_INDEX 0x00 + +#define SYN_XFER_NS_0 25 +#define SYN_XFER_NS_1 30 +#define SYN_XFER_NS_2 35 +#define SYN_XFER_NS_3 40 +#define SYN_XFER_NS_4 50 +#define SYN_XFER_NS_5 60 +#define SYN_XFER_NS_6 70 +#define SYN_XFER_NS_7 85 + +#define ASC_SDTR_PERIOD_IX_MIN 7 + +#define SYN_XMSG_WLEN 3 + +typedef struct sdtr_xmsg { + uchar msg_type; + uchar msg_len; + uchar msg_req; + uchar xfer_period; + uchar req_ack_offset; + uchar res; +} SDTR_XMSG; + +#define ASC_MCNTL_NO_SEL_TIMEOUT ( ushort )0x0001 +#define ASC_MCNTL_NULL_TARGET ( ushort )0x0002 + +#define ASC_CNTL_INITIATOR ( ushort )0x0001 +#define ASC_CNTL_BIOS_GT_1GB ( ushort )0x0002 +#define ASC_CNTL_BIOS_GT_2_DISK ( ushort )0x0004 +#define ASC_CNTL_BIOS_REMOVABLE ( ushort )0x0008 +#define ASC_CNTL_NO_SCAM ( ushort )0x0010 +#define ASC_CNTL_NO_PCI_FIX_ASYN_XFER ( ushort )0x0020 + +#define ASC_CNTL_INT_MULTI_Q ( ushort )0x0080 + +#define ASC_CNTL_NO_LUN_SUPPORT ( ushort )0x0040 + +#define ASC_CNTL_NO_VERIFY_COPY ( ushort )0x0100 +#define ASC_CNTL_RESET_SCSI ( ushort )0x0200 +#define ASC_CNTL_INIT_INQUIRY ( ushort )0x0400 +#define ASC_CNTL_INIT_VERBOSE ( ushort )0x0800 + +#define ASC_CNTL_SCSI_PARITY ( ushort )0x1000 +#define ASC_CNTL_BURST_MODE ( ushort )0x2000 + +#define ASC_CNTL_USE_8_IOP_BASE ( ushort )0x4000 + +#define ASC_EEP_DVC_CFG_BEG_VL 2 +#define ASC_EEP_MAX_DVC_ADDR_VL 15 + +#define ASC_EEP_DVC_CFG_BEG 32 +#define ASC_EEP_MAX_DVC_ADDR 45 + +#define ASC_EEP_DEFINED_WORDS 10 +#define ASC_EEP_MAX_ADDR 63 +#define ASC_EEP_RES_WORDS 0 +#define ASC_EEP_MAX_RETRY 20 +#define ASC_MAX_INIT_BUSY_RETRY 8 + +#define ASC_EEP_ISA_PNP_WSIZE 16 + +typedef struct asceep_config { + ushort cfg_lsw; + ushort cfg_msw; + + uchar init_sdtr; + uchar disc_enable; + + uchar use_cmd_qng; + + uchar start_motor; + uchar max_total_qng; + uchar max_tag_qng; + uchar bios_scan; + + uchar power_up_wait; + + uchar no_scam; + uchar chip_scsi_id:4; + + uchar isa_dma_speed:4; + + uchar sdtr_data[ASC_MAX_TID + 1]; + + uchar adapter_info[6]; + + ushort cntl; + + ushort chksum; +} ASCEEP_CONFIG; + +#define ASC_EEP_CMD_READ 0x80 +#define ASC_EEP_CMD_WRITE 0x40 +#define ASC_EEP_CMD_WRITE_ABLE 0x30 +#define ASC_EEP_CMD_WRITE_DISABLE 0x00 + +#define ASC_OVERRUN_BSIZE 0x00000048UL + +#define ASCV_MSGOUT_BEG 0x0000 +#define ASCV_MSGOUT_SDTR_PERIOD (ASCV_MSGOUT_BEG+3) +#define ASCV_MSGOUT_SDTR_OFFSET (ASCV_MSGOUT_BEG+4) + +#define ASCV_MSGIN_BEG (ASCV_MSGOUT_BEG+8) +#define ASCV_MSGIN_SDTR_PERIOD (ASCV_MSGIN_BEG+3) +#define ASCV_MSGIN_SDTR_OFFSET (ASCV_MSGIN_BEG+4) + +#define ASCV_SDTR_DATA_BEG (ASCV_MSGIN_BEG+8) +#define ASCV_SDTR_DONE_BEG (ASCV_SDTR_DATA_BEG+8) +#define ASCV_MAX_DVC_QNG_BEG ( ushort )0x0020 + +#define ASCV_ASCDVC_ERR_CODE_W ( ushort )0x0030 +#define ASCV_MCODE_CHKSUM_W ( ushort )0x0032 +#define ASCV_MCODE_SIZE_W ( ushort )0x0034 +#define ASCV_STOP_CODE_B ( ushort )0x0036 +#define ASCV_DVC_ERR_CODE_B ( ushort )0x0037 + +#define ASCV_OVERRUN_PADDR_D ( ushort )0x0038 +#define ASCV_OVERRUN_BSIZE_D ( ushort )0x003C + +#define ASCV_HALTCODE_W ( ushort )0x0040 +#define ASCV_CHKSUM_W ( ushort )0x0042 +#define ASCV_MC_DATE_W ( ushort )0x0044 +#define ASCV_MC_VER_W ( ushort )0x0046 +#define ASCV_NEXTRDY_B ( ushort )0x0048 +#define ASCV_DONENEXT_B ( ushort )0x0049 +#define ASCV_USE_TAGGED_QNG_B ( ushort )0x004A +#define ASCV_SCSIBUSY_B ( ushort )0x004B +#define ASCV_CDBCNT_B ( ushort )0x004C +#define ASCV_CURCDB_B ( ushort )0x004D +#define ASCV_RCLUN_B ( ushort )0x004E +#define ASCV_BUSY_QHEAD_B ( ushort )0x004F +#define ASCV_DISC1_QHEAD_B ( ushort )0x0050 + +#define ASCV_DISC_ENABLE_B ( ushort )0x0052 +#define ASCV_CAN_TAGGED_QNG_B ( ushort )0x0053 +#define ASCV_HOSTSCSI_ID_B ( ushort )0x0055 +#define ASCV_MCODE_CNTL_B ( ushort )0x0056 +#define ASCV_NULL_TARGET_B ( ushort )0x0057 + +#define ASCV_FREE_Q_HEAD_W ( ushort )0x0058 +#define ASCV_DONE_Q_TAIL_W ( ushort )0x005A +#define ASCV_FREE_Q_HEAD_B ( ushort )(ASCV_FREE_Q_HEAD_W+1) +#define ASCV_DONE_Q_TAIL_B ( ushort )(ASCV_DONE_Q_TAIL_W+1) + +#define ASCV_HOST_FLAG_B ( ushort )0x005D + +#define ASCV_TOTAL_READY_Q_B ( ushort )0x0064 +#define ASCV_VER_SERIAL_B ( ushort )0x0065 +#define ASCV_HALTCODE_SAVED_W ( ushort )0x0066 +#define ASCV_WTM_FLAG_B ( ushort )0x0068 +#define ASCV_RISC_FLAG_B ( ushort )0x006A +#define ASCV_REQ_SG_LIST_QP ( ushort )0x006B + +#define ASC_HOST_FLAG_IN_ISR 0x01 +#define ASC_HOST_FLAG_ACK_INT 0x02 + +#define ASC_RISC_FLAG_GEN_INT 0x01 +#define ASC_RISC_FLAG_REQ_SG_LIST 0x02 + +#define IOP_CTRL (0x0F) +#define IOP_STATUS (0x0E) +#define IOP_INT_ACK IOP_STATUS + +#define IOP_REG_IFC (0x0D) + +#define IOP_SYN_OFFSET (0x0B) +#define IOP_REG_PC (0x0C) +#define IOP_RAM_ADDR (0x0A) +#define IOP_RAM_DATA (0x08) +#define IOP_EEP_DATA (0x06) +#define IOP_EEP_CMD (0x07) + +#define IOP_VERSION (0x03) +#define IOP_CONFIG_HIGH (0x04) +#define IOP_CONFIG_LOW (0x02) +#define IOP_ASPI_ID_LOW (0x01) +#define IOP_ASPI_ID_HIGH (0x00) + +#define IOP_REG_DC1 (0x0E) +#define IOP_REG_DC0 (0x0C) +#define IOP_REG_SB (0x0B) +#define IOP_REG_DA1 (0x0A) +#define IOP_REG_DA0 (0x08) +#define IOP_REG_SC (0x09) +#define IOP_DMA_SPEED (0x07) +#define IOP_REG_FLAG (0x07) +#define IOP_FIFO_H (0x06) +#define IOP_FIFO_L (0x04) +#define IOP_REG_ID (0x05) +#define IOP_REG_QP (0x03) +#define IOP_REG_IH (0x02) +#define IOP_REG_IX (0x01) +#define IOP_REG_AX (0x00) + +#define IFC_REG_LOCK (0x00) +#define IFC_REG_UNLOCK (0x09) + +#define IFC_WR_EN_FILTER (0x10) +#define IFC_RD_NO_EEPROM (0x10) +#define IFC_SLEW_RATE (0x20) +#define IFC_ACT_NEG (0x40) +#define IFC_INP_FILTER (0x80) + +#define IFC_INIT_DEFAULT ( IFC_ACT_NEG | IFC_REG_UNLOCK ) + +#define SC_SEL (0x80) +#define SC_BSY (0x40) +#define SC_ACK (0x20) +#define SC_REQ (0x10) +#define SC_ATN (0x08) +#define SC_IO (0x04) +#define SC_CD (0x02) +#define SC_MSG (0x01) + +#define AscGetVarFreeQHead( port ) AscReadLramWord( port, ASCV_FREE_Q_HEAD_W ) +#define AscGetVarDoneQTail( port ) AscReadLramWord( port, ASCV_DONE_Q_TAIL_W ) +#define AscPutVarFreeQHead( port, val ) AscWriteLramWord( port, ASCV_FREE_Q_HEAD_W, val ) +#define AscPutVarDoneQTail( port, val ) AscWriteLramWord( port, ASCV_DONE_Q_TAIL_W, val ) + +#define AscGetRiscVarFreeQHead( port ) AscReadLramByte( port, ASCV_NEXTRDY_B ) +#define AscGetRiscVarDoneQTail( port ) AscReadLramByte( port, ASCV_DONENEXT_B ) +#define AscPutRiscVarFreeQHead( port, val ) AscWriteLramByte( port, ASCV_NEXTRDY_B, val ) +#define AscPutRiscVarDoneQTail( port, val ) AscWriteLramByte( port, ASCV_DONENEXT_B, val ) + +#define AscGetChipIFC( port ) inp( (port)+IOP_REG_IFC ) +#define AscPutChipIFC( port, data ) outp( (port)+IOP_REG_IFC, data ) + +#define AscGetChipLramAddr( port ) ( ushort )inpw( ( PortAddr )((port)+IOP_RAM_ADDR) ) +#define AscSetChipLramAddr( port, addr ) outpw( ( PortAddr )( (port)+IOP_RAM_ADDR ), addr ) +#define AscPutChipLramData( port, data ) outpw( (port)+IOP_RAM_DATA, data ) +#define AscGetChipLramData( port ) inpw( (port)+IOP_RAM_DATA ) + +#define AscWriteChipSyn( port, data ) outp( (port)+IOP_SYN_OFFSET, data ) +#define AscReadChipSyn( port ) inp( (port)+IOP_SYN_OFFSET ) + +#define AscWriteChipIH( port, data ) outpw( (port)+IOP_REG_IH, data ) +#define AscReadChipIH( port ) inpw( (port)+IOP_REG_IH ) + +#define AscWriteChipScsiID( port, data ) outp( (port)+IOP_REG_ID, data ) +#define AscReadChipScsiID( port ) inp( (port)+IOP_REG_ID ) + +#define AscGetChipDmaSpeed( port ) ( uchar )inp( (port)+IOP_DMA_SPEED ) +#define AscSetChipDmaSpeed( port, data ) outp( (port)+IOP_DMA_SPEED, data ) +#define AscGetChipQP( port ) ( uchar )inp( (port)+IOP_REG_QP ) +#define AscSetPCAddr( port, data ) outpw( (port)+IOP_REG_PC, data ) +#define AscGetPCAddr( port ) inpw( (port)+IOP_REG_PC ) +#define AscGetChipVerNo( port ) ( uchar )inp( (port)+IOP_VERSION ) + +#define AscGetChipEEPCmd( port ) ( uchar )inp( (port)+IOP_EEP_CMD ) +#define AscSetChipEEPCmd( port, data ) outp( (port)+IOP_EEP_CMD, data ) +#define AscGetChipEEPData( port ) inpw( (port)+IOP_EEP_DATA ) +#define AscSetChipEEPData( port, data ) outpw( (port)+IOP_EEP_DATA, data ) + +#define AscGetChipControl( port ) ( uchar )inp( (port)+IOP_CTRL ) +#define AscSetChipControl( port, cc_val ) outp( (port)+IOP_CTRL, cc_val ) + +#define AscGetChipStatus( port ) ( ASC_CS_TYPE )inpw( (port)+IOP_STATUS ) +#define AscSetChipStatus( port, cs_val ) outpw( (port)+IOP_STATUS, cs_val ) + +#define AscGetChipCfgLsw( port ) ( ushort )inpw( (port)+IOP_CONFIG_LOW ) +#define AscGetChipCfgMsw( port ) ( ushort )inpw( (port)+IOP_CONFIG_HIGH ) +#define AscSetChipCfgLsw( port, data ) outpw( (port)+IOP_CONFIG_LOW, data ) +#define AscSetChipCfgMsw( port, data ) outpw( (port)+IOP_CONFIG_HIGH, data ) + +#define AscIsIntPending( port ) ( AscGetChipStatus( port ) & CSW_INT_PENDING ) +#define AscGetChipScsiID( port ) ( ( AscGetChipCfgLsw( port ) >> 8 ) & ASC_MAX_TID ) + +#define ASC_HALT_EXTMSG_IN ( ushort )0x8000 +#define ASC_HALT_CHK_CONDITION ( ushort )0x8100 +#define ASC_HALT_SS_QUEUE_FULL ( ushort )0x8200 +#define ASC_HALT_SDTR_REJECTED ( ushort )0x4000 + +#define ASC_MAX_QNO 0xF8 +#define ASC_DATA_SEC_BEG ( ushort )0x0080 +#define ASC_DATA_SEC_END ( ushort )0x0080 +#define ASC_CODE_SEC_BEG ( ushort )0x0080 +#define ASC_CODE_SEC_END ( ushort )0x0080 +#define ASC_QADR_BEG (0x4000) +#define ASC_QADR_USED ( ushort )( ASC_MAX_QNO * 64 ) +#define ASC_QADR_END ( ushort )0x7FFF +#define ASC_QLAST_ADR ( ushort )0x7FC0 +#define ASC_QBLK_SIZE 0x40 +#define ASC_BIOS_DATA_QBEG 0xF8 + +#define ASC_MIN_ACTIVE_QNO 0x01 + +#define ASC_QLINK_END 0xFF +#define ASC_EEPROM_WORDS 0x10 +#define ASC_MAX_MGS_LEN 0x10 + +#define ASC_BIOS_ADDR_DEF 0xDC00 +#define ASC_BIOS_SIZE 0x3800 +#define ASC_BIOS_RAM_OFF 0x3800 +#define ASC_BIOS_RAM_SIZE 0x800 +#define ASC_BIOS_MIN_ADDR 0xC000 +#define ASC_BIOS_MAX_ADDR 0xEC00 +#define ASC_BIOS_BANK_SIZE 0x0400 + +#define ASC_MCODE_START_ADDR 0x0080 + +#define ASC_CFG0_HOST_INT_ON 0x0020 +#define ASC_CFG0_BIOS_ON 0x0040 +#define ASC_CFG0_VERA_BURST_ON 0x0080 +#define ASC_CFG0_SCSI_PARITY_ON 0x0800 + +#define ASC_CFG1_SCSI_TARGET_ON 0x0080 +#define ASC_CFG1_LRAM_8BITS_ON 0x0800 + +#define ASC_CFG_MSW_CLR_MASK 0xF0C0 + +#define CSW_TEST1 ( ASC_CS_TYPE )0x8000 +#define CSW_AUTO_CONFIG ( ASC_CS_TYPE )0x4000 +#define CSW_RESERVED1 ( ASC_CS_TYPE )0x2000 +#define CSW_IRQ_WRITTEN ( ASC_CS_TYPE )0x1000 +#define CSW_33MHZ_SELECTED ( ASC_CS_TYPE )0x0800 +#define CSW_TEST2 ( ASC_CS_TYPE )0x0400 +#define CSW_TEST3 ( ASC_CS_TYPE )0x0200 +#define CSW_RESERVED2 ( ASC_CS_TYPE )0x0100 +#define CSW_DMA_DONE ( ASC_CS_TYPE )0x0080 +#define CSW_FIFO_RDY ( ASC_CS_TYPE )0x0040 + +#define CSW_EEP_READ_DONE ( ASC_CS_TYPE )0x0020 + +#define CSW_HALTED ( ASC_CS_TYPE )0x0010 +#define CSW_SCSI_RESET_ACTIVE ( ASC_CS_TYPE )0x0008 + +#define CSW_PARITY_ERR ( ASC_CS_TYPE )0x0004 +#define CSW_SCSI_RESET_LATCH ( ASC_CS_TYPE )0x0002 + +#define CSW_INT_PENDING ( ASC_CS_TYPE )0x0001 + +#define CIW_INT_ACK ( ASC_CS_TYPE )0x0100 +#define CIW_TEST1 ( ASC_CS_TYPE )0x0200 +#define CIW_TEST2 ( ASC_CS_TYPE )0x0400 +#define CIW_SEL_33MHZ ( ASC_CS_TYPE )0x0800 + +#define CIW_IRQ_ACT ( ASC_CS_TYPE )0x1000 + +#define CC_CHIP_RESET ( uchar )0x80 +#define CC_SCSI_RESET ( uchar )0x40 +#define CC_HALT ( uchar )0x20 +#define CC_SINGLE_STEP ( uchar )0x10 +#define CC_DMA_ABLE ( uchar )0x08 +#define CC_TEST ( uchar )0x04 +#define CC_BANK_ONE ( uchar )0x02 +#define CC_DIAG ( uchar )0x01 + +#define ASC_1000_ID0W 0x04C1 +#define ASC_1000_ID0W_FIX 0x00C1 +#define ASC_1000_ID1B 0x25 + +#define ASC_EISA_BIG_IOP_GAP (0x1C30-0x0C50) +#define ASC_EISA_SMALL_IOP_GAP (0x0020) +#define ASC_EISA_MIN_IOP_ADDR (0x0C30) +#define ASC_EISA_MAX_IOP_ADDR (0xFC50) +#define ASC_EISA_REV_IOP_MASK (0x0C83) +#define ASC_EISA_PID_IOP_MASK (0x0C80) +#define ASC_EISA_CFG_IOP_MASK (0x0C86) + +#define ASC_GET_EISA_SLOT( iop ) ( PortAddr )( (iop) & 0xF000 ) + +#define ASC_EISA_ID_740 0x01745004UL +#define ASC_EISA_ID_750 0x01755004UL + +#define INS_HALTINT ( ushort )0x6281 +#define INS_HALT ( ushort )0x6280 +#define INS_SINT ( ushort )0x6200 +#define INS_RFLAG_WTM ( ushort )0x7380 + +#define ASC_MC_SAVE_CODE_WSIZE 0x500 +#define ASC_MC_SAVE_DATA_WSIZE 0x40 + +typedef struct asc_mc_saved { + ushort data[ASC_MC_SAVE_DATA_WSIZE]; + ushort code[ASC_MC_SAVE_CODE_WSIZE]; +} ASC_MC_SAVED; + +int AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg); +int AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg); +void AscWaitEEPRead(void); +void AscWaitEEPWrite(void); +ushort AscReadEEPWord(PortAddr, uchar); +ushort AscWriteEEPWord(PortAddr, uchar, ushort); +ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG dosfar *, ushort); +int AscSetEEPConfigOnce(PortAddr, ASCEEP_CONFIG dosfar *, ushort); +int AscSetEEPConfig(PortAddr, ASCEEP_CONFIG dosfar *, ushort); +ushort AscEEPSum(PortAddr, uchar, uchar); + +int AscStartChip(PortAddr); +int AscStopChip(PortAddr); +void AscSetChipIH(PortAddr, ushort); +int AscSetRunChipSynRegAtID(PortAddr, uchar, uchar); + +int AscIsChipHalted(PortAddr); + +void AscSetChipCfgDword(PortAddr, ulong); +ulong AscGetChipCfgDword(PortAddr); + +void AscAckInterrupt(PortAddr); +void AscDisableInterrupt(PortAddr); +void AscEnableInterrupt(PortAddr); +void AscSetBank(PortAddr, uchar); +uchar AscGetBank(PortAddr); +int AscResetChipAndScsiBus(PortAddr); +ushort AscGetIsaDmaChannel(PortAddr); +ushort AscSetIsaDmaChannel(PortAddr, ushort); +uchar AscSetIsaDmaSpeed(PortAddr, uchar); +uchar AscGetIsaDmaSpeed(PortAddr); + +uchar AscReadLramByte(PortAddr, ushort); +ushort AscReadLramWord(PortAddr, ushort); +ulong AscReadLramDWord(PortAddr, ushort); +void AscWriteLramWord(PortAddr, ushort, ushort); +void AscWriteLramDWord(PortAddr, ushort, ulong); +void AscWriteLramByte(PortAddr, ushort, uchar); +int AscVerWriteLramDWord(PortAddr, ushort, ulong); +int AscVerWriteLramWord(PortAddr, ushort, ushort); +int AscVerWriteLramByte(PortAddr, ushort, uchar); + +ulong AscMemSumLramWord(PortAddr, ushort, int); +void AscMemWordSetLram(PortAddr, ushort, ushort, int); +void AscMemWordCopyToLram(PortAddr, ushort, ushort dosfar *, int); +void AscMemDWordCopyToLram(PortAddr, ushort, ulong dosfar *, int); +void AscMemWordCopyFromLram(PortAddr, ushort, ushort dosfar *, int); +int AscMemWordCmpToLram(PortAddr, ushort, ushort dosfar *, int); + +ushort AscInitAscDvcVar(ASC_DVC_VAR asc_ptr_type *); +ulong AscLoadMicroCode(PortAddr, ushort, + ushort dosfar *, ushort); +ushort AscInitFromEEP(ASC_DVC_VAR asc_ptr_type *); +ushort AscInitFromAscDvcVar(ASC_DVC_VAR asc_ptr_type *); +ushort AscInitMicroCodeVar(ASC_DVC_VAR asc_ptr_type * asc_dvc); + +void dosfar AscInitPollIsrCallBack(ASC_DVC_VAR asc_ptr_type *, + ASC_QDONE_INFO dosfar *); +int AscTestExternalLram(ASC_DVC_VAR asc_ptr_type *); +ushort AscTestLramEndian(PortAddr); + +uchar AscMsgOutSDTR(PortAddr, uchar, uchar); + +uchar AscCalSDTRData(uchar, uchar); +void AscSetChipSDTR(PortAddr, uchar, uchar); +int AscInitChipAllSynReg(ASC_DVC_VAR asc_ptr_type *, uchar); +uchar AscGetSynPeriodIndex(uchar); +uchar AscSynIndexToPeriod(uchar); +uchar AscAllocFreeQueue(PortAddr, uchar); +uchar AscAllocMultipleFreeQueue(PortAddr, uchar, uchar); +int AscRiscHaltedAbortSRB(ASC_DVC_VAR asc_ptr_type *, ulong); +int AscRiscHaltedAbortTIX(ASC_DVC_VAR asc_ptr_type *, uchar); +int AscRiscHaltedAbortALL(ASC_DVC_VAR asc_ptr_type *); +int AscHostReqRiscHalt(PortAddr); +int AscStopQueueExe(PortAddr); +int AscStartQueueExe(PortAddr); +int AscCleanUpDiscQueue(PortAddr); +int AscCleanUpBusyQueue(PortAddr); +int _AscAbortTidBusyQueue(ASC_DVC_VAR asc_ptr_type *, + ASC_QDONE_INFO dosfar *, uchar); +int _AscAbortSrbBusyQueue(ASC_DVC_VAR asc_ptr_type *, + ASC_QDONE_INFO dosfar *, ulong); +int AscWaitTixISRDone(ASC_DVC_VAR asc_ptr_type *, uchar); +int AscWaitISRDone(ASC_DVC_VAR asc_ptr_type *); +ulong AscGetOnePhyAddr(ASC_DVC_VAR asc_ptr_type *, uchar dosfar *, ulong); + +int AscSendScsiQueue(ASC_DVC_VAR asc_ptr_type * asc_dvc, + ASC_SCSI_Q dosfar * scsiq, + uchar n_q_required); +int AscPutReadyQueue(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q dosfar *, uchar); +int AscPutReadySgListQueue(ASC_DVC_VAR asc_ptr_type *, + ASC_SCSI_Q dosfar *, uchar); +int AscAbortScsiIO(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q dosfar *); +void AscExeScsiIO(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q dosfar *); +int AscSetChipSynRegAtID(PortAddr, uchar, uchar); +int AscSetRunChipSynRegAtID(PortAddr, uchar, uchar); +ushort AscInitLram(ASC_DVC_VAR asc_ptr_type *); +int AscReInitLram(ASC_DVC_VAR asc_ptr_type *); +ushort AscInitQLinkVar(ASC_DVC_VAR asc_ptr_type *); +int AscSetLibErrorCode(ASC_DVC_VAR asc_ptr_type *, ushort); +int _AscWaitQDone(PortAddr, ASC_SCSI_Q dosfar *); + +int AscEnterCritical(void); +void AscLeaveCritical(int); + +int AscIsrChipHalted(ASC_DVC_VAR asc_ptr_type *); +uchar _AscCopyLramScsiDoneQ(PortAddr, ushort, + ASC_QDONE_INFO dosfar *, ulong); +int AscIsrQDone(ASC_DVC_VAR asc_ptr_type *); +ushort AscIsrExeBusyQueue(ASC_DVC_VAR asc_ptr_type *, uchar); +int AscScsiSetupCmdQ(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_REQ_Q dosfar *, + uchar dosfar *, ulong); + +int AscScsiInquiry(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_REQ_Q dosfar *, + uchar dosfar *, int); +int AscScsiTestUnitReady(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_REQ_Q dosfar *); +int AscScsiStartStopUnit(ASC_DVC_VAR asc_ptr_type *, + ASC_SCSI_REQ_Q dosfar *, uchar); +int AscScsiReadCapacity(ASC_DVC_VAR asc_ptr_type *, + ASC_SCSI_REQ_Q dosfar *, + uchar dosfar *); + +ulong dosfar *swapfarbuf4(uchar dosfar *); +int PollQueueDone(ASC_DVC_VAR asc_ptr_type *, + ASC_SCSI_REQ_Q dosfar *, + int); +int PollScsiReadCapacity(ASC_DVC_VAR asc_ptr_type *, + ASC_SCSI_REQ_Q dosfar *, + ASC_CAP_INFO dosfar *); +int PollScsiInquiry(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_REQ_Q dosfar *, + uchar dosfar *, int); +int PollScsiTestUnitReady(ASC_DVC_VAR asc_ptr_type *, + ASC_SCSI_REQ_Q dosfar *); +int PollScsiStartUnit(ASC_DVC_VAR asc_ptr_type *, + ASC_SCSI_REQ_Q dosfar *); +int InitTestUnitReady(ASC_DVC_VAR asc_ptr_type *, + ASC_SCSI_REQ_Q dosfar *); +void AscDispInquiry(uchar, uchar, ASC_SCSI_INQUIRY dosfar *); +int AscPollQDone(ASC_DVC_VAR asc_ptr_type *, + ASC_SCSI_REQ_Q dosfar *, int); + +int AscSetBIOSBank(PortAddr, int, ushort); +int AscSetVlBIOSBank(PortAddr, int); +int AscSetEisaBIOSBank(PortAddr, int); +int AscSetIsaBIOSBank(PortAddr, int); + +int AscIsBiosEnabled(PortAddr, ushort); +void AscResetScsiBus(PortAddr); +void AscClrResetScsiBus(PortAddr); + +void AscSingleStepChip(PortAddr); +uchar AscSetChipScsiID(PortAddr, uchar); +ushort AscGetChipBiosAddress(PortAddr, ushort); +ushort AscSetChipBiosAddress(PortAddr, ushort, ushort); +uchar AscGetChipVersion(PortAddr, ushort); +ushort AscGetChipBusType(PortAddr); + +PortAddr AscSearchIOPortAddr11(PortAddr); +PortAddr AscSearchIOPortAddr100(PortAddr); +int AscFindSignature(PortAddr); +void AscToggleIRQAct(PortAddr); +int AscResetChip(PortAddr); +void AscClrResetChip(PortAddr); + +short itos(ushort, uchar dosfar *, short, short); +int insnchar(uchar dosfar *, short, short, ruchar, short); +void itoh(ushort, ruchar dosfar *); +void btoh(uchar, ruchar dosfar *); +void ltoh(ulong, ruchar dosfar *); +uchar dosfar *todstr(ushort, uchar dosfar *); +uchar dosfar *tohstr(ushort, uchar dosfar *); +uchar dosfar *tobhstr(uchar, uchar dosfar *); +uchar dosfar *tolhstr(ulong, uchar dosfar *); + +void AscSetISAPNPWaitForKey(void); +uchar AscGetChipIRQ(PortAddr, ushort); +uchar AscSetChipIRQ(PortAddr, uchar, ushort); +uchar AscGetChipScsiCtrl(PortAddr); + +ushort AscGetEisaChipCfg(PortAddr); +ushort AscGetEisaChipGpReg(PortAddr); +ushort AscSetEisaChipCfg(PortAddr, ushort); +ushort AscSetEisaChipGpReg(PortAddr, ushort); + +ulong AscGetEisaProductID(PortAddr); +PortAddr AscSearchIOPortAddrEISA(PortAddr); + +int AscPollQTailSync(PortAddr); +int AscPollQHeadSync(PortAddr); +int AscWaitQTailSync(PortAddr); + +int _AscRestoreMicroCode(PortAddr, ASC_MC_SAVED dosfar *); + +int AscSCAM(ASC_DVC_VAR asc_ptr_type *); + +ushort SwapByteOfWord(ushort word_val); +ulong SwapWordOfDWord(ulong dword_val); +ulong AdjEndianDword(ulong dword_val); + +int AscAdjEndianScsiQ(ASC_SCSI_Q dosfar *); +int AscAdjEndianQDoneInfo(ASC_QDONE_INFO dosfar *); + +extern int DvcEnterCritical(void); +extern void DvcLeaveCritical(int); + +extern void DvcInPortWords(PortAddr, ushort dosfar *, int); +extern void DvcOutPortWords(PortAddr, ushort dosfar *, int); +extern void DvcOutPortDWords(PortAddr, ulong dosfar *, int); + +extern void DvcSleepMilliSecond(ulong); +extern void DvcDisplayString(uchar dosfar *); +extern ulong DvcGetPhyAddr(uchar dosfar * buf_addr, ulong buf_len); +extern ulong DvcGetSGList(ASC_DVC_VAR asc_ptr_type *, uchar dosfar *, ulong, + ASC_SG_HEAD dosfar *); + +extern void DvcSCAMDelayMS(ulong); +extern int DvcDisableCPUInterrupt(void); +extern void DvcRestoreCPUInterrupt(int); + +void DvcPutScsiQ(PortAddr, ushort, ushort dosfar *, int); +void DvcGetQinfo(PortAddr, ushort, ushort dosfar *, int); + +PortAddr AscSearchIOPortAddr(PortAddr, ushort); +ushort AscInitGetConfig(ASC_DVC_VAR asc_ptr_type *); +ushort AscInitSetConfig(ASC_DVC_VAR asc_ptr_type *); +ushort AscInitAsc1000Driver(ASC_DVC_VAR asc_ptr_type *); +int AscInitScsiTarget(ASC_DVC_VAR asc_ptr_type *, + ASC_DVC_INQ_INFO dosfar *, + uchar dosfar *, + ASC_CAP_INFO_ARRAY dosfar *, + ushort); +int AscInitPollBegin(ASC_DVC_VAR asc_ptr_type *); +int AscInitPollEnd(ASC_DVC_VAR asc_ptr_type *); +int AscInitPollTarget(ASC_DVC_VAR asc_ptr_type *, + ASC_SCSI_REQ_Q dosfar *, + ASC_SCSI_INQUIRY dosfar *, + ASC_CAP_INFO dosfar *); +int AscExeScsiQueue(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q dosfar *); + +int AscISR(ASC_DVC_VAR asc_ptr_type *); +void AscISR_AckInterrupt(ASC_DVC_VAR asc_ptr_type *); +int AscISR_CheckQDone(ASC_DVC_VAR asc_ptr_type *, + ASC_QDONE_INFO dosfar *, + uchar dosfar *); + +int AscStartUnit(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_TIX_TYPE); +int AscStopUnit( + ASC_DVC_VAR asc_ptr_type * asc_dvc, + ASC_SCSI_TIX_TYPE target_ix +); + +uint AscGetNumOfFreeQueue(ASC_DVC_VAR asc_ptr_type *, uchar, uchar); +int AscSgListToQueue(int); +int AscQueueToSgList(int); +int AscSetDvcErrorCode(ASC_DVC_VAR asc_ptr_type *, uchar); + +int AscAbortSRB(ASC_DVC_VAR asc_ptr_type *, ulong); +int AscResetDevice(ASC_DVC_VAR asc_ptr_type *, uchar); +int AscResetSB(ASC_DVC_VAR asc_ptr_type *); + +void AscEnableIsaDma(uchar); +void AscDisableIsaDma(uchar); + +ulong AscGetMaxDmaAddress(ushort); +ulong AscGetMaxDmaCount(ushort); + +int AscSaveMicroCode(ASC_DVC_VAR asc_ptr_type *, ASC_MC_SAVED dosfar *); +int AscRestoreOldMicroCode(ASC_DVC_VAR asc_ptr_type *, ASC_MC_SAVED dosfar *); +int AscRestoreNewMicroCode(ASC_DVC_VAR asc_ptr_type *, ASC_MC_SAVED dosfar *); + +/* + * --- Debugging Header + */ + +#ifdef ADVANSYS_DEBUG +#define STATIC +#else /* ADVANSYS_DEBUG */ +#define STATIC static +#endif /* ADVANSYS_DEBUG */ + + +/* + * --- Driver Constants and Macros + */ + +#define ASC_NUM_BOARD_SUPPORTED 4 +#define ASC_NUM_BUS 4 + +/* Reference Scsi_Host hostdata */ +#define ASC_BOARD(host) ((struct asc_board *) &(host)->hostdata) + +#define NO_ISA_DMA 0xff /* No ISA DMA Channel Used */ + +#ifndef min +#define min(a, b) (((a) < (b)) ? (a) : (b)) +#endif /* min */ + +/* Asc Library return codes */ +#define ASC_TRUE 1 +#define ASC_FALSE 0 +#define ASC_NOERROR 1 +#define ASC_BUSY 0 +#define ASC_ERROR (-1) + +/* Scsi_Cmnd function return codes */ +#define STATUS_BYTE(byte) (byte) +#define MSG_BYTE(byte) ((byte) << 8) +#define HOST_BYTE(byte) ((byte) << 16) +#define DRIVER_BYTE(byte) ((byte) << 24) + +/* asc_enqueue() flags */ +#define ASC_FRONT 1 +#define ASC_BACK 2 + +/* PCI configuration declarations */ + +#define ASC_PCI_REV_A_INIT 0x01 +#define ASC_PCI_REV_A_DONE 0x02 +#define ASC_PCI_REV_B_INIT 0x04 +#define ASC_PCI_REV_B_DONE 0x08 + +#define PCI_BASE_CLASS_PREDEFINED 0x00 +#define PCI_BASE_CLASS_MASS_STORAGE 0x01 +#define PCI_BASE_CLASS_NETWORK 0x02 +#define PCI_BASE_CLASS_DISPLAY 0x03 +#define PCI_BASE_CLASS_MULTIMEDIA 0x04 +#define PCI_BASE_CLASS_MEMORY_CONTROLLER 0x05 +#define PCI_BASE_CLASS_BRIDGE_DEVICE 0x06 + +/* MASS STORAGE */ +#define PCI_SUB_CLASS_SCSI_CONTROLLER 0x00 +#define PCI_SUB_CLASS_IDE_CONTROLLER 0x01 +#define PCI_SUB_CLASS_FLOPPY_DISK_CONTROLLER 0x02 +#define PCI_SUB_CLASS_IPI_BUS_CONTROLLER 0x03 +#define PCI_SUB_CLASS_OTHER_MASS_CONTROLLER 0x80 + +/* NETWORK CONTROLLER */ +#define PCI_SUB_CLASS_ETHERNET_CONTROLLER 0x00 +#define PCI_SUB_CLASS_TOKEN_RING_CONTROLLER 0x01 +#define PCI_SUB_CLASS_FDDI_CONTROLLER 0x02 +#define PCI_SUB_CLASS_OTHER_NETWORK_CONTROLLER 0x80 + +/* DISPLAY CONTROLLER */ +#define PCI_SUB_CLASS_VGA_CONTROLLER 0x00 +#define PCI_SUB_CLASS_XGA_CONTROLLER 0x01 +#define PCI_SUB_CLASS_OTHER_DISPLAY_CONTROLLER 0x80 + +/* MULTIMEDIA CONTROLLER */ +#define PCI_SUB_CLASS_VIDEO_DEVICE 0x00 +#define PCI_SUB_CLASS_AUDIO_DEVICE 0x01 +#define PCI_SUB_CLASS_OTHER_MULTIMEDIA_DEVICE 0x80 + +/* MEMORY CONTROLLER */ +#define PCI_SUB_CLASS_RAM_CONTROLLER 0x00 +#define PCI_SUB_CLASS_FLASH_CONTROLLER 0x01 +#define PCI_SUB_CLASS_OTHER_MEMORY_CONTROLLER 0x80 + +/* BRIDGE CONTROLLER */ +#define PCI_SUB_CLASS_HOST_BRIDGE_CONTROLLER 0x00 +#define PCI_SUB_CLASS_ISA_BRIDGE_CONTROLLER 0x01 +#define PCI_SUB_CLASS_EISA_BRIDGE_CONTROLLER 0x02 +#define PCI_SUB_CLASS_MC_BRIDGE_CONTROLLER 0x03 +#define PCI_SUB_CLASS_PCI_TO_PCI_BRIDGE_CONTROLLER 0x04 +#define PCI_SUB_CLASS_PCMCIA_BRIDGE_CONTROLLER 0x05 +#define PCI_SUB_CLASS_OTHER_BRIDGE_CONTROLLER 0x80 + +#define PCI_MAX_SLOT 0x1F +#define PCI_MAX_BUS 0xFF +#define ASC_PCI_VENDORID 0x10CD +#define PCI_IOADDRESS_MASK 0xFFFE + +/* PCI IO Port Addresses to generate special cycle */ + +#define PCI_CONFIG_ADDRESS_MECH1 0x0CF8 +#define PCI_CONFIG_DATA_MECH1 0x0CFC + +#define PCI_CONFIG_FORWARD_REGISTER 0x0CFA /* 0=type 0; 1=type 1; */ + +#define PCI_CONFIG_BUS_NUMBER_MASK 0x00FF0000 +#define PCI_CONFIG_DEVICE_FUNCTION_MASK 0x0000FF00 +#define PCI_CONFIG_REGISTER_NUMBER_MASK 0x000000F8 + +#define PCI_DEVICE_FOUND 0x0000 +#define PCI_DEVICE_NOT_FOUND 0xffff + +#define SUBCLASS_OFFSET 0x0A +#define CLASSCODE_OFFSET 0x0B +#define VENDORID_OFFSET 0x00 +#define DEVICEID_OFFSET 0x02 + +/* + * --- Driver Macros + */ + +#ifndef ADVANSYS_STATS +#define ASC_STATS(counter) +#define ASC_STATS_ADD(counter, count) +#else /* ADVANSYS_STATS */ +#define ASC_STATS(counter) asc_stats.counter++ +#define ASC_STATS_ADD(counter, count) asc_stats.counter += (count) +#endif /* ADVANSYS_STATS */ + +#ifndef ADVANSYS_DEBUG + +#define ASC_DBG(lvl, s) +#define ASC_DBG1(lvl, s, a1) +#define ASC_DBG2(lvl, s, a1, a2) +#define ASC_DBG3(lvl, s, a1, a2, a3) +#define ASC_DBG4(lvl, s, a1, a2, a3, a4) +#define ASC_DBG_PRT_SCSI_HOST(lvl, s) +#define ASC_DBG_PRT_DVC_VAR(lvl, v) +#define ASC_DBG_PRT_DVC_CFG(lvl, c) +#define ASC_DBG_PRT_SCSI_Q(lvl, scsiqp) +#define ASC_DBG_PRT_QDONE_INFO(lvl, qdone) +#define ASC_DBG_PRT_HEX(lvl, name, start, length) +#define ASC_DBG_PRT_CDB(lvl, cdb, len) +#define ASC_DBG_PRT_SENSE(lvl, sense, len) +#define ASC_DBG_PRT_INQUIRY(lvl, inq, len) +#define ASC_ASSERT(a) + +#else /* ADVANSYS_DEBUG */ + +/* + * Debugging Message Levels: + * 0: Errors Only + * 1: High-Level Tracing + * 2-N: Verbose Tracing + */ + +#define ASC_DBG(lvl, s) \ + { \ + if (asc_dbglvl >= (lvl)) { \ + printk(s); \ + } \ + } + +#define ASC_DBG1(lvl, s, a1) \ + { \ + if (asc_dbglvl >= (lvl)) { \ + printk((s), (a1)); \ + } \ + } + +#define ASC_DBG2(lvl, s, a1, a2) \ + { \ + if (asc_dbglvl >= (lvl)) { \ + printk((s), (a1), (a2)); \ + } \ + } + +#define ASC_DBG3(lvl, s, a1, a2, a3) \ + { \ + if (asc_dbglvl >= (lvl)) { \ + printk((s), (a1), (a2), (a3)); \ + } \ + } + +#define ASC_DBG4(lvl, s, a1, a2, a3, a4) \ + { \ + if (asc_dbglvl >= (lvl)) { \ + printk((s), (a1), (a2), (a3), (a4)); \ + } \ + } + +#define ASC_DBG_PRT_SCSI_HOST(lvl, s) \ + { \ + if (asc_dbglvl >= (lvl)) { \ + asc_prt_scsi_host(s); \ + } \ + } + +#define ASC_DBG_PRT_DVC_VAR(lvl, v) \ + { \ + if (asc_dbglvl >= (lvl)) { \ + asc_prt_dvc_var(v); \ + } \ + } + +#define ASC_DBG_PRT_DVC_CFG(lvl, c) \ + { \ + if (asc_dbglvl >= (lvl)) { \ + asc_prt_dvc_cfg(c); \ + } \ + } + +#define ASC_DBG_PRT_SCSI_Q(lvl, scsiqp) \ + { \ + if (asc_dbglvl >= (lvl)) { \ + asc_prt_scsi_q(scsiqp); \ + } \ + } + +#define ASC_DBG_PRT_QDONE_INFO(lvl, qdone) \ + { \ + if (asc_dbglvl >= (lvl)) { \ + asc_prt_qdone_info(qdone); \ + } \ + } + +#define ASC_DBG_PRT_HEX(lvl, name, start, length) \ + { \ + if (asc_dbglvl >= (lvl)) { \ + asc_prt_hex((name), (start), (length)); \ + } \ + } + +#define ASC_DBG_PRT_CDB(lvl, cdb, len) \ + ASC_DBG_PRT_HEX((lvl), "CDB", (uchar *) (cdb), (len)); + +#define ASC_DBG_PRT_SENSE(lvl, sense, len) \ + ASC_DBG_PRT_HEX((lvl), "SENSE", (uchar *) (sense), (len)); + +#define ASC_DBG_PRT_INQUIRY(lvl, inq, len) \ + ASC_DBG_PRT_HEX((lvl), "INQUIRY", (uchar *) (inq), (len)); + +#define ASC_ASSERT(a) \ + { \ + if (!(a)) { \ + printk("ASC_ASSERT() Failure: file %s, line %d\n", \ + __FILE__, __LINE__); \ + } \ + } +#endif /* ADVANSYS_DEBUG */ + + +/* + * --- Driver Structures + */ + +/* + * Structure allocated for each board. + * + * This structure is allocated by scsi_register() at the end + * of the 'Scsi_Host' structure starting at the 'hostdata' + * field. It is guaranteed to be allocated from DMA-able memory. + */ +struct asc_board { + /* Asc Library */ + ASC_DVC_VAR board; /* Board configuration */ + ASC_DVC_CFG cfg; /* Device configuration */ + uchar overrun_buf[ASC_OVERRUN_BSIZE]; + /* Queued Commands */ + ASC_SCSI_BIT_ID_TYPE pending_tidmask; /* Pending command mask */ + Scsi_Cmnd *pending[ASC_MAX_TID]; + /* Target Initialization */ + ASC_SCSI_BIT_ID_TYPE init_tidmask; /* Target initialized mask */ + ASC_SCSI_REQ_Q scsireqq; + ASC_CAP_INFO cap_info; + ASC_SCSI_INQUIRY inquiry; +}; + +/* + * PCI configuration structures + */ +typedef struct _PCI_DATA_ +{ + uchar type; + uchar bus; + uchar slot; + uchar func; + uchar offset; +} PCI_DATA; + +typedef struct _PCI_DEVICE_ +{ + ushort vendorID; + ushort deviceID; + ushort slotNumber; + ushort slotFound; + uchar busNumber; + uchar maxBusNumber; + uchar devFunc; + ushort startSlot; + ushort endSlot; + uchar bridge; + uchar type; +} PCI_DEVICE; + +typedef struct _PCI_CONFIG_SPACE_ +{ + ushort vendorID; + ushort deviceID; + ushort command; + ushort status; + uchar revision; + uchar classCode[3]; + uchar cacheSize; + uchar latencyTimer; + uchar headerType; + uchar bist; + ulong baseAddress[6]; + ushort reserved[4]; + ulong optionRomAddr; + ushort reserved2[4]; + uchar irqLine; + uchar irqPin; + uchar minGnt; + uchar maxLatency; +} PCI_CONFIG_SPACE; + +#ifdef ADVANSYS_STATS +struct asc_stats { + ulong command; /* # calls to advansys_command() */ + ulong queuecommand; /* # calls to advansys_queuecommand() */ + ulong abort; /* # calls to advansys_abort() */ + ulong reset; /* # calls to advansys_reset() */ + ulong biosparam; /* # calls to advansys_biosparam() */ + ulong interrupt; /* # calls to advansys_interrupt() */ + ulong callback; /* # calls asc_isr_callback() */ + ulong cont_cnt; /* # non-scatter-gather I/O requests received */ + ulong cont_xfer; /* contiguous transfer total (512 byte units) */ + ulong sg_cnt; /* # scatter-gather I/O requests received */ + ulong sg_elem; /* scatter-gather element total */ + ulong sg_xfer; /* scatter-gather tranfer total (512 byte units) */ + ulong error; /* # AscExeScsiQueue() ASC_ERROR returns. */ + /* + * Number of times interrupts disabled in advansys_queuecommand() and + * asc_isr_callback(), respectively. For the former indicates how many + * times commands were pending when a new command was received. + */ + ulong cmd_disable; + ulong intr_disable; + /* + * Number of times asc_enqueue() called. Indicates how many ASC_BUSY + * returns have occurred. + */ + ulong enqueue; + ulong dequeue; /* # calls to asc_dequeue(). */ + /* + * Number of times asc_rmqueue() called and the specified command + * was found and removed. + */ + ulong rmqueue; +} asc_stats; +#endif /* ADVANSYS_STATS */ + + +/* + * --- Driver Data + */ + +#ifdef LINUX_1_3 +struct proc_dir_entry proc_scsi_advansys = +{ + PROC_SCSI_ADVANSYS, /* unsigned short low_ino */ + 8, /* unsigned short namelen */ + "advansys", /* const char *name */ + S_IFDIR | S_IRUGO | S_IXUGO, /* mode_t mode */ + 2 /* nlink_t nlink */ +}; +#endif /* LINUX_1_3 */ + +STATIC int asc_board_count; /* Number of boards detected in system. */ +STATIC struct Scsi_Host *asc_host[ASC_NUM_BOARD_SUPPORTED]; +STATIC Scsi_Cmnd *asc_scsi_done; /* Commands needing done function call. */ + +STATIC ushort asc_bus[ASC_NUM_BUS] = { + ASC_IS_ISA, + ASC_IS_VL, + ASC_IS_EISA, + ASC_IS_PCI, +}; + +/* + * Used with the LILO 'advansys' option to eliminate or + * limit I/O port probing at boot time, cf. advansys_setup(). + */ +int asc_iopflag = ASC_FALSE; +int asc_ioport[ASC_NUM_BOARD_SUPPORTED] = { 0, 0, 0, 0 }; + +#ifdef ADVANSYS_DEBUG +char * +asc_bus_name[ASC_NUM_BUS] = { + "ASC_IS_ISA", + "ASC_IS_VL", + "ASC_IS_EISA", + "ASC_IS_PCI", +}; + +int asc_dbglvl = 0; +#endif /* ADVANSYS_DEBUG */ + + +/* + * --- Driver Function Prototypes + * + * advansys.h contains function prototypes for functions global to Linux. + */ + +#ifdef LINUX_1_3 +STATIC int asc_proc_copy(off_t, off_t, char *, int , char *, int); +#endif /* LINUX_1_3 */ +STATIC void advansys_interrupt(int, struct pt_regs *); +STATIC void advansys_command_done(Scsi_Cmnd *); +STATIC int asc_execute_scsi_cmnd(Scsi_Cmnd *); +STATIC void asc_isr_callback(ASC_DVC_VAR *, ASC_QDONE_INFO *); +STATIC void asc_execute_pending(struct Scsi_Host *); +STATIC int asc_init_dev(ASC_DVC_VAR *, Scsi_Cmnd *); +STATIC int asc_srch_pci_dev(PCI_DEVICE *); +STATIC uchar asc_scan_method(PCI_DEVICE *); +STATIC int asc_pci_find_dev(PCI_DEVICE *); +STATIC void asc_get_pci_cfg(PCI_DEVICE *, PCI_CONFIG_SPACE *); +STATIC ushort asc_get_cfg_word(PCI_DATA *); +STATIC uchar asc_get_cfg_byte(PCI_DATA *); +STATIC void asc_enqueue(struct Scsi_Host *, Scsi_Cmnd *, int, int); +STATIC Scsi_Cmnd *asc_dequeue(struct Scsi_Host *, int); +STATIC int asc_rmqueue(struct Scsi_Host *, Scsi_Cmnd *, int); + +/* XXX - Asc Library Routines not supposed to be used directly */ +ushort AscGetChipBiosAddress(PortAddr, ushort); +int AscFindSignature(PortAddr); + +#ifdef ADVANSYS_STATS +STATIC int asc_prt_stats(char *, int); +STATIC int asc_prt_stats_line(char *, int, char *fmt, ...); +#endif /* ADVANSYS_STATS */ +#ifdef ADVANSYS_DEBUG +STATIC void asc_prt_scsi_host(struct Scsi_Host *); +STATIC void asc_prt_dvc_cfg(ASC_DVC_CFG *); +STATIC void asc_prt_dvc_var(ASC_DVC_VAR *); +STATIC void asc_prt_scsi_q(ASC_SCSI_Q *); +STATIC void asc_prt_qdone_info(ASC_QDONE_INFO *); +STATIC void asc_prt_hex(char *f, uchar *, int); +STATIC int interrupts_enabled(void); +#endif /* ADVANSYS_DEBUG */ + + +/* + * --- Linux 'Scsi_Host_Template' and advansys_setup() Functions + */ + +#ifdef LINUX_1_3 +/* + * advansys_proc_info() - /proc/scsi/advansys/[0-ASC_NUM_BOARD_SUPPORTED] + * + * *buffer: I/O buffer + * **start: if inout == FALSE pointer into buffer where user read should start + * offset: current offset into /proc/scsi/advansys file + * length: length of buffer + * hostno: Scsi_Host host_no + * inout: TRUE - user is writing; FALSE - user is reading + * + * Return the number of bytes read from or written to + * /proc/scsi/advansys file. + */ +int +advansys_proc_info(char *buffer, char **start, off_t offset, int length, + int hostno, int inout) +{ + struct Scsi_Host *shp; + int i; + char *cp; + int cplen; + int cnt; + int totcnt; + int leftlen; + char *curbuf; + off_t advoffset; + Scsi_Device *scd; + char prtbuf[480]; /* 6 lines */ + + ASC_DBG(1, "advansys_proc_info: begin\n"); + + /* + * User write not supported. + */ + if (inout == TRUE) { + return(-ENOSYS); + } + + /* + * User read of /proc/scsi/advansys file. + */ + + /* Find the specified board. */ + for (i = 0; i < asc_board_count; i++) { + if (asc_host[i]->host_no == hostno) { + break; + } + } + if (i == asc_board_count) { + return(-ENOENT); + } + shp = asc_host[i]; + + /* Always copy read data to the beginning of the buffer. */ + *start = buffer; + + curbuf = buffer; + advoffset = 0; + totcnt = 0; + leftlen = length; + + /* Get board information. */ + cp = (char *) advansys_info(shp); + strcat(cp, "\n"); + cplen = strlen(cp); + + /* Copy board information. */ + cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); + totcnt += cnt; + leftlen -= cnt; + if (leftlen == 0) { + ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); + return totcnt; + } + advoffset += cplen; + curbuf += cnt; + + /* + * Get and copy information for each device attached to the board. + */ + cp = &prtbuf[0]; + sprintf(cp, "\nDevices attached to SCSI Host %d:\n", shp->host_no); + cplen = strlen(cp); + cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); + totcnt += cnt; + leftlen -= cnt; + if (leftlen == 0) { + ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); + return totcnt; + } + advoffset += cplen; + curbuf += cnt; + + cp = &prtbuf[0]; + for (scd = scsi_devices; scd; scd = scd->next) { + if (scd->host == shp) { + proc_print_scsidevice(scd, cp, &cplen, 0); + cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); + totcnt += cnt; + leftlen -= cnt; + if (leftlen == 0) { + ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); + return totcnt; + } + advoffset += cplen; + curbuf += cnt; + } + } + +#ifdef ADVANSYS_STATS + /* + * prtbuf[] has about 6 lines worth of space. If the statistics ever + * get longer than 6 lines, prtbuf[] should be increased in size. If + * prtbuf[] is too small it will not be overwritten. Instead the user + * just won't get all of the available statistics. + */ + cp = &prtbuf[0]; + cplen = asc_prt_stats(cp, sizeof(prtbuf)); + cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); + totcnt += cnt; + leftlen -= cnt; + if (leftlen == 0) { + ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); + return totcnt; + } + advoffset += cplen; + curbuf += cnt; +#endif /* ADVANSYS_STATS */ + + ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); + + return totcnt; +} +#endif /* LINUX_1_3 */ + + +/* + * advansys_detect() + * + * Detect function for AdvanSys adapters. + * + * Argument is a pointer to the host driver's scsi_hosts entry. + * + * Return number of adapters found. + * + * Note: Because this function is called during system initialization + * it must not call SCSI mid-level functions including scsi_malloc() + * and scsi_free(). + */ +int +advansys_detect(Scsi_Host_Template *tpnt) +{ + static int detect_called = ASC_FALSE; + int iop; + int bus; + struct Scsi_Host *shp; + ASC_DVC_VAR *boardp; + int ioport = 0; + PCI_DEVICE pciDevice; + PCI_CONFIG_SPACE pciConfig; + int ret; + extern PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX]; + + + if (detect_called == ASC_FALSE) { + detect_called = ASC_TRUE; + } else { + printk("AdvanSys SCSI: advansys_detect() mulitple calls ignored\n"); + return 0; + } + + ASC_DBG(1, "advansys_detect: begin\n"); + +#ifdef LINUX_1_3 + tpnt->proc_dir = &proc_scsi_advansys; +#endif /* LINUX_1_3 */ + +#ifdef ADVANSYS_STATS + memset(&asc_stats, 0, sizeof(asc_stats)); +#endif /* ADVANSYS_STATS */ + + asc_board_count = 0; + + /* + * If I/O port probing has been modified, then verify and + * clean-up the 'asc_ioport' list. + */ + if (asc_iopflag == ASC_TRUE) { + for (ioport = 0; ioport < ASC_NUM_BOARD_SUPPORTED; ioport++) { + ASC_DBG2(1, "asdvansys_detect: asc_ioport[%d] %x\n", + ioport, asc_ioport[ioport]); + if (asc_ioport[ioport] != 0) { + for (iop = 0; iop < ASC_IOADR_TABLE_MAX_IX; iop++) { + if (_asc_def_iop_base[iop] == asc_ioport[ioport]) { + break; + } + } + if (iop == ASC_IOADR_TABLE_MAX_IX) { + printk("AdvanSys SCSI: specified I/O Port 0x%X is invalid\n", + asc_ioport[ioport]); + asc_ioport[ioport] = 0; + } + } + } + ioport = 0; + } + + memset(&pciDevice, 0, sizeof(PCI_DEVICE)); + memset(&pciConfig, 0, sizeof(PCI_CONFIG_SPACE)); + pciDevice.maxBusNumber = PCI_MAX_BUS; + pciDevice.endSlot = PCI_MAX_SLOT; + + for (bus = 0; bus < ASC_NUM_BUS; bus++) { + + ASC_DBG2(1, "advansys_detect: bus search type %d (%s)\n", + bus, asc_bus_name[bus]); + iop = 0; + + while (asc_board_count < ASC_NUM_BOARD_SUPPORTED) { + + ASC_DBG1(2, "advansys_detect: asc_board_count %d\n", + asc_board_count); + + switch (asc_bus[bus]) { + case ASC_IS_ISA: + case ASC_IS_VL: + if (asc_iopflag == ASC_FALSE) { + iop = AscSearchIOPortAddr(iop, asc_bus[bus]); + } else { + /* + * ISA and VL I/O port scanning has either been + * eliminated or limited to selected ports on + * the LILO command line, /etc/lilo.conf, or + * by setting variables when the module was loaded. + */ + ASC_DBG(1, "advansys_detect: I/O port scanning modified\n"); + ioport_try_again: + iop = 0; + for (; ioport < ASC_NUM_BOARD_SUPPORTED; ioport++) { + if ((iop = asc_ioport[ioport]) != 0) { + break; + } + } + if (iop) { + ASC_DBG1(1, "advansys_detect: probing I/O port %x...\n", + iop); + if (check_region(iop, ASC_IOADR_GAP) != 0) { + printk("AdvanSys SCSI: specified I/O Port 0x%X is busy\n", iop); + /* Don't try this I/O port twice. */ + asc_ioport[ioport] = 0; + goto ioport_try_again; + } else if (AscFindSignature(iop) == ASC_FALSE) { + printk("AdvanSys SCSI: specified I/O Port 0x%X has no adapter\n", iop); + /* Don't try this I/O port twice. */ + asc_ioport[ioport] = 0; + goto ioport_try_again; + } else { + /* + * If this isn't an ISA board, then it must be + * a VL board. If currently looking an ISA + * board is being looked for then try for + * another ISA board in 'asc_ioport'. + */ + if (asc_bus[bus] == ASC_IS_ISA && + (AscGetChipVersion(iop, ASC_IS_ISA) & + ASC_CHIP_VER_ISA_BIT) == 0) { + /* + * Don't clear 'asc_ioport[ioport]'. Try + * this board again for VL. Increment + * 'ioport' past this board. + */ + ioport++; + goto ioport_try_again; + } + } + /* + * This board appears good, don't try the I/O port + * again by clearing its value. Increment 'ioport' + * for the next iteration. + */ + asc_ioport[ioport++] = 0; + } + } + break; + + case ASC_IS_EISA: + iop = AscSearchIOPortAddr(iop, asc_bus[bus]); + break; + + case ASC_IS_PCI: + if (asc_srch_pci_dev(&pciDevice) != PCI_DEVICE_FOUND) { + iop = 0; + } else { + ASC_DBG2(2, + "advansys_detect: slotFound %d, busNumber %d\n", + pciDevice.slotFound, pciDevice.busNumber); + asc_get_pci_cfg(&pciDevice, &pciConfig); + iop = pciConfig.baseAddress[0] & PCI_IOADDRESS_MASK; + ASC_DBG2(2, "advansys_detect: iop %x, irqLine %d\n", + iop, pciConfig.irqLine); + } + break; + + default: + ASC_DBG(0, "advansys_detect: unknown bus type\n"); + break; + } + ASC_DBG1(1, "advansys_detect: iop %x\n", iop); + + /* + * Adapter not found, try next bus type. + */ + if (iop == 0) { + break; + } + + /* + * Adapter found. + * + * Register the adapter, get its configuration, and + * initialize it. + */ + ASC_DBG(2, "advansys_detect: scsi_register()\n"); + shp = scsi_register(tpnt, sizeof(struct asc_board)); + + /* Save a pointer to the Scsi_host of each found board. */ + asc_host[asc_board_count++] = shp; + + /* Initialize private per board data */ + memset(ASC_BOARD(shp), 0, sizeof(struct asc_board)); + boardp = &ASC_BOARD(shp)->board; + boardp->cfg = &ASC_BOARD(shp)->cfg; + boardp->cfg->overrun_buf = &ASC_BOARD(shp)->overrun_buf[0]; + boardp->iop_base = iop; + + /* + * Set the board bus type and PCI IRQ for AscInitGetConfig(). + */ + boardp->bus_type = asc_bus[bus]; + switch (boardp->bus_type) { + case ASC_IS_ISA: + shp->unchecked_isa_dma = TRUE; + break; + case ASC_IS_EISA: + shp->unchecked_isa_dma = FALSE; + break; + case ASC_IS_VL: + shp->unchecked_isa_dma = FALSE; + break; + case ASC_IS_PCI: + shp->irq = boardp->irq_no = pciConfig.irqLine; + boardp->cfg->pci_device_id = pciConfig.deviceID; + shp->unchecked_isa_dma = FALSE; + break; + default: + ASC_DBG(0, "advansys_detect: unknown adapter type"); + shp->unchecked_isa_dma = TRUE; + break; + } + + /* + * Get the board configuration. AscInitGetConfig() may change + * the board's bus_type value. The asc_bus[bus] value should no + * longer be used. + */ + ASC_DBG(2, "advansys_detect: AscInitGetConfig()\n"); + switch(ret = AscInitGetConfig(boardp)) { + case 0: /* No error */ + break; + case ASC_WARN_IO_PORT_ROTATE: + ASC_DBG(0, "AscInitGetConfig: I/O port address modified\n"); + break; + case ASC_WARN_EEPROM_CHKSUM: + ASC_DBG(0, "AscInitGetConfig: EEPROM checksum error\n"); + break; + case ASC_WARN_IRQ_MODIFIED: + ASC_DBG(0, "AscInitGetConfig: IRQ modified\n"); + break; + case ASC_WARN_CMD_QNG_CONFLICT: + ASC_DBG(0, + "AscInitGetConfig: Tag queuing enabled w/o disconnects\n"); + break; + default: + ASC_DBG1(0, "AscInitGetConfig: Unknown warning: %x\n", ret); + break; + } + if (boardp->err_code != 0) { + ASC_DBG2(0, + "AscInitGetConfig: error: init_state %x, err_code %x\n", + boardp->init_state, boardp->err_code); + scsi_unregister(shp); + asc_board_count--; + continue; + } + + /* + * Modify board configuration. + */ + boardp->isr_callback = (Ptr2Func) asc_isr_callback; + boardp->exe_callback = (Ptr2Func) NULL; + + ASC_DBG(2, "advansys_detect: AscInitSetConfig()\n"); + switch (ret = AscInitSetConfig(boardp)) { + case 0: /* No error. */ + break; + case ASC_WARN_IO_PORT_ROTATE: + ASC_DBG(0, "AscInitSetConfig: I/O port address modified\n"); + break; + case ASC_WARN_EEPROM_CHKSUM: + ASC_DBG(0, "AscInitSetConfig: EEPROM checksum error\n"); + break; + case ASC_WARN_IRQ_MODIFIED: + ASC_DBG(0, "AscInitSetConfig: IRQ modified\n"); + break; + case ASC_WARN_CMD_QNG_CONFLICT: + ASC_DBG(0, "AscInitSetConfig: Tag queuing w/o disconnects\n"); + break; + default: + ASC_DBG1(0, "AscInitSetConfig: Unknown warning: %x\n", ret); + break; + } + if (boardp->err_code != 0) { + ASC_DBG2(0, + "AscInitSetConfig: error: init_state %x, err_code %x\n", + boardp->init_state, boardp->err_code); + scsi_unregister(shp); + asc_board_count--; + continue; + } + + /* + * Finish initializing the 'Scsi_Host' structure. + */ + + /* AscInitSetConfig() will set the IRQ for non-PCI boards. */ + if (boardp->bus_type != ASC_IS_PCI) { + shp->irq = boardp->irq_no; + } + + shp->io_port = boardp->iop_base; + shp->n_io_port = ASC_IOADR_GAP; + shp->this_id = boardp->cfg->chip_scsi_id; + + /* Maximum number of queues this adapter can handle. */ + shp->can_queue = boardp->max_total_qng; + + /* + * XXX - Command queuing limits are maintained per target + * by AdvanSys adapters. Set 'cmd_per_lun' to the minimum + * value of the all the target settings for the adapter. + * + * For now set 'cmd_per_lun' to 'max_total_qng'. This + * value should be adjusted every time a new device is + * found in asc_init_dev(). + * + * XXX - memory allocation is done by the mid-level scsi + * driver based on 'cmd_per_lun'. If 'sg_tablesize' is too large + * allocation failures can occur in scsi_register_host(). + * A 'Scsi_Cmnd' structure is pre-allocated for each command + * also DMA memory is reserved. Set it artificially low for now. + * + * shp->cmd_per_lun = boardp->max_total_qng; + */ +#ifdef MODULE + shp->cmd_per_lun = 1; +#else /* MODULE */ + shp->cmd_per_lun = 4; +#endif /* MODULE */ + ASC_DBG1(1, "advansys_detect: cmd_per_lun: %d\n", shp->cmd_per_lun); + + /* Maximum number of scatter-gather elements adapter can handle. */ + /* + * XXX - memory allocation is done by the mid-level scsi + * driver based on sg_tablesize. If 'sg_tablesize' is too large + * allocation failures can occur in scsi_register_host(). + */ +#ifdef MODULE + shp->sg_tablesize = 8; +#else /* MODULE */ + shp->sg_tablesize = ASC_MAX_SG_LIST; +#endif /* MODULE */ + ASC_DBG1(1, "advansys_detect: sg_tablesize: %d\n", + shp->sg_tablesize); + + /* BIOS start address. */ + shp->base = (char *) ((ulong) AscGetChipBiosAddress( + boardp->iop_base, + boardp->bus_type)); + + /* + * Register Board Resources - I/O Port, DMA, IRQ + */ + + /* Register I/O port range */ + ASC_DBG(2, "advansys_detect: request_region()\n"); + request_region(shp->io_port, shp->n_io_port, "advansys"); + + /* Register DMA channel for ISA bus. */ + if ((boardp->bus_type & ASC_IS_ISA) == 0) { + shp->dma_channel = NO_ISA_DMA; + } else { + shp->dma_channel = boardp->cfg->isa_dma_channel; + if ((ret = request_dma(shp->dma_channel, "advansys")) != 0) { + ASC_DBG2(0, "advansys_detect: request_dma() %d failed %d\n", + shp->dma_channel, ret); + release_region(shp->io_port, shp->n_io_port); + scsi_unregister(shp); + asc_board_count--; + continue; + } + AscEnableIsaDma(shp->dma_channel); + } + + /* Register IRQ Number. */ + ASC_DBG1(2, "advansys_detect: request_irq() %d\n", shp->irq); + if ((ret = request_irq(shp->irq, advansys_interrupt, + SA_INTERRUPT, "advansys")) != 0) { + ASC_DBG1(0, "advansys_detect: request_irq() failed %d\n", ret); + release_region(shp->io_port, shp->n_io_port); + if (shp->dma_channel != NO_ISA_DMA) { + free_dma(shp->dma_channel); + } + scsi_unregister(shp); + asc_board_count--; + continue; + } + + /* + * Initialize board RISC chip and enable interrupts. + */ + ASC_DBG(2, "advansys_detect: AscInitAsc1000Driver()\n"); + if (AscInitAsc1000Driver(boardp)) { + ASC_DBG2(0, + "AscInitAsc1000Driver: error: init_state %x, err_code %x\n", + boardp->init_state, boardp->err_code); + release_region(shp->io_port, shp->n_io_port); + if (shp->dma_channel != NO_ISA_DMA) { + free_dma(shp->dma_channel); + } + free_irq(shp->irq); + scsi_unregister(shp); + asc_board_count--; + continue; + } + ASC_DBG_PRT_SCSI_HOST(2, shp); + } + } + + ASC_DBG1(1, "advansys_detect: done: asc_board_count %d\n", asc_board_count); + return asc_board_count; +} + +/* + * advansys_release() + * + * Release resources allocated for a single AdvanSys adapter. + */ +int +advansys_release(struct Scsi_Host *shp) +{ + ASC_DBG(1, "advansys_release: begin\n"); + free_irq(shp->irq); + if (shp->dma_channel != NO_ISA_DMA) { + ASC_DBG(1, "advansys_release: free_dma()\n"); + free_dma(shp->dma_channel); + } + release_region(shp->io_port, shp->n_io_port); + scsi_unregister(shp); + ASC_DBG(1, "advansys_release: end\n"); + return 0; +} + +/* + * advansys_info() + * + * Return suitable for printing on the console with the argument + * adapter's configuration information. + */ +const char * +advansys_info(struct Scsi_Host *shp) +{ + static char info[128]; + ASC_DVC_VAR *boardp; + char *busname; + + boardp = &ASC_BOARD(shp)->board; + ASC_DBG(1, "advansys_info: begin\n"); + if (boardp->bus_type & ASC_IS_ISA) { + sprintf(info, + "AdvanSys SCSI %s: ISA (%u CDB): BIOS %X, IO %X-%X, IRQ %u, DMA %u", + ASC_VERSION, ASC_BOARD(shp)->board.max_total_qng, + (unsigned) shp->base, shp->io_port, + shp->io_port + (shp->n_io_port - 1), shp->irq, shp->dma_channel); + } else { + switch (boardp->bus_type) { + case ASC_IS_EISA: + busname = "EISA"; + break; + case ASC_IS_VL: + busname = "VL"; + break; + case ASC_IS_PCI: + busname = "PCI"; + break; + default: + busname = "?"; + ASC_DBG1(0, "advansys_info: unknown bus type %d\n", + boardp->bus_type); + break; + } + /* No DMA channel for non-ISA busses. */ + sprintf(info, + "AdvanSys SCSI %s: %s (%u CDB): BIOS %X, IO %X-%X, IRQ %u", + ASC_VERSION, busname, ASC_BOARD(shp)->board.max_total_qng, + (unsigned) shp->base, shp->io_port, + shp->io_port + (shp->n_io_port - 1), shp->irq); + } + ASC_DBG(1, "advansys_info: end\n"); + return info; +} + +/* + * advansys_command() + * + * Polled-I/O. Apparently host driver shouldn't return until + * command is finished. + * + * XXX - Can host driver block here instead of spinning on command status? + */ +int +advansys_command(Scsi_Cmnd *scp) +{ + ASC_DBG1(1, "advansys_command: scp %x\n", (unsigned) scp); + ASC_STATS(command); + scp->SCp.Status = 0; /* Set to a known state */ + advansys_queuecommand(scp, advansys_command_done); + while (scp->SCp.Status == 0) { + continue; + } + ASC_DBG1(1, "advansys_command: result %x\n", scp->result); + return scp->result; +} + +/* + * advansys_queuecommand() + * + * This function always returns 0. Command return status is saved + * in the 'scp' result field. + */ +int +advansys_queuecommand(Scsi_Cmnd *scp, void (*done)(Scsi_Cmnd *)) +{ + struct Scsi_Host *shp; + int flags = 0; + int interrupts_disabled; + + ASC_STATS(queuecommand); + shp = scp->host; + +#ifdef LINUX_1_2 + /* + * For LINUX_1_3, if statistics are enabled they can be accessed + * by reading /proc/scsi/advansys/[0-9]. + */ +#ifdef ADVANSYS_STATS_1_2_PRINT + /* Display statistics every 10000 commands. */ + if ((asc_stats.queuecommand % 10000) == 0) { + printk("\n"); + (void) asc_prt_stats(NULL, 0); + printk("\n"); + } +#endif /* ADVANSYS_STATS_1_2_PRINT */ +#endif /* LINUX_1_2 */ + + /* + * If there are any pending commands for this board before trying + * to execute them, disable interrupts to preserve request ordering. + * + * The typical case will be no pending commands and interrupts + * not disabled. + */ + if (ASC_BOARD(shp)->pending_tidmask == 0) { + interrupts_disabled = ASC_FALSE; + } else { + ASC_STATS(cmd_disable); + /* Disable interrupts */ + interrupts_disabled = ASC_TRUE; + save_flags(flags); + cli(); + ASC_DBG1(1, "advansys_queuecommand: asc_execute_pending() %x\n", + ASC_BOARD(shp)->pending_tidmask); + asc_execute_pending(shp); + } + + /* + * Save the function pointer to Linux mid-level 'done' function and + * execute the command. + */ + scp->scsi_done = done; + if (asc_execute_scsi_cmnd(scp) == ASC_BUSY) { + if (interrupts_disabled == ASC_FALSE) { + save_flags(flags); + cli(); + interrupts_disabled = ASC_TRUE; + } + asc_enqueue(shp, scp, scp->target, ASC_BACK); + } + + if (interrupts_disabled == ASC_TRUE) { + restore_flags(flags); + } + + return 0; +} + +/* + * advansys_abort() + * + * Abort the specified command and reset the device + * associated with the command 'scp'. + */ +int +advansys_abort(Scsi_Cmnd *scp) +{ + ASC_DVC_VAR *boardp; + int flags; + int ret; + + ASC_DBG1(1, "advansys_abort: scp %x\n", (unsigned) scp); + save_flags(flags); + cli(); + ASC_STATS(abort); + if (scp->host == NULL) { + scp->result = HOST_BYTE(DID_ERROR); + ret = SCSI_ABORT_ERROR; + } else if (asc_rmqueue(scp->host, scp, scp->target) == ASC_TRUE) { + scp->result = HOST_BYTE(DID_ABORT); + ret = SCSI_ABORT_SUCCESS; + (void) AscResetDevice(&ASC_BOARD(scp->host)->board, scp->target); + } else { + /* Must enable interrupts for AscAbortSRB() */ + sti(); + boardp = &ASC_BOARD(scp->host)->board; + scp->result = HOST_BYTE(DID_ABORT); + switch (AscAbortSRB(boardp, (ulong) scp)) { + case ASC_TRUE: + /* asc_isr_callback() will be called */ + ASC_DBG(1, "advansys_abort: AscAbortSRB() TRUE\n"); + ret = SCSI_ABORT_PENDING; + break; + case ASC_FALSE: + /* Request has apparently already completed. */ + ASC_DBG(1, "advansys_abort: AscAbortSRB() FALSE\n"); + ret = SCSI_ABORT_NOT_RUNNING; + break; + case ASC_ERROR: + default: + ASC_DBG(1, "advansys_abort: AscAbortSRB() ERROR\n"); + ret = SCSI_ABORT_ERROR; + break; + } + (void) AscResetDevice(boardp, scp->target); + } + restore_flags(flags); + ASC_DBG1(1, "advansys_abort: ret %d\n", ret); + return ret; +} + +/* + * advansys_reset() + * + * Reset all devices and the SCSI bus for the board + * associated with 'scp'. + */ +int +advansys_reset(Scsi_Cmnd *scp) +{ + ASC_DVC_VAR *boardp; + int flags; + Scsi_Cmnd *tscp; + int i; + int ret; + + ASC_DBG1(1, "advansys_reset: %x\n", (unsigned) scp); + save_flags(flags); + cli(); + ASC_STATS(reset); + if (scp->host == NULL) { + scp->result = HOST_BYTE(DID_ERROR); + ret = SCSI_RESET_ERROR; + } else { + /* Remove any pending commands, set DID_RESET, and done them. */ + for (i = 0; i < ASC_MAX_TID; i++) { + while ((tscp = asc_dequeue(scp->host, i)) != NULL) { + tscp->result = HOST_BYTE(DID_RESET); + tscp->scsi_done(tscp); + } + } + /* Must enable interrupts for AscResetSB() */ + sti(); + boardp = &ASC_BOARD(scp->host)->board; + scp->result = HOST_BYTE(DID_RESET); + switch (AscResetSB(boardp)) { + case ASC_TRUE: + ASC_DBG(1, "advansys_abort: AscResetSB() TRUE\n"); + ret = SCSI_RESET_SUCCESS; + break; + case ASC_ERROR: + default: + ASC_DBG(1, "advansys_abort: AscResetSB() ERROR\n"); + ret = SCSI_RESET_ERROR; + break; + } + } + restore_flags(flags); + ASC_DBG1(1, "advansys_reset: ret %d", ret); + return ret; +} + +/* + * advansys_biosparam() + * + * Translate disk drive geometry if the "BIOS greater than 1 GB" + * support is enabled for a drive. + * + * ip (information pointer) is an int array with the following definition: + * ip[0]: heads + * ip[1]: sectors + * ip[2]: cylinders + */ +int +#ifdef LINUX_1_2 +advansys_biosparam(Disk *dp, int dep, int ip[]) +#else /* LINUX_1_3 */ +advansys_biosparam(Disk *dp, kdev_t dep, int ip[]) +#endif /* LINUX_1_3 */ +{ + ASC_DBG(1, "advansys_biosparam: begin\n"); + ASC_STATS(biosparam); + if ((ASC_BOARD(dp->device->host)->board.dvc_cntl & ASC_CNTL_BIOS_GT_1GB) && + dp->capacity > 0x200000) { + ip[0] = 255; + ip[1] = 64; + } else { + ip[0] = 64; + ip[1] = 32; + } + ip[2] = dp->capacity / (ip[0] * ip[1]); + ASC_DBG(1, "advansys_biosparam: end\n"); + return 0; +} + +/* + * advansys_setup() + * + * This function is called from init/main.c at boot time. + * It it passed LILO parameters that can be set from the + * LILO command line or in /etc/lilo.conf. + * + * It is used by the AdvanSys driver to either disable I/O + * port scanning or to limit scanning to 1 - 4 I/O ports. + * Regardless of the option setting EISA and PCI boards + * will still be searched for and detected. This option + * only affects searching for ISA and VL boards. + * + * If ADVANSYS_DEBUG is defined the driver debug level may + * be set using the 5th (ASC_NUM_BOARD_SUPPORTED + 1) I/O Port. + * + * Examples: + * 1. Eliminate I/O port scanning: + * boot: linux advansys= + * or + * boot: linux advansys=0x0 + * 2. Limit I/O port scanning to one I/O port: + * boot: linux advansys=0x110 + * 3. Limit I/O port scanning to four I/O ports: + * boot: linux advansys=0x110,0x210,0x230,0x330 + * 4. If ADVANSYS_DEBUG, limit I/O port scanning to four I/O ports and + * set the driver debug level to 2. + * boot: linux advansys=0x110,0x210,0x230,0x330,0xdeb2 + * + * ints[0] - number of arguments + * ints[1] - first argument + * ints[2] - second argument + * ... + */ +void +advansys_setup(char *str, int *ints) +{ + int i; + + if (asc_iopflag == ASC_TRUE) { + printk("AdvanSys SCSI: 'advansys' LILO option may appear only once\n"); + return; + } + + asc_iopflag = ASC_TRUE; + + if (ints[0] > ASC_NUM_BOARD_SUPPORTED) { +#ifdef ADVANSYS_DEBUG + if ((ints[0] == ASC_NUM_BOARD_SUPPORTED + 1) && + (ints[ASC_NUM_BOARD_SUPPORTED + 1] >> 4 == 0xdeb)) { + asc_dbglvl = ints[ASC_NUM_BOARD_SUPPORTED + 1] & 0xf; + } else { +#endif /* ADVANSYS_DEBUG */ + printk("AdvanSys SCSI: only %d I/O ports accepted\n", + ASC_NUM_BOARD_SUPPORTED); +#ifdef ADVANSYS_DEBUG + } +#endif /* ADVANSYS_DEBUG */ + } + +#ifdef ADVANSYS_DEBUG + ASC_DBG1(1, "advansys_setup: ints[0] %d\n", ints[0]); + for (i = 1; i < ints[0]; i++) { + ASC_DBG2(1, " ints[%d] %x", i, ints[i]); + } + ASC_DBG(1, "\n"); +#endif /* ADVANSYS_DEBUG */ + + for (i = 1; i <= ints[0] && i <= ASC_NUM_BOARD_SUPPORTED; i++) { + asc_ioport[i-1] = ints[i]; + ASC_DBG2(1, "advansys_setup: asc_ioport[%d] %x\n", + i - 1, asc_ioport[i-1]); + } +} + + +/* + * --- Loadable Driver Support + */ + +#ifdef MODULE +Scsi_Host_Template driver_template = ADVANSYS; +# include "scsi_module.c" +#endif /* MODULE */ + + +/* + * --- Miscellaneous Driver Functions + */ + +#ifdef LINUX_1_3 +/* + * asc_proc_copy() + * + * Copy proc information to a read buffer considering the current read + * offset in the file and the remaining space in the read buffer. + */ +STATIC int +asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen, + char *cp, int cplen) +{ + int cnt = 0; + + ASC_DBG3(2, "asc_proc_copy: offset %d, advoffset %d, cplen %d\n", + (unsigned) offset, (unsigned) advoffset, cplen); + if (offset <= advoffset) { + /* Read offset below current offset, copy everything. */ + cnt = min(cplen, leftlen); + ASC_DBG3(2, "asc_proc_copy: curbuf %x, cp %x, cnt %d\n", + (unsigned) curbuf, (unsigned) cp, cnt); + memcpy(curbuf, cp, cnt); + } else if (offset < advoffset + cplen) { + /* Read offset within current range, partial copy. */ + cnt = (advoffset + cplen) - offset; + cp = (cp + cplen) - cnt; + cnt = min(cnt, leftlen); + ASC_DBG3(2, "asc_proc_copy: curbuf %x, cp %x, cnt %d\n", + (unsigned) curbuf, (unsigned) cp, cnt); + memcpy(curbuf, cp, cnt); + } + return cnt; +} +#endif /* LINUX_1_3 */ + +/* + * First-level interrupt handler. + */ +STATIC void +advansys_interrupt(int irq, struct pt_regs *regs) +{ + int i; + int flags; + Scsi_Cmnd *scp; + Scsi_Cmnd *tscp; + + /* Disable interrupts, if the aren't already disabled. */ + save_flags(flags); + cli(); + + ASC_DBG(1, "advansys_interrupt: begin\n"); + ASC_STATS(interrupt); + /* + * Check for interrupts on all boards. + * AscISR() will call asc_isr_callback(). + */ + for (i = 0; i < asc_board_count; i++) { + while (AscIsIntPending(asc_host[i]->io_port)) { + ASC_DBG(1, "advansys_interrupt: before AscISR()\n"); + AscISR(&ASC_BOARD(asc_host[i])->board); + } + } + ASC_DBG(1, "advansys_interrupt: end\n"); + + /* + * While interrupts are still disabled save the list of requests that + * need their done function called. After re-enabling interrupts call + * the done function which may re-enable interrupts anyway. + */ + if ((scp = asc_scsi_done) != NULL) { + asc_scsi_done = NULL; + } + + /* Re-enable interrupts, if they were enabled on entry. */ + restore_flags(flags); + + while (scp) { + tscp = (Scsi_Cmnd *) scp->host_scribble; + scp->scsi_done(scp); + scp = tscp; + } + + return; +} + +/* + * Function used only with polled I/O requests that are initiated by + * advansys_command(). + */ +STATIC void +advansys_command_done(Scsi_Cmnd *scp) +{ + ASC_DBG1(1, "advansys_command_done: scp %x\n", (unsigned) scp); + scp->SCp.Status = 1; +} + +/* + * Execute a single 'Scsi_Cmnd'. + * + * The function 'done' is called when the request has been completed. + * + * Scsi_Cmnd: + * + * host - board controlling device + * device - device to send command + * target - target of device + * lun - lun of device + * cmd_len - length of SCSI CDB + * cmnd - buffer for SCSI 8, 10, or 12 byte CDB + * use_sg - if non-zero indicates scatter-gather request with use_sg elements + * + * if (use_sg == 0) + * request_buffer - buffer address for request + * request_bufflen - length of request buffer + * else + * request_buffer - pointer to scatterlist structure + * + * sense_buffer - sense command buffer + * + * result (4 bytes of an int): + * Byte Meaning + * 0 SCSI Status Byte Code + * 1 SCSI One Byte Message Code + * 2 Host Error Code + * 3 Mid-Level Error Code + * + * host driver fields: + * SCp - Scsi_Pointer used for command processing status + * scsi_done - used to save caller's done function + * host_scribble - used for pointer to another Scsi_Cmnd + * + * If this function returns ASC_NOERROR or ASC_ERROR the done + * function has been called. If ASC_BUSY is returned the request + * must be enqueued by the caller and re-tried later. + */ +STATIC int +asc_execute_scsi_cmnd(Scsi_Cmnd *scp) +{ + ASC_DVC_VAR *boardp; + ASC_SCSI_Q scsiq; + ASC_SG_HEAD sghead; + int ret; + + ASC_DBG2(1, "asc_execute_scsi_cmnd: scp %x, done %x\n", + (unsigned) scp, (unsigned) scp->scsi_done); + + boardp = &ASC_BOARD(scp->host)->board; + + /* + * If this is the first command, then initialize the device. If + * no device is found set 'DID_BAD_TARGET' and return. + */ + if ((ASC_BOARD(scp->host)->init_tidmask & + ASC_TIX_TO_TARGET_ID(scp->target)) == 0) { + if (asc_init_dev(boardp, scp) == ASC_FALSE) { + scp->result = HOST_BYTE(DID_BAD_TARGET); + scp->scsi_done(scp); + return ASC_ERROR; + } + ASC_BOARD(scp->host)->init_tidmask |= ASC_TIX_TO_TARGET_ID(scp->target); + } + + memset(&scsiq, 0, sizeof(ASC_SCSI_Q)); + + /* + * Point the ASC_SCSI_Q to the 'Scsi_Cmnd'. + */ + scsiq.q2.srb_ptr = (ulong) scp; + + /* + * Build the ASC_SCSI_Q request. + */ + scsiq.cdbptr = &scp->cmnd[0]; + scsiq.q2.cdb_len = scp->cmd_len; + scsiq.q1.target_id = ASC_TID_TO_TARGET_ID(scp->target); + scsiq.q1.target_lun = scp->lun; + scsiq.q2.target_ix = ASC_TIDLUN_TO_IX(scp->target, scp->lun); + scsiq.q1.sense_addr = (ulong) &scp->sense_buffer[0]; + scsiq.q1.sense_len = sizeof(scp->sense_buffer); + scsiq.q2.tag_code = M2_QTAG_MSG_SIMPLE; + + /* + * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather + * buffer command. + */ + if (scp->use_sg == 0) { + /* + * CDB request of single contiguous buffer. + */ + ASC_STATS(cont_cnt); + /* request_buffer is already a real address. */ + scsiq.q1.data_addr = (ulong) scp->request_buffer; + scsiq.q1.data_cnt = scp->request_bufflen; + ASC_STATS_ADD(cont_xfer, (scp->request_bufflen + 511) >> 9); + scsiq.q1.sg_queue_cnt = 0; + scsiq.sg_head = NULL; + } else { + /* + * CDB scatter-gather request list. + */ + int sgcnt; + struct scatterlist *slp; + + if (scp->use_sg > ASC_MAX_SG_LIST) { + ASC_DBG2(0, "asc_execute_scsi_cmnd: use_sg %d > %d\n", + scp->use_sg, ASC_MAX_SG_LIST); + scp->result = HOST_BYTE(DID_ERROR); + scp->scsi_done(scp); + return ASC_ERROR; + } + + ASC_STATS(sg_cnt); + + /* + * Allocate a ASC_SG_HEAD structure and set the ASC_SCSI_Q + * to point to it. + */ + memset(&sghead, 0, sizeof(ASC_SG_HEAD)); + + scsiq.q1.cntl |= QC_SG_HEAD; + scsiq.sg_head = &sghead; + scsiq.q1.data_cnt = 0; + scsiq.q1.data_addr = 0; + sghead.entry_cnt = scsiq.q1.sg_queue_cnt = scp->use_sg; + ASC_STATS_ADD(sg_elem, sghead.entry_cnt); + + /* + * Convert scatter-gather list into ASC_SG_HEAD list. + */ + slp = (struct scatterlist *) scp->request_buffer; + for (sgcnt = 0; sgcnt < scp->use_sg; sgcnt++, slp++) { + sghead.sg_list[sgcnt].addr = (ulong) slp->address; + sghead.sg_list[sgcnt].bytes = slp->length; + ASC_STATS_ADD(sg_xfer, (slp->length + 511) >> 9); + } + } + + ASC_DBG_PRT_SCSI_Q(2, &scsiq); + ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len); + + switch (ret = AscExeScsiQueue(boardp, &scsiq)) { + case ASC_NOERROR: + ASC_DBG(1, "asc_execute_scsi_cmnd: AscExeScsiQueue() ASC_NOERROR\n"); + break; + case ASC_BUSY: + /* Caller must enqueue request and retry later. */ + break; + case ASC_ERROR: + ASC_DBG1(0, + "asc_execute_scsi_cmnd: AscExeScsiQueue() ASC_ERROR err_code %x\n", + boardp->err_code); + ASC_STATS(error); + scp->result = HOST_BYTE(DID_ERROR); + scp->scsi_done(scp); + break; + } + + ASC_DBG(1, "asc_execute_scsi_cmnd: end\n"); + return ret; +} + +/* + * asc_isr_callback() - Second Level Interrupt Handler called by AscISR(). + */ +void +asc_isr_callback(ASC_DVC_VAR *boardp, ASC_QDONE_INFO *qdonep) +{ + Scsi_Cmnd *scp; + struct Scsi_Host *shp; + int flags; + Scsi_Cmnd **scpp; + + ASC_ASSERT(interrupts_enabled() == ASC_FALSE); + ASC_DBG2(1, "asc_isr_callback: boardp %x, qdonep %x\n", + (unsigned) boardp, (unsigned) qdonep); + ASC_STATS(callback); + ASC_DBG_PRT_QDONE_INFO(2, qdonep); + + /* + * Get the Scsi_Cmnd structure and Scsi_Host structure for the + * command that has been completed. + */ + scp = (Scsi_Cmnd *) qdonep->d2.srb_ptr; + ASC_DBG1(1, "asc_isr_callback: scp %x\n", (unsigned) scp); + ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len); + + shp = scp->host; + ASC_ASSERT(shp); + ASC_DBG1(1, "asc_isr_callback: shp %x\n", (unsigned) shp); + + /* + * 'qdonep' contains the command's ending status. + */ + switch (qdonep->d3.done_stat) { + case QD_NO_ERROR: + ASC_DBG(2, "asc_isr_callback: QD_NO_ERROR\n"); + switch (qdonep->d3.host_stat) { + case QHSTA_NO_ERROR: + scp->result = 0; + break; + default: + /* QHSTA error occurred */ + scp->result = HOST_BYTE(DID_ERROR); + break; + } + break; + + case QD_WITH_ERROR: + ASC_DBG(2, "asc_isr_callback: QD_WITH_ERROR\n"); + switch (qdonep->d3.host_stat) { + case QHSTA_NO_ERROR: + if (qdonep->d3.scsi_stat == SS_CHK_CONDITION) { + ASC_DBG(2, "asc_isr_callback: SS_CHK_CONDITION\n"); + ASC_DBG_PRT_SENSE(2, scp->sense_buffer, + sizeof(scp->sense_buffer)); + /* + * Note: The status_byte() macro used by target drivers + * defined in scsi.h shifts the status byte returned by + * host drivers right by 1 bit. This is why target drivers + * also use left shifted status byte definitions. For instance + * target drivers use CHECK_CONDITION, defined to 0x1, instead + * of the SCSI defined check condition value of 0x2. + */ + scp->result = DRIVER_BYTE(DRIVER_SENSE) | + STATUS_BYTE(qdonep->d3.scsi_stat); + } else { + scp->result = STATUS_BYTE(qdonep->d3.scsi_stat); + } + break; + + default: + /* QHSTA error occurred */ + ASC_DBG1(2, "asc_isr_callback: host_stat %x\n", + qdonep->d3.host_stat); + scp->result = HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.scsi_msg) | + STATUS_BYTE(qdonep->d3.scsi_stat); + break; + } + break; + + case QD_ABORTED_BY_HOST: + ASC_DBG(1, "asc_isr_callback: QD_ABORTED_BY_HOST\n"); + scp->result = HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3.scsi_msg) | + STATUS_BYTE(qdonep->d3.scsi_stat); + break; + + default: + ASC_DBG1(0, "asc_isr_callback: done_stat %x\n", qdonep->d3.done_stat ); + scp->result = HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.scsi_msg) | + STATUS_BYTE(qdonep->d3.scsi_stat); + break; + } + + /* + * Before calling 'scsi_done' for the current 'Scsi_Cmnd' and possibly + * triggering more commands to be issued, try to start any pending + * commands. + */ + if (ASC_BOARD(shp)->pending_tidmask != 0) { + /* + * If there are any pending commands for this board before trying + * to execute them, disable interrupts to preserve request ordering. + */ + ASC_STATS(intr_disable); + save_flags(flags); + cli(); + ASC_DBG1(1, "asc_isr_callback: asc_execute_pending() %x\n", + ASC_BOARD(shp)->pending_tidmask); + asc_execute_pending(shp); + restore_flags(flags); + } + + /* + * Because interrupts may be enabled by the 'Scsi_Cmnd' done function, + * add the command to the end of the global done list. The done function + * for the command will be called in advansys_interrupt(). + */ + for (scpp = &asc_scsi_done; *scpp; + scpp = (Scsi_Cmnd **) &(*scpp)->host_scribble) { + ; + } + *scpp = scp; + scp->host_scribble = NULL; + return; +} + +/* + * Execute as many pending requests as possible for the + * board specified by 'Scsi_Host'. + */ +STATIC void +asc_execute_pending(struct Scsi_Host *shp) +{ + ASC_SCSI_BIT_ID_TYPE scan_tidmask; + Scsi_Cmnd *scp; + int i; + + ASC_ASSERT(interrupts_enabled() == ASC_FALSE); + /* + * Execute pending commands for devices attached to + * the current board in round-robin fashion. + */ + scan_tidmask = ASC_BOARD(shp)->pending_tidmask; + do { + for (i = 0; i < ASC_MAX_TID; i++) { + if (scan_tidmask & ASC_TIX_TO_TARGET_ID(i)) { + if ((scp = asc_dequeue(shp, i)) == NULL) { + scan_tidmask &= ~ASC_TIX_TO_TARGET_ID(i); + } else if (asc_execute_scsi_cmnd(scp) == ASC_BUSY) { + scan_tidmask &= ~ASC_TIX_TO_TARGET_ID(i); + /* Put the request back at front of the list. */ + asc_enqueue(shp, scp, i, ASC_FRONT); + } + } + } + } while (scan_tidmask); + return; +} + +/* + * asc_init_dev() + * + * Perform one-time initialization of a device. + */ +STATIC int +asc_init_dev(ASC_DVC_VAR *boardp, Scsi_Cmnd *scp) +{ + ASC_SCSI_REQ_Q *scsireqq; + ASC_CAP_INFO *cap_info; + ASC_SCSI_INQUIRY *inquiry; + int found; + ASC_SCSI_BIT_ID_TYPE save_use_tagged_qng; + ASC_SCSI_BIT_ID_TYPE save_can_tagged_qng; + int ret; +#ifdef ADVANSYS_DEBUG + ASC_SCSI_BIT_ID_TYPE tidmask; /* target id bit mask: 1 - 128 */ +#endif /* ADVANSYS_DEBUG */ + + ASC_DBG1(1, "asc_init_dev: target %d\n", (unsigned) scp->target); + + /* Return true for the board's target id. */ + if (boardp->cfg->chip_scsi_id == scp->target) { + return ASC_TRUE; + } + + /* + * XXX - Host drivers should not modify the timeout field. + * But on the first command only add some extra time to + * allow the driver to complete its initialization for the + * device. + */ + scp->timeout += 2000; /* Add 5 seconds to the request timeout. */ + + /* Set-up AscInitPollTarget() arguments. */ + scsireqq = &ASC_BOARD(scp->host)->scsireqq; + memset(scsireqq, 0, sizeof(ASC_SCSI_REQ_Q)); + cap_info = &ASC_BOARD(scp->host)->cap_info; + memset(cap_info, 0, sizeof(ASC_CAP_INFO)); + inquiry = &ASC_BOARD(scp->host)->inquiry; + memset(inquiry, 0, sizeof(ASC_SCSI_INQUIRY)); + + /* + * XXX - AscInitPollBegin() re-initializes these fields to + * zero. 'Or' in the new values and restore them before calling + * AscInitPollEnd(). Normally all targets are initialized within + * a call to AscInitPollBegin() and AscInitPollEnd(). + */ + save_use_tagged_qng = boardp->use_tagged_qng; + save_can_tagged_qng = boardp->cfg->can_tagged_qng; + + ASC_DBG(2, "asc_init_dev: AscInitPollBegin()\n"); + if (AscInitPollBegin(boardp)) { + ASC_DBG(0, "asc_init_dev: AscInitPollBegin() failed\n"); + return ASC_FALSE; + } + + scsireqq->sense_ptr = &scsireqq->sense[0]; + scsireqq->r1.sense_len = ASC_MIN_SENSE_LEN; + scsireqq->r1.target_id = ASC_TID_TO_TARGET_ID(scp->target); + scsireqq->r1.target_lun = 0; + scsireqq->r2.target_ix = ASC_TIDLUN_TO_IX(scp->target, 0); + + found = ASC_FALSE; + ASC_DBG(2, "asc_init_dev: AscInitPollTarget()\n"); + switch (ret = AscInitPollTarget(boardp, scsireqq, inquiry, cap_info)) { + case ASC_TRUE: + found = ASC_TRUE; +#ifdef ADVANSYS_DEBUG + tidmask = ASC_TIX_TO_TARGET_ID(scp->target); + ASC_DBG2(1, "asc_init_dev: lba %lu, blk_size %lu\n", + cap_info->lba, cap_info->blk_size); + ASC_DBG1(1, "asc_init_dev: peri_dvc_type %x\n", + inquiry->byte0.peri_dvc_type); + if (boardp->use_tagged_qng & tidmask) { + ASC_DBG1(1, "asc_init_dev: command queuing enabled: %d\n", + boardp->max_dvc_qng[scp->target]); + } else { + ASC_DBG(1, "asc_init_dev: command queuing disabled\n"); + } + if (boardp->init_sdtr & tidmask) { + ASC_DBG(1, "asc_init_dev: synchronous transfers enabled\n"); + } else { + ASC_DBG(1, "asc_init_dev: synchronous transfers disabled\n"); + } + /* Set bit means fix disabled. */ + if (boardp->pci_fix_asyn_xfer & tidmask) { + ASC_DBG(1, "asc_init_dev: synchronous transfer fix disabled\n"); + } else { + ASC_DBG(1, "asc_init_dev: synchronous transfer fix enabled\n"); + } +#endif /* ADVANSYS_DEBUG */ + break; + case ASC_FALSE: + ASC_DBG(1, "asc_init_dev: no device found\n"); + break; + case ASC_ERROR: + ASC_DBG(0, "asc_init_dev: AscInitPollTarget() ASC_ERROR\n"); + break; + default: + ASC_DBG1(0, "asc_init_dev: AscInitPollTarget() unknown ret %d\n", ret); + break; + } + + /* XXX - 'Or' in original tag bits. */ + boardp->use_tagged_qng |= save_use_tagged_qng; + boardp->cfg->can_tagged_qng |= save_can_tagged_qng; + + ASC_DBG(2, "asc_init_dev: AscInitPollEnd()\n"); + AscInitPollEnd(boardp); + +#ifdef ASC_SET_CMD_PER_LUN + /* + * XXX - Refer to the comment in advansys_detect() + * regarding cmd_per_lun. + */ + for (i = 0; i <= ASC_MAX_TID; i++) { + if (boardp->max_dvc_qng[i] < scp->host->cmd_per_lun) { + scp->host->cmd_per_lun = boardp->max_dvc_qng[i]; + } + } +#endif /* ASC_SET_CMD_PER_LUN */ + + return found; +} + +/* + * Search for an AdvanSys PCI device in the PCI configuration space. + */ +STATIC int +asc_srch_pci_dev(PCI_DEVICE *pciDevice) +{ + int ret; + static int scan = 1; + + ASC_DBG(2, "asc_srch_pci_dev: begin\n"); + + if (scan) { + pciDevice->type = asc_scan_method(pciDevice); + scan = 0; + ASC_DBG1(2, "asc_srch_pci_dev: type %d\n", pciDevice->type); + } + ret = asc_pci_find_dev(pciDevice); + ASC_DBG1(2, "asc_srch_pci_dev: asc_pci_find_dev() return %d\n", ret); + if (ret == PCI_DEVICE_FOUND) { + pciDevice->slotNumber = pciDevice->slotFound + 1; + pciDevice->startSlot = pciDevice->slotFound + 1; + } else { + if (pciDevice->bridge > pciDevice->busNumber) { + ASC_DBG2(2, "asc_srch_pci_dev: bridge %x, busNumber %x\n", + pciDevice->bridge, pciDevice->busNumber); + pciDevice->busNumber++; + pciDevice->slotNumber = 0; + pciDevice->startSlot = 0; + pciDevice->endSlot = 0x0f; + ret = asc_srch_pci_dev(pciDevice); + ASC_DBG1(2, "asc_srch_pci_dev recursive call return %d\n", ret); + } + } + ASC_DBG1(2, "asc_srch_pci_dev: return %d\n", ret); + return ret; +} + +/* + * Determine the access method to be used for 'pciDevice'. + */ +STATIC uchar +asc_scan_method(PCI_DEVICE *pciDevice) +{ + ushort data; + PCI_DATA pciData; + uchar type; + uchar slot; + + ASC_DBG(2, "asc_scan_method: begin\n"); + memset(&pciData, 0, sizeof(pciData)); + for (type = 1; type < 3; type++) { + pciData.type = type; + for (slot = 0; slot < PCI_MAX_SLOT; slot++) { + pciData.slot = slot; + data = asc_get_cfg_word(&pciData); + if ((data != 0xFFFF) && (data != 0x0000)) { + ASC_DBG2(4, "asc_scan_method: data %x, type %d\n", data, type); + return (type); + } + } + } + ASC_DBG1(4, "asc_scan_method: type %d\n", type); + return (type); +} + +/* + * Check for an AdvanSys PCI device in 'pciDevice'. + * + * Return PCI_DEVICE_FOUND if found, otherwise return PCI_DEVICE_NOT_FOUND. + */ +STATIC int +asc_pci_find_dev(PCI_DEVICE *pciDevice) +{ + PCI_DATA pciData; + ushort vendorid, deviceid; + uchar classcode, subclass; + uchar lslot; + + ASC_DBG(3, "asc_pci_find_dev: begin\n"); + pciData.type = pciDevice->type; + pciData.bus = pciDevice->busNumber; + pciData.func = pciDevice->devFunc; + lslot = pciDevice->startSlot; + for (; lslot < pciDevice->endSlot; lslot++) { + pciData.slot = lslot; + pciData.offset = VENDORID_OFFSET; + vendorid = asc_get_cfg_word(&pciData); + ASC_DBG1(3, "asc_pci_find_dev: vendorid %x\n", vendorid); + if (vendorid != 0xffff) { + pciData.offset = DEVICEID_OFFSET; + deviceid = asc_get_cfg_word(&pciData); + ASC_DBG1(3, "asc_pci_find_dev: deviceid %x\n", deviceid); + if ((vendorid == ASC_PCI_VENDORID) && + ((deviceid == ASC_PCI_DEVICE_ID_REV_A) || + (deviceid == ASC_PCI_DEVICE_ID_REV_B))) { + pciDevice->slotFound = lslot; + ASC_DBG(3, "asc_pci_find_dev: PCI_DEVICE_FOUND\n"); + return PCI_DEVICE_FOUND; + } else { + pciData.offset = SUBCLASS_OFFSET; + subclass = asc_get_cfg_byte(&pciData); + pciData.offset = CLASSCODE_OFFSET; + classcode = asc_get_cfg_byte(&pciData); + if ((classcode & PCI_BASE_CLASS_BRIDGE_DEVICE) && + (subclass & PCI_SUB_CLASS_PCI_TO_PCI_BRIDGE_CONTROLLER)) { + pciDevice->bridge++; + } + ASC_DBG2(3, "asc_pci_find_dev: subclass %x, classcode %x\n", + subclass, classcode); + } + } + } + return PCI_DEVICE_NOT_FOUND; +} + +/* + * Read PCI configuration data into 'pciConfig'. + */ +STATIC void +asc_get_pci_cfg(PCI_DEVICE *pciDevice, PCI_CONFIG_SPACE *pciConfig) +{ + PCI_DATA pciData; + uchar counter; + uchar *localConfig; + + ASC_DBG1(4, "asc_get_pci_cfg: slot found - %d\n ", + pciDevice->slotFound); + + pciData.type = pciDevice->type; + pciData.bus = pciDevice->busNumber; + pciData.slot = pciDevice->slotFound; + pciData.func = pciDevice->devFunc; + localConfig = (uchar *) pciConfig; + + for (counter = 0; counter < sizeof(PCI_CONFIG_SPACE); counter++) { + pciData.offset = counter; + *localConfig = asc_get_cfg_byte(&pciData); + ASC_DBG1(4, "asc_get_pci_cfg: byte %x\n", *localConfig); + localConfig++; + } + ASC_DBG1(4, "asc_get_pci_cfg: counter %d\n", counter); +} + +/* + * Read a word (16 bits) from the PCI configuration space. + * + * The configuration mechanism is checked for the correct access method. + */ +STATIC ushort +asc_get_cfg_word(PCI_DATA *pciData) +{ + ushort tmp; + ulong address; + ulong lbus = pciData->bus; + ulong lslot = pciData->slot; + ulong lfunc = pciData->func; + uchar t2CFA, t2CF8; + ushort t1CF8, t1CFA, t1CFC, t1CFE; + + ASC_DBG4(4, "asc_get_cfg_word: type %d, bus %lu, slot %lu, func %lu\n", + pciData->type, lbus, lslot, lfunc); + + /* + * check type of configuration mechanism + */ + if (pciData->type == 2) { + /* + * save these registers so we can restore them after we are done + */ + t2CFA = inp(0xCFA); /* save PCI bus register */ + t2CF8 = inp(0xCF8); /* save config space enable register */ + + /* + * go out and write the bus and enable registers + */ + /* set for type 1 cycle, if needed */ + outp(0xCFA, pciData->bus); + /* set the function number */ + outp(0xCF8, 0x10 | (pciData->func << 1)) ; + + /* + * read the configuration space type 2 locations + */ + tmp = (ushort) inpw(0xC000 | ((pciData->slot << 8) + pciData->offset)); + } else { + /* + * type 1 configuration mechanism + * + * save the CONFIG_ADDRESS and CONFIG_DATA register values + */ + t1CFC = inpw(0xCFC); + t1CFE = inpw(0xCFE); + t1CF8 = inpw(0xCF8); + t1CFA = inpw(0xCFA); + + /* + * enable <31>, bus = <23:16>, slot = <15:11>, + * func = <10:8>, reg = <7:2> + */ + address = (ulong) ((lbus << 16) | (lslot << 11) | + (lfunc << 8) | (pciData->offset & 0xFC) | 0x80000000L); + + /* + * write out the address to CONFIG_ADDRESS + */ + outl(address, 0xCF8); + + /* + * read in the word from CONFIG_DATA + */ + tmp = (ushort) ((inl(0xCFC) >> + ((pciData->offset & 2) * 8)) & 0xFFFF); + } + ASC_DBG1(4, "asc_get_cfg_word: config data: %x\n", tmp); + return tmp; +} + +/* + * Reads a byte from the PCI configuration space. + * + * The configuration mechanism is checked for the correct access method. + */ +STATIC uchar +asc_get_cfg_byte(PCI_DATA *pciData) +{ + uchar tmp; + ulong address; + ulong lbus = pciData->bus, lslot = pciData->slot, lfunc = pciData->func; + uchar t2CFA, t2CF8; + ushort t1CF8, t1CFA, t1CFC, t1CFE; + + ASC_DBG1(4, "asc_get_cfg_byte: type: %d\n", pciData->type); + + /* + * check type of configuration mechanism + */ + if (pciData->type == 2) { + /* + * save these registers so we can restore them after we are done + */ + t2CFA = inp(0xCFA); /* save PCI bus register */ + t2CF8 = inp(0xCF8); /* save config space enable register */ + + /* + * go out and write the bus and enable registers + */ + /* set for type 1 cycle, if needed */ + outp(0xCFA, pciData->bus); + /* set the function number */ + outp(0xCF8, 0x10 | (pciData->func << 1)); + + /* + * read the configuration space type 2 locations + */ + tmp = inp(0xC000 | ((pciData->slot << 8) + pciData->offset)); + + /* + * restore the registers used for our transaction + */ + outp(0xCF8, t2CF8); /* restore the enable register */ + outp(0xCFA, t2CFA); /* restore PCI bus register */ + } else { + /* + * type 1 configuration mechanism + * + * save the CONFIG_ADDRESS and CONFIG_DATA register values + */ + t1CFC = inpw(0xCFC); + t1CFE = inpw(0xCFE); + t1CF8 = inpw(0xCF8); + t1CFA = inpw(0xCFA); + + /* + * enable <31>, bus = <23:16>, slot = <15:11>, func = <10:8>, + * reg = <7:2> + */ + address = (ulong) ((lbus << 16) | (lslot << 11) | + (lfunc << 8) | (pciData->offset & 0xFC) | 0x80000000L); + + /* + * write out the address to CONFIG_ADDRESS + */ + outl(address, 0xCF8); + + /* + * read in the word from CONFIG_DATA + */ + tmp = (uchar) ((inl(0xCFC) >> ((pciData->offset & 3) * 8)) & 0xFF); + } + ASC_DBG1(4, "asc_get_cfg_byte: config data: %x\n", tmp); + return tmp; +} + +/* + * Add a 'Scsi_Cmnd' to the end of specified 'Scsi_Host' + * target device pending command list. Set 'pending_tidmask' + * to indicate a command is queued for the device. + * + * 'flag' may be either ASC_FRONT or ASC_BACK. + * + * The 'Scsi_Cmnd' host_scribble field is used as a next pointer. + */ +STATIC void +asc_enqueue(struct Scsi_Host *shp, Scsi_Cmnd *scp, int tid, int flag) +{ + Scsi_Cmnd **scpp; + + ASC_ASSERT(interrupts_enabled() == ASC_FALSE); + ASC_ASSERT(flag == ASC_FRONT || flag == ASC_BACK); + ASC_STATS(enqueue); + if (flag == ASC_FRONT) { + scp->host_scribble = (unsigned char *) ASC_BOARD(shp)->pending[tid]; + ASC_BOARD(shp)->pending[tid] = (Scsi_Cmnd *) scp; + } else { /* ASC_BACK */ + for (scpp = &ASC_BOARD(shp)->pending[tid]; *scpp; + scpp = (Scsi_Cmnd **) &(*scpp)->host_scribble) { + ; + } + *scpp = scp; + scp->host_scribble = NULL; + } + ASC_BOARD(shp)->pending_tidmask |= ASC_TIX_TO_TARGET_ID(tid); +} + +/* + * Return first pending 'Scsi_Cmnd' on the specified 'Scsi_Host' + * for the specified target device. Clear the 'pending_tidmask' + * bit for the device if no more commands are left queued for it. + * + * The 'Scsi_Cmnd' host_scribble field is used as a next pointer. + */ +STATIC Scsi_Cmnd * +asc_dequeue(struct Scsi_Host *shp, int tid) +{ + Scsi_Cmnd *scp; + + ASC_STATS(dequeue); + ASC_ASSERT(interrupts_enabled() == ASC_FALSE); + if ((scp = ASC_BOARD(shp)->pending[tid]) != NULL) { + ASC_BOARD(shp)->pending[tid] = (Scsi_Cmnd *) scp->host_scribble; + } + if (ASC_BOARD(shp)->pending[tid] == NULL) { + ASC_BOARD(shp)->pending_tidmask &= ~ASC_TIX_TO_TARGET_ID(tid); + } + return scp; +} + +/* + * Remove the specified 'Scsi_Cmnd' from the specified 'Scsi_Host' + * for the specified target device. Clear the 'pending_tidmask' + * bit for the device if no more commands are left queued for it. + * + * The 'Scsi_Cmnd' host_scribble field is used as a next pointer. + * + * Return ASC_TRUE if the command was found and removed, otherwise + * return ASC_FALSE if the command was not found. + */ +STATIC int +asc_rmqueue(struct Scsi_Host *shp, Scsi_Cmnd *scp, int tid) +{ + Scsi_Cmnd **scpp; + int ret; + + ASC_ASSERT(interrupts_enabled() == ASC_FALSE); + ret = ASC_FALSE; + for (scpp = &ASC_BOARD(shp)->pending[tid]; + *scpp; scpp = (Scsi_Cmnd **) &(*scpp)->host_scribble) { + if (*scpp == scp) { + *scpp = (Scsi_Cmnd *) scp->host_scribble; + scp->host_scribble = NULL; + ASC_STATS(rmqueue); + ret = ASC_TRUE; + } + } + if (ASC_BOARD(shp)->pending[tid] == NULL) { + ASC_BOARD(shp)->pending_tidmask &= ~ASC_TIX_TO_TARGET_ID(tid); + } + return ret; +} + + +/* + * --- Functions Required by the Asc Library + */ + +/* + * Delay for 'n' milliseconds. Don't use the 'jiffies' + * global variable which is incremented once every 5 ms + * from a timer interrupt, because this function may be + * called when interrupts are disabled. + */ +void +DvcSleepMilliSecond(ulong n) +{ + ulong i; + + ASC_DBG1(4, "DvcSleepMilliSecond: %lu\n", n); + for (i = 0; i < n; i++) { + udelay(1000); + } +} + +void +DvcDisplayString(uchar *s) +{ + printk(s); +} + +int +DvcEnterCritical(void) +{ + int flags; + + save_flags(flags); + cli(); + return flags; +} + +void +DvcLeaveCritical(int flags) +{ + restore_flags(flags); +} + +/* + * Convert a virtual address to a virtual address. + * + * Apparently Linux is loaded V=R (virtual equals real). Just return + * the virtual address. + */ +ulong +DvcGetPhyAddr(uchar *buf_addr, ulong buf_len) +{ + ulong phys_addr; + + phys_addr = (ulong) buf_addr; + return phys_addr; +} + +ulong +DvcGetSGList(ASC_DVC_VAR *asc_dvc_sg, uchar *buf_addr, ulong buf_len, + ASC_SG_HEAD *asc_sg_head_ptr) +{ + ulong buf_size; + + buf_size = buf_len; + asc_sg_head_ptr->entry_cnt = 1; + asc_sg_head_ptr->sg_list[0].addr = (ulong) buf_addr; + asc_sg_head_ptr->sg_list[0].bytes = buf_size; + return buf_size; +} + +/* + * void + * DvcPutScsiQ(PortAddr iop_base, ushort s_addr, ushort *outbuf, int words) + * + * Calling/Exit State: + * none + * + * Description: + * Output an ASC_SCSI_Q structure to the chip + */ +void +DvcPutScsiQ(PortAddr iop_base, ushort s_addr, ushort *outbuf, int words) +{ + int i; + + ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", (uchar *) outbuf, 2 * words); + AscSetChipLramAddr(iop_base, s_addr); + for (i = 0; i < words; i++, outbuf++) { + if (i == 2 || i == 10) { + continue; + } + AscPutChipLramData(iop_base, *outbuf); + } +} + +/* + * void + * DvcGetQinfo(PortAddr iop_base, ushort s_addr, ushort *inbuf, int words) + * + * Calling/Exit State: + * none + * + * Description: + * Input an ASC_QDONE_INFO structure from the chip + */ +void +DvcGetQinfo(PortAddr iop_base, ushort s_addr, ushort *inbuf, int words) +{ + int i; + + AscSetChipLramAddr(iop_base, s_addr); + for (i = 0; i < words; i++, inbuf++) { + if (i == 5) { + continue; + } + *inbuf = AscGetChipLramData(iop_base); + } + ASC_DBG_PRT_HEX(2, "DvcGetQinfo", (uchar *) inbuf, 2 * words); +} + +/* + * void DvcOutPortWords(ushort iop_base, ushort &outbuf, int words) + * + * Calling/Exit State: + * none + * + * Description: + * output a buffer to an i/o port address + */ +void +DvcOutPortWords(ushort iop_base, ushort *outbuf, int words) +{ + int i; + + for (i = 0; i < words; i++, outbuf++) + outpw(iop_base, *outbuf); +} + +/* + * void DvcInPortWords(ushort iop_base, ushort &outbuf, int words) + * + * Calling/Exit State: + * none + * + * Description: + * input a buffer from an i/o port address + */ +void +DvcInPortWords(ushort iop_base, ushort *inbuf, int words) +{ + int i; + + for (i = 0; i < words; i++, inbuf++) + *inbuf = inpw(iop_base); +} + + +/* + * void DvcOutPortDWords(PortAddr port, ulong *pdw, int dwords) + * + * Calling/Exit State: + * none + * + * Description: + * output a buffer of 32-bit integers to an i/o port address in + * 16 bit integer units + */ +void +DvcOutPortDWords(PortAddr port, ulong *pdw, int dwords) +{ + int i; + int words; + ushort *pw; + + pw = (ushort *) pdw; + words = dwords << 1; + for(i = 0; i < words; i++, pw++) { + outpw(port, *pw); + } + return; +} + + +/* + * --- Tracing and Debugging Functions + */ + +#ifdef ADVANSYS_STATS + +#define ASC_PRT_STATS_NEXT() \ + if (cp) { \ + totlen += len; \ + leftlen -= len; \ + if (leftlen == 0) { \ + return totlen; \ + } \ + cp += len; \ + } + +/* + * asc_prt_stats() + * + * Note: no single line should be greater than 160 characters, cf. + * asc_prt_stats_line(). + * + * Return the number of characters copied into 'cp'. No more than + * 'cplen' characters will be copied to 'cp'. + */ +STATIC int +asc_prt_stats(char *cp, int cplen) +{ + struct asc_stats *s; + int leftlen; + int totlen; + int len; + + s = &asc_stats; + leftlen = cplen; + totlen = len = 0; + + len = asc_prt_stats_line(cp, leftlen, +"\nAdvanSys SCSI Host Driver Statistics:\n"); + ASC_PRT_STATS_NEXT(); + + len = asc_prt_stats_line(cp, leftlen, +" command %lu, queuecommand %lu, abort %lu, reset %lu, biosparam %lu,\n", + s->command, s->queuecommand, s->abort, s->reset, s->biosparam); + ASC_PRT_STATS_NEXT(); + + len = asc_prt_stats_line(cp, leftlen, +" interrupt %lu, callback %lu, cmd_disable %lu, intr_disable %lu,\n", + s->interrupt, s->callback, s->cmd_disable, s->intr_disable); + ASC_PRT_STATS_NEXT(); + + len = asc_prt_stats_line(cp, leftlen, +" error %lu, enqueue %lu, dequeue %lu, rmqueue %lu,\n", + s->error, s->enqueue, s->dequeue, s->rmqueue); + ASC_PRT_STATS_NEXT(); + + if (s->cont_cnt > 0) { + len = asc_prt_stats_line(cp, leftlen, +" cont_cnt %lu, cont_xfer %lu: avg_xfer=%lu kb\n", + s->cont_cnt, s->cont_xfer, (s->cont_xfer/2)/s->cont_cnt); + ASC_PRT_STATS_NEXT(); + } + + if (s->sg_cnt > 0) { + len = asc_prt_stats_line(cp, leftlen, +" sg_cnt %lu, sg_elem %lu, sg_xfer %lu: avg_elem=%lu, avg_size=%lu kb\n", + s->sg_cnt, s->sg_elem, s->sg_xfer, + s->sg_elem/s->sg_cnt, (s->sg_xfer/2)/s->sg_cnt); + ASC_PRT_STATS_NEXT(); + } + + return totlen; +} + +/* + * asc_prt_stats_line() + * + * If 'cp' is NULL print to the console, otherwise print to a buffer. + * + * Return 0 if printing to the console, otherwise return the number of + * bytes written to the buffer. + * + * Note: If any single line is greater than 160 bytes the stack + * will be corrupted. 's[]' is defined to be 160 bytes. + */ +int +asc_prt_stats_line(char *buf, int buflen, char *fmt, ...) +{ + va_list args; + int ret; + char s[160]; /* 2 lines */ + + va_start(args, fmt); + ret = vsprintf(s, fmt, args); + if (buf == NULL) { + (void) printk(s); + ret = 0; + } else { + ret = min(buflen, ret); + memcpy(buf, s, ret); + } + va_end(args); + return ret; +} +#endif /* ADVANSYS_STATS */ + +#ifdef ADVANSYS_DEBUG +/* + * asc_prt_scsi_host() + */ +STATIC void +asc_prt_scsi_host(struct Scsi_Host *s) +{ + printk("Scsi_Host at addr %x\n", (unsigned) s); + printk( +" next %x, extra_bytes %u, host_busy %u, host_no %d, last_reset %d,\n", + (unsigned) s->next, s->extra_bytes, s->host_busy, s->host_no, + s->last_reset); + + printk( +" host_wait %x, host_queue %x, hostt %x, block %x,\n", + (unsigned) s->host_wait, (unsigned) s->host_queue, + (unsigned) s->hostt, (unsigned) s->block); + + printk( +" wish_block %d, base %x, io_port %d, n_io_port %d, irq %d, dma_channel %d,\n", + s->wish_block, (unsigned) s->base, s->io_port, s->n_io_port, + s->irq, s->dma_channel); + + printk( +" this_id %d, can_queue %d,\n", s->this_id, s->can_queue); + + printk( +" cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d, loaded_as_module %d\n", + s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma, + s->loaded_as_module); + + printk("hostdata (struct asc_board)\n"); + asc_prt_dvc_var(&ASC_BOARD(s)->board); + asc_prt_dvc_cfg(&ASC_BOARD(s)->cfg); + printk(" overrun_buf %x\n", (unsigned) &ASC_BOARD(s)->overrun_buf[0]); +} + +/* + * asc_prt_dvc_var() + */ +STATIC void +asc_prt_dvc_var(ASC_DVC_VAR *h) +{ + printk("ASC_DVC_VAR at addr %x\n", (unsigned) h); + + printk( +" iop_base %x, err_code %x, dvc_cntl %x, bug_fix_cntl %d,\n", + h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl); + + printk( +" bus_type %d, isr_callback %x, exe_callback %x, init_sdtr %x,\n", + h->bus_type, (unsigned) h->isr_callback, (unsigned) h->exe_callback, + (unsigned) h->init_sdtr); + + printk( +" sdtr_done %x, use_tagged_qng %x, unit_not_ready %x, chip_no %x,\n", + (unsigned) h->sdtr_done, (unsigned) h->use_tagged_qng, + (unsigned) h->unit_not_ready, (unsigned) h->chip_no); + + printk( +" queue_full_or_busy %x, start_motor %x, scsi_reset_wait %x, irq_no %x,\n", + (unsigned) h->queue_full_or_busy, (unsigned) h->start_motor, + (unsigned) h->scsi_reset_wait, (unsigned) h->irq_no); + + printk( +" is_in_int %x, max_total_qng %x, cur_total_qng %x, in_critical_cnt %x,\n", + (unsigned) h->is_in_int, (unsigned) h->max_total_qng, + (unsigned) h->cur_total_qng, (unsigned) h->in_critical_cnt); + + printk( +" last_q_shortage %x, init_state %x, no_scam %x, pci_fix_asyn_xfer %x,\n", + (unsigned) h->last_q_shortage, (unsigned) h->init_state, + (unsigned) h->no_scam, (unsigned) h->pci_fix_asyn_xfer); + + printk( +" int_count %ld, req_count %ld, busy_count %ld, cfg %x, saved_ptr2func %x\n", + h->int_count, h->req_count, h->busy_count, (unsigned) h->cfg, + (unsigned) h->saved_ptr2func); +} + +/* + * asc_prt_dvc_cfg() + */ +STATIC void +asc_prt_dvc_cfg(ASC_DVC_CFG *h) +{ + printk("ASC_DVC_CFG at addr %x\n", (unsigned) h); + + printk( +" can_tagged_qng %x, cmd_qng_enabled %x, disc_enable %x, res %x,\n", + h->can_tagged_qng, h->cmd_qng_enabled, h->disc_enable, h->res); + + printk( +" chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, chip_version %d,\n", + h->chip_scsi_id, h->isa_dma_speed, h->isa_dma_channel, + h->chip_version); + + printk( +" pci_device_id %d, lib_serial_no %d, lib_version %d, mcode_date %d,\n", + h->pci_device_id, h->lib_serial_no, h->lib_version, h->mcode_date); + + printk( +" mcode_version %d, overrun_buf %x\n", + h->mcode_version, (unsigned) h->overrun_buf); +} + +/* + * asc_prt_scsi_q() + */ +STATIC void +asc_prt_scsi_q(ASC_SCSI_Q *q) +{ + ASC_SG_HEAD *sgp; + int i; + + printk("ASC_SCSI_Q at addr %x\n", (unsigned) q); + + printk( +" target_ix %u, target_lun %u, srb_ptr %x, tag_code %u,\n", + q->q2.target_ix, q->q1.target_lun, + (unsigned) q->q2.srb_ptr, q->q2.tag_code); + + printk( +" data_addr %x, data_cnt %lu, sense_addr %x, sense_len %u,\n", + (unsigned) q->q1.data_addr, q->q1.data_cnt, + (unsigned) q->q1.sense_addr, q->q1.sense_len); + + printk( +" cdbptr %x, cdb_len %u, sg_head %x, sg_queue_cnt %u\n", + (unsigned) q->cdbptr, q->q2.cdb_len, + (unsigned) q->sg_head, q->q1.sg_queue_cnt); + + if (q->sg_head) { + sgp = q->sg_head; + printk("ASC_SG_HEAD at addr %x\n", (unsigned) sgp); + printk(" entry_cnt %u, queue_cnt %u\n", sgp->entry_cnt, sgp->queue_cnt); + for (i = 0; i < sgp->entry_cnt; i++) { + printk(" [%u]: addr %x, bytes %lu\n", + i, (unsigned) sgp->sg_list[i].addr, sgp->sg_list[i].bytes); + } + + } +} + +/* + * asc_prt_qdone_info() + */ +STATIC void +asc_prt_qdone_info(ASC_QDONE_INFO *q) +{ + printk("ASC_QDONE_INFO at addr %x\n", (unsigned) q); + printk( +" srb_ptr %x, target_ix %u, cdb_len %u, tag_code %u, done_stat %x\n", + (unsigned) q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len, + q->d2.tag_code, q->d3.done_stat); + printk( +" host_stat %x, scsi_stat %x, scsi_msg %x\n", + q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg); +} + +/* + * asc_prt_hex() + * + * Print hexadecimal output in 4 byte groupings 32 bytes + * or 8 double-words per line. + */ +STATIC void +asc_prt_hex(char *f, uchar *s, int l) +{ + int i; + int j; + int k; + int m; + + printk("%s: (%d bytes)\n", f, l); + + for (i = 0; i < l; i += 32) { + + /* Display a maximum of 8 double-words per line. */ + if ((k = (l - i) / 4) >= 8) { + k = 8; + m = 0; + } else { + m = (l - i) % 4 ; + } + + for (j = 0; j < k; j++) { + printk(" %2.2X%2.2X%2.2X%2.2X", + (unsigned) s[i+(j*4)], (unsigned) s[i+(j*4)+1], + (unsigned) s[i+(j*4)+2], (unsigned) s[i+(j*4)+3]); + } + + switch (m) { + case 0: + default: + break; + case 1: + printk(" %2.2X", + (unsigned) s[i+(j*4)+4]); + break; + case 2: + printk(" %2.2X%2.2X", + (unsigned) s[i+(j*4)+4], + (unsigned) s[i+(j*4)+5]); + break; + case 3: + printk(" %2.2X%2.2X%2.2X", + (unsigned) s[i+(j*4)+4], + (unsigned) s[i+(j*4)+5], + (unsigned) s[i+(j*4)+6]); + break; + } + + printk("\n"); + } +} + +/* + * interrupts_enabled() + * + * Return 1 if interrupts are enabled, otherwise return 0. + */ +STATIC int +interrupts_enabled(void) +{ + int flags; + + save_flags(flags); + if (flags & 0x0200) { + return ASC_TRUE; + } else { + return ASC_FALSE; + } +} + +#endif /* ADVANSYS_DEBUG */ + + +/* + * --- Asc Library Functions + */ + +ushort +AscGetEisaChipCfg( + PortAddr iop_base +) +{ + PortAddr eisa_cfg_iop; + + eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) | + (PortAddr) (ASC_EISA_CFG_IOP_MASK); + return (inpw(eisa_cfg_iop)); +} + +uchar +AscSetChipScsiID( + PortAddr iop_base, + uchar new_host_id +) +{ + ushort cfg_lsw; + + if (AscGetChipScsiID(iop_base) == new_host_id) { + return (new_host_id); + } + cfg_lsw = AscGetChipCfgLsw(iop_base); + cfg_lsw &= 0xF8FF; + cfg_lsw |= (ushort) ((new_host_id & ASC_MAX_TID) << 8); + AscSetChipCfgLsw(iop_base, cfg_lsw); + return (AscGetChipScsiID(iop_base)); +} + +ushort +AscGetChipBiosAddress( + PortAddr iop_base, + ushort bus_type +) +{ + ushort cfg_lsw; + ushort bios_addr; + + if ((bus_type & ASC_IS_EISA) != 0) { + cfg_lsw = AscGetEisaChipCfg(iop_base); + cfg_lsw &= 0x000F; + bios_addr = (ushort) (ASC_BIOS_MIN_ADDR + + (cfg_lsw * ASC_BIOS_BANK_SIZE)); + return (bios_addr); + } + cfg_lsw = AscGetChipCfgLsw(iop_base); + bios_addr = (ushort) (((cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE) + ASC_BIOS_MIN_ADDR); + return (bios_addr); +} + +uchar +AscGetChipVersion( + PortAddr iop_base, + ushort bus_type +) +{ + if ((bus_type & ASC_IS_EISA) != 0) { + + PortAddr eisa_iop; + uchar revision; + + eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) | + (PortAddr) ASC_EISA_REV_IOP_MASK; + revision = inp(eisa_iop); + return ((uchar) ((ASC_CHIP_MIN_VER_EISA - 1) + revision)); + } + return (AscGetChipVerNo(iop_base)); +} + +ushort +AscGetChipBusType( + PortAddr iop_base +) +{ + ushort chip_ver; + + chip_ver = AscGetChipVerNo(iop_base); + if ((chip_ver >= ASC_CHIP_MIN_VER_VL) && + (chip_ver <= ASC_CHIP_MAX_VER_VL)) { + if (((iop_base & 0x0C30) == 0x0C30) || + ((iop_base & 0x0C50) == 0x0C50)) { + return (ASC_IS_EISA); + } + return (ASC_IS_VL); + } else if ((chip_ver >= ASC_CHIP_MIN_VER_ISA) && + (chip_ver <= ASC_CHIP_MAX_VER_ISA)) { + if (chip_ver >= ASC_CHIP_MIN_VER_ISA_PNP) { + return (ASC_IS_ISAPNP); + } + return (ASC_IS_ISA); + } else if ((chip_ver >= ASC_CHIP_MIN_VER_PCI) && + (chip_ver <= ASC_CHIP_MAX_VER_PCI)) { + return (ASC_IS_PCI); + } else { + return (0); + } +} + +void +AscEnableIsaDma( + uchar dma_channel +) +{ + if (dma_channel < 4) { + outp(0x000B, (ushort) (0xC0 | dma_channel)); + outp(0x000A, dma_channel); + } else if (dma_channel < 8) { + + outp(0x00D6, (ushort) (0xC0 | (dma_channel - 4))); + outp(0x00D4, (ushort) (dma_channel - 4)); + } + return; +} + +ulong +AscLoadMicroCode( + PortAddr iop_base, + ushort s_addr, + ushort dosfar * mcode_buf, + ushort mcode_size +) +{ + ulong chksum; + ushort mcode_word_size; + ushort mcode_chksum; + + mcode_word_size = (ushort) (mcode_size >> 1); + AscMemWordSetLram(iop_base, s_addr, 0, mcode_word_size); + AscMemWordCopyToLram(iop_base, s_addr, mcode_buf, mcode_word_size); + + chksum = AscMemSumLramWord(iop_base, s_addr, mcode_word_size); + mcode_chksum = (ushort) AscMemSumLramWord(iop_base, + (ushort) ASC_CODE_SEC_BEG, + (ushort) ((mcode_size - s_addr - (ushort) ASC_CODE_SEC_BEG) / 2)); + AscWriteLramWord(iop_base, ASCV_MCODE_CHKSUM_W, mcode_chksum); + AscWriteLramWord(iop_base, ASCV_MCODE_SIZE_W, mcode_size); + return (chksum); +} + +uchar _hextbl_[16] = +{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F'}; + +uchar _isa_pnp_inited = 0; + +PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] = +{ + 0x100, ASC_IOADR_1, 0x120, ASC_IOADR_2, 0x140, ASC_IOADR_3, ASC_IOADR_4, + ASC_IOADR_5, ASC_IOADR_6, ASC_IOADR_7, ASC_IOADR_8 +}; + +PortAddr +AscSearchIOPortAddr( + PortAddr iop_beg, + ushort bus_type +) +{ + if (bus_type & ASC_IS_VL) { + while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) { + if (AscGetChipVersion(iop_beg, bus_type) <= ASC_CHIP_MAX_VER_VL) { + return (iop_beg); + } + } + return (0); + } + if (bus_type & ASC_IS_ISA) { + if (_isa_pnp_inited == 0) { + AscSetISAPNPWaitForKey(); + _isa_pnp_inited++; + } + while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) { + if ((AscGetChipVersion(iop_beg, bus_type) & ASC_CHIP_VER_ISA_BIT) != 0) { + return (iop_beg); + } + } + return (0); + } + if (bus_type & ASC_IS_EISA) { + if ((iop_beg = AscSearchIOPortAddrEISA(iop_beg)) != 0) { + return (iop_beg); + } + return (0); + } + return (0); +} + +PortAddr +AscSearchIOPortAddr11( + PortAddr s_addr +) +{ + + int i; + PortAddr iop_base; + + for (i = 0; i < ASC_IOADR_TABLE_MAX_IX; i++) { + if (_asc_def_iop_base[i] > s_addr) { + break; + } + } + for (; i < ASC_IOADR_TABLE_MAX_IX; i++) { + iop_base = _asc_def_iop_base[i]; + if (AscFindSignature(iop_base)) { + return (iop_base); + } + } + return (0); +} + +int +AscFindSignature( + PortAddr iop_base +) +{ + ushort sig_word; + + if ((inp((PortAddr) (iop_base + 1)) & 0xFF) == (uchar) ASC_1000_ID1B) { + sig_word = inpw(iop_base); + if ((sig_word == (ushort) ASC_1000_ID0W) || + (sig_word == (ushort) ASC_1000_ID0W_FIX)) { + return (1); + } + } + return (0); +} + +void +AscToggleIRQAct( + PortAddr iop_base +) +{ + AscSetChipStatus(iop_base, CIW_IRQ_ACT); + AscSetChipStatus(iop_base, 0); + return; +} + +#if CC_INIT_INQ_DISPLAY + +#endif + +void +AscSetISAPNPWaitForKey( + void) +{ + + outp(ASC_ISA_PNP_PORT_ADDR, 0x02); + outp(ASC_ISA_PNP_PORT_WRITE, 0x02); + return; +} + +uchar +AscGetChipIRQ( + PortAddr iop_base, + ushort bus_type +) +{ + ushort cfg_lsw; + uchar chip_irq; + + if ((bus_type & ASC_IS_EISA) != 0) { + + cfg_lsw = AscGetEisaChipCfg(iop_base); + chip_irq = (uchar) (((cfg_lsw >> 8) & 0x07) + 10); + if ((chip_irq == 13) || (chip_irq > 15)) { + + return (0); + } + return (chip_irq); + } else { + + cfg_lsw = AscGetChipCfgLsw(iop_base); + + if ((bus_type & ASC_IS_VL) != 0) { + + chip_irq = (uchar) (((cfg_lsw >> 2) & 0x07)); + if ((chip_irq == 0) || + (chip_irq == 4) || + (chip_irq == 7)) { + return (0); + } + return ((uchar) (chip_irq + (ASC_MIN_IRQ_NO - 1))); + } + chip_irq = (uchar) (((cfg_lsw >> 2) & 0x03)); + if (chip_irq == 3) + chip_irq += (uchar) 2; + return ((uchar) (chip_irq + ASC_MIN_IRQ_NO)); + } +} + +uchar +AscSetChipIRQ( + PortAddr iop_base, + uchar irq_no, + ushort bus_type +) +{ + ushort cfg_lsw; + + if ((bus_type & ASC_IS_VL) != 0) { + + if (irq_no != 0) { + if ((irq_no < ASC_MIN_IRQ_NO) || (irq_no > ASC_MAX_IRQ_NO)) { + irq_no = 0; + } else { + irq_no -= (uchar) ((ASC_MIN_IRQ_NO - 1)); + } + } + cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFE3); + cfg_lsw |= (ushort) 0x0010; + AscSetChipCfgLsw(iop_base, cfg_lsw); + AscToggleIRQAct(iop_base); + + cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFE0); + cfg_lsw |= (ushort) ((irq_no & 0x07) << 2); + AscSetChipCfgLsw(iop_base, cfg_lsw); + AscToggleIRQAct(iop_base); + + return (AscGetChipIRQ(iop_base, bus_type)); + + } else if ((bus_type & (ASC_IS_ISA)) != 0) { + + if (irq_no == 15) + irq_no -= (uchar) 2; + irq_no -= (uchar) ASC_MIN_IRQ_NO; + cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFF3); + cfg_lsw |= (ushort) ((irq_no & 0x03) << 2); + AscSetChipCfgLsw(iop_base, cfg_lsw); + return (AscGetChipIRQ(iop_base, bus_type)); + } else { + + return (0); + } +} + +uchar +AscGetChipScsiCtrl( + PortAddr iop_base +) +{ + uchar sc; + + AscSetBank(iop_base, 1); + sc = inp(iop_base + IOP_REG_SC); + AscSetBank(iop_base, 0); + return (sc); +} + +extern uchar _sdtr_period_tbl_[]; + +int +AscIsrChipHalted( + ASC_DVC_VAR asc_ptr_type * asc_dvc +) +{ + SDTR_XMSG sdtr_xmsg; + SDTR_XMSG out_msg; + ushort halt_q_addr; + int sdtr_accept; + ushort int_halt_code; + ASC_SCSI_BIT_ID_TYPE scsi_busy; + ASC_SCSI_BIT_ID_TYPE target_id; + PortAddr iop_base; + uchar tag_code; + uchar q_status; + uchar halt_qp; + uchar sdtr_data; + uchar target_ix; + uchar q_cntl, tid_no; + uchar cur_dvc_qng; + uchar asyn_sdtr; + uchar scsi_status; + + iop_base = asc_dvc->iop_base; + int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W); + + halt_qp = AscReadLramByte(iop_base, ASCV_CURCDB_B); + halt_q_addr = ASC_QNO_TO_QADDR(halt_qp); + target_ix = AscReadLramByte(iop_base, + (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TARGET_IX)); + q_cntl = AscReadLramByte(iop_base, + (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL)); + tid_no = ASC_TIX_TO_TID(target_ix); + target_id = (uchar) ASC_TID_TO_TARGET_ID(tid_no); + if (asc_dvc->pci_fix_asyn_xfer & target_id) { + + asyn_sdtr = ASYN_SDTR_DATA_FIX_PCI_REV_AB; + } else { + asyn_sdtr = 0; + } + if (int_halt_code == ASC_HALT_EXTMSG_IN) { + + AscMemWordCopyFromLram(iop_base, + ASCV_MSGIN_BEG, + (ushort dosfar *) & sdtr_xmsg, + (ushort) (sizeof (SDTR_XMSG) >> 1)); + if ((sdtr_xmsg.msg_type == MS_EXTEND) && + (sdtr_xmsg.msg_len == MS_SDTR_LEN)) { + sdtr_accept = TRUE; + if (sdtr_xmsg.msg_req == MS_SDTR_CODE) { + if (sdtr_xmsg.req_ack_offset > ASC_SYN_MAX_OFFSET) { + + sdtr_accept = FALSE; + sdtr_xmsg.req_ack_offset = ASC_SYN_MAX_OFFSET; + } + sdtr_data = AscCalSDTRData(sdtr_xmsg.xfer_period, + sdtr_xmsg.req_ack_offset); + if (sdtr_xmsg.req_ack_offset == 0) { + + q_cntl &= ~QC_MSG_OUT; + asc_dvc->init_sdtr &= ~target_id; + asc_dvc->sdtr_done &= ~target_id; + AscSetChipSDTR(iop_base, asyn_sdtr, tid_no); + } else if ((sdtr_data == 0xFF)) { + + q_cntl |= QC_MSG_OUT; + asc_dvc->init_sdtr &= ~target_id; + asc_dvc->sdtr_done &= ~target_id; + AscSetChipSDTR(iop_base, asyn_sdtr, tid_no); + } else { + if (sdtr_accept && (q_cntl & QC_MSG_OUT)) { + + q_cntl &= ~QC_MSG_OUT; + asc_dvc->sdtr_done |= target_id; + asc_dvc->init_sdtr |= target_id; + asc_dvc->pci_fix_asyn_xfer &= ~target_id; + AscSetChipSDTR(iop_base, sdtr_data, tid_no); + } else { + + q_cntl |= QC_MSG_OUT; + + AscMsgOutSDTR(iop_base, + sdtr_xmsg.xfer_period, + sdtr_xmsg.req_ack_offset); + asc_dvc->pci_fix_asyn_xfer &= ~target_id; + AscSetChipSDTR(iop_base, sdtr_data, tid_no); + asc_dvc->sdtr_done |= target_id; + asc_dvc->init_sdtr |= target_id; + } + } + + AscWriteLramByte(iop_base, + (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL), + q_cntl); + AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); + return (0); + } + } + } else if (int_halt_code == ASC_HALT_CHK_CONDITION) { + + q_cntl |= QC_REQ_SENSE; + if (((asc_dvc->init_sdtr & target_id) != 0) && + ((asc_dvc->sdtr_done & target_id) != 0)) { + + sdtr_data = AscReadLramByte(iop_base, + (ushort) ((ushort) ASCV_SDTR_DATA_BEG + (ushort) tid_no)); + AscMsgOutSDTR(iop_base, + _sdtr_period_tbl_[(sdtr_data >> 4) & (uchar) (ASC_SYN_XFER_NO - 1)], + (uchar) (sdtr_data & (uchar) ASC_SYN_MAX_OFFSET)); + q_cntl |= QC_MSG_OUT; + } + AscWriteLramByte(iop_base, + (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL), + q_cntl); + + tag_code = AscReadLramByte(iop_base, + (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE)); + tag_code &= 0xDC; + AscWriteLramByte(iop_base, + (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE), + tag_code); + + q_status = AscReadLramByte(iop_base, + (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_STATUS)); + q_status |= (QS_READY | QS_BUSY); + AscWriteLramByte(iop_base, + (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_STATUS), + q_status); + + scsi_busy = AscReadLramByte(iop_base, + (ushort) ASCV_SCSIBUSY_B); + scsi_busy &= ~target_id; + AscWriteLramByte(iop_base, (ushort) ASCV_SCSIBUSY_B, scsi_busy); + + AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); + return (0); + } else if (int_halt_code == ASC_HALT_SDTR_REJECTED) { + + AscMemWordCopyFromLram(iop_base, + ASCV_MSGOUT_BEG, + (ushort dosfar *) & out_msg, + (ushort) (sizeof (SDTR_XMSG) >> 1)); + + if ((out_msg.msg_type == MS_EXTEND) && + (out_msg.msg_len == MS_SDTR_LEN) && + (out_msg.msg_req == MS_SDTR_CODE)) { + + asc_dvc->init_sdtr &= ~target_id; + asc_dvc->sdtr_done &= ~target_id; + AscSetChipSDTR(iop_base, asyn_sdtr, tid_no); + + } else { + + } + + q_cntl &= ~QC_MSG_OUT; + AscWriteLramByte(iop_base, + (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL), + q_cntl); + AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); + return (0); + } else if (int_halt_code == ASC_HALT_SS_QUEUE_FULL) { + + scsi_status = AscReadLramByte(iop_base, + (ushort) ((ushort) halt_q_addr + (ushort) ASC_SCSIQ_SCSI_STATUS)); + cur_dvc_qng = AscReadLramByte(iop_base, + (ushort) ((ushort) ASC_QADR_BEG + (ushort) target_ix)); + if ((cur_dvc_qng > 0) && + (asc_dvc->cur_dvc_qng[tid_no] > 0)) { + + scsi_busy = AscReadLramByte(iop_base, + (ushort) ASCV_SCSIBUSY_B); + scsi_busy |= target_id; + AscWriteLramByte(iop_base, + (ushort) ASCV_SCSIBUSY_B, scsi_busy); + asc_dvc->queue_full_or_busy |= target_id; + + if (scsi_status == SS_QUEUE_FULL) { + if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) { + cur_dvc_qng -= 1; + asc_dvc->max_dvc_qng[tid_no] = cur_dvc_qng; + + AscWriteLramByte(iop_base, + (ushort) ((ushort) ASCV_MAX_DVC_QNG_BEG + (ushort) tid_no), + cur_dvc_qng); + } + } + } + AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); + return (0); + } + return (0); +} + +uchar +_AscCopyLramScsiDoneQ( + PortAddr iop_base, + ushort q_addr, + ASC_QDONE_INFO dosfar * scsiq, + ulong max_dma_count +) +{ + ushort _val; + uchar sg_queue_cnt; + + DvcGetQinfo(iop_base, + (ushort) (q_addr + (ushort) ASC_SCSIQ_DONE_INFO_BEG), + (ushort dosfar *) scsiq, + (ushort) ((sizeof (ASC_SCSIQ_2) + sizeof (ASC_SCSIQ_3)) / 2)); + +#if !CC_LITTLE_ENDIAN_HOST + AscAdjEndianQDoneInfo(scsiq); +#endif + + _val = AscReadLramWord(iop_base, + (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS)); + scsiq->q_status = (uchar) _val; + scsiq->q_no = (uchar) (_val >> 8); + + _val = AscReadLramWord(iop_base, + (ushort) (q_addr + (ushort) ASC_SCSIQ_B_CNTL)); + scsiq->cntl = (uchar) _val; + sg_queue_cnt = (uchar) (_val >> 8); + + _val = AscReadLramWord(iop_base, + (ushort) (q_addr + (ushort) ASC_SCSIQ_B_SENSE_LEN)); + scsiq->sense_len = (uchar) _val; + scsiq->user_def = (uchar) (_val >> 8); + + scsiq->remain_bytes = AscReadLramDWord(iop_base, + (ushort) (q_addr + (ushort) ASC_SCSIQ_DW_REMAIN_XFER_CNT)); + scsiq->remain_bytes &= max_dma_count; + + return (sg_queue_cnt); +} + +int +AscIsrQDone( + ASC_DVC_VAR asc_ptr_type * asc_dvc +) +{ + uchar next_qp; + uchar i; + uchar n_q_used; + uchar sg_list_qp; + uchar sg_queue_cnt; + uchar done_q_tail; + + uchar tid_no; + ASC_SCSI_BIT_ID_TYPE scsi_busy; + ASC_SCSI_BIT_ID_TYPE target_id; + PortAddr iop_base; + ushort q_addr; + ushort sg_q_addr; + uchar cur_target_qng; + ASC_QDONE_INFO scsiq_buf; + ASC_QDONE_INFO dosfar *scsiq; + int false_overrun; + ASC_ISR_CALLBACK asc_isr_callback; + + uchar tag_code; + +#if CC_LINK_BUSY_Q + ushort n_busy_q_done; + +#endif + + iop_base = asc_dvc->iop_base; + asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback; + + n_q_used = 1; + scsiq = (ASC_QDONE_INFO dosfar *) & scsiq_buf; + done_q_tail = (uchar) AscGetVarDoneQTail(iop_base); + q_addr = ASC_QNO_TO_QADDR(done_q_tail); + next_qp = AscReadLramByte(iop_base, + (ushort) (q_addr + (ushort) ASC_SCSIQ_B_FWD)); + if (next_qp != ASC_QLINK_END) { + + AscPutVarDoneQTail(iop_base, next_qp); + q_addr = ASC_QNO_TO_QADDR(next_qp); + + sg_queue_cnt = _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, asc_dvc->max_dma_count); + + AscWriteLramByte(iop_base, + (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS), + (uchar) (scsiq->q_status & (uchar) ~ (QS_READY | QS_ABORTED))); + tid_no = ASC_TIX_TO_TID(scsiq->d2.target_ix); + target_id = ASC_TIX_TO_TARGET_ID(scsiq->d2.target_ix); + if ((scsiq->cntl & QC_SG_HEAD) != 0) { + sg_q_addr = q_addr; + sg_list_qp = next_qp; + for (i = 0; i < sg_queue_cnt; i++) { + sg_list_qp = AscReadLramByte(iop_base, + (ushort) (sg_q_addr + (ushort) ASC_SCSIQ_B_FWD)); + sg_q_addr = ASC_QNO_TO_QADDR(sg_list_qp); + if (sg_list_qp == ASC_QLINK_END) { + AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SG_Q_LINKS); + scsiq->d3.done_stat = QD_WITH_ERROR; + scsiq->d3.host_stat = QHSTA_D_QDONE_SG_LIST_CORRUPTED; + goto FATAL_ERR_QDONE; + } + AscWriteLramByte(iop_base, + (ushort) (sg_q_addr + (ushort) ASC_SCSIQ_B_STATUS), + QS_FREE); + } + + n_q_used = sg_queue_cnt + 1; + AscPutVarDoneQTail(iop_base, sg_list_qp); + } + if (asc_dvc->queue_full_or_busy & target_id) { + + cur_target_qng = AscReadLramByte(iop_base, + (ushort) ((ushort) ASC_QADR_BEG + (ushort) scsiq->d2.target_ix)); + if (cur_target_qng < asc_dvc->max_dvc_qng[tid_no]) { + scsi_busy = AscReadLramByte(iop_base, + (ushort) ASCV_SCSIBUSY_B); + scsi_busy &= ~target_id; + AscWriteLramByte(iop_base, + (ushort) ASCV_SCSIBUSY_B, scsi_busy); + asc_dvc->queue_full_or_busy &= ~target_id; + } + } + if (asc_dvc->cur_total_qng >= n_q_used) { + asc_dvc->cur_total_qng -= n_q_used; + if (asc_dvc->cur_dvc_qng[tid_no] != 0) { + asc_dvc->cur_dvc_qng[tid_no]--; + } + } else { + AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CUR_QNG); + scsiq->d3.done_stat = QD_WITH_ERROR; + goto FATAL_ERR_QDONE; + } + + if ((scsiq->d2.srb_ptr == 0UL) || + ((scsiq->q_status & QS_ABORTED) != 0)) { + + return (0x11); + } else if (scsiq->q_status == QS_DONE) { + + false_overrun = FALSE; + + if (asc_dvc->bug_fix_cntl) { + if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ADD_ONE_BYTE) { + tag_code = AscReadLramByte(iop_base, + (ushort) (q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE)); + if (tag_code & ASC_TAG_FLAG_ADD_ONE_BYTE) { + if (scsiq->remain_bytes != 0UL) { + scsiq->remain_bytes--; + if (scsiq->remain_bytes == 0UL) { + false_overrun = TRUE; + } + } + } + } + } + if ((scsiq->d3.done_stat == QD_WITH_ERROR) && + (scsiq->d3.host_stat == QHSTA_M_DATA_OVER_RUN)) { + if ((scsiq->cntl & (QC_DATA_IN | QC_DATA_OUT)) == 0) { + scsiq->d3.done_stat = QD_NO_ERROR; + scsiq->d3.host_stat = QHSTA_NO_ERROR; + } else if (false_overrun) { + scsiq->d3.done_stat = QD_NO_ERROR; + scsiq->d3.host_stat = QHSTA_NO_ERROR; + } + } +#if CC_CLEAR_LRAM_SRB_PTR + AscWriteLramDWord(iop_base, + (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR), + asc_dvc->int_count); +#endif + + if ((scsiq->cntl & QC_NO_CALLBACK) == 0) { + (*asc_isr_callback) (asc_dvc, scsiq); + } else { + if ((AscReadLramByte(iop_base, + (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG)) == + SCSICMD_StartStopUnit)) { + + asc_dvc->unit_not_ready &= ~target_id; + if (scsiq->d3.done_stat != QD_NO_ERROR) { + asc_dvc->start_motor &= ~target_id; + } + } + } + +#if CC_LINK_BUSY_Q + n_busy_q_done = AscIsrExeBusyQueue(asc_dvc, tid_no); + if (n_busy_q_done == 0) { + + i = tid_no + 1; + while (TRUE) { + if (i > ASC_MAX_TID) + i = 0; + if (i == tid_no) + break; + n_busy_q_done = AscIsrExeBusyQueue(asc_dvc, i); + if (n_busy_q_done != 0) + break; + i++; + } + } + if (n_busy_q_done == 0xFFFF) + return (0x80); +#endif + + return (1); + } else { + + AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS); + + FATAL_ERR_QDONE: + if ((scsiq->cntl & QC_NO_CALLBACK) == 0) { + (*asc_isr_callback) (asc_dvc, scsiq); + } + return (0x80); + } + } + return (0); +} + +int +AscISR( + ASC_DVC_VAR asc_ptr_type * asc_dvc +) +{ + ASC_CS_TYPE chipstat; + PortAddr iop_base; + ushort saved_ram_addr; + uchar ctrl_reg; + uchar saved_ctrl_reg; + int int_pending; + int status; + uchar host_flag; + + iop_base = asc_dvc->iop_base; + int_pending = FALSE; + + asc_dvc->int_count++; + + if (((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0) || + (asc_dvc->isr_callback == 0)) { + + return (ERR); + } + if (asc_dvc->in_critical_cnt != 0) { + AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_ON_CRITICAL); + return (ERR); + } + if (asc_dvc->is_in_int) { + AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_RE_ENTRY); + asc_dvc->busy_count++; + return (ERR); + } + asc_dvc->is_in_int = TRUE; + ctrl_reg = AscGetChipControl(iop_base); + saved_ctrl_reg = ctrl_reg & (~(CC_SCSI_RESET | CC_CHIP_RESET | + CC_SINGLE_STEP | CC_DIAG | CC_TEST)); + + if ((chipstat = AscGetChipStatus(iop_base)) & CSW_INT_PENDING) { + int_pending = TRUE; + AscAckInterrupt(iop_base); + + host_flag = AscReadLramByte(iop_base, ASCV_HOST_FLAG_B); + AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, + (uchar) (host_flag | (uchar) ASC_HOST_FLAG_IN_ISR)); + saved_ram_addr = AscGetChipLramAddr(iop_base); + + if ((chipstat & CSW_HALTED) && + (ctrl_reg & CC_SINGLE_STEP)) { + if (AscIsrChipHalted(asc_dvc) == ERR) { + + goto ISR_REPORT_QDONE_FATAL_ERROR; + + } else { + saved_ctrl_reg &= ~CC_HALT; + } + } else { + ISR_REPORT_QDONE_FATAL_ERROR: + if ((asc_dvc->dvc_cntl & ASC_CNTL_INT_MULTI_Q) != 0) { + while (((status = AscIsrQDone(asc_dvc)) & 0x01) != 0) { + + } + } else { + do { + if ((status = AscIsrQDone(asc_dvc)) == 1) { + + break; + } + } while (status == 0x11); + } + if ((status & 0x80) != 0) + int_pending = ERR; + } + AscSetChipLramAddr(iop_base, saved_ram_addr); + if (AscGetChipLramAddr(iop_base) != saved_ram_addr) { + AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SET_LRAM_ADDR); + } + AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag); + } + AscSetChipControl(iop_base, saved_ctrl_reg); + asc_dvc->is_in_int = FALSE; + return (int_pending); +} + +int +AscScsiSetupCmdQ( + ASC_DVC_VAR asc_ptr_type * asc_dvc, + ASC_SCSI_REQ_Q dosfar * scsiq, + uchar dosfar * buf_addr, + ulong buf_len +) +{ + ulong phy_addr; + + scsiq->r1.cntl = 0; + scsiq->r1.sg_queue_cnt = 0; + scsiq->r1.q_no = 0; + scsiq->r1.user_def = 0; + scsiq->cdbptr = (uchar dosfar *) scsiq->cdb; + scsiq->r3.scsi_stat = 0; + scsiq->r3.scsi_msg = 0; + scsiq->r3.host_stat = 0; + scsiq->r3.done_stat = 0; + scsiq->r2.vm_id = 0; + scsiq->r1.data_cnt = buf_len; + + scsiq->r2.tag_code = (uchar) M2_QTAG_MSG_SIMPLE; + scsiq->r2.flag = (uchar) ASC_FLAG_SCSIQ_REQ; + scsiq->r2.srb_ptr = (ulong) scsiq; + scsiq->r1.status = (uchar) QS_READY; + scsiq->r1.data_addr = 0L; + + if (buf_len != 0L) { + if ((phy_addr = AscGetOnePhyAddr(asc_dvc, + (uchar dosfar *) buf_addr, scsiq->r1.data_cnt)) == 0L) { + return (ERR); + } + scsiq->r1.data_addr = phy_addr; + } + return (0); +} + +uchar _mcode_buf[] = +{ + 0x01, 0x03, 0x01, 0x19, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xDD, 0x0A, 0x01, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x23, 0x00, 0x16, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0x88, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x73, 0x48, 0x04, 0x36, 0x00, 0x00, 0xA2, 0xC8, 0x00, 0x80, 0x73, 0x03, 0x23, 0x36, 0x40, + 0xB6, 0x00, 0x36, 0x00, 0x06, 0xD6, 0x0D, 0xD2, 0x15, 0xDE, 0x12, 0xDA, 0x00, 0xA2, 0xC8, 0x00, + 0x92, 0x80, 0xE0, 0x97, 0x50, 0x00, 0xF5, 0x00, 0x0A, 0x98, 0xDF, 0x23, 0x36, 0x60, 0xB6, 0x00, + 0x92, 0x80, 0x4F, 0x00, 0xF5, 0x00, 0x0A, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, + 0x80, 0x62, 0x92, 0x80, 0x00, 0x62, 0x92, 0x80, 0x00, 0x46, 0x17, 0xEE, 0x13, 0xEA, 0x02, 0x01, + 0x09, 0xD8, 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xDC, 0x00, 0x68, 0x97, 0x7F, 0x23, 0x04, 0x61, + 0x84, 0x01, 0xB2, 0x84, 0xCF, 0xC1, 0x80, 0x73, 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xE8, 0x01, + 0x68, 0x97, 0xD4, 0x81, 0x00, 0x33, 0x02, 0x00, 0x82, 0x88, 0x80, 0x73, 0x80, 0x77, 0x00, 0x01, + 0x01, 0xA1, 0x08, 0x01, 0x4F, 0x00, 0x46, 0x97, 0x07, 0xA6, 0x12, 0x01, 0x00, 0x33, 0x03, 0x00, + 0x82, 0x88, 0x03, 0x03, 0x03, 0xDE, 0x00, 0x33, 0x05, 0x00, 0x82, 0x88, 0xCE, 0x00, 0x69, 0x60, + 0xCE, 0x00, 0x02, 0x03, 0x4A, 0x60, 0x00, 0xA2, 0x86, 0x01, 0x80, 0x63, 0x07, 0xA6, 0x32, 0x01, + 0x86, 0x81, 0x03, 0x03, 0x80, 0x63, 0xE2, 0x00, 0x07, 0xA6, 0x42, 0x01, 0x00, 0x33, 0x04, 0x00, + 0x82, 0x88, 0x03, 0x07, 0x02, 0x01, 0x04, 0xCA, 0x0D, 0x23, 0x2A, 0x98, 0x4D, 0x04, 0xD0, 0x84, + 0x05, 0xD8, 0x0D, 0x23, 0x2A, 0x98, 0xCD, 0x04, 0x15, 0x23, 0xB8, 0x88, 0xFB, 0x23, 0x02, 0x61, + 0x82, 0x01, 0x80, 0x63, 0x02, 0x03, 0x06, 0xA3, 0x70, 0x01, 0x00, 0x33, 0x0A, 0x00, 0x82, 0x88, + 0x4E, 0x00, 0x07, 0xA3, 0x7C, 0x01, 0x00, 0x33, 0x0B, 0x00, 0x82, 0x88, 0xCD, 0x04, 0x36, 0x2D, + 0x00, 0x33, 0x1A, 0x00, 0x82, 0x88, 0x50, 0x04, 0x96, 0x81, 0x06, 0xAB, 0x90, 0x01, 0x96, 0x81, + 0x4E, 0x00, 0x07, 0xA3, 0xA0, 0x01, 0x50, 0x00, 0x00, 0xA3, 0x4A, 0x01, 0x00, 0x05, 0x8A, 0x81, + 0x08, 0x97, 0x02, 0x01, 0x05, 0xC6, 0x04, 0x23, 0xA0, 0x01, 0x15, 0x23, 0xA1, 0x01, 0xCC, 0x81, + 0xFD, 0x23, 0x02, 0x61, 0x82, 0x01, 0x0A, 0xDA, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0, 0xC2, 0x01, + 0x80, 0x63, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1B, 0x00, 0x82, 0x88, 0x06, 0x23, 0x2A, 0x98, + 0xCD, 0x04, 0xB2, 0x84, 0x06, 0x01, 0x00, 0xA2, 0xE2, 0x01, 0x57, 0x60, 0x00, 0xA0, 0xE8, 0x01, + 0xB2, 0x84, 0x80, 0x23, 0xA0, 0x01, 0xB2, 0x84, 0x80, 0x73, 0x4B, 0x00, 0x06, 0x61, 0x00, 0xA2, + 0x10, 0x02, 0x04, 0x01, 0x0D, 0xDE, 0x02, 0x01, 0x03, 0xCC, 0x4F, 0x00, 0x46, 0x97, 0x0A, 0x82, + 0x08, 0x23, 0x02, 0x41, 0x82, 0x01, 0x4F, 0x00, 0x24, 0x97, 0x48, 0x04, 0xFF, 0x23, 0x84, 0x80, + 0xB2, 0x97, 0x00, 0x46, 0x56, 0x00, 0x03, 0xC0, 0x01, 0x23, 0xE8, 0x00, 0x81, 0x73, 0x06, 0x29, + 0x03, 0x42, 0x06, 0xE2, 0x03, 0xEE, 0x66, 0xEB, 0x11, 0x23, 0xB8, 0x88, 0xC6, 0x97, 0xFA, 0x80, + 0x80, 0x73, 0x80, 0x77, 0x06, 0xA6, 0x3E, 0x02, 0x00, 0x33, 0x31, 0x00, 0x82, 0x88, 0x04, 0x01, + 0x03, 0xD8, 0x74, 0x98, 0x02, 0x96, 0x50, 0x82, 0xA2, 0x95, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, + 0xB6, 0x2D, 0x02, 0xA6, 0x7A, 0x02, 0x07, 0xA6, 0x68, 0x02, 0x06, 0xA6, 0x6C, 0x02, 0x03, 0xA6, + 0x70, 0x02, 0x00, 0x33, 0x10, 0x00, 0x82, 0x88, 0x4A, 0x95, 0x52, 0x82, 0xF8, 0x95, 0x52, 0x82, + 0x04, 0x23, 0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01, 0x16, 0x84, 0x04, 0x01, 0x0C, 0xDC, 0xE0, 0x23, + 0x25, 0x61, 0xEF, 0x00, 0x14, 0x01, 0x4F, 0x04, 0xA8, 0x01, 0x6F, 0x00, 0xA5, 0x01, 0x03, 0x23, + 0xA4, 0x01, 0x06, 0x23, 0x9C, 0x01, 0x24, 0x2B, 0x1C, 0x01, 0x02, 0xA6, 0xAC, 0x02, 0x07, 0xA6, + 0x68, 0x02, 0x06, 0xA6, 0x6C, 0x02, 0x00, 0x33, 0x12, 0x00, 0x82, 0x88, 0x00, 0x0E, 0x80, 0x63, + 0x00, 0x43, 0x00, 0xA0, 0x9A, 0x02, 0x4D, 0x04, 0x04, 0x01, 0x0B, 0xDC, 0xE7, 0x23, 0x04, 0x61, + 0x84, 0x01, 0x10, 0x31, 0x12, 0x35, 0x14, 0x01, 0xEC, 0x00, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, + 0xEC, 0x82, 0x18, 0x23, 0x04, 0x61, 0x18, 0xA0, 0xE4, 0x02, 0x04, 0x01, 0x8E, 0xC8, 0x00, 0x33, + 0x1F, 0x00, 0x82, 0x88, 0x08, 0x31, 0x0A, 0x35, 0x0C, 0x39, 0x0E, 0x3D, 0x40, 0x98, 0xB6, 0x2D, + 0x01, 0xA6, 0x0E, 0x03, 0x00, 0xA6, 0x1C, 0x03, 0x07, 0xA6, 0x2A, 0x03, 0x06, 0xA6, 0x2E, 0x03, + 0x03, 0xA6, 0xFA, 0x03, 0x02, 0xA6, 0x7A, 0x02, 0x00, 0x33, 0x33, 0x00, 0x82, 0x88, 0x08, 0x23, + 0xB3, 0x01, 0x04, 0x01, 0x0E, 0xD0, 0x00, 0x33, 0x14, 0x00, 0x82, 0x88, 0x10, 0x23, 0xB3, 0x01, + 0x04, 0x01, 0x07, 0xCC, 0x00, 0x33, 0x15, 0x00, 0x82, 0x88, 0x4A, 0x95, 0xF0, 0x82, 0xF8, 0x95, + 0xF0, 0x82, 0x44, 0x98, 0x80, 0x42, 0x40, 0x98, 0x48, 0xE4, 0x04, 0x01, 0x29, 0xC8, 0x31, 0x05, + 0x07, 0x01, 0x00, 0xA2, 0x72, 0x03, 0x00, 0x43, 0x87, 0x01, 0x05, 0x05, 0x48, 0x98, 0x40, 0x98, + 0x00, 0xA6, 0x34, 0x03, 0x07, 0xA6, 0x6A, 0x03, 0x03, 0xA6, 0x16, 0x04, 0x06, 0xA6, 0x6E, 0x03, + 0x01, 0xA6, 0x34, 0x03, 0x00, 0x33, 0x25, 0x00, 0x82, 0x88, 0x4A, 0x95, 0x50, 0x83, 0xF8, 0x95, + 0x50, 0x83, 0x04, 0x01, 0x0C, 0xCE, 0x03, 0xC8, 0x00, 0x33, 0x42, 0x00, 0x82, 0x88, 0x00, 0x01, + 0x05, 0x05, 0xFF, 0xA2, 0x90, 0x03, 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x4C, 0x83, 0x05, 0x05, + 0x01, 0xA6, 0x9A, 0x03, 0x00, 0xA6, 0xAA, 0x03, 0xF0, 0x83, 0x68, 0x98, 0x80, 0x42, 0x01, 0xA6, + 0x9A, 0x03, 0xBA, 0x83, 0x00, 0x33, 0x2F, 0x00, 0x82, 0x88, 0x68, 0x98, 0x80, 0x42, 0x00, 0xA6, + 0xAA, 0x03, 0xBA, 0x83, 0x00, 0x33, 0x26, 0x00, 0x82, 0x88, 0x38, 0x2B, 0x80, 0x32, 0x80, 0x36, + 0x04, 0x23, 0xA0, 0x01, 0x12, 0x23, 0xA1, 0x01, 0xF0, 0x83, 0x04, 0xF0, 0x80, 0x6B, 0x00, 0x33, + 0x20, 0x00, 0x82, 0x88, 0x03, 0xA6, 0xEE, 0x03, 0x07, 0xA6, 0xE6, 0x03, 0x06, 0xA6, 0xEA, 0x03, + 0x00, 0x33, 0x17, 0x00, 0x82, 0x88, 0x4A, 0x95, 0xD4, 0x83, 0xF8, 0x95, 0xD4, 0x83, 0xFA, 0x83, + 0x04, 0xF0, 0x80, 0x6B, 0x00, 0x33, 0x20, 0x00, 0x82, 0x88, 0xB6, 0x2D, 0x03, 0xA6, 0x16, 0x04, + 0x07, 0xA6, 0x0E, 0x04, 0x06, 0xA6, 0x12, 0x04, 0x00, 0x33, 0x30, 0x00, 0x82, 0x88, 0x4A, 0x95, + 0xFA, 0x83, 0xF8, 0x95, 0xFA, 0x83, 0xA2, 0x0D, 0x80, 0x63, 0x07, 0xA6, 0x24, 0x04, 0x00, 0x33, + 0x18, 0x00, 0x82, 0x88, 0x03, 0x03, 0x80, 0x63, 0xA3, 0x01, 0x07, 0xA4, 0x2E, 0x04, 0x23, 0x01, + 0x00, 0xA2, 0x50, 0x04, 0x0A, 0xA0, 0x40, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1D, 0x00, 0x82, 0x88, + 0x0B, 0xA0, 0x4C, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1E, 0x00, 0x82, 0x88, 0x42, 0x23, 0xB8, 0x88, + 0x00, 0x23, 0x22, 0xA3, 0xB2, 0x04, 0x08, 0x23, 0x22, 0xA3, 0x6C, 0x04, 0x28, 0x23, 0x22, 0xA3, + 0x78, 0x04, 0x02, 0x23, 0x22, 0xA3, 0x8E, 0x04, 0x42, 0x23, 0xB8, 0x88, 0x4A, 0x00, 0x06, 0x61, + 0x00, 0xA0, 0x78, 0x04, 0x45, 0x23, 0xB8, 0x88, 0xC6, 0x97, 0x00, 0xA2, 0x8A, 0x04, 0x74, 0x98, + 0x00, 0x33, 0x00, 0x82, 0xC0, 0x20, 0x81, 0x62, 0xF6, 0x81, 0x47, 0x23, 0xB8, 0x88, 0x04, 0x01, + 0x0C, 0xDE, 0x14, 0x01, 0x00, 0xA2, 0xA6, 0x04, 0xC6, 0x97, 0x74, 0x98, 0x00, 0x33, 0x00, 0x81, + 0xC0, 0x20, 0x81, 0x62, 0x10, 0x82, 0x43, 0x23, 0xB8, 0x88, 0x04, 0x23, 0xA0, 0x01, 0x44, 0x23, + 0xA1, 0x01, 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3, 0xC0, 0x04, 0x00, 0x33, 0x27, 0x00, 0x82, 0x88, + 0x04, 0x01, 0x04, 0xDC, 0x02, 0x23, 0xA2, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xC6, 0x97, 0xF4, 0x94, + 0x4B, 0x00, 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00, 0x00, 0xA3, 0xEE, 0x04, 0x00, 0x05, 0x76, 0x00, + 0x06, 0x61, 0x00, 0xA2, 0xE8, 0x04, 0xD6, 0x84, 0x08, 0x97, 0xCD, 0x04, 0xF2, 0x84, 0x48, 0x04, + 0xFF, 0x23, 0x84, 0x80, 0x02, 0x01, 0x03, 0xDA, 0x80, 0x23, 0x82, 0x01, 0x02, 0x85, 0x02, 0x23, + 0xA0, 0x01, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x0E, 0x05, 0x1D, 0x01, 0x04, 0xD6, 0xFF, 0x23, + 0x86, 0x41, 0x4B, 0x60, 0xCB, 0x00, 0xFF, 0x23, 0x80, 0x01, 0x49, 0x00, 0x81, 0x01, 0x04, 0x01, + 0x02, 0xC8, 0x30, 0x01, 0x80, 0x01, 0xF7, 0x04, 0x03, 0x01, 0x49, 0x04, 0x80, 0x01, 0xC9, 0x00, + 0x00, 0x05, 0x00, 0x01, 0xFF, 0xA0, 0x2E, 0x05, 0x77, 0x04, 0x01, 0x23, 0xEA, 0x00, 0x5D, 0x00, + 0xFE, 0xC7, 0x00, 0x62, 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63, 0x07, 0xA4, 0xA0, 0x05, 0x03, 0x03, + 0x02, 0xA0, 0x5C, 0x05, 0x9C, 0x85, 0x00, 0x33, 0x2D, 0x00, 0x82, 0x88, 0x04, 0xA0, 0x82, 0x05, + 0x80, 0x63, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x6E, 0x05, 0x1D, 0x01, 0x06, 0xD6, 0x02, 0x23, + 0x02, 0x41, 0x82, 0x01, 0x50, 0x00, 0x24, 0x97, 0xD0, 0x84, 0x04, 0x23, 0x02, 0x41, 0x82, 0x01, + 0xD0, 0x84, 0x08, 0xA0, 0x88, 0x05, 0x9C, 0x85, 0x03, 0xA0, 0x8E, 0x05, 0x9C, 0x85, 0x01, 0xA0, + 0x9A, 0x05, 0x88, 0x00, 0x80, 0x63, 0x78, 0x96, 0x4A, 0x85, 0x88, 0x86, 0x80, 0x63, 0x4A, 0x85, + 0x00, 0x63, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0xDE, 0x05, 0x1D, 0x01, 0x18, 0xD4, 0xC0, 0x23, + 0x07, 0x41, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0xC0, 0x05, 0x00, 0x33, 0x37, 0x00, 0x82, 0x88, + 0x1D, 0x01, 0x02, 0xD6, 0x46, 0x23, 0xB8, 0x88, 0x63, 0x60, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, + 0xD8, 0x05, 0x00, 0x33, 0x38, 0x00, 0x82, 0x88, 0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63, 0x4B, 0x00, + 0x06, 0x41, 0xCB, 0x00, 0x52, 0x00, 0x06, 0x61, 0x00, 0xA2, 0xF2, 0x05, 0xC0, 0x23, 0x07, 0x41, + 0x00, 0x63, 0x80, 0x23, 0x07, 0x41, 0x00, 0x63, 0x80, 0x67, 0x08, 0x23, 0x83, 0x03, 0x80, 0x63, + 0x00, 0x63, 0x06, 0xA6, 0x14, 0x06, 0x07, 0xA6, 0x64, 0x06, 0x02, 0xA6, 0xBC, 0x06, 0x00, 0x33, + 0x39, 0x00, 0x82, 0x88, 0x00, 0x00, 0x01, 0xA0, 0xD6, 0x06, 0xA2, 0x95, 0x83, 0x03, 0x80, 0x63, + 0x06, 0xA6, 0x28, 0x06, 0x07, 0xA6, 0x64, 0x06, 0x00, 0x00, 0x00, 0x2B, 0x40, 0x0E, 0x80, 0x63, + 0x01, 0x00, 0x06, 0xA6, 0x40, 0x06, 0x07, 0xA6, 0x64, 0x06, 0x00, 0x33, 0x3A, 0x00, 0x82, 0x88, + 0x40, 0x0E, 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0x32, 0x06, 0x06, 0xA6, 0x58, 0x06, 0x07, 0xA6, + 0x64, 0x06, 0x00, 0x33, 0x3B, 0x00, 0x82, 0x88, 0x80, 0x67, 0x40, 0x0E, 0x80, 0x63, 0x07, 0xA6, + 0x64, 0x06, 0x00, 0x63, 0x03, 0x03, 0x80, 0x63, 0x88, 0x00, 0x01, 0xA2, 0x78, 0x06, 0x07, 0xA2, + 0xBC, 0x06, 0x00, 0x33, 0x35, 0x00, 0x82, 0x88, 0x07, 0xA6, 0x82, 0x06, 0x00, 0x33, 0x2A, 0x00, + 0x82, 0x88, 0x03, 0x03, 0x03, 0xA2, 0x8E, 0x06, 0x07, 0x23, 0x80, 0x00, 0xC8, 0x86, 0x80, 0x63, + 0x89, 0x00, 0x0A, 0x2B, 0x07, 0xA6, 0x9E, 0x06, 0x00, 0x33, 0x29, 0x00, 0x82, 0x88, 0x00, 0x43, + 0x00, 0xA2, 0xAA, 0x06, 0xC0, 0x0E, 0x80, 0x63, 0x94, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80, + 0xC0, 0x20, 0x81, 0x62, 0x04, 0x01, 0x08, 0xDA, 0x80, 0x63, 0x00, 0x63, 0x80, 0x67, 0x00, 0x33, + 0x00, 0x40, 0xC0, 0x20, 0x81, 0x62, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x20, 0x06, + 0x00, 0x33, 0x2C, 0x00, 0x82, 0x88, 0x0C, 0xA2, 0xF0, 0x06, 0xA2, 0x95, 0x83, 0x03, 0x80, 0x63, + 0x06, 0xA6, 0xEE, 0x06, 0x07, 0xA6, 0x64, 0x06, 0x00, 0x33, 0x3D, 0x00, 0x82, 0x88, 0x00, 0x00, + 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0, 0x06, 0x07, 0x07, 0xA6, 0x64, 0x06, 0xBF, 0x23, + 0x04, 0x61, 0x84, 0x01, 0xB2, 0x84, 0x00, 0x63, 0xF0, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x00, 0x01, + 0xF2, 0x00, 0x01, 0x05, 0x80, 0x01, 0x72, 0x04, 0x71, 0x00, 0x81, 0x01, 0x70, 0x04, 0x80, 0x05, + 0x81, 0x05, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x70, 0x00, + 0x81, 0x01, 0x70, 0x04, 0x71, 0x00, 0x81, 0x01, 0x72, 0x00, 0x80, 0x01, 0x71, 0x04, 0x70, 0x00, + 0x80, 0x01, 0x70, 0x04, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x00, 0x01, 0xF1, 0x00, + 0x70, 0x00, 0x80, 0x01, 0x70, 0x04, 0x71, 0x00, 0x80, 0x01, 0x72, 0x00, 0x81, 0x01, 0x71, 0x04, + 0x70, 0x00, 0x81, 0x01, 0x70, 0x04, 0x00, 0x63, 0x00, 0x23, 0xB3, 0x01, 0x83, 0x05, 0xA3, 0x01, + 0xA2, 0x01, 0xA1, 0x01, 0x01, 0x23, 0xA0, 0x01, 0x00, 0x01, 0xC8, 0x00, 0x03, 0xA1, 0x86, 0x07, + 0x00, 0x33, 0x07, 0x00, 0x82, 0x88, 0x80, 0x05, 0x81, 0x05, 0x04, 0x01, 0x11, 0xC8, 0x48, 0x00, + 0xB0, 0x01, 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x05, 0x01, 0x48, 0x04, 0x00, 0x43, 0x00, 0xA2, + 0xA6, 0x07, 0x00, 0x05, 0x9C, 0x87, 0x00, 0x01, 0xC8, 0x00, 0xFF, 0x23, 0x80, 0x01, 0x05, 0x05, + 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x80, 0x43, 0x76, 0x08, + 0x80, 0x02, 0x77, 0x04, 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, + 0x00, 0xA0, 0xD6, 0x07, 0xD8, 0x87, 0x00, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04, 0x00, 0x63, + 0xF3, 0x04, 0x00, 0x23, 0xF4, 0x00, 0x74, 0x00, 0x80, 0x43, 0xF4, 0x00, 0xCF, 0x40, 0x00, 0xA2, + 0x06, 0x08, 0x74, 0x04, 0x02, 0x01, 0xF7, 0xC9, 0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1, 0xE6, 0x07, + 0xC6, 0x97, 0xF4, 0x94, 0xE6, 0x87, 0x73, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x75, 0x04, 0x1C, 0x88, + 0x02, 0x01, 0x04, 0xD8, 0x08, 0x97, 0xC6, 0x97, 0xF4, 0x94, 0x0C, 0x88, 0x75, 0x00, 0x00, 0xA3, + 0x26, 0x08, 0x00, 0x05, 0x10, 0x88, 0x73, 0x04, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, + 0x38, 0x08, 0x00, 0x33, 0x3E, 0x00, 0x82, 0x88, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, + 0x38, 0x2B, 0x5E, 0x88, 0x38, 0x2B, 0x54, 0x88, 0x32, 0x09, 0x31, 0x05, 0x54, 0x98, 0x05, 0x05, + 0xB2, 0x09, 0x00, 0x63, 0x00, 0x32, 0x00, 0x36, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x63, 0x80, 0x32, + 0x80, 0x36, 0x80, 0x3A, 0x80, 0x3E, 0x00, 0x63, 0x38, 0x2B, 0x40, 0x32, 0x40, 0x36, 0x40, 0x3A, + 0x40, 0x3E, 0x00, 0x63, 0x5A, 0x20, 0xC9, 0x40, 0x00, 0xA0, 0x74, 0x08, 0x5D, 0x00, 0xFE, 0xC3, + 0x00, 0x63, 0x80, 0x73, 0xE6, 0x20, 0x02, 0x23, 0xE8, 0x00, 0x82, 0x73, 0xFF, 0xFD, 0x80, 0x73, + 0x13, 0x23, 0xB8, 0x88, 0x66, 0x20, 0xC0, 0x20, 0x04, 0x23, 0xA0, 0x01, 0xA1, 0x23, 0xA1, 0x01, + 0x81, 0x62, 0xA2, 0x88, 0x80, 0x73, 0x80, 0x77, 0x68, 0x00, 0x00, 0xA2, 0x80, 0x00, 0x03, 0xC2, + 0xF1, 0xC7, 0x41, 0x23, 0xB8, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xB2, 0x84, + +}; + +ushort _mcode_size = sizeof (_mcode_buf); +ulong _mcode_chksum = 0x012258FBUL; + +extern uchar _sdtr_period_tbl_[]; + +int +AscExeScsiQueue( + ASC_DVC_VAR asc_ptr_type * asc_dvc, + ASC_SCSI_Q dosfar * scsiq +) +{ + PortAddr iop_base; + int last_int_level; + int sta; + ulong addr; + uchar sg_entry_cnt; + uchar target_ix; + int n_q_required; + uchar sg_entry_cnt_minus_one; + uchar tid_no; + uchar sdtr_data; + ASC_EXE_CALLBACK asc_exe_callback; + +#if CC_DEBUG_SG_LIST + int i; + +#endif +#if CC_LINK_BUSY_Q + ASC_SCSI_Q dosfar *scsiq_tail; + ASC_SCSI_Q dosfar *scsiq_next; + ASC_SCSI_Q dosfar *scsiq_prev; + +#endif + + iop_base = asc_dvc->iop_base; + asc_exe_callback = (ASC_EXE_CALLBACK) asc_dvc->exe_callback; + if (asc_dvc->err_code != 0) + return (ERR); + if (scsiq == (ASC_SCSI_Q dosfar *) 0L) { + AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SCSIQ_NULL_PTR); + return (ERR); + } + scsiq->q1.q_no = 0; + sta = 0; + target_ix = scsiq->q2.target_ix; + tid_no = ASC_TIX_TO_TID(target_ix); + + n_q_required = 1; + + if (scsiq->cdbptr[0] == SCSICMD_RequestSense) { + + if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) && + ((asc_dvc->sdtr_done & scsiq->q1.target_id) != 0)) { + sdtr_data = AscReadLramByte(iop_base, + (ushort) ((ushort) ASCV_SDTR_DATA_BEG + (ushort) tid_no)); + AscMsgOutSDTR(iop_base, + _sdtr_period_tbl_[(sdtr_data >> 4) & (uchar) (ASC_SYN_XFER_NO - 1)], + (uchar) (sdtr_data & (uchar) ASC_SYN_MAX_OFFSET)); + scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT); + } + } + last_int_level = DvcEnterCritical(); + if (asc_dvc->in_critical_cnt != 0) { + DvcLeaveCritical(last_int_level); + AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CRITICAL_RE_ENTRY); + return (ERR); + } + asc_dvc->in_critical_cnt++; + + if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) { + + if ((sg_entry_cnt = scsiq->sg_head->entry_cnt) == 0) { + asc_dvc->in_critical_cnt--; + DvcLeaveCritical(last_int_level); + return (ERR); + } + if (sg_entry_cnt == 1) { + scsiq->q1.data_addr = scsiq->sg_head->sg_list[0].addr; + scsiq->q1.data_cnt = scsiq->sg_head->sg_list[0].bytes; + scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE); + goto NON_SG_LIST_REQ; + } + if (sg_entry_cnt > ASC_MAX_SG_LIST) { + + return (ERR); + } + sg_entry_cnt_minus_one = sg_entry_cnt - 1; + +#if CC_DEBUG_SG_LIST + if (asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL | ASC_IS_EISA)) { + for (i = 0; i < sg_entry_cnt_minus_one; i++) { + + addr = scsiq->sg_head->sg_list[i].addr + + scsiq->sg_head->sg_list[i].bytes; + + if (((ushort) addr & 0x0003) != 0) { + asc_dvc->in_critical_cnt--; + DvcLeaveCritical(last_int_level); + AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SG_LIST_ODD_ADDRESS); + return (ERR); + } + } + } +#endif + + if (asc_dvc->bug_fix_cntl) { + if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ADD_ONE_BYTE) { + + addr = scsiq->sg_head->sg_list[sg_entry_cnt_minus_one].addr + + scsiq->sg_head->sg_list[sg_entry_cnt_minus_one].bytes; + if (((ushort) addr & 0x0003) != 0) { + if ((scsiq->cdbptr[0] == SCSICMD_Read6) || + (scsiq->cdbptr[0] == SCSICMD_Read10)) { + if ((scsiq->q2.tag_code & ASC_TAG_FLAG_ADD_ONE_BYTE) == 0) { + + scsiq->sg_head->sg_list[sg_entry_cnt_minus_one].bytes++; + scsiq->q2.tag_code |= ASC_TAG_FLAG_ADD_ONE_BYTE; + } + } + } + } + } + scsiq->sg_head->entry_to_copy = scsiq->sg_head->entry_cnt; + n_q_required = AscSgListToQueue(sg_entry_cnt); + +#if CC_LINK_BUSY_Q + scsiq_next = (ASC_SCSI_Q dosfar *) asc_dvc->scsiq_busy_head[tid_no]; + if (scsiq_next != (ASC_SCSI_Q dosfar *) 0L) { + goto link_scisq_to_busy_list; + } +#endif + + if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, n_q_required) + >= (uint) n_q_required) || + ((scsiq->q1.cntl & QC_URGENT) != 0)) { + if ((sta = AscSendScsiQueue(asc_dvc, scsiq, + n_q_required)) == 1) { + + asc_dvc->in_critical_cnt--; + if (asc_exe_callback != 0) { + (*asc_exe_callback) (asc_dvc, scsiq); + } + DvcLeaveCritical(last_int_level); + return (sta); + } + } + } else { + + NON_SG_LIST_REQ: + + if (asc_dvc->bug_fix_cntl) { + if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ADD_ONE_BYTE) { + + addr = scsiq->q1.data_addr + scsiq->q1.data_cnt; + if ((scsiq->cdbptr[0] == SCSICMD_Read6) || + (scsiq->cdbptr[0] == SCSICMD_Read10)) { + if (((ushort) addr & 0x0003) != 0) { + if (((ushort) scsiq->q1.data_cnt & 0x01FF) == 0) { + + if ((scsiq->q2.tag_code & ASC_TAG_FLAG_ADD_ONE_BYTE) == 0) { + + scsiq->q2.tag_code |= ASC_TAG_FLAG_ADD_ONE_BYTE; + scsiq->q1.data_cnt++; + } + } + } + } + } + } + n_q_required = 1; + +#if CC_LINK_BUSY_Q + scsiq_next = (ASC_SCSI_Q dosfar *) asc_dvc->scsiq_busy_head[tid_no]; + if (scsiq_next != (ASC_SCSI_Q dosfar *) 0L) { + goto link_scisq_to_busy_list; + } +#endif + if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, 1) >= 1) || + ((scsiq->q1.cntl & QC_URGENT) != 0)) { + if ((sta = AscSendScsiQueue(asc_dvc, scsiq, + n_q_required)) == 1) { + + asc_dvc->in_critical_cnt--; + if (asc_exe_callback != 0) { + (*asc_exe_callback) (asc_dvc, scsiq); + } + DvcLeaveCritical(last_int_level); + return (sta); + } + } + } + +#if CC_LINK_BUSY_Q + if (sta == 0) { + + link_scisq_to_busy_list: + scsiq->ext.q_required = n_q_required; + if (scsiq_next == (ASC_SCSI_Q dosfar *) 0L) { + asc_dvc->scsiq_busy_head[tid_no] = (ASC_SCSI_Q dosfar *) scsiq; + asc_dvc->scsiq_busy_tail[tid_no] = (ASC_SCSI_Q dosfar *) scsiq; + scsiq->ext.next = (ASC_SCSI_Q dosfar *) 0L; + scsiq->ext.join = (ASC_SCSI_Q dosfar *) 0L; + scsiq->q1.status = QS_BUSY; + sta = 1; + } else { + scsiq_tail = (ASC_SCSI_Q dosfar *) asc_dvc->scsiq_busy_tail[tid_no]; + if (scsiq_tail->ext.next == (ASC_SCSI_Q dosfar *) 0L) { + if ((scsiq->q1.cntl & QC_URGENT) != 0) { + + asc_dvc->scsiq_busy_head[tid_no] = (ASC_SCSI_Q dosfar *) scsiq; + scsiq->ext.next = scsiq_next; + scsiq->ext.join = (ASC_SCSI_Q dosfar *) 0L; + } else { + if (scsiq->ext.cntl & QCX_SORT) { + do { + scsiq_prev = scsiq_next; + scsiq_next = scsiq_next->ext.next; + if (scsiq->ext.lba < scsiq_prev->ext.lba) + break; + } while (scsiq_next != (ASC_SCSI_Q dosfar *) 0L); + + scsiq_prev->ext.next = scsiq; + scsiq->ext.next = scsiq_next; + if (scsiq_next == (ASC_SCSI_Q dosfar *) 0L) { + asc_dvc->scsiq_busy_tail[tid_no] = (ASC_SCSI_Q dosfar *) scsiq; + } + scsiq->ext.join = (ASC_SCSI_Q dosfar *) 0L; + } else { + + scsiq_tail->ext.next = (ASC_SCSI_Q dosfar *) scsiq; + asc_dvc->scsiq_busy_tail[tid_no] = (ASC_SCSI_Q dosfar *) scsiq; + scsiq->ext.next = (ASC_SCSI_Q dosfar *) 0L; + scsiq->ext.join = (ASC_SCSI_Q dosfar *) 0L; + } + } + scsiq->q1.status = QS_BUSY; + sta = 1; + } else { + + AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SCSIQ_BAD_NEXT_PTR); + sta = ERR; + } + } + } +#endif + asc_dvc->in_critical_cnt--; + DvcLeaveCritical(last_int_level); + return (sta); +} + +int +AscSendScsiQueue( + ASC_DVC_VAR asc_ptr_type * asc_dvc, + ASC_SCSI_Q dosfar * scsiq, + uchar n_q_required +) +{ + PortAddr iop_base; + uchar free_q_head; + uchar next_qp; + uchar tid_no; + uchar target_ix; + int sta; + + iop_base = asc_dvc->iop_base; + target_ix = scsiq->q2.target_ix; + tid_no = ASC_TIX_TO_TID(target_ix); + sta = 0; + free_q_head = (uchar) AscGetVarFreeQHead(iop_base); + if (n_q_required > 1) { + if ((next_qp = AscAllocMultipleFreeQueue(iop_base, + free_q_head, (uchar) (n_q_required))) + != (uchar) ASC_QLINK_END) { + asc_dvc->last_q_shortage = 0; + scsiq->sg_head->queue_cnt = n_q_required - 1; + scsiq->q1.q_no = free_q_head; + + if ((sta = AscPutReadySgListQueue(asc_dvc, scsiq, + free_q_head)) == 1) { + +#if CC_WRITE_IO_COUNT + asc_dvc->req_count++; +#endif + + AscPutVarFreeQHead(iop_base, next_qp); + asc_dvc->cur_total_qng += (uchar) (n_q_required); + asc_dvc->cur_dvc_qng[tid_no]++; + } + return (sta); + } + } else if (n_q_required == 1) { + + if ((next_qp = AscAllocFreeQueue(iop_base, + free_q_head)) != ASC_QLINK_END) { + + scsiq->q1.q_no = free_q_head; + if ((sta = AscPutReadyQueue(asc_dvc, scsiq, + free_q_head)) == 1) { + +#if CC_WRITE_IO_COUNT + asc_dvc->req_count++; +#endif + + AscPutVarFreeQHead(iop_base, next_qp); + asc_dvc->cur_total_qng++; + asc_dvc->cur_dvc_qng[tid_no]++; + } + return (sta); + } + } + return (sta); +} + +int +AscSgListToQueue( + int sg_list +) +{ + int n_sg_list_qs; + + n_sg_list_qs = ((sg_list - 1) / ASC_SG_LIST_PER_Q); + if (((sg_list - 1) % ASC_SG_LIST_PER_Q) != 0) + n_sg_list_qs++; + return (n_sg_list_qs + 1); +} + +uint +AscGetNumOfFreeQueue( + ASC_DVC_VAR asc_ptr_type * asc_dvc, + uchar target_ix, uchar n_qs +) +{ + uint cur_used_qs; + uint cur_free_qs; + ASC_SCSI_BIT_ID_TYPE target_id; + uchar tid_no; + + target_id = ASC_TIX_TO_TARGET_ID(target_ix); + tid_no = ASC_TIX_TO_TID(target_ix); + if ((asc_dvc->unit_not_ready & target_id) || + (asc_dvc->queue_full_or_busy & target_id)) { + return (0); + } + if (n_qs == 1) { + cur_used_qs = (uint) asc_dvc->cur_total_qng + + (uint) asc_dvc->last_q_shortage + + (uint) ASC_MIN_FREE_Q; + } else { + cur_used_qs = (uint) asc_dvc->cur_total_qng + + (uint) ASC_MIN_FREE_Q; + } + + if ((uint) (cur_used_qs + n_qs) <= (uint) asc_dvc->max_total_qng) { + cur_free_qs = (uint) asc_dvc->max_total_qng - cur_used_qs; + if (asc_dvc->cur_dvc_qng[tid_no] >= + asc_dvc->max_dvc_qng[tid_no]) { + return (0); + } + return (cur_free_qs); + } + if (n_qs > 1) { + if (n_qs > asc_dvc->last_q_shortage) { + asc_dvc->last_q_shortage = n_qs; + } + } + return (0); +} + +int +AscPutReadyQueue( + ASC_DVC_VAR asc_ptr_type * asc_dvc, + ASC_SCSI_Q dosfar * scsiq, + uchar q_no +) +{ + ushort q_addr; + uchar tid_no; + uchar sdtr_data; + uchar syn_period_ix; + uchar syn_offset; + PortAddr iop_base; + + iop_base = asc_dvc->iop_base; + + if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) && + ((asc_dvc->sdtr_done & scsiq->q1.target_id) == 0)) { + + tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix); + + sdtr_data = AscReadLramByte(iop_base, + (ushort) ((ushort) ASCV_SDTR_DATA_BEG + (ushort) tid_no)); + syn_period_ix = (sdtr_data >> 4) & (ASC_SYN_XFER_NO - 1); + syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET; + AscMsgOutSDTR(iop_base, + _sdtr_period_tbl_[syn_period_ix], + syn_offset); + + scsiq->q1.cntl |= QC_MSG_OUT; + } + q_addr = ASC_QNO_TO_QADDR(q_no); + + if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) { + scsiq->q2.tag_code &= ~M2_QTAG_MSG_SIMPLE; + } + scsiq->q1.status = QS_FREE; + + AscMemWordCopyToLram(iop_base, + (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG), + (ushort dosfar *) scsiq->cdbptr, + (ushort) ((ushort) scsiq->q2.cdb_len >> 1)); + +#if !CC_LITTLE_ENDIAN_HOST + AscAdjEndianScsiQ(scsiq); +#endif + + DvcPutScsiQ(iop_base, + (ushort) (q_addr + (ushort) ASC_SCSIQ_CPY_BEG), + (ushort dosfar *) & scsiq->q1.cntl, + (ushort) ((((sizeof (ASC_SCSIQ_1) + sizeof (ASC_SCSIQ_2)) / 2) - 1))); + +#if CC_WRITE_IO_COUNT + AscWriteLramWord(iop_base, + (ushort) (q_addr + (ushort) ASC_SCSIQ_W_REQ_COUNT), + (ushort) asc_dvc->req_count); + +#endif + +#if CC_VERIFY_LRAM_COPY + if ((asc_dvc->dvc_cntl & ASC_CNTL_NO_VERIFY_COPY) == 0) { + + if (AscMemWordCmpToLram(iop_base, + (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG), + (ushort dosfar *) scsiq->cdbptr, + (ushort) (scsiq->q2.cdb_len >> 1)) != 0) { + AscSetLibErrorCode(asc_dvc, ASCQ_ERR_LOCAL_MEM); + return (ERR); + } + if (AscMemWordCmpToLram(iop_base, + (ushort) (q_addr + (ushort) ASC_SCSIQ_CPY_BEG), + (ushort dosfar *) & scsiq->q1.cntl, + (ushort) (((sizeof (ASC_SCSIQ_1) + sizeof (ASC_SCSIQ_2)) / 2) - 1)) + != 0) { + AscSetLibErrorCode(asc_dvc, ASCQ_ERR_LOCAL_MEM); + return (ERR); + } + } +#endif + +#if CC_CLEAR_DMA_REMAIN + + AscWriteLramDWord(iop_base, + (ushort) (q_addr + (ushort) ASC_SCSIQ_DW_REMAIN_XFER_ADDR), 0UL); + AscWriteLramDWord(iop_base, + (ushort) (q_addr + (ushort) ASC_SCSIQ_DW_REMAIN_XFER_CNT), 0UL); + +#endif + + AscWriteLramWord(iop_base, + (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS), + (ushort) (((ushort) scsiq->q1.q_no << 8) | (ushort) QS_READY)); + return (1); +} + +int +AscPutReadySgListQueue( + ASC_DVC_VAR asc_ptr_type * asc_dvc, + ASC_SCSI_Q dosfar * scsiq, + uchar q_no +) +{ + uchar sg_list_dwords; + uchar sg_index, i; + uchar sg_entry_cnt; + uchar next_qp; + ushort q_addr; + int sta; + ASC_SG_HEAD dosfar *sg_head; + ASC_SG_LIST_Q scsi_sg_q; + ulong saved_data_addr; + ulong saved_data_cnt; + PortAddr iop_base; + + iop_base = asc_dvc->iop_base; + + sg_head = scsiq->sg_head; + + saved_data_addr = scsiq->q1.data_addr; + saved_data_cnt = scsiq->q1.data_cnt; + scsiq->q1.data_addr = sg_head->sg_list[0].addr; + scsiq->q1.data_cnt = sg_head->sg_list[0].bytes; + sg_entry_cnt = sg_head->entry_cnt - 1; + if (sg_entry_cnt != 0) { + scsiq->q1.cntl |= QC_SG_HEAD; + q_addr = ASC_QNO_TO_QADDR(q_no); + sg_index = 1; + scsiq->q1.sg_queue_cnt = sg_head->queue_cnt; + scsi_sg_q.sg_head_qp = q_no; + scsi_sg_q.cntl = QCSG_SG_XFER_LIST; + for (i = 0; i < sg_head->queue_cnt; i++) { + scsi_sg_q.seq_no = i + 1; + if (sg_entry_cnt > ASC_SG_LIST_PER_Q) { + sg_list_dwords = (uchar) (ASC_SG_LIST_PER_Q * 2); + sg_entry_cnt -= ASC_SG_LIST_PER_Q; + if (i == 0) { + scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q; + scsi_sg_q.sg_cur_list_cnt = ASC_SG_LIST_PER_Q; + } else { + scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1; + scsi_sg_q.sg_cur_list_cnt = ASC_SG_LIST_PER_Q - 1; + } + } else { + + scsi_sg_q.cntl |= QCSG_SG_XFER_END; + sg_list_dwords = sg_entry_cnt << 1; + if (i == 0) { + scsi_sg_q.sg_list_cnt = sg_entry_cnt; + scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt; + } else { + scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1; + scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1; + } + sg_entry_cnt = 0; + } + next_qp = AscReadLramByte(iop_base, + (ushort) (q_addr + ASC_SCSIQ_B_FWD)); + scsi_sg_q.q_no = next_qp; + q_addr = ASC_QNO_TO_QADDR(next_qp); + + AscMemWordCopyToLram(iop_base, + (ushort) (q_addr + ASC_SCSIQ_SGHD_CPY_BEG), + (ushort dosfar *) & scsi_sg_q, + (ushort) (sizeof (ASC_SG_LIST_Q) >> 1)); + + AscMemDWordCopyToLram(iop_base, + (ushort) (q_addr + ASC_SGQ_LIST_BEG), + (ulong dosfar *) & sg_head->sg_list[sg_index], + (ushort) sg_list_dwords); + + sg_index += ASC_SG_LIST_PER_Q; + } + } else { + + scsiq->q1.cntl &= ~QC_SG_HEAD; + } + sta = AscPutReadyQueue(asc_dvc, scsiq, q_no); + + scsiq->q1.data_addr = saved_data_addr; + scsiq->q1.data_cnt = saved_data_cnt; + return (sta); +} + +int +AscAbortSRB( + ASC_DVC_VAR asc_ptr_type * asc_dvc, + ulong srb_ptr +) +{ + int sta; + ASC_SCSI_BIT_ID_TYPE saved_unit_not_ready; + PortAddr iop_base; + + iop_base = asc_dvc->iop_base; + sta = ERR; + saved_unit_not_ready = asc_dvc->unit_not_ready; + asc_dvc->unit_not_ready = 0xFF; + AscWaitISRDone(asc_dvc); + if (AscStopQueueExe(iop_base) == 1) { + if (AscRiscHaltedAbortSRB(asc_dvc, srb_ptr) == 1) { + sta = 1; + AscCleanUpBusyQueue(iop_base); + AscStartQueueExe(iop_base); + + } else { + sta = 0; + AscStartQueueExe(iop_base); + } + } + asc_dvc->unit_not_ready = saved_unit_not_ready; + return (sta); +} + +int +AscResetDevice( + ASC_DVC_VAR asc_ptr_type * asc_dvc, + uchar target_ix +) +{ + PortAddr iop_base; + int sta; + uchar tid_no; + ASC_SCSI_BIT_ID_TYPE target_id; + int i; + ASC_SCSI_REQ_Q scsiq_buf; + ASC_SCSI_REQ_Q dosfar *scsiq; + uchar dosfar *buf; + ASC_SCSI_BIT_ID_TYPE saved_unit_not_ready; + + iop_base = asc_dvc->iop_base; + tid_no = ASC_TIX_TO_TID(target_ix); + target_id = ASC_TID_TO_TARGET_ID(tid_no); + saved_unit_not_ready = asc_dvc->unit_not_ready; + asc_dvc->unit_not_ready = target_id; + sta = ERR; + AscWaitTixISRDone(asc_dvc, target_ix); + if (AscStopQueueExe(iop_base) == 1) { + if (AscRiscHaltedAbortTIX(asc_dvc, target_ix) == 1) { + + AscCleanUpBusyQueue(iop_base); + AscStartQueueExe(iop_base); + + AscWaitTixISRDone(asc_dvc, target_ix); + + sta = TRUE; + scsiq = (ASC_SCSI_REQ_Q dosfar *) & scsiq_buf; + buf = (uchar dosfar *) & scsiq_buf; + for (i = 0; i < sizeof (ASC_SCSI_REQ_Q); i++) { + *buf++ = 0x00; + } + + scsiq->r1.status = (uchar) QS_READY; + scsiq->r2.cdb_len = 6; + scsiq->r2.tag_code = M2_QTAG_MSG_SIMPLE; + scsiq->r1.target_id = target_id; + + scsiq->r2.target_ix = ASC_TIDLUN_TO_IX(tid_no, 0); + scsiq->cdbptr = (uchar dosfar *) scsiq->cdb; + + scsiq->r1.cntl = QC_NO_CALLBACK | QC_MSG_OUT | QC_URGENT; + AscWriteLramByte(asc_dvc->iop_base, ASCV_MSGOUT_BEG, + M1_BUS_DVC_RESET); + + asc_dvc->unit_not_ready &= ~target_id; + + asc_dvc->sdtr_done |= target_id; + + if (AscExeScsiQueue(asc_dvc, (ASC_SCSI_Q dosfar *) scsiq) + == 1) { + asc_dvc->unit_not_ready = target_id; + DvcSleepMilliSecond(1000); + _AscWaitQDone(iop_base, (ASC_SCSI_Q dosfar *) scsiq); + if (AscStopQueueExe(iop_base) == 1) { + + AscCleanUpDiscQueue(iop_base); + AscStartQueueExe(iop_base); + if (asc_dvc->pci_fix_asyn_xfer & target_id) { + + AscSetRunChipSynRegAtID(iop_base, tid_no, + ASYN_SDTR_DATA_FIX_PCI_REV_AB); + } + AscWaitTixISRDone(asc_dvc, target_ix); + } + } else { + + sta = 0; + } + + asc_dvc->sdtr_done &= ~target_id; + } else { + sta = ERR; + AscStartQueueExe(iop_base); + } + } + asc_dvc->unit_not_ready = saved_unit_not_ready; + return (sta); +} + +int +AscResetSB( + ASC_DVC_VAR asc_ptr_type * asc_dvc +) +{ + int sta; + int i; + PortAddr iop_base; + + iop_base = asc_dvc->iop_base; + asc_dvc->unit_not_ready = 0xFF; + sta = TRUE; + AscWaitISRDone(asc_dvc); + AscStopQueueExe(iop_base); + + asc_dvc->sdtr_done = 0; + AscResetChipAndScsiBus(iop_base); + + DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000)); + +#if CC_SCAM + if (!(asc_dvc->dvc_cntl & ASC_CNTL_NO_SCAM)) { + AscSCAM(asc_dvc); + } +#endif + AscReInitLram(asc_dvc); + + for (i = 0; i <= ASC_MAX_TID; i++) { + asc_dvc->cur_dvc_qng[i] = 0; + if (asc_dvc->pci_fix_asyn_xfer & (0x01 << i)) { + + AscSetChipSynRegAtID(iop_base, i, ASYN_SDTR_DATA_FIX_PCI_REV_AB); + } + } + + asc_dvc->err_code = 0; + + AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR); + if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) { + sta = ERR; + } + if (AscStartChip(iop_base) == 0) { + sta = ERR; + } + AscStartQueueExe(iop_base); + asc_dvc->unit_not_ready = 0; + asc_dvc->queue_full_or_busy = 0; + return (sta); +} + +int +AscSetRunChipSynRegAtID( + PortAddr iop_base, + uchar tid_no, + uchar sdtr_data +) +{ + int sta = FALSE; + + if (AscHostReqRiscHalt(iop_base)) { + sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data); + + AscStartChip(iop_base); + return (sta); + } + return (sta); +} + +int +AscSetChipSynRegAtID( + PortAddr iop_base, + uchar id, + uchar sdtr_data +) +{ + AscSetBank(iop_base, 1); + AscWriteChipScsiID(iop_base, id); + if (AscReadChipScsiID(iop_base) != (0x01 << id)) { + return (FALSE); + } + AscSetBank(iop_base, 0); + AscWriteChipSyn(iop_base, sdtr_data); + if (AscReadChipSyn(iop_base) != sdtr_data) { + return (FALSE); + } + return (TRUE); +} + +int +AscReInitLram( + ASC_DVC_VAR asc_ptr_type * asc_dvc +) +{ + AscInitLram(asc_dvc); + AscInitQLinkVar(asc_dvc); + return (0); +} + +ushort +AscInitLram( + ASC_DVC_VAR asc_ptr_type * asc_dvc) +{ + uchar i; + ushort s_addr; + PortAddr iop_base; + ushort warn_code; + + iop_base = asc_dvc->iop_base; + warn_code = 0; + + AscMemWordSetLram(iop_base, ASC_QADR_BEG, 0, + (ushort) (((int) (asc_dvc->max_total_qng + 2 + 1) * 64) >> 1) + ); + + i = ASC_MIN_ACTIVE_QNO; + s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE; + + AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD), + (uchar) (i + 1)); + AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD), + (uchar) (asc_dvc->max_total_qng)); + AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO), + (uchar) i); + i++; + s_addr += ASC_QBLK_SIZE; + for (; i < asc_dvc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) { + AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD), + (uchar) (i + 1)); + AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD), + (uchar) (i - 1)); + AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO), + (uchar) i); + } + + AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD), + (uchar) ASC_QLINK_END); + AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD), + (uchar) (asc_dvc->max_total_qng - 1)); + AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO), + (uchar) asc_dvc->max_total_qng); + i++; + s_addr += ASC_QBLK_SIZE; + + for (; i <= (uchar) (asc_dvc->max_total_qng + 3); + i++, s_addr += ASC_QBLK_SIZE) { + + AscWriteLramByte(iop_base, + (ushort) (s_addr + (ushort) ASC_SCSIQ_B_FWD), i); + AscWriteLramByte(iop_base, + (ushort) (s_addr + (ushort) ASC_SCSIQ_B_BWD), i); + AscWriteLramByte(iop_base, + (ushort) (s_addr + (ushort) ASC_SCSIQ_B_QNO), i); + } + + return (warn_code); +} + +ushort +AscInitQLinkVar( + ASC_DVC_VAR asc_ptr_type * asc_dvc +) +{ + PortAddr iop_base; + int i; + ushort lram_addr; + + iop_base = asc_dvc->iop_base; + AscPutRiscVarFreeQHead(iop_base, 1); + AscPutRiscVarDoneQTail(iop_base, asc_dvc->max_total_qng); + + AscPutVarFreeQHead(iop_base, 1); + AscPutVarDoneQTail(iop_base, asc_dvc->max_total_qng); + + AscWriteLramByte(iop_base, ASCV_BUSY_QHEAD_B, + (uchar) ((int) asc_dvc->max_total_qng + 1)); + AscWriteLramByte(iop_base, ASCV_DISC1_QHEAD_B, + (uchar) ((int) asc_dvc->max_total_qng + 2)); + + AscWriteLramByte(iop_base, (ushort) ASCV_TOTAL_READY_Q_B, + asc_dvc->max_total_qng); + + AscWriteLramWord(iop_base, ASCV_ASCDVC_ERR_CODE_W, 0); + AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); + AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0); + AscWriteLramByte(iop_base, ASCV_SCSIBUSY_B, 0); + AscWriteLramByte(iop_base, ASCV_WTM_FLAG_B, 0); + + AscWriteLramByte(iop_base, (ushort) ASCV_CDBCNT_B, 0); + + lram_addr = ASC_QADR_BEG; + for (i = 0; i < 32; i++, lram_addr += 2) { + AscWriteLramWord(iop_base, lram_addr, 0); + } + + return (0); +} + +int +AscSetLibErrorCode( + ASC_DVC_VAR asc_ptr_type * asc_dvc, + ushort err_code +) +{ + if (asc_dvc->err_code == 0) { + + asc_dvc->err_code = err_code; + AscWriteLramWord(asc_dvc->iop_base, ASCV_ASCDVC_ERR_CODE_W, + err_code); + } + return (err_code); +} + +int +_AscWaitQDone( + PortAddr iop_base, + ASC_SCSI_Q dosfar * scsiq +) +{ + ushort q_addr; + uchar q_status; + int count = 0; + + while (scsiq->q1.q_no == 0) ; + q_addr = ASC_QNO_TO_QADDR(scsiq->q1.q_no); + + do { + q_status = AscReadLramByte(iop_base, q_addr + ASC_SCSIQ_B_STATUS); + DvcSleepMilliSecond(100L); + if (count++ > 30) { + return (0); + } + } while ((q_status & QS_READY) != 0); + return (1); +} + +uchar _sdtr_period_tbl_[ASC_SYN_XFER_NO] = +{ + SYN_XFER_NS_0, + SYN_XFER_NS_1, + SYN_XFER_NS_2, + SYN_XFER_NS_3, + SYN_XFER_NS_4, + SYN_XFER_NS_5, + SYN_XFER_NS_6, + SYN_XFER_NS_7}; + +uchar +AscMsgOutSDTR( + PortAddr iop_base, + uchar sdtr_period, + uchar sdtr_offset +) +{ + SDTR_XMSG sdtr_buf; + uchar sdtr_period_index; + + sdtr_buf.msg_type = MS_EXTEND; + sdtr_buf.msg_len = MS_SDTR_LEN; + sdtr_buf.msg_req = MS_SDTR_CODE; + sdtr_buf.xfer_period = sdtr_period; + sdtr_offset &= ASC_SYN_MAX_OFFSET; + sdtr_buf.req_ack_offset = sdtr_offset; + AscMemWordCopyToLram(iop_base, ASCV_MSGOUT_BEG, + (ushort dosfar *) & sdtr_buf, SYN_XMSG_WLEN); + if ((sdtr_period_index = AscGetSynPeriodIndex(sdtr_period)) <= + ASC_MAX_SDTR_PERIOD_INDEX) { + return ((sdtr_period_index << 4) | sdtr_offset); + } else { + + return (0); + } +} + +uchar +AscCalSDTRData( + uchar sdtr_period, + uchar syn_offset +) +{ + uchar byte; + uchar sdtr_period_ix; + + sdtr_period_ix = AscGetSynPeriodIndex(sdtr_period); + if ((sdtr_period_ix > ASC_MAX_SDTR_PERIOD_INDEX) || + (sdtr_period_ix > ASC_SDTR_PERIOD_IX_MIN)) { + return (0xFF); + } + byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET); + return (byte); +} + +void +AscSetChipSDTR( + PortAddr iop_base, + uchar sdtr_data, + uchar tid_no +) +{ + + AscWriteChipSyn(iop_base, sdtr_data); + AscWriteLramByte(iop_base, + (ushort) ((ushort) ASCV_SDTR_DONE_BEG + (ushort) tid_no), + sdtr_data); + return; +} + +uchar +AscGetSynPeriodIndex( + uchar syn_time +) +{ + if ((syn_time >= SYN_XFER_NS_0) && (syn_time <= SYN_XFER_NS_7)) { + if (syn_time <= SYN_XFER_NS_6) { + if (syn_time <= SYN_XFER_NS_5) { + if (syn_time <= SYN_XFER_NS_4) { + if (syn_time <= SYN_XFER_NS_3) { + if (syn_time <= SYN_XFER_NS_2) { + if (syn_time <= SYN_XFER_NS_1) { + if (syn_time <= SYN_XFER_NS_0) { + return (0); + } else + return (1); + } else { + return (2); + } + } else { + return (3); + } + } else { + return (4); + } + } else { + return (5); + } + } else { + return (6); + } + } else { + return (7); + } + } else { + + return (8); + } +} + +uchar +AscAllocFreeQueue( + PortAddr iop_base, + uchar free_q_head +) +{ + ushort q_addr; + uchar next_qp; + uchar q_status; + + q_addr = ASC_QNO_TO_QADDR(free_q_head); + q_status = (uchar) AscReadLramByte(iop_base, + (ushort) (q_addr + ASC_SCSIQ_B_STATUS)); + next_qp = AscReadLramByte(iop_base, + (ushort) (q_addr + ASC_SCSIQ_B_FWD)); + if (((q_status & QS_READY) == 0) && + (next_qp != ASC_QLINK_END)) { + return (next_qp); + } + return (ASC_QLINK_END); +} + +uchar +AscAllocMultipleFreeQueue( + PortAddr iop_base, + uchar free_q_head, + uchar n_free_q +) +{ + uchar i; + + for (i = 0; i < n_free_q; i++) { + if ((free_q_head = AscAllocFreeQueue(iop_base, free_q_head)) + == ASC_QLINK_END) { + return (ASC_QLINK_END); + } + } + return (free_q_head); +} + +int +AscRiscHaltedAbortSRB( + ASC_DVC_VAR asc_ptr_type * asc_dvc, + ulong srb_ptr +) +{ + PortAddr iop_base; + ushort q_addr; + uchar q_no; + ASC_QDONE_INFO scsiq_buf; + ASC_QDONE_INFO dosfar *scsiq; + ASC_ISR_CALLBACK asc_isr_callback; + int last_int_level; + + iop_base = asc_dvc->iop_base; + asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback; + last_int_level = DvcEnterCritical(); + scsiq = (ASC_QDONE_INFO dosfar *) & scsiq_buf; + +#if CC_LINK_BUSY_Q + _AscAbortSrbBusyQueue(asc_dvc, scsiq, srb_ptr); +#endif + + for (q_no = ASC_MIN_ACTIVE_QNO; q_no <= asc_dvc->max_total_qng; + q_no++) { + q_addr = ASC_QNO_TO_QADDR(q_no); + scsiq->d2.srb_ptr = AscReadLramDWord(iop_base, + (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR)); + if (scsiq->d2.srb_ptr == srb_ptr) { + _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, asc_dvc->max_dma_count); + if (((scsiq->q_status & QS_READY) != 0) && + ((scsiq->q_status & QS_ABORTED) == 0) && + ((scsiq->cntl & QCSG_SG_XFER_LIST) == 0)) { + + scsiq->q_status |= QS_ABORTED; + scsiq->d3.done_stat = QD_ABORTED_BY_HOST; + AscWriteLramDWord(iop_base, + (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR), + 0L); + AscWriteLramByte(iop_base, + (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS), + scsiq->q_status); + (*asc_isr_callback) (asc_dvc, scsiq); + return (1); + } + } + } + DvcLeaveCritical(last_int_level); + return (0); +} + +int +AscRiscHaltedAbortTIX( + ASC_DVC_VAR asc_ptr_type * asc_dvc, + uchar target_ix +) +{ + PortAddr iop_base; + ushort q_addr; + uchar q_no; + ASC_QDONE_INFO scsiq_buf; + ASC_QDONE_INFO dosfar *scsiq; + ASC_ISR_CALLBACK asc_isr_callback; + int last_int_level; + +#if CC_LINK_BUSY_Q + uchar tid_no; + +#endif + + iop_base = asc_dvc->iop_base; + asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback; + last_int_level = DvcEnterCritical(); + scsiq = (ASC_QDONE_INFO dosfar *) & scsiq_buf; + +#if CC_LINK_BUSY_Q + + tid_no = ASC_TIX_TO_TID(target_ix); + _AscAbortTidBusyQueue(asc_dvc, scsiq, tid_no); + +#endif + + for (q_no = ASC_MIN_ACTIVE_QNO; q_no <= asc_dvc->max_total_qng; + q_no++) { + q_addr = ASC_QNO_TO_QADDR(q_no); + _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, asc_dvc->max_dma_count); + if (((scsiq->q_status & QS_READY) != 0) && + ((scsiq->q_status & QS_ABORTED) == 0) && + ((scsiq->cntl & QCSG_SG_XFER_LIST) == 0)) { + if (scsiq->d2.target_ix == target_ix) { + scsiq->q_status |= QS_ABORTED; + scsiq->d3.done_stat = QD_ABORTED_BY_HOST; + + AscWriteLramDWord(iop_base, + (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR), + 0L); + + AscWriteLramByte(iop_base, + (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS), + scsiq->q_status); + (*asc_isr_callback) (asc_dvc, scsiq); + } + } + } + DvcLeaveCritical(last_int_level); + return (1); +} + +#if CC_LINK_BUSY_Q + +#endif + +int +AscHostReqRiscHalt( + PortAddr iop_base +) +{ + int count = 0; + int sta = 0; + uchar saved_stop_code; + + if (AscIsChipHalted(iop_base)) + return (1); + saved_stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B); + + AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, + ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP + ); + do { + if (AscIsChipHalted(iop_base)) { + sta = 1; + break; + } + DvcSleepMilliSecond(100); + } while (count++ < 20); + + AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code); + return (sta); +} + +int +AscStopQueueExe( + PortAddr iop_base +) +{ + int count; + + count = 0; + if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) == 0) { + AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, + ASC_STOP_REQ_RISC_STOP); + do { + if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) & + ASC_STOP_ACK_RISC_STOP) { + return (1); + } + DvcSleepMilliSecond(100); + } while (count++ < 20); + } + return (0); +} + +int +AscStartQueueExe( + PortAddr iop_base +) +{ + if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) { + AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0); + } + return (1); +} + +int +AscCleanUpBusyQueue( + PortAddr iop_base +) +{ + int count; + uchar stop_code; + + count = 0; + if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) { + AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, + ASC_STOP_CLEAN_UP_BUSY_Q); + do { + stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B); + if ((stop_code & ASC_STOP_CLEAN_UP_BUSY_Q) == 0) + break; + DvcSleepMilliSecond(100); + } while (count++ < 20); + } + return (1); +} + +int +AscCleanUpDiscQueue( + PortAddr iop_base +) +{ + int count; + uchar stop_code; + + count = 0; + if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) { + AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, + ASC_STOP_CLEAN_UP_DISC_Q); + do { + stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B); + if ((stop_code & ASC_STOP_CLEAN_UP_DISC_Q) == 0) + break; + DvcSleepMilliSecond(100); + } while (count++ < 20); + } + return (1); +} + +int +AscWaitTixISRDone( + ASC_DVC_VAR asc_ptr_type * asc_dvc, + uchar target_ix +) +{ + uchar cur_req; + uchar tid_no; + + tid_no = ASC_TIX_TO_TID(target_ix); + while (TRUE) { + if ((cur_req = asc_dvc->cur_dvc_qng[tid_no]) == 0) { + break; + } + DvcSleepMilliSecond(1000L); + if (asc_dvc->cur_dvc_qng[tid_no] == cur_req) { + break; + } + } + return (1); +} + +int +AscWaitISRDone( + ASC_DVC_VAR asc_ptr_type * asc_dvc +) +{ + int tid; + + for (tid = 0; tid <= ASC_MAX_TID; tid++) { + AscWaitTixISRDone(asc_dvc, ASC_TID_TO_TIX(tid)); + } + return (1); +} + +ulong +AscGetOnePhyAddr( + ASC_DVC_VAR asc_ptr_type * asc_dvc, + uchar dosfar * buf_addr, + ulong buf_size +) +{ + ASC_MIN_SG_HEAD sg_head; + + sg_head.entry_cnt = ASC_MIN_SG_LIST; + if (DvcGetSGList(asc_dvc, (uchar dosfar *) buf_addr, + buf_size, (ASC_SG_HEAD dosfar *) & sg_head) != buf_size) { + return (0L); + } + if (sg_head.entry_cnt > 1) { + return (0L); + } + return (sg_head.sg_list[0].addr); +} + +ulong +AscGetEisaProductID( + PortAddr iop_base +) +{ + PortAddr eisa_iop; + ushort product_id_high, product_id_low; + ulong product_id; + + eisa_iop = ASC_GET_EISA_SLOT(iop_base) | ASC_EISA_PID_IOP_MASK; + product_id_low = inpw(eisa_iop); + product_id_high = inpw(eisa_iop + 2); + product_id = ((ulong) product_id_high << 16) | (ulong) product_id_low; + return (product_id); +} + +PortAddr +AscSearchIOPortAddrEISA( + PortAddr iop_base +) +{ + ulong eisa_product_id; + + if (iop_base == 0) { + iop_base = ASC_EISA_MIN_IOP_ADDR; + } else { + if (iop_base == ASC_EISA_MAX_IOP_ADDR) + return (0); + if ((iop_base & 0x0050) == 0x0050) { + iop_base += ASC_EISA_BIG_IOP_GAP; + } else { + iop_base += ASC_EISA_SMALL_IOP_GAP; + } + } + while (iop_base <= ASC_EISA_MAX_IOP_ADDR) { + + eisa_product_id = AscGetEisaProductID(iop_base); + if ((eisa_product_id == ASC_EISA_ID_740) || + (eisa_product_id == ASC_EISA_ID_750)) { + if (AscFindSignature(iop_base)) { + + inpw(iop_base + 4); + return (iop_base); + } + } + if (iop_base == ASC_EISA_MAX_IOP_ADDR) + return (0); + if ((iop_base & 0x0050) == 0x0050) { + iop_base += ASC_EISA_BIG_IOP_GAP; + } else { + iop_base += ASC_EISA_SMALL_IOP_GAP; + } + } + return (0); +} + +int +AscStartChip( + PortAddr iop_base +) +{ + AscSetChipControl(iop_base, 0); + if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) { + return (0); + } + return (1); +} + +int +AscStopChip( + PortAddr iop_base +) +{ + uchar cc_val; + + cc_val = AscGetChipControl(iop_base) & (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG)); + AscSetChipControl(iop_base, (uchar) (cc_val | CC_HALT)); + AscSetChipIH(iop_base, INS_HALT); + AscSetChipIH(iop_base, INS_RFLAG_WTM); + if ((AscGetChipStatus(iop_base) & CSW_HALTED) == 0) { + return (0); + } + return (1); +} + +int +AscIsChipHalted( + PortAddr iop_base +) +{ + + if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) { + if ((AscGetChipControl(iop_base) & CC_HALT) != 0) { + return (1); + } + } + return (0); +} + +void +AscSetChipIH( + PortAddr iop_base, + ushort ins_code +) +{ + AscSetBank(iop_base, 1); + AscWriteChipIH(iop_base, ins_code); + AscSetBank(iop_base, 0); + return; +} + +void +AscAckInterrupt( + PortAddr iop_base +) +{ + + uchar host_flag; + uchar risc_flag; + ushort loop; + + loop = 0; + do { + risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B); + if (loop++ > 0x7FFF) { + break; + } + } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0); + + host_flag = AscReadLramByte(iop_base, ASCV_HOST_FLAG_B); + AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, + (uchar) (host_flag | ASC_HOST_FLAG_ACK_INT)); + + AscSetChipStatus(iop_base, CIW_INT_ACK); + loop = 0; + while (AscGetChipStatus(iop_base) & CSW_INT_PENDING) { + + AscSetChipStatus(iop_base, CIW_INT_ACK); + if (loop++ > 3) { + break; + } + } + + AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag); + return; +} + +void +AscDisableInterrupt( + PortAddr iop_base +) +{ + ushort cfg; + + cfg = AscGetChipCfgLsw(iop_base); + AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON)); + return; +} + +void +AscEnableInterrupt( + PortAddr iop_base +) +{ + ushort cfg; + + cfg = AscGetChipCfgLsw(iop_base); + AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON); + return; +} + +void +AscSetBank( + PortAddr iop_base, + uchar bank +) +{ + uchar val; + + val = AscGetChipControl(iop_base) & + (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG | CC_SCSI_RESET | CC_CHIP_RESET)); + if (bank == 1) { + val |= CC_BANK_ONE; + } else if (bank == 2) { + val |= CC_DIAG | CC_BANK_ONE; + } else { + val &= ~CC_BANK_ONE; + } + AscSetChipControl(iop_base, val); + return; +} + +int +AscResetChipAndScsiBus( + PortAddr iop_base +) +{ + AscStopChip(iop_base); + AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT); + DvcSleepMilliSecond(200); + + AscSetChipIH(iop_base, INS_RFLAG_WTM); + AscSetChipIH(iop_base, INS_HALT); + + AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT); + AscSetChipControl(iop_base, CC_HALT); + DvcSleepMilliSecond(200); + return (AscIsChipHalted(iop_base)); +} + +ushort +AscGetIsaDmaChannel( + PortAddr iop_base +) +{ + ushort channel; + + channel = AscGetChipCfgLsw(iop_base) & 0x0003; + if (channel == 0x03) + return (0); + else if (channel == 0x00) + return (7); + return (channel + 4); +} + +ushort +AscSetIsaDmaChannel( + PortAddr iop_base, + ushort dma_channel +) +{ + ushort cfg_lsw; + uchar value; + + if ((dma_channel >= 5) && (dma_channel <= 7)) { + + if (dma_channel == 7) + value = 0x00; + else + value = dma_channel - 4; + cfg_lsw = AscGetChipCfgLsw(iop_base) & 0xFFFC; + cfg_lsw |= value; + AscSetChipCfgLsw(iop_base, cfg_lsw); + return (AscGetIsaDmaChannel(iop_base)); + } + return (0); +} + +uchar +AscSetIsaDmaSpeed( + PortAddr iop_base, + uchar speed_value +) +{ + speed_value &= 0x07; + AscSetBank(iop_base, 1); + AscSetChipDmaSpeed(iop_base, speed_value); + AscSetBank(iop_base, 0); + return (AscGetIsaDmaSpeed(iop_base)); +} + +uchar +AscGetIsaDmaSpeed( + PortAddr iop_base +) +{ + uchar speed_value; + + AscSetBank(iop_base, 1); + speed_value = AscGetChipDmaSpeed(iop_base); + speed_value &= 0x07; + AscSetBank(iop_base, 0); + return (speed_value); +} + +ulong +AscGetMaxDmaCount( + ushort bus_type +) +{ + if (bus_type & ASC_IS_ISA) + return (ASC_MAX_ISA_DMA_COUNT); + else if (bus_type & (ASC_IS_EISA | ASC_IS_VL)) + return (ASC_MAX_VL_DMA_COUNT); + return (ASC_MAX_PCI_DMA_COUNT); +} + +ushort +AscInitGetConfig( + ASC_DVC_VAR asc_ptr_type * asc_dvc +) +{ + ushort warn_code; + + warn_code = 0; + asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG; + if (asc_dvc->err_code != 0) + return (UW_ERR); + if (AscFindSignature(asc_dvc->iop_base)) { + warn_code |= AscInitAscDvcVar(asc_dvc); + warn_code |= AscInitFromEEP(asc_dvc); + asc_dvc->init_state |= ASC_INIT_STATE_END_GET_CFG; + + if (asc_dvc->scsi_reset_wait > 10) + asc_dvc->scsi_reset_wait = 10; + + } else { + asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; + } + return (warn_code); +} + +ushort +AscInitSetConfig( + ASC_DVC_VAR asc_ptr_type * asc_dvc +) +{ + ushort warn_code; + + warn_code = 0; + asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG; + if (asc_dvc->err_code != 0) + return (UW_ERR); + if (AscFindSignature(asc_dvc->iop_base)) { + warn_code |= AscInitFromAscDvcVar(asc_dvc); + asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG; + } else { + asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; + } + return (warn_code); +} + +ushort +AscInitAsc1000Driver( + ASC_DVC_VAR asc_ptr_type * asc_dvc +) +{ + ushort warn_code; + PortAddr iop_base; + + extern ushort _mcode_size; + extern ulong _mcode_chksum; + extern uchar _mcode_buf[]; + + ASC_DBG(3, "AscInitAsc1000Driver: begin\n"); + iop_base = asc_dvc->iop_base; + warn_code = 0; + + if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) && + !(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) { + + ASC_DBG(3, "AscInitAsc1000Driver: AscResetChipAndScsiBus()\n"); + AscResetChipAndScsiBus(iop_base); + DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000)); + } + asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC; + if (asc_dvc->err_code != 0) + return (UW_ERR); + ASC_DBG(3, "AscInitAsc1000Driver: AscFindSignature()\n"); + if (!AscFindSignature(asc_dvc->iop_base)) { + asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; + return (warn_code); + } + ASC_DBG(3, "AscInitAsc1000Driver: AscDisableInterrupt()\n"); + AscDisableInterrupt(iop_base); + + ASC_DBG(3, "AscInitAsc1000Driver: AscInitLram()\n"); + warn_code |= AscInitLram(asc_dvc); + if (asc_dvc->err_code != 0) + return (UW_ERR); + ASC_DBG(3, "AscInitAsc1000Driver: AscLoadMicroCode()\n"); + if (AscLoadMicroCode(iop_base, 0, (ushort dosfar *) _mcode_buf, + _mcode_size) != _mcode_chksum) { + asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM; + return (warn_code); + } + ASC_DBG(3, "AscInitAsc1000Driver: AscInitMicroCodeVar()\n"); + warn_code |= AscInitMicroCodeVar(asc_dvc); + asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC; + ASC_DBG(3, "AscInitAsc1000Driver: AscEnableInterrupt()\n"); + AscEnableInterrupt(iop_base); + return (warn_code); +} + +ushort +AscInitAscDvcVar( + ASC_DVC_VAR asc_ptr_type * asc_dvc +) +{ + int i; + PortAddr iop_base; + ushort warn_code; + + iop_base = asc_dvc->iop_base; + warn_code = 0; + asc_dvc->err_code = 0; + + if ((asc_dvc->bus_type & + (ASC_IS_ISA | ASC_IS_PCI | ASC_IS_EISA | ASC_IS_VL)) == 0) { + asc_dvc->err_code |= ASC_IERR_NO_BUS_TYPE; + } +#if CC_LINK_BUSY_Q + for (i = 0; i <= ASC_MAX_TID; i++) { + asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q dosfar *) 0L; + asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q dosfar *) 0L; + } +#endif + + asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL; + asc_dvc->bug_fix_cntl = 0; + asc_dvc->pci_fix_asyn_xfer = 0; + asc_dvc->init_sdtr = 0; + asc_dvc->sdtr_done = 0; + asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG; + asc_dvc->cur_total_qng = 0; + asc_dvc->is_in_int = 0; + asc_dvc->scsi_reset_wait = 3; + asc_dvc->in_critical_cnt = 0; + + asc_dvc->last_q_shortage = 0; + asc_dvc->use_tagged_qng = 0; + asc_dvc->cfg->can_tagged_qng = 0; + asc_dvc->no_scam = 0; + asc_dvc->irq_no = 10; + asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET; + asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET; + asc_dvc->cfg->cmd_qng_enabled = ASC_SCSI_WIDTH_BIT_SET; + asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID; + asc_dvc->cfg->chip_version = AscGetChipVersion(iop_base, + asc_dvc->bus_type); + if (AscGetChipBusType(iop_base) == ASC_IS_ISAPNP) { + + AscPutChipIFC(iop_base, IFC_INIT_DEFAULT); + asc_dvc->bus_type = ASC_IS_ISAPNP; + } + asc_dvc->unit_not_ready = 0; + asc_dvc->queue_full_or_busy = 0; + + if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) { + asc_dvc->cfg->isa_dma_channel = (uchar) AscGetIsaDmaChannel(iop_base); + asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED; + } + asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER; + asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) | + ASC_LIB_VERSION_MINOR; + asc_dvc->int_count = 0L; + asc_dvc->req_count = 0L; + asc_dvc->busy_count = 0L; + asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type); + + for (i = 0; i <= ASC_MAX_TID; i++) { + asc_dvc->cfg->sdtr_data[i] = + (uchar) (ASC_DEF_SDTR_OFFSET | (ASC_DEF_SDTR_INDEX << 4)); + asc_dvc->cur_dvc_qng[i] = 0; + asc_dvc->max_dvc_qng[i] = ASC_MAX_SCSI1_QNG; + asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q dosfar *) 0L; + asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q dosfar *) 0L; + } + return (warn_code); +} + +ushort +AscInitFromAscDvcVar( + ASC_DVC_VAR asc_ptr_type * asc_dvc +) +{ + PortAddr iop_base; + ushort cfg_msw; + ushort warn_code; + + iop_base = asc_dvc->iop_base; + warn_code = 0; + + cfg_msw = AscGetChipCfgMsw(iop_base); + + if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) { + cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK)); + warn_code |= ASC_WARN_CFG_MSW_RECOVER; + AscSetChipCfgMsw(iop_base, cfg_msw); + } + if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) { + warn_code |= ASC_WARN_AUTO_CONFIG; + + } + if ((asc_dvc->cfg->cmd_qng_enabled & asc_dvc->cfg->disc_enable) != + asc_dvc->cfg->cmd_qng_enabled) { + asc_dvc->cfg->disc_enable = asc_dvc->cfg->cmd_qng_enabled; + warn_code |= ASC_WARN_CMD_QNG_CONFLICT; + } + if ((asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL)) != 0) { + + if (AscSetChipIRQ(iop_base, asc_dvc->irq_no, asc_dvc->bus_type) + != asc_dvc->irq_no) { + asc_dvc->err_code |= ASC_IERR_SET_IRQ_NO; + } + } + if (AscSetChipScsiID(iop_base, asc_dvc->cfg->chip_scsi_id) != + asc_dvc->cfg->chip_scsi_id) { + asc_dvc->err_code |= ASC_IERR_SET_SCSI_ID; + } + if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) { + AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel); + AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed); + } + return (warn_code); +} + +ushort +AscInitFromEEP( + ASC_DVC_VAR asc_ptr_type * asc_dvc +) +{ + ASCEEP_CONFIG eep_config_buf; + ASCEEP_CONFIG dosfar *eep_config; + PortAddr iop_base; + ushort chksum; + ushort warn_code; + ushort cfg_msw, cfg_lsw; + uchar i; + + iop_base = asc_dvc->iop_base; + warn_code = 0; + + AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0x00FE); + + AscStopQueueExe(iop_base); + if ((AscStopChip(iop_base) == FALSE) || + (AscGetChipScsiCtrl(iop_base) != 0)) { + asc_dvc->init_state |= ASC_INIT_RESET_SCSI_DONE; + AscResetChipAndScsiBus(iop_base); + DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000)); + } + if (AscIsChipHalted(iop_base) == FALSE) { + asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP; + return (warn_code); + } + AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR); + if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) { + asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR; + return (warn_code); + } + eep_config = (ASCEEP_CONFIG dosfar *) & eep_config_buf; + + cfg_msw = AscGetChipCfgMsw(iop_base); + cfg_lsw = AscGetChipCfgLsw(iop_base); + + if (asc_dvc->bus_type & ASC_IS_PCI) { +#if CC_DISABLE_PCI_PARITY_INT + cfg_msw &= 0xFFC0; + AscSetChipCfgMsw(iop_base, cfg_msw); +#endif + if (asc_dvc->cfg->pci_device_id == ASC_PCI_DEVICE_ID_REV_A) { + asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ADD_ONE_BYTE; + } + } + if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) { + cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK)); + warn_code |= ASC_WARN_CFG_MSW_RECOVER; + AscSetChipCfgMsw(iop_base, cfg_msw); + } + chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type); + + eep_config->cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK)); + + if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) { + warn_code |= ASC_WARN_AUTO_CONFIG; + + if (asc_dvc->cfg->chip_version == 3) { + + if (eep_config->cfg_lsw != cfg_lsw) { + warn_code |= ASC_WARN_EEPROM_RECOVER; + eep_config->cfg_lsw = AscGetChipCfgLsw(iop_base); + } + if (eep_config->cfg_msw != cfg_msw) { + warn_code |= ASC_WARN_EEPROM_RECOVER; + eep_config->cfg_msw = AscGetChipCfgMsw(iop_base); + } + } + } + eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON; + if (chksum != eep_config->chksum) { + warn_code |= ASC_WARN_EEPROM_CHKSUM; + } + asc_dvc->init_sdtr = eep_config->init_sdtr; + asc_dvc->cfg->disc_enable = eep_config->disc_enable; + + asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng; + asc_dvc->cfg->isa_dma_speed = eep_config->isa_dma_speed; + asc_dvc->start_motor = eep_config->start_motor; + asc_dvc->dvc_cntl = eep_config->cntl; + asc_dvc->no_scam = eep_config->no_scam; + + if ((asc_dvc->bus_type & ASC_IS_PCI) && + !(asc_dvc->dvc_cntl & ASC_CNTL_NO_PCI_FIX_ASYN_XFER)) { + if ((asc_dvc->cfg->pci_device_id == ASC_PCI_DEVICE_ID_REV_A) || + (asc_dvc->cfg->pci_device_id == ASC_PCI_DEVICE_ID_REV_B)) { + asc_dvc->pci_fix_asyn_xfer = ASC_ALL_DEVICE_BIT_SET; + } + } else if (asc_dvc->bus_type & ASC_IS_ISAPNP) { + + if (AscGetChipVersion(iop_base, asc_dvc->bus_type) + == ASC_CHIP_VER_ASYN_BUG) { + asc_dvc->pci_fix_asyn_xfer = ASC_ALL_DEVICE_BIT_SET; + } + } + if (!AscTestExternalLram(asc_dvc)) { + if (asc_dvc->bus_type & ASC_IS_PCI) { + eep_config->cfg_msw |= 0x0800; + cfg_msw |= 0x0800; + AscSetChipCfgMsw(iop_base, cfg_msw); + eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG; + eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG; + } + } else { +#if CC_TEST_RW_LRAM + asc_dvc->err_code |= AscTestLramEndian(iop_base); +#endif + } + if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) { + eep_config->max_total_qng = ASC_MIN_TOTAL_QNG; + } + if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) { + eep_config->max_total_qng = ASC_MAX_TOTAL_QNG; + } + if (eep_config->max_tag_qng > eep_config->max_total_qng) { + eep_config->max_tag_qng = eep_config->max_total_qng; + } + if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) { + eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC; + } + asc_dvc->max_total_qng = eep_config->max_total_qng; + + if ((eep_config->use_cmd_qng & eep_config->disc_enable) != + eep_config->use_cmd_qng) { + eep_config->disc_enable = eep_config->use_cmd_qng; + warn_code |= ASC_WARN_CMD_QNG_CONFLICT; + } + asc_dvc->irq_no = AscGetChipIRQ(iop_base, asc_dvc->bus_type); + eep_config->chip_scsi_id &= ASC_MAX_TID; + asc_dvc->cfg->chip_scsi_id = eep_config->chip_scsi_id; + + for (i = 0; i <= ASC_MAX_TID; i++) { + asc_dvc->cfg->sdtr_data[i] = eep_config->sdtr_data[i]; + asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng; + } + + eep_config->cfg_msw = AscGetChipCfgMsw(iop_base); + if (AscSetEEPConfig(iop_base, eep_config, asc_dvc->bus_type) != 0) { + asc_dvc->err_code |= ASC_IERR_WRITE_EEPROM; + } + return (warn_code); +} + +ushort +AscInitMicroCodeVar( + ASC_DVC_VAR asc_ptr_type * asc_dvc +) +{ + int i; + ushort warn_code; + PortAddr iop_base; + ulong phy_addr; + + iop_base = asc_dvc->iop_base; + warn_code = 0; + for (i = 0; i <= ASC_MAX_TID; i++) { + AscWriteLramByte(iop_base, (ushort) (ASCV_SDTR_DATA_BEG + i), + asc_dvc->cfg->sdtr_data[i]); + } + + AscInitQLinkVar(asc_dvc); + + AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B, + asc_dvc->cfg->disc_enable); + AscWriteLramByte(iop_base, ASCV_HOSTSCSI_ID_B, + ASC_TID_TO_TARGET_ID(asc_dvc->cfg->chip_scsi_id)); + if ((phy_addr = AscGetOnePhyAddr(asc_dvc, + (uchar dosfar *) asc_dvc->cfg->overrun_buf, + ASC_OVERRUN_BSIZE)) == 0L) { + asc_dvc->err_code |= ASC_IERR_GET_PHY_ADDR; + } else { + + phy_addr = (phy_addr & 0xFFFFFFF8UL) + 8; + AscWriteLramDWord(iop_base, ASCV_OVERRUN_PADDR_D, phy_addr); + AscWriteLramDWord(iop_base, ASCV_OVERRUN_BSIZE_D, + ASC_OVERRUN_BSIZE - 8); + } + + asc_dvc->cfg->mcode_date = AscReadLramWord(iop_base, + (ushort) ASCV_MC_DATE_W); + asc_dvc->cfg->mcode_version = AscReadLramWord(iop_base, + (ushort) ASCV_MC_VER_W); + AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR); + if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) { + asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR; + return (warn_code); + } + if (AscStartChip(iop_base) != 1) { + asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP; + return (warn_code); + } + return (warn_code); +} + +void dosfar +AscInitPollIsrCallBack( + ASC_DVC_VAR asc_ptr_type * asc_dvc, + ASC_QDONE_INFO dosfar * scsi_done_q +) +{ + ASC_SCSI_REQ_Q dosfar *scsiq_req; + ASC_ISR_CALLBACK asc_isr_callback; + uchar cp_sen_len; + uchar i; + + if ((scsi_done_q->d2.flag & ASC_FLAG_SCSIQ_REQ) != 0) { + scsiq_req = (ASC_SCSI_REQ_Q dosfar *) scsi_done_q->d2.srb_ptr; + ASC_DBG2(3, "AscInitPollIsrCallBack: done_stat %x, host_stat %x\n", + scsiq_req->r3.done_stat, scsiq_req->r3.host_stat); + scsiq_req->r3.done_stat = scsi_done_q->d3.done_stat; + scsiq_req->r3.host_stat = scsi_done_q->d3.host_stat; + scsiq_req->r3.scsi_stat = scsi_done_q->d3.scsi_stat; + scsiq_req->r3.scsi_msg = scsi_done_q->d3.scsi_msg; + if ((scsi_done_q->d3.scsi_stat == SS_CHK_CONDITION) && + (scsi_done_q->d3.host_stat == 0)) { + cp_sen_len = (uchar) ASC_MIN_SENSE_LEN; + if (scsiq_req->r1.sense_len < ASC_MIN_SENSE_LEN) { + cp_sen_len = (uchar) scsiq_req->r1.sense_len; + } + for (i = 0; i < cp_sen_len; i++) { + scsiq_req->sense[i] = scsiq_req->sense_ptr[i]; + } + } + } else { + ASC_DBG1(3, "AscInitPollIsrCallBack: isr_callback %x\n", + (unsigned) asc_dvc->isr_callback); + if (asc_dvc->isr_callback != 0) { + asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback; + (*asc_isr_callback) (asc_dvc, scsi_done_q); + } + } + return; +} + +int +AscTestExternalLram( + ASC_DVC_VAR asc_ptr_type * asc_dvc +) +{ + PortAddr iop_base; + ushort q_addr; + ushort saved_word; + int sta; + + iop_base = asc_dvc->iop_base; + sta = 0; + + q_addr = ASC_QNO_TO_QADDR(241); + saved_word = AscReadLramWord(iop_base, q_addr); + if (AscVerWriteLramWord(iop_base, q_addr, 0x55AA) == 0) { + sta = 1; + AscWriteLramWord(iop_base, q_addr, saved_word); + } + return (sta); +} + +#if CC_TEST_LRAM_ENDIAN + +#endif + +int +AscWriteEEPCmdReg( + PortAddr iop_base, + uchar cmd_reg +) +{ + uchar read_back; + int retry; + + retry = 0; + while (TRUE) { + AscSetChipEEPCmd(iop_base, cmd_reg); + DvcSleepMilliSecond(1); + read_back = AscGetChipEEPCmd(iop_base); + if (read_back == cmd_reg) { + return (1); + } + if (retry++ > ASC_EEP_MAX_RETRY) { + return (0); + } + } +} + +int +AscWriteEEPDataReg( + PortAddr iop_base, + ushort data_reg +) +{ + ushort read_back; + int retry; + + retry = 0; + while (TRUE) { + AscSetChipEEPData(iop_base, data_reg); + DvcSleepMilliSecond(1); + read_back = AscGetChipEEPData(iop_base); + if (read_back == data_reg) { + return (1); + } + if (retry++ > ASC_EEP_MAX_RETRY) { + return (0); + } + } +} + +void +AscWaitEEPRead( + void +) +{ + DvcSleepMilliSecond(1); + return; +} + +void +AscWaitEEPWrite( + void +) +{ + DvcSleepMilliSecond(20); + return; +} + +ushort +AscReadEEPWord( + PortAddr iop_base, + uchar addr +) +{ + ushort read_wval; + uchar cmd_reg; + + AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE); + AscWaitEEPRead(); + cmd_reg = addr | ASC_EEP_CMD_READ; + AscWriteEEPCmdReg(iop_base, cmd_reg); + AscWaitEEPRead(); + read_wval = AscGetChipEEPData(iop_base); + AscWaitEEPRead(); + return (read_wval); +} + +ushort +AscWriteEEPWord( + PortAddr iop_base, + uchar addr, + ushort word_val +) +{ + ushort read_wval; + + read_wval = AscReadEEPWord(iop_base, addr); + if (read_wval != word_val) { + AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_ABLE); + AscWaitEEPRead(); + + AscWriteEEPDataReg(iop_base, word_val); + AscWaitEEPRead(); + + AscWriteEEPCmdReg(iop_base, + (uchar) ((uchar) ASC_EEP_CMD_WRITE | addr)); + AscWaitEEPWrite(); + + AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE); + AscWaitEEPRead(); + return (AscReadEEPWord(iop_base, addr)); + } + return (read_wval); +} + +ushort +AscGetEEPConfig( + PortAddr iop_base, + ASCEEP_CONFIG dosfar * cfg_buf, ushort bus_type +) +{ + ushort wval; + ushort sum; + ushort dosfar *wbuf; + int cfg_beg; + int cfg_end; + int s_addr; + int isa_pnp_wsize; + + wbuf = (ushort dosfar *) cfg_buf; + sum = 0; + + isa_pnp_wsize = 0; + for (s_addr = 0; s_addr < (2 + isa_pnp_wsize); s_addr++, wbuf++) { + wval = AscReadEEPWord(iop_base, (uchar) s_addr); + sum += wval; + *wbuf = wval; + } + + if (bus_type & ASC_IS_VL) { + cfg_beg = ASC_EEP_DVC_CFG_BEG_VL; + cfg_end = ASC_EEP_MAX_DVC_ADDR_VL; + } else { + cfg_beg = ASC_EEP_DVC_CFG_BEG; + cfg_end = ASC_EEP_MAX_DVC_ADDR; + } + + for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); + s_addr++, wbuf++) { + wval = AscReadEEPWord(iop_base, (uchar) s_addr); + sum += wval; + *wbuf = wval; + } + *wbuf = AscReadEEPWord(iop_base, (uchar) s_addr); + return (sum); +} + +int +AscSetEEPConfigOnce( + PortAddr iop_base, + ASCEEP_CONFIG dosfar * cfg_buf, ushort bus_type +) +{ + int n_error; + ushort dosfar *wbuf; + ushort sum; + int s_addr; + int cfg_beg; + int cfg_end; + + wbuf = (ushort dosfar *) cfg_buf; + n_error = 0; + sum = 0; + for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) { + sum += *wbuf; + if (*wbuf != AscWriteEEPWord(iop_base, (uchar) s_addr, *wbuf)) { + n_error++; + } + } + if (bus_type & ASC_IS_VL) { + cfg_beg = ASC_EEP_DVC_CFG_BEG_VL; + cfg_end = ASC_EEP_MAX_DVC_ADDR_VL; + } else { + cfg_beg = ASC_EEP_DVC_CFG_BEG; + cfg_end = ASC_EEP_MAX_DVC_ADDR; + } + for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); + s_addr++, wbuf++) { + sum += *wbuf; + if (*wbuf != AscWriteEEPWord(iop_base, (uchar) s_addr, *wbuf)) { + n_error++; + } + } + *wbuf = sum; + if (sum != AscWriteEEPWord(iop_base, (uchar) s_addr, sum)) { + n_error++; + } + wbuf = (ushort dosfar *) cfg_buf; + for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) { + if (*wbuf != AscReadEEPWord(iop_base, (uchar) s_addr)) { + n_error++; + } + } + for (s_addr = cfg_beg; s_addr <= cfg_end; + s_addr++, wbuf++) { + if (*wbuf != AscReadEEPWord(iop_base, (uchar) s_addr)) { + n_error++; + } + } + return (n_error); +} + +int +AscSetEEPConfig( + PortAddr iop_base, + ASCEEP_CONFIG dosfar * cfg_buf, ushort bus_type +) +{ + int retry; + int n_error; + + retry = 0; + while (TRUE) { + if ((n_error = AscSetEEPConfigOnce(iop_base, cfg_buf, + bus_type)) == 0) { + break; + } + if (++retry > ASC_EEP_MAX_RETRY) { + break; + } + } + return (n_error); +} + +int +AscInitPollBegin( + ASC_DVC_VAR asc_ptr_type * asc_dvc +) +{ + PortAddr iop_base; + + iop_base = asc_dvc->iop_base; + +#if CC_INIT_INQ_DISPLAY + DvcDisplayString((uchar dosfar *) "\r\n"); +#endif + + AscDisableInterrupt(iop_base); + + asc_dvc->init_state |= ASC_INIT_STATE_BEG_INQUIRY; + + AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B, 0x00); + asc_dvc->use_tagged_qng = 0; + asc_dvc->cfg->can_tagged_qng = 0; + asc_dvc->saved_ptr2func = (ulong) asc_dvc->isr_callback; + asc_dvc->isr_callback = ASC_GET_PTR2FUNC(AscInitPollIsrCallBack); + return (0); +} + +int +AscInitPollEnd( + ASC_DVC_VAR asc_ptr_type * asc_dvc +) +{ + PortAddr iop_base; + int i; + + iop_base = asc_dvc->iop_base; + asc_dvc->isr_callback = (Ptr2Func) asc_dvc->saved_ptr2func; + AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B, + asc_dvc->cfg->disc_enable); + AscWriteLramByte(iop_base, ASCV_USE_TAGGED_QNG_B, + asc_dvc->use_tagged_qng); + AscWriteLramByte(iop_base, ASCV_CAN_TAGGED_QNG_B, + asc_dvc->cfg->can_tagged_qng); + + for (i = 0; i <= ASC_MAX_TID; i++) { + AscWriteLramByte(iop_base, + (ushort) ((ushort) ASCV_MAX_DVC_QNG_BEG + (ushort) i), + asc_dvc->max_dvc_qng[i]); + } + + AscEnableInterrupt(iop_base); + +#if CC_INIT_INQ_DISPLAY + DvcDisplayString((uchar dosfar *) "\r\n"); +#endif + asc_dvc->init_state |= ASC_INIT_STATE_END_INQUIRY; + + return (0); +} + +int _asc_wait_slow_device_ = FALSE; + +int +AscInitPollTarget( + ASC_DVC_VAR asc_ptr_type * asc_dvc, + ASC_SCSI_REQ_Q dosfar * scsiq, + ASC_SCSI_INQUIRY dosfar * inq, + ASC_CAP_INFO dosfar * cap_info +) +{ + uchar tid_no, lun; + uchar dvc_type; + ASC_SCSI_BIT_ID_TYPE tid_bits; + int dvc_found; + int support_read_cap; + int tmp_disable_init_sdtr; + ulong phy_addr; + + dvc_found = 0; + tmp_disable_init_sdtr = FALSE; + tid_bits = scsiq->r1.target_id; + lun = scsiq->r1.target_lun; + tid_no = ASC_TIX_TO_TID(scsiq->r2.target_ix); + if ((phy_addr = AscGetOnePhyAddr(asc_dvc, + (uchar dosfar *) scsiq->sense_ptr, + (ulong) scsiq->r1.sense_len)) == 0L) { + return (ERR); + } + scsiq->r1.sense_addr = phy_addr; + if (((asc_dvc->init_sdtr & tid_bits) != 0) && + ((asc_dvc->sdtr_done & tid_bits) == 0)) { + + asc_dvc->init_sdtr &= ~tid_bits; + tmp_disable_init_sdtr = TRUE; + } + ASC_DBG(3, "AscInitPollTarget: PollScsiInquiry()\n"); + if (PollScsiInquiry(asc_dvc, scsiq, (uchar dosfar *) inq, + sizeof (ASC_SCSI_INQUIRY)) == 1) { + dvc_found = 1; + support_read_cap = TRUE; + dvc_type = inq->byte0.peri_dvc_type; + if (dvc_type != SCSI_TYPE_UNKNOWN) { + if ((dvc_type != SCSI_TYPE_DASD) && + (dvc_type != SCSI_TYPE_WORM) && + (dvc_type != SCSI_TYPE_CDROM) && + (dvc_type != SCSI_TYPE_OPTMEM)) { + asc_dvc->start_motor &= ~tid_bits; + support_read_cap = FALSE; + } + if ((dvc_type != SCSI_TYPE_DASD) || + inq->byte1.rmb) { + + if (!_asc_wait_slow_device_) { + DvcSleepMilliSecond(3000 - ((int) tid_no * 250)); + _asc_wait_slow_device_ = TRUE; + } + } +#if CC_INIT_INQ_DISPLAY + AscDispInquiry(tid_no, lun, inq); +#endif + + if (lun == 0) { + + if ((inq->byte3.rsp_data_fmt >= 2) || + (inq->byte2.ansi_apr_ver >= 2)) { + + if (inq->byte7.CmdQue) { + asc_dvc->cfg->can_tagged_qng |= tid_bits; + if (asc_dvc->cfg->cmd_qng_enabled & tid_bits) { + asc_dvc->use_tagged_qng |= tid_bits; + asc_dvc->max_dvc_qng[tid_no] = + asc_dvc->cfg->max_tag_qng[tid_no]; + } + } + if (!inq->byte7.Sync) { + + asc_dvc->init_sdtr &= ~tid_bits; + asc_dvc->sdtr_done &= ~tid_bits; + } else if (tmp_disable_init_sdtr) { + + asc_dvc->init_sdtr |= tid_bits; + } + } else { + + asc_dvc->init_sdtr &= ~tid_bits; + asc_dvc->sdtr_done &= ~tid_bits; + asc_dvc->use_tagged_qng &= ~tid_bits; + } + } + if (asc_dvc->pci_fix_asyn_xfer & tid_bits) { + if (!(asc_dvc->init_sdtr & tid_bits)) { + + AscSetRunChipSynRegAtID(asc_dvc->iop_base, tid_no, + ASYN_SDTR_DATA_FIX_PCI_REV_AB); + } + } + ASC_DBG(3, "AscInitPollTarget: InitTestUnitReady()\n"); + if (InitTestUnitReady(asc_dvc, scsiq) != 1) { + + } else { + if ((cap_info != 0L) && support_read_cap) { + ASC_DBG(3, "AscInitPollTarget: PollScsiReadCapacity()\n"); + if (PollScsiReadCapacity(asc_dvc, scsiq, + cap_info) != 1) { + cap_info->lba = 0L; + cap_info->blk_size = 0x0000; + } else { + + } + } + } + } else { + asc_dvc->start_motor &= ~tid_bits; + } + } else { + + } + return (dvc_found); +} + +int +PollQueueDone( + ASC_DVC_VAR asc_ptr_type * asc_dvc, + ASC_SCSI_REQ_Q dosfar * scsiq, + int timeout_sec +) +{ + int status; + int retry; + + retry = 0; + do { + ASC_DBG(3, "PollQueueDone: AscExeScsiQueue()\n"); + if ((status = AscExeScsiQueue(asc_dvc, + (ASC_SCSI_Q dosfar *) scsiq)) == 1) { + ASC_DBG(3, "PollQueueDone: AscPollQDone()\n"); + if ((status = AscPollQDone(asc_dvc, scsiq, + timeout_sec)) != 1) { + ASC_DBG1(3, "PollQueueDone: AscPollQDone() status %x\n", status); + if (status == 0x80) { + if (retry++ > ASC_MAX_INIT_BUSY_RETRY) { + break; + } + scsiq->r3.done_stat = 0; + scsiq->r3.host_stat = 0; + scsiq->r3.scsi_stat = 0; + scsiq->r3.scsi_msg = 0; + DvcSleepMilliSecond(100); + continue; + } + scsiq->r3.done_stat = 0; + scsiq->r3.host_stat = 0; + scsiq->r3.scsi_stat = 0; + scsiq->r3.scsi_msg = 0; + ASC_DBG1(3, "PollQueueDone: AscAbortSRB() scsiq %x\n", + (unsigned) scsiq); + + AscAbortSRB(asc_dvc, (ulong) scsiq); + } + ASC_DBG1(3, "PollQueueDone: done_stat %x\n", scsiq->r3.done_stat); + return (scsiq->r3.done_stat); + } + } while ((status == 0) || (status == 0x80)); + ASC_DBG(3, "PollQueueDone: done_stat QD_WITH_ERROR\n"); + return (scsiq->r3.done_stat = QD_WITH_ERROR); +} + +int +PollScsiInquiry( + ASC_DVC_VAR asc_ptr_type * asc_dvc, + ASC_SCSI_REQ_Q dosfar * scsiq, + uchar dosfar * buf, + int buf_len +) +{ + if (AscScsiInquiry(asc_dvc, scsiq, buf, buf_len) == ERR) { + return (scsiq->r3.done_stat = QD_WITH_ERROR); + } + return (PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q dosfar *) scsiq, 4)); +} + +int +PollScsiReadCapacity( + ASC_DVC_VAR asc_ptr_type * asc_dvc, + ASC_SCSI_REQ_Q dosfar * scsiq, + ASC_CAP_INFO dosfar * cap_info +) +{ + ASC_CAP_INFO scsi_cap_info; + int status; + + if (AscScsiReadCapacity(asc_dvc, scsiq, + (uchar dosfar *) & scsi_cap_info) == ERR) { + return (scsiq->r3.done_stat = QD_WITH_ERROR); + } + status = PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q dosfar *) scsiq, 8); + if (status == 1) { +#if CC_LITTLE_ENDIAN_HOST + cap_info->lba = (ulong) * swapfarbuf4((uchar dosfar *) & scsi_cap_info.lba); + cap_info->blk_size = (ulong) * swapfarbuf4((uchar dosfar *) & scsi_cap_info.blk_size); +#else + cap_info->lba = scsi_cap_info.lba; + cap_info->blk_size = scsi_cap_info.blk_size; +#endif + return (scsiq->r3.done_stat); + } + return (scsiq->r3.done_stat = QD_WITH_ERROR); +} + +ulong dosfar * +swapfarbuf4( + uchar dosfar * buf +) +{ + uchar tmp; + + tmp = buf[3]; + buf[3] = buf[0]; + buf[0] = tmp; + + tmp = buf[1]; + buf[1] = buf[2]; + buf[2] = tmp; + + return ((ulong dosfar *) buf); +} + +int +PollScsiTestUnitReady( + ASC_DVC_VAR asc_ptr_type * asc_dvc, + ASC_SCSI_REQ_Q dosfar * scsiq +) +{ + if (AscScsiTestUnitReady(asc_dvc, scsiq) == ERR) { + return (scsiq->r3.done_stat = QD_WITH_ERROR); + } + return (PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q dosfar *) scsiq, 12)); +} + +int +PollScsiStartUnit( + ASC_DVC_VAR asc_ptr_type * asc_dvc, + ASC_SCSI_REQ_Q dosfar * scsiq +) +{ + if (AscScsiStartStopUnit(asc_dvc, scsiq, 1) == ERR) { + return (scsiq->r3.done_stat = QD_WITH_ERROR); + } + return (PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q dosfar *) scsiq, 40)); +} + +int +InitTestUnitReady( + ASC_DVC_VAR asc_ptr_type * asc_dvc, + ASC_SCSI_REQ_Q dosfar * scsiq +) +{ + ASC_SCSI_BIT_ID_TYPE tid_bits; + int retry; + ASC_REQ_SENSE dosfar *sen; + + retry = 0; + tid_bits = scsiq->r1.target_id; + while (retry++ < 2) { + ASC_DBG(3, "InitTestUnitReady: PollScsiTestUnitReady()\n"); + PollScsiTestUnitReady(asc_dvc, scsiq); + ASC_DBG1(3, "InitTestUnitReady: done_stat %x\n", scsiq->r3.done_stat); + if (scsiq->r3.done_stat == 0x01) { + return (1); + } else if (scsiq->r3.done_stat == QD_WITH_ERROR) { + DvcSleepMilliSecond(100); + + sen = (ASC_REQ_SENSE dosfar *) scsiq->sense_ptr; + + if ((scsiq->r3.scsi_stat == SS_CHK_CONDITION) && + ((sen->err_code & 0x70) != 0)) { + + if (sen->sense_key == SCSI_SENKEY_NOT_READY) { + + if (asc_dvc->start_motor & tid_bits) { + if (PollScsiStartUnit(asc_dvc, scsiq) == 1) { + retry = 0; + continue; + } else { + asc_dvc->start_motor &= ~tid_bits; + break; + } + } else { + DvcSleepMilliSecond(100); + } + } else if (sen->sense_key == SCSI_SENKEY_ATTENSION) { + DvcSleepMilliSecond(100); + } else { + break; + } + } else { + break; + } + } else if (scsiq->r3.done_stat == QD_ABORTED_BY_HOST) { + break; + } else { + break; + } + } + return (0); +} + +#if CC_INIT_INQ_DISPLAY + +#endif + +int +AscPollQDone( + ASC_DVC_VAR asc_ptr_type * asc_dvc, + ASC_SCSI_REQ_Q dosfar * scsiq, + int timeout_sec +) +{ + int loop, loop_end; + int sta; + PortAddr iop_base; + + iop_base = asc_dvc->iop_base; + loop = 0; + loop_end = timeout_sec * 100; + sta = 1; + + while (TRUE) { + ASC_DBG4(3, + "AscPollQDone: loop %d, err_code %x, done_stat %x, scsi_stat %x\n", + loop, asc_dvc->err_code, scsiq->r3.done_stat, scsiq->r3.scsi_stat); + if (asc_dvc->err_code != 0) { + scsiq->r3.done_stat = QD_WITH_ERROR; + sta = ERR; + break; + } + if (scsiq->r3.done_stat != QD_IN_PROGRESS) { + if ((scsiq->r3.done_stat == QD_WITH_ERROR) && + (scsiq->r3.scsi_stat == SS_TARGET_BUSY)) { + sta = 0x80; + break; + } + break; + } + DvcSleepMilliSecond(10); + if (loop++ > loop_end) { + sta = 0; + break; + } + if (AscIsChipHalted(iop_base)) { + AscISR(asc_dvc); + loop = 0; + } else { + ASC_DBG(3, "AscPollQDone: AscIsIntPending()\n"); + if (AscIsIntPending(iop_base)) { + ASC_DBG(3, "AscPollQDone: AscISR()\n"); + AscISR(asc_dvc); + } + } + } + ASC_DBG1(3, "AscPollQDone: sta %x\n", sta); + return (sta); +} + +uchar +AscReadLramByte( + PortAddr iop_base, + ushort addr +) +{ + uchar byte_data; + ushort word_data; + + if (isodd_word(addr)) { + AscSetChipLramAddr(iop_base, addr - 1); + word_data = AscGetChipLramData(iop_base); + +#if CC_LITTLE_ENDIAN_HOST + byte_data = (uchar) ((word_data >> 8) & 0xFF); +#else + byte_data = (uchar) (word_data & 0xFF); +#endif + + } else { + AscSetChipLramAddr(iop_base, addr); + word_data = AscGetChipLramData(iop_base); + +#if CC_LITTLE_ENDIAN_HOST + byte_data = (uchar) (word_data & 0xFF); +#else + byte_data = (uchar) ((word_data >> 8) & 0xFF); +#endif + + } + return (byte_data); +} + +ushort +AscReadLramWord( + PortAddr iop_base, + ushort addr +) +{ + ushort word_data; + + AscSetChipLramAddr(iop_base, addr); + word_data = AscGetChipLramData(iop_base); + return (word_data); +} + +ulong +AscReadLramDWord( + PortAddr iop_base, + ushort addr +) +{ + ushort val_low, val_high; + ulong dword_data; + + AscSetChipLramAddr(iop_base, addr); + +#if CC_LITTLE_ENDIAN_HOST + val_low = AscGetChipLramData(iop_base); + + val_high = AscGetChipLramData(iop_base); +#else + val_high = AscGetChipLramData(iop_base); + val_low = AscGetChipLramData(iop_base); +#endif + + dword_data = ((ulong) val_high << 16) | (ulong) val_low; + return (dword_data); +} + +void +AscWriteLramWord( + PortAddr iop_base, + ushort addr, + ushort word_val +) +{ + AscSetChipLramAddr(iop_base, addr); + AscPutChipLramData(iop_base, word_val); + return; +} + +void +AscWriteLramDWord( + PortAddr iop_base, + ushort addr, + ulong dword_val +) +{ + ushort word_val; + + AscSetChipLramAddr(iop_base, addr); + +#if CC_LITTLE_ENDIAN_HOST + word_val = (ushort) dword_val; + AscPutChipLramData(iop_base, word_val); + word_val = (ushort) (dword_val >> 16); + AscPutChipLramData(iop_base, word_val); +#else + word_val = (ushort) (dword_val >> 16); + AscPutChipLramData(iop_base, word_val); + word_val = (ushort) dword_val; + AscPutChipLramData(iop_base, word_val); +#endif + return; +} + +void +AscWriteLramByte( + PortAddr iop_base, + ushort addr, + uchar byte_val +) +{ + ushort word_data; + + if (isodd_word(addr)) { + addr--; + word_data = AscReadLramWord(iop_base, addr); + word_data &= 0x00FF; + word_data |= (((ushort) byte_val << 8) & 0xFF00); + } else { + word_data = AscReadLramWord(iop_base, addr); + word_data &= 0xFF00; + word_data |= ((ushort) byte_val & 0x00FF); + } + AscWriteLramWord(iop_base, addr, word_data); + return; +} + +int +AscVerWriteLramWord( + PortAddr iop_base, + ushort addr, + ushort word_val +) +{ + int sta; + + sta = 0; + AscSetChipLramAddr(iop_base, addr); + AscPutChipLramData(iop_base, word_val); + AscSetChipLramAddr(iop_base, addr); + if (word_val != AscGetChipLramData(iop_base)) { + sta = ERR; + } + return (sta); +} + +void +AscMemWordCopyToLram( + PortAddr iop_base, + ushort s_addr, + ushort dosfar * s_buffer, + int words +) +{ + AscSetChipLramAddr(iop_base, s_addr); + DvcOutPortWords(iop_base + IOP_RAM_DATA, s_buffer, words); + return; +} + +void +AscMemDWordCopyToLram( + PortAddr iop_base, + ushort s_addr, + ulong dosfar * s_buffer, + int dwords +) +{ + AscSetChipLramAddr(iop_base, s_addr); + DvcOutPortDWords(iop_base + IOP_RAM_DATA, s_buffer, dwords); + return; +} + +void +AscMemWordCopyFromLram( + PortAddr iop_base, + ushort s_addr, + ushort dosfar * d_buffer, + int words +) +{ + AscSetChipLramAddr(iop_base, s_addr); + DvcInPortWords(iop_base + IOP_RAM_DATA, d_buffer, words); + return; +} + +ulong +AscMemSumLramWord( + PortAddr iop_base, + ushort s_addr, + rint words +) +{ + ulong sum; + int i; + + sum = 0L; + for (i = 0; i < words; i++, s_addr += 2) { + sum += AscReadLramWord(iop_base, s_addr); + } + return (sum); +} + +void +AscMemWordSetLram( + PortAddr iop_base, + ushort s_addr, + ushort set_wval, + rint words +) +{ + rint i; + + AscSetChipLramAddr(iop_base, s_addr); + for (i = 0; i < words; i++) { + AscPutChipLramData(iop_base, set_wval); + } + return; +} + +int +AscScsiInquiry( + ASC_DVC_VAR asc_ptr_type * asc_dvc, + ASC_SCSI_REQ_Q dosfar * scsiq, + uchar dosfar * buf, int buf_len +) +{ + if (AscScsiSetupCmdQ(asc_dvc, scsiq, buf, + (ulong) buf_len) == ERR) { + return (scsiq->r3.done_stat = QD_WITH_ERROR); + } + scsiq->cdb[0] = (uchar) SCSICMD_Inquiry; + scsiq->cdb[1] = scsiq->r1.target_lun << 5; + scsiq->cdb[2] = 0; + scsiq->cdb[3] = 0; + scsiq->cdb[4] = buf_len; + scsiq->cdb[5] = 0; + scsiq->r2.cdb_len = 6; + return (0); +} + +int +AscScsiReadCapacity( + ASC_DVC_VAR asc_ptr_type * asc_dvc, + ASC_SCSI_REQ_Q dosfar * scsiq, + uchar dosfar * info +) +{ + if (AscScsiSetupCmdQ(asc_dvc, scsiq, info, 8L) == ERR) { + return (scsiq->r3.done_stat = QD_WITH_ERROR); + } + scsiq->cdb[0] = (uchar) SCSICMD_ReadCapacity; + scsiq->cdb[1] = scsiq->r1.target_lun << 5; + scsiq->cdb[2] = 0; + scsiq->cdb[3] = 0; + scsiq->cdb[4] = 0; + scsiq->cdb[5] = 0; + scsiq->cdb[6] = 0; + scsiq->cdb[7] = 0; + scsiq->cdb[8] = 0; + scsiq->cdb[9] = 0; + scsiq->r2.cdb_len = 10; + return (0); +} + +int +AscScsiTestUnitReady( + ASC_DVC_VAR asc_ptr_type * asc_dvc, + ASC_SCSI_REQ_Q dosfar * scsiq +) +{ + if (AscScsiSetupCmdQ(asc_dvc, scsiq, FNULLPTR, + (ulong) 0L) == ERR) { + return (scsiq->r3.done_stat = QD_WITH_ERROR); + } + scsiq->r1.cntl = (uchar) ASC_SCSIDIR_NODATA; + scsiq->cdb[0] = (uchar) SCSICMD_TestUnitReady; + scsiq->cdb[1] = scsiq->r1.target_lun << 5; + scsiq->cdb[2] = 0; + scsiq->cdb[3] = 0; + scsiq->cdb[4] = 0; + scsiq->cdb[5] = 0; + scsiq->r2.cdb_len = 6; + return (0); +} + +int +AscScsiStartStopUnit( + ASC_DVC_VAR asc_ptr_type * asc_dvc, + ASC_SCSI_REQ_Q dosfar * scsiq, + uchar op_mode +) +{ + if (AscScsiSetupCmdQ(asc_dvc, scsiq, FNULLPTR, (ulong) 0L) == ERR) { + return (scsiq->r3.done_stat = QD_WITH_ERROR); + } + scsiq->r1.cntl = (uchar) ASC_SCSIDIR_NODATA; + scsiq->cdb[0] = (uchar) SCSICMD_StartStopUnit; + scsiq->cdb[1] = scsiq->r1.target_lun << 5; + scsiq->cdb[2] = 0; + scsiq->cdb[3] = 0; + scsiq->cdb[4] = op_mode; + + scsiq->cdb[5] = 0; + scsiq->r2.cdb_len = 6; + return (0); +} diff -u --recursive --new-file v1.3.57/linux/drivers/scsi/advansys.h linux/drivers/scsi/advansys.h --- v1.3.57/linux/drivers/scsi/advansys.h Thu Jan 1 02:00:00 1970 +++ linux/drivers/scsi/advansys.h Wed Jan 17 07:27:36 1996 @@ -0,0 +1,131 @@ +/* $Id: advansys.h,v 1.10 1996/01/15 04:51:06 bobf Exp bobf $ */ +/* + * advansys.h - Linux Host Driver for AdvanSys SCSI Adapters + * + * Copyright (c) 1995-1996 Advanced System Products, Inc. + * + * This driver may be modified and freely distributed provided that + * the above copyright message and this comment are included in the + * distribution. The latest version of this driver is available at + * the AdvanSys FTP and BBS sites listed below. + * + * Please send questions, comments, and bug reports to: + * bobf@advansys.com (Bob Frey) + */ + +#ifndef _ADVANSYS_H +#define _ADVANSYS_H + +/* The driver can be used in Linux 1.2.X or 1.3.X. */ +#if !defined(LINUX_1_2) && !defined(LINUX_1_3) +#ifndef LINUX_VERSION_CODE +#include +#endif /* LINUX_VERSION_CODE */ +#if LINUX_VERSION_CODE > 65536 + 3 * 256 +#define LINUX_1_3 +#else /* LINUX_VERSION_CODE */ +#define LINUX_1_2 +#endif /* LINUX_VERSION_CODE */ +#endif /* !defined(LINUX_1_2) && !defined(LINUX_1_3) */ + +/* + * Scsi_Host_Template function prototypes. + */ +int advansys_detect(Scsi_Host_Template *); +int advansys_release(struct Scsi_Host *); +const char *advansys_info(struct Scsi_Host *); +int advansys_command(Scsi_Cmnd *); +int advansys_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *)); +int advansys_abort(Scsi_Cmnd *); +int advansys_reset(Scsi_Cmnd *); +#ifdef LINUX_1_2 +int advansys_biosparam(Disk *, int, int[]); +#else /* LINUX_1_3 */ +int advansys_biosparam(Disk *, kdev_t, int[]); +extern struct proc_dir_entry proc_scsi_advansys; +int advansys_proc_info(char *, char **, off_t, int, int, int); +#endif /* LINUX_1_3 */ + +/* init/main.c setup function */ +void advansys_setup(char *, int *); + +/* + * AdvanSys Host Driver Scsi_Host_Template (struct SHT) from hosts.h. + */ +#ifdef LINUX_1_2 +#define ADVANSYS { \ + NULL, /* struct SHT *next */ \ + NULL, /* int *usage_count */ \ + "advansys", /* char *name */ \ + advansys_detect, /* int (*detect)(struct SHT *) */ \ + advansys_release, /* int (*release)(struct Scsi_Host *) */ \ + advansys_info, /* const char *(*info)(struct Scsi_Host *) */ \ + advansys_command, /* int (*command)(Scsi_Cmnd *) */ \ + advansys_queuecommand, \ + /* int (*queuecommand)(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)) */ \ + advansys_abort, /* int (*abort)(Scsi_Cmnd *) */ \ + advansys_reset, /* int (*reset)(Scsi_Cmnd *) */ \ + NULL, /* int (*slave_attach)(int, int) */ \ + advansys_biosparam, /* int (* bios_param)(Disk *, int, int []) */ \ + /* \ + * The following fields are set per adapter in advansys_detect(). \ + */ \ + 0, /* int can_queue */ \ + 0, /* int this_id */ \ + 0, /* short unsigned int sg_tablesize */ \ + 0, /* short cmd_per_lun */ \ + 0, /* unsigned char present */ \ + /* \ + * Because the driver may control an ISA adapter 'unchecked_isa_dma' \ + * must be set. The flag will be cleared in advansys_detect for non-ISA \ + * adapters. Refer to the comment in scsi_module.c for more information. \ + */ \ + 1, /* unsigned unchecked_isa_dma:1 */ \ + /* \ + * All adapters controlled by this driver are capable of large \ + * scatter-gather lists. This apparently obviates any performance + * gain provided by setting 'use_clustering'. \ + */ \ + DISABLE_CLUSTERING, /* unsigned use_clustering:1 */ \ +} +#else /* LINUX_1_3 */ +#define ADVANSYS { \ + NULL, /* struct SHT *next */ \ + NULL, /* long *usage_count */ \ + &proc_scsi_advansys, /* struct proc_dir_entry *proc_dir */ \ + advansys_proc_info, \ + /* int (*proc_info)(char *, char **, off_t, int, int, int) */ \ + "advansys", /* const char *name */ \ + advansys_detect, /* int (*detect)(struct SHT *) */ \ + advansys_release, /* int (*release)(struct Scsi_Host *) */ \ + advansys_info, /* const char *(*info)(struct Scsi_Host *) */ \ + advansys_command, /* int (*command)(Scsi_Cmnd *) */ \ + advansys_queuecommand, \ + /* int (*queuecommand)(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)) */ \ + advansys_abort, /* int (*abort)(Scsi_Cmnd *) */ \ + advansys_reset, /* int (*reset)(Scsi_Cmnd *) */ \ + NULL, /* int (*slave_attach)(int, int) */ \ + advansys_biosparam, /* int (* bios_param)(Disk *, kdev_t, int []) */ \ + /* \ + * The following fields are set per adapter in advansys_detect(). \ + */ \ + 0, /* int can_queue */ \ + 0, /* int this_id */ \ + 0, /* short unsigned int sg_tablesize */ \ + 0, /* short cmd_per_lun */ \ + 0, /* unsigned char present */ \ + /* \ + * Because the driver may control an ISA adapter 'unchecked_isa_dma' \ + * must be set. The flag will be cleared in advansys_detect for non-ISA \ + * adapters. Refer to the comment in scsi_module.c for more information. \ + */ \ + 1, /* unsigned unchecked_isa_dma:1 */ \ + /* \ + * All adapters controlled by this driver are capable of large \ + * scatter-gather lists. This apparently obviates any performance + * gain provided by setting 'use_clustering'. \ + */ \ + DISABLE_CLUSTERING, /* unsigned use_clustering:1 */ \ +} +#endif /* LINUX_1_3 */ +#endif /* _ADVANSYS_H */ diff -u --recursive --new-file v1.3.57/linux/drivers/scsi/aha1542.c linux/drivers/scsi/aha1542.c --- v1.3.57/linux/drivers/scsi/aha1542.c Mon Oct 23 18:02:07 1995 +++ linux/drivers/scsi/aha1542.c Sun Jan 14 16:46:08 1996 @@ -15,10 +15,7 @@ * Accept parameters from LILO cmd-line. -- 1-Oct-94 */ -#ifdef MODULE -#include #include -#endif #include #include diff -u --recursive --new-file v1.3.57/linux/drivers/scsi/aic7xxx.seq linux/drivers/scsi/aic7xxx.seq --- v1.3.57/linux/drivers/scsi/aic7xxx.seq Mon Nov 13 12:36:45 1995 +++ linux/drivers/scsi/aic7xxx.seq Sun Jan 14 16:22:17 1996 @@ -136,9 +136,9 @@ SEND_REJECT = 0x11 # sending a message reject NO_IDENT = 0x21 # no IDENTIFY after reconnect NO_MATCH = 0x31 # no cmd match for reconnect -MSG_SDTR = 0x41 # SDTR message recieved -MSG_WDTR = 0x51 # WDTR message recieved -MSG_REJECT = 0x61 # Reject message recieved +MSG_SDTR = 0x41 # SDTR message received +MSG_WDTR = 0x51 # WDTR message received +MSG_REJECT = 0x61 # Reject message received BAD_STATUS = 0x71 # Bad status from target RESIDUAL = 0x81 # Residual byte count != 0 ABORT_TAG = 0x91 # Sent an ABORT_TAG message diff -u --recursive --new-file v1.3.57/linux/drivers/scsi/hosts.c linux/drivers/scsi/hosts.c --- v1.3.57/linux/drivers/scsi/hosts.c Thu Jan 4 21:54:55 1996 +++ linux/drivers/scsi/hosts.c Wed Jan 17 07:27:36 1996 @@ -41,6 +41,10 @@ #include "hosts.h" +#ifdef CONFIG_SCSI_ADVANSYS +#include "advansys.h" +#endif + #ifdef CONFIG_SCSI_AHA152X #include "aha152x.h" #endif @@ -158,6 +162,9 @@ static Scsi_Host_Template builtin_scsi_hosts[] = { +#ifdef CONFIG_SCSI_ADVANSYS + ADVANSYS, +#endif /* BusLogic must come before aha1542.c */ #ifdef CONFIG_SCSI_BUSLOGIC BUSLOGIC, diff -u --recursive --new-file v1.3.57/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c --- v1.3.57/linux/drivers/scsi/scsi.c Thu Jan 4 21:54:56 1996 +++ linux/drivers/scsi/scsi.c Mon Jan 15 08:18:22 1996 @@ -82,6 +82,8 @@ struct Scsi_Host *shpnt, char * scsi_result); void scsi_build_commandblocks(Scsi_Device * SDpnt); +extern struct symbol_table scsi_symbol_table; + static FreeSectorBitmap * dma_malloc_freelist = NULL; static int scsi_need_isa_bounce_buffers; @@ -395,8 +397,8 @@ /* Make sure we have something that is valid for DMA purposes */ - scsi_result = ((!dma_malloc_freelist || !shpnt->unchecked_isa_dma) - ? &scsi_result0[0] : scsi_malloc (512)); + scsi_result = ( ( !shpnt->unchecked_isa_dma ) + ? &scsi_result0[0] : scsi_init_malloc (512, GFP_DMA)); if (scsi_result == NULL) { printk ("Unable to obtain scsi_result buffer\n"); @@ -489,7 +491,7 @@ /* If we allocated a buffer so we could do DMA, free it now */ if (scsi_result != &scsi_result0[0] && scsi_result != NULL) - scsi_free (scsi_result, 512); + scsi_init_free (scsi_result, 512); } @@ -2329,6 +2331,7 @@ timer_table[SCSI_TIMER].fn = scsi_main_timeout; timer_table[SCSI_TIMER].expires = 0; + register_symtab(&scsi_symbol_table); /* Register the /proc/scsi/scsi entry */ #if CONFIG_PROC_FS @@ -3116,8 +3119,6 @@ #endif #ifdef MODULE - -extern struct symbol_table scsi_symbol_table; int init_module(void) { unsigned long size; diff -u --recursive --new-file v1.3.57/linux/drivers/scsi/scsi_debug.c linux/drivers/scsi/scsi_debug.c --- v1.3.57/linux/drivers/scsi/scsi_debug.c Mon Oct 23 18:02:11 1995 +++ linux/drivers/scsi/scsi_debug.c Sun Jan 14 16:48:28 1996 @@ -7,10 +7,7 @@ * anything out of the ordinary is seen. */ -#ifdef MODULE -#include #include -#endif #include #include diff -u --recursive --new-file v1.3.57/linux/drivers/sound/.blurb linux/drivers/sound/.blurb --- v1.3.57/linux/drivers/sound/.blurb Wed Nov 8 07:11:35 1995 +++ linux/drivers/sound/.blurb Tue Jan 9 00:37:02 1996 @@ -1,8 +1,4 @@ ********************************************************* -* IF YOU HAVE ANY PROBLEMS WITH THE SOUND DRIVER, * -* PLEASE READ THE SOUND-HOWTO. IT'S AVAILABLE FROM YOUR * -* NEAREST LINUX FTP SITE AND CONTAINS ANSWER TO YOUR * -* PROBLEM. * * Readme.cards (this directory) contains some card * * specific instructions. * ********************************************************* diff -u --recursive --new-file v1.3.57/linux/drivers/sound/.objects linux/drivers/sound/.objects --- v1.3.57/linux/drivers/sound/.objects Wed Nov 8 07:11:35 1995 +++ linux/drivers/sound/.objects Tue Jan 9 00:37:02 1996 @@ -64,14 +64,10 @@ OBJS := $(OBJS) pss.o endif -ifdef CONFIG_SB16 - OBJS := $(OBJS) sb16_dsp.o -endif - ifdef CONFIG_SB OBJS := $(OBJS) sb16_midi.o sb_card.o sb_dsp.o sb_midi.o sb_mixer.o OBJS := $(OBJS) sb_card.o - OBJS := $(OBJS) sb_dsp.o + OBJS := $(OBJS) sb_dsp.o sb16_dsp.o OBJS := $(OBJS) sb_midi.o OBJS := $(OBJS) sb_mixer.o endif @@ -92,12 +88,12 @@ OBJS := $(OBJS) sscape.o endif -ifdef CONFIG_SEQUENCER - OBJS := $(OBJS) sys_timer.o -endif - ifdef CONFIG_TRIX OBJS := $(OBJS) trix.o +endif + +ifdef CONFIG_SEQUENCER + OBJS := $(OBJS) sys_timer.o endif ifdef CONFIG_UART6850 diff -u --recursive --new-file v1.3.57/linux/drivers/sound/.version linux/drivers/sound/.version --- v1.3.57/linux/drivers/sound/.version Wed Nov 8 07:11:35 1995 +++ linux/drivers/sound/.version Tue Jan 9 00:37:03 1996 @@ -1,2 +1,2 @@ -3.5-alpha5 +3.5-alpha8 0x030505 diff -u --recursive --new-file v1.3.57/linux/drivers/sound/CHANGELOG linux/drivers/sound/CHANGELOG --- v1.3.57/linux/drivers/sound/CHANGELOG Mon Oct 23 18:02:13 1995 +++ linux/drivers/sound/CHANGELOG Tue Jan 9 00:37:02 1996 @@ -1,5 +1,37 @@ -Changelog for version 3.5-alpha3 +Changelog for version 3.5-alpha8 -------------------------------- + +Since 3.5-alpha7 +- Linux kernel compatible configuration (_EXPERIMENTAL_). Enable + using command "cd /linux/drivers/sound;make script" and then + just run kernel's make config normally. +- Minor fixes to the SB support. Hopefully the driver works with + all SB models now. +- Added support for ESS ES1688 "AudioDrive" based cards. + +Since 3.5-alpha6 +- SB Pro and SB16 supports are no longer separately selectable options. + Enabling SB enables them too. +- Changed all #ifndef EXCLUDE_xx stuff to #ifdef CONFIG_xx. Modified +configure to handle this. +- Removed initialization messages from the +modularized version. They can be enabled by using init_trace=1 in +the insmod command line (insmod sound init_trace=1). +- More AIX stuff. +- Added support for syncronizing dsp/audio devices with /dev/sequencer. +- mmap() support for dsp/audio devices. + +Since 3.5-alpha5 +- AIX port. +- Changed some xxx_PATCH macros in soundcard.h to work with + big endian machines. + +Since 3.5-alpha4 +- Removed the 'setfx' stuff from the version distributed with kernel + sources. Running 'setfx' is required again. + +Since 3.5-alpha3 +- Moved stuff from the 'setfx' program to the AudioTriX Pro driver. Since 3.5-alpha2 - Modifications to makefile and configure.c. Unnecessary sources diff -u --recursive --new-file v1.3.57/linux/drivers/sound/Config.in linux/drivers/sound/Config.in --- v1.3.57/linux/drivers/sound/Config.in Sun Oct 29 11:38:49 1995 +++ linux/drivers/sound/Config.in Tue Jan 9 00:37:02 1996 @@ -1,8 +1,12 @@ # # Sound driver configuration # -# This is really ugly: it should probably be changed -# to use the normal config script setup +#-------- +# There is another confic script which is compatible with rest of +# the kernel. It can be activated by running 'make script' in this +# directory. Please note that this is an _experimental_ feature which +# doesn't work with all cards (PSS, SM Wave, AudioTriX Pro). +#-------- # $MAKE -C drivers/sound config || exit 1 diff -u --recursive --new-file v1.3.57/linux/drivers/sound/Makefile linux/drivers/sound/Makefile --- v1.3.57/linux/drivers/sound/Makefile Sat Jan 6 19:10:40 1996 +++ linux/drivers/sound/Makefile Tue Jan 9 00:36:59 1996 @@ -25,14 +25,6 @@ mad16.o mad16_sb_midi.o cs4232.o maui.o sound_pnp.o endif -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 @@ -44,18 +36,27 @@ .c.o: $(CC) $(CFLAGS) -c $< -endif ifeq ($(CONFIG_SOUND),y) -OBJS += $(FIXEDOBJS) all: local.h sound.a +OBJS += $(FIXEDOBJS) + else all: endif +ifndef HOSTCC +# +# Running outside the kernel build. +# +CC = gcc +HOSTCC = gcc +CFLAGS = -D__KERNEL__ -DMODULE -DMODVERSIONS -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -m486 +else include $(TOPDIR)/Rules.make +endif sound.a: $(OBJS) -rm -f sound.a @@ -64,7 +65,7 @@ clean: rm -f core core.* *.o *.a tmp_make *~ x y z *% - rm -f configure sound_stub.c + rm -f configure sound_stub.c objects/*.o indent: for n in *.c;do echo indent $$n;indent $$n;done @@ -100,6 +101,24 @@ # @echo \#define SOUND_CONFIG_DOMAIN \"`hostname -d`\" >> local.h 2>/dev/null @echo \#define SOUND_UNAME_A \"`uname -a`\" >> local.h +kernelconfig: setup-$(TARGET_OS) + rm -f configure + $(HOSTCC) -o configure configure.c + ./configure fixedlocal > local.h + ./configure fixeddefines > .defines + @echo \#define SOUND_CONFIG_DATE \"`date`\" >> local.h + @echo \#define SOUND_CONFIG_BY \"`whoami`\" >> 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 + +script: setup-$(TARGET_OS) + rm -f configure + $(HOSTCC) -o configure configure.c + ./configure script > Config.in + ./configure fixedlocal > local.h + ./configure fixeddefines > .defines + clrconf: rm -f local.h .depend synth-ld.h trix_boot.h smw-midi0001.h .defines @@ -118,4 +137,12 @@ $(LD) -r -o sound.o $(FIXEDOBJS) sound.a modules: local.h sound.o - ln -fs `pwd`/sound.o $(TOPDIR)/modules/sound.o + ln -fs `pwd`/sound.o /usr/src/linux/modules/sound.o + + +# +# include a dependency file if one exists +# +ifeq (.depend,$(wildcard .depend)) +include .depend +endif diff -u --recursive --new-file v1.3.57/linux/drivers/sound/Readme linux/drivers/sound/Readme --- v1.3.57/linux/drivers/sound/Readme Wed Nov 8 07:11:35 1995 +++ linux/drivers/sound/Readme Tue Jan 9 00:37:00 1996 @@ -1,9 +1,9 @@ -VoxWare v3.5-alpha5 release notes +VoxWare v3.5-alpha4 release notes --------------------------------- 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 + 1.3.58 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 @@ -33,11 +33,11 @@ after v3.0 (I will not add aditional features before v3.0 is ready). ==================================================== -- THIS VERSION ____REQUIRES____ Linux 1.3.33 OR LATER. +- THIS VERSION ____REQUIRES____ Linux 1.3.58 OR LATER. ==================================================== - THIS VERSION MAY NOT WORK WITH Linux VERSIONS RELEASED - AFTER end of Nov 1995. If this version doesn't compile with + AFTER end of Feb 1996. If this version doesn't compile with your kernel version, please use the sound driver version included in your kernel. @@ -65,7 +65,7 @@ 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) +SoundMan Wave Mozart (OAK OTI-601 interface chip) based soundcards. MAD16 (an interface chip by OPTi) based soundcards (TB Tropez ???). (NOTE! The MAD16 looks similar to the Mozart chip. It could be a good diff -u --recursive --new-file v1.3.57/linux/drivers/sound/Readme.cards linux/drivers/sound/Readme.cards --- v1.3.57/linux/drivers/sound/Readme.cards Wed Nov 8 07:11:35 1995 +++ linux/drivers/sound/Readme.cards Tue Jan 9 00:37:01 1996 @@ -40,7 +40,7 @@ cards in the market (July95). It's likely that your card is compatible just with SB Pro but there is also a non SB compatible 16 bit mode. Usually it's MSS/WSS but could also - be a proprietary one like MV Jazz16. + be a proprietary one like MV Jazz16 or ESS ES688. Gravis Ultrasound (GUS) GUS @@ -117,6 +117,8 @@ Several companies (including Ensoniq, Reveal and Spea) are selling cards based on this architecture. + NOTE! The new PnP SoundScape is not supported yet. + MAD16 and Mozart based cards The Mozart (OAK OTI-601) and MAD16 Pro (OPTi 82C929) interface chips are used in many different soundcards, including some @@ -337,12 +339,11 @@ have one of them. In addition the MAD16 chip is used in some cards made by known manufacturers such as Turtle Beach (Tropez), Reveal (some models) and Diamond (latest ones). - "SoundBlaster Pro support", - - Enable this option if your card is SB Pro or SB16. Enable it - also with any SB Pro clones. Answering 'n' saves some amount of - memory but 'y' is the safe alterative. - "SoundBlaster 16 support", - - Enable if you have a SB16 (including the AWE32). + "Support for TB Maui" + - This is just an experimental extension to the MPU401 driver. + Don't enable this option unless you are writing a .MOD + player for Maui. + "Audio Excel DSP 16 initialization support", - Don't know much about this card. Look at aedsp16.c for more info. @@ -468,6 +469,10 @@ the 16 bit daughtercard if you have them. Note that enabling the daughter card disables GUS MAX driver. +NOTE for owners of the 16 bit daughtercard: By default the daughtercard +uses /dev/dsp (and /dev/audio). Command "ln -sf /dev/dsp1 /dev/dsp" +selects the daughter card as the default device. + 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 with DOS. @@ -559,23 +564,17 @@ For this reason the driver asks for the name of a file containing the microcode (TRXPRO.HEX). This file is usually located in the directory where the DOS drivers were installed. You must have access to this file -when configuring the driver. - -IMPORTANT!!!!!!!!!!! - -The OPL4/OPL3 chip and the (optional) effects daughtercard require -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 snd-util-3.0.tar.gz package. -It's calls ioperm() so it must be run as root. +when configuring the driver. -Another way to initialize the effects processor (and OPL4) is to boot DOS -before running Linux. +If you have the effects daughtercard, it must be initialized by running +the setfx program of snd-util-3.0.tar.gz package. This step is not required +when using the (future) binary distribution version of the driver. Ensoniq SoundScape ------------------ +NOTE! The new PnP SoundScape is not supported yet. + The SoundScape driver handles initialization of MSS and MPU supports itself so you don't need to enable other drivers than SoundScape (enable also the /dev/dsp, /dev/sequencer and MIDI supports). @@ -695,11 +694,14 @@ may also be called as TSUNAMI.BIN or something else (older cards?). The OPL4 synth will be inaccessible without loading the microcontroller code. -Also remember to enable MPU401 support if you want to use the OPL4 mode. + +Also remember to enable SB MPU401 support if you want to use the OPL4 mode. +(Don't enable the 'normal' MPU401 device as with some earlier driver +versions (pre 3.5-alpha8)). NOTE! Don't answer 'y' when the driver asks about SM Games support (the next question after the MIDI0001.BIN name). However - aneswering 'y' is not dangerous. + aneswering 'y' doesn't cause damage your computer so don't panic. Sound Galaxies -------------- @@ -722,6 +724,11 @@ There are some new Sound Galaxies in the market. I have no experience with them so read the card's manual carefully. +ESS ES1688 'AudioDrive' based cards +----------------------------------- + +Configure these cards just like SB Pro. Enable the 'SB MPU401 MIDI port' +if you want to use MIDI features of the card. Reveal cards ------------ @@ -779,12 +786,6 @@ the card is compatible with MSS, it's a better choise. Some cards don't work in the SB and MSS modes at the same time. -There are some cards which will be supported by VoxWare sooner or later -(currently at least cards based on the ESS chipset). Such cards are -so common that there is some idea in writing the driver. Check the -VoxWare home page (http://personal.eunet.fi/pp/voxware) for latest -information. - Then there are cards which are no longer manufactured and/or which are relatively rarely used (such as the 8 bit ProAudioSpectrum models). It's extremely unlikely that such cards never get supported. @@ -837,8 +838,8 @@ there is any plans to write a driver for the cards mentioned above. I will put any news to the VoxWare www home page (see below). -There are some common audio chipsets that are supported yet. For example -the ESS chips and Sierra Aria. It's likely that these architectures +There are some common audio chipsets that are not supported yet. For example +Sierra Aria and IBM Mwave. It's possible that these architectures get some support in future but I can't make any promises. Just look at the home page for latest info. diff -u --recursive --new-file v1.3.57/linux/drivers/sound/Readme.modules linux/drivers/sound/Readme.modules --- v1.3.57/linux/drivers/sound/Readme.modules Fri Oct 13 14:44:33 1995 +++ linux/drivers/sound/Readme.modules Tue Jan 9 00:37:02 1996 @@ -86,3 +86,14 @@ 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. + +Debugging and tracing +--------------------- + +Modularized sound driver doesn't display messages during initialization as +the kernel compiled one does. This feature can be turned on by adding +init_trace=1 to the insmod command line. + +For example: + + insmod sound init_trace=1 diff -u --recursive --new-file v1.3.57/linux/drivers/sound/ad1848.c linux/drivers/sound/ad1848.c --- v1.3.57/linux/drivers/sound/ad1848.c Wed Nov 8 07:11:35 1995 +++ linux/drivers/sound/ad1848.c Tue Jan 9 00:37:06 1996 @@ -44,7 +44,7 @@ #define DEB1(x) #include "sound_config.h" -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_AD1848) +#if defined(CONFIG_AD1848) #include "ad1848_mixer.h" @@ -72,6 +72,7 @@ #define MD_4231 2 #define MD_4231A 3 #define MD_1845 4 +#define MD_4232 5 /* Mixer parameters */ int recmask; @@ -153,7 +154,8 @@ 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--; save_flags (flags); @@ -436,11 +438,19 @@ { int i; - devc->recmask = 0; - if (devc->mode != MD_1848) - devc->supported_devices = MODE2_MIXER_DEVICES; - else - devc->supported_devices = MODE1_MIXER_DEVICES; + switch (devc->mode) + { + case MD_4231: + devc->supported_devices = MODE2_MIXER_DEVICES; + break; + + case MD_4232: + devc->supported_devices = MODE3_MIXER_DEVICES; + break; + + default: + devc->supported_devices = MODE1_MIXER_DEVICES; + } devc->supported_rec_devices = MODE1_REC_DEVICES; @@ -466,7 +476,8 @@ if (((cmd >> 8) & 0xff) == 'M') { - if (cmd & IOC_IN) + + if (_IOC_DIR (cmd) & _IOC_WRITE) switch (cmd & 0xff) { case SOUND_MIXER_RECSRC: @@ -570,6 +581,7 @@ devc->intr_active = 0; devc->opened = 1; devc->irq_mode = 0; + ad1848_trigger (dev, 0); restore_flags (flags); /* * Mute output until the playback really starts. This decreases clicking. @@ -991,7 +1003,7 @@ restore_flags (flags); devc->xfer_count = 0; -#ifndef EXCLUDE_SEQUENCER +#ifdef CONFIG_SEQUENCER if (dev == timer_installed && devc->timer_running) if ((fs & 0x01) != (old_fs & 0x01)) { @@ -1012,11 +1024,14 @@ { ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; unsigned long flags; + int timeout; save_flags (flags); cli (); ad_mute (devc); + ad_enter_MCE (devc); + ad_write (devc, 9, ad_read (devc, 9) & ~0x03); /* Stop DMA */ ad_write (devc, 9, ad_read (devc, 9) & ~0x03); /* Stop DMA */ ad_write (devc, 15, 0); /* Clear DMA counter */ @@ -1028,11 +1043,14 @@ ad_write (devc, 31, 0); /* Clear DMA counter */ } - ad_write (devc, 9, ad_read (devc, 9) & ~0x03); /* Stop DMA */ + for (timeout = 0; timeout < 1000 && !(inb (io_Status (devc)) & 0x80); + timeout++); /* Wait for interrupt */ + 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 */ devc->irq_mode = 0; + ad_leave_MCE (devc); /* DMAbuf_reset_dma (dev); */ restore_flags (flags); @@ -1116,6 +1134,8 @@ ad1848_info *devc = &dev_info[nr_ad1848_devs]; unsigned char tmp1 = 0xff, tmp2 = 0xff; + DDB (printk ("ad1848_detect(%x)\n", io_base)); + if (ad_flags) *ad_flags = 0; @@ -1149,6 +1169,8 @@ * * If the I/O address is unused, it typically returns 0xff. */ + + DDB (printk ("ad1848_detect() - step A\n")); if ((inb (devc->base) & 0x80) != 0x00) /* Not a AD1848 */ { DDB (printk ("ad1848 detect error - step A (%02x)\n", @@ -1162,6 +1184,7 @@ * so try to avoid using it. */ + DDB (printk ("ad1848_detect() - step B\n")); ad_write (devc, 0, 0xaa); ad_write (devc, 1, 0x45); /* 0x55 with bit 0x10 clear */ @@ -1171,6 +1194,7 @@ return 0; } + DDB (printk ("ad1848_detect() - step C\n")); ad_write (devc, 0, 0x45); ad_write (devc, 1, 0xaa); @@ -1185,6 +1209,7 @@ * try to change them. */ + DDB (printk ("ad1848_detect() - step D\n")); tmp = ad_read (devc, 12); ad_write (devc, 12, (~tmp) & 0x0f); @@ -1206,6 +1231,7 @@ * with CS4231. */ + DDB (printk ("ad1848_detect() - step F\n")); ad_write (devc, 12, 0); /* Mode2=disabled */ for (i = 0; i < 16; i++) @@ -1220,6 +1246,7 @@ * The bit 0x80 is always 1 in CS4248 and CS4231. */ + DDB (printk ("ad1848_detect() - step G\n")); ad_write (devc, 12, 0x40); /* Set mode2, clear 0x80 */ tmp1 = ad_read (devc, 12); @@ -1238,6 +1265,7 @@ * * Verify that setting I0 doesn't change I16. */ + DDB (printk ("ad1848_detect() - step H\n")); ad_write (devc, 16, 0); /* Set I16 to known value */ ad_write (devc, 0, 0x45); @@ -1255,6 +1283,7 @@ * Verify that some bits of I25 are read only. */ + DDB (printk ("ad1848_detect() - step I\n")); tmp1 = ad_read (devc, 25); /* Original bits */ ad_write (devc, 25, ~tmp1); /* Invert all bits */ if ((ad_read (devc, 25) & 0xe7) == (tmp1 & 0xe7)) @@ -1266,10 +1295,7 @@ */ devc->chip_name = "CS4231"; -#ifdef MOZART_PORT - if (devc->base != MOZART_PORT + 4) -#endif - devc->mode = MD_4231; + devc->mode = MD_4231; /* * It could be an AD1845 or CS4231A as well. @@ -1277,6 +1303,7 @@ * while the CS4231A reports different. */ + DDB (printk ("ad1848_detect() - step I\n")); id = ad_read (devc, 25) & 0xe7; switch (id) @@ -1289,12 +1316,12 @@ case 0xa2: devc->chip_name = "CS4232"; - devc->mode = MD_4231A; + devc->mode = MD_4232; break; case 0xb2: devc->chip_name = "CS4232A"; - devc->mode = MD_4231A; + devc->mode = MD_4232; break; case 0x80: @@ -1326,15 +1353,18 @@ } ad_write (devc, 25, tmp1); /* Restore bits */ + DDB (printk ("ad1848_detect() - step K\n")); } } + DDB (printk ("ad1848_detect() - step L\n")); if (ad_flags) { if (devc->mode != MD_1848) *ad_flags |= AD_F_CS4231; } + DDB (printk ("ad1848_detect() - Detected OK\n")); return 1; } @@ -1360,6 +1390,7 @@ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; int i, my_dev; + ad1848_info *devc = &dev_info[nr_ad1848_devs]; if (!ad1848_detect (io_base, NULL, osp)) @@ -1402,14 +1433,17 @@ for (i = 16; i < 32; i++) ad_write (devc, i, init_values[i]); - if (devc->mode == MD_4231A) + if (devc->mode == MD_4231A || devc->mode == MD_4232) 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 */ + { + ad1848_pcm_operations[nr_ad1848_devs].flags &= ~DMA_DUPLEX; + ad_write (devc, 9, ad_read (devc, 9) | 0x04); /* Single DMA mode */ + } outb (0, io_Status (devc)); /* Clear pending interrupts */ @@ -1420,7 +1454,8 @@ sprintf (ad1848_pcm_operations[nr_ad1848_devs].name, "Generic audio codec (%s)", devc->chip_name); - printk (" <%s>", ad1848_pcm_operations[nr_ad1848_devs].name); + conf_printf2 (ad1848_pcm_operations[nr_ad1848_devs].name, + devc->base, devc->irq, dma_playback, dma_capture); if (num_audiodevs < MAX_AUDIO_DEV) { @@ -1473,7 +1508,7 @@ audio_devs[my_dev]->format_mask = ad_format_mask[devc->mode]; nr_ad1848_devs++; -#ifndef EXCLUDE_SEQUENCER +#ifdef CONFIG_SEQUENCER if (devc->mode != MD_1848 && devc->irq_ok) ad1848_tmr_install (my_dev); #endif @@ -1546,6 +1581,7 @@ unsigned char status; ad1848_info *devc; int dev; + int alt_stat = 0xff; if (irq < 0 || irq > 15) { @@ -1579,54 +1615,78 @@ if (status & 0x01) { - int alt_stat; if (devc->mode != MD_1848) - { - 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; + alt_stat = ad_read (devc, 24); 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) + if (devc->opened && devc->irq_mode & PCM_ENABLE_OUTPUT && + alt_stat & 0x10) { DMAbuf_outputintr (dev, 1); } - } - outb (0, io_Status (devc)); /* Clear interrupt status */ + if (devc->mode != MD_1848 && alt_stat & 0x40) /* Timer interrupt */ + { + devc->timer_ticks++; +#ifdef CONFIG_SEQUENCER + if (timer_installed == dev && devc->timer_running) + sound_timer_interrupt (); +#endif + } + } + if (devc->mode != MD_1848) + ad_write (devc, 24, ad_read (devc, 24) & ~alt_stat); /* Selective ack */ + else + outb (0, io_Status (devc)); /* Clear interrupt status */ } /* * Some extra code for the MS Sound System */ +void +check_opl3 (int base, struct address_info *hw_config) +{ + + if (check_region (base, 4)) + { + printk ("\n\nopl3.c: I/O port %x already in use\n\n", base); + return; + } + + if (!opl3_detect (base, hw_config->osp)) + return; + + opl3_init (0, base, hw_config->osp); + request_region (base, 4, "OPL3/OPL2"); +} + int probe_ms_sound (struct address_info *hw_config) { unsigned char tmp; + DDB (printk ("Entered probe_ms_sound(%x, %d)\n", hw_config->io_base, hw_config->card_subtype)); + if (check_region (hw_config->io_base, 8)) { printk ("MSS: I/O port conflict\n"); return 0; } -#if !defined(EXCLUDE_AEDSP16) && defined(AEDSP16_MSS) + if (hw_config->card_subtype == 1) /* Has no IRQ/DMA registers */ + { + /* check_opl3(0x388, hw_config); */ + return ad1848_detect (hw_config->io_base + 4, NULL, hw_config->osp); + } + +#if defined(CONFIG_AEDSP16) && defined(AEDSP16_MSS) /* * Initialize Audio Excel DSP 16 to MSS: before any operation * we must enable MSS I/O ports. @@ -1635,9 +1695,6 @@ InitAEDSP16_MSS (hw_config); #endif - if (hw_config->card_subtype == 1) /* Has IRQ/DMA registers */ - return ad1848_detect (hw_config->io_base + 4, NULL, hw_config->osp); - /* * Check if the IO port returns valid signature. The original MS Sound * system returns 0x04 while some cards (AudioTriX Pro for example) @@ -1645,7 +1702,10 @@ */ if ((tmp = inb (hw_config->io_base + 3)) == 0xff) /* Bus float */ - return 0; + { + DDB (printk ("I/O address is inactive (%x)\n", tmp)); + return 0; + } if ((tmp & 0x3f) != 0x04 && (tmp & 0x3f) != 0x0f && (tmp & 0x3f) != 0x00) @@ -1700,11 +1760,22 @@ 1, 2, 0, 3 }; - int config_port = hw_config->io_base + 0, version_port = hw_config->io_base + 3; + int config_port = hw_config->io_base + 0; + int version_port = hw_config->io_base + 3; if (!ad1848_detect (hw_config->io_base + 4, NULL, hw_config->osp)) return mem_start; + if (hw_config->card_subtype == 1) /* Has no IRQ/DMA registers */ + { + ad1848_init ("MS Sound System", hw_config->io_base + 4, + hw_config->irq, + hw_config->dma, + hw_config->dma2, 0, hw_config->osp); + request_region (hw_config->io_base, 4, "WSS config"); + return mem_start; + } + /* * Set the IRQ and DMA addresses. */ @@ -1768,7 +1839,7 @@ release_region (hw_config->io_base, 4); } -#ifndef EXCLUDE_SEQUENCER +#ifdef CONFIG_SEQUENCER /* * Timer stuff (for /dev/music). */ diff -u --recursive --new-file v1.3.57/linux/drivers/sound/ad1848_mixer.h linux/drivers/sound/ad1848_mixer.h --- v1.3.57/linux/drivers/sound/ad1848_mixer.h Wed Nov 8 07:11:35 1995 +++ linux/drivers/sound/ad1848_mixer.h Tue Jan 9 00:36:53 1996 @@ -35,20 +35,6 @@ * (Actually this is not a mapping but rather some kind of interleaving * solution). */ -#ifdef GUSMAX_MIXER -#define MODE1_REC_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | \ - SOUND_MASK_CD|SOUND_MASK_IMIX) - -#define MODE1_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_MIC | \ - SOUND_MASK_CD | \ - SOUND_MASK_IGAIN | \ - SOUND_MASK_PCM|SOUND_MASK_IMIX) - -#define MODE2_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_LINE | SOUND_MASK_MIC | \ - SOUND_MASK_CD | SOUND_MASK_SPEAKER | \ - SOUND_MASK_IGAIN | \ - SOUND_MASK_PCM | SOUND_MASK_IMIX) -#else /* Generic mapping */ #define MODE1_REC_DEVICES (SOUND_MASK_LINE3 | SOUND_MASK_MIC | \ SOUND_MASK_LINE1|SOUND_MASK_IMIX) @@ -61,7 +47,8 @@ SOUND_MASK_LINE3 | SOUND_MASK_SPEAKER | \ SOUND_MASK_IGAIN | \ SOUND_MASK_PCM | SOUND_MASK_IMIX) -#endif + +#define MODE3_MIXER_DEVICES (MODE2_MIXER_DEVICES | SOUND_MASK_VOLUME) struct mixer_def { unsigned int regno: 7; @@ -93,8 +80,8 @@ #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_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), +mixer_ent mix_devices[32][2] = { +MIX_ENT(SOUND_MIXER_VOLUME, 27, 1, 0, 4, 29, 1, 0, 4), MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0), MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0), MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 0, 5, 5, 1, 0, 5), @@ -115,11 +102,11 @@ static unsigned short default_mixer_levels[SOUND_MIXER_NRDEVICES] = { - 0x5a5a, /* Master Volume */ + 0x3232, /* Master Volume */ 0x3232, /* Bass */ 0x3232, /* Treble */ 0x4b4b, /* FM */ - 0x4040, /* PCM */ + 0x3232, /* PCM */ 0x4b4b, /* PC Speaker */ 0x2020, /* Ext Line */ 0x1010, /* Mic */ diff -u --recursive --new-file v1.3.57/linux/drivers/sound/adlib_card.c linux/drivers/sound/adlib_card.c --- v1.3.57/linux/drivers/sound/adlib_card.c Wed Nov 8 07:11:35 1995 +++ linux/drivers/sound/adlib_card.c Tue Jan 9 00:37:06 1996 @@ -29,7 +29,7 @@ #include "sound_config.h" -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_YM3812) +#if defined(CONFIG_YM3812) long attach_adlib_card (long mem_start, struct address_info *hw_config) diff -u --recursive --new-file v1.3.57/linux/drivers/sound/aedsp16.c linux/drivers/sound/aedsp16.c --- v1.3.57/linux/drivers/sound/aedsp16.c Fri Oct 13 14:44:33 1995 +++ linux/drivers/sound/aedsp16.c Tue Jan 9 00:37:07 1996 @@ -32,10 +32,10 @@ #include "sound_config.h" #ifndef AEDSP16_BASE -#define EXCLUDE_AEDSP16 +#undef CONFIG_AEDSP16 #endif -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_AEDSP16) +#if defined(CONFIG_AEDSP16) /* READ THIS @@ -865,4 +865,4 @@ #endif /* 0 */ -#endif /* !EXCLUDE_AEDSP16 */ +#endif /* CONFIG_AEDSP16 */ diff -u --recursive --new-file v1.3.57/linux/drivers/sound/audio.c linux/drivers/sound/audio.c --- v1.3.57/linux/drivers/sound/audio.c Thu Nov 9 11:23:51 1995 +++ linux/drivers/sound/audio.c Tue Jan 9 00:37:08 1996 @@ -29,8 +29,7 @@ #include "sound_config.h" -#ifdef CONFIGURE_SOUNDCARD -#ifndef EXCLUDE_AUDIO +#ifdef CONFIG_AUDIO #include "ulaw.h" #include "coproc.h" @@ -38,14 +37,6 @@ #define ON 1 #define OFF 0 -static int wr_buff_no[MAX_AUDIO_DEV]; /* - - * != -1, if there is - * a incomplete output - * block in the queue. - */ -static int wr_buff_size[MAX_AUDIO_DEV], wr_buff_ptr[MAX_AUDIO_DEV]; - static int audio_mode[MAX_AUDIO_DEV]; static int dev_nblock[MAX_AUDIO_DEV]; /* 1 if in noblocking mode */ @@ -53,12 +44,11 @@ #define AM_WRITE 1 #define AM_READ 2 -static char *wr_dma_buf[MAX_AUDIO_DEV]; static int audio_format[MAX_AUDIO_DEV]; static int local_conversion[MAX_AUDIO_DEV]; static int -set_format (int dev, long fmt) +set_format (int dev, int fmt) { if (fmt != AFMT_QUERY) { @@ -87,7 +77,7 @@ audio_open (int dev, struct fileinfo *file) { int ret; - long bits; + int bits; int dev_type = dev & 0x0f; int mode = file->mode & O_ACCMODE; @@ -126,15 +116,25 @@ else set_format (dev, bits); - wr_buff_no[dev] = -1; audio_mode[dev] = AM_NONE; - wr_buff_size[dev] = wr_buff_ptr[dev] = 0; dev_nblock[dev] = 0; return ret; } void +sync_output (int dev) +{ + int buf_no, buf_ptr, buf_size; + char *dma_buf; + + if (DMAbuf_get_curr_buffer (dev, &buf_no, &dma_buf, &buf_ptr, &buf_size) >= 0) + { + DMAbuf_start_output (dev, buf_no, buf_ptr); + } +} + +void audio_release (int dev, struct fileinfo *file) { int mode; @@ -142,12 +142,7 @@ dev = dev >> 4; mode = file->mode & O_ACCMODE; - if (wr_buff_no[dev] >= 0) - { - DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]); - - wr_buff_no[dev] = -1; - } + sync_output (dev); if (audio_devs[dev]->coproc) audio_devs[dev]->coproc->close (audio_devs[dev]->coproc->devc, COPR_PCM); @@ -188,8 +183,9 @@ int audio_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count) { - int c, p, l; + int c, p, l, buf_no, buf_ptr, buf_size; int err; + char *dma_buf; dev = dev >> 4; @@ -198,7 +194,6 @@ if ((audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX)) { /* Direction change */ - wr_buff_no[dev] = -1; } if (audio_devs[dev]->flags & DMA_DUPLEX) @@ -206,57 +201,41 @@ else audio_mode[dev] = AM_WRITE; - if (!count) /* - * Flush output - */ + if (!count) /* Flush output */ { - if (wr_buff_no[dev] >= 0) - { - DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]); - - wr_buff_no[dev] = -1; - } + sync_output (dev); return 0; } while (c) - { /* - * Perform output blocking - */ - if (wr_buff_no[dev] < 0) /* - * There is no incomplete buffers - */ + { + if (DMAbuf_get_curr_buffer (dev, &buf_no, &dma_buf, &buf_ptr, &buf_size) < 0) { - if ((wr_buff_no[dev] = DMAbuf_getwrbuffer (dev, &wr_dma_buf[dev], - &wr_buff_size[dev], - dev_nblock[dev])) < 0) + if ((buf_no = DMAbuf_getwrbuffer (dev, &dma_buf, + &buf_size, + dev_nblock[dev])) < 0) { /* Handle nonblocking mode */ - if (dev_nblock[dev] && wr_buff_no[dev] == -EAGAIN) + if (dev_nblock[dev] && buf_no == -EAGAIN) return p; /* No more space. Return # of accepted bytes */ - return wr_buff_no[dev]; + return buf_no; } - wr_buff_ptr[dev] = 0; + buf_ptr = 0; } l = c; - if (l > (wr_buff_size[dev] - wr_buff_ptr[dev])) - l = (wr_buff_size[dev] - wr_buff_ptr[dev]); + if (l > (buf_size - buf_ptr)) + l = (buf_size - buf_ptr); if (!audio_devs[dev]->copy_from_user) { /* * No device specific copy routine */ - memcpy_fromfs (&wr_dma_buf[dev][wr_buff_ptr[dev]], &((buf)[p]), l); + memcpy_fromfs (&dma_buf[buf_ptr], &((buf)[p]), l); } else audio_devs[dev]->copy_from_user (dev, - wr_dma_buf[dev], wr_buff_ptr[dev], buf, p, l); - - - /* - * Insert local processing here - */ + dma_buf, buf_ptr, buf, p, l); if (local_conversion[dev] == AFMT_MU_LAW) { @@ -264,22 +243,23 @@ * This just allows interrupts while the conversion is running */ sti (); - translate_bytes (ulaw_dsp, (unsigned char *) &wr_dma_buf[dev][wr_buff_ptr[dev]], l); + translate_bytes (ulaw_dsp, (unsigned char *) &dma_buf[buf_ptr], l); } c -= l; p += l; - wr_buff_ptr[dev] += l; + buf_ptr += l; - if (wr_buff_ptr[dev] >= wr_buff_size[dev]) + if (buf_ptr >= buf_size) { - if ((err = DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev])) < 0) + if ((err = DMAbuf_start_output (dev, buf_no, buf_ptr)) < 0) { return err; } - wr_buff_no[dev] = -1; } + else + DMAbuf_set_count (dev, buf_no, buf_ptr); } @@ -291,7 +271,7 @@ { int c, p, l; char *dmabuf; - int buff_no; + int buf_no; dev = dev >> 4; p = 0; @@ -299,13 +279,7 @@ 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]); - - if (!(audio_devs[dev]->flags & DMA_DUPLEX)) - wr_buff_no[dev] = -1; - } + sync_output (dev); } if (audio_devs[dev]->flags & DMA_DUPLEX) @@ -315,15 +289,15 @@ while (c) { - if ((buff_no = DMAbuf_getrdbuffer (dev, &dmabuf, &l, - dev_nblock[dev])) < 0) + if ((buf_no = DMAbuf_getrdbuffer (dev, &dmabuf, &l, + dev_nblock[dev])) < 0) { /* Nonblocking mode handling. Return current # of bytes */ - if (dev_nblock[dev] && buff_no == -EAGAIN) + if (dev_nblock[dev] && buf_no == -EAGAIN) return p; - return buff_no; + return buf_no; } if (l > c) @@ -345,7 +319,7 @@ memcpy_tofs (&((buf)[p]), dmabuf, l); - DMAbuf_rmchars (dev, buff_no, l); + DMAbuf_rmchars (dev, buf_no, l); p += l; c -= l; @@ -374,27 +348,16 @@ switch (cmd) { case SNDCTL_DSP_SYNC: - if (wr_buff_no[dev] >= 0) - { - DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]); - - wr_buff_no[dev] = -1; - } + sync_output (dev); return DMAbuf_ioctl (dev, cmd, arg, 0); break; case SNDCTL_DSP_POST: - if (wr_buff_no[dev] >= 0) - { - DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]); - - wr_buff_no[dev] = -1; - } + sync_output (dev); return 0; break; case SNDCTL_DSP_RESET: - wr_buff_no[dev] = -1; audio_mode[dev] = AM_NONE; return DMAbuf_ioctl (dev, cmd, arg, 0); break; @@ -428,14 +391,16 @@ { audio_buf_info info; + char *dma_buf; + int buf_no, buf_ptr, buf_size; int err = DMAbuf_ioctl (dev, cmd, (ioctl_arg) & info, 1); if (err < 0) return err; - if (wr_buff_no[dev] != -1) - info.bytes += wr_buff_size[dev] - wr_buff_ptr[dev]; + if (DMAbuf_get_curr_buffer (dev, &buf_no, &dma_buf, &buf_ptr, &buf_size) >= 0) + info.bytes += buf_size - buf_ptr; memcpy_tofs ((&((char *) arg)[0]), (char *) &info, sizeof (info)); return 0; @@ -482,8 +447,10 @@ } int -audio_select (int dev, struct fileinfo *file, int sel_type, select_table * wait) +audio_select (int dev, struct fileinfo *file, int sel_type, select_table_handle * wait) { + char *dma_buf; + int buf_no, buf_ptr, buf_size; dev = dev >> 4; @@ -493,7 +460,6 @@ if (!(audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX)) return 0; /* Not recording */ - return DMAbuf_select (dev, file, sel_type, wait); break; @@ -501,7 +467,7 @@ if (!(audio_mode[dev] & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX)) return 0; /* Wrong direction */ - if (wr_buff_no[dev] != -1) + if (DMAbuf_get_curr_buffer (dev, &buf_no, &dma_buf, &buf_ptr, &buf_size) >= 0) { return 1; /* There is space in the current buffer */ } @@ -517,5 +483,4 @@ } -#endif #endif diff -u --recursive --new-file v1.3.57/linux/drivers/sound/configure.c linux/drivers/sound/configure.c --- v1.3.57/linux/drivers/sound/configure.c Wed Nov 8 07:11:35 1995 +++ linux/drivers/sound/configure.c Tue Jan 9 00:37:10 1996 @@ -1,4 +1,4 @@ -#define DISABLED_OPTIONS (B(OPT_PNP)) +#define DISABLED_OPTIONS (B(OPT_PNP)|B(OPT_AEDSP16)) /* * sound/configure.c - Configuration program for the Linux Sound Driver * @@ -67,6 +67,7 @@ #define OPT_SEQUENCER 24 #define OPT_LAST 24 /* Last defined OPT number */ +#define DUMMY_OPTS (B(OPT_MIDI_AUTO)|B(OPT_YM3812_AUTO)) #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)| \ @@ -204,10 +205,13 @@ char *oldconf = "/etc/soundconf"; int old_config_used = 0; +int def_size, sb_base = 0; unsigned long selected_options = 0; int sb_dma = 0; +int dump_only = 0; + void build_defines (void); #include "hex2hex.h" @@ -242,8 +246,7 @@ fprintf (stderr, "\n\nERROR! Cannot read stdin\n"); perror ("stdin"); - printf ("#undef CONFIGURE_SOUNDCARD\n"); - printf ("#undef KERNEL_SOUNDCARD\n"); + printf ("invalid_configuration__run_make_config_again\n"); exit (-1); } @@ -273,8 +276,7 @@ fprintf (stderr, "\n\nERROR! Cannot read stdin\n"); perror ("stdin"); - printf ("#undef CONFIGURE_SOUNDCARD\n"); - printf ("#undef KERNEL_SOUNDCARD\n"); + printf ("invalid_configuration__run_make_config_again\n"); exit (-1); } @@ -294,6 +296,74 @@ return num; } +#define FMT_HEX 1 +#define FMT_INT 2 + +void +ask_int_choice (int mask, char *macro, + char *question, + int format, + int defa, + char *choices) +{ + int num, i; + + if (dump_only) + { + + for (i = 0; i < OPT_LAST; i++) + if (mask == B (i)) + { + int j; + + for (j = 0; j < strlen (choices); j++) + if (choices[j] == '\'') + choices[j] = '_'; + + printf ("\nif [ \"$CONFIG_%s\" = \"y\" ]; then\n", + hw_table[i].macro); + if (format == FMT_INT) + printf ("int '%s %s' %s %d\n", question, choices, macro, defa); + else + printf ("hex '%s %s' %s %x\n", question, choices, macro, defa); + printf ("fi\n"); + } + } + else + { + if (!(mask & selected_options)) + return; + + fprintf (stderr, "\n%s\n", question); + fprintf (stderr, "Possible values are: %s\n", choices); + + if (format == FMT_INT) + { + if (defa == -1) + fprintf (stderr, "\t(-1 disables this feature)\n"); + fprintf (stderr, "The default value is %d\n", defa); + fprintf (stderr, "Enter the value: "); + num = ask_value ("%d", defa); + if (num == -1) + return; + fprintf (stderr, "%s set to %d.\n", question, num); + printf ("#define %s %d\n", macro, num); + } + else + { + if (defa == 0) + fprintf (stderr, "\t(0 disables this feature)\n"); + fprintf (stderr, "The default value is %x\n", defa); + fprintf (stderr, "Enter the value: "); + num = ask_value ("%x", defa); + if (num == 0) + return; + fprintf (stderr, "%s set to %x.\n", question, num); + printf ("#define %s 0x%x\n", macro, num); + } + } +} + void rebuild_file (char *line) { @@ -398,10 +468,30 @@ if (strcmp (tmp, "SELECTED_SOUND_OPTIONS") == 0) continue; + if (strcmp (tmp, "KERNEL_SOUNDCARD") == 0) + continue; + tmp[8] = 0; /* Truncate the string */ if (strcmp (tmp, "EXCLUDE_") == 0) continue; /* Skip excludes */ + strncpy (tmp, id, i); + tmp[7] = 0; /* Truncate the string */ + + if (strcmp (tmp, "CONFIG_") == 0) + { + strncpy (tmp, &id[7], i - 7); + tmp[i - 7] = 0; + + for (i = 0; i <= OPT_LAST; i++) + if (strcmp (hw_table[i].macro, tmp) == 0) + { + selected_options |= (1 << i); + break; + } + continue; + } + printf ("%s", buf); continue; } @@ -416,7 +506,11 @@ i++; strncpy (tmp, id, i); - tmp[i] = 0; + tmp[7] = 0; /* Truncate the string */ + if (strcmp (tmp, "CONFIG_") == 0) + continue; + + strncpy (tmp, id, i); tmp[8] = 0; /* Truncate the string */ if (strcmp (tmp, "EXCLUDE_") != 0) @@ -440,9 +534,9 @@ for (i = 0; i <= OPT_LAST; i++) if (!hw_table[i].alias) if (selected_options & B (i)) - printf ("#undef EXCLUDE_%s\n", hw_table[i].macro); + printf ("#define CONFIG_%s\n", hw_table[i].macro); else - printf ("#define EXCLUDE_%s\n", hw_table[i].macro); + printf ("#undef CONFIG_%s\n", hw_table[i].macro); printf ("\n"); @@ -452,9 +546,9 @@ while (extra_options[i].name != NULL) { if (selected_options & extra_options[i].mask) - printf ("#undef EXCLUDE_%s\n", extra_options[i].name); + printf ("#define CONFIG_%s\n", extra_options[i].name); else - printf ("#define EXCLUDE_%s\n", extra_options[i].name); + printf ("#undef CONFIG_%s\n", extra_options[i].name); i++; } @@ -502,16 +596,484 @@ fclose (optf); } +void +ask_parameters (void) +{ + int num; + + build_defines (); + /* + * IRQ and DMA settings + */ + + ask_int_choice (B (OPT_AEDSP16), "AEDSP16_BASE", + "I/O base for Audio Excel DSP 16", + FMT_HEX, + 0x220, + "220 or 240"); + + ask_int_choice (B (OPT_SB), "SBC_BASE", + "I/O base for SB", + FMT_HEX, + 0x220, + ""); + + ask_int_choice (B (OPT_SB), "SBC_IRQ", + "SoundBlaster IRQ", + FMT_INT, + 7, + ""); + + ask_int_choice (B (OPT_SB), "SBC_DMA", + "SoundBlaster DMA", + FMT_INT, + 1, + ""); + + ask_int_choice (B (OPT_SB), "SB_DMA2", + "SoundBlaster 16 bit DMA (if required)", + FMT_INT, + -1, + "5, 6 or 7"); + + ask_int_choice (B (OPT_SB), "SB_MPU_BASE", + "MPU401 I/O base of SB16, Jazz16 and ES1688", + FMT_HEX, + 0, + ""); + + ask_int_choice (B (OPT_SB), "SB_MPU_IRQ", + "SB MPU401 IRQ (SB16, Jazz16 and ES1688)", + FMT_INT, + -1, + ""); + + ask_int_choice (B (OPT_PAS), "PAS_IRQ", + "PAS16 IRQ", + FMT_INT, + 10, + ""); + + ask_int_choice (B (OPT_PAS), "PAS_DMA", + "PAS16 DMA", + FMT_INT, + 3, + ""); + + if (selected_options & B (OPT_PAS)) + { + fprintf (stderr, "\nEnable Joystick port on ProAudioSpectrum (n/y) ? "); + if (think_positively (0)) + printf ("#define PAS_JOYSTICK_ENABLE\n"); + + + fprintf (stderr, "PAS16 could be noisy with some mother boards\n" + "There is a command line switch (was it :T?)\n" + "in the DOS driver for PAS16 which solves this.\n" + "Don't enable this feature unless you have problems!\n" + "Do you have to use this switch with DOS (y/n) ?"); + if (think_positively (0)) + printf ("#define BROKEN_BUS_CLOCK\n"); + } + + + ask_int_choice (B (OPT_GUS), "GUS_BASE", + "I/O base for Gravis UltraSound (GUS)", + FMT_HEX, + 0x220, + "210, 220, 230, 240, 250 or 260"); + + + ask_int_choice (B (OPT_GUS), "GUS_IRQ", + "GUS IRQ", + FMT_INT, + 15, + ""); + + ask_int_choice (B (OPT_GUS), "GUS_DMA", + "GUS DMA", + FMT_INT, + 6, + ""); + + ask_int_choice (B (OPT_GUS), "GUS_DMA2", + "Second DMA channel for GUS", + FMT_INT, + -1, + ""); + + ask_int_choice (B (OPT_GUS16), "GUS16_BASE", + "I/O base for the 16 bit daughtercard of GUS", + FMT_HEX, + 0x530, + "530, 604, E80 or F40"); + + + ask_int_choice (B (OPT_GUS16), "GUS16_IRQ", + "GUS 16 bit daughtercard IRQ", + FMT_INT, + 7, + "3, 4, 5, 7, or 9"); + + ask_int_choice (B (OPT_GUS16), "GUS16_DMA", + "GUS DMA", + FMT_INT, + 3, + "0, 1 or 3"); + + ask_int_choice (B (OPT_MPU401), "MPU_BASE", + "I/O base for MPU401", + FMT_HEX, + 0x330, + ""); + + ask_int_choice (B (OPT_MPU401), "MPU_IRQ", + "MPU401 IRQ", + FMT_INT, + 9, + ""); + + ask_int_choice (B (OPT_MAUI), "MAUI_BASE", + "I/O base for Maui", + FMT_HEX, + 0x330, + "210, 230, 260, 290, 300, 320, 338 or 330"); + + ask_int_choice (B (OPT_MAUI), "MAUI_IRQ", + "Maui IRQ", + FMT_INT, + 9, + "5, 9, 12 or 15"); + + ask_int_choice (B (OPT_UART6850), "U6850_BASE", + "I/O base for UART 6850 MIDI port", + FMT_HEX, + 0, + "(Unknown)"); + + ask_int_choice (B (OPT_UART6850), "U6850_IRQ", + "UART6850 IRQ", + FMT_INT, + -1, + "(Unknown)"); + + ask_int_choice (B (OPT_PSS), "PSS_BASE", + "PSS I/O base", + FMT_HEX, + 0x220, + "220 or 240"); + + ask_int_choice (B (OPT_PSS), "PSS_MSS_BASE", + "PSS audio I/O base", + FMT_HEX, + 0x530, + "530, 604, E80 or F40"); + + ask_int_choice (B (OPT_PSS), "PSS_MSS_IRQ", + "PSS audio IRQ", + FMT_INT, + 11, + "7, 9, 10 or 11"); + + ask_int_choice (B (OPT_PSS), "PSS_MSS_DMA", + "PSS audio DMA", + FMT_INT, + 3, + "0, 1 or 3"); + + ask_int_choice (B (OPT_PSS), "PSS_MPU_BASE", + "PSS MIDI I/O base", + FMT_HEX, + 0x330, + ""); + + ask_int_choice (B (OPT_PSS), "PSS_MPU_IRQ", + "PSS MIDI IRQ", + FMT_INT, + 9, + "3, 4, 5, 7 or 9"); + + ask_int_choice (B (OPT_MSS), "MSS_BASE", + "MSS/WSS I/O base", + FMT_HEX, + 0x530, + "530, 604, E80 or F40"); + + ask_int_choice (B (OPT_MSS), "MSS_IRQ", + "MSS/WSS IRQ", + FMT_INT, + 11, + "7, 9, 10 or 11"); + + ask_int_choice (B (OPT_MSS), "MSS_DMA", + "MSS/WSS DMA", + FMT_INT, + 3, + "0, 1 or 3"); + + ask_int_choice (B (OPT_SSCAPE), "SSCAPE_BASE", + "Soundscape MIDI I/O base", + FMT_HEX, + 0x330, + ""); + + ask_int_choice (B (OPT_SSCAPE), "SSCAPE_IRQ", + "Soundscape MIDI IRQ", + FMT_INT, + 9, + ""); + + ask_int_choice (B (OPT_SSCAPE), "SSCAPE_DMA", + "Soundscape initialization DMA", + FMT_INT, + 3, + "0, 1 or 3"); + + ask_int_choice (B (OPT_SSCAPE), "SSCAPE_MSS_BASE", + "Soundscape audio I/O base", + FMT_HEX, + 0x534, + "534, 608, E84 or F44"); + + ask_int_choice (B (OPT_SSCAPE), "SSCAPE_MSS_IRQ", + "Soundscape audio IRQ", + FMT_INT, + 11, + "7, 9, 10 or 11"); + + ask_int_choice (B (OPT_SSCAPE), "SSCAPE_MSS_DMA", + "Soundscape audio DMA", + FMT_INT, + 0, + "0, 1 or 3"); + + if (selected_options & B (OPT_SSCAPE)) + { + int reveal_spea; + + fprintf (stderr, "Is your SoundScape card made/marketed by Reveal or Spea? "); + reveal_spea = think_positively (0); + if (reveal_spea) + printf ("#define REVEAL_SPEA\n"); + + } + + ask_int_choice (B (OPT_TRIX), "TRIX_BASE", + "AudioTriX audio I/O base", + FMT_HEX, + 0x530, + "530, 604, E80 or F40"); + + ask_int_choice (B (OPT_TRIX), "TRIX_IRQ", + "AudioTriX audio IRQ", + FMT_INT, + 11, + "7, 9, 10 or 11"); + + ask_int_choice (B (OPT_TRIX), "TRIX_DMA", + "AudioTriX audio DMA", + FMT_INT, + 0, + "0, 1 or 3"); + + ask_int_choice (B (OPT_TRIX), "TRIX_DMA2", + "AudioTriX second (duplex) DMA", + FMT_INT, + 3, + "0, 1 or 3"); + + ask_int_choice (B (OPT_TRIX), "TRIX_MPU_BASE", + "AudioTriX MIDI I/O base", + FMT_HEX, + 0x330, + "330, 370, 3B0 or 3F0"); + + ask_int_choice (B (OPT_TRIX), "TRIX_MPU_IRQ", + "AudioTriX MIDI IRQ", + FMT_INT, + 9, + "3, 4, 5, 7 or 9"); + + ask_int_choice (B (OPT_TRIX), "TRIX_SB_BASE", + "AudioTriX SB I/O base", + FMT_HEX, + 0x220, + "220, 210, 230, 240, 250, 260 or 270"); + + ask_int_choice (B (OPT_TRIX), "TRIX_SB_IRQ", + "AudioTriX SB IRQ", + FMT_INT, + 7, + "3, 4, 5 or 7"); + + ask_int_choice (B (OPT_TRIX), "TRIX_SB_DMA", + "AudioTriX SB DMA", + FMT_INT, + 1, + "1 or 3"); + + ask_int_choice (B (OPT_CS4232), "CS4232_BASE", + "CS4232 audio I/O base", + FMT_HEX, + 0x530, + "530, 604, E80 or F40"); + + ask_int_choice (B (OPT_CS4232), "CS4232_IRQ", + "CS4232 audio IRQ", + FMT_INT, + 11, + "5, 7, 9, 11, 12 or 15"); + + ask_int_choice (B (OPT_CS4232), "CS4232_DMA", + "CS4232 audio DMA", + FMT_INT, + 0, + "0, 1 or 3"); + + ask_int_choice (B (OPT_CS4232), "CS4232_DMA2", + "CS4232 second (duplex) DMA", + FMT_INT, + 3, + "0, 1 or 3"); + + ask_int_choice (B (OPT_CS4232), "CS4232_MPU_BASE", + "CS4232 MIDI I/O base", + FMT_HEX, + 0x330, + "330, 370, 3B0 or 3F0"); + + ask_int_choice (B (OPT_CS4232), "CS4232_MPU_IRQ", + "CS4232 MIDI IRQ", + FMT_INT, + 9, + "5, 7, 9, 11, 12 or 15"); + + ask_int_choice (B (OPT_MAD16), "MAD16_BASE", + "MAD16 audio I/O base", + FMT_HEX, + 0x530, + "530, 604, E80 or F40"); + + ask_int_choice (B (OPT_MAD16), "MAD16_IRQ", + "MAD16 audio IRQ", + FMT_INT, + 11, + "7, 9, 10 or 11"); + + ask_int_choice (B (OPT_MAD16), "MAD16_DMA", + "MAD16 audio DMA", + FMT_INT, + 3, + "0, 1 or 3"); + + ask_int_choice (B (OPT_MAD16), "MAD16_DMA2", + "MAD16 second (duplex) DMA", + FMT_INT, + 0, + "0, 1 or 3"); + + ask_int_choice (B (OPT_MAD16), "MAD16_MPU_BASE", + "MAD16 MIDI I/O base", + FMT_HEX, + 0x330, + "300, 310, 320 or 330 (0 disables)"); + + ask_int_choice (B (OPT_MAD16), "MAD16_MPU_IRQ", + "MAD16 MIDI IRQ", + FMT_INT, + 9, + "5, 7, 9 or 10"); + ask_int_choice (B (OPT_AUDIO), "DSP_BUFFSIZE", + "Audio DMA buffer size", + FMT_INT, + 65536, + "4096, 16384, 32768 or 65536"); +} + +void +dump_script (void) +{ + int i; + + for (i = 0; i <= OPT_LAST; i++) + if (!(DUMMY_OPTS & B (i))) + if (!(DISABLED_OPTIONS & B (i))) + { + printf ("bool '%s' CONFIG_%s\n", questions[i], hw_table[i].macro); + } + + dump_only = 1; + selected_options = 0; + ask_parameters (); + + printf ("#\n$MAKE -C drivers/sound kernelconfig || exit 1\n"); +} + +void +dump_fixed_local (void) +{ + int i = 0; + + printf ("/* Computer generated file. Please don't edit! */\n\n"); + printf ("#define KERNEL_COMPATIBLE_CONFIG\n\n"); + printf ("#define SELECTED_SOUND_OPTIONS\t0x%08x\n\n", selected_options); + + while (extra_options[i].name != NULL) + { + int n = 0, j; + + printf ("#if "); + + for (j = 0; j < OPT_LAST; j++) + if (!(DISABLED_OPTIONS & B (j))) + if (extra_options[i].mask & B (j)) + { + if (n) + printf (" || "); + if (!(n++ % 2)) + printf ("\\\n "); + + printf ("defined(CONFIG_%s)", hw_table[j].macro); + } + + printf ("\n"); + printf ("#\tdefine CONFIG_%s\n", extra_options[i].name); + printf ("#endif\n\n"); + i++; + } +} + +void +dump_fixed_defines (void) +{ + int i = 0; + + printf ("# Computer generated file. Please don't edit\n\n"); + + while (extra_options[i].name != NULL) + { + int n = 0, j; + + for (j = 0; j < OPT_LAST; j++) + if (!(DISABLED_OPTIONS & B (j))) + if (extra_options[i].mask & B (j)) + { + printf ("ifdef CONFIG_%s\n", hw_table[j].macro); + printf ("CONFIG_%s=y\n", extra_options[i].name); + printf ("endif\n\n"); + } + + i++; + } +} + int main (int argc, char *argv[]) { - int i, num, def_size, full_driver = 1; + int i, num, full_driver = 1; char answ[10]; - int sb_base = 0; char old_config_file[200]; - fprintf (stderr, "\nConfiguring the sound support\n\n"); - if (getuid () != 0) /* Not root */ { char *home; @@ -528,8 +1090,25 @@ if (strcmp (argv[1], "-o") == 0 && use_old_config (oldconf)) exit (0); + else if (strcmp (argv[1], "script") == 0) + { + dump_script (); + exit (0); + } + else if (strcmp (argv[1], "fixedlocal") == 0) + { + dump_fixed_local (); + exit (0); + } + else if (strcmp (argv[1], "fixeddefines") == 0) + { + dump_fixed_defines (); + exit (0); + } } + fprintf (stderr, "\nConfiguring the sound support\n\n"); + if (access (oldconf, R_OK) == 0) { fprintf (stderr, "Old configuration exists in %s. Use it (y/n) ? ", @@ -540,7 +1119,10 @@ } - printf ("/*\tGenerated by configure. Don't edit!!!!\t*/\n\n"); + printf ("/*\tGenerated by configure. Don't edit!!!!\t*/\n"); + printf ("/*\tMaking changes to this file is not as simple as it may look.\t*/\n\n"); + printf ("/*\tIf you change the CONFIG_ settings in local.h you\t*/\n"); + printf ("/*\t_have_ to edit .defines too.\t*/\n\n"); { /* @@ -590,18 +1172,6 @@ fprintf (stderr, "Do you want support for the MV Jazz16 (ProSonic etc.) ? "); if (think_positively (0)) { - printf ("#define JAZZ16\n"); - do - { - fprintf (stderr, "\tValid 16 bit DMA channels for ProSonic/Jazz 16 are\n"); - fprintf (stderr, "\t1, 3, 5 (default), 7\n"); - fprintf (stderr, "\tEnter 16bit DMA channel for Prosonic : "); - num = ask_value ("%d", 5); - } - while (num != 1 && num != 3 && num != 5 && num != 7); - fprintf (stderr, "ProSonic 16 bit DMA set to %d\n", num); - printf ("#define JAZZ_DMA16 %d\n", num); - fprintf (stderr, "Do you have SoundMan Wave (n/y) ? "); if (think_positively (0)) @@ -687,9 +1257,8 @@ if (sel1 == 0) { - printf ("#undef CONFIGURE_SOUNDCARD\n"); - printf ("#undef KERNEL_SOUNDCARD\n"); - fprintf (stderr, "ERROR!!!!!\nYou loose: you must select at least one mode when using Audio Excel!\n"); + printf ("invalid_configuration__run_make_config_again\n"); + fprintf (stderr, "ERROR!!!!!\nYou must select at least one mode when using Audio Excel!\n"); exit (-1); } if (selected_options & B (OPT_MPU401)) @@ -769,20 +1338,17 @@ if (!(selected_options & ANY_DEVS)) { - printf ("#undef CONFIGURE_SOUNDCARD\n"); - printf ("#undef KERNEL_SOUNDCARD\n"); + printf ("invalid_configuration__run_make_config_again\n"); fprintf (stderr, "\n*** This combination is useless. Sound driver disabled!!! ***\n\n"); exit (0); } - else - printf ("#define KERNEL_SOUNDCARD\n"); for (i = 0; i <= OPT_LAST; i++) if (!hw_table[i].alias) if (selected_options & B (i)) - printf ("#undef EXCLUDE_%s\n", hw_table[i].macro); + printf ("#define CONFIG_%s\n", hw_table[i].macro); else - printf ("#define EXCLUDE_%s\n", hw_table[i].macro); + printf ("#undef CONFIG_%s\n", hw_table[i].macro); printf ("\n"); @@ -792,922 +1358,15 @@ while (extra_options[i].name != NULL) { if (selected_options & extra_options[i].mask) - printf ("#undef EXCLUDE_%s\n", extra_options[i].name); + printf ("#define CONFIG_%s\n", extra_options[i].name); else - printf ("#define EXCLUDE_%s\n", extra_options[i].name); + printf ("#undef CONFIG_%s\n", extra_options[i].name); i++; } printf ("\n"); - - - build_defines (); - /* - * IRQ and DMA settings - */ - - if (selected_options & B (OPT_AEDSP16)) - { - fprintf (stderr, "\nI/O base for Audio Excel DSP 16 ?\n" - "Warning:\n" - "If you are using Audio Excel SoundBlaster emulation,\n" - "you must use the same I/O base for Audio Excel and SoundBlaster.\n" - "The factory default is 220 (other possible value is 240)\n" - "Enter the Audio Excel DSP 16 I/O base: "); - - num = ask_value ("%x", 0x220); - fprintf (stderr, "Audio Excel DSP 16 I/O base set to %03x\n", num); - printf ("#define AEDSP16_BASE 0x%03x\n", num); - } - - if ((selected_options & B (OPT_SB)) && selected_options & (B (OPT_AUDIO) | B (OPT_MIDI))) - { - fprintf (stderr, "\nI/O base for SB?\n" - "The factory default is 220\n" - "Enter the SB I/O base: "); - - 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); - - fprintf (stderr, "\nIRQ number for SoundBlaster?\n" - "The IRQ address is defined by the jumpers on your card.\n" - "The factory default is either 5 or 7 (depending on the model).\n" - "Valid values are 9(=2), 5, 7 and 10.\n" - "Enter the value: "); - - num = ask_value ("%d", 7); - if (num != 9 && num != 5 && num != 7 && num != 10) - { - - fprintf (stderr, "*** Illegal input! ***\n"); - num = 7; - } - fprintf (stderr, "SoundBlaster IRQ set to %d\n", num); - - printf ("#define SBC_IRQ %d\n", num); - - if (selected_options & (B (OPT_SBPRO) | B (OPT_PAS))) - { - fprintf (stderr, "\nDMA channel for SoundBlaster?\n" - "For SB 1.0, 1.5 and 2.0 this MUST be 1\n" - "SB Pro supports DMA channels 0, 1 and 3 (jumper)\n" - "For SB16 give the 8 bit DMA# here\n" - "The default value is 1\n" - "Enter the value: "); - - num = ask_value ("%d", 1); - if (num < 0 || num > 3) - { - - fprintf (stderr, "*** Illegal input! ***\n"); - num = 1; - } - fprintf (stderr, "SoundBlaster DMA set to %d\n", num); - printf ("#define SBC_DMA %d\n", num); - sb_dma = num; - } - - if (selected_options & B (OPT_SB16)) - { - - fprintf (stderr, "\n16 bit DMA channel for SoundBlaster 16?\n" - "Possible values are 5, 6 or 7\n" - "The default value is 6\n" - "Enter the value: "); - - num = ask_value ("%d", 6); - if ((num < 5 || num > 7) && (num != sb_dma)) - { - - fprintf (stderr, "*** Illegal input! ***\n"); - num = 6; - } - fprintf (stderr, "SoundBlaster DMA set to %d\n", num); - printf ("#define SB16_DMA %d\n", num); - - fprintf (stderr, "\nI/O base for SB16 Midi?\n" - "Possible values are 300 and 330\n" - "The factory default is 330\n" - "Enter the SB16 Midi I/O base: "); - - num = ask_value ("%x", 0x330); - fprintf (stderr, "SB16 Midi I/O base set to %03x\n", num); - printf ("#define SB16MIDI_BASE 0x%03x\n", num); - } - } - - if (selected_options & B (OPT_PAS)) - { - - if (selected_options & (B (OPT_AUDIO) | B (OPT_MIDI))) - { - fprintf (stderr, "\nIRQ number for ProAudioSpectrum?\n" - "The recommended value is the IRQ used under DOS.\n" - "Please refer to the ProAudioSpectrum User's Guide.\n" - "The default value is 10.\n" - "Enter the value: "); - - num = ask_value ("%d", 10); - if (num == 6 || num < 3 || num > 15 || num == 2) /* - * Illegal - */ - { - - fprintf (stderr, "*** Illegal input! ***\n"); - num = 10; - } - fprintf (stderr, "ProAudioSpectrum IRQ set to %d\n", num); - printf ("#define PAS_IRQ %d\n", num); - } - - if (selected_options & B (OPT_AUDIO)) - { - fprintf (stderr, "\nDMA number for ProAudioSpectrum?\n" - "The recommended value is the DMA channel under DOS.\n" - "Please refer to the ProAudioSpectrum User's Guide.\n" - "The default value is 3\n" - "Enter the value: "); - - num = ask_value ("%d", 3); - if (num == 4 || num < 0 || num > 7) - { - - fprintf (stderr, "*** Illegal input! ***\n"); - num = 3; - } - fprintf (stderr, "\nProAudioSpectrum DMA set to %d\n", num); - printf ("#define PAS_DMA %d\n", num); - } - fprintf (stderr, "\nEnable Joystick port on ProAudioSpectrum (n/y) ? "); - if (think_positively (0)) - printf ("#define PAS_JOYSTICK_ENABLE\n"); - - fprintf (stderr, "PAS16 could be noisy with some mother boards\n" - "There is a command line switch (was it :T?)\n" - "in the DOS driver for PAS16 which solves this.\n" - "Don't enable this feature unless you have problems!\n" - "Do you have to use this switch with DOS (y/n) ?"); - if (think_positively (0)) - printf ("#define BROKEN_BUS_CLOCK\n"); - } - - if (selected_options & B (OPT_GUS)) - { - fprintf (stderr, "\nI/O base for Gravis Ultrasound?\n" - "Valid choices are 210, 220, 230, 240, 250 or 260\n" - "The factory default is 220\n" - "Enter the GUS I/O base: "); - - num = ask_value ("%x", 0x220); - if ((num > 0x260) || ((num & 0xf0f) != 0x200) || ((num & 0x0f0) > 0x060)) - { - - fprintf (stderr, "*** Illegal input! ***\n"); - 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" - "\tRun the config again.\n"); - printf ("#undef CONFIGURE_SOUNDCARD\n"); - printf ("#undef KERNEL_SOUNDCARD\n"); - exit (-1); - } - fprintf (stderr, "GUS I/O base set to %03x\n", num); - printf ("#define GUS_BASE 0x%03x\n", num); - - fprintf (stderr, "\nIRQ number for Gravis UltraSound?\n" - "The recommended value is the IRQ used under DOS.\n" - "Please refer to the Gravis Ultrasound User's Guide.\n" - "The default value is 15.\n" - "Enter the value: "); - - num = ask_value ("%d", 15); - if (num == 6 || num < 3 || num > 15 || num == 2) /* - * Invalid - */ - { - - fprintf (stderr, "*** Illegal input! ***\n"); - num = 15; - } - fprintf (stderr, "Gravis UltraSound IRQ set to %d\n", num); - printf ("#define GUS_IRQ %d\n", num); - - fprintf (stderr, "\nDMA number for Gravis UltraSound?\n" - "The recommended value is the DMA channel under DOS.\n" - "Please refer to the Gravis Ultrasound User's Guide.\n" - "The default value is 6\n" - "Enter the value: "); - - num = ask_value ("%d", 6); - if (num == 4 || num < 0 || num > 7) - { - fprintf (stderr, "*** Illegal input! ***\n"); - num = 6; - } - fprintf (stderr, "\nGravis UltraSound DMA set to %d\n", num); - printf ("#define GUS_DMA %d\n", num); - - fprintf (stderr, "\nSecond DMA channel for GUS (optional)?\n" - "The default value is 7 (-1 disables)\n" - "Enter the value: "); - - 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" - "The factory default is 530\n" - "Other possible values are 604, E80 or F40\n" - "Enter the GUS16 I/O base: "); - - num = ask_value ("%x", 0x530); - fprintf (stderr, "GUS16 I/O base set to %03x\n", num); - printf ("#define GUS16_BASE 0x%03x\n", num); - - fprintf (stderr, "\nIRQ number for GUS16?\n" - "Valid numbers are: 3, 4, 5, 7, or 9(=2).\n" - "The default value is 7.\n" - "Enter the value: "); - - num = ask_value ("%d", 7); - if (num == 6 || num < 3 || num > 15) - { - fprintf (stderr, "*** Illegal input! ***\n"); - num = 7; - } - fprintf (stderr, "GUS16 IRQ set to %d\n", num); - printf ("#define GUS16_IRQ %d\n", num); - - fprintf (stderr, "\nDMA number for GUS16?\n" - "The default value is 3\n" - "Enter the value: "); - - num = ask_value ("%d", 3); - if (num < 0 || num > 3) - { - fprintf (stderr, "*** Illegal input! ***\n"); - num = 3; - } - fprintf (stderr, "\nGUS16 DMA set to %d\n", num); - printf ("#define GUS16_DMA %d\n", num); - } - } - - if (selected_options & B (OPT_MPU401)) - { - fprintf (stderr, "\nI/O base for MPU-401?\n" - "The factory default is 330\n" - "Enter the MPU-401 I/O base: "); - - num = ask_value ("%x", 0x330); - fprintf (stderr, "MPU-401 I/O base set to %03x\n", num); - printf ("#define MPU_BASE 0x%03x\n", num); - - fprintf (stderr, "\nIRQ number for MPU-401?\n" - "Valid numbers are: 3, 4, 5, 7 and 9(=2).\n" - "The default value is 9.\n" - "Enter the value: "); - - num = ask_value ("%d", 9); - if (num == 6 || num < 3 || num > 15) - { - - fprintf (stderr, "*** Illegal input! ***\n"); - num = 5; - } - fprintf (stderr, "MPU-401 IRQ set to %d\n", num); - printf ("#define MPU_IRQ %d\n", num); - } - - if (selected_options & B (OPT_MAUI)) - { - fprintf (stderr, "\nI/O base for TB Maui (MIDI I/O of TB Tropez)?\n" - "The factory default is 330\n" - "Valid alternatives are 210, 230, 260, 290, 300, 320, 338 and 330\n" - "Enter the Maui/Tropez MIDI I/O base: "); - - num = ask_value ("%x", 0x330); - fprintf (stderr, "Maui I/O base set to %03x\n", num); - printf ("#define MAUI_BASE 0x%03x\n", num); - - fprintf (stderr, "\nIRQ number for TB Maui (TB Tropez MIDI)?\n" - "Valid numbers are: 5, 9, 12 and 15.\n" - "The default value is 9.\n" - "Enter the value: "); - - num = ask_value ("%d", 9); - if (num == 6 || num < 3 || num > 15) - { - - fprintf (stderr, "*** Illegal input! ***\n"); - num = 5; - } - fprintf (stderr, "Maui/Tropez MIDI IRQ set to %d\n", num); - printf ("#define MAUI_IRQ %d\n", num); - } - - if (selected_options & B (OPT_UART6850)) - { - fprintf (stderr, "\nI/O base for 6850 UART Midi?\n" - "Be carefull. No defaults.\n" - "Enter the 6850 UART I/O base: "); - - num = ask_value ("%x", 0); - if (num == 0) - { - /* - * Invalid value entered - */ - printf ("#define EXCLUDE_UART6850\n"); - } - else - { - fprintf (stderr, "6850 UART I/O base set to %03x\n", num); - printf ("#define U6850_BASE 0x%03x\n", num); - - fprintf (stderr, "\nIRQ number for 6850 UART?\n" - "Valid numbers are: 3, 4, 5, 7 and 9(=2).\n" - "The default value is 5.\n" - "Enter the value: "); - - num = ask_value ("%d", 5); - if (num == 6 || num < 3 || num > 15) - { - - fprintf (stderr, "*** Illegal input! ***\n"); - num = 5; - } - fprintf (stderr, "6850 UART IRQ set to %d\n", num); - printf ("#define U6850_IRQ %d\n", num); - } - } - - if (selected_options & B (OPT_PSS)) - { - fprintf (stderr, "\nI/O base for PSS?\n" - "The factory default is 220 (240 also possible)\n" - "Enter the PSS I/O base: "); - - num = ask_value ("%x", 0x220); - 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" - "Enter the value: "); - - num = ask_value ("%d", 10); - if (num == 6 || num < 3 || num > 15) - { - fprintf (stderr, "*** Illegal input! ***\n"); - num = 7; - } - fprintf (stderr, "PSS IRQ set to %d\n", num); - printf ("#define PSS_IRQ %d\n", num); - - fprintf (stderr, "\nDMA number for ECHO-PSS?\n" - "The default value is 5\n" - "Valid values are 5, 6 and 7\n" - "Enter the value: "); - - num = ask_value ("%d", 5); - if (num < 5 || num > 7) - { - fprintf (stderr, "*** Illegal input! ***\n"); - num = 5; - } - 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" - "Other possible values are 604, E80 or F40\n" - "Enter the MSS I/O base: "); - - num = ask_value ("%x", 0x530); - fprintf (stderr, "PSS/MSS I/O base set to %03x\n", num); - printf ("#define PSS_MSS_BASE 0x%03x\n", num); - - fprintf (stderr, "\nIRQ number for the MSS mode of PSS ?\n" - "Valid numbers are: 7, 9(=2), 10 and 11.\n" - "The default value is 11.\n" - "Enter the value: "); - - num = ask_value ("%d", 11); - if (num == 6 || num < 3 || num > 15) - { - fprintf (stderr, "*** Illegal input! ***\n"); - num = 11; - } - fprintf (stderr, "PSS/MSS IRQ set to %d\n", num); - printf ("#define PSS_MSS_IRQ %d\n", num); - - fprintf (stderr, "\nMSS DMA number for PSS?\n" - "Valid values are 0, 1 and 3.\n" - "The default value is 3\n" - "Enter the value: "); - - num = ask_value ("%d", 3); - if (num == 4 || num < 0 || num > 7) - { - fprintf (stderr, "*** Illegal input! ***\n"); - num = 3; - } - fprintf (stderr, "\nPSS/MSS DMA set to %d\n", num); - printf ("#define PSS_MSS_DMA %d\n", num); - - fprintf (stderr, "\nMIDI I/O base for PSS?\n" - "The factory default is 330\n" - "Enter the PSS MIDI I/O base: "); - - num = ask_value ("%x", 0x330); - fprintf (stderr, "PSS/MIDI I/O base set to %03x\n", num); - printf ("#define PSS_MPU_BASE 0x%03x\n", num); - - fprintf (stderr, "\nIRQ number for PSS MIDI?\n" - "Valid numbers are: 3, 4, 5, 7 and 9(=2).\n" - "The default value is 9.\n" - "Enter the value: "); - - num = ask_value ("%d", 9); - if (num == 6 || num < 3 || num > 15) - { - - fprintf (stderr, "*** Illegal input! ***\n"); - num = 5; - } - fprintf (stderr, "PSS MIDI IRQ set to %d\n", num); - printf ("#define PSS_MPU_IRQ %d\n", num); - } - - if (selected_options & B (OPT_MSS)) - { - fprintf (stderr, "\nI/O base for MSS (MS Sound System)?\n" - "The factory default is 530\n" - "Other possible values are 604, E80 or F40\n" - "Enter the MSS I/O base: "); - - num = ask_value ("%x", 0x530); - fprintf (stderr, "MSS I/O base set to %03x\n", num); - printf ("#define MSS_BASE 0x%03x\n", num); - - fprintf (stderr, "\nIRQ number for MSS?\n" - "Valid numbers are: 7, 9(=2), 10 and 11.\n" - "The default value is 10.\n" - "Enter the value: "); - - num = ask_value ("%d", 10); - if (num == 6 || num < 3 || num > 15) - { - fprintf (stderr, "*** Illegal input! ***\n"); - num = 7; - } - fprintf (stderr, "MSS IRQ set to %d\n", num); - printf ("#define MSS_IRQ %d\n", num); - - fprintf (stderr, "\nDMA number for MSS?\n" - "Valid values are 0, 1 and 3.\n" - "The default value is 3\n" - "Enter the value: "); - - num = ask_value ("%d", 3); - if (num == 4 || num < 0 || num > 7) - { - fprintf (stderr, "*** Illegal input! ***\n"); - num = 3; - } - fprintf (stderr, "\nMSS DMA set to %d\n", num); - printf ("#define MSS_DMA %d\n", num); - } - - if (selected_options & B (OPT_SSCAPE)) - { - int reveal_spea; - - fprintf (stderr, "\n(MIDI) I/O base for Ensoniq Soundscape?\n" - "The factory default is 330\n" - "Other possible values are 320, 340 or 350\n" - "Enter the Soundscape I/O base: "); - - num = ask_value ("%x", 0x330); - fprintf (stderr, "Soundscape I/O base set to %03x\n", num); - printf ("#define SSCAPE_BASE 0x%03x\n", num); - - fprintf (stderr, "Is your SoundScape card made/marketed by Reveal or Spea? "); - reveal_spea = think_positively (0); - if (reveal_spea) - printf ("#define REVEAL_SPEA\n"); - - fprintf (stderr, "\nIRQ number for Soundscape?\n"); - - if (reveal_spea) - fprintf (stderr, "Check valid interrupts from the manual of your card.\n"); - else - fprintf (stderr, "Valid numbers are: 5, 7, 9(=2) and 10.\n"); - - fprintf (stderr, "The default value is 9.\n" - "Enter the value: "); - - num = ask_value ("%d", 9); - if (num == 6 || num < 3 || num > 15) - { - fprintf (stderr, "*** Illegal input! ***\n"); - num = 9; - } - fprintf (stderr, "Soundscape IRQ set to %d\n", num); - printf ("#define SSCAPE_IRQ %d\n", num); - - fprintf (stderr, "\nDMA number for Soundscape?\n" - "Valid values are 1 and 3 (sometimes 0)" - "The default value is 3\n" - "Enter the value: "); - - num = ask_value ("%d", 3); - if (num == 4 || num < 0 || num > 7) - { - fprintf (stderr, "*** Illegal input! ***\n"); - num = 3; - } - fprintf (stderr, "\nSoundscape DMA set to %d\n", num); - printf ("#define SSCAPE_DMA %d\n", num); - - fprintf (stderr, "\nMSS (MS Sound System) I/O base for the SSCAPE card?\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, "SSCAPE/MSS I/O base set to %03x\n", num); - printf ("#define SSCAPE_MSS_BASE 0x%03x\n", num); - - fprintf (stderr, "\nIRQ number for the MSS mode of SSCAPE ?\n"); - if (reveal_spea) - fprintf (stderr, "Valid numbers are: 5, 7, 9(=2) and 15.\n"); - else - fprintf (stderr, "Valid numbers are: 5, 7, 9(=2) and 10.\n"); - fprintf (stderr, "The default value is 5.\n" - "Enter the value: "); - - num = ask_value ("%d", 5); - if (num == 6 || num < 3 || num > 15) - { - fprintf (stderr, "*** Illegal input! ***\n"); - num = 10; - } - fprintf (stderr, "SSCAPE/MSS IRQ set to %d\n", num); - printf ("#define SSCAPE_MSS_IRQ %d\n", num); - - fprintf (stderr, "\nMSS DMA number for SSCAPE?\n" - "Valid values are 0, 1 and 3.\n" - "The default value is 3\n" - "Enter the value: "); - - num = ask_value ("%d", 3); - if (num == 4 || num < 0 || num > 7) - { - fprintf (stderr, "*** Illegal input! ***\n"); - num = 3; - } - fprintf (stderr, "\nSSCAPE/MSS DMA set to %d\n", num); - printf ("#define SSCAPE_MSS_DMA %d\n", num); - } - if (selected_options & B (OPT_TRIX)) - { - - fprintf (stderr, "\nWindows Sound System I/O base for the AudioTriX card?\n" - "The factory default is 530\n" - "Other possible values are 604, E80 or F40\n" - "Enter the MSS I/O base: "); - - num = ask_value ("%x", 0x530); - fprintf (stderr, "AudioTriX MSS I/O base set to %03x\n", num); - printf ("#define TRIX_BASE 0x%03x\n", num); - - fprintf (stderr, "\nIRQ number for the WSS mode of AudioTriX ?\n" - "Valid numbers are: 5, 7, 9(=2), 10 and 11.\n" - "The default value is 11.\n" - "Enter the value: "); - - num = ask_value ("%d", 11); - if (num != 5 && num != 7 && num != 9 && num != 10 && num != 11) - { - fprintf (stderr, "*** Illegal input! ***\n"); - num = 11; - } - fprintf (stderr, " AudioTriX WSS IRQ set to %d\n", num); - printf ("#define TRIX_IRQ %d\n", num); - - fprintf (stderr, "\nWSS DMA number for AudioTriX?\n" - "Valid values are 0, 1 and 3.\n" - "The default value is 3\n" - "Enter the value: "); - - num = ask_value ("%d", 3); - if (num != 0 && num != 1 && num != 3) - { - fprintf (stderr, "*** Illegal input! ***\n"); - num = 3; - } - 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" - "Enter the MSS I/O base: "); - - num = ask_value ("%x", 0x220); - fprintf (stderr, "AudioTriX SB I/O base set to %03x\n", num); - printf ("#define TRIX_SB_BASE 0x%03x\n", num); - - fprintf (stderr, "\nIRQ number for the SB mode of AudioTriX ?\n" - "Valid numbers are: 3, 4, 5 and 7.\n" - "The default value is 7.\n" - "Enter the value: "); - - num = ask_value ("%d", 7); - if (num != 3 && num != 4 && num != 5 && num != 7) - { - fprintf (stderr, "*** Illegal input! ***\n"); - num = 7; - } - fprintf (stderr, " AudioTriX SB IRQ set to %d\n", num); - printf ("#define TRIX_SB_IRQ %d\n", num); - - fprintf (stderr, "\nSB DMA number for AudioTriX?\n" - "Valid values are 1 and 3.\n" - "The default value is 1\n" - "Enter the value: "); - - num = ask_value ("%d", 1); - if (num != 1 && num != 3) - { - fprintf (stderr, "*** Illegal input! ***\n"); - num = 1; - } - fprintf (stderr, "\nAudioTriX/SB DMA set to %d\n", num); - printf ("#define TRIX_SB_DMA %d\n", num); - - fprintf (stderr, "\nMIDI (MPU-401) I/O address for the AudioTriX 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, "AudioTriX MIDI I/O base set to %03x\n", num); - printf ("#define TRIX_MPU_BASE 0x%03x\n", num); - - fprintf (stderr, "\nMIDI IRQ number for the AudioTriX ?\n" - "Valid numbers are: 3, 4, 5, 7 and 9(=2).\n" - "The default value is 5.\n" - "Enter the value: "); - - num = ask_value ("%d", 5); - if (num != 3 && num != 4 && num != 5 && num != 7 && num != 9) - { - fprintf (stderr, "*** Illegal input! ***\n"); - num = 5; - } - fprintf (stderr, " AudioTriX MIDI IRQ set to %d\n", num); - 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"); - - fprintf (stderr, "\nWindows Sound System I/O base for the MAD16/Mozart card?\n" - "The factory default is 530\n" - "Other possible values are 604, E80 or F40\n" - "(Check which ones are supported by your card!!!!!!)\n" - "Enter the MSS I/O base: "); - - num = ask_value ("%x", 0x530); - 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" - "Enter the value: "); - - num = ask_value ("%d", 11); - if (num != 7 && num != 9 && num != 10 && num != 11) - { - fprintf (stderr, "*** Illegal input! ***\n"); - num = 11; - } - fprintf (stderr, " MAD16 WSS IRQ set to %d\n", num); - printf ("#define MAD16_IRQ %d\n", num); - - 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: "); - - num = ask_value ("%d", 3); - if (num != 0 && num != 1 && num != 3) - { - fprintf (stderr, "*** Illegal input! ***\n"); - num = 3; - } - fprintf (stderr, "\nMAD16/WSS DMA set to %d\n", num); - printf ("#define MAD16_DMA %d\n", num); - - 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" - "Other possible values are 330, 320, 310 and 300\n" - "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) - fprintf (stderr, "MAD16/Mozart MIDI port disabled\n"); - else - { - fprintf (stderr, "MAD16 MIDI I/O base set to %03x\n", num); - printf ("#define MAD16_MPU_BASE 0x%03x\n", num); - - fprintf (stderr, "\nMIDI IRQ number for the MAD16 ?\n" - "Valid numbers are: 5, 7, 9(=2) and 10.\n" - "The default value is 5.\n" - "Enter the value: "); - - num = ask_value ("%d", 5); - if (num != 3 && num != 4 && num != 5 && num != 7 && num != 9) - { - fprintf (stderr, "*** Illegal input! ***\n"); - num = 5; - } - fprintf (stderr, " MAD16 MIDI IRQ set to %d\n", num); - printf ("#define MAD16_MPU_IRQ %d\n", num); - } - } - - if (selected_options & B (OPT_AUDIO)) - { - def_size = 65536; - - fprintf (stderr, "\nSelect the DMA buffer size (4096, 16384, 32768 or 65536 bytes)\n" - "%d is recommended value for this configuration.\n" - "Enter the value: ", def_size); - - num = ask_value ("%d", def_size); - if (num != 4096 && num != 16384 && num != 32768 && num != 65536) - { - - fprintf (stderr, "*** Illegal input! ***\n"); - num = def_size; - } - fprintf (stderr, "The DMA buffer size set to %d\n", num); - printf ("#define DSP_BUFFSIZE %d\n", num); - } + ask_parameters (); printf ("#define SELECTED_SOUND_OPTIONS\t0x%08x\n", selected_options); fprintf (stderr, "The sound driver is now configured.\n"); diff -u --recursive --new-file v1.3.57/linux/drivers/sound/cs4232.c linux/drivers/sound/cs4232.c --- v1.3.57/linux/drivers/sound/cs4232.c Wed Nov 8 07:11:35 1995 +++ linux/drivers/sound/cs4232.c Tue Jan 9 00:37:10 1996 @@ -34,7 +34,7 @@ #include "sound_config.h" -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_CS4232) +#if defined(CONFIG_CS4232) #define KEY_PORT 0x279 /* Same as LPT1 status port */ #define CSN_NUM 0x99 /* Just a random number */ @@ -44,6 +44,7 @@ #define CS_OUT3(a, b, c) {CS_OUT(a);CS_OUT(b);CS_OUT(c);} static int mpu_base = 0, mpu_irq = 0; +static int mpu_detected = 0; int probe_cs4232_mpu (struct address_info *hw_config) @@ -88,6 +89,9 @@ return 0; } + if (ad1848_detect (hw_config->io_base, NULL, hw_config->osp)) + return 1; /* The card is already active */ + /* * 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 @@ -108,14 +112,6 @@ 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 @@ -144,7 +140,7 @@ * Initialize logical device 3 (MPU) */ -#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI) +#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI) if (mpu_base != 0 && mpu_irq != 0) { CS_OUT2 (0x15, 0x03); /* Select logical device 3 (MPU) */ @@ -182,7 +178,7 @@ 0, hw_config->osp); -#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI) +#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI) if (mpu_base != 0 && mpu_irq != 0) { static struct address_info hw_config2 = @@ -201,6 +197,7 @@ if (probe_mpu401 (&hw_config2)) { + mpu_detected = 1; mem_start = attach_mpu401 (mem_start, &hw_config2); } else @@ -227,8 +224,8 @@ dma2, /* Capture DMA */ 0); -#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI) - if (mpu_base != 0 && mpu_irq != 0) +#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI) + if (mpu_base != 0 && mpu_irq != 0 && mpu_detected) { static struct address_info hw_config2 = {0}; /* Ensure it's initialized */ diff -u --recursive --new-file v1.3.57/linux/drivers/sound/dev_table.c linux/drivers/sound/dev_table.c --- v1.3.57/linux/drivers/sound/dev_table.c Wed Nov 8 07:11:35 1995 +++ linux/drivers/sound/dev_table.c Tue Jan 9 00:37:11 1996 @@ -30,8 +30,6 @@ #define _DEV_TABLE_C_ #include "sound_config.h" -#ifdef CONFIGURE_SOUNDCARD - int sound_started = 0; int sndtable_get_cardcount (void); @@ -48,6 +46,33 @@ return -1; } +static long +start_services (long mem_start) +{ + int soundcards_installed; + + if (!(soundcards_installed = sndtable_get_cardcount ())) + return mem_start; /* No cards detected */ + +#ifdef CONFIG_AUDIO + if (num_audiodevs) /* Audio devices present */ + { + DMAbuf_init (0); + audio_init (0); + } +#endif + +#ifdef CONFIG_MIDI + if (num_midis) + MIDIbuf_init (0); +#endif + +#ifdef CONFIG_SEQUENCER + if (num_midis + num_synths) + sequencer_init (0); +#endif + return mem_start; +} static long start_cards (long mem_start) @@ -56,7 +81,8 @@ int drv; sound_started = 1; - printk ("Sound initialization started\n"); + if (trace_init) + printk ("Sound initialization started\n"); /* * Check the number of cards actually defined in the table @@ -83,27 +109,9 @@ if (sound_drivers[drv].probe (&snd_installed_cards[i].config)) { - int tmp; - - printk ("snd%d", - snd_installed_cards[i].card_type); mem_start = sound_drivers[drv].attach (mem_start, &snd_installed_cards[i].config); - printk (" at 0x%x", - snd_installed_cards[i].config.io_base); - if ((tmp = snd_installed_cards[i].config.irq) != 0) - printk (" irq %d", - (tmp > 0) ? tmp : -tmp); - - if (snd_installed_cards[i].config.dma >= 0) - printk (" drq %d", - 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"); } else snd_installed_cards[i].enabled = 0; /* @@ -111,7 +119,8 @@ */ } - printk ("Sound initialization complete\n"); + if (trace_init) + printk ("Sound initialization complete\n"); return mem_start; } @@ -130,7 +139,8 @@ if (!sound_started) return; - printk ("Sound unload started\n"); + if (trace_init) + printk ("Sound unload started\n"); for (i = 0; i < n && snd_installed_cards[i].card_type; i++) if (snd_installed_cards[i].enabled) @@ -141,7 +151,8 @@ snd_installed_cards[i].enabled = 0; } - printk ("Sound unload complete\n"); + if (trace_init) + printk ("Sound unload complete\n"); } void @@ -182,6 +193,8 @@ { int i, sel = -1, n = num_sound_cards; + DDB (printk ("sndtable_probe(%d)\n", unit)); + if (!unit) return TRUE; @@ -221,16 +234,22 @@ if ((drv = snd_find_driver (snd_installed_cards[sel].card_type)) == -1) { snd_installed_cards[sel].enabled = 0; + DDB (printk ("Failed to find driver\n")); return FALSE; } + DDB (printk ("Driver name '%s'\n", sound_drivers[drv].name)); - - snd_installed_cards[sel].config.card_subtype = + hw_config->card_subtype = + snd_installed_cards[sel].config.card_subtype = sound_drivers[drv].card_subtype; if (sound_drivers[drv].probe (hw_config)) - return TRUE; + { + return TRUE; + DDB (printk ("Hardware probed OK\n")); + } + DDB (printk ("Failed to find hardware\n")); snd_installed_cards[sel].enabled = 0; /* * Mark as not detected */ @@ -278,26 +297,17 @@ { 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"); } + start_services (0); return TRUE; } - printk ("sndtable_init_card: No card defined with type=%d, num cards: %d\n", - unit, num_sound_cards); + DDB (printk ("sndtable_init_card: No card defined with type=%d, num cards: %d\n", + unit, num_sound_cards)); return FALSE; } @@ -413,7 +423,3 @@ return &snd_installed_cards[ptr].config; } - - - -#endif diff -u --recursive --new-file v1.3.57/linux/drivers/sound/dev_table.h linux/drivers/sound/dev_table.h --- v1.3.57/linux/drivers/sound/dev_table.h Wed Nov 8 07:11:35 1995 +++ linux/drivers/sound/dev_table.h Tue Jan 9 00:36:54 1996 @@ -26,7 +26,6 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - */ #ifndef _DEV_TABLE_H_ @@ -77,6 +76,7 @@ struct dma_buffparms { int dma_mode; /* DMODE_INPUT, DMODE_OUTPUT or DMODE_NONE */ + int closing; /* * Pointers to raw buffers @@ -104,6 +104,7 @@ int qlen; int qhead; int qtail; + int cfrag; /* Current incomplete fragment (write) */ int nbufs; int counts[MAX_SUB_BUFFERS]; @@ -120,6 +121,9 @@ int mapping_flags; #define DMA_MAP_MAPPED 0x00000001 char neutral_byte; +#ifdef OS_DMA_PARMS + OS_DMA_PARMS +#endif }; /* @@ -265,7 +269,7 @@ struct synth_operations *synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV] = {NULL}; int num_synths = 0; struct midi_operations *midi_devs[MAX_MIDI_DEV] = {NULL}; int num_midis = 0; -#ifndef EXCLUDE_SEQUENCER +#ifdef CONFIG_SEQUENCER extern struct sound_timer_operations default_sound_timer; struct sound_timer_operations *sound_timer_devs[MAX_TIMER_DEV] = {&default_sound_timer, NULL}; @@ -281,66 +285,64 @@ */ struct driver_info sound_drivers[] = { -#ifndef EXCLUDE_PSS +#ifdef CONFIG_PSS {"PSSECHO", 0, SNDCARD_PSS, "Echo Personal Sound System PSS (ESC614)", attach_pss, probe_pss, unload_pss}, {"PSSMPU", 0, SNDCARD_PSS_MPU, "PSS-MPU", attach_pss_mpu, probe_pss_mpu, unload_pss_mpu}, {"PSSMSS", 0, SNDCARD_PSS_MSS, "PSS-MSS", attach_pss_mss, probe_pss_mss, unload_pss_mss}, #endif -#ifndef EXCLUDE_MSS +#ifdef CONFIG_MSS {"MSS", 0, SNDCARD_MSS, "MS Sound System", attach_ms_sound, probe_ms_sound, unload_ms_sound}, /* MSS without IRQ/DMA config registers (for DEC Alphas) */ - {"PCXBJ", 1, SNDCARD_PSEUDO_MSS, "MS Sound System", attach_ms_sound, probe_ms_sound, unload_ms_sound}, + {"PCXBJ", 1, SNDCARD_PSEUDO_MSS, "MS Sound System (AXP)", attach_ms_sound, probe_ms_sound, unload_ms_sound}, #endif -#ifndef EXCLUDE_MAD16 +#ifdef CONFIG_MAD16 {"MAD16", 0, SNDCARD_MAD16, "MAD16/Mozart (MSS)", attach_mad16, probe_mad16, unload_mad16}, {"MAD16MPU", 0, SNDCARD_MAD16_MPU, "MAD16/Mozart (MPU)", attach_mad16_mpu, probe_mad16_mpu, unload_mad16_mpu}, #endif -#ifndef EXCLUDE_CS4232 +#ifdef CONFIG_CS4232 {"CS4232", 0, SNDCARD_CS4232, "CS4232", attach_cs4232, probe_cs4232, unload_cs4232}, {"CS4232MPU", 0, SNDCARD_CS4232_MPU, "CS4232 MIDI", attach_cs4232_mpu, probe_cs4232_mpu, unload_cs4232_mpu}, #endif -#ifndef EXCLUDE_YM3812 +#ifdef CONFIG_YM3812 {"OPL3", 0, SNDCARD_ADLIB, "OPL-2/OPL-3 FM", attach_adlib_card, probe_adlib, unload_adlib}, #endif -#ifndef EXCLUDE_PAS +#ifdef CONFIG_PAS {"PAS16", 0, SNDCARD_PAS, "ProAudioSpectrum", attach_pas_card, probe_pas, unload_pas}, #endif -#if !defined(EXCLUDE_MPU401) && !defined(EXCLUDE_MIDI) +#if defined(CONFIG_MPU401) && defined(CONFIG_MIDI) {"MPU401", 0, SNDCARD_MPU401,"Roland MPU-401", attach_mpu401, probe_mpu401, unload_mpu401}, #endif -#if !defined(EXCLUDE_MAUI) +#if defined(CONFIG_MAUI) {"MAUI", 0, SNDCARD_MAUI,"TB Maui", attach_maui, probe_maui, unload_maui}, #endif -#if !defined(EXCLUDE_UART6850) && !defined(EXCLUDE_MIDI) +#if defined(CONFIG_UART6850) && defined(CONFIG_MIDI) {"MIDI6850", 0, SNDCARD_UART6850,"6860 UART Midi", attach_uart6850, probe_uart6850, unload_uart6850}, #endif -#ifndef EXCLUDE_SB +#ifdef CONFIG_SB {"SBLAST", 0, SNDCARD_SB, "SoundBlaster", attach_sb_card, probe_sb, unload_sb}, +#ifdef CONFIG_AUDIO + {"SBX", 0, SNDCARD_SB16, "SoundBlaster 16bit", sb16_dsp_init, sb16_dsp_detect, unload_sb16}, #endif -#if !defined(EXCLUDE_SB) && !defined(EXCLUDE_SB16) -#ifndef EXCLUDE_AUDIO - {"SB16", 0, SNDCARD_SB16, "SoundBlaster16", sb16_dsp_init, sb16_dsp_detect, unload_sb16}, +#ifdef CONFIG_MIDI + {"SBMPU", 0, SNDCARD_SB16MIDI,"SB MPU", attach_sb16midi, probe_sb16midi, unload_sb16midi}, #endif -#ifndef EXCLUDE_MIDI - {"SB16MIDI", 0, SNDCARD_SB16MIDI,"SB16 MIDI", attach_sb16midi, probe_sb16midi, unload_sb16midi}, #endif -#endif -#ifndef EXCLUDE_GUS16 +#ifdef CONFIG_GUS16 {"GUS16", 0, SNDCARD_GUS16, "Ultrasound 16-bit opt.", attach_gus_db16, probe_gus_db16, unload_gus_db16}, #endif -#ifndef EXCLUDE_GUS +#ifdef CONFIG_GUS {"GUS", 0, SNDCARD_GUS, "Gravis Ultrasound", attach_gus_card, probe_gus, unload_gus}, #endif -#ifndef EXCLUDE_SSCAPE +#ifdef CONFIG_SSCAPE {"SSCAPE", 0, SNDCARD_SSCAPE, "Ensoniq Soundscape", attach_sscape, probe_sscape, unload_sscape}, {"SSCAPEMSS", 0, SNDCARD_SSCAPE_MSS, "MS Sound System (SoundScape)", attach_ss_ms_sound, probe_ss_ms_sound, unload_ss_ms_sound}, #endif -#ifndef EXCLUDE_TRIX +#ifdef CONFIG_TRIX {"TRXPRO", 0, SNDCARD_TRXPRO, "MediaTriX AudioTriX Pro", attach_trix_wss, probe_trix_wss, unload_trix_wss}, {"TRXPROSB", 0, SNDCARD_TRXPRO_SB, "AudioTriX (SB mode)", attach_trix_sb, probe_trix_sb, unload_trix_sb}, {"TRXPROMPU", 0, SNDCARD_TRXPRO_MPU, "AudioTriX MIDI", attach_trix_mpu, probe_trix_mpu, unload_trix_mpu}, #endif -#ifndef EXCLUDE_PNP +#ifdef CONFIG_PNP {"AD1848", 0, 500, "PnP MSS", attach_pnp_ad1848, probe_pnp_ad1848, unload_pnp_ad1848}, #endif {NULL, 0, 0, "*?*", NULL, NULL, NULL} @@ -360,7 +362,7 @@ */ struct card_info snd_installed_cards[] = { -#ifndef EXCLUDE_PSS +#ifdef CONFIG_PSS {SNDCARD_PSS, {PSS_BASE, 0, -1, -1}, SND_DEFAULT_ENABLE}, # ifdef PSS_MPU_BASE {SNDCARD_PSS_MPU, {PSS_MPU_BASE, PSS_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, @@ -369,7 +371,10 @@ {SNDCARD_PSS_MSS, {PSS_MSS_BASE, PSS_MSS_IRQ, PSS_MSS_DMA, -1}, SND_DEFAULT_ENABLE}, # endif #endif -#ifndef EXCLUDE_TRIX +#ifdef CONFIG_TRIX +#ifndef TRIX_DMA2 +#define TRIX_DMA2 TRIX_DMA +#endif {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, -1}, SND_DEFAULT_ENABLE}, @@ -378,26 +383,32 @@ {SNDCARD_TRXPRO_MPU, {TRIX_MPU_BASE, TRIX_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, # endif #endif -#ifndef EXCLUDE_SSCAPE +#ifdef CONFIG_SSCAPE {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 +#ifdef CONFIG_MAD16 +#ifndef MAD16_DMA2 +#define MAD16_DMA2 MAD16_DMA +#endif {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, -1}, SND_DEFAULT_ENABLE}, # endif #endif -#ifndef EXCLUDE_CS4232 +#ifdef CONFIG_CS4232 +#ifndef CS4232_DMA2 +#define CS4232_DMA2 CS4232_DMA +#endif # 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 -# ifdef PSEUDO_MSS +#ifdef CONFIG_MSS +# ifndef PSEUDO_MSS {SNDCARD_MSS, {MSS_BASE, MSS_IRQ, MSS_DMA, -1}, SND_DEFAULT_ENABLE}, # else {SNDCARD_PSEUDO_MSS, {MSS_BASE, MSS_IRQ, MSS_DMA, -1}, SND_DEFAULT_ENABLE}, @@ -407,21 +418,21 @@ # endif #endif -#ifndef EXCLUDE_PAS +#ifdef CONFIG_PAS {SNDCARD_PAS, {PAS_BASE, PAS_IRQ, PAS_DMA, -1}, SND_DEFAULT_ENABLE}, #endif -#ifndef EXCLUDE_SB +#ifdef CONFIG_SB # ifndef SBC_DMA # define SBC_DMA 1 # endif {SNDCARD_SB, {SBC_BASE, SBC_IRQ, SBC_DMA, -1}, SND_DEFAULT_ENABLE}, #endif -#if !defined(EXCLUDE_MAUI) +#if defined(CONFIG_MAUI) {SNDCARD_MAUI, {MAUI_BASE, MAUI_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, #endif -#if !defined(EXCLUDE_MPU401) && !defined(EXCLUDE_MIDI) +#if defined(CONFIG_MPU401) && defined(CONFIG_MIDI) {SNDCARD_MPU401, {MPU_BASE, MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, #ifdef MPU2_BASE {SNDCARD_MPU401, {MPU2_BASE, MPU2_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, @@ -431,27 +442,30 @@ #endif #endif -#if !defined(EXCLUDE_UART6850) && !defined(EXCLUDE_MIDI) +#if defined(CONFIG_UART6850) && defined(CONFIG_MIDI) {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, -1}, SND_DEFAULT_ENABLE}, +#if defined(CONFIG_SB) +#if defined(CONFIG_AUDIO) && defined(SB_DMA2) + {SNDCARD_SB16, {SBC_BASE, SBC_IRQ, SB_DMA2, -1}, SND_DEFAULT_ENABLE}, #endif -#ifndef EXCLUDE_MIDI - {SNDCARD_SB16MIDI,{SB16MIDI_BASE, SBC_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, +#if defined(CONFIG_MIDI) && defined(SB_MPU_BASE) + {SNDCARD_SB16MIDI,{SB_MPU_BASE, SB_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, #endif #endif -#ifndef EXCLUDE_GUS -#ifndef EXCLUDE_GUS16 +#ifdef CONFIG_GUS +#ifndef GUS_DMA2 +#define GUS_DMA2 GUS_DMA +#endif +#ifdef CONFIG_GUS16 {SNDCARD_GUS16, {GUS16_BASE, GUS16_IRQ, GUS16_DMA, -1}, SND_DEFAULT_ENABLE}, #endif {SNDCARD_GUS, {GUS_BASE, GUS_IRQ, GUS_DMA, GUS_DMA2}, SND_DEFAULT_ENABLE}, #endif -#ifndef EXCLUDE_YM3812 +#ifdef CONFIG_YM3812 {SNDCARD_ADLIB, {FM_MONO, 0, 0, -1}, SND_DEFAULT_ENABLE}, #endif /* Define some expansion space */ @@ -473,8 +487,13 @@ int max_sound_cards = 20; #endif +# ifdef MODULE + int trace_init = 0; +# else + int trace_init = 1; +# endif #else - extern struct audio_operations * audio_devs[MAX_AUDIO_DEV]; int num_audiodevs; + extern struct audio_operations * audio_devs[MAX_AUDIO_DEV]; extern int num_audiodevs; extern struct mixer_operations * mixer_devs[MAX_MIXER_DEV]; extern int num_mixers; extern struct synth_operations * synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV]; extern int num_synths; extern struct midi_operations * midi_devs[MAX_MIDI_DEV]; extern int num_midis; @@ -486,6 +505,8 @@ extern struct card_info snd_installed_cards[]; extern int num_sound_cards; extern int max_sound_cards; + + extern int trace_init; long sndtable_init(long mem_start); int sndtable_get_cardcount (void); diff -u --recursive --new-file v1.3.57/linux/drivers/sound/dmabuf.c linux/drivers/sound/dmabuf.c --- v1.3.57/linux/drivers/sound/dmabuf.c Wed Nov 8 07:11:35 1995 +++ linux/drivers/sound/dmabuf.c Tue Jan 9 00:37:14 1996 @@ -29,16 +29,14 @@ #include "sound_config.h" -#ifdef CONFIGURE_SOUNDCARD +#if defined(CONFIG_AUDIO) || defined(CONFIG_GUS) -#if !defined(EXCLUDE_AUDIO) || !defined(EXCLUDE_GUS) - -static struct wait_queue *in_sleeper[MAX_AUDIO_DEV] = +static wait_handle *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] = +static wait_handle *out_sleeper[MAX_AUDIO_DEV] = {NULL}; static volatile struct snd_wait out_sleep_flag[MAX_AUDIO_DEV] = { @@ -133,6 +131,9 @@ } bsz &= ~0x03; /* Force size which is multiple of 4 bytes */ +#ifdef OS_DMA_ALIGN_CHECK + OS_DMA_ALIGN_CHECK (bsz); +#endif n = dsp_dev->buffsize / bsz; if (n > MAX_SUB_BUFFERS) @@ -158,7 +159,9 @@ out_sleep_flag[dev].mode = WK_NONE; } else - in_sleep_flag[dev].mode = WK_NONE; + { + in_sleep_flag[dev].mode = WK_NONE; + } dmap->flags = DMA_BUSY; /* Other flags off */ dmap->qlen = dmap->qhead = dmap->qtail = 0; @@ -168,6 +171,8 @@ dmap->dma_mode = DMODE_NONE; dmap->mapping_flags = 0; dmap->neutral_byte = 0x00; + dmap->cfrag = -1; + dmap->closing = 0; } static int @@ -262,6 +267,8 @@ } audio_devs[dev]->open_mode = mode; audio_devs[dev]->go = 1; + in_sleep_flag[dev].mode = WK_NONE; + out_sleep_flag[dev].mode = WK_NONE; 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); @@ -335,19 +342,19 @@ save_flags (flags); cli (); - while (!(current->signal & ~current->blocked) - && audio_devs[dev]->dmap_out->qlen) + while (!current_got_fatal_signal () + && audio_devs[dev]->dmap_out->qlen > 1) { { unsigned long tl; - if (10 * HZ) - current->timeout = tl = jiffies + (10 * HZ); + if (HZ) + current_set_timeout (tl = jiffies + (HZ)); else tl = 0xffffffff; out_sleep_flag[dev].mode = WK_SLEEP; - interruptible_sleep_on (&out_sleeper[dev]); + module_interruptible_sleep_on (&out_sleeper[dev]); if (!(out_sleep_flag[dev].mode & WK_WAKEUP)) { if (jiffies >= tl) @@ -372,7 +379,7 @@ cli (); if (audio_devs[dev]->local_qlen) /* Device has hidden buffers */ { - while (!((current->signal & ~current->blocked)) + while (!(current_got_fatal_signal ()) && audio_devs[dev]->local_qlen (dev)) { @@ -380,11 +387,11 @@ unsigned long tl; if (HZ) - current->timeout = tl = jiffies + (HZ); + current_set_timeout (tl = jiffies + (HZ)); else tl = 0xffffffff; out_sleep_flag[dev].mode = WK_SLEEP; - interruptible_sleep_on (&out_sleeper[dev]); + module_interruptible_sleep_on (&out_sleeper[dev]); if (!(out_sleep_flag[dev].mode & WK_WAKEUP)) { if (jiffies >= tl) @@ -404,7 +411,10 @@ { unsigned long flags; - if (!((current->signal & ~current->blocked)) + audio_devs[dev]->dmap_out->closing = 1; + audio_devs[dev]->dmap_in->closing = 1; + + if (!(current_got_fatal_signal ()) && (audio_devs[dev]->dmap_out->dma_mode == DMODE_OUTPUT)) { dma_sync (dev); @@ -412,7 +422,6 @@ save_flags (flags); cli (); - audio_devs[dev]->reset (dev); audio_devs[dev]->close (dev); @@ -485,6 +494,14 @@ save_flags (flags); cli (); +#ifdef ALLOW_BUFFER_MAPPING + if (audio_devs[dev]->dmap_in->mapping_flags & DMA_MAP_MAPPED) + { + printk ("Sound: Can't read from mmapped device (1)\n"); + return -EINVAL; + } + else +#endif if (!dmap->qlen) { int timeout; @@ -520,11 +537,11 @@ unsigned long tl; if (timeout) - current->timeout = tl = jiffies + (timeout); + current_set_timeout (tl = jiffies + (timeout)); else tl = 0xffffffff; in_sleep_flag[dev].mode = WK_SLEEP; - interruptible_sleep_on (&in_sleeper[dev]); + module_interruptible_sleep_on (&in_sleeper[dev]); if (!(in_sleep_flag[dev].mode & WK_WAKEUP)) { if (jiffies >= tl) @@ -536,6 +553,7 @@ { printk ("Sound: DMA (input) timed out - IRQ/DRQ config error?\n"); err = EIO; + audio_devs[dev]->reset (dev); ; } else @@ -559,6 +577,14 @@ int p = dmap->counts[dmap->qhead] + c; +#ifdef ALLOW_BUFFER_MAPPING + if (audio_devs[dev]->dmap_in->mapping_flags & DMA_MAP_MAPPED) + { + printk ("Sound: Can't read from mmapped device (2)\n"); + return -EINVAL; + } + else +#endif if (p >= dmap->fragment_size) { /* This buffer is completely empty */ dmap->counts[dmap->qhead] = 0; @@ -623,6 +649,11 @@ if (count < 2) return -EINVAL; +#ifdef OS_DMA_MINBITS + if (bytes < OS_DMA_MINBITS) + bytes = OS_DMA_MINBITS; +#endif + dmap->fragment_size = (1 << bytes); dmap->max_fragments = count; @@ -739,6 +770,10 @@ if (cmd == SNDCTL_DSP_GETISPACE && audio_devs[dev]->flags & DMA_DUPLEX) dmap = dmap_in; +#ifdef ALLOW_BUFFER_MAPPING + if (dmap->mapping_flags & DMA_MAP_MAPPED) + return -EINVAL; +#endif if (!(dmap->flags & DMA_ALLOC_DONE)) reorganize_buffers (dev, dmap); @@ -758,7 +793,7 @@ { int tmp = audio_devs[dev]->local_qlen (dev); - if (tmp & info->fragments) + if (tmp && info->fragments) tmp--; /* * This buffer has been counted twice */ @@ -809,6 +844,18 @@ activate_recording (dev, dmap_in); } +#ifdef ALLOW_BUFFER_MAPPING + 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); + } +#endif audio_devs[dev]->enable_bits = bits; if (changed && audio_devs[dev]->trigger) @@ -819,6 +866,16 @@ return snd_ioctl_return ((int *) arg, audio_devs[dev]->enable_bits); break; + case SNDCTL_DSP_SETSYNCRO: + + if (!audio_devs[dev]->trigger) + return -EINVAL; + + audio_devs[dev]->trigger (dev, 0); + audio_devs[dev]->go = 0; + return 0; + break; + case SNDCTL_DSP_GETIPTR: { count_info info; @@ -832,6 +889,10 @@ info.bytes += info.ptr; memcpy_tofs ((&((char *) arg)[0]), (char *) &info, sizeof (info)); +#ifdef ALLOW_BUFFER_MAPPING + if (audio_devs[dev]->dmap_in->mapping_flags & DMA_MAP_MAPPED) + audio_devs[dev]->dmap_in->qlen = 0; /* Acknowledge interrupts */ +#endif restore_flags (flags); return 0; } @@ -850,6 +911,10 @@ info.bytes += info.ptr; memcpy_tofs ((&((char *) arg)[0]), (char *) &info, sizeof (info)); +#ifdef ALLOW_BUFFER_MAPPING + if (audio_devs[dev]->dmap_out->mapping_flags & DMA_MAP_MAPPED) + audio_devs[dev]->dmap_out->qlen = 0; /* Acknowledge interrupts */ +#endif restore_flags (flags); return 0; } @@ -879,6 +944,10 @@ { /* OK to start the device */ audio_devs[dev]->go = 1; + + if (audio_devs[dev]->trigger) + audio_devs[dev]->trigger (dev, + audio_devs[dev]->enable_bits * audio_devs[dev]->go); } } @@ -902,7 +971,7 @@ if (audio_devs[dev]->local_qlen) { tmp = audio_devs[dev]->local_qlen (dev); - if (tmp & len) + if (tmp && len) tmp--; /* * This buffer has been counted twice */ @@ -921,6 +990,13 @@ int abort, err = EIO; struct dma_buffparms *dmap = audio_devs[dev]->dmap_out; +#ifdef ALLOW_BUFFER_MAPPING + if (audio_devs[dev]->dmap_out->mapping_flags & DMA_MAP_MAPPED) + { + printk ("Sound: Can't write to mmapped device (3)\n"); + return -EINVAL; + } +#endif if (dmap->dma_mode == DMODE_INPUT) /* Direction change */ { @@ -983,11 +1059,11 @@ unsigned long tl; if (timeout) - current->timeout = tl = jiffies + (timeout); + current_set_timeout (tl = jiffies + (timeout)); else tl = 0xffffffff; out_sleep_flag[dev].mode = WK_SLEEP; - interruptible_sleep_on (&out_sleeper[dev]); + module_interruptible_sleep_on (&out_sleeper[dev]); if (!(out_sleep_flag[dev].mode & WK_WAKEUP)) { if (jiffies >= tl) @@ -1001,8 +1077,9 @@ err = EIO; abort = 1; ; + audio_devs[dev]->reset (dev); } - else if ((current->signal & ~current->blocked)) + else if (current_got_fatal_signal ()) { err = EINTR; abort = 1; @@ -1023,19 +1100,58 @@ } int +DMAbuf_get_curr_buffer (int dev, int *buf_no, char **dma_buf, int *buf_ptr, int *buf_size) +{ + struct dma_buffparms *dmap = audio_devs[dev]->dmap_out; + + if (dmap->cfrag < 0) + return -1; + + *dma_buf = dmap->raw_buf + dmap->qtail * dmap->fragment_size; + *buf_ptr = dmap->counts[dmap->qtail]; + *buf_size = dmap->fragment_size; + return *buf_no = dmap->cfrag; +} + +int +DMAbuf_set_count (int dev, int buff_no, int l) +{ + struct dma_buffparms *dmap = audio_devs[dev]->dmap_out; + + if (buff_no == dmap->qtail) + { + dmap->cfrag = buff_no; + dmap->counts[buff_no] = l; + } + else + dmap->cfrag = -1; + return 0; +} + +int DMAbuf_start_output (int dev, int buff_no, int l) { struct dma_buffparms *dmap = audio_devs[dev]->dmap_out; + dmap->cfrag = -1; /* * Bypass buffering if using mmaped access */ +#ifdef ALLOW_BUFFER_MAPPING + 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 +#else if (dmap != NULL) +#endif { - 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) @@ -1165,12 +1281,43 @@ unsigned long flags; struct dma_buffparms *dmap = audio_devs[dev]->dmap_out; + int p; + dmap->byte_counter += dmap->counts[dmap->qhead]; #ifdef OS_DMA_INTR sound_dma_intr (dev, audio_devs[dev]->dmap_out, audio_devs[dev]->dmachan1); #endif +#ifdef ALLOW_BUFFER_MAPPING + if (dmap->mapping_flags & DMA_MAP_MAPPED) + { + /* mmapped access */ + + 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 +#endif if (event_type != 2) { if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs) @@ -1184,6 +1331,27 @@ dmap->qhead = (dmap->qhead + 1) % dmap->nbufs; dmap->flags &= ~DMA_ACTIVE; + if (event_type == 1 && dmap->qlen < 1) + { + dmap->underrun_count++; + /* Ignore underrun. Just move the tail pointer forward and go */ + if (dmap->closing) + { + audio_devs[dev]->halt_xfer (dev); + } + else + { + dmap->qlen++; + dmap->cfrag = -1; + dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; + + p = dmap->fragment_size * dmap->qhead; + memset (dmap->raw_buf + p, + dmap->neutral_byte, + dmap->fragment_size); + } + } + if (dmap->qlen) { if (!(audio_devs[dev]->flags & DMA_AUTOMODE)) @@ -1198,21 +1366,6 @@ } dmap->flags |= DMA_ACTIVE; } - else if (event_type == 1) - { - dmap->underrun_count++; - 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; - else - dmap->flags &= ~DMA_RESTART; - } } /* event_type != 2 */ save_flags (flags); @@ -1221,7 +1374,7 @@ { { out_sleep_flag[dev].mode = WK_WAKEUP; - wake_up (&out_sleeper[dev]); + module_wake_up (&out_sleeper[dev]); }; } restore_flags (flags); @@ -1239,21 +1392,47 @@ sound_dma_intr (dev, audio_devs[dev]->dmap_in, audio_devs[dev]->dmachan2); #endif +#ifdef ALLOW_BUFFER_MAPPING + 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 +#endif if (dmap->qlen == (dmap->nbufs - 1)) { printk ("Sound: Recording overrun\n"); dmap->underrun_count++; - 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; - else - dmap->flags &= ~DMA_RESTART; + { + /* Force restart on next write */ + 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; + else + dmap->flags &= ~DMA_RESTART; + } } else { @@ -1262,28 +1441,28 @@ printk ("\nSound: Audio queue4 corrupted for dev%d (%d/%d)\n", dev, dmap->qlen, dmap->nbufs); dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; + } - 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, + 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, + if (audio_devs[dev]->trigger) + audio_devs[dev]->trigger (dev, audio_devs[dev]->enable_bits * audio_devs[dev]->go); - } - - dmap->flags |= DMA_ACTIVE; } + dmap->flags |= DMA_ACTIVE; + save_flags (flags); cli (); if ((in_sleep_flag[dev].mode & WK_SLEEP)) { { in_sleep_flag[dev].mode = WK_WAKEUP; - wake_up (&in_sleeper[dev]); + module_wake_up (&in_sleeper[dev]); }; } restore_flags (flags); @@ -1352,7 +1531,7 @@ } int -DMAbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wait) +DMAbuf_select (int dev, struct fileinfo *file, int sel_type, select_table_handle * wait) { struct dma_buffparms *dmap; unsigned long flags; @@ -1362,6 +1541,20 @@ case SEL_IN: dmap = audio_devs[dev]->dmap_in; +#ifdef ALLOW_BUFFER_MAPPING + if (dmap->mapping_flags & DMA_MAP_MAPPED) + { + if (dmap->qlen) + return 1; + + save_flags (flags); + cli (); + in_sleep_flag[dev].mode = WK_SLEEP; + module_select_wait (&in_sleeper[dev], wait); + restore_flags (flags); + return 0; + } +#endif if (dmap->dma_mode != DMODE_INPUT) { @@ -1384,7 +1577,7 @@ save_flags (flags); cli (); in_sleep_flag[dev].mode = WK_SLEEP; - select_wait (&in_sleeper[dev], wait); + module_select_wait (&in_sleeper[dev], wait); restore_flags (flags); return 0; } @@ -1394,6 +1587,20 @@ case SEL_OUT: dmap = audio_devs[dev]->dmap_out; +#ifdef ALLOW_BUFFER_MAPPING + if (dmap->mapping_flags & DMA_MAP_MAPPED) + { + if (dmap->qlen) + return 1; + + save_flags (flags); + cli (); + out_sleep_flag[dev].mode = WK_SLEEP; + module_select_wait (&out_sleeper[dev], wait); + restore_flags (flags); + return 0; + } +#endif if (dmap->dma_mode == DMODE_INPUT) { @@ -1410,7 +1617,7 @@ save_flags (flags); cli (); out_sleep_flag[dev].mode = WK_SLEEP; - select_wait (&out_sleeper[dev], wait); + module_select_wait (&out_sleeper[dev], wait); restore_flags (flags); return 0; } @@ -1425,7 +1632,7 @@ } -#else /* EXCLUDE_AUDIO */ +#else /* CONFIG_AUDIO */ /* * Stub versions if audio services not included */ @@ -1513,6 +1720,4 @@ { return; } -#endif - #endif diff -u --recursive --new-file v1.3.57/linux/drivers/sound/experimental.txt linux/drivers/sound/experimental.txt --- v1.3.57/linux/drivers/sound/experimental.txt Tue Jul 11 10:02:52 1995 +++ linux/drivers/sound/experimental.txt Thu Jan 1 02:00:00 1970 @@ -1,165 +0,0 @@ -This version contains some features which is may NOT be enabled by default. -I'm trying to release an official/reliable version soon so that the -Linux version of Doom (and other games) becomes possible. For that reason -I have disabled some features which are not reliable enough to be -released for wide public. If you are interested to try them, please -read this file carefully. - -1) ECHO PSS (Personal Sound System support) - -This version contains support for soundcards based on the AD20msp614 -chipset made by Analog Devices. This chipset consist of the -AD1848 codec, ADSP-21xx DSP chip and a ESC614 ASIC and is used in some -soundcards made by Orchid, Cardinal, Echo Speech Corporation, Western -Digital and Wearnes Technology. The PSS support is by Marc M. Hoffman -(marc.hoffman@analog.com). I received this stuff about a week ago and -have not been able to test it yet. -If you are interested, remove the B(OPT_PSS) from the DISABLED_OPTIONS -(see above). -You have also to enable the MSS support since I have not integrated -the AD1848 driver with the PSS one yet. - -2) /dev/music (/dev/sequencer2) - -This version has a new device file called /dev/music. I have not -implemented all parts of it but it's there. It's only interesting if -you are writing a sequencer program yourself. Enable by creating -the device file /dev/music. Use the script at the end of linux/Readme - -3) /dev/midi## - -These are tty like raw devices for MIDI ports. Since there is a minor -incompatibility between different versions of Linux, I have disabled -this feature by default. You just need to create the device files yourself. - -4) Support for hardware based u-Law/A-Law and ADPCM formats. - -The AD1848 (and compatibles) are able to do compression and -decompression by hardware. This version has experimental support -for some of them. Currently they are implemented just in the -AD1848 driver. The GUS MAX (and the 16 bit daughtercard) support -also 16->4 bit ADPCM (the IMA one) but it don't work yet. -The argument ioctl(SNDCTL_DSP_SAMPLESIZE) can have some new values -in addition to the 8 and 16 supported earlier. Look at soundcard.h -for more info. -(In case somebody dares to ask: The ASP chip of SB16 is not supported -so the hardware compression/decompression doesn't work with it. Also -the ADPCM format is different than the standard (IMA) one (I guess). -This feature is enabled by default. - -5) Real time fix to /dev/dsp and /dev/audio drivers - -The following feature should help game writers. This stuff is enabled -by default. ----------------- cut here --------------------- -There is a new ioctl called SNDCTL_DSP_SETFRAGMENT. It accepts a -int parameter which has format 0x00nn00ss where the nn is max number of -buffer fragments (between 0x02 and 0xff) and the ss gives indirectly the -size of a buffer fragment (fragment_size = (1 << ss)). Valid sizes are -between (ss=0x07 -> 128 bytes and ss=0x11 (17 dec) -> 128k). - -This ioctl must be used ONCE between open() and first call to -read()/write() or ioctl(SNDCTL_DSP_GETBLKSIZE). - -You need just to force the fragment size to a value which is sufficiently -short (gives the 1/20th of sec with the speed/#channels/#bits you are using). - -Using a small number of fragments offers (I guess) a significant advantage. -For example with 2 fragments the driver works as the following (at least -I hope so). Assuming that the process writes exactly 'fragment_size' of -bytes each time (this is really important). - - 1) When the process writes the first fragment, it will be copied to - the DMA buffer area and the playback begins. The write() returns - immediately and the process is free to continue. - - - 2a) If the fragment gets played before the application writes a new - one, the device will be stoppen and restarted which causes a click. - When the process calls write next time, it will be processes as - in step 1. - - 2b) If the process calls write before the buffer underflows, the - data will be queued and the process is free to continue. (There - is now one full and one partially played fragment in the kernel - buffers. This gives average delay of 1.5*fragment_time (for - example 1/20th sec) before the last byte in the buffer gets played. - - - 3a) If the device gets both fragments played before the next write - (underflow), there will be a click. The write will be processed as - in step 1. - - 3b) If the 1st fragment gets played before next write (the process - calls write during playback of the second fragment), it will be - processed as step 2b. - - 3c) If the process writes 3rd fragment when there is already 2 - fragments in the queue (1 playing and 1 waiting), the process - will block until the 1st fragment gets played. It will then be - woken up and it continues as in step 2b. This means that - the process blocks for at most the time required to play a - buffer fragment. - -This method syncronizes the process and the audio device together -automaticly. The process will block at most the 'fragment_time'. Usually -less, depending on how much it needs time to do other things. The maximum -delay between writing a byte and the time when it finally plays is -at most 3 times the 'fragment_time'. - -The delay depends on how much time the program needs to do it's -computations for the next sample (updating screen etc). If it's about -80% of the 'fragment_time' the game will run almost without delays. If it -uses more time, there is a risk that the audio buffer gets empty. - -The application code should be something like the following: - -int frag = 0x00020008; /* 2 fragments of 2^8=256 bytes */ -int frag_size; - -int fd=open("/dev/dsp"); -ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &frag); -ioctl(NDCTL_DSP_SPEED); /* And #channels & #bits if required */ - -/* - * Query the actual fragment sice since the driver may refuse - * the requested one (unlikely but possible?) - */ - -ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &frag_size); - -while(True) -{ - do_computations(); - write(fd, buf, frag_size); /* Always the same size!!!!!!! */ -} - -I have tested this with a modified version of str.c. The algorithm works -as long as the playing program gets enough time to run. Hitting ENTER on -another virtual console causes a pause/click (with 2 frags of 64 bytes). - -NOTE! It's important to know that this call may be called just once and -it must be done immediately after open(). The fragment size will remain -in effect until the device is closed. -------------------- cut here --------------------- - -6) Detection and initialization code for Ensoniq Soundscape - -This version is able to initialize SoundScape (almost). However -PCM recording and playback don't work. Also MIDI playback sounds wierd -since the driver is not able to set volume controls properly. -The soundscape support is disabled. You need to enable it by editing -beginning of configure.c. Also read comments in sndscape/README. - -7) select() support for /dev/audio and /dev/dsp. (/dev/midi## and - /dev/sequencer had it already in v2.90). - -There is now select() support in the audio/dsp driver (for Linux only). -However I have not tried this feature yet. -There are also some new ioctl() calls (please look at soundcard.h). - -8) MIDI recording in /dev/music (/dev/sequencer2) - -MIDI recording was earlier implemented only with full MPU-401 devices. -This version has it also for dumb MIDI ports. However I have not tested it -yet. diff -u --recursive --new-file v1.3.57/linux/drivers/sound/gus_card.c linux/drivers/sound/gus_card.c --- v1.3.57/linux/drivers/sound/gus_card.c Wed Nov 8 07:11:35 1995 +++ linux/drivers/sound/gus_card.c Tue Jan 9 00:37:14 1996 @@ -29,7 +29,7 @@ #include "sound_config.h" -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_GUS) +#if defined(CONFIG_GUS) #include "gus_hw.h" @@ -64,7 +64,7 @@ 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 +#ifdef CONFIG_MIDI mem_start = gus_midi_init (mem_start); #endif return mem_start; @@ -93,7 +93,7 @@ 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 +#ifdef CONFIG_MIDI mem_start = gus_midi_init (mem_start); #endif return mem_start; @@ -166,7 +166,7 @@ sti (); -#ifndef EXCLUDE_GUSMAX +#ifdef CONFIG_GUSMAX if (have_gus_max) ad1848_interrupt (irq, NULL); #endif @@ -183,16 +183,19 @@ if (src & (MIDI_TX_IRQ | MIDI_RX_IRQ)) { -#ifndef EXCLUDE_MIDI +#ifdef CONFIG_MIDI gus_midi_interrupt (0); #endif } if (src & (GF1_TIMER1_IRQ | GF1_TIMER2_IRQ)) { -#ifndef EXCLUDE_SEQUENCER +#ifdef CONFIG_SEQUENCER if (gus_timer_enabled) - sound_timer_interrupt (); + { + sound_timer_interrupt (); + } + gus_write8 (0x45, 0); /* Ack IRQ */ gus_timer_command (4, 0x80); /* Reset IRQ flags */ @@ -213,7 +216,7 @@ /* * Some extra code for the 16 bit sampling option */ -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_GUS16) +#if defined(CONFIG_GUS16) int probe_gus_db16 (struct address_info *hw_config) @@ -224,8 +227,10 @@ long attach_gus_db16 (long mem_start, struct address_info *hw_config) { +#ifdef CONFIG_GUS gus_pcm_volume = 100; gus_wave_volume = 90; +#endif ad1848_init ("GUS 16 bit sampling", hw_config->io_base, hw_config->irq, diff -u --recursive --new-file v1.3.57/linux/drivers/sound/gus_midi.c linux/drivers/sound/gus_midi.c --- v1.3.57/linux/drivers/sound/gus_midi.c Wed Nov 8 07:11:35 1995 +++ linux/drivers/sound/gus_midi.c Tue Jan 9 00:37:15 1996 @@ -29,11 +29,9 @@ #include "sound_config.h" -#ifdef CONFIGURE_SOUNDCARD - #include "gus_hw.h" -#if !defined(EXCLUDE_GUS) && !defined(EXCLUDE_MIDI) +#if defined(CONFIG_GUS) && defined(CONFIG_MIDI) static int midi_busy = 0, input_opened = 0; static int my_dev; @@ -75,14 +73,8 @@ input_opened = 1; } - if (mode == OPEN_WRITE || mode == OPEN_READWRITE) - { - gus_midi_control |= MIDI_ENABLE_XMIT; - } - outb (gus_midi_control, u_MidiControl); /* - * Enable - */ + outb (gus_midi_control, u_MidiControl); /* Enable */ midi_busy = 1; qlen = qhead = qtail = output_used = 0; @@ -276,37 +268,37 @@ save_flags (flags); cli (); - stat = GUS_MIDI_STATUS (); - - if (stat & MIDI_RCV_FULL) + while ((stat = GUS_MIDI_STATUS ()) & (MIDI_RCV_FULL | MIDI_XMIT_EMPTY)) { - data = inb (u_MidiData); - if (input_opened) - midi_input_intr (my_dev, data); - } - - if (stat & MIDI_XMIT_EMPTY) - { - while (qlen && dump_to_midi (tmp_queue[qhead])) + if (stat & MIDI_RCV_FULL) { - qlen--; - qhead++; + data = inb (u_MidiData); + if (input_opened) + midi_input_intr (my_dev, data); } - if (!qlen) + if (stat & MIDI_XMIT_EMPTY) { - /* - * Disable Midi output interrupts, since no data in the buffer - */ - gus_midi_control &= ~MIDI_ENABLE_XMIT; - outb (gus_midi_control, u_MidiControl); + while (qlen && dump_to_midi (tmp_queue[qhead])) + { + qlen--; + qhead++; + } + + if (!qlen) + { + /* + * 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); + } } - } + } restore_flags (flags); } - -#endif #endif diff -u --recursive --new-file v1.3.57/linux/drivers/sound/gus_vol.c linux/drivers/sound/gus_vol.c --- v1.3.57/linux/drivers/sound/gus_vol.c Fri Oct 13 14:44:34 1995 +++ linux/drivers/sound/gus_vol.c Tue Jan 9 00:37:15 1996 @@ -4,7 +4,7 @@ * Greg Lee 1993. */ #include "sound_config.h" -#ifndef EXCLUDE_GUS +#ifdef CONFIG_GUS #include "gus_linearvol.h" #define GUS_VOLUME gus_wave_volume diff -u --recursive --new-file v1.3.57/linux/drivers/sound/gus_wave.c linux/drivers/sound/gus_wave.c --- v1.3.57/linux/drivers/sound/gus_wave.c Wed Nov 8 07:11:36 1995 +++ linux/drivers/sound/gus_wave.c Tue Jan 9 00:37:19 1996 @@ -31,7 +31,7 @@ #include #include "gus_hw.h" -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_GUS) +#if defined(CONFIG_GUS) #define MAX_SAMPLE 150 #define MAX_PATCH 256 @@ -112,7 +112,7 @@ static int gus_sampling_channels; static int gus_sampling_bits; -static struct wait_queue *dram_sleeper = NULL; +static wait_handle *dram_sleeper = NULL; static volatile struct snd_wait dram_sleep_flag = {0}; @@ -1734,11 +1734,11 @@ unsigned long tl; if (HZ) - current->timeout = tl = jiffies + (HZ); + current_set_timeout (tl = jiffies + (HZ)); else tl = 0xffffffff; dram_sleep_flag.mode = WK_SLEEP; - interruptible_sleep_on (&dram_sleeper); + module_interruptible_sleep_on (&dram_sleeper); if (!(dram_sleep_flag.mode & WK_WAKEUP)) { if (jiffies >= tl) @@ -2829,7 +2829,7 @@ SOUND_MASK_SYNTH|SOUND_MASK_PCM) if (((cmd >> 8) & 0xff) == 'M') { - if (cmd & IOC_IN) + if (_IOC_DIR (cmd) & _IOC_WRITE) switch (cmd & 0xff) { case SOUND_MIXER_RECSRC: @@ -3052,7 +3052,7 @@ model_num = "MAX"; gus_type = 0x40; mixer_type = CS4231; -#ifndef EXCLUDE_GUSMAX +#ifdef CONFIG_GUSMAX { unsigned char max_config = 0x40; /* Codec enable */ @@ -3098,10 +3098,8 @@ */ } - - printk (" ", model_num, (int) gus_mem_size / 1024); - sprintf (gus_info.name, "Gravis UltraSound %s (%dk)", model_num, (int) gus_mem_size / 1024); + conf_printf (gus_info.name, hw_config); if (num_synths >= MAX_SYNTH_DEV) printk ("GUS Error: Too many synthesizers\n"); @@ -3109,7 +3107,7 @@ { voice_alloc = &guswave_operations.alloc; synth_devs[num_synths++] = &guswave_operations; -#ifndef EXCLUDE_SEQUENCER +#ifdef CONFIG_SEQUENCER gus_tmr_install (gus_base + 8); #endif } @@ -3157,7 +3155,7 @@ void gus_wave_unload (void) { -#ifndef EXCLUDE_GUSMAX +#ifdef CONFIG_GUSMAX if (have_gus_max) { ad1848_unload (gus_base + 0x10c, @@ -3389,7 +3387,7 @@ if ((dram_sleep_flag.mode & WK_SLEEP)) { dram_sleep_flag.mode = WK_WAKEUP; - wake_up (&dram_sleeper); + module_wake_up (&dram_sleeper); }; break; @@ -3426,7 +3424,7 @@ } -#ifndef EXCLUDE_SEQUENCER +#ifdef CONFIG_SEQUENCER /* * Timer stuff */ @@ -3469,7 +3467,7 @@ gus_timer_command (0x04, 0x02); /* Start timer 2 */ } - gus_timer_enabled = 0; + gus_timer_enabled = 1; } static unsigned int @@ -3510,6 +3508,7 @@ gus_write8 (0x45, 0x04); /* Start timer 1 again */ else gus_write8 (0x45, 0x08); /* Start timer 2 again */ + gus_timer_enabled = 1; } static struct sound_lowlev_timer gus_tmr = diff -u --recursive --new-file v1.3.57/linux/drivers/sound/ics2101.c linux/drivers/sound/ics2101.c --- v1.3.57/linux/drivers/sound/ics2101.c Wed Nov 8 07:11:36 1995 +++ linux/drivers/sound/ics2101.c Tue Jan 9 00:37:20 1996 @@ -28,7 +28,7 @@ */ #include "sound_config.h" -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_GUS) +#if defined(CONFIG_GUS) #include #include "gus_hw.h" @@ -134,7 +134,7 @@ { if (((cmd >> 8) & 0xff) == 'M') { - if (cmd & IOC_IN) + if (_IOC_DIR (cmd) & _IOC_WRITE) switch (cmd & 0xff) { case SOUND_MIXER_RECSRC: diff -u --recursive --new-file v1.3.57/linux/drivers/sound/mad16.c linux/drivers/sound/mad16.c --- v1.3.57/linux/drivers/sound/mad16.c Fri Oct 13 14:44:34 1995 +++ linux/drivers/sound/mad16.c Tue Jan 9 00:37:20 1996 @@ -72,7 +72,7 @@ #include "sound_config.h" -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_MAD16) +#if defined(CONFIG_MAD16) static int already_initialized = 0; @@ -451,7 +451,7 @@ { if (board_type < C929) /* Early chip. No MPU support. Just SB MIDI */ { -#ifndef EXCLUDE_MIDI +#ifdef CONFIG_MIDI if (mad_read (MC1_PORT) & 0x20) hw_config->io_base = 0x240; @@ -464,7 +464,7 @@ #endif } -#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI) +#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI) if (!already_initialized) return mem_start; @@ -477,7 +477,7 @@ int probe_mad16_mpu (struct address_info *hw_config) { -#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI) +#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI) static int mpu_attached = 0; static int valid_ports[] = {0x330, 0x320, 0x310, 0x300}; @@ -497,7 +497,7 @@ if (board_type < C929) /* Early chip. No MPU support. Just SB MIDI */ { -#ifndef EXCLUDE_MIDI +#ifdef CONFIG_MIDI unsigned char tmp; tmp = mad_read (MC3_PORT); @@ -597,7 +597,15 @@ void unload_mad16_mpu (struct address_info *hw_config) { -#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI) +#ifdef CONFIG_MIDI + if (board_type < C929) /* Early chip. No MPU support. Just SB MIDI */ + { + mad16_sb_dsp_unload (hw_config); + return; + } +#endif + +#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI) unload_mpu401 (hw_config); #endif } diff -u --recursive --new-file v1.3.57/linux/drivers/sound/mad16_sb_midi.c linux/drivers/sound/mad16_sb_midi.c --- v1.3.57/linux/drivers/sound/mad16_sb_midi.c Wed Nov 8 07:11:36 1995 +++ linux/drivers/sound/mad16_sb_midi.c Tue Jan 9 00:37:21 1996 @@ -29,7 +29,7 @@ #include "sound_config.h" -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_MAD16) && !defined(EXCLUDE_MIDI) +#if defined(CONFIG_MAD16) && defined(CONFIG_MIDI) #define sbc_base mad16_sb_base #include "sb.h" @@ -39,6 +39,7 @@ static int mad16_sb_base = 0x220; static int mad16_sb_irq = 0; static int mad16_sb_dsp_ok = 0; +static int mad16_sb_dsp_attached = 0; static sound_os_info *midi_osp; int mad16_sb_midi_mode = NORMAL_MIDI; @@ -111,11 +112,11 @@ int loopc; outb (1, DSP_RESET); - tenmicrosec (); + tenmicrosec (midi_osp); outb (0, DSP_RESET); - tenmicrosec (); - tenmicrosec (); - tenmicrosec (); + tenmicrosec (midi_osp); + tenmicrosec (midi_osp); + tenmicrosec (midi_osp); for (loopc = 0; loopc < 1000 && !(inb (DSP_DATA_AVAIL) & 0x80); loopc++); /* * Wait @@ -165,6 +166,7 @@ * mad16_sb_midi_init -- everything else is done elsewhere */ { + mad16_sb_dsp_attached = 1; midi_osp = hw_config->osp; if (snd_set_irq_handler (mad16_sb_irq, mad16_sbintr, "MAD16 SB MIDI", midi_osp) < 0) { @@ -174,11 +176,21 @@ request_region (hw_config->io_base, 16, "mad16/Mozart MIDI"); - printk (" "); + conf_printf ("MAD16 MIDI (SB mode)", hw_config); mad16_sb_midi_init (2); mad16_sb_dsp_ok = 1; return mem_start; +} + +void +mad16_sb_dsp_unload (struct address_info *hw_config) +{ + if (!mad16_sb_dsp_attached) + return; + + release_region (hw_config->io_base, 16); + snd_release_irq (hw_config->irq); } static int diff -u --recursive --new-file v1.3.57/linux/drivers/sound/maui.c linux/drivers/sound/maui.c --- v1.3.57/linux/drivers/sound/maui.c Wed Nov 8 07:11:36 1995 +++ linux/drivers/sound/maui.c Tue Jan 9 00:37:21 1996 @@ -32,7 +32,7 @@ #include "sound_config.h" -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_MAUI) +#if defined(CONFIG_MAUI) static int maui_base = 0x330; @@ -191,13 +191,16 @@ return 0; } - printk ("WaveFront hardware version %d.%d\n", tmp1, tmp2); + if (trace_init) + 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 (trace_init) + printk ("WaveFront firmware version %d.%d\n", tmp1, tmp2); if (!maui_write (0x85)) /* Report free DRAM */ return 0; @@ -206,7 +209,8 @@ { tmp1 |= maui_read () << (7 * i); } - printk ("Available DRAM %dk\n", tmp1 / 1024); + if (trace_init) + printk ("Available DRAM %dk\n", tmp1 / 1024); request_region (hw_config->io_base + 2, 6, "Maui"); @@ -222,7 +226,7 @@ { int this_dev = num_midis; - printk (" "); + conf_printf ("Maui", hw_config); hw_config->irq *= -1; mem_start = attach_mpu401 (mem_start, hw_config); diff -u --recursive --new-file v1.3.57/linux/drivers/sound/midi_synth.c linux/drivers/sound/midi_synth.c --- v1.3.57/linux/drivers/sound/midi_synth.c Wed Nov 8 07:11:36 1995 +++ linux/drivers/sound/midi_synth.c Tue Jan 9 00:37:22 1996 @@ -32,11 +32,11 @@ #include "sound_config.h" -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_MIDI) +#if defined(CONFIG_MIDI) #define _MIDI_SYNTH_C_ -static struct wait_queue *sysex_sleeper = NULL; +static wait_handle *sysex_sleeper = NULL; static volatile struct snd_wait sysex_sleep_flag = {0}; @@ -47,7 +47,7 @@ {0}; static unsigned char prev_out_status[MAX_MIDI_DEV]; -#ifdef EXCLUDE_SEQUENCER +#ifndef CONFIG_SEQUENCER #define STORE(cmd) #else #define STORE(cmd) \ @@ -472,6 +472,8 @@ inc->m_prev_status = 0x00; restore_flags (flags); + sysex_sleep_flag.mode = WK_NONE; + return 1; } @@ -545,7 +547,7 @@ sysex_sleep_flag.mode = WK_NONE; - for (i = 0; i < left && !(current->signal & ~current->blocked); i++) + for (i = 0; i < left && !current_got_fatal_signal (); i++) { unsigned char data; @@ -566,17 +568,17 @@ } while (!midi_devs[orig_dev]->putc (orig_dev, (unsigned char) (data & 0xff)) && - !(current->signal & ~current->blocked)) + !current_got_fatal_signal ()) { unsigned long tl; if (1) - current->timeout = tl = jiffies + (1); + current_set_timeout (tl = jiffies + (1)); else tl = 0xffffffff; sysex_sleep_flag.mode = WK_SLEEP; - interruptible_sleep_on (&sysex_sleeper); + module_interruptible_sleep_on (&sysex_sleeper); if (!(sysex_sleep_flag.mode & WK_WAKEUP)) { if (jiffies >= tl) @@ -638,8 +640,8 @@ int orig_dev = synth_devs[dev]->midi_dev; int chn, msg; - if (ctrl_num < 1 || ctrl_num > 127) - return; /* NOTE! Controller # 0 ignored */ + if (ctrl_num < 0 || ctrl_num > 127) + return; if (channel < 0 || channel > 15) return; diff -u --recursive --new-file v1.3.57/linux/drivers/sound/midi_synth.h linux/drivers/sound/midi_synth.h --- v1.3.57/linux/drivers/sound/midi_synth.h Fri Oct 13 14:44:34 1995 +++ linux/drivers/sound/midi_synth.h Tue Jan 9 00:36:54 1996 @@ -15,7 +15,6 @@ int midi_synth_patchmgr (int dev, struct patmgr_info *rec); 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_ diff -u --recursive --new-file v1.3.57/linux/drivers/sound/midibuf.c linux/drivers/sound/midibuf.c --- v1.3.57/linux/drivers/sound/midibuf.c Wed Nov 8 07:11:36 1995 +++ linux/drivers/sound/midibuf.c Tue Jan 9 00:37:23 1996 @@ -29,7 +29,7 @@ #include "sound_config.h" -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_MIDI) +#if defined(CONFIG_MIDI) /* * Don't make MAX_QUEUE_SIZE larger than 4000 @@ -37,12 +37,12 @@ #define MAX_QUEUE_SIZE 4000 -static struct wait_queue *midi_sleeper[MAX_MIDI_DEV] = +static wait_handle *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] = +static wait_handle *input_sleeper[MAX_MIDI_DEV] = {NULL}; static volatile struct snd_wait input_sleep_flag[MAX_MIDI_DEV] = { @@ -106,18 +106,18 @@ */ if (midi_devs[dev]->buffer_status != NULL) - while (!(current->signal & ~current->blocked) && + while (!current_got_fatal_signal () && midi_devs[dev]->buffer_status (dev)) { unsigned long tl; if (HZ / 10) - current->timeout = tl = jiffies + (HZ / 10); + current_set_timeout (tl = jiffies + (HZ / 10)); else tl = 0xffffffff; midi_sleep_flag[dev].mode = WK_SLEEP; - interruptible_sleep_on (&midi_sleeper[dev]); + module_interruptible_sleep_on (&midi_sleeper[dev]); if (!(midi_sleep_flag[dev].mode & WK_WAKEUP)) { if (jiffies >= tl) @@ -146,7 +146,7 @@ if ((input_sleep_flag[dev].mode & WK_SLEEP)) { input_sleep_flag[dev].mode = WK_WAKEUP; - wake_up (&input_sleeper[dev]); + module_wake_up (&input_sleeper[dev]); }; } @@ -185,7 +185,7 @@ (midi_sleep_flag[dev].mode & WK_SLEEP)) { midi_sleep_flag[dev].mode = WK_WAKEUP; - wake_up (&midi_sleeper[dev]); + module_wake_up (&midi_sleeper[dev]); }; } @@ -203,7 +203,6 @@ MIDIbuf_open (int dev, struct fileinfo *file) { int mode, err; - unsigned long flags; dev = dev >> 4; mode = file->mode & O_ACCMODE; @@ -224,27 +223,20 @@ * Interrupts disabled. Be careful */ - save_flags (flags); - cli (); if ((err = midi_devs[dev]->open (dev, mode, midi_input_intr, midi_output_intr)) < 0) { - restore_flags (flags); return err; } parms[dev].prech_timeout = 0; - midi_sleep_flag[dev].mode = WK_NONE; - input_sleep_flag[dev].mode = WK_NONE; - midi_in_buf[dev] = (struct midi_buf *) kmalloc (sizeof (struct midi_buf), GFP_KERNEL); if (midi_in_buf[dev] == NULL) { printk ("midi: Can't allocate buffer\n"); midi_devs[dev]->close (dev); - restore_flags (flags); return -EIO; } midi_in_buf[dev]->len = midi_in_buf[dev]->head = midi_in_buf[dev]->tail = 0; @@ -257,20 +249,23 @@ midi_devs[dev]->close (dev); kfree (midi_in_buf[dev]); midi_in_buf[dev] = NULL; - restore_flags (flags); return -EIO; } midi_out_buf[dev]->len = midi_out_buf[dev]->head = midi_out_buf[dev]->tail = 0; - if (!open_devs) + open_devs++; + midi_sleep_flag[dev].mode = WK_NONE; + input_sleep_flag[dev].mode = WK_NONE; + + if (open_devs < 2) /* This was first open */ { - poll_timer.expires = (1) + jiffies; - add_timer (&poll_timer); - }; /* - * Come back later - */ - open_devs++; - restore_flags (flags); + ; + + { + poll_timer.expires = (1) + jiffies; + add_timer (&poll_timer); + }; /* Start polling */ + } return err; } @@ -284,6 +279,9 @@ dev = dev >> 4; mode = file->mode & O_ACCMODE; + if (dev < 0 || dev >= num_midis) + return; + save_flags (flags); cli (); @@ -298,18 +296,18 @@ * devices */ - while (!(current->signal & ~current->blocked) && + while (!current_got_fatal_signal () && DATA_AVAIL (midi_out_buf[dev])) { unsigned long tl; if (0) - current->timeout = tl = jiffies + (0); + current_set_timeout (tl = jiffies + (0)); else tl = 0xffffffff; midi_sleep_flag[dev].mode = WK_SLEEP; - interruptible_sleep_on (&midi_sleeper[dev]); + module_interruptible_sleep_on (&midi_sleeper[dev]); if (!(midi_sleep_flag[dev].mode & WK_WAKEUP)) { if (jiffies >= tl) @@ -325,14 +323,17 @@ */ } + restore_flags (flags); + midi_devs[dev]->close (dev); + kfree (midi_in_buf[dev]); kfree (midi_out_buf[dev]); midi_in_buf[dev] = NULL; midi_out_buf[dev] = NULL; + if (open_devs < 2) + del_timer (&poll_timer);; open_devs--; - del_timer (&poll_timer);; - restore_flags (flags); } int @@ -365,11 +366,11 @@ unsigned long tl; if (0) - current->timeout = tl = jiffies + (0); + current_set_timeout (tl = jiffies + (0)); else tl = 0xffffffff; midi_sleep_flag[dev].mode = WK_SLEEP; - interruptible_sleep_on (&midi_sleeper[dev]); + module_interruptible_sleep_on (&midi_sleeper[dev]); if (!(midi_sleep_flag[dev].mode & WK_WAKEUP)) { if (jiffies >= tl) @@ -377,7 +378,7 @@ } midi_sleep_flag[dev].mode &= ~WK_SLEEP; }; - if ((current->signal & ~current->blocked)) + if (current_got_fatal_signal ()) { restore_flags (flags); return -EINTR; @@ -424,11 +425,11 @@ unsigned long tl; if (parms[dev].prech_timeout) - current->timeout = tl = jiffies + (parms[dev].prech_timeout); + current_set_timeout (tl = jiffies + (parms[dev].prech_timeout)); else tl = 0xffffffff; input_sleep_flag[dev].mode = WK_SLEEP; - interruptible_sleep_on (&input_sleeper[dev]); + module_interruptible_sleep_on (&input_sleeper[dev]); if (!(input_sleep_flag[dev].mode & WK_WAKEUP)) { if (jiffies >= tl) @@ -436,7 +437,7 @@ } input_sleep_flag[dev].mode &= ~WK_SLEEP; }; - if ((current->signal & ~current->blocked)) + if (current_got_fatal_signal ()) c = -EINTR; /* * The user is getting restless */ @@ -501,7 +502,7 @@ } int -MIDIbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wait) +MIDIbuf_select (int dev, struct fileinfo *file, int sel_type, select_table_handle * wait) { dev = dev >> 4; @@ -511,7 +512,7 @@ if (!DATA_AVAIL (midi_in_buf[dev])) { input_sleep_flag[dev].mode = WK_SLEEP; - select_wait (&input_sleeper[dev], wait); + module_select_wait (&input_sleeper[dev], wait); return 0; } return 1; @@ -521,7 +522,7 @@ if (SPACE_AVAIL (midi_out_buf[dev])) { midi_sleep_flag[dev].mode = WK_SLEEP; - select_wait (&midi_sleeper[dev], wait); + module_select_wait (&midi_sleeper[dev], wait); return 0; } return 1; diff -u --recursive --new-file v1.3.57/linux/drivers/sound/mpu401.c linux/drivers/sound/mpu401.c --- v1.3.57/linux/drivers/sound/mpu401.c Wed Nov 8 07:11:36 1995 +++ linux/drivers/sound/mpu401.c Tue Jan 9 00:37:25 1996 @@ -35,14 +35,12 @@ #include "sound_config.h" -#ifdef CONFIGURE_SOUNDCARD - -#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI) +#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI) #include "coproc.h" static int init_sequence[20]; /* NOTE! pos 0 = len, start pos 1. */ -#ifndef EXCLUDE_SEQUENCER +#ifdef CONFIG_SEQUENCER static int timer_mode = TMR_INTERNAL, timer_caps = TMR_INTERNAL; #endif @@ -122,7 +120,7 @@ static void timer_ext_event (struct mpu_config *devc, int event, int parm); static struct synth_info mpu_synth_info_proto = -{"MPU-401 MIDI interface", 0, SYNTH_TYPE_MIDI, 0, 0, 128, 0, 128, SYNTH_CAP_INPUT}; +{"MPU-401 MIDI interface", 0, SYNTH_TYPE_MIDI, MIDI_TYPE_MPU401, 0, 128, 0, 128, SYNTH_CAP_INPUT}; static struct synth_info mpu_synth_info[MAX_MIDI_DEV]; @@ -153,7 +151,7 @@ 0 /* Fx */ }; -#ifdef EXCLUDE_SEQUENCER +#ifndef CONFIG_SEQUENCER #define STORE(cmd) #else #define STORE(cmd) \ @@ -576,11 +574,11 @@ devc = &dev_conf[dev]; /* - * Sometimes it takes about 13000 loops before the output becomes ready + * Sometimes it takes about 30000 loops before the output becomes ready * (After reset). Normally it takes just about 10 loops. */ - for (timeout = 3000; timeout > 0 && !output_ready (devc); timeout--); + for (timeout = 30000; timeout > 0 && !output_ready (devc); timeout--); save_flags (flags); cli (); @@ -919,6 +917,7 @@ { mpu_cmd (midi_dev, 0x8B, 0); /* Enable data in stop mode */ mpu_cmd (midi_dev, 0x34, 0); /* Return timing bytes in stop mode */ + mpu_cmd (midi_dev, 0x87, 0); /* Enable pitch & controller */ } return 0; @@ -1129,9 +1128,6 @@ MPU_CAP_CLS | MPU_CAP_2PORT; revision_char = (devc->revision == 0x7f) ? 'M' : ' '; - printk (" ", - ports, - revision_char); sprintf (mpu_synth_info[num_midis].name, "MQX-%d%c MIDI Interface #%d", ports, @@ -1147,10 +1143,6 @@ devc->capabilities |= MPU_CAP_SYNC | MPU_CAP_FSK; - printk (" ", - (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", (int) (devc->version & 0xf0) >> 4, @@ -1162,6 +1154,8 @@ strcpy (mpu401_midi_operations[num_midis].info.name, mpu_synth_info[num_midis].name); + conf_printf (mpu_synth_info[num_midis].name, hw_config); + mpu401_synth_operations[num_midis]->midi_dev = devc->devno = num_midis; mpu401_synth_operations[devc->devno]->info = &mpu_synth_info[devc->devno]; @@ -1273,7 +1267,7 @@ tmp_devc.opened = 0; tmp_devc.osp = hw_config->osp; -#if !defined(EXCLUDE_AEDSP16) && defined(AEDSP16_MPU401) +#if defined(CONFIG_AEDSP16) && defined(AEDSP16_MPU401) /* * Initialize Audio Excel DSP 16 to MPU-401, before any operation. */ @@ -1311,7 +1305,7 @@ * Timer stuff ****************************************************/ -#if !defined(EXCLUDE_SEQUENCER) +#if defined(CONFIG_SEQUENCER) static volatile int timer_initialized = 0, timer_open = 0, tmr_running = 0; static volatile int curr_tempo, curr_timebase, hw_timebase; @@ -1827,7 +1821,5 @@ #endif - -#endif #endif diff -u --recursive --new-file v1.3.57/linux/drivers/sound/opl3.c linux/drivers/sound/opl3.c --- v1.3.57/linux/drivers/sound/opl3.c Wed Nov 8 07:11:36 1995 +++ linux/drivers/sound/opl3.c Tue Jan 9 00:37:27 1996 @@ -36,7 +36,7 @@ #include "sound_config.h" -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_YM3812) +#if defined(CONFIG_YM3812) #include "opl3.h" @@ -226,7 +226,7 @@ */ for (i = 0; i < 50; i++) - tenmicrosec (); + tenmicrosec (devc->osp); stat2 = inb (ioaddr); /* * Read status after timers have expired @@ -281,18 +281,18 @@ int tmp; outb (0x02, ioaddr - 8); /* Select OPL4 ID register */ - tenmicrosec (); + tenmicrosec (devc->osp); tmp = inb (ioaddr - 7); /* Read it */ - tenmicrosec (); + tenmicrosec (devc->osp); if (tmp == 0x20) /* OPL4 should return 0x20 here */ { detected_model = 4; outb (0xF8, ioaddr - 8); /* Select OPL4 FM mixer control */ - tenmicrosec (); + tenmicrosec (devc->osp); outb (0x1B, ioaddr - 7); /* Write value */ - tenmicrosec (); + tenmicrosec (devc->osp); } else detected_model = 3; @@ -775,7 +775,7 @@ outb ((unsigned char) (addr & 0xff), io_addr); if (!devc->model != 2) - tenmicrosec (); + tenmicrosec (devc->osp); else for (i = 0; i < 2; i++) inb (io_addr); @@ -784,9 +784,9 @@ if (devc->model != 2) { - tenmicrosec (); - tenmicrosec (); - tenmicrosec (); + tenmicrosec (devc->osp); + tenmicrosec (devc->osp); + tenmicrosec (devc->osp); } else for (i = 0; i < 2; i++) @@ -1222,9 +1222,9 @@ if (devc->model == 2) { if (devc->is_opl4) - printk (" "); + conf_printf2 ("Yamaha OPL4/OPL3 FM", ioaddr, 0, -1, -1); else - printk (" "); + conf_printf2 ("Yamaha OPL3 FM", ioaddr, 0, -1, -1); devc->v_alloc->max_voice = devc->nr_voice = 18; devc->fm_info.nr_drums = 0; @@ -1242,7 +1242,7 @@ } else { - printk (" "); + conf_printf2 ("Yamaha OPL2 FM", ioaddr, 0, -1, -1); devc->v_alloc->max_voice = devc->nr_voice = 9; devc->fm_info.nr_drums = 0; diff -u --recursive --new-file v1.3.57/linux/drivers/sound/os.h linux/drivers/sound/os.h --- v1.3.57/linux/drivers/sound/os.h Sat Nov 11 17:41:33 1995 +++ linux/drivers/sound/os.h Tue Jan 9 00:36:59 1996 @@ -1,7 +1,18 @@ + #define ALLOW_SELECT -#undef ALLOW_BUFFER_MAPPING #undef NO_INLINE_ASM -#undef SHORT_BANNERS +#define SHORT_BANNERS + +#include + +#ifdef MODULE +#define __NO_VERSION__ +#include +#include +#ifdef MODVERSIONS +#include +#endif +#endif #include #include @@ -22,6 +33,7 @@ #include #include +#include #include @@ -46,3 +58,5 @@ extern int sound_num_blocks; typedef int sound_os_info; + +#undef PSEUDO_DMA_AUTOINIT diff -u --recursive --new-file v1.3.57/linux/drivers/sound/pas2_card.c linux/drivers/sound/pas2_card.c --- v1.3.57/linux/drivers/sound/pas2_card.c Wed Nov 8 07:11:36 1995 +++ linux/drivers/sound/pas2_card.c Tue Jan 9 00:37:28 1996 @@ -30,7 +30,7 @@ #include "sound_config.h" -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_PAS) +#if defined(CONFIG_PAS) #define DEFINE_TRANSLATIONS #include "pas.h" @@ -93,14 +93,14 @@ if (status & I_S_PCM_SAMPLE_BUFFER_IRQ) { -#ifndef EXCLUDE_AUDIO +#ifdef CONFIG_AUDIO pas_pcm_interrupt (status, 1); #endif status &= ~I_S_PCM_SAMPLE_BUFFER_IRQ; } if (status & I_S_MIDI_IRQ) { -#ifndef EXCLUDE_MIDI +#ifdef CONFIG_MIDI pas_midi_interrupt (); #endif status &= ~I_S_MIDI_IRQ; @@ -259,7 +259,7 @@ mix_write (P_M_MV508_ADDRESS | 5, PARALLEL_MIXER); mix_write (5, PARALLEL_MIXER); -#if !defined(EXCLUDE_SB_EMULATION) && !defined(EXCLUDE_SB) +#if defined(CONFIG_SB_EMULATION) && defined(CONFIG_SB) { struct address_info *sb_config; @@ -369,17 +369,22 @@ if ((pas_model = pas_read (CHIP_REV))) { - printk (" <%s rev %d>", pas_model_names[(int) pas_model], pas_read (BOARD_REV_ID)); + char temp[100]; + + sprintf (temp, + "%s rev %d", pas_model_names[(int) pas_model], + pas_read (BOARD_REV_ID)); + conf_printf (temp, hw_config); } if (config_pas_hw (hw_config)) { -#ifndef EXCLUDE_AUDIO +#ifdef CONFIG_AUDIO mem_start = pas_pcm_init (mem_start, hw_config); #endif -#if !defined(EXCLUDE_SB_EMULATION) && !defined(EXCLUDE_SB) +#if defined(CONFIG_SB_EMULATION) && defined(CONFIG_SB) sb_dsp_disable_midi (); /* * The SB emulation don't support * @@ -388,7 +393,7 @@ #endif -#ifndef EXCLUDE_MIDI +#ifdef CONFIG_MIDI mem_start = pas_midi_init (mem_start); #endif diff -u --recursive --new-file v1.3.57/linux/drivers/sound/pas2_midi.c linux/drivers/sound/pas2_midi.c --- v1.3.57/linux/drivers/sound/pas2_midi.c Fri Oct 13 14:44:34 1995 +++ linux/drivers/sound/pas2_midi.c Tue Jan 9 00:37:28 1996 @@ -29,11 +29,9 @@ #include "sound_config.h" -#ifdef CONFIGURE_SOUNDCARD - #include "pas.h" -#if !defined(EXCLUDE_PAS) && !defined(EXCLUDE_MIDI) +#if defined(CONFIG_PAS) && defined(CONFIG_MIDI) static int midi_busy = 0, input_opened = 0; static int my_dev; @@ -335,7 +333,5 @@ * Acknowledge interrupts */ } - -#endif #endif diff -u --recursive --new-file v1.3.57/linux/drivers/sound/pas2_mixer.c linux/drivers/sound/pas2_mixer.c --- v1.3.57/linux/drivers/sound/pas2_mixer.c Fri Oct 13 14:44:34 1995 +++ linux/drivers/sound/pas2_mixer.c Tue Jan 9 00:37:29 1996 @@ -31,7 +31,7 @@ #include "sound_config.h" -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_PAS) +#if defined(CONFIG_PAS) #include "pas.h" @@ -264,7 +264,7 @@ if (((cmd >> 8) & 0xff) == 'M') { - if (cmd & IOC_IN) + if (_IOC_DIR (cmd) & _IOC_WRITE) return snd_ioctl_return ((int *) arg, pas_mixer_set (cmd & 0xff, get_fs_long ((long *) arg))); else { /* diff -u --recursive --new-file v1.3.57/linux/drivers/sound/pas2_pcm.c linux/drivers/sound/pas2_pcm.c --- v1.3.57/linux/drivers/sound/pas2_pcm.c Fri Oct 13 14:44:34 1995 +++ linux/drivers/sound/pas2_pcm.c Tue Jan 9 00:37:29 1996 @@ -30,11 +30,9 @@ #include "sound_config.h" -#ifdef CONFIGURE_SOUNDCARD - #include "pas.h" -#if !defined(EXCLUDE_PAS) && !defined(EXCLUDE_AUDIO) +#if defined(CONFIG_PAS) && defined(CONFIG_AUDIO) #define TRACE(WHAT) /* * * * (WHAT) */ @@ -444,7 +442,5 @@ } } } - -#endif #endif diff -u --recursive --new-file v1.3.57/linux/drivers/sound/patmgr.c linux/drivers/sound/patmgr.c --- v1.3.57/linux/drivers/sound/patmgr.c Wed Nov 8 07:11:36 1995 +++ linux/drivers/sound/patmgr.c Tue Jan 9 00:37:30 1996 @@ -30,9 +30,9 @@ #define PATMGR_C #include "sound_config.h" -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SEQUENCER) +#if defined(CONFIG_SEQUENCER) -static struct wait_queue *server_procs[MAX_SYNTH_DEV] = +static wait_handle *server_procs[MAX_SYNTH_DEV] = {NULL}; static volatile struct snd_wait server_wait_flag[MAX_SYNTH_DEV] = { @@ -49,7 +49,7 @@ #define A_TO_S 1 #define S_TO_A 2 -static struct wait_queue *appl_proc = NULL; +static wait_handle *appl_proc = NULL; static volatile struct snd_wait appl_wait_flag = {0}; @@ -83,7 +83,7 @@ if ((appl_wait_flag.mode & WK_SLEEP)) { appl_wait_flag.mode = WK_WAKEUP; - wake_up (&appl_proc); + module_wake_up (&appl_proc); }; } @@ -102,31 +102,18 @@ return -EIO; } - while (!ok && !(current->signal & ~current->blocked)) + while (!ok && !current_got_fatal_signal ()) { save_flags (flags); cli (); while (!(mbox[dev] && msg_direction[dev] == A_TO_S) && - !(current->signal & ~current->blocked)) + !current_got_fatal_signal ()) { - { - unsigned long tl; - - if (0) - current->timeout = tl = 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 (jiffies >= tl) - server_wait_flag[dev].mode |= WK_TIMEOUT; - } - server_wait_flag[dev].mode &= ~WK_SLEEP; - }; + server_wait_flag[dev].mode = WK_SLEEP; + module_interruptible_sleep_on (&server_procs[dev]); + server_wait_flag[dev].mode &= ~WK_SLEEP;; } if (mbox[dev] && msg_direction[dev] == A_TO_S) @@ -193,7 +180,7 @@ { { appl_wait_flag.mode = WK_WAKEUP; - wake_up (&appl_proc); + module_wake_up (&appl_proc); }; } } @@ -224,27 +211,14 @@ { { server_wait_flag[dev].mode = WK_WAKEUP; - wake_up (&server_procs[dev]); + module_wake_up (&server_procs[dev]); }; } - { - unsigned long tl; - - if (0) - current->timeout = tl = jiffies + (0); - else - tl = 0xffffffff; - appl_wait_flag.mode = WK_SLEEP; - interruptible_sleep_on (&appl_proc); - if (!(appl_wait_flag.mode & WK_WAKEUP)) - { - if (jiffies >= tl) - appl_wait_flag.mode |= WK_TIMEOUT; - } - appl_wait_flag.mode &= ~WK_SLEEP; - }; + appl_wait_flag.mode = WK_SLEEP; + module_interruptible_sleep_on (&appl_proc); + appl_wait_flag.mode &= ~WK_SLEEP;; if (msg_direction[dev] != S_TO_A) { @@ -274,9 +248,19 @@ unsigned long flags; int err = 0; + struct patmgr_info *tmp_mbox; + if (!pmgr_opened[dev]) return 0; + tmp_mbox = (struct patmgr_info *) kmalloc (sizeof (struct patmgr_info), GFP_KERNEL); + + if (tmp_mbox == NULL) + { + printk ("pmgr: Couldn't allocate memory for a message\n"); + return 0; + } + save_flags (flags); cli (); @@ -284,13 +268,8 @@ printk (" PATMGR: Server %d mbox full. Why?\n", dev); else { - if ((mbox[dev] = - (struct patmgr_info *) kmalloc (sizeof (struct patmgr_info), GFP_KERNEL)) == NULL) - { - printk ("pmgr: Couldn't allocate memory for a message\n"); - return 0; - } + mbox[dev] = tmp_mbox; mbox[dev]->key = PM_K_EVENT; mbox[dev]->command = event; mbox[dev]->parm1 = p1; @@ -302,34 +281,20 @@ { { server_wait_flag[dev].mode = WK_WAKEUP; - wake_up (&server_procs[dev]); + module_wake_up (&server_procs[dev]); }; } - { - unsigned long tl; - - if (0) - current->timeout = tl = jiffies + (0); - else - tl = 0xffffffff; - appl_wait_flag.mode = WK_SLEEP; - interruptible_sleep_on (&appl_proc); - if (!(appl_wait_flag.mode & WK_WAKEUP)) - { - if (jiffies >= tl) - appl_wait_flag.mode |= WK_TIMEOUT; - } - appl_wait_flag.mode &= ~WK_SLEEP; - }; - if (mbox[dev]) - kfree (mbox[dev]); + appl_wait_flag.mode = WK_SLEEP; + module_interruptible_sleep_on (&appl_proc); + appl_wait_flag.mode &= ~WK_SLEEP;; mbox[dev] = NULL; msg_direction[dev] = 0; } restore_flags (flags); + kfree (tmp_mbox); return err; } diff -u --recursive --new-file v1.3.57/linux/drivers/sound/pss.c linux/drivers/sound/pss.c --- v1.3.57/linux/drivers/sound/pss.c Mon Oct 23 18:02:16 1995 +++ linux/drivers/sound/pss.c Tue Jan 9 00:37:31 1996 @@ -29,7 +29,7 @@ #include "sound_config.h" -#if defined (CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_PSS) && !defined(EXCLUDE_AUDIO) +#if defined(CONFIG_PSS) && defined(CONFIG_AUDIO) /* * PSS registers. @@ -109,13 +109,6 @@ return 0; } - if (irq != 3 && irq != 5 && irq != 7 && irq != 9 && - irq != 10 && irq != 11 && irq != 12) - return 0; - - if (dma != 5 && dma != 6 && dma != 7) - return 0; - id = inw (REG (PSS_ID)); if ((id >> 8) != 'E') { @@ -329,6 +322,7 @@ attach_pss (long mem_start, struct address_info *hw_config) { unsigned short id; + char tmp[100]; devc->base = hw_config->io_base; devc->irq = hw_config->irq; @@ -370,7 +364,8 @@ #endif pss_initialized = 1; - printk (" ", id); + sprintf (tmp, "ECHO-PSS Rev. %d", id); + conf_printf (tmp, hw_config); return mem_start; } @@ -426,7 +421,7 @@ break; /* No more input */ } -#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI) +#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI) return probe_mpu401 (hw_config); #else return 0 @@ -700,7 +695,7 @@ int prev_devs; long ret; -#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI) +#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI) prev_devs = num_midis; ret = attach_mpu401 (mem_start, hw_config); diff -u --recursive --new-file v1.3.57/linux/drivers/sound/sb16_dsp.c linux/drivers/sound/sb16_dsp.c --- v1.3.57/linux/drivers/sound/sb16_dsp.c Thu Nov 9 11:23:51 1995 +++ linux/drivers/sound/sb16_dsp.c Tue Jan 9 00:37:32 1996 @@ -38,7 +38,7 @@ #include "sb.h" #include "sb_mixer.h" -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB16) && !defined(EXCLUDE_SB) && !defined(EXCLUDE_AUDIO) && !defined(EXCLUDE_SBPRO) +#if defined(CONFIG_SB) && defined(CONFIG_AUDIO) extern int sbc_base; extern sound_os_info *sb_osp; @@ -157,7 +157,7 @@ { case SOUND_PCM_WRITE_RATE: if (local) - return dsp_set_speed ((long) 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: @@ -167,12 +167,12 @@ case SNDCTL_DSP_STEREO: if (local) - return dsp_set_stereo ((long) 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 ((long) 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: @@ -182,7 +182,7 @@ case SNDCTL_DSP_SETFMT: if (local) - return dsp_set_bits ((long) 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: @@ -260,9 +260,24 @@ restore_flags (flags); } +static unsigned long trg_buf; +static int trg_bytes; +static int trg_intrflag; +static int trg_restart; + static void sb16_dsp_output_block (int dev, unsigned long buf, int count, int intrflag, int dma_restart) { + trg_buf = buf; + trg_bytes = count; + trg_intrflag = intrflag; + trg_restart = dma_restart; + irq_mode = IMODE_OUTPUT; +} + +static void +actually_output_block (int dev, unsigned long buf, int count, int intrflag, int dma_restart) +{ unsigned long flags, cnt; cnt = count; @@ -322,6 +337,16 @@ static void sb16_dsp_start_input (int dev, unsigned long buf, int count, int intrflag, int dma_restart) { + trg_buf = buf; + trg_bytes = count; + trg_intrflag = intrflag; + trg_restart = dma_restart; + irq_mode = IMODE_INPUT; +} + +static void +actually_start_input (int dev, unsigned long buf, int count, int intrflag, int dma_restart) +{ unsigned long flags, cnt; cnt = count; @@ -415,7 +440,18 @@ if (!bits) sb_dsp_command (0xd0); /* Halt DMA */ else if (bits & irq_mode) - sb_dsp_command (0xd4); /* Continue DMA */ + switch (irq_mode) + { + case IMODE_INPUT: + actually_start_input (my_dev, trg_buf, trg_bytes, + trg_intrflag, trg_restart); + break; + + case IMODE_OUTPUT: + actually_output_block (my_dev, trg_buf, trg_bytes, + trg_intrflag, trg_restart); + break; + } } static void @@ -491,7 +527,7 @@ sprintf (sb16_dsp_operations.name, "SoundBlaster 16 %d.%d", sbc_major, sbc_minor); - printk (" <%s>", sb16_dsp_operations.name); + conf_printf (sb16_dsp_operations.name, hw_config); if (num_audiodevs < MAX_AUDIO_DEV) { @@ -520,10 +556,18 @@ sb16_dsp_detect (struct address_info *hw_config) { struct address_info *sb_config; - extern int sbc_major; + extern int sbc_major, Jazz16_detected; + + extern void Jazz16_set_dma16 (int dma); if (sb16_dsp_ok) return 1; /* Can't drive two cards */ + + if (Jazz16_detected) + { + Jazz16_set_dma16 (hw_config->dma); + return 0; + } if (!(sb_config = sound_getconf (SNDCARD_SB))) { diff -u --recursive --new-file v1.3.57/linux/drivers/sound/sb16_midi.c linux/drivers/sound/sb16_midi.c --- v1.3.57/linux/drivers/sound/sb16_midi.c Fri Oct 13 14:44:43 1995 +++ linux/drivers/sound/sb16_midi.c Tue Jan 9 00:37:33 1996 @@ -29,9 +29,7 @@ #include "sound_config.h" -#ifdef CONFIGURE_SOUNDCARD - -#if !defined(EXCLUDE_SB) && !defined(EXCLUDE_SB16) && !defined(EXCLUDE_MIDI) +#if defined(CONFIG_SB) && defined(CONFIG_MIDI) #include "sb.h" @@ -60,8 +58,12 @@ static int my_dev; extern int sbc_base; +extern int Jazz16_detected; +extern int AudioDrive; + static int reset_sb16midi (void); static void (*midi_input_intr) (int dev, unsigned char data); +static volatile unsigned char input_byte; static void sb16midi_input_loop (void) @@ -70,7 +72,9 @@ { unsigned char c = sb16midi_read (); - if (sb16midi_opened & OPEN_READ) + if (c == MPU_ACK) + input_byte = c; + else if (sb16midi_opened & OPEN_READ && midi_input_intr) midi_input_intr (my_dev, c); } } @@ -82,6 +86,13 @@ sb16midi_input_loop (); } +void +sbmidiintr (int irq, struct pt_regs *dummy) +{ + if (input_avail ()) + sb16midi_input_loop (); +} + static int sb16midi_open (int dev, int mode, void (*input) (int dev, unsigned char data), @@ -175,13 +186,13 @@ */ } -#define MIDI_SYNTH_NAME "SoundBlaster 16 Midi" +#define MIDI_SYNTH_NAME "SoundBlaster MPU" #define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT #include "midi_synth.h" static struct midi_operations sb16midi_operations = { - {"SoundBlaster 16 Midi", 0, 0, SNDCARD_SB16MIDI}, + {"SoundBlaster MPU", 0, 0, SNDCARD_SB16MIDI}, &std_midi_synth, {0}, sb16midi_open, @@ -196,7 +207,6 @@ NULL }; - long attach_sb16midi (long mem_start, struct address_info *hw_config) { @@ -206,18 +216,23 @@ sb16midi_base = hw_config->io_base; if (!sb16midi_detected) - return -EIO; + return mem_start; + + request_region (hw_config->io_base, 4, "SB MIDI"); save_flags (flags); cli (); for (timeout = 30000; timeout < 0 && !output_ready (); timeout--); /* * Wait */ + input_byte = 0; sb16midi_cmd (UART_MODE_ON); ok = 0; for (timeout = 50000; timeout > 0 && !ok; timeout--) - if (input_avail ()) + if (input_byte == MPU_ACK) + ok = 1; + else if (input_avail ()) if (sb16midi_read () == MPU_ACK) ok = 1; @@ -229,7 +244,7 @@ return mem_start; } - printk (" "); + conf_printf ("SoundBlaster MPU-401", hw_config); std_midi_synth.midi_dev = my_dev = num_midis; midi_devs[num_midis++] = &sb16midi_operations; @@ -239,23 +254,25 @@ static int reset_sb16midi (void) { - unsigned long flags; int ok, timeout, n; /* * Send the RESET command. Try again if no success at the first time. */ + if (inb (STATPORT) == 0xff) + return 0; + ok = 0; - save_flags (flags); - cli (); + /*save_flags(flags);cli(); */ for (n = 0; n < 2 && !ok; n++) { for (timeout = 30000; timeout < 0 && !output_ready (); timeout--); /* * Wait */ + input_byte = 0; sb16midi_cmd (MPU_RESET); /* * Send MPU-401 RESET Command */ @@ -266,7 +283,9 @@ */ for (timeout = 50000; timeout > 0 && !ok; timeout--) - if (input_avail ()) + if (input_byte == MPU_ACK) /* Interrupt */ + ok = 1; + else if (input_avail ()) if (sb16midi_read () == MPU_ACK) ok = 1; @@ -278,19 +297,28 @@ * Flush input before enabling interrupts */ - restore_flags (flags); + /* restore_flags(flags); */ return ok; } - int probe_sb16midi (struct address_info *hw_config) { int ok = 0; extern int sbc_major; - if (sbc_major < 4) + extern void ess_midi_init (struct address_info *hw_config); + extern void Jazz16_midi_init (struct address_info *hw_config); + + if (check_region (hw_config->io_base, 4)) + return 0; + + if (AudioDrive) + ess_midi_init (hw_config); + else if (Jazz16_detected) + Jazz16_midi_init (hw_config); + else if (sbc_major < 4) return 0; /* Not a SB16 */ sb16midi_base = hw_config->io_base; @@ -307,8 +335,7 @@ void unload_sb16midi (struct address_info *hw_config) { + release_region (hw_config->io_base, 4); } - -#endif #endif diff -u --recursive --new-file v1.3.57/linux/drivers/sound/sb_card.c linux/drivers/sound/sb_card.c --- v1.3.57/linux/drivers/sound/sb_card.c Wed Nov 8 07:11:36 1995 +++ linux/drivers/sound/sb_card.c Tue Jan 9 00:37:33 1996 @@ -32,18 +32,18 @@ #include "sound_config.h" -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB) +#if defined(CONFIG_SB) #include "sb.h" long attach_sb_card (long mem_start, struct address_info *hw_config) { -#if !defined(EXCLUDE_AUDIO) || !defined(EXCLUDE_MIDI) +#if defined(CONFIG_AUDIO) || defined(CONFIG_MIDI) 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"); + request_region (hw_config->io_base, 16, "SoundBlaster"); #endif return mem_start; @@ -59,7 +59,7 @@ return 0; } -#if !defined(EXCLUDE_AEDSP16) && defined(AEDSP16_SBPRO) +#if defined(CONFIG_AEDSP16) && defined(AEDSP16_SBPRO) /* * Initialize Audio Excel DSP 16 to SBPRO. */ diff -u --recursive --new-file v1.3.57/linux/drivers/sound/sb_dsp.c linux/drivers/sound/sb_dsp.c --- v1.3.57/linux/drivers/sound/sb_dsp.c Thu Nov 9 11:23:51 1995 +++ linux/drivers/sound/sb_dsp.c Tue Jan 9 00:37:35 1996 @@ -35,23 +35,22 @@ #include "sound_config.h" -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB) - -#ifdef SM_WAVE -#define JAZZ16 -#endif +#if defined(CONFIG_SB) #include "sb.h" #include "sb_mixer.h" #undef SB_TEST_IRQ int sbc_base = 0; -static int sbc_irq = 0; +static int sbc_irq = 0, sbc_dma; static int open_mode = 0; /* Read, write or both */ int Jazz16_detected = 0; +int AudioDrive = 0; /* 1=ES1688 detected */ +static int ess_mpu_irq = 0; int sb_no_recording = 0; static int dsp_count = 0; static int trigger_bits; +static int mpu_base = 0, mpu_irq = 0; /* * The DSP channel can be used either for input or output. Variable @@ -68,46 +67,32 @@ * initialization * */ static int midi_disabled = 0; int sb_dsp_highspeed = 0; -int sbc_major = 1, sbc_minor = 0; /* - - - * * * * DSP version */ +int sbc_major = 1, sbc_minor = 0; static int dsp_stereo = 0; static int dsp_current_speed = DSP_DEFAULT_SPEED; static int sb16 = 0; static int irq_verified = 0; int sb_midi_mode = NORMAL_MIDI; -int sb_midi_busy = 0; /* - - - * * * * 1 if the process has output - * to * * MIDI */ +int sb_midi_busy = 0; int sb_dsp_busy = 0; -volatile int sb_irq_mode = IMODE_NONE; /* - - - * * * * IMODE_INPUT, * - * IMODE_OUTPUT * * or * - * IMODE_NONE */ +volatile int sb_irq_mode = IMODE_NONE; static volatile int irq_ok = 0; static int dma8 = 1; +static int dsp_16bit = 0; -#ifdef JAZZ16 /* 16 bit support */ -static int dsp_16bit = 0; -static int dma16 = 5; +static int dma16 = 1; static int dsp_set_bits (int arg); static int initialize_ProSonic16 (void); /* end of 16 bit support */ -#endif int sb_duplex_midi = 0; static int my_dev = 0; @@ -116,11 +101,12 @@ 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) +static void ess_init (void); + +#if defined(CONFIG_MIDI) || defined(CONFIG_AUDIO) /* * Common code for the midi and pcm functions @@ -154,58 +140,83 @@ } printk ("SoundBlaster: DSP Command(%x) Timeout.\n", val); - printk ("IRQ conflict???\n"); return 0; } +static int +ess_write (unsigned char reg, unsigned char data) +{ + /* Write a byte to an extended mode register of ES1688 */ + + if (!sb_dsp_command (reg)) + return 0; + + return sb_dsp_command (data); +} + +static int +ess_read (unsigned char reg) +{ +/* Read a byte from an extended mode register of ES1688 */ + + int i; + + if (!sb_dsp_command (0xc0)) /* Read register command */ + return -1; + + if (!sb_dsp_command (reg)) + return -1; + + for (i = 1000; i; i--) + { + if (inb (DSP_DATA_AVAIL) & 0x80) + return inb (DSP_READ); + } + + return -1; +} + void sbintr (int irq, struct pt_regs *dummy) { int status; -#ifndef EXCLUDE_SBPRO - if (sb16) + if (sb16 && !AudioDrive) { unsigned char src = sb_getmixer (IRQ_STAT); /* Interrupt source register */ -#ifndef EXCLUDE_SB16 if (src & 3) sb16_dsp_interrupt (irq); -#ifndef EXCLUDE_MIDI +#ifdef CONFIG_MIDI if (src & 4) sb16midiintr (irq); /* * SB MPU401 interrupt */ #endif -#endif - if (!(src & 1)) return; /* * Not a DSP interupt */ } -#endif status = inb (DSP_DATA_AVAIL); /* * Clear interrupt */ - if (sb_intr_active) switch (sb_irq_mode) { case IMODE_OUTPUT: - sb_intr_active = 0; + if (!AudioDrive) + sb_intr_active = 0; DMAbuf_outputintr (my_dev, 1); break; case IMODE_INPUT: - sb_intr_active = 0; + if (!AudioDrive) + sb_intr_active = 0; DMAbuf_inputintr (my_dev); - /* - * A complete buffer has been input. Let's start new one - */ break; case IMODE_INIT: @@ -214,7 +225,7 @@ break; case IMODE_MIDI: -#ifndef EXCLUDE_MIDI +#ifdef CONFIG_MIDI sb_midi_interrupt (irq); #endif break; @@ -240,24 +251,31 @@ { int loopc; - outb (1, DSP_RESET); - tenmicrosec (); + if (AudioDrive) + outb (3, DSP_RESET); /* Reset FIFO too */ + else + outb (1, DSP_RESET); + + tenmicrosec (sb_osp); outb (0, DSP_RESET); - tenmicrosec (); - tenmicrosec (); - tenmicrosec (); + tenmicrosec (sb_osp); + tenmicrosec (sb_osp); + tenmicrosec (sb_osp); for (loopc = 0; loopc < 1000 && !(inb (DSP_DATA_AVAIL) & 0x80); loopc++); if (inb (DSP_READ) != 0xAA) return 0; /* Sorry */ + if (AudioDrive) + sb_dsp_command (0xc6); /* Enable extended mode */ + return 1; } #endif -#ifndef EXCLUDE_AUDIO +#ifdef CONFIG_AUDIO static void dsp_speaker (char state) @@ -269,12 +287,45 @@ } static int +ess_speed (int speed) +{ + int rate; + unsigned char bits = 0; + + if (speed < 4000) + speed = 4000; + else if (speed > 48000) + speed = 48000; + + if (speed > 22000) + { + bits = 0x80; + rate = 256 - (795500 + speed / 2) / speed; + speed = 795500 / (256 - rate); + } + else + { + rate = 128 - (397700 + speed / 2) / speed; + speed = 397700 / (128 - rate); + } + + bits |= (unsigned char) rate; + ess_write (0xa1, bits); + + dsp_current_speed = speed; + return speed; +} + +static int dsp_speed (int speed) { unsigned char tconst; unsigned long flags; int max_speed = 44100; + if (AudioDrive) + return ess_speed (speed); + if (speed < 4000) speed = 4000; @@ -306,7 +357,7 @@ /* * Max. stereo speed is 22050 */ - if (dsp_stereo && speed > 22050 && Jazz16_detected == 0) + if (dsp_stereo && speed > 22050 && Jazz16_detected == 0 && AudioDrive == 0) speed = 22050; #endif @@ -373,9 +424,6 @@ { dsp_stereo = 0; -#ifdef EXCLUDE_SBPRO - return 0; -#else if (sbc_major < 3 || sb16) return 0; /* * Sorry no stereo @@ -389,14 +437,30 @@ dsp_stereo = !!mode; return dsp_stereo; -#endif } +static unsigned long trg_buf; +static int trg_bytes; +static int trg_intrflag; +static int trg_restart; + static void -sb_dsp_output_block (int dev, unsigned long buf, int count, +sb_dsp_output_block (int dev, unsigned long buf, int nr_bytes, int intrflag, int restart_dma) { + trg_buf = buf; + trg_bytes = nr_bytes; + trg_intrflag = intrflag; + trg_restart = restart_dma; + sb_irq_mode = IMODE_OUTPUT; +} + +static void +actually_output_block (int dev, unsigned long buf, int nr_bytes, + int intrflag, int restart_dma) +{ unsigned long flags; + int count = nr_bytes; if (!sb_irq_mode) dsp_speaker (ON); @@ -411,7 +475,17 @@ dsp_count = count; sb_irq_mode = IMODE_OUTPUT; - if (sb_dsp_highspeed) + + if (AudioDrive) + { + int c = 0x10000 - count; /* ES1688 increments the count */ + + ess_write (0xa4, (unsigned char) (c & 0xff)); + ess_write (0xa5, (unsigned char) ((c >> 8) & 0xff)); + + ess_write (0xb8, ess_read (0xb8) | 0x01); /* Go */ + } + else if (sb_dsp_highspeed) { save_flags (flags); cli (); @@ -451,6 +525,17 @@ sb_dsp_start_input (int dev, unsigned long buf, int count, int intrflag, int restart_dma) { + trg_buf = buf; + trg_bytes = count; + trg_intrflag = intrflag; + trg_restart = restart_dma; + sb_irq_mode = IMODE_INPUT; +} + +static void +actually_start_input (int dev, unsigned long buf, int count, int intrflag, + int restart_dma) +{ unsigned long flags; if (sb_no_recording) @@ -475,7 +560,17 @@ dsp_count = count; sb_irq_mode = IMODE_INPUT; - if (sb_dsp_highspeed) + + if (AudioDrive) + { + int c = 0x10000 - count; /* ES1688 increments the count */ + + ess_write (0xa4, (unsigned char) (c & 0xff)); + ess_write (0xa5, (unsigned char) ((c >> 8) & 0xff)); + + ess_write (0xb8, ess_read (0xb8) | 0x01); /* Go */ + } + else if (sb_dsp_highspeed) { save_flags (flags); cli (); @@ -515,13 +610,24 @@ static void sb_dsp_trigger (int dev, int bits) { - if (bits == trigger_bits) - return; if (!bits) sb_dsp_command (0xd0); /* Halt DMA */ else if (bits & sb_irq_mode) - sb_dsp_command (0xd4); /* Continue DMA */ + { + switch (sb_irq_mode) + { + case IMODE_INPUT: + actually_start_input (my_dev, trg_buf, trg_bytes, + trg_intrflag, trg_restart); + break; + + case IMODE_OUTPUT: + actually_output_block (my_dev, trg_buf, trg_bytes, + trg_intrflag, trg_restart); + break; + } + } trigger_bits = bits; } @@ -542,30 +648,61 @@ * SB Pro */ { -#ifdef JAZZ16 - /* Select correct dma channel - * for 16/8 bit acccess - */ - audio_devs[my_dev]->dmachan1 = dsp_16bit ? dma16 : dma8; - if (dsp_stereo) - sb_dsp_command (dsp_16bit ? 0xac : 0xa8); - else - sb_dsp_command (dsp_16bit ? 0xa4 : 0xa0); -#else - /* 8 bit only cards use this - */ - if (dsp_stereo) - sb_dsp_command (0xa8); + if (AudioDrive) + { + + /* ess_init(); */ + ess_write (0xb8, 0x0e); /* Auto init DMA mode */ + ess_write (0xa8, (ess_read (0xa8) & ~0x04) | + (2 - dsp_stereo)); /* Mono/stereo */ + ess_write (0xb9, 2); /* Demand mode (2 bytes/xfer) */ + + if (!dsp_stereo) + { + if (dsp_16bit == 0) + { /* 8 bit mono */ + ess_write (0xb7, 0x51); + ess_write (0xb7, 0xd0); + } + else + { /* 16 bit mono */ + ess_write (0xb7, 0x71); + ess_write (0xb7, 0xf4); + } + } + else + { /* Stereo */ + if (!dsp_16bit) + { /* 8 bit stereo */ + ess_write (0xb7, 0x51); + ess_write (0xb7, 0x98); + } + else + { /* 16 bit stereo */ + ess_write (0xb7, 0x71); + ess_write (0xb7, 0xbc); + } + } + + ess_write (0xb1, (ess_read (0xb1) & 0x0f) | 0x50); + ess_write (0xb2, (ess_read (0xb2) & 0x0f) | 0x50); + } else - sb_dsp_command (0xa0); -#endif - dsp_speed (dsp_current_speed); /* - * Speed must be recalculated if - * #channels * changes - */ + { /* !AudioDrive */ + + /* Select correct dma channel + * for 16/8 bit acccess + */ + audio_devs[my_dev]->dmachan1 = dsp_16bit ? dma16 : dma8; + if (dsp_stereo) + sb_dsp_command (dsp_16bit ? 0xac : 0xa8); + else + sb_dsp_command (dsp_16bit ? 0xa4 : 0xa0); + + dsp_speed (dsp_current_speed); + } /* !AudioDrive */ } trigger_bits = 0; - sb_dsp_command (0xd0); /* Halt DMA */ return 0; } @@ -573,34 +710,72 @@ sb_dsp_prepare_for_output (int dev, int bsize, int bcount) { dsp_cleanup (); - dsp_speaker (ON); + dsp_speaker (OFF); -#ifndef EXCLUDE_SBPRO - if (sbc_major == 3) /* - * SB Pro - */ + if (sbc_major == 3) /* SB Pro (at least ) */ { -#ifdef JAZZ16 - /* 16 bit specific instructions - */ - audio_devs[my_dev]->dmachan1 = dsp_16bit ? dma16 : dma8; - if (Jazz16_detected != 2) /* SM Wave */ - sb_mixer_set_stereo (dsp_stereo); - if (dsp_stereo) - sb_dsp_command (dsp_16bit ? 0xac : 0xa8); + + if (AudioDrive) + { + + /* ess_init(); */ + ess_write (0xb8, 4); /* Auto init DMA mode */ + ess_write (0xa8, ess_read (0xa8) | + (2 - dsp_stereo)); /* Mono/stereo */ + ess_write (0xb9, 2); /* Demand mode (2 bytes/xfer) */ + + if (!dsp_stereo) + { + if (dsp_16bit == 0) + { /* 8 bit mono */ + ess_write (0xb6, 0x80); + ess_write (0xb7, 0x51); + ess_write (0xb7, 0xd0); + } + else + { /* 16 bit mono */ + ess_write (0xb6, 0x00); + ess_write (0xb7, 0x71); + ess_write (0xb7, 0xf4); + } + } + else + { /* Stereo */ + if (!dsp_16bit) + { /* 8 bit stereo */ + ess_write (0xb6, 0x80); + ess_write (0xb7, 0x51); + ess_write (0xb7, 0x98); + } + else + { /* 16 bit stereo */ + ess_write (0xb6, 0x00); + ess_write (0xb7, 0x71); + ess_write (0xb7, 0xbc); + } + } + + ess_write (0xb1, (ess_read (0xb1) & 0x0f) | 0x50); + ess_write (0xb2, (ess_read (0xb2) & 0x0f) | 0x50); + } else - sb_dsp_command (dsp_16bit ? 0xa4 : 0xa0); -#else - sb_mixer_set_stereo (dsp_stereo); -#endif - dsp_speed (dsp_current_speed); /* - * Speed must be recalculated if - * #channels * changes - */ + { /* !AudioDrive */ + + /* 16 bit specific instructions (Jazz16) + */ + audio_devs[my_dev]->dmachan1 = dsp_16bit ? dma16 : dma8; + if (Jazz16_detected != 2) /* SM Wave */ + sb_mixer_set_stereo (dsp_stereo); + if (dsp_stereo) + sb_dsp_command (dsp_16bit ? 0xac : 0xa8); + else + sb_dsp_command (dsp_16bit ? 0xa4 : 0xa0); + } /* !AudioDrive */ + } -#endif + trigger_bits = 0; - sb_dsp_command (0xd0); /* Halt DMA */ + dsp_speaker (ON); return 0; } @@ -653,11 +828,9 @@ /* Allocate 8 bit dma */ -#ifdef JAZZ16 audio_devs[my_dev]->dmachan1 = dma8; -#endif -#ifdef JAZZ16 - /* Allocate 16 bit dma + + /* Allocate 16 bit dma (jazz16) */ if (Jazz16_detected != 0) if (dma16 != dma8) @@ -669,7 +842,6 @@ return -EBUSY; } } -#endif sb_irq_mode = IMODE_NONE; @@ -682,7 +854,6 @@ static void sb_dsp_close (int dev) { -#ifdef JAZZ16 /* Release 16 bit dma channel */ if (Jazz16_detected) @@ -692,7 +863,6 @@ if (dma16 != dma8) sound_close_dma (dma16); } -#endif /* DMAbuf_close_dma (dev); */ sb_free_irq (); @@ -704,14 +874,11 @@ open_mode = 0; } -#ifdef JAZZ16 -/* Function dsp_set_bits() only required for 16 bit cards - */ static int dsp_set_bits (int arg) { if (arg) - if (Jazz16_detected == 0) + if (Jazz16_detected == 0 && AudioDrive == 0) dsp_16bit = 0; else switch (arg) @@ -725,11 +892,10 @@ default: dsp_16bit = 0; } + return dsp_16bit ? 16 : 8; } -#endif /* ifdef JAZZ16 */ - static int sb_dsp_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local) { @@ -737,7 +903,7 @@ { case SOUND_PCM_WRITE_RATE: if (local) - return dsp_speed ((long) arg); + return dsp_speed ((int) arg); return snd_ioctl_return ((int *) arg, dsp_speed (get_fs_long ((long *) arg))); break; @@ -749,7 +915,7 @@ case SOUND_PCM_WRITE_CHANNELS: if (local) - return dsp_set_stereo ((long) 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; @@ -761,11 +927,10 @@ case SNDCTL_DSP_STEREO: if (local) - return dsp_set_stereo ((long) arg); + return dsp_set_stereo ((int) arg); return snd_ioctl_return ((int *) arg, dsp_set_stereo (get_fs_long ((long *) arg))); break; -#ifdef JAZZ16 /* Word size specific cases here. * SNDCTL_DSP_SETFMT=SOUND_PCM_WRITE_BITS */ @@ -780,14 +945,6 @@ return 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 snd_ioctl_return ((int *) arg, 8); /* Only 8 bits/sample supported */ - break; -#endif /* ifdef JAZZ16 */ case SOUND_PCM_WRITE_FILTER: case SOUND_PCM_READ_FILTER: @@ -818,8 +975,6 @@ #endif -#ifdef JAZZ16 - /* * Initialization of a Media Vision ProSonic 16 Soundcard. * The function initializes a ProSonic 16 like PROS.EXE does for DOS. It sets @@ -845,7 +1000,6 @@ return 0xffff; } -#ifdef SM_WAVE /* * Logitech Soundman Wave detection and initialization by Hannu Savolainen. * @@ -914,7 +1068,7 @@ outb ((control & 0xfe) | 2, mpu_base + 7); /* xxxxxxx0 resets the mc */ for (i = 0; i < 300; i++) /* Wait at least 1ms */ - tenmicrosec (); + tenmicrosec (sb_osp); outb (control & 0xfc, mpu_base + 7); /* xxxxxx00 enables RAM */ @@ -923,7 +1077,7 @@ */ smw_putmem (mp_base, 0, 0x00); smw_putmem (mp_base, 1, 0xff); - tenmicrosec (); + tenmicrosec (sb_osp); if (smw_getmem (mp_base, 0) != 0x00 || smw_getmem (mp_base, 1) != 0xff) { @@ -995,8 +1149,6 @@ return 1; } -#endif - static int initialize_ProSonic16 (void) { @@ -1005,23 +1157,9 @@ {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}; - struct address_info *mpu_config; - - int mpu_base, mpu_irq; - - if ((mpu_config = sound_getconf (SNDCARD_MPU401))) - { - mpu_base = mpu_config->io_base; - mpu_irq = mpu_config->irq; - } - else - { - mpu_base = mpu_irq = 0; - } - outb (0xAF, 0x201); /* ProSonic/Jazz16 wakeup */ for (x = 0; x < 1000; ++x) /* wait 10 milliseconds */ - tenmicrosec (); + tenmicrosec (sb_osp); outb (0x50, 0x201); outb ((sbc_base & 0x70) | ((mpu_base & 0x30) >> 4), 0x201); @@ -1036,18 +1174,15 @@ return 1; if (sb_dsp_command (0xFB) && /* set DMA-channels and Interrupts */ - sb_dsp_command ((dma_translat[JAZZ_DMA16] << 4) | dma_translat[dma8]) && + sb_dsp_command ((dma_translat[dma16] << 4) | dma_translat[dma8]) && sb_dsp_command ((int_translat[mpu_irq] << 4) | int_translat[sbc_irq])) { Jazz16_detected = 1; - if (mpu_base == 0) - printk ("Jazz16: No MPU401 devices configured - MIDI port not initialized\n"); -#ifdef SM_WAVE if (mpu_base != 0) if (initialize_smw (mpu_base)) Jazz16_detected = 2; -#endif + sb_dsp_disable_midi (); } @@ -1056,37 +1191,29 @@ return 0; /* No SB or ProSonic16 detected */ } -#endif /* ifdef JAZZ16 */ - int sb_dsp_detect (struct address_info *hw_config) { sbc_base = hw_config->io_base; sbc_irq = hw_config->irq; + sbc_dma = hw_config->dma; sb_osp = hw_config->osp; if (sb_dsp_ok) return 0; /* * Already initialized */ - dma8 = hw_config->dma; - -#ifdef JAZZ16 - dma16 = JAZZ_DMA16; + dma8 = dma16 = hw_config->dma; if (!initialize_ProSonic16 ()) return 0; -#else - if (!sb_reset_dsp ()) - return 0; -#endif return 1; /* * Detected */ } -#ifndef EXCLUDE_AUDIO +#ifdef CONFIG_AUDIO static struct audio_operations sb_dsp_operations = { "SoundBlaster", @@ -1111,16 +1238,154 @@ #endif +static void +ess_init (void) /* ESS1688 Initialization */ +{ + unsigned char cfg, irq_bits = 0, dma_bits = 0; + + AudioDrive = 1; + midi_disabled = 1; + + sb_reset_dsp (); /* Turn on extended mode */ + +/* + * Set IRQ configuration register + */ + + cfg = 0x50; /* Enable only DMA counter interrupt */ + + switch (sbc_irq) + { + case 2: + case 9: + irq_bits = 0; + break; + + case 5: + irq_bits = 1; + break; + + case 7: + irq_bits = 2; + break; + + case 10: + irq_bits = 3; + break; + + default: + irq_bits = 0; + cfg = 0x10; /* Disable all interrupts */ + printk ("\nESS1688: Invalid IRQ %d\n", sbc_irq); + } + + if (!ess_write (0xb1, cfg | (irq_bits << 2))) + printk ("\nESS1688: Failed to write to IRQ config register\n"); + +/* + * Set DMA configuration register + */ + + cfg = 0x50; /* Extended mode DMA ebable */ + + if (sbc_dma > 3 || sbc_dma < 0 || sbc_dma == 2) + { + dma_bits = 0; + cfg = 0x00; /* Disable all DMA */ + printk ("\nESS1688: Invalid DMA %d\n", sbc_dma); + } + else + { + if (sbc_dma == 3) + dma_bits = 3; + else + dma_bits = sbc_dma + 1; + } + + if (!ess_write (0xb2, cfg | (dma_bits << 2))) + printk ("\nESS1688: Failed to write to DMA config register\n"); + +/* + * Enable joystick and OPL3 + */ + + cfg = sb_getmixer (0x40); + sb_setmixer (0x40, cfg | 0x03); +} + +void +ess_midi_init (struct address_info *hw_config) /* called from sb16_midi.c */ +{ + unsigned char cfg, tmp; + + cfg = sb_getmixer (0x40) & 0x03; + + tmp = (hw_config->io_base & 0x0f0) >> 4; + + if (tmp > 3) + { + sb_setmixer (0x40, cfg); + return; + } + + cfg |= tmp << 3; + + tmp = 1; /* MPU enabled without interrupts */ + + switch (hw_config->irq) + { + case 9: + tmp = 0x4; + break; + case 5: + tmp = 0x5; + break; + case 7: + tmp = 0x6; + break; + case 10: + tmp = 0x7; + break; + } + + cfg |= tmp << 5; + + if (tmp != 1) + { + ess_mpu_irq = hw_config->irq; + + if (snd_set_irq_handler (ess_mpu_irq, sbmidiintr, "ES1688 MIDI", sb_osp) < 0) + printk ("ES1688: Can't allocate IRQ%d\n", ess_mpu_irq); + } + + sb_setmixer (0x40, cfg); +} + +void +Jazz16_midi_init (struct address_info *hw_config) +{ + mpu_base = hw_config->io_base; + mpu_irq = hw_config->irq; + + initialize_ProSonic16 (); +} + +void +Jazz16_set_dma16 (int dma) +{ + dma16 = dma; + + initialize_ProSonic16 (); +} + long sb_dsp_init (long mem_start, struct address_info *hw_config) { int i; + int ess_major = 0, ess_minor = 0; -#ifndef EXCLUDE_SBPRO int mixer_type = 0; -#endif - sb_osp = hw_config->osp; sbc_major = sbc_minor = 0; sb_dsp_command (0xe1); /* @@ -1158,7 +1423,6 @@ if (sbc_major == 3 && sbc_minor == 1) { - int ess_major = 0, ess_minor = 0; /* * Try to detect ESS chips. @@ -1183,28 +1447,12 @@ } } } - - 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); } if (snd_set_irq_handler (sbc_irq, sbintr, "SoundBlaster", sb_osp) < 0) printk ("sb_dsp: Can't allocate IRQ\n");; -#ifndef EXCLUDE_SBPRO - if (sbc_major >= 3) - mixer_type = sb_mixer_init (sbc_major); -#else - if (sbc_major >= 3) - printk ("\n\n\n\nNOTE! SB Pro support is required with your soundcard!\n\n\n"); -#endif - - -#ifndef EXCLUDE_AUDIO +#ifdef CONFIG_AUDIO if (sbc_major >= 3) { if (Jazz16_detected) @@ -1228,6 +1476,20 @@ { sprintf (sb_dsp_operations.name, "SoundBlaster 16 %d.%d", sbc_major, sbc_minor); } + else if (ess_major != 0) + { + if (ess_major == 0x48 && (ess_minor & 0xf0) == 0x80) + sprintf (sb_dsp_operations.name, "ESS ES488 AudioDrive (rev %d)", + ess_minor & 0x0f); + else if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80) + { + sprintf (sb_dsp_operations.name, + "ESS ES1688 AudioDrive (rev %d)", + ess_minor & 0x0f); + sb_dsp_operations.format_mask |= AFMT_S16_LE; + ess_init (); + } + } else { sprintf (sb_dsp_operations.name, "SoundBlaster Pro %d.%d", sbc_major, sbc_minor); @@ -1238,23 +1500,26 @@ sprintf (sb_dsp_operations.name, "SoundBlaster %d.%d", sbc_major, sbc_minor); } - printk (" <%s>", sb_dsp_operations.name); + conf_printf (sb_dsp_operations.name, hw_config); -#if !defined(EXCLUDE_SB16) && !defined(EXCLUDE_SBPRO) - if (!sb16) /* - * There is a better driver for SB16 - */ -#endif + if (sbc_major >= 3) + mixer_type = sb_mixer_init (sbc_major); + + if (!sb16) if (num_audiodevs < MAX_AUDIO_DEV) { audio_devs[my_dev = num_audiodevs++] = &sb_dsp_operations; + + if (AudioDrive) + audio_devs[my_dev]->flags |= DMA_AUTOMODE; + audio_devs[my_dev]->buffsize = DSP_BUFFSIZE; dma8 = audio_devs[my_dev]->dmachan1 = hw_config->dma; audio_devs[my_dev]->dmachan2 = -1; - if (sound_alloc_dma (hw_config->dma, "soundblaster")) + if (sound_alloc_dma (hw_config->dma, "SoundBlaster")) printk ("sb_dsp.c: Can't allocate DMA channel\n"); -#ifdef JAZZ16 - /* Allocate 16 bit dma + + /* Allocate 16 bit dma (Jazz16) */ if (Jazz16_detected != 0) if (dma16 != dma8) @@ -1264,15 +1529,14 @@ printk ("Jazz16: Can't allocate 16 bit DMA channel\n"); } } -#endif } else printk ("SB: Too many DSP devices available\n"); #else - printk (" "); + conf_printf ("SoundBlaster (configured without audio support)", hw_config); #endif -#ifndef EXCLUDE_MIDI +#ifdef CONFIG_MIDI if (!midi_disabled && !sb16) /* * Midi don't work in the SB emulation mode * * of PAS, SB16 has better midi interface @@ -1288,16 +1552,20 @@ sb_dsp_unload (void) { sound_free_dma (dma8); -#ifdef JAZZ16 - /* Allocate 16 bit dma + + /* Free 16 bit dma (Jazz16) */ if (Jazz16_detected != 0) if (dma16 != dma8) { sound_free_dma (dma16); } -#endif snd_release_irq (sbc_irq); + + if (AudioDrive && ess_mpu_irq) + { + snd_release_irq (ess_mpu_irq); + } } void diff -u --recursive --new-file v1.3.57/linux/drivers/sound/sb_midi.c linux/drivers/sound/sb_midi.c --- v1.3.57/linux/drivers/sound/sb_midi.c Fri Oct 13 14:44:43 1995 +++ linux/drivers/sound/sb_midi.c Tue Jan 9 00:37:35 1996 @@ -29,7 +29,7 @@ #include "sound_config.h" -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB) && !defined(EXCLUDE_MIDI) +#if defined(CONFIG_SB) && defined(CONFIG_MIDI) #include "sb.h" #undef SB_TEST_IRQ diff -u --recursive --new-file v1.3.57/linux/drivers/sound/sb_mixer.c linux/drivers/sound/sb_mixer.c --- v1.3.57/linux/drivers/sound/sb_mixer.c Wed Nov 8 07:11:36 1995 +++ linux/drivers/sound/sb_mixer.c Tue Jan 9 00:37:36 1996 @@ -34,7 +34,7 @@ #include "sound_config.h" -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB) && !defined(EXCLUDE_SBPRO) +#if defined(CONFIG_SB) #define __SB_MIXER_C__ #include "sb.h" @@ -44,6 +44,7 @@ extern int sbc_base; extern int Jazz16_detected; extern sound_os_info *sb_osp; +extern int AudioDrive; static int mixer_initialized = 0; @@ -64,9 +65,9 @@ outb ((unsigned char) (port & 0xff), MIXER_ADDR); /* * Select register */ - tenmicrosec (); + tenmicrosec (sb_osp); outb ((unsigned char) (value & 0xff), MIXER_DATA); - tenmicrosec (); + tenmicrosec (sb_osp); restore_flags (flags); } @@ -81,9 +82,9 @@ outb ((unsigned char) (port & 0xff), MIXER_ADDR); /* * Select register */ - tenmicrosec (); + tenmicrosec (sb_osp); val = inb (MIXER_DATA); - tenmicrosec (); + tenmicrosec (sb_osp); restore_flags (flags); return val; @@ -201,7 +202,6 @@ return levels[dev]; } -#ifdef JAZZ16 static char smw_mix_regs[] = /* Left mixer registers */ { 0x0b, /* SOUND_MIXER_VOLUME */ @@ -293,8 +293,6 @@ return left | (right << 8); } -#endif - static int sb_mixer_set (int dev, int value) { @@ -304,10 +302,8 @@ int regoffs; unsigned char val; -#ifdef JAZZ16 if (Jazz16_detected == 2) return smw_mixer_set (dev, value); -#endif if (left > 100) left = 100; @@ -449,7 +445,7 @@ { if (((cmd >> 8) & 0xff) == 'M') { - if (cmd & IOC_IN) + if (_IOC_DIR (cmd) & _IOC_WRITE) switch (cmd & 0xff) { case SOUND_MIXER_RECSRC: @@ -539,8 +535,13 @@ case 3: mixer_caps = SOUND_CAP_EXCL_INPUT; -#ifdef JAZZ16 - if (Jazz16_detected == 2) /* SM Wave */ + if (AudioDrive) + { + supported_devices = ES688_MIXER_DEVICES; + supported_rec_devices = ES688_RECORDING_DEVICES; + iomap = &es688_mix; + } + else if (Jazz16_detected == 2) /* SM Wave */ { supported_devices = 0; supported_rec_devices = 0; @@ -549,7 +550,6 @@ mixer_type = 1; } else -#endif #ifdef __SGNXPRO__ if (mixer_type == 2) /* A SGNXPRO was detected */ { diff -u --recursive --new-file v1.3.57/linux/drivers/sound/sb_mixer.h linux/drivers/sound/sb_mixer.h --- v1.3.57/linux/drivers/sound/sb_mixer.h Tue Jul 11 10:02:54 1995 +++ linux/drivers/sound/sb_mixer.h Tue Jan 9 00:36:56 1996 @@ -50,6 +50,9 @@ #define SB16_RECORDING_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_LINE | SOUND_MASK_MIC | \ SOUND_MASK_CD) +#define ES688_RECORDING_DEVICES SBPRO_RECORDING_DEVICES +#define ES688_MIXER_DEVICES (SBPRO_MIXER_DEVICES|SOUND_MASK_LINE2|SOUND_MASK_SPEAKER) + #define SB16_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \ SOUND_MASK_CD | \ SOUND_MASK_IGAIN | SOUND_MASK_OGAIN | \ @@ -131,6 +134,25 @@ MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0), MIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0) }; +mixer_tab es688_mix = { +MIX_ENT(SOUND_MIXER_VOLUME, 0x32, 7, 4, 0x32, 3, 4), +MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0), +MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0), +MIX_ENT(SOUND_MIXER_SYNTH, 0x36, 7, 4, 0x36, 3, 4), +MIX_ENT(SOUND_MIXER_PCM, 0x14, 7, 4, 0x14, 3, 4), +MIX_ENT(SOUND_MIXER_SPEAKER, 0x3c, 2, 3, 0x00, 0, 0), +MIX_ENT(SOUND_MIXER_LINE, 0x3e, 7, 4, 0x3e, 3, 4), +MIX_ENT(SOUND_MIXER_MIC, 0x1a, 7, 4, 0x1a, 3, 4), +MIX_ENT(SOUND_MIXER_CD, 0x38, 7, 4, 0x38, 3, 4), +MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0), +MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0), +MIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0), +MIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0), +MIX_ENT(SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0), +MIX_ENT(SOUND_MIXER_LINE1, 0x00, 0, 0, 0x00, 0, 0), +MIX_ENT(SOUND_MIXER_LINE2, 0x3a, 7, 4, 0x3a, 3, 4), +MIX_ENT(SOUND_MIXER_LINE3, 0x00, 0, 0, 0x00, 0, 0) +}; #ifdef __SGNXPRO__ mixer_tab sgnxpro_mix = { @@ -187,7 +209,10 @@ 0x4b4b, /* SB PCM */ 0x4b4b, /* Recording level */ 0x4b4b, /* Input gain */ - 0x4b4b}; /* Output gain */ + 0x4b4b, /* Output gain */ + 0x4040, /* Line1 */ + 0x4040, /* Line2 */ + 0x1515 /* Line3 */ #else /* If the user selected just plain SB Pro */ @@ -206,7 +231,11 @@ 0x4b4b, /* SB PCM */ 0x4b4b, /* Recording level */ 0x4b4b, /* Input gain */ - 0x4b4b}; /* Output gain */ + 0x4b4b, /* Output gain */ + 0x4040, /* Line1 */ + 0x4040, /* Line2 */ + 0x1515 /* Line3 */ +}; #endif /* SM_GAMES */ static unsigned char sb16_recmasks_L[SOUND_MIXER_NRDEVICES] = diff -u --recursive --new-file v1.3.57/linux/drivers/sound/sequencer.c linux/drivers/sound/sequencer.c --- v1.3.57/linux/drivers/sound/sequencer.c Wed Nov 8 07:11:36 1995 +++ linux/drivers/sound/sequencer.c Tue Jan 9 00:37:39 1996 @@ -30,9 +30,7 @@ #define SEQUENCER_C #include "sound_config.h" -#ifdef CONFIGURE_SOUNDCARD - -#ifndef EXCLUDE_SEQUENCER +#ifdef CONFIG_SEQUENCER #include "midi_ctrl.h" @@ -58,10 +56,10 @@ #define SEQ_2 2 static int seq_mode = SEQ_1; -static struct wait_queue *seq_sleeper = NULL; +static wait_handle *seq_sleeper = NULL; static volatile struct snd_wait seq_sleep_flag = {0}; -static struct wait_queue *midi_sleeper = NULL; +static wait_handle *midi_sleeper = NULL; static volatile struct snd_wait midi_sleep_flag = {0}; @@ -84,7 +82,7 @@ static volatile int qhead = 0, qtail = 0, qlen = 0; static volatile int iqhead = 0, iqtail = 0, iqlen = 0; static volatile int seq_playing = 0; -static int sequencer_busy = 0; +static volatile int sequencer_busy = 0; static int output_treshold; static int pre_event_timeout; static unsigned synth_open_mask; @@ -132,11 +130,11 @@ unsigned long tl; if (pre_event_timeout) - current->timeout = tl = jiffies + (pre_event_timeout); + current_set_timeout (tl = jiffies + (pre_event_timeout)); else tl = 0xffffffff; midi_sleep_flag.mode = WK_SLEEP; - interruptible_sleep_on (&midi_sleeper); + module_interruptible_sleep_on (&midi_sleeper); if (!(midi_sleep_flag.mode & WK_WAKEUP)) { if (jiffies >= tl) @@ -202,7 +200,7 @@ { { midi_sleep_flag.mode = WK_WAKEUP; - wake_up (&midi_sleeper); + module_wake_up (&midi_sleeper); }; } restore_flags (flags); @@ -276,9 +274,7 @@ if (mode == OPEN_READ) return -EIO; - if (dev) /* - * Patch manager device - */ + if (dev) return pmgr_write (dev - 1, file, buf, count); c = count; @@ -412,22 +408,9 @@ * Sleep until there is enough space on the queue */ - { - unsigned long tl; - - if (0) - current->timeout = tl = jiffies + (0); - else - tl = 0xffffffff; - seq_sleep_flag.mode = WK_SLEEP; - interruptible_sleep_on (&seq_sleeper); - if (!(seq_sleep_flag.mode & WK_WAKEUP)) - { - if (jiffies >= tl) - seq_sleep_flag.mode |= WK_TIMEOUT; - } - seq_sleep_flag.mode &= ~WK_SLEEP; - }; + seq_sleep_flag.mode = WK_SLEEP; + module_interruptible_sleep_on (&seq_sleeper); + seq_sleep_flag.mode &= ~WK_SLEEP;; } if (qlen >= SEQ_MAX_QUEUE) @@ -729,7 +712,7 @@ { { seq_sleep_flag.mode = WK_WAKEUP; - wake_up (&seq_sleeper); + module_wake_up (&seq_sleeper); }; } restore_flags (flags); @@ -769,7 +752,7 @@ { { seq_sleep_flag.mode = WK_WAKEUP; - wake_up (&seq_sleeper); + module_wake_up (&seq_sleeper); }; } restore_flags (flags); @@ -819,7 +802,7 @@ switch (cmd) { case LOCL_STARTAUDIO: -#ifndef EXCLUDE_AUDIO +#ifdef CONFIG_AUDIO DMAbuf_start_devices (parm); #endif break; @@ -905,7 +888,7 @@ { { seq_sleep_flag.mode = WK_WAKEUP; - wake_up (&seq_sleeper); + module_wake_up (&seq_sleeper); }; } restore_flags (flags); @@ -1041,7 +1024,7 @@ { { seq_sleep_flag.mode = WK_WAKEUP; - wake_up (&seq_sleeper); + module_wake_up (&seq_sleeper); }; } restore_flags (flags); @@ -1095,6 +1078,7 @@ { int retval, mode, i; int level, tmp; + unsigned long flags; level = ((dev & 0x0f) == SND_DEV_SEQ2) ? 2 : 1; @@ -1109,9 +1093,7 @@ return -ENXIO; } - if (dev) /* - * Patch manager device - */ + if (dev) /* Patch manager device */ { int err; @@ -1125,19 +1107,22 @@ if (pmgr_present[dev]) return -EBUSY; if ((err = pmgr_open (dev)) < 0) - return err; /* - * Failed - */ + return err; pmgr_present[dev] = 1; return err; } + save_flags (flags); + cli (); if (sequencer_busy) { printk ("Sequencer busy\n"); + restore_flags (flags); return -EBUSY; } + sequencer_busy = 1; + restore_flags (flags); max_mididev = num_midis; max_synthdev = num_synths; @@ -1173,6 +1158,7 @@ if (tmr == NULL) { printk ("sequencer: No timer for level 2\n"); + sequencer_busy = 0; return -ENXIO; } setup_mode2 (); @@ -1182,6 +1168,7 @@ if (!max_mididev) { printk ("Sequencer: No Midi devices. Input not possible\n"); + sequencer_busy = 0; return -ENXIO; } @@ -1239,7 +1226,6 @@ tmr->open (tmr_no, seq_mode); } - sequencer_busy = 1; seq_sleep_flag.mode = WK_NONE; midi_sleep_flag.mode = WK_NONE; output_treshold = SEQ_MAX_QUEUE / 2; @@ -1262,7 +1248,7 @@ n = 1; - while (!(current->signal & ~current->blocked) && n) + while (!current_got_fatal_signal () && n) { n = 0; @@ -1282,11 +1268,11 @@ unsigned long tl; if (HZ / 10) - current->timeout = tl = jiffies + (HZ / 10); + current_set_timeout (tl = jiffies + (HZ / 10)); else tl = 0xffffffff; seq_sleep_flag.mode = WK_SLEEP; - interruptible_sleep_on (&seq_sleeper); + module_interruptible_sleep_on (&seq_sleeper); if (!(seq_sleep_flag.mode & WK_WAKEUP)) { if (jiffies >= tl) @@ -1324,7 +1310,7 @@ if (mode != OPEN_READ && !(file->flags & (O_NONBLOCK) ? 1 : 0)) - while (!(current->signal & ~current->blocked) && qlen) + while (!current_got_fatal_signal () && qlen) { seq_sync (); } @@ -1370,7 +1356,7 @@ { unsigned long flags; - if (qlen && !seq_playing && !(current->signal & ~current->blocked)) + if (qlen && !seq_playing && !current_got_fatal_signal ()) seq_startplay (); save_flags (flags); @@ -1381,12 +1367,12 @@ { unsigned long tl; - if (0) - current->timeout = tl = jiffies + (0); + if (HZ) + current_set_timeout (tl = jiffies + (HZ)); else tl = 0xffffffff; seq_sleep_flag.mode = WK_SLEEP; - interruptible_sleep_on (&seq_sleeper); + module_interruptible_sleep_on (&seq_sleeper); if (!(seq_sleep_flag.mode & WK_WAKEUP)) { if (jiffies >= tl) @@ -1427,11 +1413,11 @@ unsigned long tl; if (4) - current->timeout = tl = jiffies + (4); + current_set_timeout (tl = jiffies + (4)); else tl = 0xffffffff; seq_sleep_flag.mode = WK_SLEEP; - interruptible_sleep_on (&seq_sleeper); + module_interruptible_sleep_on (&seq_sleeper); if (!(seq_sleep_flag.mode & WK_WAKEUP)) { if (jiffies >= tl) @@ -1521,7 +1507,7 @@ /* printk ("Sequencer Warning: Unexpected sleeping process - Waking up\n"); */ { seq_sleep_flag.mode = WK_WAKEUP; - wake_up (&seq_sleeper); + module_wake_up (&seq_sleeper); }; } restore_flags (flags); @@ -1605,7 +1591,7 @@ if (mode == OPEN_READ) return 0; - while (qlen && !(current->signal & ~current->blocked)) + while (qlen && !current_got_fatal_signal ()) seq_sync (); if (qlen) return -EINTR; @@ -1921,7 +1907,7 @@ } int -sequencer_select (int dev, struct fileinfo *file, int sel_type, select_table * wait) +sequencer_select (int dev, struct fileinfo *file, int sel_type, select_table_handle * wait) { unsigned long flags; @@ -1935,7 +1921,7 @@ if (!iqlen) { midi_sleep_flag.mode = WK_SLEEP; - select_wait (&midi_sleeper, wait); + module_select_wait (&midi_sleeper, wait); restore_flags (flags); return 0; } @@ -1947,10 +1933,10 @@ case SEL_OUT: save_flags (flags); cli (); - if (qlen >= SEQ_MAX_QUEUE) + if ((SEQ_MAX_QUEUE - qlen) < output_treshold) { seq_sleep_flag.mode = WK_SLEEP; - select_wait (&seq_sleeper, wait); + module_select_wait (&seq_sleeper, wait); restore_flags (flags); return 0; } @@ -2074,7 +2060,5 @@ return mem_start; } - -#endif #endif diff -u --recursive --new-file v1.3.57/linux/drivers/sound/sound_calls.h linux/drivers/sound/sound_calls.h --- v1.3.57/linux/drivers/sound/sound_calls.h Mon Oct 23 18:02:16 1995 +++ linux/drivers/sound/sound_calls.h Tue Jan 9 00:36:57 1996 @@ -5,9 +5,11 @@ int DMAbuf_open(int dev, int mode); int DMAbuf_release(int dev, int mode); int DMAbuf_getwrbuffer(int dev, char **buf, int *size, int dontblock); +int DMAbuf_get_curr_buffer(int dev, int *buff_no, char **dma_buf, int *buff_ptr, int *buff_size); 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_set_count(int dev, int buff_no, int l); 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); @@ -16,7 +18,7 @@ void DMAbuf_reset_dma (int dev); void DMAbuf_inputintr(int dev); void DMAbuf_outputintr(int dev, int underflow_flag); -int DMAbuf_select(int dev, struct fileinfo *file, int sel_type, select_table * wait); +int DMAbuf_select(int dev, struct fileinfo *file, int sel_type, select_table_handle * wait); void DMAbuf_start_devices(unsigned int devmask); /* @@ -32,7 +34,7 @@ int audio_lseek (int dev, struct fileinfo *file, off_t offset, int orig); long audio_init (long mem_start); -int audio_select(int dev, struct fileinfo *file, int sel_type, select_table * wait); +int audio_select(int dev, struct fileinfo *file, int sel_type, select_table_handle * wait); /* * System calls for the /dev/sequencer @@ -52,7 +54,7 @@ void seq_input_event(unsigned char *event, int len); void seq_copy_to_input (unsigned char *event, int len); -int sequencer_select(int dev, struct fileinfo *file, int sel_type, select_table * wait); +int sequencer_select(int dev, struct fileinfo *file, int sel_type, select_table_handle * wait); /* * System calls for the /dev/midi @@ -68,7 +70,7 @@ void MIDIbuf_bytes_received(int dev, unsigned char *buf, int count); long MIDIbuf_init(long mem_start); -int MIDIbuf_select(int dev, struct fileinfo *file, int sel_type, select_table * wait); +int MIDIbuf_select(int dev, struct fileinfo *file, int sel_type, select_table_handle * wait); /* * @@ -77,7 +79,7 @@ /* From soundcard.c */ void soundcard_init(void); -void tenmicrosec(void); +void tenmicrosec(sound_os_info *osp); void request_sound_timer (int count); void sound_stop_timer(void); int snd_ioctl_return(int *addr, int value); @@ -85,6 +87,8 @@ void snd_release_irq(int vect); void sound_dma_malloc(int dev); void sound_dma_free(int dev); +void conf_printf(char *name, struct address_info *hw_config); +void conf_printf2(char *name, int base, int irq, int dma, int dma2); /* From sound_switch.c */ int sound_read_sw (int dev, struct fileinfo *file, snd_rw_buf *buf, int count); @@ -114,6 +118,7 @@ long attach_sb16midi(long mem_start, struct address_info * hw_config); int probe_sb16midi(struct address_info *hw_config); void sb_midi_interrupt(int dummy); +void sbmidiintr(int irq, struct pt_regs * dummy); /* From sb_midi.c */ void sb_midi_init(int model); @@ -268,6 +273,7 @@ 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); +void mad16_sb_dsp_unload(struct address_info *hw_config); /* Unload routines from various source files*/ void unload_pss(struct address_info *hw_info); diff -u --recursive --new-file v1.3.57/linux/drivers/sound/sound_config.h linux/drivers/sound/sound_config.h --- v1.3.57/linux/drivers/sound/sound_config.h Wed Nov 8 07:11:36 1995 +++ linux/drivers/sound/sound_config.h Tue Jan 9 00:36:57 1996 @@ -28,18 +28,8 @@ * */ -#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 "local.h" #include "soundvers.h" #if defined(ISC) || defined(SCO) || defined(SVR42) @@ -51,13 +41,10 @@ - #ifndef SND_DEFAULT_ENABLE #define SND_DEFAULT_ENABLE 1 #endif -#ifdef CONFIGURE_SOUNDCARD - #ifndef MAX_REALTIME_FACTOR #define MAX_REALTIME_FACTOR 4 #endif @@ -89,10 +76,16 @@ #define PAS_BASE 0x388 #endif -#ifdef JAZZ16 -#ifndef JAZZ_DMA16 -#define JAZZ_DMA16 5 +#if defined(SB16_DMA) && !defined(SB_DMA2) +# define SB_DMA2 SB16_DMA +#endif + +#if defined(SB16MIDI_BASE) && !defined(SB_MPU_BASE) +# define SB_MPU_BASE SB16MIDI_BASE #endif + +#ifndef SB_MPU_IRQ +# define SB_MPU_IRQ SBC_IRQ #endif /* SEQ_MAX_QUEUE is the maximum number of sequencer events buffered by the @@ -198,5 +191,3 @@ #define TIMER_ARMED 121234 #define TIMER_NOT_ARMED 1 - -#endif diff -u --recursive --new-file v1.3.57/linux/drivers/sound/sound_pnp.c linux/drivers/sound/sound_pnp.c --- v1.3.57/linux/drivers/sound/sound_pnp.c Wed Nov 8 07:11:36 1995 +++ linux/drivers/sound/sound_pnp.c Tue Jan 9 00:37:39 1996 @@ -28,7 +28,7 @@ */ #include "sound_config.h" -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_PNP) +#if defined(CONFIG_PNP) #include diff -u --recursive --new-file v1.3.57/linux/drivers/sound/sound_switch.c linux/drivers/sound/sound_switch.c --- v1.3.57/linux/drivers/sound/sound_switch.c Wed Nov 8 07:11:37 1995 +++ linux/drivers/sound/sound_switch.c Tue Jan 9 00:37:40 1996 @@ -29,17 +29,11 @@ #include "sound_config.h" -#ifdef CONFIGURE_SOUNDCARD - struct sbc_device { int usecount; }; -static struct sbc_device sbc_devices[SND_NDEVS] = -{ - {0}}; - static int in_use = 0; /* @@ -210,7 +204,7 @@ return; } -#ifdef EXCLUDE_AUDIO +#ifndef CONFIG_AUDIO if (!put_status ("\nAudio devices: NOT ENABLED IN CONFIG\n")) return; #else @@ -235,7 +229,7 @@ } #endif -#ifdef EXCLUDE_SEQUENCER +#ifndef CONFIG_SEQUENCER if (!put_status ("\nSynth devices: NOT ENABLED IN CONFIG\n")) return; #else @@ -255,7 +249,7 @@ } #endif -#ifdef EXCLUDE_MIDI +#ifndef CONFIG_MIDI if (!put_status ("\nMidi devices: NOT ENABLED IN CONFIG\n")) return; #else @@ -339,7 +333,7 @@ return read_status (buf, count); break; -#ifndef EXCLUDE_AUDIO +#ifdef CONFIG_AUDIO case SND_DEV_DSP: case SND_DEV_DSP16: case SND_DEV_AUDIO: @@ -347,14 +341,14 @@ break; #endif -#ifndef EXCLUDE_SEQUENCER +#ifdef CONFIG_SEQUENCER case SND_DEV_SEQ: case SND_DEV_SEQ2: return sequencer_read (dev, file, buf, count); break; #endif -#ifndef EXCLUDE_MIDI +#ifdef CONFIG_MIDI case SND_DEV_MIDIN: return MIDIbuf_read (dev, file, buf, count); #endif @@ -375,14 +369,14 @@ switch (dev & 0x0f) { -#ifndef EXCLUDE_SEQUENCER +#ifdef CONFIG_SEQUENCER case SND_DEV_SEQ: case SND_DEV_SEQ2: return sequencer_write (dev, file, buf, count); break; #endif -#ifndef EXCLUDE_AUDIO +#ifdef CONFIG_AUDIO case SND_DEV_DSP: case SND_DEV_DSP16: case SND_DEV_AUDIO: @@ -390,7 +384,7 @@ break; #endif -#ifndef EXCLUDE_MIDI +#ifdef CONFIG_MIDI case SND_DEV_MIDIN: return MIDIbuf_write (dev, file, buf, count); #endif @@ -407,7 +401,7 @@ { int retval; - DEB (printk ("sound_open_sw(dev=%d) : usecount=%d\n", dev, sbc_devices[dev].usecount)); + DEB (printk ("sound_open_sw(dev=%d)\n", dev)); if ((dev >= SND_NDEVS) || (dev < 0)) { @@ -431,7 +425,7 @@ return 0; break; -#ifndef EXCLUDE_SEQUENCER +#ifdef CONFIG_SEQUENCER case SND_DEV_SEQ: case SND_DEV_SEQ2: if ((retval = sequencer_open (dev, file)) < 0) @@ -439,14 +433,14 @@ break; #endif -#ifndef EXCLUDE_MIDI +#ifdef CONFIG_MIDI case SND_DEV_MIDIN: if ((retval = MIDIbuf_open (dev, file)) < 0) return retval; break; #endif -#ifndef EXCLUDE_AUDIO +#ifdef CONFIG_AUDIO case SND_DEV_DSP: case SND_DEV_DSP16: case SND_DEV_AUDIO: @@ -460,7 +454,6 @@ return -ENXIO; } - sbc_devices[dev].usecount++; in_use++; return 0; @@ -484,20 +477,20 @@ case SND_DEV_CTL: break; -#ifndef EXCLUDE_SEQUENCER +#ifdef CONFIG_SEQUENCER case SND_DEV_SEQ: case SND_DEV_SEQ2: sequencer_release (dev, file); break; #endif -#ifndef EXCLUDE_MIDI +#ifdef CONFIG_MIDI case SND_DEV_MIDIN: MIDIbuf_release (dev, file); break; #endif -#ifndef EXCLUDE_AUDIO +#ifdef CONFIG_AUDIO case SND_DEV_DSP: case SND_DEV_DSP16: case SND_DEV_AUDIO: @@ -508,8 +501,6 @@ default: printk ("Sound error: Releasing unknown device 0x%02x\n", dev); } - - sbc_devices[dev].usecount--; in_use--; } @@ -527,7 +518,7 @@ switch (dtype) { -#ifndef EXCLUDE_AUDIO +#ifdef CONFIG_AUDIO case SND_DEV_DSP: case SND_DEV_DSP16: case SND_DEV_AUDIO: @@ -559,14 +550,14 @@ return mixer_devs[dev]->ioctl (dev, cmd, arg); break; -#ifndef EXCLUDE_SEQUENCER +#ifdef CONFIG_SEQUENCER case SND_DEV_SEQ: case SND_DEV_SEQ2: return sequencer_ioctl (dev, file, cmd, arg); break; #endif -#ifndef EXCLUDE_AUDIO +#ifdef CONFIG_AUDIO case SND_DEV_DSP: case SND_DEV_DSP16: case SND_DEV_AUDIO: @@ -574,7 +565,7 @@ break; #endif -#ifndef EXCLUDE_MIDI +#ifdef CONFIG_MIDI case SND_DEV_MIDIN: return MIDIbuf_ioctl (dev, file, cmd, arg); break; @@ -587,5 +578,3 @@ return -EPERM; } - -#endif diff -u --recursive --new-file v1.3.57/linux/drivers/sound/sound_timer.c linux/drivers/sound/sound_timer.c --- v1.3.57/linux/drivers/sound/sound_timer.c Mon Oct 23 18:02:16 1995 +++ linux/drivers/sound/sound_timer.c Tue Jan 9 00:37:40 1996 @@ -28,9 +28,7 @@ #define SEQUENCER_C #include "sound_config.h" -#ifdef CONFIGURE_SOUNDCARD - -#if !defined(EXCLUDE_SEQUENCER) +#if defined(CONFIG_SEQUENCER) static volatile int initialized = 0, opened = 0, tmr_running = 0; static volatile time_t tmr_offs, tmr_ctr; @@ -351,5 +349,4 @@ sound_timer_devs[n] = &sound_timer; } -#endif #endif diff -u --recursive --new-file v1.3.57/linux/drivers/sound/soundcard.c linux/drivers/sound/soundcard.c --- v1.3.57/linux/drivers/sound/soundcard.c Tue Dec 26 04:45:37 1995 +++ linux/drivers/sound/soundcard.c Tue Jan 9 00:37:41 1996 @@ -29,15 +29,12 @@ /* * Created modular version by Peter Trattler (peter@sbox.tu-graz.ac.at) */ -#include #include "sound_config.h" -#ifdef CONFIGURE_SOUNDCARD - #include -#ifndef EXCLUDE_PNP +#ifdef CONFIG_PNP #include #endif @@ -73,37 +70,37 @@ } static int -sound_read (struct inode *inode, struct file *file, char *buf, int count) +sound_read (inode_handle * inode, file_handle * file, char *buf, int count) { int dev; - dev = inode->i_rdev; + dev = inode_get_rdev (inode); dev = MINOR (dev); - files[dev].flags = file->f_flags; + files[dev].flags = file_get_flags (file); return sound_read_sw (dev, &files[dev], buf, count); } static int -sound_write (struct inode *inode, struct file *file, const char *buf, int count) +sound_write (inode_handle * inode, file_handle * file, const char *buf, int count) { int dev; - dev = inode->i_rdev; + dev = inode_get_rdev (inode); dev = MINOR (dev); - files[dev].flags = file->f_flags; + files[dev].flags = file_get_flags (file); return sound_write_sw (dev, &files[dev], buf, count); } static int -sound_lseek (struct inode *inode, struct file *file, off_t offset, int orig) +sound_lseek (inode_handle * inode, file_handle * file, off_t offset, int orig) { return -EPERM; } static int -sound_open (struct inode *inode, struct file *file) +sound_open (inode_handle * inode, file_handle * file) { int dev, retval; struct fileinfo tmp_file; @@ -114,7 +111,7 @@ return -EBUSY; } - dev = inode->i_rdev; + dev = inode_get_rdev (inode); dev = MINOR (dev); if (!soundcard_configured && dev != SND_DEV_CTL && dev != SND_DEV_STATUS) @@ -124,7 +121,7 @@ } tmp_file.mode = 0; - tmp_file.flags = file->f_flags; + tmp_file.flags = file_get_flags (file); if ((tmp_file.flags & O_ACCMODE) == O_RDWR) tmp_file.mode = OPEN_READWRITE; @@ -145,13 +142,13 @@ } static void -sound_release (struct inode *inode, struct file *file) +sound_release (inode_handle * inode, file_handle * file) { int dev; - dev = inode->i_rdev; + dev = inode_get_rdev (inode); dev = MINOR (dev); - files[dev].flags = file->f_flags; + files[dev].flags = file_get_flags (file); sound_release_sw (dev, &files[dev]); #ifdef MODULE @@ -160,31 +157,31 @@ } static int -sound_ioctl (struct inode *inode, struct file *file, +sound_ioctl (inode_handle * inode, file_handle * file, unsigned int cmd, unsigned long arg) { int dev, err; - dev = inode->i_rdev; + dev = inode_get_rdev (inode); dev = MINOR (dev); - files[dev].flags = file->f_flags; + files[dev].flags = file_get_flags (file); - if (cmd & IOC_INOUT) + if (_IOC_DIR (cmd) != _IOC_NONE) { /* * Have to validate the address given by the process. */ int len; - len = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT; + len = _IOC_SIZE (cmd); - if (cmd & IOC_IN) + if (_IOC_DIR (cmd) == _IOC_WRITE) { if ((err = verify_area (VERIFY_READ, (void *) arg, len)) < 0) return err; } - if (cmd & IOC_OUT) + if (_IOC_DIR (cmd) == _IOC_READ) { if ((err = verify_area (VERIFY_WRITE, (void *) arg, len)) < 0) return err; @@ -198,32 +195,32 @@ } static int -sound_select (struct inode *inode, struct file *file, int sel_type, select_table * wait) +sound_select (inode_handle * inode, file_handle * file, int sel_type, select_table_handle * wait) { int dev; - dev = inode->i_rdev; + dev = inode_get_rdev (inode); dev = MINOR (dev); - files[dev].flags = file->f_flags; + files[dev].flags = file_get_flags (file); DEB (printk ("sound_select(dev=%d, type=0x%x)\n", dev, sel_type)); switch (dev & 0x0f) { -#ifndef EXCLUDE_SEQUENCER +#ifdef CONFIG_SEQUENCER case SND_DEV_SEQ: case SND_DEV_SEQ2: return sequencer_select (dev, &files[dev], sel_type, wait); break; #endif -#ifndef EXCLUDE_MIDI +#ifdef CONFIG_MIDI case SND_DEV_MIDIN: return MIDIbuf_select (dev, &files[dev], sel_type, wait); break; #endif -#ifndef EXCLUDE_AUDIO +#ifdef CONFIG_AUDIO case SND_DEV_DSP: case SND_DEV_DSP16: case SND_DEV_AUDIO: @@ -238,8 +235,98 @@ return 0; } +#ifdef ALLOW_BUFFER_MAPPING +static int +sound_mmap (inode_handle * inode, file_handle * file, vm_area_handle * vma) +{ + int dev, dev_class; + unsigned long size, i; + struct dma_buffparms *dmap = NULL; + + dev = inode_get_rdev (inode); + dev = MINOR (dev); + files[dev].flags = file_get_flags (file); + + 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_get_flags (vma) & (VM_READ | VM_WRITE)) == (VM_READ | VM_WRITE)) + { + printk ("Sound: Cannot do read/write mmap()\n"); + return -EINVAL; + } + + if (vma_get_flags (vma) & VM_READ) + { + dmap = audio_devs[dev]->dmap_in; + } + else if (vma_get_flags (vma) & 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_get_offset (vma) != 0) + { + printk ("Sound: mmap() offset must be 0.\n"); + return -EINVAL; + } + + size = vma_get_end (vma) - vma_get_start (vma); -static struct file_operations sound_fops = + 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_get_start (vma), dmap->raw_buf_phys, + vma_get_end (vma) - vma_get_start (vma), + vma_get_page_prot (vma))) + return -EAGAIN; + + vma_set_inode (vma, inode); + inode_inc_count (inode); + + dmap->mapping_flags |= DMA_MAP_MAPPED; + + memset (dmap->raw_buf, + dmap->neutral_byte, + dmap->bytes_in_use); + return 0; +} +#endif + +static struct file_operation_handle sound_fops = { sound_lseek, sound_read, @@ -247,7 +334,11 @@ NULL, /* sound_readdir */ sound_select, sound_ioctl, +#ifdef ALLOW_BUFFER_MAPPING + sound_mmap, +#else NULL, +#endif sound_open, sound_release }; @@ -256,7 +347,7 @@ soundcard_init (void) { #ifndef MODULE - register_chrdev (SOUND_MAJOR, "sound", &sound_fops); + module_register_chrdev (SOUND_MAJOR, "sound", &sound_fops); chrdev_registered = 1; #endif @@ -265,14 +356,14 @@ sndtable_init (0); /* Initialize call tables and * detect cards */ -#ifndef EXCLUDE_PNP +#ifdef CONFIG_PNP sound_pnp_init (); #endif if (sndtable_get_cardcount () == 0) return; /* No cards detected */ -#ifndef EXCLUDE_AUDIO +#ifdef CONFIG_AUDIO if (num_audiodevs) /* Audio devices present */ { DMAbuf_init (0); @@ -280,12 +371,12 @@ } #endif -#ifndef EXCLUDE_MIDI +#ifdef CONFIG_MIDI if (num_midis) MIDIbuf_init (0); #endif -#ifndef EXCLUDE_SEQUENCER +#ifdef CONFIG_SEQUENCER if (num_midis + num_synths) sequencer_init (0); #endif @@ -309,6 +400,8 @@ irqs = 0; } +char kernel_version[] = UTS_RELEASE; + #endif static int debugmem = 0; /* switched off by default */ @@ -323,7 +416,7 @@ int ints[21]; int i; - if (0 < 0) + if (connect_wrapper (WRAPPER_VERSION) < 0) { printk ("Sound: Incompatible kernel (wrapper) version\n"); return -EINVAL; @@ -340,7 +433,7 @@ if (i) sound_setup ("sound=", ints); - err = register_chrdev (SOUND_MAJOR, "sound", &sound_fops); + err = module_register_chrdev (SOUND_MAJOR, "sound", &sound_fops); if (err) { printk ("sound: driver already loaded/included in kernel\n"); @@ -369,9 +462,9 @@ int i; if (chrdev_registered) - unregister_chrdev (SOUND_MAJOR, "sound"); + module_unregister_chrdev (SOUND_MAJOR, "sound"); -#ifndef EXCLUDE_SEQUENCER +#ifdef CONFIG_SEQUENCER sound_stop_timer (); #endif sound_unload_drivers (); @@ -388,7 +481,7 @@ sound_free_dma (i); } -#ifndef EXCLUDE_PNP +#ifdef CONFIG_PNP sound_pnp_disconnect (); #endif @@ -397,7 +490,7 @@ #endif void -tenmicrosec (void) +tenmicrosec (sound_os_info * osp) { int i; @@ -466,7 +559,7 @@ { if (dma_alloc_map[chn] != DMA_MAP_FREE) { - printk ("sound_free_dma: Bad access to DMA channel %d\n", chn); + /* printk ("sound_free_dma: Bad access to DMA channel %d\n", chn); */ return; } free_dma (chn); @@ -491,7 +584,7 @@ restore_flags (flags); } -#ifndef EXCLUDE_SEQUENCER +#ifdef CONFIG_SEQUENCER static struct timer_list seq_timer = @@ -507,6 +600,7 @@ else count += seq_time; + ; { seq_timer.expires = ((count - jiffies)) + jiffies; @@ -521,7 +615,7 @@ } #endif -#ifndef EXCLUDE_AUDIO +#ifdef CONFIG_AUDIO #ifdef KMALLOC_DMA_BROKEN fatal_error__This_version_is_not_compatible_with_this_kernel; @@ -535,6 +629,10 @@ char *start_addr, *end_addr; int i, dma_pagesize; +#ifdef ALLOW_BUFFER_MAPPING + dmap->mapping_flags &= ~DMA_MAP_MAPPED; +#endif + if (dmap->raw_buf != NULL) return 0; /* Already done */ @@ -611,7 +709,7 @@ for (i = MAP_NR (start_addr); i <= MAP_NR (end_addr); i++) { - mem_map[i].reserved = 1; + mem_map_reserve (i); } return 0; @@ -622,6 +720,12 @@ { if (dmap->raw_buf == NULL) return; + +#ifdef ALLOW_BUFFER_MAPPING + if (dmap->mapping_flags & DMA_MAP_MAPPED) + return; /* Don't free mmapped buffer. Will use it next time */ +#endif + { int sz, size, i; unsigned long start_addr, end_addr; @@ -635,7 +739,7 @@ for (i = MAP_NR (start_addr); i <= MAP_NR (end_addr); i++) { - mem_map[i].reserved = 0; + mem_map_unreserve (i); } free_pages ((unsigned long) dmap->raw_buf, sz); @@ -651,13 +755,45 @@ return -EINVAL; } -#else - void -soundcard_init (void) /* Dummy version */ +conf_printf (char *name, struct address_info *hw_config) { + if (!trace_init) + return; + + printk ("<%s> at 0x%03x", name, hw_config->io_base); + + if (hw_config->irq) + printk (" irq %d", hw_config->irq); + + if (hw_config->dma != -1 || hw_config->dma2 != -1) + { + printk (" dma %d", hw_config->dma); + if (hw_config->dma2 != -1) + printk (",%d", hw_config->dma2); + } + + printk ("\n"); } -#endif +void +conf_printf2 (char *name, int base, int irq, int dma, int dma2) +{ + if (!trace_init) + return; + + printk ("<%s> at 0x%03x", name, base); + + if (irq) + printk (" irq %d", irq); + if (dma != -1 || dma2 != -1) + { + printk (" dma %d", dma); + if (dma2 != -1) + printk (",%d", dma2); + } + + printk ("\n"); +} #endif diff -u --recursive --new-file v1.3.57/linux/drivers/sound/soundvers.h linux/drivers/sound/soundvers.h --- v1.3.57/linux/drivers/sound/soundvers.h Wed Nov 8 07:11:37 1995 +++ linux/drivers/sound/soundvers.h Tue Jan 9 00:36:58 1996 @@ -1,2 +1,2 @@ -#define SOUND_VERSION_STRING "3.5-alpha5-951002" +#define SOUND_VERSION_STRING "3.5-alpha8-960109" #define SOUND_INTERNAL_VERSION 0x030505 diff -u --recursive --new-file v1.3.57/linux/drivers/sound/sscape.c linux/drivers/sound/sscape.c --- v1.3.57/linux/drivers/sound/sscape.c Wed Nov 8 07:11:37 1995 +++ linux/drivers/sound/sscape.c Tue Jan 9 00:37:43 1996 @@ -29,7 +29,7 @@ #include "sound_config.h" -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SSCAPE) +#if defined(CONFIG_SSCAPE) #include "coproc.h" @@ -102,7 +102,7 @@ {0}; static struct sscape_info *devc = &dev_info; -static struct wait_queue *sscape_sleeper = NULL; +static wait_handle *sscape_sleeper = NULL; static volatile struct snd_wait sscape_sleep_flag = {0}; @@ -309,7 +309,7 @@ { { sscape_sleep_flag.mode = WK_WAKEUP; - wake_up (&sscape_sleeper); + module_wake_up (&sscape_sleeper); }; } @@ -318,7 +318,7 @@ printk ("SSCAPE: Host interrupt, data=%02x\n", host_read (devc)); } -#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI) +#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI) if (bits & 0x01) { mpuintr (irq, NULL); @@ -338,35 +338,6 @@ } -static void -sscape_enable_intr (struct sscape_info *devc, unsigned intr_bits) -{ - unsigned char temp, orig; - - temp = orig = sscape_read (devc, GA_INTENA_REG); - temp |= intr_bits; - temp |= 0x80; /* Master IRQ enable */ - - if (temp == orig) - return; /* No change */ - - sscape_write (devc, GA_INTENA_REG, temp); -} - -static void -sscape_disable_intr (struct sscape_info *devc, unsigned intr_bits) -{ - unsigned char temp, orig; - - temp = orig = sscape_read (devc, GA_INTENA_REG); - temp &= ~intr_bits; - if ((temp & ~0x80) == 0x00) - temp = 0x00; /* Master IRQ disable */ - if (temp == orig) - return; /* No change */ - - sscape_write (devc, GA_INTENA_REG, temp); -} static void do_dma (struct sscape_info *devc, int dma_chan, unsigned long buf, int blk_size, int mode) @@ -431,6 +402,7 @@ return -EIO; } + sscape_sleep_flag.mode = WK_NONE; return 0; } @@ -445,7 +417,7 @@ if (devc->dma_allocated) { sscape_write (devc, GA_DMAA_REG, 0x20); /* DMA channel disabled */ -#ifndef EXCLUDE_NATIVE_PCM +#ifdef CONFIG_NATIVE_PCM #endif devc->dma_allocated = 0; } @@ -478,7 +450,7 @@ cli (); if (devc->dma_allocated == 0) { -#ifndef EXCLUDE_NATIVE_PCM +#ifdef CONFIG_NATIVE_PCM #endif devc->dma_allocated = 1; @@ -523,11 +495,11 @@ unsigned long tl; if (1) - current->timeout = tl = jiffies + (1); + current_set_timeout (tl = jiffies + (1)); else tl = 0xffffffff; sscape_sleep_flag.mode = WK_SLEEP; - interruptible_sleep_on (&sscape_sleeper); + module_interruptible_sleep_on (&sscape_sleeper); if (!(sscape_sleep_flag.mode & WK_WAKEUP)) { if (jiffies >= tl) @@ -571,11 +543,11 @@ unsigned long tl; if (1) - current->timeout = tl = jiffies + (1); + current_set_timeout (tl = jiffies + (1)); else tl = 0xffffffff; sscape_sleep_flag.mode = WK_SLEEP; - interruptible_sleep_on (&sscape_sleeper); + module_interruptible_sleep_on (&sscape_sleeper); if (!(sscape_sleep_flag.mode & WK_WAKEUP)) { if (jiffies >= tl) @@ -604,11 +576,11 @@ unsigned long tl; if (1) - current->timeout = tl = jiffies + (1); + current_set_timeout (tl = jiffies + (1)); else tl = 0xffffffff; sscape_sleep_flag.mode = WK_SLEEP; - interruptible_sleep_on (&sscape_sleeper); + module_interruptible_sleep_on (&sscape_sleeper); if (!(sscape_sleep_flag.mode & WK_WAKEUP)) { if (jiffies >= tl) @@ -917,10 +889,10 @@ if (old_hardware) { valid_interrupts = valid_interrupts_old; - printk (" "); + conf_printf ("Ensoniq Soundscape (old)", hw_config); } else - printk (" "); + conf_printf ("Ensoniq Soundscape", hw_config); for (i = 0; i < sizeof (valid_interrupts); i++) if (hw_config->irq == valid_interrupts[i]) @@ -964,7 +936,7 @@ case 9: /* Master control reg. Don't modify CR-ROM bits. Disable SB emul */ sscape_write (devc, i, - (sscape_read (devc, i) & 0xf0) | 0x00); + (sscape_read (devc, i) & 0xf0) | 0x08); break; default: @@ -986,7 +958,7 @@ } #endif -#if !defined(EXCLUDE_MIDI) && !defined(EXCLUDE_MPU_EMU) +#if defined(CONFIG_MIDI) && defined(CONFIG_MPU_EMU) if (probe_mpu401 (hw_config)) hw_config->always_detect = 1; { @@ -1003,7 +975,7 @@ #ifndef EXCLUDE_NATIVE_PCM /* Not supported yet */ -#ifndef EXCLUDE_AUDIO +#ifdef CONFIG_AUDIO if (num_audiodevs < MAX_AUDIO_DEV) { audio_devs[my_dev = num_audiodevs++] = &sscape_audio_operations; @@ -1088,7 +1060,6 @@ if (old_hardware) /* Check that it's really an old Spea/Reveal card. */ { - int status = 0; unsigned char tmp; int cc; @@ -1153,7 +1124,7 @@ int i, irq_bits = 0xff; -#ifdef EXCLUDE_NATIVE_PCM +#ifndef CONFIG_NATIVE_PCM int prev_devs = num_audiodevs; #endif @@ -1192,7 +1163,7 @@ 0, devc->osp); -#ifdef EXCLUDE_NATIVE_PCM +#ifndef CONFIG_NATIVE_PCM if (num_audiodevs == (prev_devs + 1)) /* The AD1848 driver installed itself */ audio_devs[prev_devs]->coproc = &sscape_coproc_operations; #endif diff -u --recursive --new-file v1.3.57/linux/drivers/sound/sys_timer.c linux/drivers/sound/sys_timer.c --- v1.3.57/linux/drivers/sound/sys_timer.c Mon Oct 23 18:02:17 1995 +++ linux/drivers/sound/sys_timer.c Tue Jan 9 00:37:43 1996 @@ -31,9 +31,7 @@ #define SEQUENCER_C #include "sound_config.h" -#ifdef CONFIGURE_SOUNDCARD - -#ifndef EXCLUDE_SEQUENCER +#ifdef CONFIG_SEQUENCER static volatile int opened = 0, tmr_running = 0; static volatile time_t tmr_offs, tmr_ctr; @@ -113,6 +111,7 @@ curr_timebase = HZ; opened = 1; + ; { def_tmr.expires = (1) + jiffies; @@ -306,5 +305,4 @@ def_tmr_arm }; -#endif #endif diff -u --recursive --new-file v1.3.57/linux/drivers/sound/trix.c linux/drivers/sound/trix.c --- v1.3.57/linux/drivers/sound/trix.c Mon Oct 23 18:02:17 1995 +++ linux/drivers/sound/trix.c Tue Jan 9 00:37:44 1996 @@ -30,12 +30,13 @@ #include "sound_config.h" -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_TRIX) +#if defined(CONFIG_TRIX) #ifdef INCLUDE_TRIX_BOOT #include "trix_boot.h" #endif + static int kilroy_was_here = 0; /* Don't detect twice */ static int sb_initialized = 0; static int mpu_initialized = 0; @@ -80,6 +81,7 @@ outb (0x00, base + 6); /* Reset */ outb (0x50, 0x390); /* ?????? */ #endif + } static int @@ -324,20 +326,20 @@ long attach_trix_sb (long mem_start, struct address_info *hw_config) { -#ifndef EXCLUDE_SB +#ifdef CONFIG_SB extern int sb_no_recording; sb_dsp_disable_midi (); sb_no_recording = 1; #endif - printk (" "); + conf_printf ("AudioTriX (SB)", hw_config); return mem_start; } long attach_trix_mpu (long mem_start, struct address_info *hw_config) { -#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI) +#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI) return attach_mpu401 (mem_start, hw_config); #else return mem_start; @@ -347,7 +349,7 @@ int probe_trix_mpu (struct address_info *hw_config) { -#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI) +#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI) unsigned char conf; static char irq_bits[] = {-1, -1, -1, 1, 2, 3, -1, 4, -1, 5}; @@ -439,7 +441,7 @@ void unload_trix_mpu (struct address_info *hw_config) { -#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI) +#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI) unload_mpu401 (hw_config); #endif } diff -u --recursive --new-file v1.3.57/linux/drivers/sound/uart6850.c linux/drivers/sound/uart6850.c --- v1.3.57/linux/drivers/sound/uart6850.c Fri Oct 13 14:44:44 1995 +++ linux/drivers/sound/uart6850.c Tue Jan 9 00:37:44 1996 @@ -30,9 +30,7 @@ #include "sound_config.h" -#ifdef CONFIGURE_SOUNDCARD - -#if !defined(EXCLUDE_UART6850) && !defined(EXCLUDE_MIDI) +#if defined(CONFIG_UART6850) && defined(CONFIG_MIDI) #define DATAPORT (uart6850_base) /* * * * Midi6850 Data I/O Port on IBM @@ -117,9 +115,7 @@ unsigned long flags; if (!(uart6850_opened & OPEN_READ)) - return; /* - * No longer required - */ + return; /* Device has been closed */ save_flags (flags); cli (); @@ -150,6 +146,7 @@ return -EBUSY; } + ; uart6850_cmd (UART_RESET); uart6850_input_loop (); @@ -298,7 +295,7 @@ restore_flags (flags); - printk (" <6850 Midi Interface>"); + conf_printf ("6850 Midi Interface", hw_config); std_midi_synth.midi_dev = my_dev = num_midis; midi_devs[num_midis++] = &uart6850_operations; @@ -338,7 +335,5 @@ { snd_release_irq (hw_config->irq); } - -#endif #endif diff -u --recursive --new-file v1.3.57/linux/drivers/sound/ulaw.h linux/drivers/sound/ulaw.h --- v1.3.57/linux/drivers/sound/ulaw.h Tue Jul 11 10:02:55 1995 +++ linux/drivers/sound/ulaw.h Tue Jan 9 00:36:59 1996 @@ -1,74 +1,69 @@ - -/* - * This is a new ulaw.h made by Andy Fingerhut - */ - static unsigned char ulaw_dsp[] = { - 2, 6, 10, 14, 18, 22, 26, 30, - 34, 38, 42, 46, 50, 54, 58, 62, - 65, 67, 69, 71, 73, 75, 77, 79, - 81, 83, 85, 87, 89, 91, 93, 95, - 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, - 112, 113, 113, 114, 114, 115, 115, 116, - 116, 117, 117, 118, 118, 119, 119, 120, - 120, 120, 121, 121, 121, 121, 122, 122, - 122, 122, 123, 123, 123, 123, 124, 124, - 124, 124, 124, 124, 125, 125, 125, 125, - 125, 125, 125, 125, 126, 126, 126, 126, - 126, 126, 126, 126, 126, 126, 126, 126, - 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 128, - 253, 249, 245, 241, 237, 233, 229, 225, - 221, 217, 213, 209, 205, 201, 197, 193, - 190, 188, 186, 184, 182, 180, 178, 176, - 174, 172, 170, 168, 166, 164, 162, 160, - 158, 157, 156, 155, 154, 153, 152, 151, - 150, 149, 148, 147, 146, 145, 144, 143, - 143, 142, 142, 141, 141, 140, 140, 139, - 139, 138, 138, 137, 137, 136, 136, 135, - 135, 135, 134, 134, 134, 134, 133, 133, - 133, 133, 132, 132, 132, 132, 131, 131, - 131, 131, 131, 131, 130, 130, 130, 130, - 130, 130, 130, 130, 129, 129, 129, 129, - 129, 129, 129, 129, 129, 129, 129, 129, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128 + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2, + 5, 9, 13, 17, 21, 25, 29, 33, + 37, 41, 45, 49, 53, 57, 61, 65, + 68, 70, 72, 74, 76, 78, 80, 82, + 84, 86, 88, 90, 92, 94, 96, 98, + 100, 101, 102, 103, 104, 105, 106, 107, + 108, 109, 110, 111, 112, 113, 114, 115, + 115, 116, 116, 117, 117, 118, 118, 119, + 119, 120, 120, 121, 121, 122, 122, 123, + 123, 123, 124, 124, 124, 124, 125, 125, + 125, 125, 126, 126, 126, 126, 127, 127, + 127, 127, 127, 127, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 252, 248, 244, 240, 236, 232, 228, 224, + 220, 216, 212, 208, 204, 200, 196, 192, + 189, 187, 185, 183, 181, 179, 177, 175, + 173, 171, 169, 167, 165, 163, 161, 159, + 157, 156, 155, 154, 153, 152, 151, 150, + 149, 148, 147, 146, 145, 144, 143, 142, + 142, 141, 141, 140, 140, 139, 139, 138, + 138, 137, 137, 136, 136, 135, 135, 134, + 134, 134, 133, 133, 133, 133, 132, 132, + 132, 132, 131, 131, 131, 131, 130, 130, + 130, 130, 130, 130, 129, 129, 129, 129, + 129, 129, 129, 129, 128, 128, 128, 128, }; static unsigned char dsp_ulaw[] = { - 0, 0, 0, 0, 0, 1, 1, 1, - 1, 2, 2, 2, 2, 3, 3, 3, - 3, 4, 4, 4, 4, 5, 5, 5, - 5, 6, 6, 6, 6, 7, 7, 7, - 7, 8, 8, 8, 8, 9, 9, 9, - 9, 10, 10, 10, 10, 11, 11, 11, - 11, 12, 12, 12, 12, 13, 13, 13, - 13, 14, 14, 14, 14, 15, 15, 15, - 15, 16, 16, 17, 17, 18, 18, 19, - 19, 20, 20, 21, 21, 22, 22, 23, - 23, 24, 24, 25, 25, 26, 26, 27, - 27, 28, 28, 29, 29, 30, 30, 31, - 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 50, 52, 54, 56, 58, 60, - 62, 65, 69, 73, 77, 83, 91, 103, - 255, 231, 219, 211, 205, 201, 197, 193, - 190, 188, 186, 184, 182, 180, 178, 176, - 175, 174, 173, 172, 171, 170, 169, 168, - 167, 166, 165, 164, 163, 162, 161, 160, - 159, 159, 158, 158, 157, 157, 156, 156, - 155, 155, 154, 154, 153, 153, 152, 152, - 151, 151, 150, 150, 149, 149, 148, 148, - 147, 147, 146, 146, 145, 145, 144, 144, - 143, 143, 143, 143, 142, 142, 142, 142, - 141, 141, 141, 141, 140, 140, 140, 140, - 139, 139, 139, 139, 138, 138, 138, 138, - 137, 137, 137, 137, 136, 136, 136, 136, - 135, 135, 135, 135, 134, 134, 134, 134, - 133, 133, 133, 133, 132, 132, 132, 132, - 131, 131, 131, 131, 130, 130, 130, 130, - 129, 129, 129, 129, 128, 128, 128, 128 + 31, 31, 31, 32, 32, 32, 32, 33, + 33, 33, 33, 34, 34, 34, 34, 35, + 35, 35, 35, 36, 36, 36, 36, 37, + 37, 37, 37, 38, 38, 38, 38, 39, + 39, 39, 39, 40, 40, 40, 40, 41, + 41, 41, 41, 42, 42, 42, 42, 43, + 43, 43, 43, 44, 44, 44, 44, 45, + 45, 45, 45, 46, 46, 46, 46, 47, + 47, 47, 47, 48, 48, 49, 49, 50, + 50, 51, 51, 52, 52, 53, 53, 54, + 54, 55, 55, 56, 56, 57, 57, 58, + 58, 59, 59, 60, 60, 61, 61, 62, + 62, 63, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, 73, 74, 75, 76, + 77, 78, 79, 81, 83, 85, 87, 89, + 91, 93, 95, 99, 103, 107, 111, 119, + 255, 247, 239, 235, 231, 227, 223, 221, + 219, 217, 215, 213, 211, 209, 207, 206, + 205, 204, 203, 202, 201, 200, 199, 198, + 197, 196, 195, 194, 193, 192, 191, 191, + 190, 190, 189, 189, 188, 188, 187, 187, + 186, 186, 185, 185, 184, 184, 183, 183, + 182, 182, 181, 181, 180, 180, 179, 179, + 178, 178, 177, 177, 176, 176, 175, 175, + 175, 175, 174, 174, 174, 174, 173, 173, + 173, 173, 172, 172, 172, 172, 171, 171, + 171, 171, 170, 170, 170, 170, 169, 169, + 169, 169, 168, 168, 168, 168, 167, 167, + 167, 167, 166, 166, 166, 166, 165, 165, + 165, 165, 164, 164, 164, 164, 163, 163, + 163, 163, 162, 162, 162, 162, 161, 161, + 161, 161, 160, 160, 160, 160, 159, 159, }; diff -u --recursive --new-file v1.3.57/linux/fs/Config.in linux/fs/Config.in --- v1.3.57/linux/fs/Config.in Tue Jan 2 16:46:27 1996 +++ linux/fs/Config.in Sun Jan 14 16:22:16 1996 @@ -27,3 +27,4 @@ tristate 'ISO9660 cdrom filesystem support' CONFIG_ISO9660_FS tristate 'OS/2 HPFS filesystem support (read only)' CONFIG_HPFS_FS tristate 'System V and Coherent filesystem support' CONFIG_SYSV_FS +endmenu diff -u --recursive --new-file v1.3.57/linux/fs/buffer.c linux/fs/buffer.c --- v1.3.57/linux/fs/buffer.c Sun Jan 14 16:30:11 1996 +++ linux/fs/buffer.c Thu Jan 18 06:41:22 1996 @@ -56,6 +56,7 @@ 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; +struct buffer_head * reuse_list = NULL; static struct wait_queue * buffer_wait = NULL; int nr_buffers = 0; @@ -459,7 +460,7 @@ struct buffer_head * tmp; for (tmp = hash(dev,block) ; tmp != NULL ; tmp = tmp->b_next) - if (tmp->b_dev == dev && tmp->b_blocknr == block) + if (tmp->b_blocknr == block && tmp->b_dev == dev) if (tmp->b_size == size) return tmp; else { @@ -980,10 +981,38 @@ } } +/* + * We can't put completed temporary IO buffer_heads directly onto the + * unused_list when they become unlocked, since the device driver + * end_request routines still expect access to the buffer_head's + * fields after the final unlock. So, the device driver puts them on + * the reuse_list instead once IO completes, and we recover these to + * the unused_list here. + * + * The reuse_list receives buffers from interrupt routines, so we need + * to be IRQ-safe here. + */ +static inline void recover_reusable_buffer_heads(void) +{ + struct buffer_head *bh; + unsigned long flags; + + save_flags(flags); + cli(); + while (reuse_list) { + bh = reuse_list; + reuse_list = bh->b_next_free; + restore_flags(flags); + put_unused_buffer_head(bh); + cli(); + } +} + static struct buffer_head * get_unused_buffer_head(void) { struct buffer_head * bh; + recover_reusable_buffer_heads(); get_more_buffer_heads(); if (!unused_list) return NULL; @@ -1033,22 +1062,14 @@ return NULL; } -static void read_buffers(struct buffer_head * bh[], int nrbuf) -{ - ll_rw_block(READ, nrbuf, bh); - bh += nrbuf; - do { - nrbuf--; - bh--; - wait_on_buffer(*bh); - } while (nrbuf > 0); -} - static int bread_page(unsigned long address, kdev_t dev, int b[], int size) { - struct buffer_head *bh, *next, *arr[MAX_BUF_PER_PAGE]; + struct buffer_head *bh, *prev, *next, *arr[MAX_BUF_PER_PAGE]; int block, nr; + struct page *page; + page = mem_map + MAP_NR(address); + page->uptodate = 0; bh = create_buffers(address, size); if (!bh) return -ENOMEM; @@ -1057,6 +1078,17 @@ do { struct buffer_head * tmp; block = *(b++); + + set_bit(BH_FreeOnIO, &next->b_state); + next->b_list = BUF_CLEAN; + next->b_dev = dev; + next->b_blocknr = block; + next->b_count = 1; + next->b_flushtime = 0; + clear_bit(BH_Dirty, &next->b_state); + clear_bit(BH_Req, &next->b_state); + set_bit(BH_Uptodate, &next->b_state); + if (!block) { memset(next->b_data, 0, size); continue; @@ -1071,32 +1103,47 @@ brelse(tmp); continue; } - arr[nr++] = next; - next->b_dev = dev; - next->b_blocknr = block; - next->b_count = 1; - next->b_flushtime = 0; - clear_bit(BH_Dirty, &next->b_state); clear_bit(BH_Uptodate, &next->b_state); - clear_bit(BH_Req, &next->b_state); - next->b_list = BUF_CLEAN; - } while ((next = next->b_this_page) != NULL); - + arr[nr++] = next; + } while (prev = next, (next = next->b_this_page) != NULL); + prev->b_this_page = bh; + if (nr) - read_buffers(arr,nr); - ++current->maj_flt; - - while ((next = bh) != NULL) { - bh = bh->b_this_page; - put_unused_buffer_head(next); + ll_rw_block(READ, nr, arr); + else { + page->locked = 0; + page->uptodate = 1; + wake_up(&page->wait); } + ++current->maj_flt; return 0; } +void mark_buffer_uptodate(struct buffer_head * bh, int on) +{ + if (on) { + struct buffer_head *tmp = bh; + int page_uptodate = 1; + set_bit(BH_Uptodate, &bh->b_state); + do { + if (!test_bit(BH_Uptodate, &tmp->b_state)) { + page_uptodate = 0; + break; + } + tmp=tmp->b_this_page; + } while (tmp && tmp != bh); + if (page_uptodate) + mem_map[MAP_NR(bh->b_data)].uptodate = 1; + } else + clear_bit(BH_Uptodate, &bh->b_state); +} + /* - * Generic "readpage" function for block devices that have the - * normal bmap functionality. This is most of the block device - * filesystems. + * Generic "readpage" function for block devices that have the normal + * bmap functionality. This is most of the block device filesystems. + * Reads the page asynchronously --- the unlock_buffer() and + * mark_buffer_uptodate() functions propogate buffer state into the + * page struct once IO has completed. */ int generic_readpage(struct inode * inode, struct page * page) { @@ -1104,6 +1151,9 @@ int *p, nr[PAGE_SIZE/512]; int i; + wait_on_page(page); + page->locked = 1; + i = PAGE_SIZE >> inode->i_sb->s_blocksize_bits; block = page->offset >> inode->i_sb->s_blocksize_bits; p = nr; @@ -1114,20 +1164,11 @@ p++; } while (i > 0); - /* - * We should make this asynchronous, but this is good enough for now.. - */ - /* IO start */ page->count++; address = page_address(page); bread_page(address, inode->i_dev, nr, inode->i_sb->s_blocksize); - - /* IO ready (this part should be in the "page ready callback" function) */ - page->uptodate = 1; - wake_up(&page->wait); free_page(address); - return 0; } diff -u --recursive --new-file v1.3.57/linux/fs/ext/inode.c linux/fs/ext/inode.c --- v1.3.57/linux/fs/ext/inode.c Mon Nov 27 12:48:31 1995 +++ linux/fs/ext/inode.c Mon Jan 15 07:59:09 1996 @@ -451,15 +451,24 @@ return err; } -#ifdef MODULE static struct file_system_type ext_fs_type = { ext_read_super, "ext", 1, NULL }; -int init_module(void) +int init_ext_fs(void) { return register_filesystem(&ext_fs_type); +} + +#ifdef MODULE +int init_module(void) +{ + int status; + + if ((status = init_ext_fs()) == 0) + register_symtab(0); + return status; } void cleanup_module(void) diff -u --recursive --new-file v1.3.57/linux/fs/ext2/CHANGES linux/fs/ext2/CHANGES --- v1.3.57/linux/fs/ext2/CHANGES Sun Aug 13 14:45:34 1995 +++ linux/fs/ext2/CHANGES Wed Jan 17 07:31:58 1996 @@ -1,5 +1,7 @@ Changes from version 0.5a to version 0.5b ========================================= + - Now that we have sysctl(), the immutable flag cannot be changed when + the system is running at security level > 0. - Some cleanups in the code. - More consistency checks on directories. - The ext2.diff patch from Tom May has been diff -u --recursive --new-file v1.3.57/linux/fs/ext2/ioctl.c linux/fs/ext2/ioctl.c --- v1.3.57/linux/fs/ext2/ioctl.c Wed Mar 22 10:33:59 1995 +++ linux/fs/ext2/ioctl.c Wed Jan 17 07:31:58 1996 @@ -33,12 +33,13 @@ case EXT2_IOC_SETFLAGS: flags = get_fs_long ((long *) arg); /* - * Only the super-user can change the IMMUTABLE flag + * The IMMUTABLE flag can only be changed by the super user + * when the security level is zero. */ if ((flags & EXT2_IMMUTABLE_FL) ^ (inode->u.ext2_i.i_flags & EXT2_IMMUTABLE_FL)) { /* This test looks nicer. Thanks to Pauline Middelink */ - if (!fsuser()) + if (!fsuser() || securelevel > 0) return -EPERM; } else if ((current->fsuid != inode->i_uid) && !fsuser()) diff -u --recursive --new-file v1.3.57/linux/fs/ext2/super.c linux/fs/ext2/super.c --- v1.3.57/linux/fs/ext2/super.c Mon Dec 11 15:42:04 1995 +++ linux/fs/ext2/super.c Mon Jan 15 07:59:09 1996 @@ -685,15 +685,23 @@ return 0; } -#ifdef MODULE - static struct file_system_type ext2_fs_type = { ext2_read_super, "ext2", 1, NULL }; -int init_module(void) +int init_ext2_fs(void) { return register_filesystem(&ext2_fs_type); +} + +#ifdef MODULE +int init_module(void) +{ + int status; + + if ((status = init_ext2_fs()) == 0) + register_symtab(0); + return status; } void cleanup_module(void) diff -u --recursive --new-file v1.3.57/linux/fs/filesystems.c linux/fs/filesystems.c --- v1.3.57/linux/fs/filesystems.c Tue Jan 2 16:46:27 1996 +++ linux/fs/filesystems.c Mon Jan 15 07:59:09 1996 @@ -44,74 +44,55 @@ device_setup(); #ifdef CONFIG_EXT_FS - register_filesystem(&(struct file_system_type) - {ext_read_super, "ext", 1, NULL}); + init_ext_fs(); #endif #ifdef CONFIG_EXT2_FS - register_filesystem(&(struct file_system_type) - {ext2_read_super, "ext2", 1, NULL}); + init_ext2_fs(); #endif #ifdef CONFIG_XIA_FS - register_filesystem(&(struct file_system_type) - {xiafs_read_super, "xiafs", 1, NULL}); + init_xiafs_fs(); #endif #ifdef CONFIG_MINIX_FS - register_filesystem(&(struct file_system_type) - {minix_read_super, "minix", 1, NULL}); + init_minix_fs(); #endif #ifdef CONFIG_UMSDOS_FS - register_filesystem(&(struct file_system_type) - {UMSDOS_read_super, "umsdos", 1, NULL}); + init_umsdos_fs(); #endif #ifdef CONFIG_MSDOS_FS - register_filesystem(&(struct file_system_type) - {msdos_read_super, "msdos", 1, NULL}); + init_msdos_fs(); #endif #ifdef CONFIG_PROC_FS - register_filesystem(&(struct file_system_type) - {proc_read_super, "proc", 0, NULL}); + init_proc_fs(); #endif #ifdef CONFIG_NFS_FS - register_filesystem(&(struct file_system_type) - {nfs_read_super, "nfs", 0, NULL}); + init_nfs_fs(); #endif #ifdef CONFIG_SMB_FS - register_filesystem(&(struct file_system_type) - {smb_read_super, "smbfs", 0, NULL}); + init_smb_fs(); #endif #ifdef CONFIG_NCP_FS - register_filesystem(&(struct file_system_type) - {ncp_read_super, "ncpfs", 0, NULL}); + init_ncp_fs(); #endif #ifdef CONFIG_ISO9660_FS - register_filesystem(&(struct file_system_type) - {isofs_read_super, "iso9660", 1, NULL}); + init_iso9660_fs(); #endif #ifdef CONFIG_SYSV_FS - register_filesystem(&(struct file_system_type) - {sysv_read_super, "xenix", 1, NULL}); - - register_filesystem(&(struct file_system_type) - {sysv_read_super, "sysv", 1, NULL}); - - register_filesystem(&(struct file_system_type) - {sysv_read_super, "coherent", 1, NULL}); + init_sysv_fs(); #endif #ifdef CONFIG_HPFS_FS - register_filesystem(&(struct file_system_type) - {hpfs_read_super, "hpfs", 1, NULL}); + init_hpfs_fs(); #endif #ifdef CONFIG_ROOT_NFS diff -u --recursive --new-file v1.3.57/linux/fs/hpfs/hpfs_fs.c linux/fs/hpfs/hpfs_fs.c --- v1.3.57/linux/fs/hpfs/hpfs_fs.c Thu Jan 4 21:54:56 1996 +++ linux/fs/hpfs/hpfs_fs.c Mon Jan 15 07:59:09 1996 @@ -1744,15 +1744,23 @@ kfree_s(qbh->data, 2048); } -#ifdef MODULE - static struct file_system_type hpfs_fs_type = { hpfs_read_super, "hpfs", 1, NULL }; -int init_module(void) +int init_hpfs_fs(void) { return register_filesystem(&hpfs_fs_type); +} + +#ifdef MODULE +int init_module(void) +{ + int status; + + if ((status = init_hpfs_fs()) == 0) + register_symtab(0); + return status; } void cleanup_module(void) diff -u --recursive --new-file v1.3.57/linux/fs/isofs/inode.c linux/fs/isofs/inode.c --- v1.3.57/linux/fs/isofs/inode.c Tue Dec 26 04:45:38 1995 +++ linux/fs/isofs/inode.c Mon Jan 15 07:59:10 1996 @@ -801,15 +801,23 @@ #endif -#ifdef MODULE - static struct file_system_type iso9660_fs_type = { isofs_read_super, "iso9660", 1, NULL }; +int init_iso9660_fs(void) +{ + return register_filesystem(&iso9660_fs_type); +} + +#ifdef MODULE int init_module(void) { - return register_filesystem(&iso9660_fs_type); + int status; + + if ((status = init_iso9660_fs()) == 0) + register_symtab(0); + return status; } void cleanup_module(void) diff -u --recursive --new-file v1.3.57/linux/fs/minix/inode.c linux/fs/minix/inode.c --- v1.3.57/linux/fs/minix/inode.c Thu Jan 4 21:54:57 1996 +++ linux/fs/minix/inode.c Mon Jan 15 07:59:11 1996 @@ -873,15 +873,23 @@ return err; } -#ifdef MODULE - static struct file_system_type minix_fs_type = { minix_read_super, "minix", 1, NULL }; +int init_minix_fs(void) +{ + return register_filesystem(&minix_fs_type); +} + +#ifdef MODULE int init_module(void) { - return register_filesystem(&minix_fs_type); + int status; + + if ((status = init_minix_fs()) == 0) + register_symtab(0); + return status; } void cleanup_module(void) diff -u --recursive --new-file v1.3.57/linux/fs/msdos/Makefile linux/fs/msdos/Makefile --- v1.3.57/linux/fs/msdos/Makefile Tue Aug 15 20:39:04 1995 +++ linux/fs/msdos/Makefile Mon Jan 15 07:59:11 1996 @@ -8,7 +8,8 @@ # Note 2! The CFLAGS definitions are now in the main makefile... O_TARGET := msdos.o -O_OBJS := buffer.o namei.o inode.o file.o dir.o misc.o fat.o mmap.o +O_OBJS := buffer.o namei.o file.o dir.o misc.o fat.o mmap.o +OX_OBJS := inode.o M_OBJS := $(O_TARGET) include $(TOPDIR)/Rules.make diff -u --recursive --new-file v1.3.57/linux/fs/msdos/inode.c linux/fs/msdos/inode.c --- v1.3.57/linux/fs/msdos/inode.c Sun Jan 14 16:30:12 1996 +++ linux/fs/msdos/inode.c Mon Jan 15 07:59:11 1996 @@ -515,15 +515,55 @@ return 0; } -#ifdef MODULE +static struct symbol_table msdos_syms = { +/* Should this be surrounded with "#ifdef CONFIG_MODULES" ? */ +#include + /* + * Support for umsdos fs + * + * These symbols are _always_ exported, in case someone + * wants to install the umsdos module later. + */ + X(msdos_bmap), + X(msdos_create), + X(msdos_file_read), + X(msdos_file_write), + X(msdos_lookup), + X(msdos_mkdir), + X(msdos_mmap), + X(msdos_put_inode), + X(msdos_put_super), + X(msdos_read_inode), + X(msdos_read_super), + X(msdos_readdir), + X(msdos_rename), + X(msdos_rmdir), + X(msdos_smap), + X(msdos_statfs), + X(msdos_truncate), + X(msdos_unlink), + X(msdos_unlink_umsdos), + X(msdos_write_inode), +#include +}; static struct file_system_type msdos_fs_type = { msdos_read_super, "msdos", 1, NULL }; +int init_msdos_fs(void) +{ + int status; + + if ((status = register_filesystem(&msdos_fs_type)) == 0) + status = register_symtab(&msdos_syms); + return status; +} + +#ifdef MODULE int init_module(void) { - return register_filesystem(&msdos_fs_type); + return init_msdos_fs(); } void cleanup_module(void) diff -u --recursive --new-file v1.3.57/linux/fs/ncpfs/dir.c linux/fs/ncpfs/dir.c --- v1.3.57/linux/fs/ncpfs/dir.c Tue Jan 2 16:46:28 1996 +++ linux/fs/ncpfs/dir.c Sun Jan 14 15:37:42 1996 @@ -551,6 +551,7 @@ root->finfo.opened = 0; i->attributes = aDIR; i->dataStreamSize = 1024; + i->volNumber = NCP_NUMBER_OF_VOLUMES+1; /* illegal volnum */ ncp_date_unix2dos(0, &(i->creationTime), &(i->creationDate)); ncp_date_unix2dos(0, &(i->modifyTime), &(i->modifyDate)); ncp_date_unix2dos(0, &dummy, &(i->lastAccessDate)); @@ -608,6 +609,7 @@ do { if ( (result->dir->finfo.i.DosDirNum == dir_info->DosDirNum) + && (result->dir->finfo.i.volNumber == dir_info->volNumber) && (strcmp(result->finfo.i.entryName, name) == 0)) { return result; @@ -626,8 +628,9 @@ { struct nw_file_info finfo; struct ncp_server *server; - struct ncp_inode_info *result_info; - int found_in_cache; + struct ncp_inode_info *result_info; + int found_in_cache; + char name[len+1]; *result = NULL; @@ -671,7 +674,9 @@ } } - result_info = ncp_find_inode(dir, __name); + memcpy(name, __name, len); + name[len] = 0; + result_info = ncp_find_inode(dir, name); if (result_info != 0) { @@ -710,7 +715,7 @@ DDPRINTK("ncp_lookup: trying index: %d, name: %s\n", i, c_entry[i].i.entryName); - if (strcmp(c_entry[i].i.entryName, __name) == 0) + if (strcmp(c_entry[i].i.entryName, name) == 0) { DPRINTK("ncp_lookup: found in cache!\n"); finfo.i = c_entry[i].i; @@ -724,20 +729,15 @@ if (found_in_cache == 0) { - char this_name[len+1]; - - memcpy(this_name, __name, len); - this_name[len] = 0; - str_upper(this_name); + str_upper(name); DDPRINTK("ncp_lookup: do_lookup on %s/%s\n", - NCP_ISTRUCT(dir)->entryName, this_name); + NCP_ISTRUCT(dir)->entryName, name); if (ncp_do_lookup(server, dir->i_ino == (int)&(NCP_SERVER(dir)->root) ? NULL : NCP_ISTRUCT(dir), - this_name, - &(finfo.i)) != 0) + name, &(finfo.i)) != 0) { iput(dir); return -ENOENT; diff -u --recursive --new-file v1.3.57/linux/fs/ncpfs/inode.c linux/fs/ncpfs/inode.c --- v1.3.57/linux/fs/ncpfs/inode.c Tue Jan 2 16:46:28 1996 +++ linux/fs/ncpfs/inode.c Mon Jan 15 07:59:11 1996 @@ -483,25 +483,31 @@ int ncp_current_malloced; #endif -#ifdef MODULE - static struct file_system_type ncp_fs_type = { ncp_read_super, "ncpfs", 0, NULL }; -int +int init_ncp_fs(void) +{ + return register_filesystem(&ncp_fs_type); +} + +#ifdef MODULE init_module( void) { + int status; + DPRINTK("ncpfs: init_module called\n"); #ifdef DEBUG_NCP_MALLOC ncp_malloced = 0; ncp_current_malloced = 0; #endif - ncp_init_dir_cache(); - register_filesystem(&ncp_fs_type); - return 0; + + if ((status = init_ncp_fs()) == 0) + register_symtab(0); + return status; } void diff -u --recursive --new-file v1.3.57/linux/fs/nfs/inode.c linux/fs/nfs/inode.c --- v1.3.57/linux/fs/nfs/inode.c Thu Jan 4 21:54:58 1996 +++ linux/fs/nfs/inode.c Mon Jan 15 07:59:11 1996 @@ -288,17 +288,25 @@ return error; } -#ifdef MODULE - /* Every kernel module contains stuff like this. */ static struct file_system_type nfs_fs_type = { nfs_read_super, "nfs", 0, NULL }; +int init_nfs_fs(void) +{ + return register_filesystem(&nfs_fs_type); +} + +#ifdef MODULE int init_module(void) { - return register_filesystem(&nfs_fs_type); + int status; + + if ((status = init_nfs_fs()) == 0) + register_symtab(0); + return status; } void cleanup_module(void) diff -u --recursive --new-file v1.3.57/linux/fs/nfs/nfsroot.c linux/fs/nfs/nfsroot.c --- v1.3.57/linux/fs/nfs/nfsroot.c Sun Jan 14 16:30:12 1996 +++ linux/fs/nfs/nfsroot.c Wed Jan 17 07:32:09 1996 @@ -15,6 +15,7 @@ * * Alan Cox : Removed get_address name clash with FPU. * Alan Cox : Reformatted a bit. + * Michael Rausch : Fixed recognition of an incoming RARP answer. * */ @@ -317,6 +318,7 @@ { int retries = 0; unsigned long timeout = 0; + volatile struct device **root_dev_ptr = (volatile struct device **) &root_dev; /* Setup RARP protocol */ root_rarp_open(); @@ -329,16 +331,16 @@ * [Actually we could now, but the nothing else running note still * applies.. - AC] */ - for (retries = 0; retries < RARP_RETRIES && root_dev == NULL; retries++) { + for (retries = 0; retries < RARP_RETRIES && *root_dev_ptr == NULL; retries++) { if (root_rarp_send() < 0) break; timeout = jiffies + (RARP_TIMEOUT * HZ); - while (jiffies < timeout && root_dev == NULL) - ;; + while (jiffies < timeout && *root_dev_ptr == NULL) + ; } root_rarp_close(); - if (root_dev == NULL && timeout > 0) { + if (*root_dev_ptr == NULL && timeout > 0) { printk(KERN_ERR "NFS: Timed out while waiting for RARP answer\n"); return -1; } diff -u --recursive --new-file v1.3.57/linux/fs/proc/Makefile linux/fs/proc/Makefile --- v1.3.57/linux/fs/proc/Makefile Sat Dec 30 15:50:54 1995 +++ linux/fs/proc/Makefile Thu Jan 18 07:06:17 1996 @@ -8,12 +8,8 @@ # Note 2! The CFLAGS definitions are now in the main makefile... O_TARGET := proc.o -O_OBJS := inode.o root.o base.o mem.o link.o fd.o array.o kmsg.o net.o +O_OBJS := inode.o root.o base.o mem.o link.o fd.o array.o kmsg.o net.o scsi.o +OX_OBJS := procfs_syms.o M_OBJS := $(O_TARGET) - -# For either CONFIG_SCSI=y or CONFIG_SCSI=m -ifdef CONFIG_SCSI -O_OBJS += scsi.o -endif include $(TOPDIR)/Rules.make diff -u --recursive --new-file v1.3.57/linux/fs/proc/inode.c linux/fs/proc/inode.c --- v1.3.57/linux/fs/proc/inode.c Sat Dec 30 15:50:54 1995 +++ linux/fs/proc/inode.c Thu Jan 18 10:09:25 1996 @@ -12,7 +12,6 @@ #include #include #include -#include #include #include @@ -171,13 +170,11 @@ case PROC_NET: inode->i_nlink = 2; break; -#ifdef CONFIG_SCSI case PROC_SCSI: inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO; inode->i_nlink = 2; inode->i_op = &proc_scsi_inode_operations; break; -#endif case PROC_KCORE: inode->i_mode = S_IFREG | S_IRUSR; inode->i_op = &proc_kcore_inode_operations; diff -u --recursive --new-file v1.3.57/linux/fs/proc/net.c linux/fs/proc/net.c --- v1.3.57/linux/fs/proc/net.c Tue Dec 26 04:45:40 1995 +++ linux/fs/proc/net.c Sun Jan 14 16:47:28 1996 @@ -24,16 +24,14 @@ * * proc net directory handling functions */ -#include - -#include - #include #include #include #include #include #include + +#include #define PROC_BLOCK_SIZE (3*1024) /* 4K page size but our output routines use some slack for overruns */ diff -u --recursive --new-file v1.3.57/linux/fs/proc/procfs_syms.c linux/fs/proc/procfs_syms.c --- v1.3.57/linux/fs/proc/procfs_syms.c Thu Jan 1 02:00:00 1970 +++ linux/fs/proc/procfs_syms.c Mon Jan 15 09:09:16 1996 @@ -0,0 +1,35 @@ +#include +#include +#include +#include + +static struct symbol_table procfs_syms = { +/* Should this be surrounded with "#ifdef CONFIG_MODULES" ? */ +#include + X(proc_register), + X(proc_unregister), + X(in_group_p), + X(generate_cluster), + X(proc_net_inode_operations), + X(proc_net), +#ifdef CONFIG_SCSI /* Ugh... */ + X(proc_scsi), + X(proc_scsi_inode_operations), + X(dispatch_scsi_info_ptr), +#endif +#include +}; + +static struct file_system_type proc_fs_type = { + proc_read_super, "proc", 0, NULL +}; + +int init_proc_fs(void) +{ + int status; + + if ((status = register_filesystem(&proc_fs_type)) == 0) + status = register_symtab(&procfs_syms); + return status; +} + diff -u --recursive --new-file v1.3.57/linux/fs/proc/scsi.c linux/fs/proc/scsi.c --- v1.3.57/linux/fs/proc/scsi.c Sat Dec 30 15:50:55 1995 +++ linux/fs/proc/scsi.c Sun Jan 14 16:48:05 1996 @@ -20,13 +20,13 @@ * TODO: Improve support to write to the driver files * Add some more comments */ -#include -#include #include #include #include #include #include + +#include /* forward references */ static int proc_readscsi(struct inode * inode, struct file * file, diff -u --recursive --new-file v1.3.57/linux/fs/smbfs/inode.c linux/fs/smbfs/inode.c --- v1.3.57/linux/fs/smbfs/inode.c Tue Jan 2 16:46:28 1996 +++ linux/fs/smbfs/inode.c Mon Jan 15 07:59:11 1996 @@ -403,15 +403,20 @@ int smb_current_malloced; #endif -#ifdef MODULE - static struct file_system_type smb_fs_type = { smb_read_super, "smbfs", 0, NULL }; -int -init_module( void) +int init_smb_fs(void) { + return register_filesystem(&smb_fs_type); +} + +#ifdef MODULE +int init_module(void) +{ + int status; + DPRINTK("smbfs: init_module called\n"); #ifdef DEBUG_SMB_MALLOC @@ -420,7 +425,10 @@ #endif smb_init_dir_cache(); - return register_filesystem(&smb_fs_type); + + if ((status = init_smb_fs()) == 0) + register_symtab(0); + return status; } void diff -u --recursive --new-file v1.3.57/linux/fs/smbfs/proc.c linux/fs/smbfs/proc.c --- v1.3.57/linux/fs/smbfs/proc.c Tue Jan 2 16:46:29 1996 +++ linux/fs/smbfs/proc.c Sun Jan 14 16:22:17 1996 @@ -1664,7 +1664,7 @@ } if (server->packet[0] != 0x82) { - printk("smb_proc_connect: Did not recieve positive response " + printk("smb_proc_connect: Did not receive positive response " "(err = %x)\n", server->packet[0]); smb_dont_catch_keepalive(server); diff -u --recursive --new-file v1.3.57/linux/fs/sysv/inode.c linux/fs/sysv/inode.c --- v1.3.57/linux/fs/sysv/inode.c Mon Nov 27 12:48:32 1995 +++ linux/fs/sysv/inode.c Mon Jan 15 07:59:12 1996 @@ -969,8 +969,6 @@ return err; } -#ifdef MODULE - /* Every kernel module contains stuff like this. */ static struct file_system_type sysv_fs_type[3] = { @@ -979,7 +977,7 @@ {sysv_read_super, "coherent", 1, NULL} }; -int init_module(void) +int init_sysv_fs(void) { int i; int ouch; @@ -988,7 +986,17 @@ if ((ouch = register_filesystem(&sysv_fs_type[i])) != 0) return ouch; } - return 0; + return ouch; +} + +#ifdef MODULE +int init_module(void) +{ + int status; + + if ((status = init_sysv_fs()) == 0) + register_symtab(0); + return status; } void cleanup_module(void) diff -u --recursive --new-file v1.3.57/linux/fs/umsdos/inode.c linux/fs/umsdos/inode.c --- v1.3.57/linux/fs/umsdos/inode.c Sun Dec 17 11:43:20 1995 +++ linux/fs/umsdos/inode.c Mon Jan 15 07:59:12 1996 @@ -494,15 +494,23 @@ } -#ifdef MODULE - static struct file_system_type umsdos_fs_type = { UMSDOS_read_super, "umsdos", 1, NULL }; +int init_umsdos_fs(void) +{ + return register_filesystem(&umsdos_fs_type); +} + +#ifdef MODULE int init_module(void) { - return register_filesystem(&umsdos_fs_type); + int status; + + if ((status = init_umsdos_fs()) == 0) + register_symtab(0); + return status; } void cleanup_module(void) diff -u --recursive --new-file v1.3.57/linux/fs/xiafs/inode.c linux/fs/xiafs/inode.c --- v1.3.57/linux/fs/xiafs/inode.c Mon Nov 27 12:48:32 1995 +++ linux/fs/xiafs/inode.c Mon Jan 15 07:59:13 1996 @@ -511,17 +511,25 @@ return err; } -#ifdef MODULE - /* Every kernel module contains stuff like this. */ static struct file_system_type xiafs_fs_type = { xiafs_read_super, "xiafs", 1, NULL }; +int init_xiafs_fs(void) +{ + return register_filesystem(&xiafs_fs_type); +} + +#ifdef MODULE int init_module(void) { - return register_filesystem(&xiafs_fs_type); + int status; + + if ((status = init_xiafs_fs()) == 0) + register_symtab(0); + return status; } void cleanup_module(void) diff -u --recursive --new-file v1.3.57/linux/include/asm-alpha/param.h linux/include/asm-alpha/param.h --- v1.3.57/linux/include/asm-alpha/param.h Tue Dec 26 04:45:40 1995 +++ linux/include/asm-alpha/param.h Sat Jan 13 11:09:26 1996 @@ -4,8 +4,7 @@ #include #ifndef HZ -# if defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB66P) || \ - defined(CONFIG_ALPHA_EB64P) +# if defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB66P) # define HZ 977 /* Evaluation Boards seem to be a little odd */ # else # define HZ 1024 /* normal value for Alpha systems */ diff -u --recursive --new-file v1.3.57/linux/include/asm-i386/delay.h linux/include/asm-i386/delay.h --- v1.3.57/linux/include/asm-i386/delay.h Wed Nov 8 07:11:41 1995 +++ linux/include/asm-i386/delay.h Thu Jan 18 06:32:06 1996 @@ -13,7 +13,11 @@ extern __inline__ void __delay(int loops) { - __asm__(".align 2,0x90\n1:\tdecl %0\n\tjns 1b": :"a" (loops):"ax"); + __asm__ __volatile__( + ".align 2,0x90\n1:\tdecl %0\n\tjns 1b" + :/* no outputs */ + :"a" (loops) + :"ax"); } /* diff -u --recursive --new-file v1.3.57/linux/include/linux/blk.h linux/include/linux/blk.h --- v1.3.57/linux/include/linux/blk.h Sun Dec 17 11:43:32 1995 +++ linux/include/linux/blk.h Thu Jan 18 10:17:08 1996 @@ -340,7 +340,7 @@ #if ! SCSI_MAJOR(MAJOR_NR) -#if defined(_IDE_CD_C) || defined(_TRITON_C) || defined(_IDE_TAPE_C) /* shares copy with ide.c */ +#if defined(IDE_DRIVER) && !defined(_IDE_C) /* shared copy for IDE modules */ void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup); #else @@ -393,7 +393,7 @@ req->rq_status = RQ_INACTIVE; wake_up(&wait_for_request); } -#endif /* ndef _IDE_CD_C */ +#endif /* defined(IDE_DRIVER) && !defined(_IDE_C) */ #endif /* ! SCSI_MAJOR(MAJOR_NR) */ #endif /* defined(MAJOR_NR) || defined(IDE_DRIVER) */ diff -u --recursive --new-file v1.3.57/linux/include/linux/ext2_fs.h linux/include/linux/ext2_fs.h --- v1.3.57/linux/include/linux/ext2_fs.h Mon Dec 11 15:42:05 1995 +++ linux/include/linux/ext2_fs.h Mon Jan 15 07:59:13 1996 @@ -475,6 +475,7 @@ extern void ext2_write_super (struct super_block *); extern int ext2_remount (struct super_block *, int *, char *); extern struct super_block * ext2_read_super (struct super_block *,void *,int); +extern int init_ext2_fs(void); extern void ext2_statfs (struct super_block *, struct statfs *, int); /* truncate.c */ diff -u --recursive --new-file v1.3.57/linux/include/linux/ext2_fs_sb.h linux/include/linux/ext2_fs_sb.h --- v1.3.57/linux/include/linux/ext2_fs_sb.h Tue Jul 11 10:02:59 1995 +++ linux/include/linux/ext2_fs_sb.h Mon Jan 15 09:12:08 1996 @@ -16,6 +16,8 @@ #ifndef _LINUX_EXT2_FS_SB #define _LINUX_EXT2_FS_SB +#include + /* * The following is not needed anymore since the descriptors buffer * heads are now dynamically allocated diff -u --recursive --new-file v1.3.57/linux/include/linux/ext_fs.h linux/include/linux/ext_fs.h --- v1.3.57/linux/include/linux/ext_fs.h Mon Dec 11 15:42:05 1995 +++ linux/include/linux/ext_fs.h Mon Jan 15 07:59:13 1996 @@ -91,6 +91,7 @@ extern void ext_put_super(struct super_block *); extern void ext_write_super(struct super_block *); extern struct super_block *ext_read_super(struct super_block *,void *,int); +extern int init_ext_fs(void); extern void ext_read_inode(struct inode *); extern void ext_write_inode(struct inode *); extern void ext_put_inode(struct inode *); diff -u --recursive --new-file v1.3.57/linux/include/linux/fs.h linux/include/linux/fs.h --- v1.3.57/linux/include/linux/fs.h Sun Jan 14 16:30:14 1996 +++ linux/include/linux/fs.h Thu Jan 18 06:41:22 1996 @@ -136,14 +136,35 @@ #define BH_Touched 4 /* 1 if the buffer has been touched (aging) */ #define BH_Has_aged 5 /* 1 if the buffer has been aged (aging) */ #define BH_Protected 6 /* 1 if the buffer is protected */ +#define BH_FreeOnIO 7 /* 1 to discard the buffer_head after IO */ +/* + * Try to keep the most commonly used fields in single cache lines (16 + * bytes) to improve performance. This ordering should be + * particularly beneficial on 32-bit processors. + * + * We use the first 16 bytes for the data which is used in searches + * over the block hash lists (ie. getblk(), find_buffer() and + * friends). + * + * The second 16 bytes we use for lru buffer scans, as used by + * sync_buffers() and refill_freelist(). -- sct + */ struct buffer_head { - char * b_data; /* pointer to data block (1024 bytes) */ - unsigned long b_size; /* block size */ + /* First cache line: */ unsigned long b_blocknr; /* block number */ kdev_t b_dev; /* device (B_FREE = free) */ + struct buffer_head * b_next; /* Hash queue list */ + struct buffer_head * b_this_page; /* circular list of buffers in one page */ + + /* Second cache line: */ unsigned long b_state; /* buffer state bitmap (see above) */ + struct buffer_head * b_next_free; unsigned int b_count; /* users using this block */ + unsigned long b_size; /* block size */ + + /* Non-performance-critical data follows. */ + char * b_data; /* pointer to data block (1024 bytes) */ unsigned int b_list; /* List that this buffer appears */ unsigned long b_flushtime; /* Time when this (dirty) buffer * should be written */ @@ -151,10 +172,7 @@ * last used. */ struct wait_queue * b_wait; struct buffer_head * b_prev; /* doubly linked list of hash-queue */ - struct buffer_head * b_next; struct buffer_head * b_prev_free; /* doubly linked list of buffers */ - struct buffer_head * b_next_free; - struct buffer_head * b_this_page; /* circular list of buffers in one page */ struct buffer_head * b_reqnext; /* request queue */ }; @@ -507,13 +525,7 @@ #define BUF_SHARED 5 /* Buffers shared */ #define NR_LIST 6 -extern inline void mark_buffer_uptodate(struct buffer_head * bh, int on) -{ - if (on) - set_bit(BH_Uptodate, &bh->b_state); - else - clear_bit(BH_Uptodate, &bh->b_state); -} +void mark_buffer_uptodate(struct buffer_head * bh, int on); extern inline void mark_buffer_clean(struct buffer_head * bh) { diff -u --recursive --new-file v1.3.57/linux/include/linux/hpfs_fs.h linux/include/linux/hpfs_fs.h --- v1.3.57/linux/include/linux/hpfs_fs.h Wed Dec 1 14:44:15 1993 +++ linux/include/linux/hpfs_fs.h Mon Jan 15 07:59:13 1996 @@ -8,5 +8,6 @@ /* The entry point for a VFS */ extern struct super_block *hpfs_read_super (struct super_block *, void *, int); +extern int init_hpfs_fs(void); #endif diff -u --recursive --new-file v1.3.57/linux/include/linux/iso_fs.h linux/include/linux/iso_fs.h --- v1.3.57/linux/include/linux/iso_fs.h Mon Dec 11 15:42:05 1995 +++ linux/include/linux/iso_fs.h Mon Jan 15 07:59:14 1996 @@ -175,6 +175,7 @@ extern void isofs_put_super(struct super_block *); extern struct super_block *isofs_read_super(struct super_block *,void *,int); +extern int init_iso9660_fs(void); extern void isofs_read_inode(struct inode *); extern void isofs_put_inode(struct inode *); extern void isofs_statfs(struct super_block *, struct statfs *, int); diff -u --recursive --new-file v1.3.57/linux/include/linux/locks.h linux/include/linux/locks.h --- v1.3.57/linux/include/linux/locks.h Mon Nov 27 12:48:36 1995 +++ linux/include/linux/locks.h Thu Jan 18 06:52:42 1996 @@ -1,6 +1,16 @@ #ifndef _LINUX_LOCKS_H #define _LINUX_LOCKS_H +#ifndef _LINUX_MM_H +#include +#endif + +/* + * Unlocked, temporary IO buffer_heads gets moved to the reuse_list + * once their page becomes unlocked. + */ +extern struct buffer_head *reuse_list; + /* * Buffer cache locking - note that interrupts may only unlock, not * lock buffers. @@ -21,8 +31,36 @@ extern inline void unlock_buffer(struct buffer_head * bh) { + struct buffer_head *tmp = bh; + int page_locked = 0; + unsigned long flags; + clear_bit(BH_Lock, &bh->b_state); wake_up(&bh->b_wait); + do { + if (test_bit(BH_Lock, &tmp->b_state)) { + page_locked = 1; + break; + } + tmp=tmp->b_this_page; + } while (tmp && tmp != bh); + save_flags(flags); + if (!page_locked) { + struct page *page = mem_map + MAP_NR(bh->b_data); + page->locked = 0; + wake_up(&page->wait); + tmp = bh; + cli(); + do { + if (test_bit(BH_FreeOnIO, &tmp->b_state)) { + tmp->b_next_free = reuse_list; + reuse_list = tmp; + clear_bit(BH_FreeOnIO, &tmp->b_state); + } + tmp = tmp->b_this_page; + } while (tmp && tmp != bh); + restore_flags(flags); + } } /* diff -u --recursive --new-file v1.3.57/linux/include/linux/mcdx.h linux/include/linux/mcdx.h --- v1.3.57/linux/include/linux/mcdx.h Tue Nov 21 13:22:13 1995 +++ linux/include/linux/mcdx.h Sun Jan 14 16:22:16 1996 @@ -1,7 +1,7 @@ /* * Definitions for the Mitsumi CDROM interface * Copyright (C) 1995 Heiko Schlittermann - * VERSION: 1.5 + * VERSION: 1.5a * * 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 diff -u --recursive --new-file v1.3.57/linux/include/linux/minix_fs.h linux/include/linux/minix_fs.h --- v1.3.57/linux/include/linux/minix_fs.h Thu Jan 4 21:54:59 1996 +++ linux/include/linux/minix_fs.h Mon Jan 15 07:59:14 1996 @@ -116,6 +116,7 @@ extern void minix_truncate(struct inode *); extern void minix_put_super(struct super_block *); extern struct super_block *minix_read_super(struct super_block *,void *,int); +extern int init_minix_fs(void); extern void minix_write_super(struct super_block *); extern int minix_remount (struct super_block * sb, int * flags, char * data); extern void minix_read_inode(struct inode *); diff -u --recursive --new-file v1.3.57/linux/include/linux/mm.h linux/include/linux/mm.h --- v1.3.57/linux/include/linux/mm.h Sun Jan 14 16:30:14 1996 +++ linux/include/linux/mm.h Thu Jan 18 06:52:36 1996 @@ -105,6 +105,15 @@ pte_t (*swapin)(struct vm_area_struct *, unsigned long, unsigned long); }; +/* + * Try to keep the most commonly accessed fields in single cache lines + * here (16 bytes or greater). This ordering should be particularly + * beneficial on 32-bit processors. + * + * The first line is data used in linear searches (eg. clock algorithm + * scans). The second line is data used in page searches through the + * page-cache. -- sct + */ typedef struct page { unsigned int count; unsigned dirty:16, @@ -112,14 +121,19 @@ uptodate:1, error:1, referenced:1, - unused:4, + locked:1, + unused:3, reserved:1; + struct wait_queue *wait; + struct page *next; + + struct page *next_hash; unsigned long offset; struct inode *inode; - struct wait_queue *wait; struct page *write_list; - struct page *next, *prev; - struct page *next_hash, *prev_hash; + + struct page *prev; + struct page *prev_hash; } mem_map_t; extern mem_map_t * mem_map; diff -u --recursive --new-file v1.3.57/linux/include/linux/msdos_fs.h linux/include/linux/msdos_fs.h --- v1.3.57/linux/include/linux/msdos_fs.h Mon Dec 11 15:42:05 1995 +++ linux/include/linux/msdos_fs.h Thu Jan 18 06:57:23 1996 @@ -164,6 +164,7 @@ extern void msdos_put_super(struct super_block *sb); extern struct super_block *msdos_read_super(struct super_block *s, void *data,int); +extern int init_msdos_fs(void); extern void msdos_statfs(struct super_block *sb,struct statfs *buf, int); extern int msdos_bmap(struct inode *inode,int block); extern void msdos_read_inode(struct inode *inode); diff -u --recursive --new-file v1.3.57/linux/include/linux/ncp_fs.h linux/include/linux/ncp_fs.h --- v1.3.57/linux/include/linux/ncp_fs.h Thu Jan 4 21:54:59 1996 +++ linux/include/linux/ncp_fs.h Thu Jan 18 06:59:37 1996 @@ -142,6 +142,7 @@ /* linux/fs/ncpfs/inode.c */ struct super_block *ncp_read_super(struct super_block *sb, void *raw_data, int silent); +extern int init_ncp_fs(void); void ncp_invalidate_connection(struct ncp_server *server); int ncp_conn_is_valid(struct ncp_server *server); diff -u --recursive --new-file v1.3.57/linux/include/linux/nfs_fs.h linux/include/linux/nfs_fs.h --- v1.3.57/linux/include/linux/nfs_fs.h Fri Nov 17 08:42:28 1995 +++ linux/include/linux/nfs_fs.h Mon Jan 15 07:59:14 1996 @@ -98,6 +98,7 @@ extern struct super_block *nfs_read_super(struct super_block *sb, void *data,int); +extern int init_nfs_fs(void); extern struct inode *nfs_fhget(struct super_block *sb, struct nfs_fh *fhandle, struct nfs_fattr *fattr); extern void nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr); diff -u --recursive --new-file v1.3.57/linux/include/linux/optcd.h linux/include/linux/optcd.h --- v1.3.57/linux/include/linux/optcd.h Mon Sep 18 14:54:09 1995 +++ linux/include/linux/optcd.h Thu Jan 18 06:22:13 1996 @@ -1,200 +1,48 @@ +/* linux/include/linux/optcd.h - Optics Storage 8000 AT CDROM driver + $Id: optcd.h,v 1.2 1996/01/15 18:43:44 root Exp root $ -/* Defines for the Optics Storage 8000AT CDROM drive. */ + Copyright (C) 1995 Leo Spiekman (spiekman@dutette.et.tudelft.nl) -#ifndef _LINUX_OPTCD_H + Configuration file for linux/drivers/cdrom/optcd.c +*/ + +#ifndef _LINUX_OPTCD_H #define _LINUX_OPTCD_H -/* Drive registers */ + +/* I/O base of drive. Drive uses base to base+2. + This setting can be overridden with the kernel or insmod command + line option 'optcd='. Use address of 0 to disable driver. */ #define OPTCD_PORTBASE 0x340 -/* Read */ -#define DATA_PORT optcd_port /* Read data/status */ -#define STATUS_PORT optcd_port+1 /* Indicate data/status availability */ -/* Write */ -#define COMIN_PORT optcd_port /* For passing command/parameter */ -#define RESET_PORT optcd_port+1 /* Write anything and wait 0.5 sec */ -#define HCON_PORT optcd_port+2 /* Host Xfer Configuration */ - - -/* Command completion/status read from DATA register */ -#define ST_DRVERR 0x80 -#define ST_DOOR_OPEN 0x40 -#define ST_MIXEDMODE_DISK 0x20 -#define ST_MODE_BITS 0x1c -#define ST_M_STOP 0x00 -#define ST_M_READ 0x04 -#define ST_M_AUDIO 0x04 -#define ST_M_PAUSE 0x08 -#define ST_M_INITIAL 0x0c -#define ST_M_ERROR 0x10 -#define ST_M_OTHERS 0x14 -#define ST_MODE2TRACK 0x02 -#define ST_DSK_CHG 0x01 -#define ST_L_LOCK 0x01 -#define ST_CMD_OK 0x00 -#define ST_OP_OK 0x01 -#define ST_PA_OK 0x02 -#define ST_OP_ERROR 0x05 -#define ST_PA_ERROR 0x06 - -/* Error codes (appear as command completion code from DATA register) */ -/* Player related errors */ -#define ERR_ILLCMD 0x11 /* Illegal command to player module */ -#define ERR_ILLPARM 0x12 /* Illegal parameter to player module */ -#define ERR_SLEDGE 0x13 -#define ERR_FOCUS 0x14 -#define ERR_MOTOR 0x15 -#define ERR_RADIAL 0x16 -#define ERR_PLL 0x17 /* PLL lock error */ -#define ERR_SUB_TIM 0x18 /* Subcode timeout error */ -#define ERR_SUB_NF 0x19 /* Subcode not found error */ -#define ERR_TRAY 0x1a -#define ERR_TOC 0x1b /* Table of Contents read error */ -#define ERR_JUMP 0x1c -/* Data errors */ -#define ERR_MODE 0x21 -#define ERR_FORM 0x22 -#define ERR_HEADADDR 0x23 /* Header Address not found */ -#define ERR_CRC 0x24 -#define ERR_ECC 0x25 /* Uncorrectable ECC error */ -#define ERR_CRC_UNC 0x26 /* CRC error and uncorrectable error */ -#define ERR_ILLBSYNC 0x27 /* Illegal block sync error */ -#define ERR_VDST 0x28 /* VDST not found */ -/* Timeout errors */ -#define ERR_READ_TIM 0x31 /* Read timeout error */ -#define ERR_DEC_STP 0x32 /* Decoder stopped */ -#define ERR_DEC_TIM 0x33 /* Decoder interrupt timeout error */ -/* Function abort codes */ -#define ERR_KEY 0x41 /* Key -Detected abort */ -#define ERR_READ_FINISH 0x42 /* Read Finish */ -/* Second Byte diagnostic codes */ -#define ERR_NOBSYNC 0x01 /* No block sync */ -#define ERR_SHORTB 0x02 /* Short block */ -#define ERR_LONGB 0x03 /* Long block */ -#define ERR_SHORTDSP 0x04 /* Short DSP word */ -#define ERR_LONGDSP 0x05 /* Long DSP word */ - - -/* Status availability flags read from STATUS register */ -#define FL_EJECT 0x20 -#define FL_WAIT 0x10 /* active low */ -#define FL_EOP 0x08 /* active low */ -#define FL_STEN 0x04 /* Status available when low */ -#define FL_DTEN 0x02 /* Data available when low */ -#define FL_DRQ 0x01 /* active low */ -#define FL_RESET 0xde /* These bits are high after a reset */ -#define FL_STDT (FL_STEN|FL_DTEN) - - -/* Transfer mode, written to HCON register */ -#define HCON_DTS 0x08 -#define HCON_SDRQB 0x04 -#define HCON_LOHI 0x02 -#define HCON_DMA16 0x01 - - -/* Drive command set, written to COMIN register */ -/* Quick response commands */ -#define COMDRVST 0x20 /* Drive Status Read */ -#define COMERRST 0x21 /* Error Status Read */ -#define COMIOCTLISTAT 0x22 /* Status Read; reset disk changed bit */ -#define COMINITSINGLE 0x28 /* Initialize Single Speed */ -#define COMINITDOUBLE 0x29 /* Initialize Double Speed */ -#define COMUNLOCK 0x30 /* Unlock */ -#define COMLOCK 0x31 /* Lock */ -#define COMLOCKST 0x32 /* Lock/Unlock Status */ -#define COMVERSION 0x40 /* Get Firmware Revision */ -#define COMVOIDREADMODE 0x50 /* Void Data Read Mode */ -/* Read commands */ -#define COMFETCH 0x60 /* Prefetch Data */ -#define COMREAD 0x61 /* Read */ -#define COMREADRAW 0x62 /* Read Raw Data */ -#define COMREADALL 0x63 /* Read All 2646 Bytes */ -/* Player control commands */ -#define COMLEADIN 0x70 /* Seek To Lead-in */ -#define COMSEEK 0x71 /* Seek */ -#define COMPAUSEON 0x80 /* Pause On */ -#define COMPAUSEOFF 0x81 /* Pause Off */ -#define COMSTOP 0x82 /* Stop */ -#define COMOPEN 0x90 /* Open Tray Door */ -#define COMCLOSE 0x91 /* Close Tray Door */ -#define COMPLAY 0xa0 /* Audio Play */ -#define COMPLAY_TNO 0xa2 /* Audio Play By Track Number */ -#define COMSUBQ 0xb0 /* Read Sub-q Code */ -#define COMLOCATION 0xb1 /* Read Head Position */ -/* Audio control commands */ -#define COMCHCTRL 0xc0 /* Audio Channel Control */ -/* Miscellaneous (test) commands */ -#define COMDRVTEST 0xd0 /* Write Test Bytes */ -#define COMTEST 0xd1 /* Diagnostic Test */ +/* enable / disable parts of driver by define / undef */ +#define MULTISESSION /* multisession support (ALPHA) */ +#define PROBE_ISP16 /* ISP16 interface card probing */ +/* ISP16 probing can also be suppressed with kernel command line option + 'noisp16', or with insmod parameter 'noisp16=1'. */ + + +/* Change 0 to 1 to debug various parts of the driver */ +#define DEBUG_DRIVE_IF 0 /* Low level drive interface */ +#define DEBUG_CONV 0 /* Address conversions */ +#define DEBUG_BUFFERS 0 /* Buffering and block size conversion */ +#define DEBUG_REQUEST 0 /* Request mechanism */ +#define DEBUG_STATE 0 /* State machine */ +#define DEBUG_TOC 0 /* Q-channel and Table of Contents */ +#define DEBUG_MULTIS 0 /* Multisession code */ +#define DEBUG_VFS 0 /* VFS interface */ + + +/* Various timeout loop repetition counts. Don't touch unless you know + what you're doing. */ #define BUSY_TIMEOUT 10000000 /* for busy wait */ -#define SLEEP_TIMEOUT 400 /* for timer wait */ +#define FAST_TIMEOUT 100000 /* ibid. for probing */ +#define SLEEP_TIMEOUT 3000 /* for timer wait */ +#define MULTI_SEEK_TIMEOUT 500 /* for timer wait */ #define READ_TIMEOUT 3000 /* for poll wait */ -#define RESET_WAIT 1000 - -#define SET_TIMER(func, jifs) \ - delay_timer.expires = jiffies+(jifs); \ - delay_timer.function = (void *) (func); \ - add_timer(&delay_timer); -#define CLEAR_TIMER del_timer(&delay_timer) - -#define MAX_TRACKS 104 - -struct msf { - unsigned char min; - unsigned char sec; - unsigned char frame; -}; - -struct opt_Play_msf { - struct msf start; - struct msf end; -}; - -struct opt_DiskInfo { - unsigned char first; - unsigned char last; - struct msf diskLength; - struct msf firstTrack; -}; - -struct opt_Toc { - unsigned char ctrl_addr; - unsigned char track; - unsigned char pointIndex; - struct msf trackTime; - struct msf diskTime; -}; - - -#define CURRENT_VALID \ - (CURRENT && MAJOR(CURRENT -> rq_dev) == MAJOR_NR \ - && CURRENT -> cmd == READ && CURRENT -> sector != -1) - - -#undef DEBUG_DRIVE_IF /* Low level drive interface */ -#undef DEBUG_COMMANDS /* Commands sent to drive */ -#undef DEBUG_VFS /* VFS interface */ -#undef DEBUG_CONV /* Address conversions */ -#undef DEBUG_TOC /* Q-channel and Table of Contents */ -#undef DEBUG_BUFFERS /* Buffering and block size conversion */ -#undef DEBUG_REQUEST /* Request mechanism */ -#undef DEBUG_STATE /* State machine */ - - -/* Low level drive interface */ - -/* Errors that can occur in the low level interface */ -#define ERR_IF_CMD_TIMEOUT 0x100 -#define ERR_IF_ERR_TIMEOUT 0x101 -#define ERR_IF_RESP_TIMEOUT 0x102 -#define ERR_IF_DATA_TIMEOUT 0x103 -#define ERR_IF_NOSTAT 0x104 -/* Errors in table of contents */ -#define ERR_TOC_MISSINGINFO 0x120 -#define ERR_TOC_MISSINGENTRY 0x121 +#define STOP_TIMEOUT 1000 /* for poll wait */ +#define RESET_WAIT 1000 /* busy wait at drive reset */ -/* End .h defines */ #endif _LINUX_OPTCD_H diff -u --recursive --new-file v1.3.57/linux/include/linux/pagemap.h linux/include/linux/pagemap.h --- v1.3.57/linux/include/linux/pagemap.h Sun Jan 14 16:30:14 1996 +++ linux/include/linux/pagemap.h Thu Jan 18 06:41:22 1996 @@ -110,6 +110,13 @@ *p = page; } +extern void __wait_on_page(struct page *); +static inline void wait_on_page(struct page * page) +{ + if (page->locked) + __wait_on_page(page); +} + extern void update_vm_cache(struct inode *, unsigned long, const char *, int); #endif diff -u --recursive --new-file v1.3.57/linux/include/linux/pci.h linux/include/linux/pci.h --- v1.3.57/linux/include/linux/pci.h Sat Dec 30 15:50:55 1995 +++ linux/include/linux/pci.h Sun Jan 14 16:22:16 1996 @@ -296,6 +296,7 @@ #define PCI_DEVICE_ID_FD_36C70 0x0000 #define PCI_VENDOR_ID_SI 0x1039 +#define PCI_DEVICE_ID_SI_6201 0x0001 #define PCI_DEVICE_ID_SI_6202 0x0002 #define PCI_DEVICE_ID_SI_503 0x0008 #define PCI_DEVICE_ID_SI_501 0x0406 diff -u --recursive --new-file v1.3.57/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h --- v1.3.57/linux/include/linux/proc_fs.h Sun Jan 14 16:30:14 1996 +++ linux/include/linux/proc_fs.h Thu Jan 18 06:52:42 1996 @@ -98,6 +98,7 @@ enum scsi_directory_inos { PROC_SCSI_SCSI = 256, + PROC_SCSI_ADVANSYS, PROC_SCSI_EATA, PROC_SCSI_EATA_PIO, PROC_SCSI_AHA152X, @@ -223,6 +224,7 @@ } extern struct super_block *proc_read_super(struct super_block *,void *,int); +extern int init_proc_fs(void); extern struct inode * proc_get_inode(struct super_block *, int, struct proc_dir_entry *); extern void proc_statfs(struct super_block *, struct statfs *, int); extern void proc_read_inode(struct inode *); diff -u --recursive --new-file v1.3.57/linux/include/linux/quota.h linux/include/linux/quota.h --- v1.3.57/linux/include/linux/quota.h Mon Dec 11 15:42:05 1995 +++ linux/include/linux/quota.h Sun Jan 14 16:22:15 1996 @@ -192,8 +192,6 @@ /* * declaration of quota_function calls in kernel. */ -int quota_off (kdev_t dev, short type); -int sync_dquots (kdev_t dev, short type); extern void dquot_initialize(struct inode *inode, short type); extern void dquot_drop(struct inode *inode); diff -u --recursive --new-file v1.3.57/linux/include/linux/sched.h linux/include/linux/sched.h --- v1.3.57/linux/include/linux/sched.h Sat Jan 6 19:10:40 1996 +++ linux/include/linux/sched.h Thu Jan 18 06:52:36 1996 @@ -316,6 +316,8 @@ extern unsigned long prof_len; extern unsigned long prof_shift; +extern int securelevel; /* system security level */ + #define CURRENT_TIME (xtime.tv_sec) extern void sleep_on(struct wait_queue ** p); diff -u --recursive --new-file v1.3.57/linux/include/linux/smb_fs.h linux/include/linux/smb_fs.h --- v1.3.57/linux/include/linux/smb_fs.h Tue Jan 2 16:46:30 1996 +++ linux/include/linux/smb_fs.h Thu Jan 18 06:59:37 1996 @@ -114,6 +114,7 @@ /* linux/fs/smbfs/inode.c */ struct super_block *smb_read_super(struct super_block *sb, void *raw_data, int silent); +extern int init_smb_fs(void); int smb_notify_change(struct inode *inode, struct iattr *attr); void smb_invalidate_connection(struct smb_server *server); int smb_conn_is_valid(struct smb_server *server); diff -u --recursive --new-file v1.3.57/linux/include/linux/soundcard.h linux/include/linux/soundcard.h --- v1.3.57/linux/include/linux/soundcard.h Wed Nov 8 07:11:42 1995 +++ linux/include/linux/soundcard.h Tue Jan 9 00:36:58 1996 @@ -148,6 +148,16 @@ #define SNDCTL_TMR_SELECT _IOW ('T', 8, int) /* + * Endian aware patch key generation algorithm. + */ + +#if defined(_AIX) || defined(AIX) +# define _PATCHKEY(id) (0xfd00|id) +#else +# define _PATCHKEY(id) ((id<<8)|0xfd) +#endif + +/* * Sample loading mechanism for internal synthesizers (/dev/sequencer) * The following patch_info structure has been designed to support * Gravis UltraSound. It tries to be universal format for uploading @@ -155,9 +165,10 @@ */ struct patch_info { - short key; /* Use GUS_PATCH here */ -#define GUS_PATCH 0x04fd -#define OBSOLETE_GUS_PATCH 0x02fd + unsigned short key; /* Use GUS_PATCH here */ +#define GUS_PATCH _PATCHKEY(0x04) +#define OBSOLETE_GUS_PATCH _PATCHKEY(0x02) + short device_no; /* Synthesizer number */ short instr_no; /* Midi pgm# */ @@ -236,8 +247,8 @@ struct sysex_info { short key; /* Use GUS_PATCH here */ -#define SYSEX_PATCH 0x05fd -#define MAUI_PATCH 0x06fd /* For future use */ +#define SYSEX_PATCH _PATCHKEY(0x05) +#define MAUI_PATCH _PATCHKEY(0x06) short device_no; /* Synthesizer number */ long len; /* Size of the sysex data in bytes */ unsigned char data[1]; /* Sysex data starts here */ @@ -488,9 +499,9 @@ typedef unsigned char sbi_instr_data[32]; struct sbi_instrument { - unsigned short key; /* Initialize to FM_PATCH or OPL3_PATCH */ -#define FM_PATCH 0x01fd -#define OPL3_PATCH 0x03fd + unsigned short key; /* FM_PATCH or OPL3_PATCH */ +#define FM_PATCH _PATCHKEY(0x01) +#define OPL3_PATCH _PATCHKEY(0x03) short device; /* Synth# (0-4) */ int channel; /* Program# to be initialized */ sbi_instr_data operators; /* Register settings for operator cells (.SBI format) */ @@ -507,6 +518,7 @@ int synth_subtype; #define FM_TYPE_ADLIB 0x00 #define FM_TYPE_OPL3 0x01 +#define MIDI_TYPE_MPU401 0x401 #define SAMPLE_TYPE_GUS 0x10 @@ -628,6 +640,7 @@ } buffmem_desc; #define SNDCTL_DSP_MAPINBUF _IOR ('P', 19, buffmem_desc) #define SNDCTL_DSP_MAPOUTBUF _IOR ('P', 20, buffmem_desc) +#define SNDCTL_DSP_SETSYNCRO _IO ('P', 21) #define SOUND_PCM_READ_RATE _IOR ('P', 2, int) #define SOUND_PCM_READ_CHANNELS _IOR ('P', 6, int) @@ -650,6 +663,7 @@ #define SOUND_PCM_GETCAPS SNDCTL_DSP_GETCAPS #define SOUND_PCM_GETTRIGGER SNDCTL_DSP_GETTRIGGER #define SOUND_PCM_SETTRIGGER SNDCTL_DSP_SETTRIGGER +#define SOUND_PCM_SETSYNCRO SNDCTL_DSP_SETSYNCRO #define SOUND_PCM_GETIPTR SNDCTL_DSP_GETIPTR #define SOUND_PCM_GETOPTR SNDCTL_DSP_GETOPTR #define SOUND_PCM_MAPINBUF SNDCTL_DSP_MAPINBUF @@ -739,10 +753,18 @@ #define SOUND_ONOFF_MIN 28 #define SOUND_ONOFF_MAX 30 #define SOUND_MIXER_MUTE 28 /* 0 or 1 */ -#define SOUND_MIXER_ENHANCE 29 /* Enhanced stereo (0, 40, 60 or 80) */ #define SOUND_MIXER_LOUD 30 /* 0 or 1 */ /* Note! Number 31 cannot be used since the sign bit is reserved */ + + +/* + * SOUND_MIXER_ENHANCE is an unsupported and undocumented call which + * will be removed from the API in future. + */ +#define SOUND_MIXER_ENHANCE 29 /* Enhanced stereo (0, 40, 60 or 80) */ + + #define SOUND_DEVICE_LABELS {"Vol ", "Bass ", "Trebl", "Synth", "Pcm ", "Spkr ", "Line ", \ "Mic ", "CD ", "Mix ", "Pcm2 ", "Rec ", "IGain", "OGain", \ diff -u --recursive --new-file v1.3.57/linux/include/linux/swapctl.h linux/include/linux/swapctl.h --- v1.3.57/linux/include/linux/swapctl.h Sun Jan 14 16:30:15 1996 +++ linux/include/linux/swapctl.h Thu Jan 18 06:41:22 1996 @@ -42,6 +42,17 @@ typedef kswapd_control_v1 kswapd_control_t; extern kswapd_control_t kswapd_ctl; +typedef struct swapstat_v1 +{ + int wakeups; + int pages_reclaimed; + int pages_shm; + int pages_mmap; + int pages_swap; +} swapstat_v1; +typedef swapstat_v1 swapstat_t; +extern swapstat_t swapstats; + #define SC_VERSION 1 #define SC_MAX_VERSION 1 diff -u --recursive --new-file v1.3.57/linux/include/linux/sysctl.h linux/include/linux/sysctl.h --- v1.3.57/linux/include/linux/sysctl.h Sun Jan 14 16:30:15 1996 +++ linux/include/linux/sysctl.h Wed Jan 17 07:31:59 1996 @@ -54,6 +54,7 @@ #define KERN_NRFILE 11 #define KERN_MAXFILE 12 #define KERN_MAXID 13 +#define KERN_SECURELVL 14 /* int: system security level */ /* CTL_VM names: */ #define VM_SWAPCTL 1 /* struct: Set vm swapping control */ diff -u --recursive --new-file v1.3.57/linux/include/linux/sysv_fs.h linux/include/linux/sysv_fs.h --- v1.3.57/linux/include/linux/sysv_fs.h Mon Dec 11 15:42:06 1995 +++ linux/include/linux/sysv_fs.h Thu Jan 18 06:59:37 1996 @@ -390,6 +390,7 @@ extern void sysv_truncate(struct inode *); extern void sysv_put_super(struct super_block *); extern struct super_block *sysv_read_super(struct super_block *,void *,int); +extern int init_sysv_fs(void); extern void sysv_write_super(struct super_block *); extern void sysv_read_inode(struct inode *); extern int sysv_notify_change(struct inode *, struct iattr *); diff -u --recursive --new-file v1.3.57/linux/include/linux/umsdos_fs.h linux/include/linux/umsdos_fs.h --- v1.3.57/linux/include/linux/umsdos_fs.h Mon Nov 27 12:48:36 1995 +++ linux/include/linux/umsdos_fs.h Thu Jan 18 06:59:37 1996 @@ -136,6 +136,7 @@ extern struct inode_operations umsdos_file_inode_operations; extern struct inode_operations umsdos_file_inode_operations_no_bmap; extern struct inode_operations umsdos_symlink_inode_operations; +extern int init_umsdos_fs(void); #include diff -u --recursive --new-file v1.3.57/linux/include/linux/wrapper.h linux/include/linux/wrapper.h --- v1.3.57/linux/include/linux/wrapper.h Thu Jan 1 02:00:00 1970 +++ linux/include/linux/wrapper.h Wed Jan 17 09:33:33 1996 @@ -0,0 +1,40 @@ +#ifndef _WRAPPER_H_ +#define _WRAPPER_H_ +#define wait_handle struct wait_queue +#define file_handle struct file +#define inode_handle struct inode +#define select_table_handle select_table +#define vm_area_handle struct vm_area_struct +#define file_operation_handle file_operations + +#define connect_wrapper(x) 0 +#define current_got_fatal_signal() (current->signal & ~current->blocked) +#define current_set_timeout(val) current->timeout = val + +#define module_interruptible_sleep_on interruptible_sleep_on +#define module_wake_up wake_up +#define module_select_wait select_wait +#define module_register_chrdev register_chrdev +#define module_unregister_chrdev unregister_chrdev +#define module_register_blkdev register_blkdev +#define module_unregister_blkdev unregister_blkdev + +#define inode_get_rdev(i) i->i_rdev +#define inode_get_count(i) i->i_count +#define inode_inc_count(i) i->i_count++ +#define inode_dec_count(i) i->i_count-- + +#define file_get_flags(f) f->f_flags + +#define vma_set_inode(v,i) v->vm_inode = i +#define vma_get_flags(v) v->vm_flags +#define vma_get_offset(v) v->vm_offset +#define vma_get_start(v) v->vm_start +#define vma_get_end(v) v->vm_end +#define vma_get_page_prot(v) v->vm_page_prot + +#define mem_map_reserve(p) mem_map[p].reserved = 1 +#define mem_map_unreserve(p) mem_map[p].reserved = 0 +#define mem_map_inc_count(p) mem_map[p].count++ +#define mem_map_dec_count(p) mem_map[p].count-- +#endif diff -u --recursive --new-file v1.3.57/linux/include/linux/xia_fs.h linux/include/linux/xia_fs.h --- v1.3.57/linux/include/linux/xia_fs.h Mon Jun 12 17:03:19 1995 +++ linux/include/linux/xia_fs.h Mon Jan 15 07:59:14 1996 @@ -95,6 +95,7 @@ extern void xiafs_truncate(struct inode *); extern void xiafs_put_super(struct super_block *); extern struct super_block *xiafs_read_super(struct super_block *,void *,int); +extern int init_xiafs_fs(void); extern void xiafs_read_inode(struct inode *); extern void xiafs_write_inode(struct inode *); extern void xiafs_put_inode(struct inode *); diff -u --recursive --new-file v1.3.57/linux/include/net/route.h linux/include/net/route.h --- v1.3.57/linux/include/net/route.h Sun Jan 14 16:30:15 1996 +++ linux/include/net/route.h Thu Jan 18 10:16:25 1996 @@ -26,6 +26,8 @@ #ifndef _ROUTE_H #define _ROUTE_H +#include + /* * 0 - no debugging messages * 1 - rare events and bugs situations (default) diff -u --recursive --new-file v1.3.57/linux/init/main.c linux/init/main.c --- v1.3.57/linux/init/main.c Sun Jan 14 16:30:15 1996 +++ linux/init/main.c Wed Jan 17 07:27:36 1996 @@ -62,6 +62,7 @@ extern void floppy_setup(char *str, int *ints); extern void st_setup(char *str, int *ints); extern void st0x_setup(char *str, int *ints); +extern void advansys_setup(char *str, int *ints); extern void tmc8xx_setup(char *str, int *ints); extern void t128_setup(char *str, int *ints); extern void pas16_setup(char *str, int *ints); @@ -201,6 +202,9 @@ #ifdef CONFIG_SCSI { "max_scsi_luns=", scsi_luns_setup }, #endif +#ifdef CONFIG_SCSI_ADVANSYS + { "advansys=", advansys_setup }, +#endif #if defined(CONFIG_BLK_DEV_HD) { "hd=", hd_setup }, #endif @@ -489,6 +493,7 @@ extern void setup_arch(char **, unsigned long *, unsigned long *); +extern void arch_syms_export(void); #ifndef __SMP__ @@ -635,6 +640,7 @@ apm_bios_init(); #endif dquot_init(); + arch_syms_export(); sti(); check_bugs(); diff -u --recursive --new-file v1.3.57/linux/ipc/msg.c linux/ipc/msg.c --- v1.3.57/linux/ipc/msg.c Sun Jan 14 16:30:15 1996 +++ linux/ipc/msg.c Sun Jan 14 16:46:37 1996 @@ -6,7 +6,7 @@ * */ -#include +#include #include #include #include @@ -190,7 +190,7 @@ return -EIDRM; if ((msgflg & IPC_KERNELD) == 0) /* - * Non-root processes may recieve from kerneld! + * Non-root processes may receive from kerneld! * i.e. no permission check if called from the kernel * otoh we don't want user level non-root snoopers... */ @@ -554,7 +554,7 @@ /* * We do perhaps need a "flush" for waiting processes, * so that if they are terminated, a call from do_exit - * will minimize the possibility of orphaned recieved + * will minimize the possibility of orphaned received * messages in the queue. For now we just make sure * that the queue is shut down whenever kerneld dies. */ diff -u --recursive --new-file v1.3.57/linux/ipc/util.c linux/ipc/util.c --- v1.3.57/linux/ipc/util.c Sun Jan 14 16:30:15 1996 +++ linux/ipc/util.c Wed Jan 17 07:32:09 1996 @@ -118,4 +118,7 @@ return -ENOSYS; } +void kerneld_exit(void) +{ +} #endif /* CONFIG_SYSVIPC */ diff -u --recursive --new-file v1.3.57/linux/kernel/ksyms.c linux/kernel/ksyms.c --- v1.3.57/linux/kernel/ksyms.c Sun Jan 14 16:30:15 1996 +++ linux/kernel/ksyms.c Mon Jan 15 08:18:22 1996 @@ -41,28 +41,10 @@ #include #include #include +#include extern unsigned char aux_device_present, kbd_read_mask; -#ifdef __alpha__ -# include -# include - -extern void bcopy (const char *src, char *dst, int len); -extern struct hwrpb_struct *hwrpb; - -/* these are C runtime functions with special calling conventions: */ -extern void __divl (void); -extern void __reml (void); -extern void __divq (void); -extern void __remq (void); -extern void __divlu (void); -extern void __remlu (void); -extern void __divqu (void); -extern void __remqu (void); - -#endif - #ifdef CONFIG_NET #include #include @@ -84,9 +66,6 @@ #include #include #include -#if defined(CONFIG_PPP) || defined(CONFIG_SLIP) -#include "../drivers/net/slhc.h" -#endif #endif #ifdef CONFIG_NET_ALIAS #include @@ -96,10 +75,6 @@ #include #include #endif -#if defined(CONFIG_MSDOS_FS) && !defined(CONFIG_UMSDOS_FS) -#include -#endif - #if defined(CONFIG_PROC_FS) #include #endif @@ -111,6 +86,19 @@ #include #endif +#ifndef CONFIG_SCSI +#if defined(CONFIG_PROC_FS) +/* + * This is all required so that if we load all of scsi as a module, + * that the scsi code will be able to talk to the /proc/scsi handling + * in the procfs. + */ +extern int (* dispatch_scsi_info_ptr) (int ino, char *buffer, char **start, + off_t offset, int length, int inout); +extern struct inode_operations proc_scsi_inode_operations; +#endif +#endif + extern char *get_options(char *str, int *ints); extern void set_device_ro(int dev,int flag); extern struct file_operations * get_blkfops(unsigned int); @@ -124,17 +112,6 @@ #include "../drivers/net/8390.h" #endif -#ifdef CONFIG_SCSI -#include "../drivers/scsi/scsi.h" -#include "../drivers/scsi/scsi_ioctl.h" -#include "../drivers/scsi/hosts.h" -#include "../drivers/scsi/constants.h" -#include "../drivers/scsi/sd.h" -#include - -extern int generic_proc_info(char *, char **, off_t, int, int, int); -#endif - extern int sys_tz; extern int request_dma(unsigned int dmanr, char * deviceID); extern void free_dma(unsigned int dmanr); @@ -154,30 +131,6 @@ SYMBOL_NAME_STR (Using_Versions) }, #endif - /* platform dependent support */ -#ifdef __alpha__ - X(_inb), - X(_inw), - X(_inl), - X(_outb), - X(_outw), - X(_outl), - X(bcopy), /* generated by gcc-2.7.0 for string assignments */ - X(hwrpb), - X(__divl), - X(__reml), - X(__divq), - X(__remq), - X(__divlu), - X(__remlu), - X(__divqu), - X(__remqu), - X(strlen), /* used by ftape */ - X(memcmp), - X(memmove), - X(__constant_c_memset), -#endif - /* stackable module support */ X(rename_module_symbol), X(register_symtab), @@ -361,9 +314,6 @@ X(interruptible_sleep_on), X(schedule), X(current_set), -#if defined(__i386__) && defined(__SMP__) - X(apic_reg), /* Needed internally for the I386 inlines */ -#endif X(jiffies), X(xtime), X(do_gettimeofday), @@ -431,15 +381,6 @@ X(ethdev_init), X(NS8390_init), #endif -#if defined(CONFIG_PPP) || defined(CONFIG_SLIP) - /* VJ header compression */ - X(slhc_init), - X(slhc_free), - X(slhc_remember), - X(slhc_compress), - X(slhc_uncompress), - X(slhc_toss), -#endif #ifdef CONFIG_NET_ALIAS #include #endif @@ -484,50 +425,24 @@ X(tty_register_ldisc), X(kill_fasync), #endif -#ifdef CONFIG_SCSI - /* Supports loadable scsi drivers - * technically some of this stuff could be moved to scsi.c, but - * scsi.c is initialized before the memory manager is set up. - * So we add it here too. There is a duplicate set in scsi.c - * that is used when the entire scsi subsystem is a loadable - * module. - */ - X(scsi_register_module), - X(scsi_unregister_module), - X(scsi_free), - X(scsi_malloc), - X(scsi_register), - X(scsi_unregister), - X(scsicam_bios_param), - X(allocate_device), - X(scsi_do_cmd), - X(scsi_command_size), - X(scsi_init_malloc), - X(scsi_init_free), - X(scsi_ioctl), - X(scsi_mark_host_bus_reset), - X(print_command), - X(print_msg), - X(print_status), - X(print_sense), - X(dma_free_sectors), - X(kernel_scsi_ioctl), - X(need_isa_buffer), - X(request_queueable), - X(generic_proc_info), - X(scsi_devices), - X(gendisk_head), /* Needed for sd.c */ - X(resetup_one_dev), /* Needed for sd.c */ -#if defined(CONFIG_PROC_FS) - X(proc_print_scsidevice), -#endif -#else +#ifndef CONFIG_SCSI /* * With no scsi configured, we still need to export a few * symbols so that scsi can be loaded later via insmod. + * Don't remove this unless you are 100% sure of what you are + * doing. If you want to remove this, you don't know what + * you are doing! */ X(gendisk_head), X(resetup_one_dev), +#if defined(CONFIG_PROC_FS) + /* + * This is required so that if we load scsi later, that the + * scsi code can attach to /proc/scsi in the correct manner. + */ + X(proc_scsi_inode_operations), + X(dispatch_scsi_info_ptr), +#endif #endif /* Added to make file system as module */ X(set_writetime), @@ -547,38 +462,6 @@ X(insert_inode_hash), X(event), X(__down), -#if defined(CONFIG_MSDOS_FS) && !defined(CONFIG_UMSDOS_FS) - /* support for umsdos fs */ - X(msdos_bmap), - X(msdos_create), - X(msdos_file_read), - X(msdos_file_write), - X(msdos_lookup), - X(msdos_mkdir), - X(msdos_mmap), - X(msdos_put_inode), - X(msdos_put_super), - X(msdos_read_inode), - X(msdos_read_super), - X(msdos_readdir), - X(msdos_rename), - X(msdos_rmdir), - X(msdos_smap), - X(msdos_statfs), - X(msdos_truncate), - X(msdos_unlink), - X(msdos_unlink_umsdos), - X(msdos_write_inode), -#endif -#ifdef CONFIG_PROC_FS - X(proc_register), - X(proc_unregister), - X(in_group_p), - X(generate_cluster), - X(proc_scsi), - X(proc_net_inode_operations), - X(proc_net), -#endif /* all busmice */ X(add_mouse_randomness), X(fasync_helper), diff -u --recursive --new-file v1.3.57/linux/kernel/sched.c linux/kernel/sched.c --- v1.3.57/linux/kernel/sched.c Sat Jan 6 19:10:42 1996 +++ linux/kernel/sched.c Wed Jan 17 07:31:59 1996 @@ -38,6 +38,9 @@ /* * kernel variables */ + +int securelevel = 0; /* system security level */ + long tick = 1000000 / HZ; /* timer interrupt period */ volatile struct timeval xtime; /* The current time */ int tickadj = 500/HZ; /* microsecs */ diff -u --recursive --new-file v1.3.57/linux/kernel/sysctl.c linux/kernel/sysctl.c --- v1.3.57/linux/kernel/sysctl.c Sun Jan 14 16:30:16 1996 +++ linux/kernel/sysctl.c Wed Jan 17 07:31:59 1996 @@ -5,7 +5,7 @@ * Added /proc support, Dec 1995 */ -#include +#include #include #include #include @@ -81,6 +81,9 @@ static void unregister_proc_table(ctl_table *, struct proc_dir_entry *); #endif +static int do_securelevel_strategy (ctl_table *, int *, int, void *, size_t *, + void *, size_t, void **); + /* The default sysctl tables: */ static ctl_table root_table[] = { @@ -108,6 +111,8 @@ 0444, NULL, &proc_dointvec}, {KERN_MAXFILE, "file-max", &max_files, sizeof(int), 0644, NULL, &proc_dointvec}, + {KERN_SECURELVL, "securelevel", &securelevel, sizeof(int), + 0444, NULL, &proc_dointvec, (ctl_handler *)&do_securelevel_strategy}, {0} }; @@ -293,6 +298,27 @@ return 0; } +/* + * This function only checks permission for changing the security level + * If the tests are successfull, the actual change is done by + * do_sysctl_strategy + */ +static int do_securelevel_strategy (ctl_table *table, + int *name, int nlen, + void *oldval, size_t *oldlenp, + void *newval, size_t newlen, void **context) +{ + int level; + + if (newval && newlen) { + if (newlen != sizeof (int)) + return -EINVAL; + memcpy_fromfs (&level, newval, newlen); + if (level < securelevel && current->pid != 1) + return -EPERM; + } + return 0; +} struct ctl_table_header *register_sysctl_table(ctl_table * table, int insert_at_head) diff -u --recursive --new-file v1.3.57/linux/mm/filemap.c linux/mm/filemap.c --- v1.3.57/linux/mm/filemap.c Sun Jan 14 16:30:16 1996 +++ linux/mm/filemap.c Thu Jan 18 06:41:22 1996 @@ -43,14 +43,20 @@ void invalidate_inode_pages(struct inode * inode, unsigned long start) { - struct page ** p = &inode->i_pages; + struct page ** p; struct page * page; +repeat: + p = &inode->i_pages; while ((page = *p) != NULL) { unsigned long offset = page->offset; /* page wholly truncated - free it */ if (offset >= start) { + if (page->locked) { + wait_on_page(page); + goto repeat; + } inode->i_nrpages--; if ((*p = page->next) != NULL) (*p)->prev = page->prev; @@ -107,7 +113,7 @@ page->referenced = 1; else if (page->referenced) page->referenced = 0; - else if (page->count) { + else if (page->count && !page->locked) { /* The page is an old, unshared page --- try to discard it. */ if (page->inode) { @@ -179,13 +185,15 @@ { struct page * page; + offset &= PAGE_MASK; if (!page_cache) { page_cache = __get_free_page(GFP_KERNEL); if (!page_cache) return 0; } -#ifdef readahead_makes_sense_due_to_asynchronous_reads - offset = (offset + PAGE_SIZE) & PAGE_MASK; + if (offset >= inode->i_size) + return page_cache; +#if 1 page = find_page(inode, offset); if (page) { page->count--; @@ -202,11 +210,8 @@ add_page_to_inode_queue(inode, page); add_page_to_hash_queue(inode, page); - /* - * And start IO on it.. - * (this should be asynchronous, but currently isn't) - */ inode->i_op->readpage(inode, page); + free_page(page_cache); return 0; #else @@ -214,17 +219,41 @@ #endif } +/* + * Wait for IO to complete on a locked page. + */ +void __wait_on_page(struct page *page) +{ + struct wait_queue wait = { current, NULL }; + + page->count++; + add_wait_queue(&page->wait, &wait); +repeat: + current->state = TASK_UNINTERRUPTIBLE; + if (page->locked) { + schedule(); + goto repeat; + } + remove_wait_queue(&page->wait, &wait); + page->count--; + current->state = TASK_RUNNING; +} + + /* * This is a generic file read routine, and uses the * inode->i_op->readpage() function for the actual low-level * stuff. */ +#define READAHEAD_PAGES 3 +#define MAX_IO_PAGES 4 int generic_file_read(struct inode * inode, struct file * filp, char * buf, int count) { - int read = 0; + int read = 0, newpage = 0; unsigned long pos; unsigned long page_cache = 0; - + int pre_read = 0; + if (count <= 0) return 0; @@ -232,6 +261,8 @@ do { struct page *page; unsigned long offset, addr, nr; + int i; + off_t p; if (pos >= inode->i_size) break; @@ -278,21 +309,49 @@ add_page_to_inode_queue(inode, page); add_page_to_hash_queue(inode, page); - /* - * And start IO on it.. - * (this should be asynchronous, but currently isn't) - */ inode->i_op->readpage(inode, page); + /* We only set "newpage" when we encounter a + completely uncached page. This way, we do no + readahead if we are still just reading data out of + the cache (even if the cached page is not yet + uptodate --- it may be currently being read as a + result of previous readahead). -- sct */ + newpage = 1; found_page: addr = page_address(page); if (nr > count) nr = count; - if (!page->uptodate) { - page_cache = try_to_read_ahead(inode, offset, page_cache); - if (!page->uptodate) - sleep_on(&page->wait); + /* We have two readahead cases. First, do data + pre-read if the current read request is for more + than one page, so we can merge the adjacent + requests. */ + if (newpage && nr < count) { + if (pre_read > 0) + pre_read -= PAGE_SIZE; + else { + pre_read = (MAX_IO_PAGES-1) * PAGE_SIZE; + if (pre_read > (count - nr)) + pre_read = count - nr; + for (i=0, p=pos; if_reada + && !((pos + nr) & ~PAGE_MASK)) { + for (i=0, p=pos; i inode->i_size - pos) nr = inode->i_size - pos; memcpy_tofs(buf, (void *) (addr + offset), nr); @@ -304,6 +363,7 @@ } while (count); filp->f_pos = pos; + filp->f_reada = 1; if (page_cache) free_page(page_cache); if (!IS_RDONLY(inode)) { @@ -315,7 +375,7 @@ /* * Find a cached page and wait for it to become up-to-date, return - * the page address. + * the page address. Increments the page count. */ static inline unsigned long fill_page(struct inode * inode, unsigned long offset) { @@ -344,8 +404,7 @@ add_page_to_hash_queue(inode, page); inode->i_op->readpage(inode, page); found_page: - if (!page->uptodate) - sleep_on(&page->wait); + wait_on_page(page); return page_address(page); } diff -u --recursive --new-file v1.3.57/linux/mm/swap.c linux/mm/swap.c --- v1.3.57/linux/mm/swap.c Sun Jan 14 16:30:16 1996 +++ linux/mm/swap.c Thu Jan 18 06:41:22 1996 @@ -58,6 +58,8 @@ RCL_ROUND_ROBIN /* Balancing policy */ }; +swapstat_t swapstats = {0}; + /* General swap control */ /* Parse the kernel command line "swap=" option at load time: */ diff -u --recursive --new-file v1.3.57/linux/mm/vmscan.c linux/mm/vmscan.c --- v1.3.57/linux/mm/vmscan.c Sun Jan 14 16:30:16 1996 +++ linux/mm/vmscan.c Thu Jan 18 06:43:09 1996 @@ -3,7 +3,9 @@ * * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds * - * Swap reorganised 29.12.95, + * Swap reorganised 29.12.95, Stephen Tweedie. + * kswapd added: 7.1.96 sct + * Version: $Id: vmscan.c,v 1.3.2.3 1996/01/17 02:43:11 linux Exp $ */ #include @@ -357,6 +359,7 @@ int kswapd(void *unused) { int i; + char *revision="$Revision: 1.3.2.3 $", *s, *e; current->session = 1; current->pgrp = 1; @@ -380,15 +383,21 @@ namings for POSIX.4 realtime scheduling priorities. */ - printk ("Started kswapd v$Revision: 1.1.2.3 $\n"); init_swap_timer(); + if ((s = strchr(revision, ':')) && + (e = strchr(s, '$'))) + s++, i = e - s; + else + s = revision, i = -1; + printk ("Started kswapd v%.*s\n", i, s); + while (1) { kswapd_awake = 0; current->signal = 0; interruptible_sleep_on(&kswapd_wait); kswapd_awake = 1; - + swapstats.wakeups++; /* Do the background pageout: */ for (i=0; i < kswapd_ctl.maxpages; i++) try_to_free_page(GFP_KERNEL, ~0UL); diff -u --recursive --new-file v1.3.57/linux/net/Config.in linux/net/Config.in --- v1.3.57/linux/net/Config.in Wed Dec 13 09:02:47 1995 +++ linux/net/Config.in Sun Jan 14 16:22:16 1996 @@ -20,3 +20,4 @@ if [ "$CONFIG_NETLINK" = "y" ]; then bool 'Routing messages' CONFIG_RTNETLINK fi +endmenu diff -u --recursive --new-file v1.3.57/linux/net/ipv4/proc.c linux/net/ipv4/proc.c --- v1.3.57/linux/net/ipv4/proc.c Mon Nov 13 12:36:46 1995 +++ linux/net/ipv4/proc.c Sun Jan 14 16:45:11 1996 @@ -30,7 +30,6 @@ * 2 of the License, or (at your option) any later version. */ #include -#include #include #include #include diff -u --recursive --new-file v1.3.57/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c --- v1.3.57/linux/net/ipv4/tcp.c Thu Jan 4 21:54:59 1996 +++ linux/net/ipv4/tcp.c Wed Jan 17 07:32:09 1996 @@ -256,7 +256,7 @@ * * Use of PSH (4.2.2.2) * MAY aggregate data sent without the PSH flag. (does) - * MAY queue data recieved without the PSH flag. (does) + * MAY queue data received without the PSH flag. (does) * SHOULD collapse successive PSH flags when it packetizes data. (doesn't) * MAY implement PSH on send calls. (doesn't, thus:) * MUST NOT buffer data indefinitely (doesn't [1 second]) @@ -281,12 +281,12 @@ * [Follows BSD 1 byte of urgent data] * * TCP Options (4.2.2.5) - * MUST be able to recieve TCP options in any segment. (does) + * MUST be able to receive TCP options in any segment. (does) * MUST ignore unsupported options (does) * * Maximum Segment Size Option (4.2.2.6) * MUST implement both sending and receiving MSS. (does) - * SHOULD send an MSS with every SYN where recieve MSS != 536 (MAY send + * SHOULD send an MSS with every SYN where receive MSS != 536 (MAY send * it always). (does, even when MSS == 536, which is legal) * MUST assume MSS == 536 if no MSS received at connection setup (does) * MUST calculate "effective send MSS" correctly: @@ -798,7 +798,7 @@ { del_timer(&sk->retransmit_timer); sk->ip_xmit_timeout = why; - if((int)when < 0) + if((long)when < 0) { when=3; printk("Error: Negative timer in xmit_timer\n"); @@ -3643,10 +3643,10 @@ sk->rto = ((sk->rtt >> 2) + sk->mdev) >> 1; if (sk->rto > 120*HZ) sk->rto = 120*HZ; - if (sk->rto < 20) /* Was 1*HZ, then 1 - turns out we must allow about + if (sk->rto < HZ/5) /* Was 1*HZ, then 1 - turns out we must allow about .2 of a second because of BSD delayed acks - on a 100Mb/sec link .2 of a second is going to need huge windows (SIGH) */ - sk->rto = 20; + sk->rto = HZ/5; } } @@ -3743,8 +3743,8 @@ sk->rto = ((sk->rtt >> 2) + sk->mdev) >> 1; if (sk->rto > 120*HZ) sk->rto = 120*HZ; - if (sk->rto < 20) /* Was 1*HZ - keep .2 as minimum cos of the BSD delayed acks */ - sk->rto = 20; + if (sk->rto < HZ/5) /* Was 1*HZ - keep .2 as minimum cos of the BSD delayed acks */ + sk->rto = HZ/5; sk->backoff = 0; } flag |= (2|4); /* 2 is really more like 'don't adjust the rtt diff -u --recursive --new-file v1.3.57/linux/scripts/Configure linux/scripts/Configure --- v1.3.57/linux/scripts/Configure Sat Dec 30 15:50:56 1995 +++ linux/scripts/Configure Wed Jan 17 09:33:33 1996 @@ -48,6 +48,9 @@ function mainmenu_name () { : } +function endmenu () { + : +} # # help prints the corresponding help text from Configure.help to stdout @@ -262,6 +265,35 @@ case "$ans" in [1-9] | [1-9][0-9] | [1-9][0-9][0-9] | [1-9][0-9][0-9][0-9] ) define_int "$2" "$ans" + break;; + * ) help "$2" + ;; + esac + done +} +# +# define_hex sets the value of a hexadecimal argument +# +# define_hex define value +# +function define_hex () { + echo "$1=$2" >>$CONFIG + echo "#define $1 0x$2" >>$CONFIG_H + eval "$1=$2" +} + +# +# hex processes an hexadecimal argument +# +# hex question define default +# +function hex () { + def=$(eval echo "\${$2:-$3}") + while :; do + readln "$1 ($2) [$def] " "$def" + case "$ans" in + [1-9] | [1-9][0-9] | [1-9][0-9][0-9] | [1-9][0-9][0-9][0-9] ) + define_hex "$2" "$ans" break;; * ) help "$2" ;; diff -u --recursive --new-file v1.3.57/linux/scripts/tkparse.c linux/scripts/tkparse.c --- v1.3.57/linux/scripts/tkparse.c Thu Nov 9 11:23:57 1995 +++ linux/scripts/tkparse.c Sun Jan 14 16:22:16 1996 @@ -381,6 +381,11 @@ tok = tok_fi; pnt += 2; } + else if (strncmp(pnt, "endmenu", 7) == 0) + { + tok = tok_endmenu; + pnt += 7; + } if( tok == tok_unknown) { @@ -476,6 +481,7 @@ case tok_else: case tok_fi: case tok_sound: + case tok_endmenu: break; case tok_if: /* @@ -692,6 +698,7 @@ dump_if(cfg->cond); break; case tok_nop: + case tok_endmenu: break; default: printf("\n"); diff -u --recursive --new-file v1.3.57/linux/scripts/tkparse.h linux/scripts/tkparse.h --- v1.3.57/linux/scripts/tkparse.h Thu Nov 9 11:23:57 1995 +++ linux/scripts/tkparse.h Sun Jan 14 16:22:16 1996 @@ -15,7 +15,9 @@ tok_define, tok_choose, tok_choice, + tok_endmenu, tok_unknown + }; enum operator {