From 27fc11ad19808c27b4c9a26f95b1393d79220388 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:10:34 -0500 Subject: [PATCH] Import 1.3.63 --- CREDITS | 7 + Documentation/Configure.help | 242 ++++-- Documentation/cdrom/isp16 | 100 +++ Documentation/cdrom/sjcd | 82 +-- Documentation/modules.txt | 2 + Makefile | 2 +- arch/i386/defconfig | 9 +- arch/ppc/config.in | 3 +- drivers/block/Config.in | 50 +- drivers/block/README.ide | 22 +- drivers/block/ali14xx.c | 27 +- drivers/block/cmd640.c | 83 +-- drivers/block/dtc2278.c | 59 +- drivers/block/ht6560b.c | 177 +++-- drivers/block/ide-cd.c | 86 ++- drivers/block/ide-tape.c | 746 ++++++++++--------- drivers/block/ide-tape.h | 34 +- drivers/block/ide.c | 90 ++- drivers/block/ide.h | 18 +- drivers/block/ide_modes.h | 142 ++++ drivers/block/ll_rw_blk.c | 44 +- drivers/block/qd6580.c | 16 +- drivers/block/rz1000.c | 4 +- drivers/block/triton.c | 30 +- drivers/block/umc8672.c | 24 +- drivers/cdrom/Config.in | 6 +- drivers/cdrom/Makefile | 22 +- drivers/cdrom/cdi.c | 49 ++ drivers/cdrom/isp16.c | 315 ++++++++ drivers/cdrom/optcd.c | 50 +- drivers/cdrom/sjcd.c | 568 +++----------- drivers/char/vt.c | 4 +- drivers/char/wd501p.h | 5 + drivers/net/3c59x.c | 57 +- drivers/net/loopback.c | 26 +- drivers/net/slip.c | 1 + drivers/scsi/NCR5380.c | 6 +- drivers/scsi/NCR53c406a.c | 1311 +++++++++++++++++---------------- drivers/scsi/NCR53c406a.h | 23 +- drivers/sound/.objects | 4 - drivers/sound/.version | 2 +- drivers/sound/CHANGELOG | 23 +- drivers/sound/COPYING | 34 +- drivers/sound/Config.in | 2 +- drivers/sound/Makefile | 8 +- drivers/sound/Readme | 48 +- drivers/sound/Readme.cards | 93 +-- drivers/sound/Readme.linux | 9 +- drivers/sound/Readme.modules | 2 +- drivers/sound/Readme.v30 | 4 +- drivers/sound/ad1848.c | 40 +- drivers/sound/ad1848_mixer.h | 12 +- drivers/sound/adlib_card.c | 9 +- drivers/sound/aedsp16.c | 1 + drivers/sound/audio.c | 35 +- drivers/sound/configure.c | 31 +- drivers/sound/cs4232.c | 19 +- drivers/sound/dev_table.c | 8 +- drivers/sound/dev_table.h | 58 +- drivers/sound/dmabuf.c | 107 ++- drivers/sound/finetune.h | 33 +- drivers/sound/gus_card.c | 10 +- drivers/sound/gus_midi.c | 23 +- drivers/sound/gus_vol.c | 25 +- drivers/sound/gus_wave.c | 99 +-- drivers/sound/hex2hex.h | 57 +- drivers/sound/ics2101.c | 12 +- drivers/sound/mad16.c | 58 +- drivers/sound/mad16_sb_midi.c | 15 +- drivers/sound/maui.c | 14 +- drivers/sound/midi_synth.c | 14 +- drivers/sound/midi_synth.h | 4 +- drivers/sound/midibuf.c | 22 +- drivers/sound/mpu401.c | 98 ++- drivers/sound/opl3.c | 20 +- drivers/sound/opl3.h | 35 +- drivers/sound/os.h | 8 +- drivers/sound/pas2_card.c | 10 +- drivers/sound/pas2_midi.c | 10 +- drivers/sound/pas2_mixer.c | 12 +- drivers/sound/pas2_pcm.c | 37 +- drivers/sound/patmgr.c | 12 +- drivers/sound/pss.c | 12 +- drivers/sound/pss.h | 371 ---------- drivers/sound/sb16_dsp.c | 72 +- drivers/sound/sb16_midi.c | 38 +- drivers/sound/sb_card.c | 17 +- drivers/sound/sb_dsp.c | 107 ++- drivers/sound/sb_midi.c | 12 +- drivers/sound/sb_mixer.c | 18 +- drivers/sound/sb_mixer.h | 14 +- drivers/sound/sequencer.c | 140 ++-- drivers/sound/sound_calls.h | 50 +- drivers/sound/sound_config.h | 39 +- drivers/sound/sound_pnp.c | 203 ----- drivers/sound/sound_switch.c | 28 +- drivers/sound/sound_timer.c | 16 +- drivers/sound/soundcard.c | 40 +- drivers/sound/soundvers.h | 2 +- drivers/sound/sscape.c | 28 +- drivers/sound/sys_timer.c | 20 +- drivers/sound/trix.c | 44 +- drivers/sound/uart6850.c | 67 +- fs/dquot.c | 22 +- fs/inode.c | 12 +- fs/msdos/msdosfs_syms.c | 2 + fs/proc/array.c | 4 +- include/linux/blk.h | 10 +- include/linux/if_slip.h | 2 +- include/linux/isp16.h | 75 ++ include/linux/proc_fs.h | 1 + include/linux/sched.h | 28 +- include/linux/sjcd.h | 4 +- include/linux/skbuff.h | 180 +++-- include/linux/soundcard.h | 83 +-- include/linux/time.h | 4 +- include/linux/ultrasound.h | 43 +- include/net/tcp.h | 4 +- init/main.c | 8 + kernel/ksyms.c | 1 - kernel/panic.c | 22 + kernel/sched.c | 4 +- net/core/dev.c | 108 ++- net/core/iovec.c | 5 +- net/core/skbuff.c | 43 +- net/core/sock.c | 36 +- net/ipv4/af_inet.c | 14 +- net/ipv4/tcp.c | 245 +++--- net/ipv4/tcp_input.c | 506 +++++++------ net/ipv4/tcp_output.c | 98 +-- net/ipv4/tcp_timer.c | 7 +- net/socket.c | 12 +- net/unix/af_unix.c | 77 +- scripts/Configure | 216 +++--- 134 files changed, 4729 insertions(+), 4204 deletions(-) create mode 100644 Documentation/cdrom/isp16 create mode 100644 drivers/block/ide_modes.h create mode 100644 drivers/cdrom/cdi.c create mode 100644 drivers/cdrom/isp16.c delete mode 100644 drivers/sound/pss.h delete mode 100644 drivers/sound/sound_pnp.c create mode 100644 include/linux/isp16.h diff --git a/CREDITS b/CREDITS index 3634becfe9d9..a7d5e4eea766 100644 --- a/CREDITS +++ b/CREDITS @@ -366,6 +366,13 @@ N: Philip Gladstone E: philipg@onsett.com D: Kernel / timekeeping stuff +N: Danny ter Haar +E: dth@cistron.nl +D: /proc/procinfo, reboot on panic , kernel pre-patch tester ;) +S: PObox 297 +S: 2400 AG, Alphen aan den Rijn +S: The Netherlands + N: Bruno Haible E: haible@ma2s2.mathematik.uni-karlsruhe.de D: Unified SysV FS based on Xenix FS (part of standard kernel since 0.99.15) diff --git a/Documentation/Configure.help b/Documentation/Configure.help index 0660c08d0b34..092e2ebb5eca 100644 --- a/Documentation/Configure.help +++ b/Documentation/Configure.help @@ -70,80 +70,138 @@ CONFIG_BLK_DEV_RAM Most normal users won't need the RAM disk functionality, and can thus say N here. -Normal (MFM/RLL) disk and IDE disk/cdrom support -CONFIG_ST506 - This is the regular, non-SCSI harddisk support. Pretty much everyone - will want to say Y here, except if they configure a diskless machine - which mounts all files over the network using NFS (rare; if you are - planning to do this, have a look at the package - /pub/Linux/system/Linux-boot/netboot-nfs.tar.gz, available via ftp - (user: anonymous) from sunsite.unc.edu, extract with "tar xzvf - filename") or if they exclusively use SCSI drives and no IDE/ATAPI - CDROMs (ATAPI = AT Attachment Packet Interface is a new protocol - currently used for controlling CDROM and tape drives, similar to the - SCSI protocol. Some newer CDROM drives such as NEC 260 and MITSUMI - triple/quad speed drives use it, but most MITSUMI CDROM drives - don't). Useful information about how to use large (>504MB) IDE - harddrives and how to work around a hardware bug in the CMD640 IDE - interface is contained in drivers/block/README.ide. To fine-tune - the parameters of your IDE drive for improved performance, you might - want to have a look at the hdparm package in +Enhanced IDE/MFM/RLL disk/cdrom/tape support +CONFIG_BLK_DEV_IDE + This will use the full-featured IDE driver to control up to four IDE + interfaces, for a combination of up to eight IDE disk/cdrom/tape drives. + Useful information about large (>540MB) IDE disks, soundcard IDE ports, + and other topics, is all contained in drivers/block/README.ide. + If you have one or more IDE drives, say Y here. + If your system has no IDE drives, or if memory requirements are really tight, + you could say N here, and select the Old harddisk driver instead to save + about 13kB of memory in the kernel. + To fine-tune IDE drive/interface parameters for improved performance, + look for the hdparm package at sunsite.unc.edu:/pub/Linux/kernel/patches/diskdrives/ - -Use old (reliable) disk-only driver for primary i/f -CONFIG_BLK_DEV_HD - As you might have guessed, there are now two drivers for IDE - harddrives around: the old one and the new improved one. The old one - is not any longer more reliable than the new one. The new driver can - also handle IDE/ATAPI CDROM and tape drives (ATAPI = AT Attachment Packet - Interface is a new protocol currently used for controlling CDROM and - tape drives, similar to the SCSI protocol. Some newer CDROM drives - such as NEC 260 and MITSUMI triple/quad speed drives use it, but - most MITSUMI CDROM drives don't). The old driver supports up to two - hard drives, while the new one can deal with any mix of up to eight - hard drives and IDE/ATAPI CDROMs, two per IDE interface. Using the - old driver makes sense if you have older MFM/RLL/ESDI drives, since - it is smaller and these drives don't benefit from the additional - features of the new driver. If you have more than one IDE interface - (=controller), you can use the old driver on the first and the new - one on the others, if you like. In that case (or if you have just - one interface and don't want to use the new driver at all) you would - say Y here, thereby enlarging your kernel by about 4 kB. If you want - to use the new driver exclusively, say N and answer Y to the - following question(s). Useful information about how to use large - (>504MB) IDE harddrives is contained in drivers/block/README.ide. If - unsure, say N. -Use new IDE driver for primary/secondary i/f -CONFIG_BLK_DEV_IDE - This will use the new and improved IDE driver for the specified IDE - interface (=controller). You can use up to 8 IDE harddisks and - IDE/ATAPI CDROMs, 2 per interface. (ATAPI = AT Attachment Packet - Interface is a new protocol currently used for controlling CDROM and - tape drives, similar to the SCSI protocol. Some newer CDROM drives - such as NEC 260 and MITSUMI triple/quad speed drives use it, but - most MITSUMI CDROM drives don't.) If you have just one IDE harddisk - and no IDE/ATAPI CDROM drive and you intend to use the old IDE - driver on the primary interface, say N here. Everybody else says - Y. This driver enlarges your kernel by about 8kB. Useful information - about how to use large (>504MB) IDE harddrives and how to use more - than 2 IDE interfaces is contained in drivers/block/README.ide. - -Include support for IDE/ATAPI CDROMs +Old harddisk (MFM/RLL/IDE) driver +CONFIG_BLK_DEV_HD_ONLY + There are two drivers for MFM/RLL/IDE disks. Most people use the + newer enhanced driver, but the old one is still around for two reasons. + Some older systems have strange timing problems and seem to work only + with the old driver (which itself does not work with some newer systems). + The other reason is that the old driver is smaller, since it lacks the + enhanced functionality of the new one. This makes it a good choice + for systems with very tight memory restrictions, or for systems with + only older MFM/RLL/ESDI drives. Choosing the old driver can save 13kB + or so of kernel memory. If you are unsure, then just choose the + Enhanced IDE/MFM/RLL driver instead of this one. + +Use old disk-only driver on primary interface +CONFIG_BLK_DEV_HD_IDE + There are two drivers for MFM/RLL/IDE disks. Most people use just the + new enhanced driver by itself. This option installs the old harddisk + driver to control the primary IDE/disk interface in the system, + leaving the new enhanced IDE driver take care of only the 2nd/3rd/4th + IDE interfaces. Choosing this option may be useful for older systems + which have MFM/RLL/ESDI controller+drives at the primary port address + (0x1f0), along with IDE drives at the secondary/3rd/4th port addresses. + Normally, just say N here. + +Include IDE/ATAPI CDROM support CONFIG_BLK_DEV_IDECD - If you have a CDROM drive using the ATAPI protocol, say Y. (ATAPI = - AT Attachment Packet Interface is a new protocol currently used for - controlling CDROM and tape drives, similar to the SCSI protocol and - derived from IDE=ATA. Some newer CDROM drives such as NEC 260 and - MITSUMI triple/quad speed drives use it, but most MITSUMI CDROM - drives don't.) If this is your only CDROM drive, you can say N to - all other CDROM options appearing later, but make sure to say Y to - the ISO9660 filesystem and read the CDROM-HOWTO, available via ftp - (user: anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO. Note - that older version of the linux boot loader lilo cannot properly - deal with IDE/ATAPI CDROMs; install lilo 16 or higher, available + If you have a CDROM drive using the ATAPI protocol, say Y. + ATAPI is a new protocol used by IDE CDROM and TAPE drives, + similar to the SCSI protocol. Most new CDROM drives use ATAPI, + including the NEC-260, Mitsumi FX400, Sony 55E, and just about + all non-SCSI double(2X), quad(4X), and six(6X) speed drives. + At boot time, the TAPE drive will be identified along with other IDE devices, + as "hdb" or "hdc", or something similar. + If this is your only CDROM drive, you can say N to all other CDROM options, + but be sure to say Y to the ISO9660 filesystem. Read the CDROM-HOWTO, + available via ftp (user: anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO. + Note that older versions of lilo (the linux boot loader) cannot properly + deal with IDE/ATAPI CDROMs, so install lilo-16 or higher, available from sunsite.unc.edu:/pub/Linux/system/Linux-boot/lilo. +Include IDE/ATAPI TAPE support +CONFIG_BLK_DEV_IDETAPE + If you have an IDE tape drive using the ATAPI protocol, say Y. + ATAPI is a new protocol used by IDE TAPE and ATAPI drives, + similar to the SCSI protocol. At boot time, the TAPE drive will + be identified along with other IDE devices, as "hdb" or "hdc", + or something similar. Be sure to consult the drivers/block/ide-tape.c + and README.ide files for usage information. + +CMD640 chipset bugfix/support +CONFIG_BLK_DEV_CMD640 + The CMD-Technologies CMD640 chip is used on many common 486 and Pentium + motherboards, usually in combination with a "Neptune" or "SiS" chipset. + Unfortunately, it has a number of rather nasty design flaws that can cause + severe data corruption under many common conditions. Say Y here to include + code which tries to automatically detect and correct the problems under Linux. + This also provides support for the enhanced features of the CMD640, + for improved support/operation under linux, including access to the secondary + IDE ports in some systems. This driver will work automatically in PCI + based systems (most new systems have PCI slots). But if your system uses + VESA local bus (VLB) instead of PCI, you must also supply a kernel boot + parameter to enable the CMD640 bugfix/support: "ide0=cmd640_vlb" + The CMD640 chip is also used on add-in cards by Acculogic, + and on the "CSA-6400E PCI to IDE controller" that some people have. + +RZ1000 chipset bugfix/support +CONFIG_BLK_DEV_RZ1000 + The PC-Technologies RZ1000 chip is used on many common 486 and Pentium + motherboards, usually along with the "Neptune" chipset. Unfortunately, + it has a rather nasty design flaw that can cause severe data corruption + under many conditions. Say Y here to include code which automatically + detects and corrects the problem under Linux. This may slow disk throughput + by a few percent, but at least things will operate 100% reliably. + +Other IDE chipset support +CONFIG_IDE_CHIPSETS + Say Y here if you want to include enhanced support for various + IDE interface chipsets used on motherboards and add-on cards. + This enhanced support may be necessary for linux to be able to access + the 3rd/4th drives in some systems. It may also enable setting of + higher speed I/O rates to improve system performance with these chipsets. + Most of these also require special kernel boot parameters to actually + turn on the support at runtime. + +DTC-2278 chipset support +CONFIG_BLK_DEV_DTC2278 + This driver is enabled at runtime using the "ide0=dtc2278" kernel + boot parameter. It enables support for the secondary IDE interface + of the DTC-2278 card, and permits faster I/O speeds to be set as well. + See the README.ide and dtc2278.c files for more info. + +Holtek HT6560B chipset support +CONFIG_BLK_DEV_HT6560B + This driver is enabled at runtime using the "ide0=ht6560b" kernel + boot parameter. It enables support for the secondary IDE interface + of the Holtek card, and permits faster I/O speeds to be set as well. + See the README.ide and ht6560b.c files for more info. + +QDI QD6580 chipset support +CONFIG_BLK_DEV_QD6580 + This driver is enabled at runtime using the "ide0=qd6580" kernel + boot parameter. It permits faster I/O speeds to be set. + See the README.ide and qd6580.c files for more info. + +UMC 8672 chipset support +CONFIG_BLK_DEV_UMC8672 + This driver is enabled at runtime using the "ide0=umc8672" kernel + boot parameter. It enables support for the secondary IDE interface + of the UMC-8672, and permits faster I/O speeds to be set as well. + See the README.ide and umc8672.c files for more info. + +ALI M1439/M1445 chipset support +CONFIG_BLK_DEV_ALI14XX + This driver is enabled at runtime using the "ide0=ali14xx" kernel + boot parameter. It enables support for the secondary IDE interface + of the chipset, and permits faster I/O speeds to be set as well. + See the README.ide and ali14xx.c files for more info. + XT harddisk support CONFIG_BLK_DEV_XD Very old 8 bit hard disk controllers used in the IBM XT @@ -278,15 +336,16 @@ CONFIG_PCI_OPTIMIZE certain BIOSes if your computer uses a PCI bussystem. This is recommended; say Y. -PCI Triton IDE Bus Master DMA support +Intel 430FX (Triton) chipset DMA support CONFIG_BLK_DEV_TRITON + This option is valid only if PCI BIOS support was also selected earlier. If your PCI system uses an IDE harddrive (as opposed to SCSI, say) - and includes the Intel PCI Triton chipset (82371FB), you will want - to enable this option to improve performance. Read the comments at - the beginning of drivers/block/triton.c. The hdparm utility can be - gotten via ftp (user: anonymous) from - sunsite.unc.edu:/pub/Linux/kernel/patches/diskdrives/. It's safe to - say Y. + and includes the Intel 430FX PCI Triton chipset, you will want + to enable this option to allow use of bus-mastering DMA data transfers. + Read the comments at the beginning of drivers/block/triton.c. + The hdparm utility can be obtained via ftp (user: anonymous) + from sunsite.unc.edu:/pub/Linux/kernel/patches/diskdrives/. + It is safe to say Y. System V IPC CONFIG_SYSVIPC @@ -1885,9 +1944,36 @@ Optics Storage DOLPHIN 8000AT CDROM support CONFIG_OPTCD If this is your CDROM drive, say Y here. -Sanyo H94A CDROM support +Sanyo CDR-H94A CDROM support CONFIG_SJCD - If this is your CDROM drive, say Y here. + If this is your CDROM drive, say Y here. Command line option + (or 'append=' option in /etc/lilo.conf) is: + sjcd= + Here 'port' is the base i/o address used by the drive. It defaults + to port=0x340. + +Soft configurable cdrom interface card support +CONFIG_CDI_INIT + If you want to include boot-time intialisation of any cdrom + interface card that is software configurable, say Y here. + Currently only the ISP16/MAD16/Mozart cards are supported. + +ISP16/MAD16/Mozart soft configurable cdrom interface support +CONFIG_ISP16_CDI + If you want any of these cdrom interface cards based on the + OPTi 82C928 or 82C929 chips get detected and possibly configured + at boot time, please say Y. Boot time command line options (or + 'append=' options in /etc/lilo.conf) are: + isp16=,,, + Here 'port','irq' and 'dma' are the base i/o address, irq number + and dma line assumed to be used by the attached cdrom drive. 'drive_type' + is the type of cdrom drive or its emulation mode. Valid values for + drive_type include: Sanyo, Panasonic (same as Sanyo), Sony and Mitsumi. + Default values are: port=0x340, irq=0, dma=0, drive_type=Sanyo. + The command line + isp16=noisp16 + will skip detection and configuration after all. + N.B. options are case sensitive. Quota support CONFIG_QUOTA diff --git a/Documentation/cdrom/isp16 b/Documentation/cdrom/isp16 new file mode 100644 index 000000000000..96164e2d5d86 --- /dev/null +++ b/Documentation/cdrom/isp16 @@ -0,0 +1,100 @@ + -- Documentation/cdrom/isp16 + +Docs by Eric van der Maarel + +This is the README for version 0.6 of the cdrom interface on an +ISP16, MAD16 or Mozart sound card. + +The detection and configuration of this interface used to be included +in both the sjcd and optcd cdrom driver. Drives supported by these +drivers came packed with Media Magic's multi media kit, which also +included the ISP16 card. The idea (thanks Leo Spiekman) +to move it from thes drivers into a separate module and moreover, not to +rely on the MAD16 sound driver, are as follows: +-duplication of code in the kernel is a waste of resources and should + be avoided; +-however, kernels and notably those included with Linux distributions + (cf Slackware 3.0 included version 0.5 of the isp16 configuration + code included in the drivers) don't always come with sound support + included. Especially when they already include a bunch of cdrom drivers. + Hence, the cdrom interface should be configurable _independently_ of + sound support. + +The ISP16, MAD16 and Mozart sound cards have an OPTi 82C928 or an +OPTi 82C929 chip. The interface on these cards should work with +any cdrom attached to the card, which is 'electrically' compatible +with Sanyo/Panasonic, Sony or Mitsumi non-ide drives. However, the +command sets for any propriatary drives may differ +(and hence may not be supported in the kernel) from these four types. +For a fact I know the interface works and the way of configuration +as described in this documentation works in combination with the +sjcd (in Sanyo/Panasonic compatibility mode) cdrom drivers +(probably with the optcd (in Sony compatibility mode) as well). +If you have such an OPTi based sound card and you want to use the +cdrom interface with a cdrom drive supported by any of the other cdrom +drivers, it will probably work. Please let me know any experience you +might have). +I understand that cards based on the OPTi 82C929 chips may be configured +(hardware jumpers that is) as an IDE interface. Initialisation of such a +card in this mode is not supported (yet?). + +The suggestion to configure the ISP16 etc. sound card by booting DOS and +do a warm reboot to boot Linux somehow doesn't work, at least not +on my machine (IPC P90), with the OPTi 82C928 based card. + +Booting the kernel through the boot manager LILO allows the use +of some command line options on the 'LILO boot:' prompt. At boot time +press Alt or Shift while the LILO prompt is written on the screen and enter +any kernel options. Alternatively these options may be used in +the apropriate section in /etc/lilo.conf. Adding 'append=""' +will do the trick as well. +The syntax of 'cmd_line_options' is + + isp16=[[,[,]]][[,]] + +If there is no ISP16 or compatibles detected, there's probably no harm done. +These options indicate the values that your cdrom drive has been (or will be) +configured to use. +Valid values for the base i/o address are: + port=0x340,0x320,0x330,0x360 +for the interrupt request number + irq=0,3,5,7,9,10,11 +for the direct memory access line + dma=0,3,5,6,7 +and for the type of drive + drive_type=noisp16,Sanyo,Panasonic,Sony,Mitsumi. +Note that these options are case sensitive. +The values 0 for irq and dma indicate that they are not used, and +the drive will be used in 'polling' mode. The values 5 and 7 for irq +should be avoided in order to avoid any conflicts with optional +sound card configuration. +The syntax of the command line does not allow the specifiaction of +irq when there's nothing specified for the base address and no +specification of dma when there is no specification of irq. +The value 'nosip16' for drive_type, which may be used as the first +non-integer option value (e.g. 'isp16=noisp16'), makes sure that probing +for and subsequent configuration of an ISP16-compatible card is skipped +all together. This can be useful to overcome possible conflicts which +may arise while the kernel is probing your hardware. +The default values are + port=0x340 + irq=0 + dma=0 + drive_type=Sanyo +reflecting my own configuration. The defaults can be changed in +the file ~/include/linux/ips16.h. + +The cdrom interface can be configured at run time by loading the +initialisation driver as a module. In that case, the interface +parameters can be set by giving appropriate values on the command +line. Configuring the driver can then be done by the following +command (assuming you have iso16.o installed in a proper place): + + insmod isp16.o isp16_cdrom_base= isp16_cdrom_irq= \ + isp16_cdrom_dma= isp16_cdrom_type= + +where port, irq, dma and drive_type can have any of the values mentioned +above. + + +Have fun! diff --git a/Documentation/cdrom/sjcd b/Documentation/cdrom/sjcd index f475e80ccba9..842084d9d22e 100644 --- a/Documentation/cdrom/sjcd +++ b/Documentation/cdrom/sjcd @@ -1,4 +1,4 @@ - -- README.sjcd + -- Documentation/cdrom/sjcd 80% of the work takes 20% of the time, 20% of the work takes 80% of the time... (Murphy law) @@ -6,57 +6,24 @@ Once started, training can not be stopped... (StarWars) -This is the README for the sjcd cdrom driver, version 1.5. +This is the README for the sjcd cdrom driver, version 1.6. This file is meant as a tips & tricks edge for the usage of the SANYO CDR-H94A cdrom drive. It will grow as the questions arise. ;-) -Since the drive often comes with an ISP16 soundcard, which can be used -as cdrom interface, this is also the place for ISP16 related issues. +For info on configuring the ISP16 sound card look at Documetation/cdrom/isp16. -The driver should work with any SoundBlaster/Panasonic style CDROM interface, -including the "soft configurable" MediaMagic sound card. -To make this sound card (and others like "Mozart") working, it has to get -"configured" by software. -The suggestion to configure the ISP16 soundcard by booting DOS and -a warm reboot to boot Linux somehow doesn't work, at least not -on Eric's machine (IPC P90), with the version of the ISP16 -card he has (there appear to be at least two versions: Eric's card with -no jumpered IDE support and OPTi 82C928 chip, and Vadim's version -with a jumper to enable IDE support, probably with a OPTi 82C929 chip). -Therefore detection and configuration of the ISP16 interfaces is included -in the driver. -If we should support any other interfaces (which cannot be configured -through DOS) or if there are any more ISP16 types, please let us -know (maarel@marin.nl) and we'll see. - -Otherwise, you should boot DOS once (and by this, run the "configuration driver") -and then switch to Linux by use of CTRL-ALT-DEL. Each use of the RESET -button or the power switch makes this procedure necessary again. -If no ISP16 is detected, there's no harm done; a card configured trough DOS -may still work as expected. - -As of version 1.4 sound through the speakers is supported; only for MSS-mode -and no volume controle yet. - -PAUSE and STOP ioctl commands don't seem to work yet. - -ISP16 configuration routines reside at Vadim's server - ftp.rbrf.ru:/linux/mediamagic/ -and at Eberhard's mirror - ftp.gwdg.de:/pub/linux/cdrom/drivers/sanyo/ - -Leo Spiekman's configuration routines for the ISP-16 card can get found at - dutette.et.tudelft.nl:/pub/linux/ -and at Eberhard's mirror - ftp.gwdg.de:/pub/linux/cdrom/drivers/optics/ - -Eric van der Maarel's routines are included in sjcd.c. -This, and any related stuff may be found by anonymous ftp at - ftp.gwdg.de:/pub/linux/cdrom/drivers/sanyo/ +The driver should work with any of the Panasonic, Sony or Mitsum style +CDROM interface. +The cdrom interface on Media Magic's soft configurable sound card ISP16, +which used to be included in the driver, is now supported in a separate module. +This initilisation module will probably also work with other interfaces +based on an OPTi 82C928 or 82C929 chip (like MAD16 and Mozart): see the +documentation Documentation/cdrom/isp16. The device major for sjcd is 18, and minor is 0. Create a block special file in your /dev directory (e.g., /dev/sjcd) with these numbers. -(For those who don't know, being root and doing the following should do the trick: +(For those who don't know, being root and doing the following should do +the trick: mknod -m 644 /dev/sjcd b 18 0 and mount the cdrom by /dev/sjcd). @@ -64,17 +31,30 @@ The default configuration parameters are: base address 0x340 no irq no dma -As of version 1.2, setting base address, irq and dma at boot time is supported +(Acctulay the CDR-H94A doesn't know how to use irq and dma.) +As of version 1.2, setting base address at boot time is supported through the use of command line options: type at the "boot:" prompt: - linux sjcd=,, -(where your kernel is assumed to be called by saying "linux" to -the boot manager). + linux sjcd= +(where you would use the kernel labeled "linux" in lilo's configuration +file /etc/lilo.conf). You could also use 'append="sjcd="' +in the appropriate section of /etc/lilo.conf +If you're building a kernel yourself you can set your default base +i/o address with SJCD_BASE_ADDR in include/linux/sjcd.h. + +The sjcd driver supports beng loaded as a module. The following +command will set the base i/o address on the fly (assuming you +have installed the module in an appropriate place). + insmod sjcd.o sjcd_base= + + +Have fun! -If something is wrong, e-mail to vadim@rbrf.ru +If something is wrong, please email to vadim@rbrf.ru or vadim@ipsun.ras.ru or model@cecmow.enet.dec.com + or H.T.M.v.d.Maarel@marin.nl It happens sometimes that Vadim is not reachable by mail. For these -instances, Eric van der Maarel (maarel@marin.nl) will help, too. +instances, Eric van der Maarel will help too. Vadim V. Model, Eric van der Maarel, Eberhard Moenkeberg diff --git a/Documentation/modules.txt b/Documentation/modules.txt index 21c41d8864e5..dcc382ceb370 100644 --- a/Documentation/modules.txt +++ b/Documentation/modules.txt @@ -51,6 +51,7 @@ The set of modules is rapidly increasing, but so far these are known: gscd: Goldstar GCDR-420 mcd, mcdx: Mitsumi LU005, FX001 optcd: Optics Storage Dolphin 8000AT + sjcd: Sanyo CDR-H94A sbpcd: Matsushita/Panasonic CR52x, CR56x, CD200, Longshine LCS-7260, TEAC CD-55A sonycd535: Sony CDU-531/535, CDU-510/515 @@ -58,6 +59,7 @@ The set of modules is rapidly increasing, but so far these are known: Some misc modules: lp: line printer binfmt_elf: elf loader + isp16: cdrom interface When you have made the kernel, you create the modules by doing: diff --git a/Makefile b/Makefile index 148b15bfc2a5..4265b4d1704e 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 1 PATCHLEVEL = 3 -SUBLEVEL = 62 +SUBLEVEL = 63 ARCH = i386 diff --git a/arch/i386/defconfig b/arch/i386/defconfig index 33d260665981..b0d0a4784ae3 100644 --- a/arch/i386/defconfig +++ b/arch/i386/defconfig @@ -27,21 +27,20 @@ CONFIG_M586=y # CONFIG_M686 is not set # -# Block devices +# Floppy, IDE, and other block devices # CONFIG_BLK_DEV_FD=y # CONFIG_BLK_DEV_RAM is not set -CONFIG_ST506=y +CONFIG_BLK_DEV_IDE=y # # Please see drivers/block/README.ide for help/info on IDE drives # -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDE=y +# CONFIG_BLK_DEV_HD_IDE is not set CONFIG_BLK_DEV_IDECD=y # CONFIG_BLK_DEV_IDETAPE is not set -CONFIG_BLK_DEV_RZ1000=y CONFIG_BLK_DEV_CMD640=y +CONFIG_BLK_DEV_RZ1000=y # CONFIG_BLK_DEV_TRITON is not set # CONFIG_IDE_CHIPSETS is not set # CONFIG_BLK_DEV_XD is not set diff --git a/arch/ppc/config.in b/arch/ppc/config.in index 7889294ed2c6..d8717f80ef77 100644 --- a/arch/ppc/config.in +++ b/arch/ppc/config.in @@ -245,7 +245,8 @@ if [ "$CONFIG_CD_NO_IDESCSI" = "y" ]; then tristate 'Goldstar R420 CDROM support' CONFIG_GSCD n tristate 'Philips/LMS CM206 CDROM support' CONFIG_CM206 n tristate 'Experimental Optics Storage DOLPHIN 8000AT CDROM support' CONFIG_OPTCD n - bool 'Experimental Sanyo H94A CDROM support' CONFIG_SJCD n + tristate 'Sanyo CDR-H94A CDROM support' CONFIG_SJCD n + bool 'ISP16/MAD16/Mozart soft configurable cdrom interface support' CONFIG_ISP16_CDI n fi comment 'Filesystems' diff --git a/drivers/block/Config.in b/drivers/block/Config.in index 9aa221bddd1d..2ddf3868121c 100644 --- a/drivers/block/Config.in +++ b/drivers/block/Config.in @@ -2,38 +2,36 @@ # Block device driver configuration # mainmenu_option next_comment -comment 'Block devices' +comment 'Floppy, IDE, and other block devices' tristate 'Normal floppy disk support' CONFIG_BLK_DEV_FD tristate 'RAM disk support' CONFIG_BLK_DEV_RAM -bool 'Normal (MFM/RLL) disk and IDE disk/cdrom support' CONFIG_ST506 -if [ "$CONFIG_ST506" = "y" ]; then - comment 'Please see drivers/block/README.ide for help/info on IDE drives' - bool ' Use old disk-only driver for primary i/f' CONFIG_BLK_DEV_HD - if [ "$CONFIG_BLK_DEV_HD" = "y" ]; then - bool ' Include new IDE driver for secondary i/f support' CONFIG_BLK_DEV_IDE - else - bool ' Use new IDE driver for primary/secondary i/f' CONFIG_BLK_DEV_IDE - fi - if [ "$CONFIG_BLK_DEV_IDE" = "y" ]; then - bool ' Include IDE/ATAPI CDROM support' CONFIG_BLK_DEV_IDECD - bool ' Include (ALPHA) IDE/ATAPI TAPE support' CONFIG_BLK_DEV_IDETAPE +bool 'Enhanced IDE/MFM/RLL disk/cdrom/tape support' CONFIG_BLK_DEV_IDE +comment 'Please see drivers/block/README.ide for help/info on IDE drives' +if [ "$CONFIG_BLK_DEV_IDE" = "n" ]; then + bool 'Old harddisk (MFM/RLL/IDE) driver' CONFIG_BLK_DEV_HD_ONLY +else + bool ' Use old disk-only driver on primary interface' CONFIG_BLK_DEV_HD_IDE + bool ' Include IDE/ATAPI CDROM support' CONFIG_BLK_DEV_IDECD + bool ' Include IDE/ATAPI TAPE support' CONFIG_BLK_DEV_IDETAPE + bool ' CMD640 chipset bugfix/support' CONFIG_BLK_DEV_CMD640 + if [ "$CONFIG_PCI" = "y" ]; then bool ' RZ1000 chipset bugfix/support' CONFIG_BLK_DEV_RZ1000 - bool ' CMD640 chipset bugfix/support' CONFIG_BLK_DEV_CMD640 - if [ "$CONFIG_PCI" = "y" ]; then - bool ' TRITON chipset DMA support' CONFIG_BLK_DEV_TRITON - fi - bool ' Other IDE chipset support' CONFIG_IDE_CHIPSETS - if [ "$CONFIG_IDE_CHIPSETS" = "y" ]; then - comment 'Note: most of these also require special kernel boot parameters' - bool ' DTC2278 chipset support' CONFIG_BLK_DEV_DTC2278 - bool ' HT6560B chipset support' CONFIG_BLK_DEV_HT6560B - bool ' QD6580 chipset support' CONFIG_BLK_DEV_QD6580 - bool ' UMC8672 chipset support' CONFIG_BLK_DEV_UMC8672 - bool ' ALI14XX chipset support' CONFIG_BLK_DEV_ALI14XX - fi + bool ' Intel 430FX (Triton) chipset DMA support' CONFIG_BLK_DEV_TRITON + fi + bool ' Other IDE chipset support' CONFIG_IDE_CHIPSETS + if [ "$CONFIG_IDE_CHIPSETS" = "y" ]; then + comment 'Note: most of these also require special kernel boot parameters' + bool ' DTC-2278 chipset support' CONFIG_BLK_DEV_DTC2278 + bool ' Holtek HT6560B chipset support' CONFIG_BLK_DEV_HT6560B + bool ' QDI QD6580 chipset support' CONFIG_BLK_DEV_QD6580 + bool ' UMC 8672 chipset support' CONFIG_BLK_DEV_UMC8672 + bool ' ALI M1439/M1445 chipset support' CONFIG_BLK_DEV_ALI14XX fi fi +if [ "$CONFIG_BLK_DEV_HD_IDE" = "y" -o "$CONFIG_BLK_DEV_HD_ONLY" = "y" ]; then + define_bool CONFIG_BLK_DEV_HD y +fi bool 'XT harddisk support' CONFIG_BLK_DEV_XD endmenu diff --git a/drivers/block/README.ide b/drivers/block/README.ide index ac52506e56cc..b9faf0905d2d 100644 --- a/drivers/block/README.ide +++ b/drivers/block/README.ide @@ -58,6 +58,7 @@ NEW! - Bus-Master DMA support for Intel PCI Triton chipset IDE interfaces NEW! - ide-cd.c now supports door locking and auto-loading. - Also preliminary support for multisession and direct reads of audio data. +NEW! - the hdparm-2.6 package can be used to set PIO modes for some chipsets. For work in progress, see the comments in ide.c, ide-cd.c, and triton.c. @@ -260,7 +261,7 @@ Summary of ide driver parameters for kernel "command line": "ide0=cmd640_vlb" : *REQUIRED* for VLB cards with the CMD640 chip (not for PCI -- automatically detected) "ide0=qd6580" : probe/support qd6580 interface - "ide0=ali14xx" : probe/support ali14xx chipsets (ALI M1439, M1443, M1445) + "ide0=ali14xx" : probe/support ali14xx chipsets (ALI M1439/M1445) "ide0=umc8672" : probe/support umc8672 chipsets Everything else is rejected with a "BAD OPTION" message. @@ -428,6 +429,25 @@ more generally compatible method of achieving the same results (DOS access to the entire disk). However, if you must use DiskManager, it now works with Linux 1.3.x in most cases. Let me know if you still have trouble. +My recommendations to anyone who asks about NEW systems are: + + - buy a motherboard that uses the Intel Triton chipset -- very common. + - use IDE for the first two drives, placing them on separate interfaces. + - place the IDE cdrom drive as slave on either interface. + - if additional disks are to be connected, consider your needs: + - fileserver? Buy a SC200 SCSI adaptor for the next few drives. + - personal system? Use IDE for the next two drives. + - still not enough? Keep adding SC200 SCSI cards as needed. + +Most manufacturers make both IDE and SCSI-2 versions of each of their drives. +The IDE ones are usually faster and cheaper, due to the higher data transfer +speed of PIO mode4 (ATA2), 16.6MBytes/sec versus 10Mbytes/sec for SCSI-2. + +In particular, I recommend Quantum FireBalls as cheap and exceptionally fast. +The new WD1.6GB models are also cheap screamers. + +For really high end systems, go for fast/wide 7200rpm SCSI. But it'll cost ya! + mlord@bnr.ca ================================================================================ diff --git a/drivers/block/ali14xx.c b/drivers/block/ali14xx.c index 6d5c47f38113..717d717790ed 100644 --- a/drivers/block/ali14xx.c +++ b/drivers/block/ali14xx.c @@ -1,5 +1,5 @@ /* - * linux/drivers/block/ali14xx.c Version 0.01 Feb 06, 1996 + * linux/drivers/block/ali14xx.c Version 0.03 Feb 09, 1996 * * Copyright (C) 1996 Linus Torvalds & author (see below) */ @@ -37,8 +37,21 @@ #include #include #include "ide.h" +#include "ide_modes.h" -#define ALI_14xx_BUS_SPEED 40 /* PCI / VLB bus speed */ +/* + * This should be set to the system's local bus (PCI or VLB) speed, + * e.g., 33 for a 486DX33 or 486DX2/66. Legal values are anything + * from 25 to 50. Setting this too *low* will make the EIDE + * controller unable to communicate with the disks. + * + * I suggest using a default of 50, since it should work ok with any + * system. (Low values cause problems because it multiplies by bus speed + * to get cycles, and thus gets a too-small cycle count and tries to + * access the disks too fast. I tried this once under DOS and it locked + * up the system.) -- derekn@vw.ece.cmu.edu + */ +#define ALI_14xx_BUS_SPEED 50 /* PCI / VLB bus speed */ /* port addresses for auto-detection */ #define ALI_NUM_PORTS 4 @@ -112,11 +125,11 @@ static void ali14xx_tune_drive (ide_drive_t *drive, byte pio) struct hd_driveid *id = drive->id; unsigned long flags; - if (pio == 255) { /* auto-tune */ - pio = id->tPIO; - if ((id->field_valid & 0x02) && (id->eide_pio_modes & 0x01)) - pio = 3; - } + if (pio == 255) + pio = ide_get_best_pio_mode(drive); + if (pio > 3) + pio = 3; + /* calculate timing, according to PIO mode */ time1 = timeTab[pio].time1; time2 = timeTab[pio].time2; diff --git a/drivers/block/cmd640.c b/drivers/block/cmd640.c index 927958f8a61f..99a139dc9d06 100644 --- a/drivers/block/cmd640.c +++ b/drivers/block/cmd640.c @@ -56,6 +56,7 @@ #include #include #include "ide.h" +#include "ide_modes.h" int cmd640_vlb = 0; @@ -594,88 +595,10 @@ static struct pio_timing { { 50, 125, 383 }, /* PIO Mode 1 */ { 30, 100, 240 }, /* PIO Mode 2 */ { 30, 80, 180 }, /* PIO Mode 3 */ - { 25, 70, 125 }, /* PIO Mode 4 */ + { 25, 70, 125 }, /* PIO Mode 4 -- should be 120, not 125 */ { 20, 50, 100 } /* PIO Mode ? (nonstandard) */ }; -/* - * Black list. Some drives incorrectly report their maximal PIO modes, at least - * in respect to CMD640. Here we keep info on some known drives. - */ - -static struct drive_pio_info { - const char *name; - int pio; -} drive_pios[] = { -/* { "Conner Peripherals 1275MB - CFS1275A", 4 }, */ - - { "WDC AC2700", 3 }, - { "WDC AC2540", 3 }, - { "WDC AC2420", 3 }, - { "WDC AC2340", 3 }, - { "WDC AC2250", 0 }, - { "WDC AC2200", 0 }, - { "WDC AC2120", 0 }, - { "WDC AC2850", 3 }, - { "WDC AC1270", 3 }, - { "WDC AC1170", 3 }, - { "WDC AC1210", 1 }, - { "WDC AC280", 0 }, -/* { "WDC AC21000", 4 }, */ - { "WDC AC31000", 3 }, -/* { "WDC AC21200", 4 }, */ - { "WDC AC31200", 3 }, -/* { "WDC AC31600", 4 }, */ - - { "Maxtor 7131 AT", 1 }, - { "Maxtor 7171 AT", 1 }, - { "Maxtor 7213 AT", 1 }, - { "Maxtor 7245 AT", 1 }, - { "Maxtor 7345 AT", 1 }, - { "Maxtor 7546 AT", 3 }, - { "Maxtor 7540 AV", 3 }, - - { "SAMSUNG SHD-3121A", 1 }, - { "SAMSUNG SHD-3122A", 1 }, - { "SAMSUNG SHD-3172A", 1 }, - -/* { "ST51080A", 4 }, - * { "ST51270A", 4 }, - * { "ST31220A", 4 }, - * { "ST31640A", 4 }, - * { "ST32140A", 4 }, - * { "ST3780A", 4 }, - */ { "ST5660A", 3 }, - { "ST3660A", 3 }, - { "ST3630A", 3 }, - { "ST3655A", 3 }, - { "ST3391A", 3 }, - { "ST3390A", 1 }, - { "ST3600A", 1 }, - { "ST3290A", 0 }, - { "ST3144A", 0 }, - - { "QUANTUM ELS127A", 0 }, - { "QUANTUM ELS170A", 0 }, - { "QUANTUM LPS240A", 0 }, - { "QUANTUM LPS210A", 3 }, - { "QUANTUM LPS270A", 3 }, - { "QUANTUM LPS365A", 3 }, - { "QUANTUM LPS540A", 3 }, - { "QUANTUM FIREBALL", 3 }, /* For models 540/640/1080/1280 */ - { NULL, 0 } -}; - -static int known_drive_pio(char* name) { - struct drive_pio_info* pi; - - for (pi = drive_pios; pi->name != NULL; pi++) { - if (strmatch(pi->name, name) == 0) - return pi->pio; - } - return -1; -} - static void cmd640_timings_to_clocks(int mc_time, int av_time, int ds_time, int clock_time, int drv_idx) { @@ -764,7 +687,7 @@ static void cmd640_tune_drive(ide_drive_t *drive, byte pio_mode) { drive_number = drive->select.b.unit; clock_time = 1000/bus_speed; id = drive->id; - if ((max_pio = known_drive_pio(id->model)) != -1) { + if ((max_pio = ide_scan_pio_blacklist(id->model)) != -1) { ds_time = pio_timings[max_pio].ds_time; } else { max_pio = id->tPIO; diff --git a/drivers/block/dtc2278.c b/drivers/block/dtc2278.c index f291e570637b..2d18111083fb 100644 --- a/drivers/block/dtc2278.c +++ b/drivers/block/dtc2278.c @@ -1,5 +1,5 @@ /* - * linux/drivers/block/dtc2278.c Version 0.01 Feb 06, 1996 + * linux/drivers/block/dtc2278.c Version 0.02 Feb 10, 1996 * * Copyright (C) 1996 Linus Torvalds & author (see below) */ @@ -16,6 +16,12 @@ #include #include #include "ide.h" +#include "ide_modes.h" + +/* + * Changing this #undef to #define may solve start up problems in some systems. + */ +#undef ALWAYS_SET_DTC2278_PIO_MODE /* * From: andy@cercle.cts.com (Dyan Wile) @@ -27,9 +33,9 @@ * /dev/hd.. ) for the drives connected to the EIDE interface. (I get my * filesystem corrupted with -u1, but under heavy disk load only :-) * - * From: mlord@bnr.ca -- this chipset is now forced to use the "serialize" feature, - * which hopefully will make it more reliable to use.. maybe it has the same bugs - * as the CMD640B and RZ1000 ?? + * This chipset is now forced to use the "serialize" feature, + * and irq-unmasking is disallowed. If io_32bit is enabled, + * it must be done for BOTH drives on each interface. */ static void sub22 (char b, char c) @@ -50,24 +56,31 @@ static void sub22 (char b, char c) } } -static void tune_dtc2278 (ide_drive_t *drive, byte pio_mode) +static void tune_dtc2278 (ide_drive_t *drive, byte pio) { unsigned long flags; - if (pio_mode != 255) { /* auto-tune not yet supported here */ - if (pio_mode >= 3) { - save_flags(flags); - cli(); - /* - * This enables PIO mode4 (3?) on the first interface - */ - sub22(1,0xc3); - sub22(0,0xa0); - restore_flags(flags); - } else { - /* we don't know how to set it back again.. */ - } + if (pio == 255) + pio = ide_get_best_pio_mode(drive); + + if (pio >= 3) { + save_flags(flags); + cli(); + /* + * This enables PIO mode4 (3?) on the first interface + */ + sub22(1,0xc3); + sub22(0,0xa0); + restore_flags(flags); + } else { + /* we don't know how to set it back again.. */ } + + /* + * 32bit I/O has to be enabled for *both* drives at the same time. + */ + drive->io_32bit = 1; + HWIF(drive)->drives[!drive->select.b.unit].io_32bit = 1; } void init_dtc2278 (void) @@ -83,10 +96,20 @@ void init_dtc2278 (void) inb(0x3f6); outb_p(0x20,0xb4); inb(0x3f6); +#ifdef ALWAYS_SET_DTC2278_PIO_MODE + /* + * This enables PIO mode4 (3?) on the first interface + * and may solve start-up problems for some people. + */ + sub22(1,0xc3); + sub22(0,0xa0); +#endif restore_flags(flags); ide_hwifs[0].serialized = 1; ide_hwifs[0].chipset = ide_dtc2278; ide_hwifs[1].chipset = ide_dtc2278; ide_hwifs[0].tuneproc = &tune_dtc2278; + ide_hwifs[0].no_unmask = 1; + ide_hwifs[1].no_unmask = 1; } diff --git a/drivers/block/ht6560b.c b/drivers/block/ht6560b.c index a80abf532c42..022bbe810010 100644 --- a/drivers/block/ht6560b.c +++ b/drivers/block/ht6560b.c @@ -1,9 +1,55 @@ /* - * linux/drivers/block/ht6580.c Version 0.01 Feb 06, 1996 + * linux/drivers/block/ht6580.c Version 0.03 Feb 09, 1996 * * Copyright (C) 1995-1996 Linus Torvalds & author (see below) */ +/* + * + * Version 0.01 Initial version hacked out of ide.c + * + * Version 0.02 Added support for PIO modes, auto-tune + * + * Version 0.03 Some cleanups + * + * I reviewed some assembler sourcer listings of htide drivers and found + * out how they setup those cycle time interfacing values, as they at Holtek + * call them. IDESETUP.COM that is supplied with the drivers figures out + * optimal values and fetches those values to drivers. I found out that + * they use IDE_SELECT_REG to fetch timings to the ide board right after + * interface switching. After that it was quite easy to add code to + * ht6560b.c. + * + * IDESETUP.COM gave me values 0x24, 0x45, 0xaa, 0xff that worked fine + * for hda and hdc. But hdb needed higher values to work, so I guess + * that sometimes it is necessary to give higher value than IDESETUP + * gives. [see cmd640.c for an extreme example of this. -ml] + * + * Perhaps I should explain something about these timing values: + * The higher nibble of value is the Recovery Time (rt) and the lower nibble + * of the value is the Active Time (at). Minimum value 2 is the fastest and + * the maximum value 15 is the slowest. Default values should be 15 for both. + * So 0x24 means 2 for rt and 4 for at. Each of the drives should have + * both values, and IDESETUP gives automatically rt=15 st=15 for cdroms or + * similar. If value is too small there will be all sorts of failures. + * + * Port 0x3e6 bit 0x20 sets these timings on/off. If 0x20 bit is set + * these timings are disabled. + * + * Mikko Ala-Fossi + * + * More notes: + * + * There's something still missing from the initialization code, though. + * If I have booted to dos sometime after power on, I can get smaller + * timing values working. Perhaps I could soft-ice the initialization. + * + * OS/2 driver seems to use some kind of DMA. But that code is really + * messy to me to found out how. + * + * -=- malafoss@snakemail.hut.fi -=- searching the marvels of universe -=- + */ + #undef REALLY_SLOW_IO /* most systems can safely undef this */ #include @@ -16,6 +62,7 @@ #include #include #include "ide.h" +#include "ide_modes.h" /* * This routine handles interface switching for the peculiar hardware design @@ -30,34 +77,81 @@ * a read-modify-write sequence, so as not to disturb other bits in the reg? */ +/* + * The special i/o-port that HT-6560B uses to select interfaces: + */ +#define HT_SELECT_PORT 0x3e6 + /* * We don't know what all of the bits are for, but we *do* know about these: - * bit5 (0x20): "1" selects slower speed (?) + * bit5 (0x20): "1" selects slower speed by disabling use of timing values * bit0 (0x01): "1" selects second interface */ -static byte qd6560b_selects [2][MAX_DRIVES] = {{0x3c,0x3c}, {0x3d,0x3d}}; +static byte ht6560b_selects [2][MAX_DRIVES] = {{0x3c,0x3c}, {0x3d,0x3d}}; -static void qd6560b_selectproc (ide_drive_t *drive) /* called from ide.c */ +/* + * VLB ht6560b Timing values: + * + * Timing byte consists of + * High nibble: Recovery Time (rt) + * The valid values range from 2 to 15. The default is 15. + * + * Low nibble: Active Time (at) + * The valid values range from 2 to 15. The default is 15. + * + * You can obtain optimized timing values by running Holtek IDESETUP.COM + * for DOS. DOS drivers get their timing values from command line, where + * the first value is the Recovery Time and the second value is the + * Active Time for each drive. Smaller value gives higher speed. + * In case of failures you should probably fall back to a higher value. + * + * Hopefully this example will make it clearer: + * + * DOS: DEVICE=C:\bin\HTIDE\HTIDE.SYS /D0=2,4 /D1=4,5 /D2=10,10 /D3=15,15 + * Linux: byte ht6560b_timings [][] = {{0x24, 0x45}, {0xaa, 0xff}}; + * + * Note: There are no ioctls to change these values directly, + * but settings can be approximated as PIO modes, using "hdparm": + * + * rc.local: hdparm -p3 /dev/hda -p2 /dev/hdb -p1 /dev/hdc -p0 /dev/hdd + */ + +static byte ht6560b_timings [2][MAX_DRIVES] = {{0xff,0xff}, {0xff,0xff}}; + +static byte pio_to_timings[6] = {0xff, 0xaa, 0x45, 0x24, 0x13, 0x12}; + +/* + * This routine is invoked from ide.c to prepare for access to a given drive. + */ +static void ht6560b_selectproc (ide_drive_t *drive) { + byte t; + unsigned long flags; static byte current_select = 0; - byte drive_select = qd6560b_selects[HWIF(drive)->index][drive->select.b.unit]; + static byte current_timing = 0; + byte select = ht6560b_selects[HWIF(drive)->index][drive->select.b.unit]; + byte timing = ht6560b_timings[HWIF(drive)->index][drive->select.b.unit]; - if (drive_select != current_select) { - byte t; - unsigned long flags; + if (select != current_select || timing != current_timing) { + current_select = select; + current_timing = timing; save_flags (flags); cli(); - current_select = drive_select; - (void) inb(0x3e6); - (void) inb(0x3e6); - (void) inb(0x3e6); + (void) inb(HT_SELECT_PORT); + (void) inb(HT_SELECT_PORT); + (void) inb(HT_SELECT_PORT); /* * Note: input bits are reversed to output bits!! */ - t = inb(0x3e6) ^ 0x3f; + t = inb(HT_SELECT_PORT) ^ 0x3f; t &= (~0x21); t |= (current_select & 0x21); - outb(t,0x3e6); + outb(t, HT_SELECT_PORT); + /* + * Set timing for this drive: + */ + outb (timing, IDE_SELECT_REG); + (void) inb (IDE_STATUS_REG); restore_flags (flags); } } @@ -71,28 +165,29 @@ int try_to_init_ht6560b(void) int i; /* Autodetect ht6560b */ - if ((orig_value=inb(0x3e6)) == 0xff) + if ((orig_value=inb(HT_SELECT_PORT)) == 0xff) return 0; for (i=3;i>0;i--) { - outb(0x00,0x3e6); - if (!( (~inb(0x3e6)) & 0x3f )) { - outb(orig_value,0x3e6); + outb(0x00, HT_SELECT_PORT); + if (!( (~inb(HT_SELECT_PORT)) & 0x3f )) { + outb(orig_value, HT_SELECT_PORT); return 0; } } - outb(0x00,0x3e6); - if ((~inb(0x3e6))& 0x3f) { - outb(orig_value,0x3e6); + outb(0x00, HT_SELECT_PORT); + if ((~inb(HT_SELECT_PORT))& 0x3f) { + outb(orig_value, HT_SELECT_PORT); return 0; } - /* + /* * Ht6560b autodetected: * reverse input bits to output bits * initialize bit1 to 0 */ - outb((orig_value ^ 0x3f) & 0xfd,0x3e6); - printk("ht6560b: detected and initialized\n"); + outb((orig_value ^ 0x3f) & 0xfd, HT_SELECT_PORT); + + printk("\nht6560b: detected and initialized"); return 1; } @@ -101,37 +196,37 @@ static void tune_ht6560b (ide_drive_t *drive, byte pio) unsigned int hwif, unit; if (pio == 255) { /* auto-tune */ - if (drive->media != ide_disk) { - pio = 0; /* cdroms don't like our fast mode */ - } else { - struct hd_driveid *id = drive->id; - pio = id->tPIO; - if ((id->field_valid & 0x02) && (id->eide_pio_modes & 0x01)) - pio = 3; - } + if (drive->media != ide_disk) + pio = 0; /* some cdroms don't like fast modes (?) */ + else + pio = ide_get_best_pio_mode (drive); } - hwif = HWIF(drive)->index; + if (pio > 5) + pio = 5; unit = drive->select.b.unit; - if (pio < 3) - qd6560b_selects[hwif][unit] |= 0x20; + hwif = HWIF(drive)->index; + ht6560b_timings[hwif][unit] = pio_to_timings[pio]; + if (pio == 0) + ht6560b_selects[hwif][unit] |= 0x20; else - qd6560b_selects[hwif][unit] &= ~0x20; + ht6560b_selects[hwif][unit] &= ~0x20; } void init_ht6560b (void) { - if (check_region(0x3e6,1)) { + if (check_region(HT_SELECT_PORT,1)) { printk("\nht6560b: PORT 0x3e6 ALREADY IN USE\n"); } else { if (try_to_init_ht6560b()) { - request_region(0x3e6, 1, "ht6560b"); + request_region(HT_SELECT_PORT, 1, ide_hwifs[0].name); ide_hwifs[0].chipset = ide_ht6560b; ide_hwifs[1].chipset = ide_ht6560b; - ide_hwifs[0].selectproc = &qd6560b_selectproc; - ide_hwifs[1].selectproc = &qd6560b_selectproc; + ide_hwifs[0].selectproc = &ht6560b_selectproc; + ide_hwifs[1].selectproc = &ht6560b_selectproc; ide_hwifs[0].tuneproc = &tune_ht6560b; ide_hwifs[1].tuneproc = &tune_ht6560b; ide_hwifs[0].serialized = 1; - } + } else + printk("ht6560b: not found\n"); } } diff --git a/drivers/block/ide-cd.c b/drivers/block/ide-cd.c index 232dbd663204..d9378233ed1b 100644 --- a/drivers/block/ide-cd.c +++ b/drivers/block/ide-cd.c @@ -84,6 +84,8 @@ * Add NO_DOOR_LOCKING configuration option. * Handle drive_cmd requests w/NULL args (for hdparm -t). * Work around sporadic Sony55e audio play problem. + * 3.07a Feb 11, 1996 -- check drive->id for NULL before dereferencing, to fix + * problem with "hde=cdrom" with no drive present. -ml * * NOTE: Direct audio reads will only work on some types of drive. * So far, i've received reports of success for Sony and Toshiba drives. @@ -2664,8 +2666,12 @@ void ide_cdrom_setup (ide_drive_t *drive) CDROM_CONFIG_FLAGS (drive)->no_doorlock = 0; #endif - CDROM_CONFIG_FLAGS (drive)->drq_interrupt = - ((drive->id->config & 0x0060) == 0x20); + if (drive->id != NULL) { + CDROM_CONFIG_FLAGS (drive)->drq_interrupt = + ((drive->id->config & 0x0060) == 0x20); + } else { + CDROM_CONFIG_FLAGS (drive)->drq_interrupt = 0; + } #if ! STANDARD_ATAPI CDROM_CONFIG_FLAGS (drive)->no_playaudio12 = 0; @@ -2674,52 +2680,54 @@ void ide_cdrom_setup (ide_drive_t *drive) CDROM_CONFIG_FLAGS (drive)->playmsf_uses_bcd = 0; CDROM_CONFIG_FLAGS (drive)->vertos_lossage = 0; - /* Accommodate some broken drives... */ - if (strcmp (drive->id->model, "CD220E") == 0 || - strcmp (drive->id->model, "CD") == 0) /* Creative Labs */ - CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1; - - else if (strcmp (drive->id->model, "TO-ICSLYAL") == 0 || /* Acer CD525E */ - strcmp (drive->id->model, "OTI-SCYLLA") == 0) - CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1; + if (drive->id != NULL) { + /* Accommodate some broken drives... */ + if (strcmp (drive->id->model, "CD220E") == 0 || + strcmp (drive->id->model, "CD") == 0) /* Creative Labs */ + CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1; - /* I don't know who makes this. - Francesco Messineo says this one's broken too. */ - else if (strcmp (drive->id->model, "DCI-2S10") == 0) - CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1; + else if (strcmp (drive->id->model, "TO-ICSLYAL") == 0 || /* Acer CD525E */ + strcmp (drive->id->model, "OTI-SCYLLA") == 0) + CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1; - else if (strcmp (drive->id->model, "CDA26803I SE") == 0) /* Aztech */ - { + /* I don't know who makes this. + Francesco Messineo says this one's broken too. */ + else if (strcmp (drive->id->model, "DCI-2S10") == 0) CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1; - /* This drive _also_ does not implement PLAYAUDIO12 correctly. */ - CDROM_CONFIG_FLAGS (drive)->no_playaudio12 = 1; - } + else if (strcmp (drive->id->model, "CDA26803I SE") == 0) /* Aztech */ + { + CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1; - /* Vertos 300. - There seem to be at least two different, incompatible versions - of this drive floating around. Luckily, they appear to return their - id strings with different byte orderings. */ - else if (strcmp (drive->id->model, "V003S0DS") == 0) - { - CDROM_CONFIG_FLAGS (drive)->vertos_lossage = 1; - CDROM_CONFIG_FLAGS (drive)->playmsf_uses_bcd = 1; + /* This drive _also_ does not implement PLAYAUDIO12 correctly. */ + CDROM_CONFIG_FLAGS (drive)->no_playaudio12 = 1; + } + + /* Vertos 300. + There seem to be at least two different, incompatible versions + of this drive floating around. Luckily, they appear to return their + id strings with different byte orderings. */ + else if (strcmp (drive->id->model, "V003S0DS") == 0) + { + CDROM_CONFIG_FLAGS (drive)->vertos_lossage = 1; + CDROM_CONFIG_FLAGS (drive)->playmsf_uses_bcd = 1; + CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1; + } + else if (strcmp (drive->id->model, "0V300SSD") == 0 || + strcmp (drive->id->model, "V003M0DP") == 0) CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1; - } - else if (strcmp (drive->id->model, "0V300SSD") == 0 || - strcmp (drive->id->model, "V003M0DP") == 0) - CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1; - /* Vertos 400. */ - else if (strcmp (drive->id->model, "V004E0DT") == 0 || - strcmp (drive->id->model, "0V400ETD") == 0) - CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1; + /* Vertos 400. */ + else if (strcmp (drive->id->model, "V004E0DT") == 0 || + strcmp (drive->id->model, "0V400ETD") == 0) + CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1; - else if ( strcmp (drive->id->model, "CD-ROM CDU55D") == 0) /*sony cdu55d */ - CDROM_CONFIG_FLAGS (drive)->no_playaudio12 = 1; + else if ( strcmp (drive->id->model, "CD-ROM CDU55D") == 0) /*sony cdu55d */ + CDROM_CONFIG_FLAGS (drive)->no_playaudio12 = 1; - else if (strcmp (drive->id->model, "CD-ROM CDU55E") == 0) - CDROM_CONFIG_FLAGS (drive)->no_playaudio12 = 1; + else if (strcmp (drive->id->model, "CD-ROM CDU55E") == 0) + CDROM_CONFIG_FLAGS (drive)->no_playaudio12 = 1; + } /* drive-id != NULL */ #endif /* not STANDARD_ATAPI */ drive->cdrom_info.toc = NULL; diff --git a/drivers/block/ide-tape.c b/drivers/block/ide-tape.c index 8b36dce83611..f9bb3ddab792 100644 --- a/drivers/block/ide-tape.c +++ b/drivers/block/ide-tape.c @@ -1,5 +1,5 @@ /* - * linux/drivers/block/ide-tape.c Version 1.2 - ALPHA Jan 1, 1996 + * linux/drivers/block/ide-tape.c Version 1.3 - ALPHA Feb 9, 1996 * * Copyright (C) 1995, 1996 Gadi Oxman * @@ -53,6 +53,8 @@ * integral number of the tape's recommended data transfer unit * (which is shown on initialization and can be received with * an ioctl). + * As of version 1.3 of the driver, this is no longer as critical + * as it used to be. * 3. No buffering is performed by the user backup program. * * Testing was done with a 2 GB CONNER CTMA 4000 IDE ATAPI Streaming Tape Drive. @@ -161,6 +163,23 @@ * The recommended user block size is returned by * the MTIOCGET ioctl. * Additional minor changes. + * Ver 1.3 Feb 9 96 Fixed pipelined read mode bug which prevented the + * use of some block sizes during a restore procedure. + * The character device interface will now present a + * continuous view of the media - any mix of block sizes + * during a backup/restore procedure is supported. The + * driver will buffer the requests internally and + * convert them to the tape's recommended transfer + * unit, making performance almost independent of the + * chosen user block size. + * Some improvements in error recovery. + * By cooperating with triton.c, bus mastering DMA can + * now sometimes be used with IDE tape drives as well. + * Bus mastering DMA has the potential to dramatically + * reduce the CPU's overhead when accessing the device, + * and can be enabled by using hdparm -d1 on the tape's + * block device interface. For more info, read the + * comments in triton.c. * * We are currently in an *alpha* stage. The driver is not complete and not * much tested. I would strongly suggest to: @@ -279,6 +298,7 @@ * sharing a (fast) ATA-2 disk with any (slow) new ATAPI device. */ +#include #include #include #include @@ -351,11 +371,6 @@ * device interface. */ -#define IDETAPE_INQUIRY_IOCTL 0x0341 -#define IDETAPE_LOCATE_IOCTL 0x0342 - -#define IDETAPE_RESET_IOCTL 0x0350 - /* * Special requests for our block device strategy routine. * @@ -663,13 +678,22 @@ typedef struct { typedef struct { unsigned error_code :7; /* Current of deferred errors */ unsigned valid :1; /* The information field conforms to QIC-157C */ - byte reserved_1; /* Segment Number - Reserved */ + unsigned reserved_1 :8; /* Segment Number - Reserved */ unsigned sense_key :4; /* Sense Key */ unsigned reserved2_4 :1; /* Reserved */ unsigned ili :1; /* Incorrect Length Indicator */ unsigned eom :1; /* End Of Medium */ - unsigned filemark :1; /* Filemark */ - unsigned long information; /* Information - Command specific */ + unsigned filemark :1; /* Filemark */ + + /* + * We can't use a 32 bit variable, since it will be re-aligned + * by GCC, as we are not on a 32 bit boundary. + */ + + byte information1; /* MSB - Information - Command specific */ + byte information2; + byte information3; + byte information4; /* LSB */ byte asl; /* Additional sense length (n-7) */ unsigned long command_specific; /* Additional command specific information */ byte asc; /* Additional Sense Code */ @@ -679,6 +703,7 @@ typedef struct { unsigned sksv :1; /* Sense Key Specific informatio is valid */ byte sk_specific2; /* Sense Key Specific */ byte sk_specific3; /* Sense Key Specific */ + byte pad [2]; /* Padding to 20 bytes */ } idetape_request_sense_result_t; /* @@ -816,13 +841,6 @@ void idetape_analyze_error (ide_drive_t *drive,idetape_request_sense_result_t *r idetape_packet_command_t *idetape_next_pc_storage (ide_drive_t *drive); struct request *idetape_next_rq_storage (ide_drive_t *drive); -/* - * idetape_end_request is used to finish servicing a request, and to - * insert a pending pipeline request into the main device queue. - */ - -void idetape_end_request (byte uptodate, ide_hwgroup_t *hwgroup); - /* * Various packet commands */ @@ -857,9 +875,7 @@ void idetape_display_inquiry_result (byte *buffer); */ int idetape_chrdev_read (struct inode *inode, struct file *file, char *buf, int count); -int idetape_chrdev_read_remainder (struct inode *inode, struct file *file, char *buf, int count); int idetape_chrdev_write (struct inode *inode, struct file *file, const char *buf, int count); -int idetape_chrdev_write_remainder (struct inode *inode, struct file *file, const char *buf, int count); int idetape_chrdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); int idetape_chrdev_open (struct inode *inode, struct file *file); void idetape_chrdev_release (struct inode *inode,struct file *file); @@ -927,6 +943,8 @@ void idetape_get_mode_sense_results (ide_drive_t *drive); unsigned long idetape_swap_long (unsigned long temp); unsigned short idetape_swap_short (unsigned short temp); +#define IDETAPE_MIN(a,b) ((a)<(b) ? (a):(b)) + /* * Pipeline related functions */ @@ -939,7 +957,8 @@ void idetape_increase_max_pipeline_stages (ide_drive_t *drive); void idetape_add_stage_tail (ide_drive_t *drive,idetape_pipeline_stage_t *stage); void idetape_remove_stage_head (ide_drive_t *drive); void idetape_active_next_stage (ide_drive_t *drive); -void idetape_empty_read_pipeline (ide_drive_t *drive); +void idetape_wait_for_pipeline (ide_drive_t *drive); +void idetape_discard_read_pipeline (ide_drive_t *drive); void idetape_empty_write_pipeline (ide_drive_t *drive); void idetape_insert_pipeline_into_queue (ide_drive_t *drive); @@ -1223,6 +1242,7 @@ void idetape_setup (ide_drive_t *drive) tape->error_in_pipeline_stage=0; tape->request_status=0; tape->chrdev_direction=idetape_direction_none; + tape->reset_issued=0; #if IDETAPE_PIPELINE tape->max_number_of_stages=IDETAPE_MIN_PIPELINE_STAGES; @@ -1240,16 +1260,22 @@ void idetape_setup (ide_drive_t *drive) if (tape->data_buffer_size % IDETAPE_ALLOCATION_BLOCK) allocation_length+=IDETAPE_ALLOCATION_BLOCK; +#if IDETAPE_MINIMIZE_IDLE_MEMORY_USAGE + tape->data_buffer=tape->merge_buffer=NULL; +#else tape->data_buffer=kmalloc (allocation_length,GFP_KERNEL); - tape->temp_data_buffer=kmalloc (allocation_length,GFP_KERNEL); - if (tape->data_buffer == NULL || tape->temp_data_buffer == NULL) { + tape->merge_buffer=kmalloc (allocation_length,GFP_KERNEL); + if (tape->data_buffer == NULL || tape->merge_buffer == NULL) { printk ("ide-tape: FATAL - Can not allocate 2 buffers of %d bytes each\n",allocation_length); printk ("ide-tape: Aborting character device installation\n"); idetape_drive_already_found=0; unregister_chrdev (idetape_chrdev.major,idetape_chrdev.name); return; } +#endif /* IDETAPE_MINIMIZE_IDLE_MEMORY_USAGE */ + tape->merge_buffer_size=tape->merge_buffer_offset=0; + #if IDETAPE_ANTICIPATE_READ_WRITE_DSC /* @@ -1428,13 +1454,14 @@ void idetape_issue_packet_command (ide_drive_t *drive,idetape_packet_command_t { idetape_tape_t *tape; idetape_bcount_reg_t bcount; - idetape_ireason_reg_t ireason; + idetape_ireason_reg_t ireason; + int dma_ok=0; tape=&(drive->tape); #if IDETAPE_DEBUG_BUGS if (tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD && pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) { - printk ("ide-tape: ide-tape.c bug - Two request sense in serial were issued\n"); + printk ("ide-tape: possible ide-tape.c bug - Two request sense in serial were issued\n"); } #endif /* IDETAPE_DEBUG_BUGS */ @@ -1447,7 +1474,8 @@ void idetape_issue_packet_command (ide_drive_t *drive,idetape_packet_command_t /* * We will "abort" retrying a packet command in case * a legitimate error code was received (crossing a - * filemark, for example). We will not log those errors. + * filemark, or DMA error in the end of media, for + * example). */ if (!pc->abort) { @@ -1478,10 +1506,21 @@ void idetape_issue_packet_command (ide_drive_t *drive,idetape_packet_command_t */ pc->actually_transferred=0; /* We haven't transferred any data yet */ + pc->current_position=pc->buffer; bcount.all=pc->request_transfer; /* Request to transfer the entire buffer at once */ - /* Initialize the task file registers */ - OUT_BYTE (0,IDETAPE_FEATURES_REG); /* Use PIO data transger, No DMA */ +#ifdef CONFIG_BLK_DEV_TRITON + if (pc->dma_error) { + printk ("ide-tape: DMA disabled, reverting to PIO\n"); + drive->using_dma=0; + pc->dma_error=0; + } + if (pc->request_transfer && pc->dma_recommended && drive->using_dma) { + dma_ok=!(HWIF(drive)->dmaproc(pc->writing ? ide_dma_write : ide_dma_read, drive)); + } +#endif /* CONFIG_BLK_DEV_TRITON */ + + OUT_BYTE (dma_ok ? 1:0,IDETAPE_FEATURES_REG); /* Use PIO/DMA */ OUT_BYTE (bcount.b.high,IDETAPE_BCOUNTH_REG); OUT_BYTE (bcount.b.low,IDETAPE_BCOUNTL_REG); OUT_BYTE (drive->select.all,IDETAPE_DRIVESEL_REG); @@ -1498,17 +1537,24 @@ void idetape_issue_packet_command (ide_drive_t *drive,idetape_packet_command_t * here anyway. */ - printk ("ide-tape: Strange, packet command initiated yet DRQ isn't asserted\n"); - return; + printk ("ide-tape: Strange, packet command initiated yet DRQ isn't asserted\n"); + return; } ireason.all=IN_BYTE (IDETAPE_IREASON_REG); if (!ireason.b.cod || ireason.b.io) { printk ("ide-tape: (IO,CoD) != (0,1) while issuing a packet command\n"); - /* ??? */ + ide_do_reset (drive); + return; } ide_output_data (drive,pc->c,12/4); /* Send the actual packet */ +#ifdef CONFIG_BLK_DEV_TRITON + if ((pc->dma_in_progress=dma_ok)) { /* Begin DMA, if necessary */ + pc->dma_error=0; + (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive)); + } +#endif /* CONFIG_BLK_DEV_TRITON */ } /* @@ -1527,10 +1573,27 @@ void idetape_pc_intr (ide_drive_t *drive) idetape_tape_t *tape=&(drive->tape); idetape_status_reg_t status; idetape_bcount_reg_t bcount; - idetape_ireason_reg_t ireason; + idetape_ireason_reg_t ireason; idetape_packet_command_t *pc=tape->pc; unsigned long temp; +#ifdef CONFIG_BLK_DEV_TRITON + if (pc->dma_in_progress) { + if ((pc->dma_error=HWIF(drive)->dmaproc(ide_dma_status_bad, drive))) + /* + * We will currently correct the following in + * idetape_analyze_error. + */ + pc->actually_transferred=HWIF(drive)->dmaproc(ide_dma_transferred, drive); + else + pc->actually_transferred=pc->request_transfer; + (void) (HWIF(drive)->dmaproc(ide_dma_abort, drive)); /* End DMA */ +#if IDETAPE_DEBUG_LOG + printk ("ide-tape: DMA finished\n"); +#endif /* IDETAPE_DEBUG_LOG */ + } +#endif /* CONFIG_BLK_DEV_TRITON */ + status.all=IN_BYTE (IDETAPE_STATUS_REG); /* Clear the interrupt */ #if IDETAPE_DEBUG_LOG @@ -1542,10 +1605,11 @@ void idetape_pc_intr (ide_drive_t *drive) printk ("Packet command completed\n"); printk ("Total bytes transferred: %lu\n",pc->actually_transferred); #endif /* IDETAPE_DEBUG_LOG */ - + pc->dma_in_progress=0; + sti (); - if (status.b.check) { /* Error detected */ + if (status.b.check || pc->dma_error) { /* Error detected */ #if IDETAPE_DEBUG_LOG /* * Without debugging, we only log an error if we decided to @@ -1553,6 +1617,12 @@ void idetape_pc_intr (ide_drive_t *drive) */ printk ("ide-tape: %s: I/O error, ",drive->name); #endif /* IDETAPE_DEBUG_LOG */ + if (pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) { + printk ("ide-tape: I/O error in request sense command\n"); + ide_do_reset (drive); + return; + } + idetape_retry_pc (drive); /* Retry operation */ return; } @@ -1572,19 +1642,30 @@ void idetape_pc_intr (ide_drive_t *drive) (*pc->callback)(drive); /* Command finished - Call the callback function */ return; } - +#ifdef CONFIG_BLK_DEV_TRITON + if (pc->dma_in_progress) { + pc->dma_in_progress=0; + printk ("ide-tape: The tape wants to issue more interrupts in DMA mode\n"); + printk ("ide-tape: DMA disabled, reverting to PIO\n"); + drive->using_dma=0; + ide_do_reset (drive); + return; + } +#endif /* CONFIG_BLK_DEV_TRITON */ bcount.b.high=IN_BYTE (IDETAPE_BCOUNTH_REG); /* Get the number of bytes to transfer */ bcount.b.low=IN_BYTE (IDETAPE_BCOUNTL_REG); /* on this interrupt */ ireason.all=IN_BYTE (IDETAPE_IREASON_REG); /* Read the interrupt reason register */ if (ireason.b.cod) { printk ("ide-tape: CoD != 0 in idetape_pc_intr\n"); - /* ??? */ + ide_do_reset (drive); + return; } if (ireason.b.io != !(pc->writing)) { /* Hopefully, we will never get here */ printk ("ide-tape: We wanted to %s, ",pc->writing ? "Write":"Read"); printk ("but the tape wants us to %s !\n",ireason.b.io ? "Read":"Write"); - /* ??? */ + ide_do_reset (drive); + return; } if (!pc->writing) { /* Reading - Check that we have enough space */ @@ -2058,24 +2139,19 @@ void idetape_pc_callback (ide_drive_t *drive) void idetape_read_callback (ide_drive_t *drive) { - idetape_tape_t *tape; - struct request *rq; + idetape_tape_t *tape=&(drive->tape); + struct request *rq=HWGROUP(drive)->rq; + int blocks_read=tape->pc->actually_transferred/tape->tape_block_size; - tape=&(drive->tape); - rq=HWGROUP(drive)->rq; #if IDETAPE_DEBUG_LOG printk ("ide-tape: Reached idetape_read_callback\n"); #endif /* IDETAPE_DEBUG_LOG */ - tape->block_address+=tape->pc->actually_transferred/tape->tape_block_size; - if (!tape->pc->error) { -#if IDETAPE_DEBUG_LOG - printk ("Request completed\n"); -#endif /* IDETAPE_DEBUG_LOG */ - rq->sector+=rq->current_nr_sectors; - rq->nr_sectors-=rq->current_nr_sectors; - rq->current_nr_sectors=0; + + tape->block_address+=blocks_read; + rq->current_nr_sectors-=blocks_read; + + if (!tape->pc->error) idetape_end_request (1,HWGROUP (drive)); - } else { rq->errors=tape->pc->error; switch (rq->errors) { @@ -2091,25 +2167,21 @@ void idetape_read_callback (ide_drive_t *drive) void idetape_write_callback (ide_drive_t *drive) { - idetape_tape_t *tape; - struct request *rq; - - tape=&(drive->tape); - rq=HWGROUP(drive)->rq; + idetape_tape_t *tape=&(drive->tape); + struct request *rq=HWGROUP(drive)->rq; + int blocks_written=tape->pc->actually_transferred/tape->tape_block_size; + #if IDETAPE_DEBUG_LOG printk ("ide-tape: Reached idetape_write_callback\n"); #endif /* IDETAPE_DEBUG_LOG */ - tape->block_address+=tape->pc->actually_transferred/tape->tape_block_size; - if (!tape->pc->error) { -#if IDETAPE_DEBUG_LOG - printk ("Request completed\n"); -#endif /* IDETAPE_DEBUG_LOG */ - rq->sector+=rq->current_nr_sectors; - rq->nr_sectors-=rq->current_nr_sectors; - rq->current_nr_sectors=0; + + tape->block_address+=blocks_written; + rq->current_nr_sectors-=blocks_written; + + if (!tape->pc->error) idetape_end_request (1,HWGROUP (drive)); - } else { + rq->errors=tape->pc->error; idetape_end_request (0,HWGROUP (drive)); } return; @@ -2200,7 +2272,7 @@ void idetape_create_inquiry_cmd (idetape_packet_command_t *pc) pc->callback=&idetape_inquiry_callback; pc->writing=0; - idetape_zero_packet_command (pc); + idetape_zero_packet_command (pc); pc->c[0]=IDETAPE_INQUIRY_CMD; pc->c[4]=255; } @@ -2355,14 +2427,29 @@ void idetape_analyze_error (ide_drive_t *drive,idetape_request_sense_result_t *r if (result->filemark) { pc->error=IDETAPE_RQ_ERROR_FILEMARK; pc->abort=1; - return; } + } + + if (pc->c[0] == IDETAPE_READ_CMD || pc->c[0] == IDETAPE_WRITE_CMD) { if (result->sense_key == 8) { pc->error=IDETAPE_RQ_ERROR_EOD; pc->abort=1; - return; } } + +#if 1 +#ifdef CONFIG_BLK_DEV_TRITON + + /* + * Correct pc->actually_transferred by asking the tape. + */ + + if (pc->dma_error && pc->abort) { + unsigned long *long_ptr=(unsigned long *) &(result->information1); + pc->actually_transferred=pc->request_transfer-tape->tape_block_size*idetape_swap_long (*long_ptr); + } +#endif /* CONFIG_BLK_DEV_TRITON */ +#endif } void idetape_create_test_unit_ready_cmd (idetape_packet_command_t *pc) @@ -2546,12 +2633,16 @@ void idetape_create_read_cmd (idetape_packet_command_t *pc,unsigned long length) pc->writing=0; idetape_zero_packet_command (pc); + pc->c [0]=IDETAPE_READ_CMD; pc->c [1]=1; pc->c [4]=original.b.b1; pc->c [3]=original.b.b2; pc->c [2]=original.b.b3; + if (length) + pc->dma_recommended=1; + return; } @@ -2616,12 +2707,16 @@ void idetape_create_write_cmd (idetape_packet_command_t *pc,unsigned long length pc->writing=1; idetape_zero_packet_command (pc); + pc->c [0]=IDETAPE_WRITE_CMD; pc->c [1]=1; pc->c [4]=original.b.b1; pc->c [3]=original.b.b2; pc->c [2]=original.b.b3; + if (length) + pc->dma_recommended=1; + return; } @@ -2699,7 +2794,6 @@ int idetape_blkdev_ioctl (ide_drive_t *drive, struct inode *inode, struct file * unsigned int cmd, unsigned long arg) { idetape_packet_command_t pc; - int retval; pc.buffer=pc.temp_buffer; pc.buffer_size=IDETAPE_TEMP_BUFFER_SIZE; @@ -2709,33 +2803,6 @@ int idetape_blkdev_ioctl (ide_drive_t *drive, struct inode *inode, struct file * printk ("ide-tape: Reached idetape_blkdev_ioctl\n"); #endif /* IDETAPE_DEBUG_LOG */ switch (cmd) { - case IDETAPE_INQUIRY_IOCTL: -#if IDETAPE_DEBUG_LOG - printk ("Adding INQUIRY packet command to the tail of the request queue\n"); -#endif /* IDETAPE_DEBUG_LOG */ - idetape_create_inquiry_cmd (&pc); - pc.buffer=pc.temp_buffer; - pc.buffer_size=IDETAPE_TEMP_BUFFER_SIZE; - pc.current_position=pc.temp_buffer; - return (idetape_queue_pc_tail (drive,&pc)); - case IDETAPE_LOCATE_IOCTL: -#if IDETAPE_DEBUG_LOG - printk ("Adding LOCATE packet command to the tail of the request queue\n"); -#endif /* IDETAPE_DEBUG_LOG */ - idetape_create_locate_cmd (&pc,arg,0); - retval=idetape_queue_pc_tail (drive,&pc); - if (retval!=0) return (retval); - - idetape_create_read_position_cmd (&pc); - pc.buffer=pc.temp_buffer; - pc.buffer_size=IDETAPE_TEMP_BUFFER_SIZE; - pc.current_position=pc.temp_buffer; - return (idetape_queue_pc_tail (drive,&pc)); -/* - case IDETAPE_RESET_IOCTL: - printk ("Resetting drive\n"); - return (!ide_do_reset (drive)); -*/ default: return -EIO; } @@ -2757,6 +2824,7 @@ void idetape_end_request (byte uptodate, ide_hwgroup_t *hwgroup) idetape_tape_t *tape = &(drive->tape); unsigned int major = HWIF(drive)->major; struct blk_dev_struct *bdev = &blk_dev[major]; + int error; #if IDETAPE_DEBUG_LOG printk ("Reached idetape_end_request\n"); @@ -2766,7 +2834,8 @@ void idetape_end_request (byte uptodate, ide_hwgroup_t *hwgroup) if (!rq->errors) /* In case rq->errors is already set, */ rq->errors=!uptodate; /* we won't change it. */ - + error=rq->errors; + if (tape->active_data_request == rq) { /* The request was a pipelined data transfer request */ if (rq->cmd == IDETAPE_READ_REQUEST) { @@ -2783,12 +2852,13 @@ void idetape_end_request (byte uptodate, ide_hwgroup_t *hwgroup) if (rq->cmd == IDETAPE_WRITE_REQUEST) { if (rq->errors) - tape->error_in_pipeline_stage=1; + tape->error_in_pipeline_stage=rq->errors; idetape_remove_stage_head (drive); } if (tape->next_stage == NULL) { - idetape_increase_max_pipeline_stages (drive); + if (!error) + idetape_increase_max_pipeline_stages (drive); ide_end_drive_cmd (drive, 0, 0); return; } @@ -2904,10 +2974,22 @@ void idetape_do_request (ide_drive_t *drive, struct request *rq, unsigned long b tape->postponed_rq = NULL; } + + status.all=IN_BYTE (IDETAPE_STATUS_REG); + + /* + * After a software reset, the status register is locked. We + * will ignore the DSC value for our very first packet command, + * which will restore DSC operation. + */ + + if (tape->reset_issued) { + status.b.dsc=1; + tape->reset_issued=0; + } switch (rq->cmd) { case IDETAPE_READ_REQUEST: - status.all=IN_BYTE (IDETAPE_STATUS_REG); if (!status.b.dsc) { /* Tape buffer not ready to accept r/w command */ #if IDETAPE_DEBUG_LOG printk ("ide-tape: DSC != 1 - Postponing read request\n"); @@ -2930,7 +3012,6 @@ void idetape_do_request (ide_drive_t *drive, struct request *rq, unsigned long b return; case IDETAPE_WRITE_REQUEST: - status.all=IN_BYTE (IDETAPE_STATUS_REG); if (!status.b.dsc) { /* Tape buffer not ready to accept r/w command */ #if IDETAPE_DEBUG_LOG printk ("ide-tape: DSC != 1 - Postponing write request\n"); @@ -2959,7 +3040,6 @@ void idetape_do_request (ide_drive_t *drive, struct request *rq, unsigned long b * but I have occasionally missed DSC on a media access command otherwise. * ??? Still have to figure it out ... */ - status.all=IN_BYTE (IDETAPE_STATUS_REG); if (!status.b.dsc) { /* Tape buffers are still not ready */ #if IDETAPE_DEBUG_LOG printk ("ide-tape: DSC != 1 - Postponing packet command request\n"); @@ -3072,13 +3152,8 @@ void idetape_wait_for_request (struct request *rq) } /* - * idetape_queue_rw_tail is typically called from the character device - * interface to generate a read/write request for the block device interface - * and wait for it to be serviced. Note that cmd will be different than - * a buffer cache originated read/write request. This will be used - * in idetape_end_request. - * - * Returns 0 on success or -EIO if an error occured. + * idetape_queue_rw_tail generates a read/write request for the block + * device interface and wait for it to be serviced. */ int idetape_queue_rw_tail (ide_drive_t *drive,int cmd,int blocks,char *buffer) @@ -3090,16 +3165,21 @@ int idetape_queue_rw_tail (ide_drive_t *drive,int cmd,int blocks,char *buffer) #if IDETAPE_DEBUG_LOG printk ("idetape_queue_rw_tail: cmd=%d\n",cmd); #endif /* IDETAPE_DEBUG_LOG */ - /* build up a special read request, and add it to the queue */ - +#if IDETAPE_DEBUG_BUGS + if (tape->active_data_request != NULL) { + printk ("ide-tape: bug: the pipeline is active in idetape_queue_rw_tail\n"); + return (0); + } +#endif /* IDETAPE_DEBUG_BUGS */ + ide_init_drive_cmd (&rq); rq.buffer = buffer; rq.cmd = cmd; rq.sector = tape->block_address; - rq.nr_sectors = blocks; - rq.current_nr_sectors = blocks; - tape->active_data_request=NULL; /* Non-pipelined mode */ - return ide_do_drive_cmd (drive, &rq, ide_wait); + rq.nr_sectors = rq.current_nr_sectors = blocks; + (void) ide_do_drive_cmd (drive, &rq, ide_wait); + + return (tape->tape_block_size*(blocks-rq.current_nr_sectors)); } /* @@ -3113,8 +3193,8 @@ int idetape_add_chrdev_read_request (ide_drive_t *drive,int blocks,char *buffer) idetape_tape_t *tape = &(drive->tape); idetape_pipeline_stage_t *new_stage; unsigned long flags; - struct request rq; - int errors; + struct request rq,*rq_ptr; + int bytes_read; #if IDETAPE_DEBUG_LOG printk ("Reached idetape_add_chrdev_read_request\n"); @@ -3123,8 +3203,7 @@ int idetape_add_chrdev_read_request (ide_drive_t *drive,int blocks,char *buffer) ide_init_drive_cmd (&rq); rq.cmd = IDETAPE_READ_REQUEST; rq.sector = tape->block_address; - rq.nr_sectors = blocks; - rq.current_nr_sectors = blocks; + rq.nr_sectors = rq.current_nr_sectors = blocks; if (tape->current_number_of_stages < 0.5*tape->max_number_of_stages) { new_stage=idetape_kmalloc_stage (drive); @@ -3154,12 +3233,19 @@ int idetape_add_chrdev_read_request (ide_drive_t *drive,int blocks,char *buffer) idetape_wait_for_request (tape->active_data_request); restore_flags (flags); - errors=tape->first_stage->rq.errors; - if (!errors) - idetape_copy_buffer_from_stage (tape->first_stage,buffer); - - idetape_remove_stage_head (drive); - return (errors ? -EIO:0); + rq_ptr=&(tape->first_stage->rq); + bytes_read=tape->tape_block_size*(rq_ptr->nr_sectors-rq_ptr->current_nr_sectors); + rq_ptr->nr_sectors=rq_ptr->current_nr_sectors=0; + idetape_copy_buffer_from_stage (tape->first_stage,buffer); + if (rq_ptr->errors != IDETAPE_RQ_ERROR_FILEMARK) + idetape_remove_stage_head (drive); +#if IDETAPE_DEBUG_BUGS + if (bytes_read > blocks*tape->tape_block_size) { + printk ("ide-tape: bug: trying to return more bytes than requested\n"); + bytes_read=blocks*tape->tape_block_size; + } +#endif /* IDETAPE_DEBUG_BUGS */ + return (bytes_read); } /* @@ -3186,8 +3272,6 @@ int idetape_add_chrdev_write_request (ide_drive_t *drive,int blocks,char *buffer printk ("Reached idetape_add_chrdev_write_request\n"); #endif /* IDETAPE_DEBUG_LOG */ - if (tape->error_in_pipeline_stage) /* Return a deferred error */ - return (-EIO); new_stage=idetape_kmalloc_stage (drive); @@ -3242,10 +3326,15 @@ int idetape_add_chrdev_write_request (ide_drive_t *drive,int blocks,char *buffer if (tape->active_data_request == NULL && tape->current_number_of_stages >= 0.75*tape->max_number_of_stages) idetape_insert_pipeline_into_queue (drive); - return (0); + if (tape->error_in_pipeline_stage) { /* Return a deferred error */ + tape->error_in_pipeline_stage=0; + return (-EIO); + } + + return (blocks); } -void idetape_empty_read_pipeline (ide_drive_t *drive) +void idetape_discard_read_pipeline (ide_drive_t *drive) { idetape_tape_t *tape = &(drive->tape); @@ -3253,11 +3342,14 @@ void idetape_empty_read_pipeline (ide_drive_t *drive) #if IDETAPE_DEBUG_BUGS if (tape->chrdev_direction != idetape_direction_read) { - printk ("ide-tape: bug: Trying to empty read pipeline, but we are not reading.\n"); + printk ("ide-tape: bug: Trying to discard read pipeline, but we are not reading.\n"); return; } #endif /* IDETAPE_DEBUG_BUGS */ + tape->merge_buffer_size=tape->merge_buffer_offset=0; + tape->chrdev_direction=idetape_direction_none; + if (tape->first_stage == NULL) return; @@ -3277,23 +3369,23 @@ void idetape_empty_read_pipeline (ide_drive_t *drive) #endif /* IDETAPE_PIPELINE */ } - -void idetape_empty_write_pipeline (ide_drive_t *drive) +/* + * idetape_wait_for_pipeline will wait until all pending pipeline + * requests are serviced. Typically called on device close. + */ + +void idetape_wait_for_pipeline (ide_drive_t *drive) { idetape_tape_t *tape = &(drive->tape); unsigned long flags; -#if IDETAPE_DEBUG_BUGS - if (tape->chrdev_direction != idetape_direction_write) { - printk ("ide-tape: bug: Trying to empty write pipeline, but we are not writing.\n"); - return; - } -#endif /* IDETAPE_DEBUG_BUGS */ - if (tape->active_data_request == NULL) idetape_insert_pipeline_into_queue (drive); + if (tape->active_data_request == NULL) + return; + save_flags (flags);cli (); if (tape->last_stage != NULL) idetape_wait_for_request (&(tape->last_stage->rq)); @@ -3301,8 +3393,39 @@ void idetape_empty_write_pipeline (ide_drive_t *drive) else if (tape->active_data_request != NULL) idetape_wait_for_request (tape->active_data_request); restore_flags (flags); +} + +void idetape_empty_write_pipeline (ide_drive_t *drive) + +{ + idetape_tape_t *tape = &(drive->tape); + int blocks; +#if IDETAPE_DEBUG_BUGS + if (tape->chrdev_direction != idetape_direction_write) { + printk ("ide-tape: bug: Trying to empty write pipeline, but we are not writing.\n"); + return; + } + if (tape->merge_buffer_size > tape->data_buffer_size) { + printk ("ide-tape: bug: merge_buffer too big\n"); + tape->merge_buffer_size = tape->data_buffer_size; + } +#endif /* IDETAPE_DEBUG_BUGS */ + + if (tape->merge_buffer_size) { + blocks=tape->merge_buffer_size/tape->tape_block_size; + if (tape->merge_buffer_size % tape->tape_block_size) { + blocks++; + memset (tape->merge_buffer+tape->merge_buffer_size,0,tape->data_buffer_size-tape->merge_buffer_size); + } + (void) idetape_add_chrdev_write_request (drive,blocks,tape->merge_buffer); + tape->merge_buffer_size=0; + } + + idetape_wait_for_pipeline (drive); + tape->error_in_pipeline_stage=0; + tape->chrdev_direction=idetape_direction_none; /* * On the next backup, perform the feedback loop again. @@ -3316,7 +3439,6 @@ void idetape_empty_write_pipeline (ide_drive_t *drive) #else tape->max_number_of_stages=0; #endif /* IDETAPE_PIPELINE */ - #if IDETAPE_DEBUG_BUGS if (tape->first_stage != NULL || tape->next_stage != NULL || tape->last_stage != NULL || tape->current_number_of_stages != 0) { printk ("ide-tape: ide-tape pipeline bug\n"); @@ -3324,7 +3446,6 @@ void idetape_empty_write_pipeline (ide_drive_t *drive) #endif /* IDETAPE_DEBUG_BUGS */ } - /* * idetape_zero_packet_command just zeros a packet command and * sets the number of retries to 0, as we haven't retried it yet. @@ -3339,6 +3460,8 @@ void idetape_zero_packet_command (idetape_packet_command_t *pc) pc->c[i]=0; pc->retries=0; pc->abort=0; + pc->dma_recommended=0; + pc->dma_error=0; } /* @@ -3494,27 +3617,20 @@ void idetape_blkdev_release (struct inode *inode, struct file *filp, ide_drive_t * Our character device read / write functions. * * The tape is optimized to maximize throughput when it is transfering - * an integral number of the "continous transfer limit", which is - * a parameter of the specific tape (26 KB on my particular tape). The - * resulting increase in performance should be dramatical. In the - * character device read/write functions, we split the current - * request to units of the above size, and handle the remaining bytes - * in some other sub-functions. - * - * In case the count number is not even an integral number of the tape - * block size (usually 512 or 1024 bytes), we will pad the transfer with - * zeroes (write) or read the entire block and return only the requested - * bytes (but the tape will be in the "wrong" position). Do not supply - * such a count value unless you are going to close the device right - * after this request. + * an integral number of the "continuous transfer limit", which is + * a parameter of the specific tape (26 KB on my particular tape). * - * Again, for best results use an integral number of the tape's parameter + * For best results use an integral number of the tape's parameter * (which is displayed in the driver installation stage and is returned * by the MTIOCGET ioctl). - */ - -/* - * Our character device read function. + * + * As of version 1.3 of the driver, the character device provides an + * abstract continuous view of the media - any mix of block sizes (even 1 + * byte) on the same backup/restore procedure is supported. The driver + * will internally convert the requests to the recommended transfer unit, + * so that an unmatch between the user's block size to the recommended + * size will only result in a (slightly) increased driver overhead, but + * will no longer hit performance. */ int idetape_chrdev_read (struct inode *inode, struct file *file, char *buf, int count) @@ -3522,9 +3638,8 @@ int idetape_chrdev_read (struct inode *inode, struct file *file, char *buf, int { ide_drive_t *drive=idetape_chrdev.drive; idetape_tape_t *tape=&(drive->tape); - int blocks,remainder,retval; - char *buf_ptr; - unsigned long previous_block_address,actually_read; + char *buf_ptr=buf; + int bytes_read,temp,actually_read=0; #if IDETAPE_DEBUG_LOG printk ("Reached idetape_chrdev_read\n"); @@ -3542,9 +3657,9 @@ int idetape_chrdev_read (struct inode *inode, struct file *file, char *buf, int * mode. */ - retval=idetape_queue_rw_tail (drive,IDETAPE_READ_REQUEST,0,tape->temp_data_buffer); - if (retval) - return (retval); + bytes_read=idetape_queue_rw_tail (drive,IDETAPE_READ_REQUEST,0,tape->merge_buffer); + if (bytes_read < 0) + return (bytes_read); tape->chrdev_direction=idetape_direction_read; } @@ -3552,97 +3667,55 @@ int idetape_chrdev_read (struct inode *inode, struct file *file, char *buf, int if (count==0) return (0); - actually_read=0; - buf_ptr=buf; - blocks=count/tape->data_buffer_size; - remainder=count%tape->data_buffer_size; - - while (blocks) { - previous_block_address=tape->block_address; - retval=idetape_add_chrdev_read_request (drive,tape->capabilities.ctl,tape->temp_data_buffer); - if (tape->max_number_of_stages) - actually_read+=tape->data_buffer_size; - else - actually_read+=tape->tape_block_size*(tape->block_address-previous_block_address); - - if (retval) { - if (tape->max_number_of_stages) - return (0); - else - return (actually_read); + if (tape->merge_buffer_size) { +#if IDETAPE_DEBUG_BUGS + if (tape->merge_buffer_offset+tape->merge_buffer_size > tape->data_buffer_size) { + printk ("ide-tape: bug: merge buffer too big\n"); + tape->merge_buffer_offset=0;tape->merge_buffer_size=tape->data_buffer_size-1; } - memcpy_tofs (buf_ptr,tape->temp_data_buffer,tape->data_buffer_size); - buf_ptr+=tape->data_buffer_size; - blocks--; +#endif /* IDETAPE_DEBUG_BUGS */ + actually_read=IDETAPE_MIN (tape->merge_buffer_size,count); + memcpy_tofs (buf_ptr,tape->merge_buffer+tape->merge_buffer_offset,actually_read); + buf_ptr+=actually_read;tape->merge_buffer_size-=actually_read; + count-=actually_read;tape->merge_buffer_offset+=actually_read; } - if (remainder) - return (actually_read+idetape_chrdev_read_remainder (inode,file,buf_ptr,remainder)); - else - return (actually_read); -} - -int idetape_chrdev_read_remainder (struct inode *inode, struct file *file, char *buf, int count) - -{ - ide_drive_t *drive=idetape_chrdev.drive; - idetape_tape_t *tape=&(drive->tape); - int blocks,remainder,retval; - unsigned long previous_block_address,actually_read; -#if IDETAPE_DEBUG_LOG - printk ("Reached idetape_chrdev_read_remainder\n"); -#endif /* IDETAPE_DEBUG_LOG */ - - blocks=count/tape->tape_block_size; - remainder=count%tape->tape_block_size; - if (remainder) { -#if IDETAPE_DEBUG_LOG - printk ("ide-tape: Padding read to block boundary\n"); -#endif /* IDETAPE_DEBUG_LOG */ - blocks++; + while (count >= tape->data_buffer_size) { + bytes_read=idetape_add_chrdev_read_request (drive,tape->capabilities.ctl,tape->merge_buffer); + if (bytes_read <= 0) + return (actually_read); + memcpy_tofs (buf_ptr,tape->merge_buffer,bytes_read); + buf_ptr+=bytes_read;count-=bytes_read;actually_read+=bytes_read; } -#if IDETAPE_DEBUG_LOG - printk ("Adding a READ request to the block device request queue\n"); -#endif /* IDETAPE_DEBUG_LOG */ - previous_block_address=tape->block_address; - retval=idetape_add_chrdev_read_request (drive,blocks,tape->temp_data_buffer); - if (retval) { - if (tape->max_number_of_stages) - actually_read=0; - else - actually_read=tape->tape_block_size*(tape->block_address-previous_block_address); - if (actually_read > count) - actually_read=count; - if (actually_read != 0) - memcpy_tofs (buf,tape->temp_data_buffer,actually_read); - return (actually_read); + + if (count) { + bytes_read=idetape_add_chrdev_read_request (drive,tape->capabilities.ctl,tape->merge_buffer); + if (bytes_read <= 0) + return (actually_read); + temp=IDETAPE_MIN (count,bytes_read); + memcpy_tofs (buf_ptr,tape->merge_buffer,temp); + actually_read+=temp; + tape->merge_buffer_offset=temp; + tape->merge_buffer_size=bytes_read-temp; } -#if IDETAPE_DEBUG_LOG - printk ("Copying %d bytes to the user space memory\n",count); -#endif /* IDETAPE_DEBUG_LOG */ - memcpy_tofs (buf,tape->temp_data_buffer,count); - return (count); + return (actually_read); } - + int idetape_chrdev_write (struct inode *inode, struct file *file, const char *buf, int count) { - ide_drive_t *drive; - idetape_tape_t *tape; - int blocks,remainder,retval; - const char *buf_ptr; - unsigned long previous_block_address,actually_written; + ide_drive_t *drive=idetape_chrdev.drive; + idetape_tape_t *tape=&(drive->tape); + const char *buf_ptr=buf; + int retval,actually_written=0; #if IDETAPE_DEBUG_LOG printk ("Reached idetape_chrdev_write\n"); #endif /* IDETAPE_DEBUG_LOG */ - drive=idetape_chrdev.drive; - tape=&(drive->tape); - if (tape->chrdev_direction != idetape_direction_write) { /* Initialize write operation */ if (tape->chrdev_direction == idetape_direction_read) - idetape_empty_read_pipeline (drive); + idetape_discard_read_pipeline (drive); /* * Issue a write 0 command to ensure that DSC handshake @@ -3650,93 +3723,51 @@ int idetape_chrdev_write (struct inode *inode, struct file *file, const char *bu * mode. */ - retval=idetape_queue_rw_tail (drive,IDETAPE_WRITE_REQUEST,0,tape->temp_data_buffer); - if (retval) + retval=idetape_queue_rw_tail (drive,IDETAPE_WRITE_REQUEST,0,tape->merge_buffer); + if (retval < 0) return (retval); - + tape->chrdev_direction=idetape_direction_write; } if (count==0) return (0); - actually_written=0; - buf_ptr=buf; - blocks=count/tape->data_buffer_size; - remainder=count%tape->data_buffer_size; - - while (blocks) { - memcpy_fromfs (tape->temp_data_buffer,buf_ptr,tape->data_buffer_size); - buf_ptr+=tape->data_buffer_size; - previous_block_address=tape->block_address; - retval=idetape_add_chrdev_write_request (drive,tape->capabilities.ctl,tape->temp_data_buffer); - if (tape->max_number_of_stages) - actually_written+=tape->data_buffer_size; /* Pipelined mode - Cheat :-) */ - else - actually_written+=tape->tape_block_size*(tape->block_address-previous_block_address); - - if (retval) { - if (tape->max_number_of_stages) - return (0); - else - return (actually_written); + if (tape->merge_buffer_size) { +#if IDETAPE_DEBUG_BUGS + if (tape->merge_buffer_size >= tape->data_buffer_size) { + printk ("ide-tape: bug: merge buffer too big\n"); + tape->merge_buffer_size=0; } - blocks--; - } - if (remainder) - return (actually_written+idetape_chrdev_write_remainder (inode,file,buf_ptr,remainder)); - else - return (actually_written); -} +#endif /* IDETAPE_DEBUG_BUGS */ -int idetape_chrdev_write_remainder (struct inode *inode, struct file *file, const char *buf, int count) + actually_written=IDETAPE_MIN (tape->data_buffer_size-tape->merge_buffer_size,count); + memcpy_fromfs (tape->merge_buffer+tape->merge_buffer_size,buf_ptr,actually_written); + buf_ptr+=actually_written;tape->merge_buffer_size+=actually_written;count-=actually_written; -{ - ide_drive_t *drive; - idetape_tape_t *tape; - int blocks,remainder,retval; - char *ptr; - unsigned long previous_block_address,actually_written; - -#if IDETAPE_DEBUG_LOG - printk ("Reached idetape_chrdev_write_remainder\n"); -#endif /* IDETAPE_DEBUG_LOG */ - - drive=idetape_chrdev.drive; - tape=&(drive->tape); - - blocks=count/tape->tape_block_size; - remainder=count%tape->tape_block_size; - if (remainder) - blocks++; -#if IDETAPE_DEBUG_LOG - printk ("Copying %d bytes from the user space memory\n",count); -#endif /* IDETAPE_DEBUG_LOG */ + if (tape->merge_buffer_size == tape->data_buffer_size) { + tape->merge_buffer_size=0; + retval=idetape_add_chrdev_write_request (drive,tape->capabilities.ctl,tape->merge_buffer); + if (retval <= 0) + return (retval); + } + } - memcpy_fromfs (tape->temp_data_buffer,buf,count); - if (remainder) { -#if IDETAPE_DEBUG_LOG - printk ("ide-tape: Padding written data to block boundary\n"); -#endif /* IDETAPE_DEBUG_LOG */ - ptr=tape->temp_data_buffer+(blocks-1)*tape->tape_block_size; - memset (ptr,0,remainder); + while (count >= tape->data_buffer_size) { + memcpy_fromfs (tape->merge_buffer,buf_ptr,tape->data_buffer_size); + buf_ptr+=tape->data_buffer_size;count-=tape->data_buffer_size; + retval=idetape_add_chrdev_write_request (drive,tape->capabilities.ctl,tape->merge_buffer); + actually_written+=tape->data_buffer_size; + if (retval <= 0) + return (retval); } -#if IDETAPE_DEBUG_LOG - printk ("Adding a WRITE request to the block device request queue\n"); -#endif /* IDETAPE_DEBUG_LOG */ - previous_block_address=tape->block_address; - retval=idetape_add_chrdev_write_request (drive,blocks,tape->temp_data_buffer); - if (retval) { - if (tape->max_number_of_stages) - actually_written=0; - else - actually_written=tape->tape_block_size*(tape->block_address-previous_block_address); - if (actually_written > count) - actually_written=count; - return (actually_written); + if (count) { + actually_written+=count; + memcpy_fromfs (tape->merge_buffer,buf_ptr,count); + tape->merge_buffer_size+=count; } - return (count); + return (actually_written); } /* @@ -3788,14 +3819,10 @@ int idetape_chrdev_ioctl (struct inode *inode, struct file *file, unsigned int c if (tape->chrdev_direction == idetape_direction_write) { idetape_empty_write_pipeline (drive); idetape_flush_tape_buffers (drive); - tape->chrdev_direction=idetape_direction_none; } - if (tape->chrdev_direction == idetape_direction_read) - if (cmd != MTIOCTOP) { - idetape_empty_read_pipeline (drive); - tape->chrdev_direction=idetape_direction_none; - } + if (tape->chrdev_direction == idetape_direction_read && cmd != MTIOCTOP) + idetape_discard_read_pipeline (drive); pc.buffer=pc.temp_buffer; pc.buffer_size=IDETAPE_TEMP_BUFFER_SIZE; @@ -3904,6 +3931,8 @@ int idetape_mtioctop (ide_drive_t *drive,short mt_op,int mt_count) case MTFSFM: case MTBSF: case MTBSFM: + if (!mt_count) + return (0); return (idetape_space_over_filemarks (drive,mt_op,mt_count)); default: break; @@ -3913,10 +3942,8 @@ int idetape_mtioctop (ide_drive_t *drive,short mt_op,int mt_count) * Empty the pipeline. */ - if (tape->chrdev_direction == idetape_direction_read) { - idetape_empty_read_pipeline (drive); - tape->chrdev_direction=idetape_direction_none; - } + if (tape->chrdev_direction == idetape_direction_read) + idetape_discard_read_pipeline (drive); switch (mt_op) { case MTWEOF: @@ -3976,7 +4003,8 @@ int idetape_space_over_filemarks (ide_drive_t *drive,short mt_op,int mt_count) * We have a read-ahead buffer. Scan it for crossed * filemarks. */ - + + tape->merge_buffer_size=tape->merge_buffer_offset=0; while (tape->first_stage != NULL) { /* @@ -4003,7 +4031,7 @@ int idetape_space_over_filemarks (ide_drive_t *drive,short mt_op,int mt_count) } idetape_remove_stage_head (drive); } - tape->chrdev_direction = idetape_direction_none; + idetape_discard_read_pipeline (drive); } /* @@ -4049,10 +4077,10 @@ int idetape_space_over_filemarks (ide_drive_t *drive,short mt_op,int mt_count) int idetape_chrdev_open (struct inode *inode, struct file *filp) { - ide_drive_t *drive; - idetape_tape_t *tape; + ide_drive_t *drive=idetape_chrdev.drive; + idetape_tape_t *tape=&(drive->tape); unsigned long flags; - unsigned int minor; + unsigned int minor=MINOR (inode->i_rdev),allocation_length; save_flags (flags);cli (); @@ -4060,11 +4088,6 @@ int idetape_chrdev_open (struct inode *inode, struct file *filp) printk ("Reached idetape_chrdev_open\n"); #endif /* IDETAPE_DEBUG_LOG */ - - drive=idetape_chrdev.drive; - tape=&(drive->tape); - minor=MINOR (inode->i_rdev); - if (minor!=0 && minor!=128) { /* Currently supporting only one */ restore_flags (flags); /* tape drive */ return (-ENXIO); @@ -4078,6 +4101,26 @@ int idetape_chrdev_open (struct inode *inode, struct file *filp) tape->busy=1; restore_flags (flags); + allocation_length=tape->data_buffer_size; + if (tape->data_buffer_size % IDETAPE_ALLOCATION_BLOCK) + allocation_length+=IDETAPE_ALLOCATION_BLOCK; + +#if IDETAPE_MINIMIZE_IDLE_MEMORY_USAGE + if (tape->data_buffer == NULL) + tape->data_buffer=kmalloc (allocation_length,GFP_KERNEL); + if (tape->data_buffer == NULL) + goto sorry; + if (tape->merge_buffer == NULL) + tape->merge_buffer=kmalloc (allocation_length,GFP_KERNEL); + if (tape->merge_buffer == NULL) { + kfree (tape->data_buffer); + sorry: + printk ("ide-tape: FATAL - Can not allocate continuous buffer of %d bytes\n",allocation_length); + tape->busy=0; + return (-EIO); + } +#endif /* IDETAPE_MINIMIZE_IDLE_MEMORY_USAGE */ + if (!tape->block_address_valid) { if (idetape_rewind_tape (drive)) { printk ("ide-tape: Rewinding tape failed\n"); @@ -4096,10 +4139,9 @@ int idetape_chrdev_open (struct inode *inode, struct file *filp) void idetape_chrdev_release (struct inode *inode, struct file *filp) { - ide_drive_t *drive; - idetape_tape_t *tape; - - unsigned int minor; + ide_drive_t *drive=idetape_chrdev.drive; + idetape_tape_t *tape=&(drive->tape); + unsigned int minor=MINOR (inode->i_rdev); idetape_packet_command_t pc; unsigned long flags; @@ -4107,28 +4149,32 @@ void idetape_chrdev_release (struct inode *inode, struct file *filp) printk ("Reached idetape_chrdev_release\n"); #endif /* IDETAPE_DEBUG_LOG */ - drive=idetape_chrdev.drive; - tape=&(drive->tape); - minor=MINOR (inode->i_rdev); - if (tape->chrdev_direction == idetape_direction_write) { idetape_empty_write_pipeline (drive); - tape->chrdev_direction = idetape_direction_none; idetape_create_write_filemark_cmd (&pc,1); /* Write a filemark */ - if (idetape_queue_pc_tail (drive,&pc)) { + if (idetape_queue_pc_tail (drive,&pc)) printk ("ide-tape: Couldn't write a filemark\n"); - /* ??? */ - } } - - if (minor < 128) { - if (tape->chrdev_direction == idetape_direction_read) - idetape_empty_read_pipeline (drive); - if (idetape_rewind_tape (drive)) { + + if (tape->chrdev_direction == idetape_direction_read) { + if (minor < 128) + idetape_discard_read_pipeline (drive); + else + idetape_wait_for_pipeline (drive); + } + + if (minor < 128) + if (idetape_rewind_tape (drive)) printk ("ide-tape: Rewinding tape failed\n"); - /* ??? */ - } + +#if IDETAPE_MINIMIZE_IDLE_MEMORY_USAGE + kfree (tape->data_buffer); + tape->data_buffer=NULL; + if (!tape->merge_buffer_size) { + kfree (tape->merge_buffer); + tape->merge_buffer=NULL; } +#endif /* IDETAPE_MINIMIZE_IDLE_MEMORY_USAGE */ save_flags (flags);cli (); tape->busy=0; @@ -4307,7 +4353,7 @@ void idetape_kfree_stage (idetape_pipeline_stage_t *stage) /* * idetape_copy_buffer_from_stage and idetape_copy_buffer_to_stage - * copy data from/to the small buffers into/from a continous buffer. + * copy data from/to the small buffers into/from a continuous buffer. */ void idetape_copy_buffer_from_stage (idetape_pipeline_stage_t *stage,char *buffer) diff --git a/drivers/block/ide-tape.h b/drivers/block/ide-tape.h index 7382a34de159..a18bacd25976 100644 --- a/drivers/block/ide-tape.h +++ b/drivers/block/ide-tape.h @@ -1,5 +1,5 @@ /* - * linux/drivers/block/ide-tape.h Version 1.2 - ALPHA Jan 1, 1996 + * linux/drivers/block/ide-tape.h Version 1.3 - ALPHA Feb 9, 1996 * * Copyright (C) 1995, 1996 Gadi Oxman */ @@ -96,6 +96,20 @@ #define IDETAPE_ALLOCATION_BLOCK 512 #endif +/* + * ide-tape currently uses two continous buffers, each of the size of + * one stage. By default, those buffers are allocated at initialization + * time and never released, since dynamic allocation of pages bigger + * than PAGE_SIZE may fail as memory becomes fragmented. + * + * This results in about 100 KB memory usage when the tape is idle. + * Setting IDETAPE_MINIMIZE_IDLE_MEMORY_USAGE to 1 will let ide-tape + * to dynamically allocate those buffers, resulting in about 20 KB idle + * memory usage. + */ + +#define IDETAPE_MINIMIZE_IDLE_MEMORY_USAGE 0 + /* * The following are used to debug the driver: * @@ -124,7 +138,7 @@ * Setting IDETAPE_MAX_PC_RETRIES to 0 will disable retries. */ -#define IDETAPE_MAX_PC_RETRIES 2 +#define IDETAPE_MAX_PC_RETRIES 3 /* * With each packet command, we allocate a buffer of @@ -256,6 +270,9 @@ typedef struct idetape_packet_command_s { byte error; /* Error code */ byte abort; /* Set when an error is considered normal - We won't retry */ byte wait_for_dsc; /* 1 When polling for DSC on a media access command */ + byte dma_recommended; /* 1 when we prefer to use DMA if possible */ + byte dma_in_progress; /* 1 while DMA in progress */ + byte dma_error; /* 1 when encountered problem during DMA */ unsigned long request_transfer; /* Bytes to transfer */ unsigned long actually_transferred; /* Bytes actually transferred */ unsigned long buffer_size; /* Size of our data buffer */ @@ -419,6 +436,14 @@ typedef struct { byte last_status; /* Contents of the tape status register */ /* before the current request (saved for us */ /* by ide.c) */ + /* + * After an ATAPI software reset, the status register will be + * locked, and thus we need to ignore it when checking DSC for + * the first time. + */ + + byte reset_issued; + /* Position information */ byte partition_num; /* Currently not used */ @@ -456,8 +481,11 @@ typedef struct { struct request *active_data_request; /* Pointer to the request which is waiting in the device request queue */ char *data_buffer; /* The correspoding data buffer (for read/write requests) */ int data_buffer_size; /* Data buffer size (chosen based on the tape's recommendation */ - char *temp_data_buffer; /* Temporary buffer for user <-> kernel space data transfer */ + char *merge_buffer; /* Temporary buffer for user <-> kernel space data transfer */ + int merge_buffer_offset; + int merge_buffer_size; + /* * Pipeline parameters. * diff --git a/drivers/block/ide.c b/drivers/block/ide.c index d53e19038ae1..d3bb67c5e682 100644 --- a/drivers/block/ide.c +++ b/drivers/block/ide.c @@ -1,5 +1,5 @@ /* - * linux/drivers/block/ide.c Version 5.27 Feb 8, 1996 + * linux/drivers/block/ide.c Version 5.28 Feb 11, 1996 * * Copyright (C) 1994-1996 Linus Torvalds & authors (see below) */ @@ -200,6 +200,11 @@ * add ali14xx support in ali14xx.c * Version 5.27 add [no]autotune parameters to help cmd640 * move rz1000 support to rz1000.c + * Version 5.28 #include "ide_modes.h" + * fix disallow_unmask: now per-interface "no_unmask" bit + * force io_32bit to be the same on drive pairs of dtc2278 + * improved IDE tape error handling, and tape DMA support + * bugfix in ide_do_drive_cmd() for cdroms + serialize * * Some additional driver compile-time options are in ide.h * @@ -237,13 +242,13 @@ #endif /* CONFIG_PCI */ #include "ide.h" +#include "ide_modes.h" -static ide_hwgroup_t *irq_to_hwgroup [16]; +static ide_hwgroup_t *irq_to_hwgroup [NR_IRQS]; 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}; - int ide_disallow_unmask = 0; /* for buggy hardware */ #if (DISK_RECOVERY_TIME > 0) /* @@ -302,7 +307,7 @@ static void init_ide_data (void) return; /* already initialized */ magic_cookie = 0; - for (h = 0; h < 16; ++h) + for (h = 0; h < NR_IRQS; ++h) irq_to_hwgroup[h] = NULL; /* bulk initialize hwif & drive info with zeros */ @@ -311,10 +316,10 @@ static void init_ide_data (void) *--p = 0; } while (p > (byte *) ide_hwifs); + /* fill in any non-zero initial values */ for (h = 0; h < MAX_HWIFS; ++h) { ide_hwif_t *hwif = &ide_hwifs[h]; - /* fill in any non-zero initial values */ hwif->index = h; hwif->noprobe = (h > 1); hwif->io_base = default_io_base[h]; @@ -334,7 +339,6 @@ static void init_ide_data (void) for (unit = 0; unit < MAX_DRIVES; ++unit) { ide_drive_t *drive = &hwif->drives[unit]; - /* fill in any non-zero initial values */ drive->select.all = (unit<<4)|0xa0; drive->hwif = hwif; drive->ctl = 0x08; @@ -349,7 +353,7 @@ static void init_ide_data (void) } } -#define VLB_SYNC 1 +#if SUPPORT_VLB_SYNC /* * Some localbus EIDE interfaces require a special access sequence * when using 32-bit I/O instructions to transfer data. We call this @@ -362,6 +366,7 @@ static inline void do_vlb_sync (unsigned short port) { (void) inb (port); (void) inb (port); } +#endif /* SUPPORT_VLB_SYNC */ /* * This is used for most PIO data transfers *from* the IDE interface @@ -373,7 +378,7 @@ void ide_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount) byte io_32bit = drive->io_32bit; if (io_32bit) { -#ifdef VLB_SYNC +#if SUPPORT_VLB_SYNC if (io_32bit & 2) { cli(); do_vlb_sync(io_base+IDE_NSECTOR_OFFSET); @@ -381,7 +386,7 @@ void ide_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount) if (drive->unmask) sti(); } else -#endif /* VLB_SYNC */ +#endif /* SUPPORT_VLB_SYNC */ insl(data_reg, buffer, wcount); } else insw(data_reg, buffer, wcount<<1); @@ -397,7 +402,7 @@ void ide_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount) byte io_32bit = drive->io_32bit; if (io_32bit) { -#ifdef VLB_SYNC +#if SUPPORT_VLB_SYNC if (io_32bit & 2) { cli(); do_vlb_sync(io_base+IDE_NSECTOR_OFFSET); @@ -405,7 +410,7 @@ void ide_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount) if (drive->unmask) sti(); } else -#endif /* VLB_SYNC */ +#endif /* SUPPORT_VLB_SYNC */ outsl(data_reg, buffer, wcount); } else outsw(data_reg, buffer, wcount<<1); @@ -723,6 +728,10 @@ static void do_reset1 (ide_drive_t *drive, int do_not_try_atapi) void ide_do_reset (ide_drive_t *drive) { do_reset1 (drive, 0); +#ifdef CONFIG_BLK_DEV_IDETAPE + if (drive->media == ide_tape) + drive->tape.reset_issued=1; +#endif /* CONFIG_BLK_DEV_IDETAPE */ } /* @@ -851,7 +860,8 @@ void ide_error (ide_drive_t *drive, const char *msg, byte stat) if ((rq = HWGROUP(drive)->rq) == NULL || drive == NULL) return; /* retry only "normal" I/O: */ - if (rq->cmd != READ && rq->cmd != WRITE && drive->media != ide_cdrom) { + if (rq->cmd == IDE_DRIVE_CMD || (rq->cmd != READ && rq->cmd != WRITE && drive->media == ide_disk)) + { rq->errors = 1; ide_end_drive_cmd(drive, stat, err); return; @@ -872,8 +882,16 @@ void ide_error (ide_drive_t *drive, const char *msg, byte stat) if (GET_STAT() & (BUSY_STAT|DRQ_STAT)) rq->errors |= ERROR_RESET; /* Mmmm.. timing problem */ - if (rq->errors >= ERROR_MAX) - ide_end_request(0, HWGROUP(drive)); + if (rq->errors >= ERROR_MAX) { +#ifdef CONFIG_BLK_DEV_IDETAPE + if (drive->media == ide_tape) { + rq->errors = 0; + idetape_end_request(0, HWGROUP(drive)); + } + else +#endif /* CONFIG_BLK_DEV_IDETAPE */ + ide_end_request(0, HWGROUP(drive)); + } else { if ((rq->errors & ERROR_RESET) == ERROR_RESET) { ++rq->errors; @@ -1347,6 +1365,12 @@ static inline void do_request (ide_hwif_t *hwif, struct request *rq) #endif /* CONFIG_BLK_DEV_IDECD */ #ifdef CONFIG_BLK_DEV_IDETAPE case ide_tape: + if (rq->cmd == IDE_DRIVE_CMD) { + byte *args = (byte *) rq->buffer; + OUT_BYTE(args[2],IDE_FEATURE_REG); + ide_cmd(drive, args[0], args[1], &drive_cmd_intr); + return; + } idetape_do_request (drive, rq, block); return; #endif /* CONFIG_BLK_DEV_IDETAPE */ @@ -1656,9 +1680,13 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio if (cur_rq == NULL || action == ide_preempt) { rq->next = cur_rq; bdev->current_request = rq; - HWGROUP(drive)->rq = NULL; - if (action != ide_preempt) + if (action == ide_preempt) { + HWGROUP(drive)->rq = NULL; + } else + if (HWGROUP(drive)->rq == NULL) { /* is this necessary (?) */ bdev->request_fn(); + cli(); + } } else { if (action == ide_wait || action == ide_end) { while (cur_rq->next != NULL) /* find end of list */ @@ -1667,7 +1695,7 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio rq->next = cur_rq->next; cur_rq->next = rq; } - if (action == ide_wait) + if (action == ide_wait && rq->rq_status != RQ_INACTIVE) down(&sem); /* wait for it to be serviced */ restore_flags(flags); return rq->errors ? -EIO : 0; /* return -EIO if errors */ @@ -1879,8 +1907,10 @@ static int ide_ioctl (struct inode *inode, struct file *file, return write_fs_long(arg, drive->bad_wstat == BAD_R_STAT); case HDIO_SET_DMA: - if (drive->media != ide_disk) +#ifdef CONFIG_BLK_DEV_IDECD + if (drive->media == ide_cdrom) return -EPERM; +#endif /* CONFIG_BLK_DEV_IDECD */ if (!drive->id || !(drive->id->capability & 1) || !HWIF(drive)->dmaproc) return -EPERM; case HDIO_SET_KEEPSETTINGS: @@ -1907,7 +1937,7 @@ static int ide_ioctl (struct inode *inode, struct file *file, drive->keep_settings = arg; break; case HDIO_SET_UNMASKINTR: - if (arg && ide_disallow_unmask) { + if (arg && HWIF(drive)->no_unmask) { restore_flags(flags); return -EPERM; } @@ -1917,11 +1947,13 @@ static int ide_ioctl (struct inode *inode, struct file *file, drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT; break; case HDIO_SET_32BIT: + if (arg > (1 + (SUPPORT_VLB_SYNC<<1))) + return -EINVAL; drive->io_32bit = arg; -#ifndef VLB_SYNC - if (arg & 2) - printk("%s: VLB_SYNC not supported by this kernel\n", drive->name); -#endif +#ifdef CONFIG_BLK_DEV_DTC2278 + if (HWIF(drive)->chipset == ide_dtc2278) + HWIF(drive)->drives[!drive->select.b.unit].io_32bit = arg; +#endif /* CONFIG_BLK_DEV_DTC2278 */ break; } restore_flags(flags); @@ -1932,7 +1964,7 @@ static int ide_ioctl (struct inode *inode, struct file *file, return -EACCES; if (MINOR(inode->i_rdev) & PARTN_MASK) return -EINVAL; - if ((drive->id != NULL) && (arg > drive->id->max_multsect)) + if (drive->id && arg > drive->id->max_multsect) return -EINVAL; save_flags(flags); cli(); @@ -2093,15 +2125,19 @@ static inline void do_identify (ide_drive_t *drive, byte cmd) #endif /* CONFIG_BLK_DEV_IDECD */ case 1: #ifdef CONFIG_BLK_DEV_IDETAPE - printk ("TAPE drive\n"); + printk ("TAPE drive"); if (idetape_identify_device (drive,id)) { drive->media = ide_tape; drive->present = 1; drive->removeable = 1; + if (HWIF(drive)->dmaproc != NULL && + !HWIF(drive)->dmaproc(ide_dma_check, drive)) + printk(", DMA"); + printk("\n"); } else { drive->present = 0; - printk ("ide-tape: The tape is not supported by this version of the driver\n"); + printk ("\nide-tape: the tape is not supported by this version of the driver\n"); } return; #else @@ -2249,7 +2285,7 @@ static int try_to_identify (ide_drive_t *drive, byte cmd) if (OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)) { cli(); /* some systems need this */ do_identify(drive, cmd); /* drive returned ID */ - if (drive->present && (drive->media == ide_disk || drive->media == ide_cdrom)) { + if (drive->present && drive->media != ide_tape) { ide_tuneproc_t *tuneproc = HWIF(drive)->tuneproc; if (tuneproc != NULL && drive->autotune == 1) tuneproc(drive, 255); /* auto-tune PIO mode */ diff --git a/drivers/block/ide.h b/drivers/block/ide.h index e8c3834d1500..b1ebc4c3c88e 100644 --- a/drivers/block/ide.h +++ b/drivers/block/ide.h @@ -25,6 +25,9 @@ #undef REALLY_FAST_IO /* define if ide ports are perfect */ #define INITIAL_MULT_COUNT 0 /* off=0; on=2,4,8,16,32, etc.. */ +#ifndef SUPPORT_VLB_SYNC /* 1 to support weird 32-bit chips */ +#define SUPPORT_VLB_SYNC 1 /* 0 to reduce kernel size */ +#endif #ifndef DISK_RECOVERY_TIME /* off=0; on=access_delay_time */ #define DISK_RECOVERY_TIME 0 /* for hardware that needs it */ #endif @@ -347,7 +350,12 @@ typedef struct ide_drive_s { * Returns 1 if DMA read/write could not be started, in which case the caller * should either try again later, or revert to PIO for the current request. */ -typedef enum {ide_dma_read = 0, ide_dma_write = 1, ide_dma_abort = 2, ide_dma_check = 3} ide_dma_action_t; +typedef enum { ide_dma_read = 0, ide_dma_write = 1, + ide_dma_abort = 2, ide_dma_check = 3, + ide_dma_status_bad = 4, ide_dma_transferred = 5, + ide_dma_begin = 6 } + ide_dma_action_t; + typedef int (ide_dmaproc_t)(ide_dma_action_t, ide_drive_t *); @@ -401,6 +409,7 @@ typedef struct hwif_s { unsigned noprobe : 1; /* don't probe for this interface */ unsigned present : 1; /* this interface exists */ unsigned serialized : 1; /* valid only for ide_hwifs[0] */ + unsigned no_unmask : 1; /* disallow setting unmask bits */ #if (DISK_RECOVERY_TIME > 0) unsigned long last_time; /* time when previous rq was done */ #endif @@ -616,6 +625,13 @@ void idetape_setup (ide_drive_t *drive); void idetape_do_request (ide_drive_t *drive, struct request *rq, unsigned long block); +/* + * idetape_end_request is used to finish servicing a request, and to + * insert a pending pipeline request into the main device queue. + */ + +void idetape_end_request (byte uptodate, ide_hwgroup_t *hwgroup); + /* * Block device interface functions. */ diff --git a/drivers/block/ide_modes.h b/drivers/block/ide_modes.h new file mode 100644 index 000000000000..e174d5dc14f3 --- /dev/null +++ b/drivers/block/ide_modes.h @@ -0,0 +1,142 @@ +#ifndef _IDE_MODES_H +#define _IDE_MODES_H +/* + * linux/drivers/block/ide_modes.h + * + * Copyright (C) 1996 Linus Torvalds, Igor Abramov, and Mark Lord + */ + +/* + * Shared data/functions for determining best PIO mode for an IDE drive. + * Most of this stuff originally lived in cmd640.c, and changes to the + * ide_pio_blacklist[] table should be made with EXTREME CAUTION to avoid + * breaking the fragile cmd640.c support. + */ + +#if defined(CONFIG_BLK_DEV_CMD640) || defined(CONFIG_IDE_CHIPSETS) + +#ifndef _IDE_C + +int ide_scan_pio_blacklist (char *model); +unsigned int ide_get_best_pio_mode (ide_drive_t *drive); + +#else /* _IDE_C */ + +/* + * Black list. Some drives incorrectly report their maximal PIO mode, + * at least in respect to CMD640. Here we keep info on some known drives. + */ +static struct ide_pio_info { + const char *name; + int pio; +} ide_pio_blacklist [] = { +/* { "Conner Peripherals 1275MB - CFS1275A", 4 }, */ + + { "WDC AC2700", 3 }, + { "WDC AC2540", 3 }, + { "WDC AC2420", 3 }, + { "WDC AC2340", 3 }, + { "WDC AC2250", 0 }, + { "WDC AC2200", 0 }, + { "WDC AC2120", 0 }, + { "WDC AC2850", 3 }, + { "WDC AC1270", 3 }, + { "WDC AC1170", 3 }, + { "WDC AC1210", 1 }, + { "WDC AC280", 0 }, +/* { "WDC AC21000", 4 }, */ + { "WDC AC31000", 3 }, +/* { "WDC AC21200", 4 }, */ + { "WDC AC31200", 3 }, +/* { "WDC AC31600", 4 }, */ + + { "Maxtor 7131 AT", 1 }, + { "Maxtor 7171 AT", 1 }, + { "Maxtor 7213 AT", 1 }, + { "Maxtor 7245 AT", 1 }, + { "Maxtor 7345 AT", 1 }, + { "Maxtor 7546 AT", 3 }, + { "Maxtor 7540 AV", 3 }, + + { "SAMSUNG SHD-3121A", 1 }, + { "SAMSUNG SHD-3122A", 1 }, + { "SAMSUNG SHD-3172A", 1 }, + +/* { "ST51080A", 4 }, + * { "ST51270A", 4 }, + * { "ST31220A", 4 }, + * { "ST31640A", 4 }, + * { "ST32140A", 4 }, + * { "ST3780A", 4 }, + */ + { "ST5660A", 3 }, + { "ST3660A", 3 }, + { "ST3630A", 3 }, + { "ST3655A", 3 }, + { "ST3391A", 3 }, + { "ST3390A", 1 }, + { "ST3600A", 1 }, + { "ST3290A", 0 }, + { "ST3144A", 0 }, + + { "QUANTUM ELS127A", 0 }, + { "QUANTUM ELS170A", 0 }, + { "QUANTUM LPS240A", 0 }, + { "QUANTUM LPS210A", 3 }, + { "QUANTUM LPS270A", 3 }, + { "QUANTUM LPS365A", 3 }, + { "QUANTUM LPS540A", 3 }, + { "QUANTUM FIREBALL", 3 }, /* For models 540/640/1080/1280 */ + /* 1080A works fine in mode4 with triton */ + { NULL, 0 } +}; + +/* + * This routine searches the ide_pio_blacklist for an entry + * matching the start/whole of the supplied model name. + * + * Returns -1 if no match found. + * Otherwise returns the recommended PIO mode from ide_pio_blacklist[]. + */ +int ide_scan_pio_blacklist (char *model) +{ + struct ide_pio_info *p; + + for (p = ide_pio_blacklist; p->name != NULL; p++) { + if (strncmp(p->name, model, strlen(p->name)) == 0) + return p->pio; + } + return -1; +} + +/* + * This routine returns the recommended PIO mode for a given drive, + * based on the drive->id information and the ide_pio_blacklist[]. + * This is used by most chipset support modules when "auto-tuning". + */ +unsigned int ide_get_best_pio_mode (ide_drive_t *drive) +{ + unsigned int pio = 0; + struct hd_driveid *id = drive->id; + + if (id != NULL) { + if (HWIF(drive)->chipset != ide_cmd640 && !strcmp("QUANTUM FIREBALL1080A", id->model)) + pio = 4; + else + pio = ide_scan_pio_blacklist(id->model); + if (pio == -1) { + pio = (id->tPIO < 2) ? id->tPIO : 2; + if (id->field_valid & 2) { + byte modes = id->eide_pio_modes; + if (modes & 4) pio = 5; + else if (modes & 2) pio = 4; + else if (modes & 1) pio = 3; + } + } + } + return pio; +} + +#endif /* _IDE_C */ +#endif /* defined(CONFIG_BLK_DEV_CMD640) || defined(CONFIG_IDE_CHIPSETS) */ +#endif /* _IDE_MODES_H */ diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 576fcb43cf25..b2269e38171c 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -24,7 +24,12 @@ /* * The request-struct contains all necessary data * to load a nr of sectors into memory + * + * NR_REQUEST is the number of entries in the request-queue. + * NOTE that writes may use only the low 2/3 of these: reads + * take precedence. */ +#define NR_REQUEST 16 static struct request all_requests[NR_REQUEST]; /* @@ -37,34 +42,10 @@ struct wait_queue * wait_for_request = NULL; int read_ahead[MAX_BLKDEV] = {0, }; /* blk_dev_struct is: - * do_request-address - * next-request + * *request_fn + * *current_request */ -struct blk_dev_struct blk_dev[MAX_BLKDEV] = { - { NULL, NULL }, /* 0 no_dev */ - { NULL, NULL }, /* 1 dev mem */ - { NULL, NULL }, /* 2 dev fd */ - { NULL, NULL }, /* 3 dev ide0 or hd */ - { NULL, NULL }, /* 4 dev ttyx */ - { NULL, NULL }, /* 5 dev tty */ - { NULL, NULL }, /* 6 dev lp */ - { NULL, NULL }, /* 7 dev pipes */ - { NULL, NULL }, /* 8 dev sd */ - { NULL, NULL }, /* 9 dev st */ - { NULL, NULL }, /* 10 */ - { NULL, NULL }, /* 11 */ - { NULL, NULL }, /* 12 */ - { NULL, NULL }, /* 13 */ - { NULL, NULL }, /* 14 */ - { NULL, NULL }, /* 15 */ - { NULL, NULL }, /* 16 */ - { NULL, NULL }, /* 17 */ - { NULL, NULL }, /* 18 */ - { NULL, NULL }, /* 19 */ - { NULL, NULL }, /* 20 */ - { NULL, NULL }, /* 21 */ - { NULL, NULL } /* 22 dev ide1 */ -}; +struct blk_dev_struct blk_dev[MAX_BLKDEV]; /* initialized by blk_dev_init() */ /* * blk_size contains the size of all block-devices in units of 1024 byte @@ -610,6 +591,12 @@ void ll_rw_swap_file(int rw, kdev_t dev, unsigned int *b, int nb, char *buf) int blk_dev_init(void) { struct request * req; + struct blk_dev_struct *dev; + + for (dev = blk_dev + MAX_BLKDEV; dev-- != blk_dev;) { + dev->request_fn = NULL; + dev->current_request = NULL; + } req = all_requests + NR_REQUEST; while (--req >= all_requests) { @@ -634,6 +621,9 @@ int blk_dev_init(void) #else outb_p(0xc, 0x3f2); #endif +#ifdef CONFIG_CDI_INIT + cdi_init(); +#endif CONFIG_CDI_INIT #ifdef CONFIG_CDU31A cdu31a_init(); #endif CONFIG_CDU31A diff --git a/drivers/block/qd6580.c b/drivers/block/qd6580.c index 553cd77b590e..d11e9d96cd9d 100644 --- a/drivers/block/qd6580.c +++ b/drivers/block/qd6580.c @@ -1,5 +1,5 @@ /* - * linux/drivers/block/qd6580.c Version 0.01 Feb 06, 1996 + * linux/drivers/block/qd6580.c Version 0.02 Feb 09, 1996 * * Copyright (C) 1996 Linus Torvalds & author (see below) */ @@ -21,6 +21,7 @@ #include #include #include "ide.h" +#include "ide_modes.h" /* * Register 0xb3 looks like: @@ -43,19 +44,16 @@ static void tune_qd6580 (ide_drive_t *drive, byte pio) { unsigned long flags; - if (pio == 255) { /* auto-tune */ - struct hd_driveid *id = drive->id; - pio = id->tPIO; - if ((id->field_valid & 0x02) && (id->eide_pio_modes & 0x03)) - pio = 3; - } - pio++; /* is this correct? */ + if (pio == 255) + pio = ide_get_best_pio_mode (drive); + if (pio > 3) + pio = 3; save_flags(flags); cli(); outb_p(0x8d,0xb0); outb_p(0x0 ,0xb2); - outb_p((pio<<4)|0x0f,0xb3); + outb_p(((pio+1)<<4)|0x0f,0xb3); inb(0x3f6); restore_flags(flags); } diff --git a/drivers/block/rz1000.c b/drivers/block/rz1000.c index ca417c6504e5..11f1dbd57421 100644 --- a/drivers/block/rz1000.c +++ b/drivers/block/rz1000.c @@ -45,8 +45,8 @@ void init_rz1000 (byte bus, byte fn) if ((rc = pcibios_read_config_word(bus, fn, 0x40, ®)) || (rc = pcibios_write_config_word(bus, fn, 0x40, reg & 0xdfff))) { - extern int ide_disallow_unmask; - ide_disallow_unmask = 1; + ide_hwifs[0].no_unmask = 1; + ide_hwifs[1].no_unmask = 1; ide_hwifs[0].serialized = 1; ide_pci_access_error (rc); printk("serialized, disabled unmasking\n"); diff --git a/drivers/block/triton.c b/drivers/block/triton.c index fe0a6dae7aa5..5829661170a1 100644 --- a/drivers/block/triton.c +++ b/drivers/block/triton.c @@ -95,6 +95,7 @@ * * And, yes, Intel Zappa boards really *do* use the Triton IDE ports. */ +#include #include #include #include @@ -116,7 +117,8 @@ * of drives which do not support mword2 DMA but which are * known to work fine with this interface under Linux. */ -const char *good_dma_drives[] = {"Micropolis 2112A"}; +const char *good_dma_drives[] = {"Micropolis 2112A", + "CONNER CTMA 4000"}; /* * Our Physical Region Descriptor (PRD) table should be large enough @@ -184,8 +186,13 @@ static int build_dmatable (ide_drive_t *drive) * is always composed of two adjacent physical 4kB pages rather * than two possibly non-adjacent physical 4kB pages. */ - if (bh == NULL) { /* paging requests have (rq->bh == NULL) */ + if (bh == NULL) { /* paging and tape requests have (rq->bh == NULL) */ addr = virt_to_bus (rq->buffer); +#ifdef CONFIG_BLK_DEV_IDETAPE + if (drive->media == ide_tape) + size = drive->tape.pc->request_transfer; + else +#endif /* CONFIG_BLK_DEV_IDETAPE */ size = rq->nr_sectors << 9; } else { /* group sequential buffers into one large buffer */ @@ -255,6 +262,10 @@ static int config_drive_for_dma (ide_drive_t *drive) * sector address using CHS or LBA. All that remains is to prepare for DMA * and then issue the actual read/write DMA/PIO command to the drive. * + * For ATAPI devices, we just prepare for DMA and return. The caller should + * then issue the packet command to the drive and call us again with + * ide_dma_begin afterwards. + * * Returns 0 if all went well. * Returns 1 if DMA read/write could not be started, in which case * the caller should revert to PIO for the current request. @@ -274,6 +285,17 @@ static int triton_dmaproc (ide_dma_action_t func, ide_drive_t *drive) reading = 0; case ide_dma_read: break; + case ide_dma_status_bad: + return ((inb(dma_base+2) & 7) != 4); /* verify good DMA status */ + case ide_dma_transferred: +#if 0 + return (number of bytes actually transferred); +#else + return (0); +#endif + case ide_dma_begin: + outb(inb(dma_base)|1, dma_base); /* begin DMA */ + return 0; default: printk("triton_dmaproc: unsupported func: %d\n", func); return 1; @@ -283,6 +305,10 @@ static int triton_dmaproc (ide_dma_action_t func, ide_drive_t *drive) 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 */ +#ifdef CONFIG_BLK_DEV_IDEATAPI + if (drive->media != ide_disk) + return 0; +#endif /* CONFIG_BLK_DEV_IDEATAPI */ 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 */ diff --git a/drivers/block/umc8672.c b/drivers/block/umc8672.c index 516a2bf85b46..2a8a583ae4cd 100644 --- a/drivers/block/umc8672.c +++ b/drivers/block/umc8672.c @@ -1,5 +1,5 @@ /* - * linux/drivers/block/umc8672.c Version 0.02 Feb 06, 1996 + * linux/drivers/block/umc8672.c Version 0.03 Feb 09, 1996 * * Copyright (C) 1995-1996 Linus Torvalds & author (see below) */ @@ -15,6 +15,7 @@ * This will get cleaned up in a subsequent release. * * Version 0.02 now configs/compiles separate from ide.c -ml + * Version 0.03 enhanced auto-tune, fix display bug */ /* @@ -46,10 +47,10 @@ #include #include #include "ide.h" +#include "ide_modes.h" /* - * The speeds will eventually become selectable using hdparm via ioctl's, - * but for now they are coded here: + * Default speeds. These can be changed with "auto-tune" and/or hdparm. */ #define UMC_DRIVE0 1 /* DOS measured drive speeds */ #define UMC_DRIVE1 1 /* 0 to 11 allowed */ @@ -57,7 +58,7 @@ #define UMC_DRIVE3 1 /* In case of crash reduce speed */ static byte current_speeds[4] = {UMC_DRIVE0, UMC_DRIVE1, UMC_DRIVE2, UMC_DRIVE3}; -static const byte pio_to_umc [5] = {0,3,6,10,11}; /* rough guesses */ +static const byte pio_to_umc [5] = {0,3,7,10,11}; /* rough guesses */ /* 0 1 2 3 4 5 6 7 8 9 10 11 */ static const byte speedtab [3][12] = { @@ -103,23 +104,16 @@ static void umc_set_speeds (byte speeds[]) restore_flags(flags); printk ("umc8672: drive speeds [0 to 11]: %d %d %d %d\n", - speeds[0], speeds[1], speeds[2], speeds[4]); + speeds[0], speeds[1], speeds[2], speeds[3]); } static void tune_umc (ide_drive_t *drive, byte pio) { - if (pio == 255) { /* auto-tune */ - struct hd_driveid *id = drive->id; - pio = id->tPIO; - if (id->field_valid & 0x02) { - if (id->eide_pio_modes & 0x01) - pio = 3; - if (id->eide_pio_modes & 0x02) - pio = 4; - } - } + if (pio == 255) + pio = ide_get_best_pio_mode(drive); if (pio > 4) pio = 4; + current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio]; umc_set_speeds (current_speeds); } diff --git a/drivers/cdrom/Config.in b/drivers/cdrom/Config.in index 6d6ceea62b14..b1a0de6eb67b 100644 --- a/drivers/cdrom/Config.in +++ b/drivers/cdrom/Config.in @@ -19,4 +19,8 @@ tristate 'Sony CDU535 CDROM support' CONFIG_CDU535 tristate 'Goldstar R420 CDROM support' CONFIG_GSCD tristate 'Philips/LMS CM206 CDROM support' CONFIG_CM206 tristate 'Optics Storage DOLPHIN 8000AT CDROM support' CONFIG_OPTCD -tristate 'Sanyo H94A CDROM support' CONFIG_SJCD +tristate 'Sanyo CDR-H94A CDROM support' CONFIG_SJCD +bool 'Soft configurable cdrom interface card support' CONFIG_CDI_INIT +if [ "$CONFIG_CDI_INIT" = "y" ]; then + tristate 'ISP16/MAD16/Mozart soft configurable cdrom interface support' CONFIG_ISP16_CDI +fi diff --git a/drivers/cdrom/Makefile b/drivers/cdrom/Makefile index 13bbd50a3d4b..f2b6ac432473 100644 --- a/drivers/cdrom/Makefile +++ b/drivers/cdrom/Makefile @@ -106,10 +106,24 @@ endif #CONFIG_OPTCD ifeq ($(CONFIG_SJCD),y) L_OBJS += sjcd.o -#else -# ifeq ($(CONFIG_SJCD),m) -# M_OBJS += sjcd.o -# endif +else + ifeq ($(CONFIG_SJCD),m) + M_OBJS += sjcd.o + endif endif #CONFIG_SJCD +ifeq ($(CONFIG_CDI_INIT),y) +L_OBJS += cdi.o +endif #CONFIG_CDI_INIT +ifeq ($(CONFIG_ISP16_CDI),y) +L_OBJS += isp16.o +else +# ifeq ($(CONFIG_CDI_INIT),m) +# M_OBJS += cdi.o +# endif + ifeq ($(CONFIG_ISP16_CDI),m) + M_OBJS += isp16.o + endif +endif #CONFIG_ISP16_CDI + include $(TOPDIR)/Rules.make diff --git a/drivers/cdrom/cdi.c b/drivers/cdrom/cdi.c new file mode 100644 index 000000000000..c45056d2e667 --- /dev/null +++ b/drivers/cdrom/cdi.c @@ -0,0 +1,49 @@ +/* -- cdi.c + * + * Initialisation of software configurable cdrom interface + * cards goes here. + * + * Copyright (c) 1996 Eric van der Maarel + * + * Version 0.1 + * + * History: + * 0.1 First release. Only support for ISP16/MAD16/Mozart. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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. + * + */ + +#include +#include /* where the proto type of cdi_init() is */ +#ifdef CONFIG_ISP16_CDI +#include +#endif CONFIG_ISP16_CDI + +/* + * Cdrom interface configuration. + */ +int +cdi_init(void) +{ + int ret_val = -1; + +#ifdef CONFIG_ISP16_CDI + ret_val &= isp16_init(); +#endif CONFIG_ISP16_CDI + + return(ret_val); +} + diff --git a/drivers/cdrom/isp16.c b/drivers/cdrom/isp16.c new file mode 100644 index 000000000000..36aa45315a56 --- /dev/null +++ b/drivers/cdrom/isp16.c @@ -0,0 +1,315 @@ +/* -- ISP16 cdrom detection and configuration + * + * Copyright (c) 1995,1996 Eric van der Maarel + * + * Version 0.6 + * + * History: + * 0.5 First release. + * Was included in the sjcd and optcd cdrom drivers. + * 0.6 First "stand-alone" version. + * Removed sound configuration. + * Added "module" support. + * + * Detect cdrom interface on ISP16 sound card. + * Configure cdrom 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. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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. + * + */ + +#define ISP16_VERSION_MAJOR 0 +#define ISP16_VERSION_MINOR 6 + +#ifdef MODULE +#include +#endif /* MODULE */ + +#include +#include +#include +#include +#include +#include + +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 short isp16_type; /* dependent on type of interface card */ +static u_char isp16_ctrl; +static u_short isp16_enable_port; + +static int isp16_cdrom_base = ISP16_CDROM_IO_BASE; +static int isp16_cdrom_irq = ISP16_CDROM_IRQ; +static int isp16_cdrom_dma = ISP16_CDROM_DMA; +static char *isp16_cdrom_type = ISP16_CDROM_TYPE; +#ifdef MODULE +int init_module(void); +void cleanup_module(void); +#endif + +#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)) + + +void +isp16_setup(char *str, int *ints) +{ + if ( ints[0] > 0 ) + isp16_cdrom_base = ints[1]; + if ( ints[0] > 1 ) + isp16_cdrom_irq = ints[2]; + if ( ints[0] > 2 ) + isp16_cdrom_dma = ints[3]; + if ( str ) + isp16_cdrom_type = str; +} + +/* + * ISP16 initialisation. + * + */ +int +isp16_init(void) +{ + u_char expected_drive; + + printk("ISP16: configuration cdrom interface, version %d.%d.\n", ISP16_VERSION_MAJOR, + ISP16_VERSION_MINOR); + + if ( !strcmp(isp16_cdrom_type, "noisp16") ) { + printk("ISP16: no cdrom interface configured.\n"); + return(0); + } + + if (check_region(ISP16_IO_BASE, ISP16_IO_SIZE)) { + printk("ISP16: i/o ports already in use.\n"); + return(-EIO); + } + + if ( (isp16_type=isp16_detect()) < 0 ) { + printk("ISP16: no cdrom interface found.\n"); + return(-EIO); + } + + printk("ISP16: cdrom interface (with OPTi 82C92%d chip) detected.\n", + (isp16_type==2) ? 9 : 8); + + if ( !strcmp(isp16_cdrom_type, "Sanyo") ) + expected_drive = (isp16_type ? ISP16_SANYO1 : ISP16_SANYO0); + else if ( !strcmp(isp16_cdrom_type, "Sony") ) + expected_drive = ISP16_SONY; + else if ( !strcmp(isp16_cdrom_type, "Panasonic") ) + expected_drive = (isp16_type ? ISP16_PANASONIC1 : ISP16_PANASONIC0); + else if ( !strcmp(isp16_cdrom_type, "Mitsumi") ) + expected_drive = ISP16_MITSUMI; + else { + printk("ISP16: %s not supported by cdrom interface.\n", isp16_cdrom_type); + return(-EIO); + } + + if ( isp16_cdi_config(isp16_cdrom_base, expected_drive, + isp16_cdrom_irq, isp16_cdrom_dma ) < 0) { + printk("ISP16: cdrom interface has not been properly configured.\n"); + return(-EIO); + } + printk("ISP16: cdrom interface set up with io base 0x%03X, irq %d, dma %d," + " type %s.\n", isp16_cdrom_base, isp16_cdrom_irq, isp16_cdrom_dma, + isp16_cdrom_type); + return(0); +} + +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("ISP16: 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("ISP16: base address 0x%03X not supported by cdrom interface.\n", + base); + return(-1); + } + switch (irq) { + case 0: irq_code = ISP16_IRQ_X; break; /* disable irq */ + case 5: irq_code = ISP16_IRQ_5; + printk("ISP16: irq 5 shouldn't be used by cdrom interface," + " due to possible conflicts with the sound card.\n"); + break; + case 7: irq_code = ISP16_IRQ_7; + printk("ISP16: irq 7 shouldn't be used by cdrom interface," + " due to possible conflicts with the sound card.\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("ISP16: irq %d not supported by cdrom interface.\n", irq ); + return(-1); + } + switch (dma) { + case 0: dma_code = ISP16_DMA_X; break; /* disable dma */ + case 1: printk("ISP16: dma 1 cannot be used by cdrom interface," + " due to conflict with the sound card.\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("ISP16: dma %d not supported by cdrom interface.\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("ISP16: drive type (code 0x%02X) not supported by cdrom" + " interface.\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); +} + +#ifdef MODULE +int init_module(void) +{ + return isp16_init(); +} + +void cleanup_module(void) +{ + release_region(ISP16_IO_BASE, ISP16_IO_SIZE); + printk("ISP16: module released.\n"); +} +#endif /* MODULE */ diff --git a/drivers/cdrom/optcd.c b/drivers/cdrom/optcd.c index 4f5d52ea5adf..3dbba4230650 100644 --- a/drivers/cdrom/optcd.c +++ b/drivers/cdrom/optcd.c @@ -5,9 +5,7 @@ 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) and - Vadim Model (vadim@cecmow.enet.dec.com). + by Eberhard Moenkeberg (emoenke@gwdg.de). 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 @@ -71,9 +69,6 @@ #include #include -#ifdef PROBE_ISP16 -#include "optcd_isp16.h" /* optional ISP16 detection/configuration */ -#endif /* Debug support */ @@ -1960,51 +1955,13 @@ static struct file_operations opt_fops = { }; -/* 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) { if (ints[0] > 0) optcd_port = ints[1]; - if (!strcmp(str ,"noisp16")) - skip_isp16_init = 1; } - -#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) @@ -2021,11 +1978,6 @@ int optcd_init(void) return -EIO; } -#ifdef PROBE_ISP16 - if (!probe_isp16()) - return -EIO; -#endif - if (!reset_drive()) { printk("optcd: drive at 0x%x not ready\n", optcd_port); return -EIO; diff --git a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c index 9273cb8f4e46..fc57f801a2e7 100644 --- a/drivers/cdrom/sjcd.c +++ b/drivers/cdrom/sjcd.c @@ -1,23 +1,16 @@ /* -- sjcd.c * - * Sanyo CD-ROM device driver implementation, Version 1.5 + * Sanyo CD-ROM device driver implementation, Version 1.6 * Copyright (C) 1995 Vadim V. Model * * model@cecmow.enet.dec.com * vadim@rbrf.ru * vadim@ipsun.ras.ru * - * ISP16 detection and configuration. - * Copyright (C) 1995 Eric van der Maarel (maarel@marin.nl) - * and Vadim Model (vadim@cecmow.enet.dec.com) - * * * This driver is based on pre-works by Eberhard Moenkeberg (emoenke@gwdg.de); * it was developed under use of mcd.c from Martin Harriss, with help of - * Eric van der Maarel (maarel@marin.nl). - * - * ISP16 detection and configuration by Eric van der Maarel (maarel@marin.nl). - * Sound configuration by Vadim V. Model (model@cecmow.enet.dec.com) + * Eric van der Maarel (H.T.M.v.d.Maarel@marin.nl). * * It is planned to include these routines into sbpcd.c later - to make * a "mixed use" on one cable possible for all kinds of drives which use @@ -48,10 +41,19 @@ * 1.4 MSS Sound support!! Listen to a CD through the speakers. * 1.5 Module support and bugfixes. * Tray locking. + * 1.6 Removed ISP16 code from this driver. + * Allow only to set io base address on comand line: sjcd= + * Changes to Documentation/cdrom/sjcd + * Added cleanup after any error in the initialisation. * */ +#define SJCD_VERSION_MAJOR 1 +#define SJCD_VERSION_MINOR 6 + +#ifdef MODULE #include +#endif /* MODULE */ #include #include @@ -72,65 +74,7 @@ #include #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 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 -}; #define SJCD_BUF_SIZ 32 /* cdr-h94a has internal 64K buffer */ @@ -161,9 +105,7 @@ static int sjcd_open_count; static int sjcd_audio_status; static struct sjcd_play_msf sjcd_playing; -static int sjcd_port = SJCD_BASE_ADDR; -static int sjcd_irq = SJCD_INTR_NR; -static int sjcd_dma = SJCD_DMA_NR; +static int sjcd_base = SJCD_BASE_ADDR; static struct wait_queue *sjcd_waitq = NULL; @@ -207,18 +149,16 @@ static struct timer_list sjcd_delay_timer = { NULL, NULL, 0, 0, NULL }; #define CLEAR_TIMER del_timer( &sjcd_delay_timer ) +static int sjcd_cleanup(void); + /* * Set up device, i.e., use command line data to set - * base address, irq and dma. + * base address. */ void sjcd_setup( char *str, int *ints ) { if (ints[0] > 0) - sjcd_port = ints[1]; - if (ints[0] > 1) - sjcd_irq = ints[2]; - if (ints[0] > 2) - sjcd_dma = ints[3]; + sjcd_base = ints[1]; } /* @@ -253,7 +193,7 @@ static void hsg2msf( long hsg, struct msf *msf ){ */ static void sjcd_send_cmd( unsigned char cmd ){ #if defined( SJCD_TRACE ) - printk( "sjcd: send_cmd( 0x%x )\n", cmd ); + printk( "SJCD: send_cmd( 0x%x )\n", cmd ); #endif outb( cmd, SJCDPORT( 0 ) ); sjcd_command_is_in_progress = 1; @@ -266,7 +206,7 @@ static void sjcd_send_cmd( unsigned char cmd ){ */ static void sjcd_send_1_cmd( unsigned char cmd, unsigned char a ){ #if defined( SJCD_TRACE ) - printk( "sjcd: send_1_cmd( 0x%x, 0x%x )\n", cmd, a ); + printk( "SJCD: send_1_cmd( 0x%x, 0x%x )\n", cmd, a ); #endif outb( cmd, SJCDPORT( 0 ) ); outb( a, SJCDPORT( 0 ) ); @@ -281,7 +221,7 @@ static void sjcd_send_1_cmd( unsigned char cmd, unsigned char a ){ static void sjcd_send_4_cmd( unsigned char cmd, unsigned char a, unsigned char b, unsigned char c, unsigned char d ){ #if defined( SJCD_TRACE ) - printk( "sjcd: send_4_cmd( 0x%x )\n", cmd ); + printk( "SJCD: send_4_cmd( 0x%x )\n", cmd ); #endif outb( cmd, SJCDPORT( 0 ) ); outb( a, SJCDPORT( 0 ) ); @@ -298,7 +238,7 @@ static void sjcd_send_4_cmd( unsigned char cmd, unsigned char a, */ static void sjcd_send_6_cmd( unsigned char cmd, struct sjcd_play_msf *pms ){ #if defined( SJCD_TRACE ) - printk( "sjcd: send_long_cmd( 0x%x )\n", cmd ); + printk( "SJCD: send_long_cmd( 0x%x )\n", cmd ); #endif outb( cmd, SJCDPORT( 0 ) ); outb( pms->start.min, SJCDPORT( 0 ) ); @@ -365,7 +305,7 @@ static void sjcd_load_status( void ){ */ if( sjcd_media_is_changed ) sjcd_toc_uptodate = 0; #if defined( SJCD_TRACE ) - printk( "sjcd: status %02x.%02x loaded.\n", + printk( "SJCD: status %02x.%02x loaded.\n", ( int )sjcd_completion_status, ( int )sjcd_completion_error ); #endif } @@ -429,7 +369,7 @@ static int sjcd_wait_for_status( void ){ sleep_on( &sjcd_waitq ); #if defined( SJCD_DIAGNOSTIC ) || defined ( SJCD_TRACE ) if( sjcd_status_timeout <= 0 ) - printk( "sjcd: Error Wait For Status.\n" ); + printk( "SJCD: Error Wait For Status.\n" ); #endif return( sjcd_status_timeout ); } @@ -437,7 +377,7 @@ static int sjcd_wait_for_status( void ){ static int sjcd_receive_status( void ){ int i; #if defined( SJCD_TRACE ) - printk( "sjcd: receive_status\n" ); + printk( "SJCD: receive_status\n" ); #endif /* * Wait a bit for status available. @@ -445,10 +385,10 @@ static int sjcd_receive_status( void ){ for( i = 200; i-- && ( sjcd_check_status() == 0 ); ); if( i < 0 ){ #if defined( SJCD_TRACE ) - printk( "sjcd: long wait for status\n" ); + printk( "SJCD: long wait for status\n" ); #endif if( sjcd_wait_for_status() <= 0 ) - printk( "sjcd: Timeout when read status.\n" ); + printk( "SJCD: Timeout when read status.\n" ); else i = 0; } return( i ); @@ -459,7 +399,7 @@ static int sjcd_receive_status( void ){ */ static void sjcd_get_status( void ){ #if defined( SJCD_TRACE ) - printk( "sjcd: get_status\n" ); + printk( "SJCD: get_status\n" ); #endif sjcd_send_cmd( SCMD_GET_STATUS ); sjcd_receive_status(); @@ -470,10 +410,10 @@ static void sjcd_get_status( void ){ */ static int sjcd_disk_change( kdev_t full_dev ){ #if 0 - printk( "sjcd_disk_change( 0x%x )\n", full_dev ); + printk( "SJCD: sjcd_disk_change( 0x%x )\n", full_dev ); #endif if( MINOR( full_dev ) > 0 ){ - printk( "sjcd: request error: invalid device minor.\n" ); + printk( "SJCD: request error: invalid device minor.\n" ); return 0; } if( !sjcd_command_is_in_progress ) @@ -493,7 +433,7 @@ static int sjcd_update_toc( void ){ struct sjcd_hw_disk_info info; int i; #if defined( SJCD_TRACE ) - printk( "sjcd: update toc:\n" ); + printk( "SJCD: update toc:\n" ); #endif /* * check to see if we need to do anything @@ -507,27 +447,27 @@ static int sjcd_update_toc( void ){ sjcd_receive_status(); if( !sjcd_status_valid ){ - printk( "cannot load status.\n" ); + printk( "SJCD: cannot load status.\n" ); return( -1 ); } if( !sjcd_media_is_available ){ - printk( "no disk in drive\n" ); + printk( "SJCD: no disk in drive\n" ); return( -1 ); } if( !sjcd_command_failed ){ if( sjcd_load_response( &info, sizeof( info ) ) != 0 ){ - printk( "cannot load response about TOC start.\n" ); + printk( "SJCD: cannot load response about TOC start.\n" ); return( -1 ); } sjcd_first_track_no = bcd2bin( info.un.track_no ); } else { - printk( "get first failed\n" ); + printk( "SJCD: get first failed\n" ); return( -1 ); } #if defined( SJCD_TRACE ) - printk( "TOC start 0x%02x ", sjcd_first_track_no ); + printk( "SJCD: TOC start 0x%02x ", sjcd_first_track_no ); #endif /* * Get the TOC finish information. @@ -536,27 +476,27 @@ static int sjcd_update_toc( void ){ sjcd_receive_status(); if( !sjcd_status_valid ){ - printk( "cannot load status.\n" ); + printk( "SJCD: cannot load status.\n" ); return( -1 ); } if( !sjcd_media_is_available ){ - printk( "no disk in drive\n" ); + printk( "SJCD: no disk in drive\n" ); return( -1 ); } if( !sjcd_command_failed ){ if( sjcd_load_response( &info, sizeof( info ) ) != 0 ){ - printk( "cannot load response about TOC finish.\n" ); + printk( "SJCD: cannot load response about TOC finish.\n" ); return( -1 ); } sjcd_last_track_no = bcd2bin( info.un.track_no ); } else { - printk( "get last failed\n" ); + printk( "SJCD: get last failed\n" ); return( -1 ); } #if defined( SJCD_TRACE ) - printk( "TOC finish 0x%02x ", sjcd_last_track_no ); + printk( "SJCD: TOC finish 0x%02x ", sjcd_last_track_no ); #endif for( i = sjcd_first_track_no; i <= sjcd_last_track_no; i++ ){ /* @@ -566,23 +506,23 @@ static int sjcd_update_toc( void ){ sjcd_receive_status(); if( !sjcd_status_valid ){ - printk( "cannot load status.\n" ); + printk( "SJCD: cannot load status.\n" ); return( -1 ); } if( !sjcd_media_is_available ){ - printk( "no disk in drive\n" ); + printk( "SJCD: no disk in drive\n" ); return( -1 ); } if( !sjcd_command_failed ){ if( sjcd_load_response( &sjcd_table_of_contents[ i ], sizeof( struct sjcd_hw_disk_info ) ) != 0 ){ - printk( "cannot load info for %d track\n", i ); + printk( "SJCD: cannot load info for %d track\n", i ); return( -1 ); } } else { - printk( "get info %d failed\n", i ); + printk( "SJCD: get info %d failed\n", i ); return( -1 ); } } @@ -594,29 +534,29 @@ static int sjcd_update_toc( void ){ sjcd_receive_status(); if( !sjcd_status_valid ){ - printk( "cannot load status.\n" ); + printk( "SJCD: cannot load status.\n" ); return( -1 ); } if( !sjcd_media_is_available ){ - printk( "no disk in drive\n" ); + printk( "SJCD: no disk in drive\n" ); return( -1 ); } if( !sjcd_command_failed ){ if( sjcd_load_response( &info, sizeof( info ) ) != 0 ){ - printk( "cannot load response about disk size.\n" ); + printk( "SJCD: cannot load response about disk size.\n" ); return( -1 ); } sjcd_disk_length.min = info.un.track_msf.min; sjcd_disk_length.sec = info.un.track_msf.sec; sjcd_disk_length.frame = info.un.track_msf.frame; } else { - printk( "get size failed\n" ); + printk( "SJCD: get size failed\n" ); return( 1 ); } #if defined( SJCD_TRACE ) - printk( "(%02x:%02x.%02x)\n", sjcd_disk_length.min, + printk( "SJCD: (%02x:%02x.%02x)\n", sjcd_disk_length.min, sjcd_disk_length.sec, sjcd_disk_length.frame ); #endif return( 0 ); @@ -628,7 +568,7 @@ static int sjcd_update_toc( void ){ static int sjcd_get_q_info( struct sjcd_hw_qinfo *qp ){ int s; #if defined( SJCD_TRACE ) - printk( "sjcd: load sub q\n" ); + printk( "SJCD: load sub q\n" ); #endif sjcd_send_cmd( SCMD_GET_QINFO ); s = sjcd_receive_status(); @@ -677,7 +617,7 @@ static int sjcd_play( struct sjcd_play_msf *mp ){ */ static int sjcd_tray_close( void ){ #if defined( SJCD_TRACE ) - printk( "sjcd: tray_close\n" ); + printk( "SJCD: tray_close\n" ); #endif sjcd_send_cmd( SCMD_CLOSE_TRAY ); return( sjcd_receive_status() ); @@ -685,7 +625,7 @@ static int sjcd_tray_close( void ){ static int sjcd_tray_lock( void ){ #if defined( SJCD_TRACE ) - printk( "sjcd: tray_lock\n" ); + printk( "SJCD: tray_lock\n" ); #endif sjcd_send_cmd( SCMD_LOCK_TRAY ); return( sjcd_receive_status() ); @@ -693,7 +633,7 @@ static int sjcd_tray_lock( void ){ static int sjcd_tray_unlock( void ){ #if defined( SJCD_TRACE ) - printk( "sjcd: tray_unlock\n" ); + printk( "SJCD: tray_unlock\n" ); #endif sjcd_send_cmd( SCMD_UNLOCK_TRAY ); return( sjcd_receive_status() ); @@ -701,7 +641,7 @@ static int sjcd_tray_unlock( void ){ static int sjcd_tray_open( void ){ #if defined( SJCD_TRACE ) - printk( "sjcd: tray_open\n" ); + printk( "SJCD: tray_open\n" ); #endif sjcd_send_cmd( SCMD_EJECT_TRAY ); return( sjcd_receive_status() ); @@ -713,7 +653,7 @@ static int sjcd_tray_open( void ){ static int sjcd_ioctl( struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg ){ #if defined( SJCD_TRACE ) - printk( "sjcd:ioctl\n" ); + printk( "SJCD:ioctl\n" ); #endif if( ip == NULL ) return( -EINVAL ); @@ -725,14 +665,14 @@ static int sjcd_ioctl( struct inode *ip, struct file *fp, switch( cmd ){ case CDROMSTART:{ #if defined( SJCD_TRACE ) - printk( "sjcd: ioctl: start\n" ); + printk( "SJCD: ioctl: start\n" ); #endif return( 0 ); } case CDROMSTOP:{ #if defined( SJCD_TRACE ) - printk( "sjcd: ioctl: stop\n" ); + printk( "SJCD: ioctl: stop\n" ); #endif sjcd_send_cmd( SCMD_PAUSE ); ( void )sjcd_receive_status(); @@ -743,7 +683,7 @@ static int sjcd_ioctl( struct inode *ip, struct file *fp, case CDROMPAUSE:{ struct sjcd_hw_qinfo q_info; #if defined( SJCD_TRACE ) - printk( "sjcd: ioctl: pause\n" ); + printk( "SJCD: ioctl: pause\n" ); #endif if( sjcd_audio_status == CDROM_AUDIO_PLAY ){ sjcd_send_cmd( SCMD_PAUSE ); @@ -760,7 +700,7 @@ static int sjcd_ioctl( struct inode *ip, struct file *fp, case CDROMRESUME:{ #if defined( SJCD_TRACE ) - printk( "sjcd: ioctl: resume\n" ); + printk( "SJCD: ioctl: resume\n" ); #endif if( sjcd_audio_status == CDROM_AUDIO_PAUSED ){ /* @@ -779,7 +719,7 @@ static int sjcd_ioctl( struct inode *ip, struct file *fp, case CDROMPLAYTRKIND:{ struct cdrom_ti ti; int s; #if defined( SJCD_TRACE ) - printk( "sjcd: ioctl: playtrkind\n" ); + printk( "SJCD: ioctl: playtrkind\n" ); #endif if( ( s = verify_area( VERIFY_READ, (void *)arg, sizeof( ti ) ) ) == 0 ){ memcpy_fromfs( &ti, (void *)arg, sizeof( ti ) ); @@ -805,7 +745,7 @@ static int sjcd_ioctl( struct inode *ip, struct file *fp, case CDROMPLAYMSF:{ struct cdrom_msf sjcd_msf; int s; #if defined( SJCD_TRACE ) - printk( "sjcd: ioctl: playmsf\n" ); + printk( "SJCD: ioctl: playmsf\n" ); #endif if( ( s = verify_area( VERIFY_READ, (void *)arg, sizeof( sjcd_msf ) ) ) == 0 ){ if( sjcd_audio_status == CDROM_AUDIO_PLAY ){ @@ -834,7 +774,7 @@ static int sjcd_ioctl( struct inode *ip, struct file *fp, case CDROMREADTOCHDR:{ struct cdrom_tochdr toc_header; int s; #if defined (SJCD_TRACE ) - printk( "sjcd: ioctl: readtocheader\n" ); + printk( "SJCD: ioctl: readtocheader\n" ); #endif if( ( s = verify_area( VERIFY_WRITE, (void *)arg, sizeof( toc_header ) ) ) == 0 ){ toc_header.cdth_trk0 = sjcd_first_track_no; @@ -847,7 +787,7 @@ static int sjcd_ioctl( struct inode *ip, struct file *fp, case CDROMREADTOCENTRY:{ struct cdrom_tocentry toc_entry; int s; #if defined( SJCD_TRACE ) - printk( "sjcd: ioctl: readtocentry\n" ); + printk( "SJCD: ioctl: readtocentry\n" ); #endif if( ( s = verify_area( VERIFY_WRITE, (void *)arg, sizeof( toc_entry ) ) ) == 0 ){ struct sjcd_hw_disk_info *tp; @@ -882,7 +822,7 @@ static int sjcd_ioctl( struct inode *ip, struct file *fp, case CDROMSUBCHNL:{ struct cdrom_subchnl subchnl; int s; #if defined( SJCD_TRACE ) - printk( "sjcd: ioctl: subchnl\n" ); + printk( "SJCD: ioctl: subchnl\n" ); #endif if( ( s = verify_area( VERIFY_WRITE, (void *)arg, sizeof( subchnl ) ) ) == 0 ){ struct sjcd_hw_qinfo q_info; @@ -919,7 +859,7 @@ static int sjcd_ioctl( struct inode *ip, struct file *fp, case CDROMVOLCTRL:{ struct cdrom_volctrl vol_ctrl; int s; #if defined( SJCD_TRACE ) - printk( "sjcd: ioctl: volctrl\n" ); + printk( "SJCD: ioctl: volctrl\n" ); #endif if( ( s = verify_area( VERIFY_READ, (void *)arg, sizeof( vol_ctrl ) ) ) == 0 ){ unsigned char dummy[ 4 ]; @@ -935,7 +875,7 @@ static int sjcd_ioctl( struct inode *ip, struct file *fp, case CDROMEJECT:{ #if defined( SJCD_TRACE ) - printk( "sjcd: ioctl: eject\n" ); + printk( "SJCD: ioctl: eject\n" ); #endif if( !sjcd_command_is_in_progress ){ sjcd_tray_unlock(); @@ -949,7 +889,7 @@ static int sjcd_ioctl( struct inode *ip, struct file *fp, case 0xABCD:{ int s; #if defined( SJCD_TRACE ) - printk( "sjcd: ioctl: statistic\n" ); + printk( "SJCD: ioctl: statistic\n" ); #endif if( ( s = verify_area( VERIFY_WRITE, (void *)arg, sizeof( statistic ) ) ) == 0 ) memcpy_tofs( (void *)arg, &statistic, sizeof( statistic ) ); @@ -982,7 +922,7 @@ static void sjcd_invalidate_buffers( void ){ static void sjcd_transfer( void ){ #if defined( SJCD_TRACE ) - printk( "sjcd: transfer:\n" ); + printk( "SJCD: transfer:\n" ); #endif if( CURRENT_IS_VALID ){ while( CURRENT->nr_sectors ){ @@ -1001,7 +941,7 @@ static void sjcd_transfer( void ){ if( nr_sectors > CURRENT->nr_sectors ) nr_sectors = CURRENT->nr_sectors; #if defined( SJCD_TRACE ) - printk( "copy out\n" ); + printk( "SJCD: copy out\n" ); #endif memcpy( CURRENT->buffer, sjcd_buf + offs, nr_sectors * 512 ); CURRENT->nr_sectors -= nr_sectors; @@ -1014,7 +954,7 @@ static void sjcd_transfer( void ){ } } #if defined( SJCD_TRACE ) - printk( "sjcd: transfer: done\n" ); + printk( "SJCD: transfer: done\n" ); #endif } @@ -1127,7 +1067,7 @@ static void sjcd_poll( void ){ msf.end.min = 0; msf.end.sec = 0; msf.end.frame = sjcd_read_count = SJCD_BUF_SIZ; #if defined( SJCD_TRACE ) - printk( "---reading msf-address %x:%x:%x %x:%x:%x\n", + printk( "SJCD: ---reading msf-address %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( "sjcd_next_bn:%x buf_in:%x buf_out:%x buf_bn:%x\n", \ @@ -1170,7 +1110,7 @@ static void sjcd_poll( void ){ if( !sjcd_status_valid || sjcd_command_failed ){ #if defined( SJCD_TRACE ) - printk( "sjcd: read block %d failed, maybe audio disk? Giving up\n", + printk( "SJCD: read block %d failed, maybe audio disk? Giving up\n", sjcd_next_bn ); #endif if( CURRENT_IS_VALID ) end_request( 0 ); @@ -1305,12 +1245,12 @@ static void sjcd_poll( void ){ } default: - printk( "sjcd_poll: invalid state %d\n", sjcd_transfer_state ); + printk( "SJCD: poll: invalid state %d\n", sjcd_transfer_state ); return; } if( --sjcd_transfer_timeout == 0 ){ - printk( "sjcd: timeout in state %d\n", sjcd_transfer_state ); + printk( "SJCD: timeout in state %d\n", sjcd_transfer_state ); while( CURRENT_IS_VALID ) end_request( 0 ); sjcd_send_cmd( SCMD_STOP ); sjcd_transfer_state = SJCD_S_IDLE; @@ -1326,7 +1266,7 @@ static void sjcd_poll( void ){ static void do_sjcd_request( void ){ #if defined( SJCD_TRACE ) - printk( "sjcd: do_sjcd_request(%ld+%ld)\n", + printk( "SJCD: do_sjcd_request(%ld+%ld)\n", CURRENT->sector, CURRENT->nr_sectors ); #endif sjcd_transfer_is_active = 1; @@ -1344,7 +1284,7 @@ static void do_sjcd_request( void ){ if( sjcd_transfer_state == SJCD_S_IDLE ){ if( !sjcd_toc_uptodate ){ if( sjcd_update_toc() < 0 ){ - printk( "sjcd: transfer: discard\n" ); + printk( "SJCD: transfer: discard\n" ); while( CURRENT_IS_VALID ) end_request( 0 ); break; } @@ -1396,22 +1336,22 @@ int sjcd_open( struct inode *ip, struct file *fp ){ if( !sjcd_status_valid ) sjcd_get_status(); if( !sjcd_status_valid ){ #if defined( SJCD_DIAGNOSTIC ) - printk( "sjcd: open: timed out when check status.\n" ); + printk( "SJCD: open: timed out when check status.\n" ); #endif return( -EIO ); } else if( !sjcd_media_is_available ){ #if defined( SJCD_DIAGNOSTIC ) - printk("sjcd: open: no disk in drive\n"); + printk("SJCD: open: no disk in drive\n"); #endif if( !sjcd_door_closed ){ sjcd_door_was_open = 1; #if defined( SJCD_TRACE ) - printk("sjcd: open: close the tray\n"); + printk("SJCD: open: close the tray\n"); #endif s = sjcd_tray_close(); if( s < 0 || !sjcd_status_valid || sjcd_command_failed ){ #if defined( SJCD_DIAGNOSTIC ) - printk("sjcd: open: tray close attempt failed\n"); + printk("SJCD: open: tray close attempt failed\n"); #endif return( -EIO ); } @@ -1423,15 +1363,17 @@ int sjcd_open( struct inode *ip, struct file *fp ){ s = sjcd_tray_lock(); if( s < 0 || !sjcd_status_valid || sjcd_command_failed ){ #if defined( SJCD_DIAGNOSTIC ) - printk("sjcd: open: tray lock attempt failed\n"); + printk("SJCD: open: tray lock attempt failed\n"); #endif return( -EIO ); } #if defined( SJCD_TRACE ) - printk( "sjcd: open: done\n" ); + printk( "SJCD: open: done\n" ); #endif } +#ifdef MODULE MOD_INC_USE_COUNT; +#endif ++sjcd_open_count; return( 0 ); } @@ -1443,9 +1385,11 @@ static void sjcd_release( struct inode *inode, struct file *file ){ int s; #if defined( SJCD_TRACE ) - printk( "sjcd: release\n" ); + printk( "SJCD: release\n" ); #endif +#ifdef MODULE MOD_DEC_USE_COUNT; +#endif if( --sjcd_open_count == 0 ){ sjcd_invalidate_buffers(); sync_dev( inode->i_rdev ); @@ -1453,14 +1397,14 @@ static void sjcd_release( struct inode *inode, struct file *file ){ s = sjcd_tray_unlock(); if( s < 0 || !sjcd_status_valid || sjcd_command_failed ){ #if defined( SJCD_DIAGNOSTIC ) - printk("sjcd: release: tray unlock attempt failed.\n"); + printk("SJCD: release: tray unlock attempt failed.\n"); #endif } if( sjcd_door_was_open ){ s = sjcd_tray_open(); if( s < 0 || !sjcd_status_valid || sjcd_command_failed ){ #if defined( SJCD_DIAGNOSTIC ) - printk("sjcd: release: tray unload attempt failed.\n"); + printk("SJCD: release: tray unload attempt failed.\n"); #endif } } @@ -1503,40 +1447,25 @@ static struct { int sjcd_init( void ){ int i; - if ( (isp16_type=isp16_detect()) < 0 ) - printk( "No ISP16 cdrom interface found.\n" ); - else { - u_char expected_drive; - - printk( "ISP16 cdrom interface (with OPTi 82C92%s chip) detected.\n", - (isp16_type==2)?"9":"8" ); - - printk( "ISP16 sound configuration.\n" ); - isp16_sound_config(); - - expected_drive = (isp16_type?ISP16_SANYO1:ISP16_SANYO0); - - if ( isp16_cdi_config( sjcd_port, expected_drive, sjcd_irq, sjcd_dma ) < 0 ) { - printk( "ISP16 cdrom interface has not been properly configured.\n" ); - return( -EIO ); - } - } + printk("SJCD: Sanyo CDR-H94A cdrom driver version %d.%d.\n", SJCD_VERSION_MAJOR, + SJCD_VERSION_MINOR); #if defined( SJCD_TRACE ) - printk( "sjcd=0x%x,%d: ", sjcd_port, sjcd_irq ); + printk("SJCD: sjcd=0x%x: ", sjcd_base); #endif if( register_blkdev( MAJOR_NR, "sjcd", &sjcd_fops ) != 0 ){ - printk( "Unable to get major %d for Sanyo CD-ROM\n", MAJOR_NR ); + printk( "SJCD: Unable to get major %d for Sanyo CD-ROM\n", MAJOR_NR ); return( -EIO ); } blk_dev[ MAJOR_NR ].request_fn = DEVICE_REQUEST; read_ahead[ MAJOR_NR ] = 4; - if( check_region( sjcd_port, 4 ) ){ - printk( "Init failed, I/O port (%X) is already in use\n", - sjcd_port ); + if( check_region( sjcd_base, 4 ) ){ + printk( "SJCD: Init failed, I/O port (%X) is already in use\n", + sjcd_base ); + sjcd_cleanup(); return( -EIO ); } @@ -1544,9 +1473,9 @@ int sjcd_init( void ){ * Check for card. Since we are booting now, we can't use standard * wait algorithm. */ - printk( "Sanyo: Resetting: " ); + printk( "SJCD: Resetting: " ); sjcd_send_cmd( SCMD_RESET ); - for( i = 1000; i-- > 0 && !sjcd_status_valid; ){ + for( i = 1000; i > 0 && !sjcd_status_valid; --i ){ unsigned long timer; /* @@ -1558,13 +1487,14 @@ int sjcd_init( void ){ } if( i == 0 || sjcd_command_failed ){ printk( " reset failed, no drive found.\n" ); + sjcd_cleanup(); return( -EIO ); } else printk( "\n" ); /* * Get and print out cdrom version. */ - printk( "Sanyo: Getting version: " ); + printk( "SJCD: Getting version: " ); sjcd_send_cmd( SCMD_GET_VERSION ); for( i = 1000; i > 0 && !sjcd_status_valid; --i ){ unsigned long timer; @@ -1578,6 +1508,7 @@ int sjcd_init( void ){ } if( i == 0 || sjcd_command_failed ){ printk( " get version failed, no drive found.\n" ); + sjcd_cleanup(); return( -EIO ); } @@ -1586,6 +1517,7 @@ int sjcd_init( void ){ ( int )sjcd_version.minor ); } else { printk( " read version failed, no drive found.\n" ); + sjcd_cleanup(); return( -EIO ); } @@ -1593,7 +1525,7 @@ int sjcd_init( void ){ * Check and print out the tray state. (if it is needed?). */ if( !sjcd_status_valid ){ - printk( "Sanyo: Getting status: " ); + printk( "SJCD: Getting status: " ); sjcd_send_cmd( SCMD_GET_STATUS ); for( i = 1000; i > 0 && !sjcd_status_valid; --i ){ unsigned long timer; @@ -1607,300 +1539,40 @@ int sjcd_init( void ){ } if( i == 0 || sjcd_command_failed ){ printk( " get status failed, no drive found.\n" ); + sjcd_cleanup(); return( -EIO ); } else printk( "\n" ); } - printk( "SANYO CDR-H94A: Status: port=0x%x, irq=%d, dma=%d.\n", - sjcd_port, sjcd_irq, sjcd_dma ); + printk("SJCD: Status: port=0x%x.\n", sjcd_base); sjcd_present++; return( 0 ); } -#ifdef MODULE - -int init_module(void) +static int +sjcd_cleanup(void) { - return sjcd_init(); -} - -void cleanup_module( void ){ - if( ( unregister_blkdev( MAJOR_NR, "sjcd" ) == -EINVAL ) ){ - printk( "sjcd: module: can not unregister device.\n" ); - } else { - release_region( sjcd_port, 4 ); - printk( "sjcd: module: removed.\n"); - } -} -#endif - -/* - * -- 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); + if( (unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL) ) + printk( "SJCD: cannot unregister device.\n" ); else - return( isp16_c928__detect() ); -} + release_region( sjcd_base, 4 ); -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); + return(0); } -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); -} +#ifdef MODULE -static short -isp16_cdi_config( int base, u_char drive_type, int irq, int dma ) +int init_module(void) { - 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); + return sjcd_init(); } -static void isp16_sound_config( void ) +void cleanup_module(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 ); -*/ - + if ( sjcd_cleanup() ) + printk( "SJCD: module: cannot be removed.\n" ); + else + printk( "SJCD: module: removed.\n"); } +#endif diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 72af7eac3c8c..28b10fdeacff 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -219,7 +219,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, case KIOCSOUND: if (!perm) return -EPERM; - kd_mksound(1193180 / (unsigned int) arg, 0); + if (arg) + arg = 1193180 / arg; + kd_mksound(arg, 0); return 0; case KDMKTONE: diff --git a/drivers/char/wd501p.h b/drivers/char/wd501p.h index 002021ed3cb2..6eae253455ff 100644 --- a/drivers/char/wd501p.h +++ b/drivers/char/wd501p.h @@ -64,6 +64,11 @@ #define FEATUREMAP2 (WDC_SR_PSUOVER|WDC_SR_PSUUNDR) #endif +#ifdef CONFIG_SOFT_WATCHDOG +#define FEATUREMAP1 0 +#define FEATUREMAP2 0 +#endif + #ifndef FEATUREMAP1 #error "Config option not set" #endif diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 86c870b68166..b5c4d5b721fa 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -14,11 +14,12 @@ Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 */ -static char *version = "3c59x.c:v0.11 1/21/96 becker@cesdis.gsfc.nasa.gov\n"; +static char *version = "3c59x.c:v0.13 2/13/96 becker@cesdis.gsfc.nasa.gov\n"; /* "Knobs" that turn on special features. */ -/* Use bus master transfers instead of programmed-I/O for the Tx process. - This is disabled by default! */ +/* Allow the use of bus master transfers instead of programmed-I/O for the + Tx process. Bus master transfers are always disabled by default, but + iff this is set they may be turned on using 'options'. */ #define VORTEX_BUS_MASTER /* Put out somewhat more debugging messages. (0 - no msg, 1 minimal msgs). */ @@ -45,6 +46,11 @@ static char *version = "3c59x.c:v0.11 1/21/96 becker@cesdis.gsfc.nasa.gov\n"; #include #include +#ifdef HAVE_SHARED_IRQ +#define USE_SHARED_IRQ +#include +#endif + /* The total size is twice that of the original EtherLinkIII series: the runtime register window, window 1, is now always mapped in. */ #define VORTEX_TOTAL_SIZE 0x20 @@ -295,8 +301,8 @@ static int vortex_scan(struct device *dev) int cards_found = 0; if (pcibios_present()) { - int pci_index; - for (pci_index = 0; pci_index < 8; pci_index++) { + static int pci_index = 0; + for (; pci_index < 8; pci_index++) { unsigned char pci_bus, pci_device_fn, pci_irq_line, pci_latency; unsigned int pci_ioaddr; unsigned short pci_command; @@ -340,8 +346,9 @@ static int vortex_scan(struct device *dev) PCI_LATENCY_TIMER, 255); } #endif /* VORTEX_BUS_MASTER */ - vortex_found_device(dev, pci_ioaddr, pci_irq_line, - index, options[cards_found]); + vortex_found_device(dev, pci_ioaddr, pci_irq_line, index, + dev && dev->mem_start ? dev->mem_start + : options[cards_found]); dev = 0; cards_found++; } @@ -359,7 +366,8 @@ static int vortex_scan(struct device *dev) && (inw(ioaddr + 0xC82) & 0xFFF0) != 0x5920) continue; vortex_found_device(dev, ioaddr, inw(ioaddr + 0xC88) >> 12, - DEMON_INDEX, options[cards_found]); + DEMON_INDEX, dev && dev->mem_start + ? dev->mem_start : options[cards_found]); dev = 0; cards_found++; } @@ -389,7 +397,7 @@ static int vortex_found_device(struct device *dev, int ioaddr, int irq, vp->product_name = product_names[product_index]; vp->options = options; if (options >= 0) { - vp->media_override = options & 7; + vp->media_override = ((options & 7) == 2) ? 0 : options & 7; vp->full_duplex = (options & 8) ? 1 : 0; vp->bus_master = (options & 16) ? 1 : 0; } else { @@ -414,7 +422,7 @@ static int vortex_found_device(struct device *dev, int ioaddr, int irq, vp->product_name = product_names[product_index]; vp->options = options; if (options >= 0) { - vp->media_override = options & 7; + vp->media_override = ((options & 7) == 2) ? 0 : options & 7; vp->full_duplex = (options & 8) ? 1 : 0; vp->bus_master = (options & 16) ? 1 : 0; } else { @@ -534,12 +542,19 @@ vortex_open(struct device *dev) outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD); - if (irq2dev_map[dev->irq] != NULL - || (irq2dev_map[dev->irq] = dev) == NULL - || dev->irq == 0 - || request_irq(dev->irq, &vortex_interrupt, 0, vp->product_name)) { +#ifdef USE_SHARED_IRQ + i = request_shared_irq(dev->irq, &vortex_interrupt, dev, vp->product_name); + if (i) /* Error */ + return i; +#else + if (dev->irq == 0 || irq2dev_map[dev->irq] != NULL) + return -EAGAIN; + irq2dev_map[dev->irq] = dev; + if (request_irq(dev->irq, &vortex_interrupt, 0, vp->product_name)) { + irq2dev_map[dev->irq] = NULL; return -EAGAIN; } +#endif if (vortex_debug > 1) { EL3WINDOW(4); @@ -571,7 +586,7 @@ vortex_open(struct device *dev) inw(ioaddr + 10); inw(ioaddr + 12); /* New: On the Vortex we must also clear the BadSSD counter. */ - EL3WINDOW(3); + EL3WINDOW(4); inb(ioaddr + 12); /* Switch to register set 7 for normal use. */ @@ -723,7 +738,11 @@ vortex_start_xmit(struct sk_buff *skb, struct device *dev) after the Tx thread. */ static void vortex_interrupt(int irq, struct pt_regs *regs) { +#ifdef USE_SHARED_IRQ + struct device *dev = (struct device *)(irq == 0 ? regs : irq2dev_map[irq]); +#else struct device *dev = (struct device *)(irq2dev_map[irq]); +#endif struct vortex_private *lp; int ioaddr, status; int latency; @@ -933,9 +952,13 @@ vortex_close(struct device *dev) outw(inw(ioaddr + Wn4_Media) & ~Media_TP, ioaddr + Wn4_Media); } +#ifdef USE_SHARED_IRQ + free_shared_irq(dev->irq, dev); +#else free_irq(dev->irq); /* Mmmm, we should diable all interrupt sources here. */ irq2dev_map[dev->irq] = 0; +#endif update_stats(ioaddr, dev); #ifdef MODULE @@ -979,7 +1002,7 @@ static void update_stats(int ioaddr, struct device *dev) vp->stats.tx_window_errors += inb(ioaddr + 4); vp->stats.rx_fifo_errors += inb(ioaddr + 5); vp->stats.tx_packets += inb(ioaddr + 6); - vp->stats.tx_packets += (inb(ioaddr + 9)&15) << 8; + vp->stats.tx_packets += (inb(ioaddr + 9)&0x30) << 4; /* Rx packets */ inb(ioaddr + 7); /* Must read to clear */ /* Tx deferrals */ inb(ioaddr + 8); /* Don't bother with register 9, an extention of registers 6&7. @@ -988,7 +1011,7 @@ static void update_stats(int ioaddr, struct device *dev) inw(ioaddr + 10); /* Total Rx and Tx octets. */ inw(ioaddr + 12); /* New: On the Vortex we must also clear the BadSSD counter. */ - EL3WINDOW(3); + EL3WINDOW(4); inb(ioaddr + 12); /* We change back to window 7 (not 1) with the Vortex. */ diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index e5f54a722150..d96a6e2a6a6e 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -49,26 +49,18 @@ #define LOOPBACK_MTU (PAGE_SIZE*7/8) +/* + * The higher levels take care of making this non-reentrant (it's + * called with bh's disabled). + */ static int loopback_xmit(struct sk_buff *skb, struct device *dev) { struct enet_statistics *stats = (struct enet_statistics *)dev->priv; - unsigned long flags; int unlock=1; if (skb == NULL || dev == NULL) return(0); - save_flags(flags); - cli(); - if (dev->tbusy != 0) - { - restore_flags(flags); - stats->tx_errors++; - return(1); - } - dev->tbusy = 1; - restore_flags(flags); - /* * Optimise so buffers with skb->free=1 are not copied but * instead are lobbed from tx queue to rx queue @@ -89,29 +81,21 @@ static int loopback_xmit(struct sk_buff *skb, struct device *dev) * Packet sent but looped back around. Cease to charge * the socket for the frame. */ - save_flags(flags); - cli(); skb->sk->wmem_alloc-=skb->truesize; skb->sk->write_space(skb->sk); - restore_flags(flags); } skb->protocol=eth_type_trans(skb,dev); skb->dev=dev; - save_flags(flags); - cli(); #ifndef LOOPBACK_MUST_CHECKSUM skb->ip_summed = CHECKSUM_UNNECESSARY; #endif netif_rx(skb); if(unlock) skb_device_unlock(skb); - restore_flags(flags); - stats->tx_packets++; stats->rx_packets++; - - dev->tbusy = 0; + stats->tx_packets++; return(0); } diff --git a/drivers/net/slip.c b/drivers/net/slip.c index d2771cf2904e..ff8b697f0d9e 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c @@ -76,6 +76,7 @@ #include #include #include +#include #include "slip.h" #ifdef CONFIG_INET #include diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 90f935ea0ce8..c934b222ec7a 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -68,8 +68,6 @@ * the high level code. */ -#include "g_NCR5380.h" - #if (NDEBUG & NDEBUG_LISTS) #define LIST(x,y) {printk("LINE:%d Adding %p to %p\n", __LINE__, (void*)(x), (void*)(y)); if ((x)==(y)) udelay(5); } #define REMOVE(w,x,y,z) {printk("LINE:%d Removing: %p->%p %p->%p \n", __LINE__, (void*)(w), (void*)(x), (void*)(y), (void*)(z)); if ((x)==(y)) udelay(5); } @@ -788,8 +786,10 @@ static void NCR5380_init (struct Scsi_Host *instance, int flags) { * the base address. */ +#ifdef NCR53C400 if (flags & FLAG_NCR53C400) instance->NCR5380_instance_name += NCR53C400_address_adjust; +#endif NCR5380_setup(instance); @@ -839,9 +839,11 @@ static void NCR5380_init (struct Scsi_Host *instance, int flags) { NCR5380_write(TARGET_COMMAND_REG, 0); NCR5380_write(SELECT_ENABLE_REG, 0); +#ifdef NCR53C400 if (hostdata->flags & FLAG_NCR53C400) { NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE); } +#endif /* * Detect and correct bus wedge problems. diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c index 5fd5ea3eb93b..3105b1bb1f1a 100644 --- a/drivers/scsi/NCR53c406a.c +++ b/drivers/scsi/NCR53c406a.c @@ -1,7 +1,7 @@ /* * NCR53c406.c * Low-level SCSI driver for NCR53c406a chip. - * Copyright (C) 1994, 1995 Normunds Saumanis (normunds@tech.swh.lv) + * Copyright (C) 1994, 1995, 1996 Normunds Saumanis (normunds@fi.ibm.com) * * LILO command line usage: ncr53c406a=[,[,]] * Specify IRQ = 0 for non-interrupt driven mode. @@ -43,6 +43,8 @@ #include #include #include +#include +#include #include #include #include @@ -157,13 +159,13 @@ /*----------------------------------------------------------------*/ enum Phase { - idle, - data_out, - data_in, - command_ph, - status_ph, - message_out, - message_in + idle, + data_out, + data_in, + command_ph, + status_ph, + message_out, + message_in }; /* Static function prototypes */ @@ -207,13 +209,17 @@ static volatile int internal_done_flag = 0; static volatile int internal_done_errcode = 0; static char info_msg[256]; +struct proc_dir_entry proc_scsi_NCR53c406a = { + PROC_SCSI_NCR53C406A, 7, "NCR53c406a", + S_IFDIR | S_IRUGO | S_IXUGO, 2 +}; /* ================================================================= */ /* possible BIOS locations */ #if USE_BIOS static void *addresses[] = { - (void *)0xd8000, - (void *)0xc8000 + (void *)0xd8000, + (void *)0xc8000 }; #define ADDRESS_COUNT (sizeof( addresses ) / sizeof( unsigned )) #endif USE_BIOS @@ -229,13 +235,13 @@ static unsigned short intrs[] = { 10, 11, 12, 15 }; /* signatures for NCR 53c406a based controllers */ #if USE_BIOS struct signature { - char *signature; - int sig_offset; - int sig_length; + char *signature; + int sig_offset; + int sig_length; } signatures[] = { - /* 1 2 3 4 5 6 */ - /* 123456789012345678901234567890123456789012345678901234567890 */ - { "Copyright (C) Acculogic, Inc.\r\n2.8M Diskette Extension Bios ver 4.04.03 03/01/1993", 61, 82 }, + /* 1 2 3 4 5 6 */ + /* 123456789012345678901234567890123456789012345678901234567890 */ + { "Copyright (C) Acculogic, Inc.\r\n2.8M Diskette Extension Bios ver 4.04.03 03/01/1993", 61, 82 }, }; #define SIGNATURE_COUNT (sizeof( signatures ) / sizeof( struct signature )) #endif USE_BIOS @@ -287,60 +293,60 @@ static __inline__ int NCR53c406a_dma_setup (unsigned char *ptr, unsigned int count, unsigned char mode) { - unsigned limit; - unsigned long flags = 0; - - VDEB(printk("dma: before count=%d ", count)); - if (dma_chan <=3) { - if (count > 65536) - count = 65536; - limit = 65536 - (((unsigned) ptr) & 0xFFFF); - } else { - if (count > (65536<<1)) - count = (65536<<1); - limit = (65536<<1) - (((unsigned) ptr) & 0x1FFFF); - } - - if (count > limit) count = limit; - - VDEB(printk("after count=%d\n", count)); - if ((count & 1) || (((unsigned) ptr) & 1)) - panic ("NCR53c406a: attempted unaligned DMA transfer\n"); - - save_flags(flags); - cli(); - disable_dma(dma_chan); - clear_dma_ff(dma_chan); - set_dma_addr(dma_chan, (long) ptr); - set_dma_count(dma_chan, count); - set_dma_mode(dma_chan, mode); - enable_dma(dma_chan); - restore_flags(flags); - - return count; + unsigned limit; + unsigned long flags = 0; + + VDEB(printk("dma: before count=%d ", count)); + if (dma_chan <=3) { + if (count > 65536) + count = 65536; + limit = 65536 - (((unsigned) ptr) & 0xFFFF); + } else { + if (count > (65536<<1)) + count = (65536<<1); + limit = (65536<<1) - (((unsigned) ptr) & 0x1FFFF); + } + + if (count > limit) count = limit; + + VDEB(printk("after count=%d\n", count)); + if ((count & 1) || (((unsigned) ptr) & 1)) + panic ("NCR53c406a: attempted unaligned DMA transfer\n"); + + save_flags(flags); + cli(); + disable_dma(dma_chan); + clear_dma_ff(dma_chan); + set_dma_addr(dma_chan, (long) ptr); + set_dma_count(dma_chan, count); + set_dma_mode(dma_chan, mode); + enable_dma(dma_chan); + restore_flags(flags); + + return count; } - + static __inline__ int NCR53c406a_dma_write(unsigned char *src, unsigned int count) { - return NCR53c406a_dma_setup (src, count, DMA_MODE_WRITE); + return NCR53c406a_dma_setup (src, count, DMA_MODE_WRITE); } static __inline__ int NCR53c406a_dma_read(unsigned char *src, unsigned int count) { - return NCR53c406a_dma_setup (src, count, DMA_MODE_READ); + return NCR53c406a_dma_setup (src, count, DMA_MODE_READ); } static __inline__ int NCR53c406a_dma_residual (void) { - register int tmp; - unsigned long flags = 0; - save_flags(flags); - cli(); - clear_dma_ff(dma_chan); - tmp = get_dma_residue(dma_chan); - restore_flags(flags); - - return tmp; + register int tmp; + unsigned long flags = 0; + save_flags(flags); + cli(); + clear_dma_ff(dma_chan); + tmp = get_dma_residue(dma_chan); + restore_flags(flags); + + return tmp; } #endif USE_DMA @@ -348,710 +354,702 @@ NCR53c406a_dma_residual (void) { static __inline__ int NCR53c406a_pio_read(unsigned char *request, unsigned int reqlen) { - int i; - int len; /* current scsi fifo size */ - unsigned long flags = 0; - - REG1; - while (reqlen) { - i = inb(PIO_STATUS); -/* VDEB(printk("pio_status=%x\n", i)); */ - if (i & 0x80) - return 0; - - switch( i & 0x1e ) { - default: - case 0x10: - len=0; break; - case 0x0: - len=1; break; - case 0x8: - len=42; break; - case 0xc: - len=84; break; - case 0xe: - len=128; break; - } - - if ((i & 0x40) && len == 0) { /* fifo empty and interrupt occured */ - return 0; - } - - if (len) { - if( len > reqlen ) - len = reqlen; - - save_flags(flags); - cli(); - if( fast_pio && len > 3 ) { - insl(PIO_FIFO,request,len>>2); - request += len & 0xfc; - reqlen -= len & 0xfc; - } - else { - while(len--) { - *request++ = inb(PIO_FIFO); - reqlen--; - } - } - restore_flags(flags); + int i; + int len; /* current scsi fifo size */ + unsigned long flags = 0; + + REG1; + while (reqlen) { + i = inb(PIO_STATUS); + /* VDEB(printk("pio_status=%x\n", i)); */ + if (i & 0x80) + return 0; + + switch( i & 0x1e ) { + default: + case 0x10: + len=0; break; + case 0x0: + len=1; break; + case 0x8: + len=42; break; + case 0xc: + len=84; break; + case 0xe: + len=128; break; + } + + if ((i & 0x40) && len == 0) { /* fifo empty and interrupt occured */ + return 0; + } + + if (len) { + if( len > reqlen ) + len = reqlen; + + save_flags(flags); + cli(); + if( fast_pio && len > 3 ) { + insl(PIO_FIFO,request,len>>2); + request += len & 0xfc; + reqlen -= len & 0xfc; + } + else { + while(len--) { + *request++ = inb(PIO_FIFO); + reqlen--; + } + } + restore_flags(flags); + } } - } - return 0; + return 0; } static __inline__ int NCR53c406a_pio_write(unsigned char *request, unsigned int reqlen) { - int i = 0; - int len; /* current scsi fifo size */ - unsigned long flags = 0; - - REG1; - while (reqlen && !(i&0x40)) { - i = inb(PIO_STATUS); -/* VDEB(printk("pio_status=%x\n", i)); */ - if (i & 0x80) /* error */ - return 0; + int i = 0; + int len; /* current scsi fifo size */ + unsigned long flags = 0; - switch( i & 0x1e ) { - case 0x10: - len=128; break; - case 0x0: - len=84; break; - case 0x8: - len=42; break; - case 0xc: - len=1; break; - default: - case 0xe: - len=0; break; + REG1; + while (reqlen && !(i&0x40)) { + i = inb(PIO_STATUS); + /* VDEB(printk("pio_status=%x\n", i)); */ + if (i & 0x80) /* error */ + return 0; + + switch( i & 0x1e ) { + case 0x10: + len=128; break; + case 0x0: + len=84; break; + case 0x8: + len=42; break; + case 0xc: + len=1; break; + default: + case 0xe: + len=0; break; + } + + if (len) { + if( len > reqlen ) + len = reqlen; + + save_flags(flags); + cli(); + if( fast_pio && len > 3 ) { + outsl(PIO_FIFO,request,len>>2); + request += len & 0xfc; + reqlen -= len & 0xfc; + } + else { + while(len--) { + outb(*request++, PIO_FIFO); + reqlen--; + } + } + restore_flags(flags); + } } - - if (len) { - if( len > reqlen ) - len = reqlen; - - save_flags(flags); - cli(); - if( fast_pio && len > 3 ) { - outsl(PIO_FIFO,request,len>>2); - request += len & 0xfc; - reqlen -= len & 0xfc; - } - else { - while(len--) { - outb(*request++, PIO_FIFO); - reqlen--; - } - } - restore_flags(flags); - } - } - return 0; + return 0; } #endif USE_PIO int NCR53c406a_detect(Scsi_Host_Template * tpnt){ - struct Scsi_Host *shpnt; + struct Scsi_Host *shpnt; #ifndef PORT_BASE - int i; + int i; #endif - + #if USE_BIOS - int ii, jj; - bios_base = 0; - /* look for a valid signature */ - for( ii=0; ii < ADDRESS_COUNT && !bios_base; ii++) - for( jj=0; (jj < SIGNATURE_COUNT) && !bios_base; jj++) - if(!memcmp((void *) addresses[ii]+signatures[jj].sig_offset, - (void *) signatures[jj].signature, - (int) signatures[jj].sig_length)) - bios_base=addresses[ii]; - - if(!bios_base){ - printk("NCR53c406a: BIOS signature not found\n"); - return 0; - } - - DEB(printk("NCR53c406a BIOS found at %X\n", (unsigned int) bios_base);); + int ii, jj; + bios_base = 0; + /* look for a valid signature */ + for( ii=0; ii < ADDRESS_COUNT && !bios_base; ii++) + for( jj=0; (jj < SIGNATURE_COUNT) && !bios_base; jj++) + if(!memcmp((void *) addresses[ii]+signatures[jj].sig_offset, + (void *) signatures[jj].signature, + (int) signatures[jj].sig_length)) + bios_base=addresses[ii]; + + if(!bios_base){ + printk("NCR53c406a: BIOS signature not found\n"); + return 0; + } + + DEB(printk("NCR53c406a BIOS found at %X\n", (unsigned int) bios_base);); #endif USE_BIOS #ifdef PORT_BASE - if (check_region(port_base, 0x10)) /* ports already snatched */ - port_base = 0; - + if (check_region(port_base, 0x10)) /* ports already snatched */ + port_base = 0; + #else /* autodetect */ - if (port_base) { /* LILO override */ - if (check_region(port_base, 0x10)) - port_base = 0; - } - else { - for(i=0; i= 0*/ - irq_level=irq_probe(); - if (irq_level < 0) { /* Trouble */ - printk("NCR53c406a: IRQ problem, irq_level=%d, giving up\n", irq_level); - return 0; + if (irq_level < 0) { /* LILO override if >= 0*/ + irq_level=irq_probe(); + if (irq_level < 0) { /* Trouble */ + printk("NCR53c406a: IRQ problem, irq_level=%d, giving up\n", irq_level); + return 0; + } } - } #endif - - DEB(printk("NCR53c406a: using port_base %x\n", port_base)); - request_region(port_base, 0x10, "NCR53c406a"); - - if(irq_level > 0) { - if(request_irq(irq_level, NCR53c406a_intr, 0, "NCR53c406a")){ - printk("NCR53c406a: unable to allocate IRQ %d\n", irq_level); - return 0; + + DEB(printk("NCR53c406a: using port_base %x\n", port_base)); + request_region(port_base, 0x10, "NCR53c406a"); + + if(irq_level > 0) { + if(request_irq(irq_level, NCR53c406a_intr, 0, "NCR53c406a")){ + printk("NCR53c406a: unable to allocate IRQ %d\n", irq_level); + return 0; + } + tpnt->can_queue = 1; + DEB(printk("NCR53c406a: allocated IRQ %d\n", irq_level)); } - tpnt->can_queue = 1; - DEB(printk("NCR53c406a: allocated IRQ %d\n", irq_level)); - } - else if (irq_level == 0) { - tpnt->can_queue = 0; - DEB(printk("NCR53c406a: No interrupts detected\n")); + else if (irq_level == 0) { + tpnt->can_queue = 0; + DEB(printk("NCR53c406a: No interrupts detected\n")); #if USE_DMA - printk("NCR53c406a: No interrupts found and DMA mode defined. Giving up.\n"); - return 0; + printk("NCR53c406a: No interrupts found and DMA mode defined. Giving up.\n"); + return 0; #endif USE_DMA - } - else { - DEB(printk("NCR53c406a: Shouldn't get here!\n")); - return 0; - } - + } + else { + DEB(printk("NCR53c406a: Shouldn't get here!\n")); + return 0; + } + #if USE_DMA - dma_chan = DMA_CHAN; - if(request_dma(dma_chan, "NCR53c406a") != 0){ - printk("NCR53c406a: unable to allocate DMA channel %d\n", dma_chan); - return 0; - } - - DEB(printk("Allocated DMA channel %d\n", dma_chan)); + dma_chan = DMA_CHAN; + if(request_dma(dma_chan, "NCR53c406a") != 0){ + printk("NCR53c406a: unable to allocate DMA channel %d\n", dma_chan); + return 0; + } + + DEB(printk("Allocated DMA channel %d\n", dma_chan)); #endif USE_DMA - - tpnt->present = 1; - - shpnt = scsi_register(tpnt, 0); - shpnt->irq = irq_level; - shpnt->io_port = port_base; - shpnt->n_io_port = 0x10; + + tpnt->present = 1; + tpnt->proc_dir = &proc_scsi_NCR53c406a; + + shpnt = scsi_register(tpnt, 0); + shpnt->irq = irq_level; + shpnt->io_port = port_base; + shpnt->n_io_port = 0x10; #if USE_DMA - shpnt->dma = dma_chan; + shpnt->dma = dma_chan; #endif - + #if USE_DMA - sprintf(info_msg, "NCR53c406a at 0x%x, IRQ %d, DMA channel %d.", port_base, irq_level, dma_chan); + sprintf(info_msg, "NCR53c406a at 0x%x, IRQ %d, DMA channel %d.", + port_base, irq_level, dma_chan); #else - sprintf(info_msg, "NCR53c406a at 0x%x, IRQ %d, %s PIO mode.", port_base, irq_level, fast_pio ? "fast" : "slow"); + sprintf(info_msg, "NCR53c406a at 0x%x, IRQ %d, %s PIO mode.", + port_base, irq_level, fast_pio ? "fast" : "slow"); #endif - - return (tpnt->present); + + return (tpnt->present); } /* called from init/main.c */ void NCR53c406a_setup(char *str, int *ints) { - static size_t setup_idx = 0; - size_t i; - - DEB(printk("NCR53c406a: Setup called\n");); - - if (setup_idx >= PORT_COUNT - 1) { - printk("NCR53c406a: Setup called too many times. Bad LILO params?\n"); - return; - } - if (ints[0] < 1 || ints[0] > 3) { - printk("NCR53c406a: Malformed command line\n"); - printk("NCR53c406a: Usage: ncr53c406a=[,[,]]\n"); - return; - } - for (i = 0; i < PORT_COUNT && !port_base; i++) - if (ports[i] == ints[1]) { - port_base = ints[1]; - DEB(printk("NCR53c406a: Specified port_base 0x%X\n", port_base);) + static size_t setup_idx = 0; + size_t i; + + DEB(printk("NCR53c406a: Setup called\n");); + + if (setup_idx >= PORT_COUNT - 1) { + printk("NCR53c406a: Setup called too many times. Bad LILO params?\n"); + return; } - if (!port_base) { - printk("NCR53c406a: Invalid PORTBASE 0x%X specified\n", ints[1]); - return; - } - - if (ints[0] > 1) { - if (ints[2] == 0) { - irq_level = 0; - DEB(printk("NCR53c406a: Specified irq %d\n", irq_level);) + if (ints[0] < 1 || ints[0] > 3) { + printk("NCR53c406a: Malformed command line\n"); + printk("NCR53c406a: Usage: ncr53c406a=[,[,]]\n"); + return; } - else - for (i = 0; i < INTR_COUNT && irq_level < 0; i++) - if (intrs[i] == ints[2]) { - irq_level = ints[2]; - DEB(printk("NCR53c406a: Specified irq %d\n", port_base);) - } - if (irq_level < 0) - printk("NCR53c406a: Invalid IRQ %d specified\n", ints[2]); - } - - if (ints[0] > 2) - fast_pio = ints[3]; - - DEB(printk("NCR53c406a: port_base=0x%X, irq=%d, fast_pio=%d\n", port_base, irq_level, fast_pio);) + for (i = 0; i < PORT_COUNT && !port_base; i++) + if (ports[i] == ints[1]) { + port_base = ints[1]; + DEB(printk("NCR53c406a: Specified port_base 0x%X\n", port_base);) + } + if (!port_base) { + printk("NCR53c406a: Invalid PORTBASE 0x%X specified\n", ints[1]); + return; + } + + if (ints[0] > 1) { + if (ints[2] == 0) { + irq_level = 0; + DEB(printk("NCR53c406a: Specified irq %d\n", irq_level);) + } + else + for (i = 0; i < INTR_COUNT && irq_level < 0; i++) + if (intrs[i] == ints[2]) { + irq_level = ints[2]; + DEB(printk("NCR53c406a: Specified irq %d\n", port_base);) + } + if (irq_level < 0) + printk("NCR53c406a: Invalid IRQ %d specified\n", ints[2]); + } + + if (ints[0] > 2) + fast_pio = ints[3]; + + DEB(printk("NCR53c406a: port_base=0x%X, irq=%d, fast_pio=%d\n", + port_base, irq_level, fast_pio);) } const char* NCR53c406a_info(struct Scsi_Host *SChost){ - DEB(printk("NCR53c406a_info called\n")); - return (info_msg); + DEB(printk("NCR53c406a_info called\n")); + return (info_msg); } static void internal_done(Scsi_Cmnd *SCpnt) { - internal_done_errcode = SCpnt->result; - ++internal_done_flag; + internal_done_errcode = SCpnt->result; + ++internal_done_flag; } static void wait_intr() { - int i = jiffies + WATCHDOG; - - while(i>jiffies && !(inb(STAT_REG)&0xe0)) /* wait for a pseudo-interrupt */ - barrier(); - - if (i <= jiffies) { /* Timed out */ - rtrc(0); - current_SC->result = DID_TIME_OUT << 16; - current_SC->SCp.phase = idle; - current_SC->scsi_done(current_SC); - return; - } - - NCR53c406a_intr(0, NULL); + int i = jiffies + WATCHDOG; + + while(i>jiffies && !(inb(STAT_REG)&0xe0)) /* wait for a pseudo-interrupt */ + barrier(); + + if (i <= jiffies) { /* Timed out */ + rtrc(0); + current_SC->result = DID_TIME_OUT << 16; + current_SC->SCp.phase = idle; + current_SC->scsi_done(current_SC); + return; + } + + NCR53c406a_intr(0, NULL); } int NCR53c406a_command(Scsi_Cmnd *SCpnt){ - DEB(printk("NCR53c406a_command called\n")); - NCR53c406a_queue(SCpnt, internal_done); - if(irq_level) - while (!internal_done_flag); - else /* interrupts not supported */ - while (!internal_done_flag) - wait_intr(); - - internal_done_flag = 0; - return internal_done_errcode; + DEB(printk("NCR53c406a_command called\n")); + NCR53c406a_queue(SCpnt, internal_done); + if(irq_level) + while (!internal_done_flag); + else /* interrupts not supported */ + while (!internal_done_flag) + wait_intr(); + + internal_done_flag = 0; + return internal_done_errcode; } int NCR53c406a_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)){ - int i; - unsigned long flags = 0; - - VDEB(printk("NCR53c406a_queue called\n")); - DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", - SCpnt->cmnd[0], - SCpnt->cmd_len, - SCpnt->target, - SCpnt->lun, - SCpnt->request_bufflen)); - + int i; + unsigned long flags = 0; + + VDEB(printk("NCR53c406a_queue called\n")); + DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", + SCpnt->cmnd[0], + SCpnt->cmd_len, + SCpnt->target, + SCpnt->lun, + SCpnt->request_bufflen)); + #if 0 - VDEB(for(i=0; icmd_len; i++) - printk("cmd[%d]=%02x ", i, SCpnt->cmnd[i])); - VDEB(printk("\n")); + VDEB(for(i=0; icmd_len; i++) + printk("cmd[%d]=%02x ", i, SCpnt->cmnd[i])); + VDEB(printk("\n")); #endif - - current_SC = SCpnt; - current_SC->scsi_done = done; - current_SC->SCp.phase = command_ph; - current_SC->SCp.Status = 0; - current_SC->SCp.Message = 0; - - save_flags(flags); - cli(); - REG0; - outb(SCpnt->target, DEST_ID); /* set destination */ - outb(FLUSH_FIFO, CMD_REG); /* reset the fifos */ - - for(i=0; icmd_len; i++){ - outb(SCpnt->cmnd[i], SCSI_FIFO); - } - outb(SELECT_NO_ATN, CMD_REG); - restore_flags(flags); - - rtrc(1); - return 0; + + current_SC = SCpnt; + current_SC->scsi_done = done; + current_SC->SCp.phase = command_ph; + current_SC->SCp.Status = 0; + current_SC->SCp.Message = 0; + + save_flags(flags); + cli(); + REG0; + outb(SCpnt->target, DEST_ID); /* set destination */ + outb(FLUSH_FIFO, CMD_REG); /* reset the fifos */ + + for(i=0; icmd_len; i++){ + outb(SCpnt->cmnd[i], SCSI_FIFO); + } + outb(SELECT_NO_ATN, CMD_REG); + restore_flags(flags); + + rtrc(1); + return 0; } int NCR53c406a_abort(Scsi_Cmnd *SCpnt){ - DEB(printk("NCR53c406a_abort called\n")); - return SCSI_ABORT_SNOOZE; /* Don't know how to abort */ + DEB(printk("NCR53c406a_abort called\n")); + return SCSI_ABORT_SNOOZE; /* Don't know how to abort */ } int NCR53c406a_reset(Scsi_Cmnd *SCpnt){ - DEB(printk("NCR53c406a_reset called\n")); - outb(C4_IMG, CONFIG4); /* Select reg set 0 */ - outb(CHIP_RESET, CMD_REG); - outb(SCSI_NOP, CMD_REG); /* required after reset */ - outb(SCSI_RESET, CMD_REG); - chip_init(); - - rtrc(2); - if (irq_level) - return SCSI_RESET_PENDING; /* should get an interrupt */ - else - return SCSI_RESET_WAKEUP; /* won't get any interrupts */ + DEB(printk("NCR53c406a_reset called\n")); + outb(C4_IMG, CONFIG4); /* Select reg set 0 */ + outb(CHIP_RESET, CMD_REG); + outb(SCSI_NOP, CMD_REG); /* required after reset */ + outb(SCSI_RESET, CMD_REG); + chip_init(); + + rtrc(2); + if (irq_level) + return SCSI_RESET_PENDING; /* should get an interrupt */ + else + return SCSI_RESET_WAKEUP; /* won't get any interrupts */ } int NCR53c406a_biosparm(Scsi_Disk *disk, kdev_t dev, int* info_array){ - int size; - - DEB(printk("NCR53c406a_biosparm called\n")); - - size = disk->capacity; - info_array[0] = 64; /* heads */ - info_array[1] = 32; /* sectors */ - info_array[2] = size>>11; /* cylinders */ - if (info_array[2] > 1024) { /* big disk */ - info_array[0] = 255; - info_array[1] = 63; - info_array[2] = size / (255*63); + int size; + + DEB(printk("NCR53c406a_biosparm called\n")); + + size = disk->capacity; + info_array[0] = 64; /* heads */ + info_array[1] = 32; /* sectors */ + info_array[2] = size>>11; /* cylinders */ + if (info_array[2] > 1024) { /* big disk */ + info_array[0] = 255; + info_array[1] = 63; + info_array[2] = size / (255*63); + } + return 0; } - return 0; -} - -static void + + static void NCR53c406a_intr(int unused, struct pt_regs *regs){ - DEB(unsigned char fifo_size;) - DEB(unsigned char seq_reg;) - unsigned char status, int_reg; - unsigned long flags = 0; + DEB(unsigned char fifo_size;) + DEB(unsigned char seq_reg;) + unsigned char status, int_reg; + unsigned long flags = 0; #if USE_PIO - unsigned char pio_status; - struct scatterlist *sglist; - unsigned int sgcount; + unsigned char pio_status; + struct scatterlist *sglist; + unsigned int sgcount; #endif - - VDEB(printk("NCR53c406a_intr called\n")); - - save_flags(flags); - cli(); + + VDEB(printk("NCR53c406a_intr called\n")); + + save_flags(flags); + cli(); #if USE_PIO - REG1; - pio_status = inb(PIO_STATUS); + REG1; + pio_status = inb(PIO_STATUS); #endif - REG0; - status = inb(STAT_REG); - DEB(seq_reg = inb(SEQ_REG)); - int_reg = inb(INT_REG); - DEB(fifo_size = inb(FIFO_FLAGS) & 0x1f); - restore_flags(flags); - + REG0; + status = inb(STAT_REG); + DEB(seq_reg = inb(SEQ_REG)); + int_reg = inb(INT_REG); + DEB(fifo_size = inb(FIFO_FLAGS) & 0x1f); + restore_flags(flags); + #if NCR53C406A_DEBUG - printk("status=%02x, seq_reg=%02x, int_reg=%02x, fifo_size=%02x", - status, seq_reg, int_reg, fifo_size); + printk("status=%02x, seq_reg=%02x, int_reg=%02x, fifo_size=%02x", + status, seq_reg, int_reg, fifo_size); #if (USE_DMA) - printk("\n"); + printk("\n"); #else - printk(", pio=%02x\n", pio_status); + printk(", pio=%02x\n", pio_status); #endif USE_DMA #endif NCR53C406A_DEBUG - - if(int_reg & 0x80){ /* SCSI reset intr */ - rtrc(3); - DEB(printk("NCR53c406a: reset intr received\n")); - current_SC->SCp.phase = idle; - current_SC->result = DID_RESET << 16; - current_SC->scsi_done(current_SC); - return; - } - + + if(int_reg & 0x80){ /* SCSI reset intr */ + rtrc(3); + DEB(printk("NCR53c406a: reset intr received\n")); + current_SC->SCp.phase = idle; + current_SC->result = DID_RESET << 16; + current_SC->scsi_done(current_SC); + return; + } + #if USE_PIO - if(pio_status & 0x80) { - printk("NCR53C406A: Warning: PIO error!\n"); - current_SC->SCp.phase = idle; - current_SC->result = DID_ERROR << 16; - current_SC->scsi_done(current_SC); - return; - } + if(pio_status & 0x80) { + printk("NCR53C406A: Warning: PIO error!\n"); + current_SC->SCp.phase = idle; + current_SC->result = DID_ERROR << 16; + current_SC->scsi_done(current_SC); + return; + } #endif USE_PIO - - if(status & 0x20) { /* Parity error */ - printk("NCR53c406a: Warning: parity error!\n"); - current_SC->SCp.phase = idle; - current_SC->result = DID_PARITY << 16; - current_SC->scsi_done(current_SC); - return; - } - - if(status & 0x40) { /* Gross error */ - printk("NCR53c406a: Warning: gross error!\n"); - current_SC->SCp.phase = idle; - current_SC->result = DID_ERROR << 16; - current_SC->scsi_done(current_SC); - return; - } - - if(int_reg & 0x20){ /* Disconnect */ - DEB(printk("NCR53c406a: disconnect intr received\n")); - if(current_SC->SCp.phase != message_in){ /* Unexpected disconnect */ - current_SC->result = DID_NO_CONNECT << 16; - } - else{ /* Command complete, return status and message */ - current_SC->result = (current_SC->SCp.Status & 0xff) - | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16); + + if(status & 0x20) { /* Parity error */ + printk("NCR53c406a: Warning: parity error!\n"); + current_SC->SCp.phase = idle; + current_SC->result = DID_PARITY << 16; + current_SC->scsi_done(current_SC); + return; } - - rtrc(0); - current_SC->SCp.phase = idle; - current_SC->scsi_done( current_SC ); - return; - } - - switch(status & 0x07){ /* scsi phase */ - case 0x00: /* DATA-OUT */ - if(int_reg & 0x10){ /* Target requesting info transfer */ - rtrc(5); - current_SC->SCp.phase = data_out; - VDEB(printk("NCR53c406a: Data-Out phase\n")); - outb(FLUSH_FIFO, CMD_REG); - LOAD_DMA_COUNT(current_SC->request_bufflen); /* Max transfer size */ + + if(status & 0x40) { /* Gross error */ + printk("NCR53c406a: Warning: gross error!\n"); + current_SC->SCp.phase = idle; + current_SC->result = DID_ERROR << 16; + current_SC->scsi_done(current_SC); + return; + } + + if(int_reg & 0x20){ /* Disconnect */ + DEB(printk("NCR53c406a: disconnect intr received\n")); + if(current_SC->SCp.phase != message_in){ /* Unexpected disconnect */ + current_SC->result = DID_NO_CONNECT << 16; + } + else{ /* Command complete, return status and message */ + current_SC->result = (current_SC->SCp.Status & 0xff) + | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16); + } + + rtrc(0); + current_SC->SCp.phase = idle; + current_SC->scsi_done( current_SC ); + return; + } + + switch(status & 0x07){ /* scsi phase */ + case 0x00: /* DATA-OUT */ + if(int_reg & 0x10){ /* Target requesting info transfer */ + rtrc(5); + current_SC->SCp.phase = data_out; + VDEB(printk("NCR53c406a: Data-Out phase\n")); + outb(FLUSH_FIFO, CMD_REG); + LOAD_DMA_COUNT(current_SC->request_bufflen); /* Max transfer size */ #if USE_DMA /* No s/g support for DMA */ - NCR53c406a_dma_write(current_SC->request_buffer, - current_SC->request_bufflen); + NCR53c406a_dma_write(current_SC->request_buffer, + current_SC->request_bufflen); #endif USE_DMA - outb(TRANSFER_INFO | DMA_OP, CMD_REG); + outb(TRANSFER_INFO | DMA_OP, CMD_REG); #if USE_PIO - if (!current_SC->use_sg) /* Don't use scatter-gather */ - NCR53c406a_pio_write(current_SC->request_buffer, - current_SC->request_bufflen); - else { /* use scatter-gather */ - sgcount = current_SC->use_sg; - sglist = current_SC->request_buffer; - while( sgcount-- ) { - NCR53c406a_pio_write(sglist->address, sglist->length); - sglist++; - } - } - REG0; + if (!current_SC->use_sg) /* Don't use scatter-gather */ + NCR53c406a_pio_write(current_SC->request_buffer, + current_SC->request_bufflen); + else { /* use scatter-gather */ + sgcount = current_SC->use_sg; + sglist = current_SC->request_buffer; + while( sgcount-- ) { + NCR53c406a_pio_write(sglist->address, sglist->length); + sglist++; + } + } + REG0; #endif USE_PIO - } - break; - - case 0x01: /* DATA-IN */ - if(int_reg & 0x10){ /* Target requesting info transfer */ - rtrc(6); - current_SC->SCp.phase = data_in; - VDEB(printk("NCR53c406a: Data-In phase\n")); - outb(FLUSH_FIFO, CMD_REG); - LOAD_DMA_COUNT(current_SC->request_bufflen); /* Max transfer size */ + } + break; + + case 0x01: /* DATA-IN */ + if(int_reg & 0x10){ /* Target requesting info transfer */ + rtrc(6); + current_SC->SCp.phase = data_in; + VDEB(printk("NCR53c406a: Data-In phase\n")); + outb(FLUSH_FIFO, CMD_REG); + LOAD_DMA_COUNT(current_SC->request_bufflen); /* Max transfer size */ #if USE_DMA /* No s/g support for DMA */ - NCR53c406a_dma_read(current_SC->request_buffer, - current_SC->request_bufflen); + NCR53c406a_dma_read(current_SC->request_buffer, + current_SC->request_bufflen); #endif USE_DMA - outb(TRANSFER_INFO | DMA_OP, CMD_REG); + outb(TRANSFER_INFO | DMA_OP, CMD_REG); #if USE_PIO - if (!current_SC->use_sg) /* Don't use scatter-gather */ - NCR53c406a_pio_read(current_SC->request_buffer, - current_SC->request_bufflen); - else { /* Use scatter-gather */ - sgcount = current_SC->use_sg; - sglist = current_SC->request_buffer; - while( sgcount-- ) { - NCR53c406a_pio_read(sglist->address, sglist->length); - sglist++; - } - } - REG0; + if (!current_SC->use_sg) /* Don't use scatter-gather */ + NCR53c406a_pio_read(current_SC->request_buffer, + current_SC->request_bufflen); + else { /* Use scatter-gather */ + sgcount = current_SC->use_sg; + sglist = current_SC->request_buffer; + while( sgcount-- ) { + NCR53c406a_pio_read(sglist->address, sglist->length); + sglist++; + } + } + REG0; #endif USE_PIO + } + break; + + case 0x02: /* COMMAND */ + current_SC->SCp.phase = command_ph; + printk("NCR53c406a: Warning: Unknown interupt occured in command phase!\n"); + break; + + case 0x03: /* STATUS */ + rtrc(7); + current_SC->SCp.phase = status_ph; + VDEB(printk("NCR53c406a: Status phase\n")); + outb(FLUSH_FIFO, CMD_REG); + outb(INIT_CMD_COMPLETE, CMD_REG); + break; + + case 0x04: /* Reserved */ + case 0x05: /* Reserved */ + printk("NCR53c406a: WARNING: Reserved phase!!!\n"); + break; + + case 0x06: /* MESSAGE-OUT */ + DEB(printk("NCR53c406a: Message-Out phase\n")); + current_SC->SCp.phase = message_out; + outb(SET_ATN, CMD_REG); /* Reject the message */ + outb(MSG_ACCEPT, CMD_REG); + break; + + case 0x07: /* MESSAGE-IN */ + rtrc(4); + VDEB(printk("NCR53c406a: Message-In phase\n")); + current_SC->SCp.phase = message_in; + + current_SC->SCp.Status = inb(SCSI_FIFO); + current_SC->SCp.Message = inb(SCSI_FIFO); + + VDEB(printk("SCSI FIFO size=%d\n", inb(FIFO_FLAGS) & 0x1f)); + DEB(printk("Status = %02x Message = %02x\n", + current_SC->SCp.Status, current_SC->SCp.Message)); + + if(current_SC->SCp.Message == SAVE_POINTERS || + current_SC->SCp.Message == DISCONNECT) { + outb(SET_ATN, CMD_REG); /* Reject message */ + DEB(printk("Discarding SAVE_POINTERS message\n")); + } + outb(MSG_ACCEPT, CMD_REG); + break; } - break; - - case 0x02: /* COMMAND */ - current_SC->SCp.phase = command_ph; - printk("NCR53c406a: Warning: Unknown interupt occured in command phase!\n"); - break; - - case 0x03: /* STATUS */ - rtrc(7); - current_SC->SCp.phase = status_ph; - VDEB(printk("NCR53c406a: Status phase\n")); -#if 0 -#if VERBOSE_NCR53C406A_DEBUG - printk("request_buffer="); - for(i=0; irequest_bufflen && i<256; i++) - printk("%02x ", *((unsigned char*)current_SC->request_buffer + i)); - printk("\n"); -#if USE_DMA - printk("dma residue = %d\n", NCR53c406a_dma_residual()); -#endif USE_DMA -#endif VERBOSE_NCR53C406A_DEBUG -#endif - - outb(FLUSH_FIFO, CMD_REG); - outb(INIT_CMD_COMPLETE, CMD_REG); - break; +} + +#ifndef IRQ_LEV +static int irq_probe() +{ + int irqs, irq; + int i; - case 0x04: /* Reserved */ - case 0x05: /* Reserved */ - printk("NCR53c406a: WARNING: Reserved phase!!!\n"); - break; + inb(INT_REG); /* clear the interrupt register */ + sti(); + irqs = probe_irq_on(); - case 0x06: /* MESSAGE-OUT */ - DEB(printk("NCR53c406a: Message-Out phase\n")); - current_SC->SCp.phase = message_out; - outb(SET_ATN, CMD_REG); /* Reject the message */ - outb(MSG_ACCEPT, CMD_REG); - break; + /* Invalid command will cause an interrupt */ + REG0; + outb(0xff, CMD_REG); - case 0x07: /* MESSAGE-IN */ - rtrc(4); - VDEB(printk("NCR53c406a: Message-In phase\n")); - current_SC->SCp.phase = message_in; + /* Wait for the interrupt to occur */ + i = jiffies + WATCHDOG; + while(i > jiffies && !(inb(STAT_REG) & 0x80)) + barrier(); + if (i <= jiffies) { /* Timed out, must be hardware trouble */ + probe_irq_off(irqs); + return -1; + } - current_SC->SCp.Status = inb(SCSI_FIFO); - current_SC->SCp.Message = inb(SCSI_FIFO); + irq = probe_irq_off(irqs); - VDEB(printk("SCSI FIFO size=%d\n", inb(FIFO_FLAGS) & 0x1f)); - DEB(printk("Status = %02x Message = %02x\n", - current_SC->SCp.Status, current_SC->SCp.Message)); + /* Kick the chip */ + outb(CHIP_RESET, CMD_REG); + outb(SCSI_NOP, CMD_REG); + chip_init(); - if(current_SC->SCp.Message == SAVE_POINTERS || - current_SC->SCp.Message == DISCONNECT) { - outb(SET_ATN, CMD_REG); /* Reject message */ - DEB(printk("Discarding SAVE_POINTERS message\n")); - } - outb(MSG_ACCEPT, CMD_REG); - break; - } -} - -#ifndef IRQ_LEV -static int irq_probe() -{ - int irqs, irq; - int i; - - inb(INT_REG); /* clear the interrupt register */ - sti(); - irqs = probe_irq_on(); - - /* Invalid command will cause an interrupt */ - REG0; - outb(0xff, CMD_REG); - - /* Wait for the interrupt to occur */ - i = jiffies + WATCHDOG; - while(i > jiffies && !(inb(STAT_REG) & 0x80)) - barrier(); - if (i <= jiffies) { /* Timed out, must be hardware trouble */ - probe_irq_off(irqs); - return -1; - } - - irq = probe_irq_off(irqs); - - /* Kick the chip */ - outb(CHIP_RESET, CMD_REG); - outb(SCSI_NOP, CMD_REG); - chip_init(); - - return irq; + return irq; } #endif IRQ_LEV static void chip_init() { - REG1; + REG1; #if USE_DMA - outb(0x00, PIO_STATUS); + outb(0x00, PIO_STATUS); #else /* USE_PIO */ - outb(0x01, PIO_STATUS); + outb(0x01, PIO_STATUS); #endif - outb(0x00, PIO_FLAG); - - outb(C4_IMG, CONFIG4); /* REG0; */ - outb(C3_IMG, CONFIG3); - outb(C2_IMG, CONFIG2); - outb(C1_IMG, CONFIG1); - - outb(0x05, CLKCONV); /* clock conversion factor */ - outb(0x9C, SRTIMOUT); /* Selection timeout */ - outb(0x05, SYNCPRD); /* Synchronous transfer period */ - outb(SYNC_MODE, SYNCOFF); /* synchronous mode */ + outb(0x00, PIO_FLAG); + + outb(C4_IMG, CONFIG4); /* REG0; */ + outb(C3_IMG, CONFIG3); + outb(C2_IMG, CONFIG2); + outb(C1_IMG, CONFIG1); + + outb(0x05, CLKCONV); /* clock conversion factor */ + outb(0x9C, SRTIMOUT); /* Selection timeout */ + outb(0x05, SYNCPRD); /* Synchronous transfer period */ + outb(SYNC_MODE, SYNCOFF); /* synchronous mode */ } void calc_port_addr() { -/* Control Register Set 0 */ -TC_LSB = (port_base+0x00); -TC_MSB = (port_base+0x01); -SCSI_FIFO = (port_base+0x02); -CMD_REG = (port_base+0x03); -STAT_REG = (port_base+0x04); -DEST_ID = (port_base+0x04); -INT_REG = (port_base+0x05); -SRTIMOUT = (port_base+0x05); -SEQ_REG = (port_base+0x06); -SYNCPRD = (port_base+0x06); -FIFO_FLAGS = (port_base+0x07); -SYNCOFF = (port_base+0x07); -CONFIG1 = (port_base+0x08); -CLKCONV = (port_base+0x09); -/* TESTREG = (port_base+0x0A); */ -CONFIG2 = (port_base+0x0B); -CONFIG3 = (port_base+0x0C); -CONFIG4 = (port_base+0x0D); -TC_HIGH = (port_base+0x0E); -/* FIFO_BOTTOM = (port_base+0x0F); */ - -/* Control Register Set 1 */ -/* JUMPER_SENSE = (port_base+0x00);*/ -/* SRAM_PTR = (port_base+0x01);*/ -/* SRAM_DATA = (port_base+0x02);*/ -PIO_FIFO = (port_base+0x04); -/* PIO_FIFO1 = (port_base+0x05);*/ -/* PIO_FIFO2 = (port_base+0x06);*/ -/* PIO_FIFO3 = (port_base+0x07);*/ -PIO_STATUS = (port_base+0x08); -/* ATA_CMD = (port_base+0x09);*/ -/* ATA_ERR = (port_base+0x0A);*/ -PIO_FLAG = (port_base+0x0B); -CONFIG5 = (port_base+0x0D); -/* SIGNATURE = (port_base+0x0E);*/ -/* CONFIG6 = (port_base+0x0F);*/ + /* Control Register Set 0 */ + TC_LSB = (port_base+0x00); + TC_MSB = (port_base+0x01); + SCSI_FIFO = (port_base+0x02); + CMD_REG = (port_base+0x03); + STAT_REG = (port_base+0x04); + DEST_ID = (port_base+0x04); + INT_REG = (port_base+0x05); + SRTIMOUT = (port_base+0x05); + SEQ_REG = (port_base+0x06); + SYNCPRD = (port_base+0x06); + FIFO_FLAGS = (port_base+0x07); + SYNCOFF = (port_base+0x07); + CONFIG1 = (port_base+0x08); + CLKCONV = (port_base+0x09); + /* TESTREG = (port_base+0x0A); */ + CONFIG2 = (port_base+0x0B); + CONFIG3 = (port_base+0x0C); + CONFIG4 = (port_base+0x0D); + TC_HIGH = (port_base+0x0E); + /* FIFO_BOTTOM = (port_base+0x0F); */ + + /* Control Register Set 1 */ + /* JUMPER_SENSE = (port_base+0x00);*/ + /* SRAM_PTR = (port_base+0x01);*/ + /* SRAM_DATA = (port_base+0x02);*/ + PIO_FIFO = (port_base+0x04); + /* PIO_FIFO1 = (port_base+0x05);*/ + /* PIO_FIFO2 = (port_base+0x06);*/ + /* PIO_FIFO3 = (port_base+0x07);*/ + PIO_STATUS = (port_base+0x08); + /* ATA_CMD = (port_base+0x09);*/ + /* ATA_ERR = (port_base+0x0A);*/ + PIO_FLAG = (port_base+0x0B); + CONFIG5 = (port_base+0x0D); + /* SIGNATURE = (port_base+0x0E);*/ + /* CONFIG6 = (port_base+0x0F);*/ } #ifdef MODULE @@ -1060,3 +1058,22 @@ Scsi_Host_Template driver_template = NCR53c406a; #include "scsi_module.c" #endif + +/* + * Overrides for Emacs so that we get a uniform tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-indent-level: 4 + * c-brace-imaginary-offset: 0 + * c-brace-offset: -4 + * c-argdecl-indent: 4 + * c-label-offset: -4 + * c-continued-statement-offset: 4 + * c-continued-brace-offset: 0 + * indent-tabs-mode: nil + * tab-width: 8 + * End: + */ diff --git a/drivers/scsi/NCR53c406a.h b/drivers/scsi/NCR53c406a.h index 80c78127c836..dcb48870bfdc 100644 --- a/drivers/scsi/NCR53c406a.h +++ b/drivers/scsi/NCR53c406a.h @@ -28,7 +28,7 @@ #define NCR53c406a { \ NULL /* next */, \ NULL /* usage count */, \ - NULL /* proc_dir */, \ + &proc_scsi_NCR53c406a /* proc_dir */, \ NULL /* proc_info */, \ "NCR53c406a" /* name */, \ NCR53c406a_detect /* detect */, \ @@ -49,6 +49,8 @@ ENABLE_CLUSTERING \ } +extern struct proc_dir_entry proc_scsi_NCR53c406a; + int NCR53c406a_detect(Scsi_Host_Template *); const char* NCR53c406a_info(struct Scsi_Host *); @@ -60,3 +62,22 @@ int NCR53c406a_biosparm(Disk *, kdev_t, int []); #endif /* _NCR53C406A_H */ +/* + * Overrides for Emacs so that we get a uniform tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-indent-level: 4 + * c-brace-imaginary-offset: 0 + * c-brace-offset: -4 + * c-argdecl-indent: 4 + * c-label-offset: -4 + * c-continued-statement-offset: 4 + * c-continued-brace-offset: 0 + * indent-tabs-mode: nil + * tab-width: 8 + * End: + */ + diff --git a/drivers/sound/.objects b/drivers/sound/.objects index 4ba152101b52..6162f79884ed 100644 --- a/drivers/sound/.objects +++ b/drivers/sound/.objects @@ -76,10 +76,6 @@ ifdef CONFIG_SEQUENCER OBJS := $(OBJS) sequencer.o endif -ifdef CONFIG_PNP - OBJS := $(OBJS) sound_pnp.o -endif - ifdef CONFIG_SEQUENCER OBJS := $(OBJS) sound_timer.o endif diff --git a/drivers/sound/.version b/drivers/sound/.version index dccae463dcfb..2f62e9bcc940 100644 --- a/drivers/sound/.version +++ b/drivers/sound/.version @@ -1,2 +1,2 @@ -3.5-alpha8 +3.5-beta2 0x030505 diff --git a/drivers/sound/CHANGELOG b/drivers/sound/CHANGELOG index 60fbb41c6d03..5e3fdba21a7e 100644 --- a/drivers/sound/CHANGELOG +++ b/drivers/sound/CHANGELOG @@ -1,5 +1,24 @@ -Changelog for version 3.5-alpha8 --------------------------------- +Changelog for version 3.5-beta2 +------------------------------- + +Since 3.5-beta1 +- Bugfixes. +- Full duplex audio with MAD16+CS4231 may work now. The driver configures + SB DMA of MAD16 so that it doesn't conflict with codec's DMA channels. + The side effect is that all 8 bit DMA channels (0,1,3) are populated in duplex + mode. + +Since 3.5-alpha9 +- Bugfixes (mostly in Jazz16 and ESS1688/688 supports). +- Temporarily disabled recording with ESS1688/688 since it causes crash. +- Changed audio buffer partitioning algorithm so that it selects + smaller fragment size than earlier. This improves real time capabilities + of the driver and makes recording to disk to work better. Unfortunately + this change breaks some programs which assume that fragments cannot be + shorter than 4096 bytes. + +Since 3.5-alpha8 +- Bugfixes Since 3.5-alpha7 - Linux kernel compatible configuration (_EXPERIMENTAL_). Enable diff --git a/drivers/sound/COPYING b/drivers/sound/COPYING index d1509c500253..1489ab70cbd3 100644 --- a/drivers/sound/COPYING +++ b/drivers/sound/COPYING @@ -1,25 +1,25 @@ /* - * Copyright by Hannu Savolainen 1993 + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. + * modification, are permitted provided that the following conditions are + * met: 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. 2. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ +#include + diff --git a/drivers/sound/Config.in b/drivers/sound/Config.in index de49f5025c7e..447e82f6f126 100644 --- a/drivers/sound/Config.in +++ b/drivers/sound/Config.in @@ -3,7 +3,7 @@ # #-------- # There is another confic script which is compatible with rest of -# the kernel. It can be activated by running 'make script' in this +# the kernel. It can be activated by running 'make mkscript' in this # directory. Please note that this is an _experimental_ feature which # doesn't work with all cards (PSS, SM Wave, AudioTriX Pro). #-------- diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile index 8bf2ffc9240a..e160199b3571 100644 --- a/drivers/sound/Makefile +++ b/drivers/sound/Makefile @@ -22,14 +22,12 @@ OBJS = audio.o dmabuf.o sb_dsp.o \ gus_midi.o gus_vol.o patmgr.o sb_mixer.o sb16_dsp.o sb_midi.o \ sb16_midi.o midi_synth.o uart6850.o sound_timer.o \ sys_timer.o ics2101.o ad1848.o pss.o sscape.o trix.o aedsp16.o \ - mad16.o mad16_sb_midi.o cs4232.o maui.o sound_pnp.o + mad16.o mad16_sb_midi.o cs4232.o maui.o endif build: - @echo Compiling modularized sound driver @make sound.o - @echo Sound module compiled. install: sound.o cp sound.o $(MODULEDIR) @@ -53,7 +51,7 @@ ifndef HOSTCC # CC = gcc HOSTCC = gcc -CFLAGS = -D__KERNEL__ -DMODULE -DMODVERSIONS -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -m486 +CFLAGS = -D__KERNEL__ -DMODULE -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -m486 else include $(TOPDIR)/Rules.make endif @@ -112,7 +110,7 @@ kernelconfig: setup-$(TARGET_OS) # @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) +mkscript: setup-$(TARGET_OS) rm -f configure $(HOSTCC) -o configure configure.c ./configure script > Config.in diff --git a/drivers/sound/Readme b/drivers/sound/Readme index c08986977092..01de214e99d8 100644 --- a/drivers/sound/Readme +++ b/drivers/sound/Readme @@ -1,22 +1,27 @@ -VoxWare v3.5-alpha4 release notes ---------------------------------- +Version 3.5-beta2 release notes +------------------------------- IMPORTANT! This version of the driver is compatible only with Linux versions - 1.3.58 and later. It may work with earlier ones as a loadable + 1.3.59 to 1.3.6x. It may work with few earlier ones as a loadable module but... - Also this is an ALPHA test version which has not been tested - with all cards. At least AEDSP16 support will not work. PAS16 - and PSS supports have not been tested. /dev/dsp and /dev/audio - playback with standard GUS sounds scrambled. 16 bit mode of - SB16 doesn't work. + This is a BETA test version. Most known bugs should have been fixed. + However it's possible that there are still bugs. Please report them + to me ASAP so that they can be fixed before Linux 1.4. But look + at the web page (see below) before sending me a bug report. + + Crashing with GUS should be fixed now. + Recording is still disabled with ESS1688/688 cards since it + causes a crash. Please read the SOUND-HOWTO (available from sunsite.unc.edu and other Linux ftp -sites). It contains much more information than this file. +sites). It gives instructions about using sound with Linux. It's bit out of +date but still very useful. Information about bug fixes and such things +is available from the web page (see below). ***************************************************************** -* NEW! VoxWare home page is http://personal.eunet.fi/pp/voxware * +* NEW! Driver's home page is http://personal.eunet.fi/pp/voxware* * The file Readme.cards contains card specific instructions * * about configuring various cards. * ***************************************************************** @@ -30,7 +35,7 @@ was accidently removed some time ago but it's now back. I have got many patches from various persons during last year. Some of them are still on my mailbox and they should be included in versions -after v3.0 (I will not add aditional features before v3.0 is ready). +after v3.5 (I will not add aditional features before v3.5 is ready). ==================================================== - THIS VERSION ____REQUIRES____ Linux 1.3.58 OR LATER. @@ -55,6 +60,8 @@ Supported soundcards Gravis Ultrasound (GUS) GUS MAX GUS with the 16 bit sampling daughtercard +GUS ACE +GUS PnP support should be available around May 1996. PAS16 Windows Sound System compatible soundcards ECHO-PSS (cards based on the PSS architecture by Analog Devices. @@ -63,7 +70,8 @@ ECHO-PSS (cards based on the PSS architecture by Analog Devices. MediaTriX AudioTriX Pro (OPL4 and the optional effect daughtercard require special initialization. There is a program (setfx) in the snd-util-3.0.tar.gz package which does it). -Ensoniq SoundScape (works but needs some improvements) +Ensoniq SoundScape & SoundScape Elite +Ensonig SoundScape PnP not supported yet (summer 1996?) MV Jazz16 based soundcards (ProSonic, 3D etc). SoundMan Wave Mozart (OAK OTI-601 interface chip) based soundcards. @@ -72,19 +80,17 @@ MAD16 (an interface chip by OPTi) based soundcards (TB Tropez ???). idea to configure MAD16 cards as Mozart ones. The MAD16 driver doesn't set up MPU401 which the Mozart one does. CS4232 based cards such as AcerMagic S23. +ESS ES1688 based soundcards. In addition all Sound Blaster models and clones (up to AWE32) work if -you want to use them. +you want to use them. SB16/SB32/AWE32 PnP models don't work yet. See the web +page for more info. -The Emu synthesizer chip of AWE32 is not and will not be supported. The same is +The Emu synthesizer chip of AWE32 will not be supported soon. The same is true with the ASP chip also. Creative Technology will not release detailed information about them so it's not possible to support them. -If you want to get support for AWE32 or ASP, please contact Creative Labs. -Ask _politely_ if they are going to support Linux. Maybe they change -their policy if there is enough demand. - =========================================================================== If your card is compatible with SB, MPU401 or Windows Sound System, it may work with the driver even if it's not listed in the above list. In this @@ -109,7 +115,6 @@ contributors. (I could have forgotten some names.) Craig Metz 1/2 of the PAS16 Mixer and PCM support Rob Hooft Volume computation algorithm for the FM synth. Mika Liljeberg uLaw encoding and decoding routines - Andy Fingerhut New ulaw conversion tables (ulaw.h) Jeff Tranter Linux SOUND HOWTO document Greg Lee Volume computation algorithm for the GUS and lot's of valuable suggestions. @@ -223,7 +228,7 @@ For owners of TI TM4000M notebooks ---------------------------------- There appears to be some kind of conflict between the sound support -(MV Jazz), mouse port and VoxWare. You could try to configure kernel +(MV Jazz), mouse port and the sound driver. You could try to configure kernel with the C&T 82C710 mouse port support disabled. Hannu @@ -232,7 +237,6 @@ Regards, Hannu Savolainen hannu@voxware.pp.fi -(or Hannu.Savolainen@cctap.carel.fi in case the above bounces) Snail mail: Hannu Savolainen Hiekkalaiturintie 3 A 8 @@ -245,4 +249,4 @@ NOTE! I propably don't answer to Snail mail or FAX messages. Sending answer get response, please check how your address is written in the message header. I can't answer if I don't have a valid reply address. -VoxWare home page is http://personal.eunet.fi/pp/voxware +Sound driver's home page is http://personal.eunet.fi/pp/voxware diff --git a/drivers/sound/Readme.cards b/drivers/sound/Readme.cards index 3d0da809d2ef..779addb7d134 100644 --- a/drivers/sound/Readme.cards +++ b/drivers/sound/Readme.cards @@ -1,4 +1,4 @@ -Configuring VoxWare 3.0 (for Linux) with some most common soundcards +Configuring version 3.5 (for Linux) with some most common soundcards ==================================================================== NOTE! This document may contain some error. Please inform me @@ -7,10 +7,10 @@ NOTE! This document may contain some error. Please inform me Read this before trying to configure the driver ----------------------------------------------- -There are currently many cards that work with VoxWare. Some of the cards +There are currently many cards that work with this driver. Some of the cards have native support while the others work since they emulate some other cards (usually SB, MSS/WSS and/or MPU401). The following cards have native -support in VoxWare. Detailed instructions for configuring these cards +support in the driver. Detailed instructions for configuring these cards will be given later in this document. Pro Audio Spectrum 16 (PAS16) and compatibles: @@ -18,7 +18,7 @@ Pro Audio Spectrum 16 (PAS16) and compatibles: Pro Audio Studio 16 Logitech Sound Man 16 NOTE! The original Pro Audio Spectrum as well as the PAS+ are not - and will not be supported by VoxWare. + and will not be supported by the driver. Media Vision Jazz16 based cards Pro Sonic 16 @@ -33,7 +33,7 @@ Sound Blasters NOTE! The ASP chip and the EMU synth of the AWE32 is not supported since their manufacturer doesn't release information about the card. However both the AB16ASP and the AWE32 work with - VoxWare just like a SB16. Also see the comment about some + the driver just like a SB16. Also see the comment about some unsupported cards at the end of this file. SB16 compatible cards by other manufacturers than Creative. You have been fooled since there are no SB16 compatible @@ -47,6 +47,7 @@ Gravis Ultrasound (GUS) GUS + the 16 bit option GUS MAX GUS ACE (No MIDI port and audio recording) + GUS PnP (Partially supported) MPU-401 and compatibles The driver works both with the full (intelligent mode) MPU-401 @@ -54,7 +55,7 @@ MPU-401 and compatibles dumb MIDI ports. MPU-401 is currently the most common MIDI interface. Most soundcards are compatible with it. However don't enable MPU401 mode blindly. Many cards having native support - in VoxWare have their own MPU401 driver. Enabling the standard one + in the driver have their own MPU401 driver. Enabling the standard one will cause a conflict with these cards. So look if your card is in the list of supported cards before enabling MPU401. @@ -69,16 +70,16 @@ Windows Sound System (MSS/WSS) Having a AD1848, CS4248 or CS4231 codec chip on the card is a good sign. Even if the card is not MSS compatible, it could be easy to write - support for it to VoxWare. Note also that most MSS compatible cards + support for it. Note also that most MSS compatible cards require special boot time initialization which may not be present - in VoxWare. Also some MSS compatible cards have native support in - VoxWare. Enabling the MSS support with these cards is likely to + in in the driver. Also some MSS compatible cards have native support. + Enabling the MSS support with these cards is likely to cause a conflict. So check if your card is listed in this file before enabling the MSS support. 6850 UART MIDI This UART chip is used in the MIDI interface of some (rare) - soundcards. It's supported by VoxWare in case you need it. + soundcards. It's supported by the driver in case you need it. Yamaha FM synthesizers (OPL2, OPL3 and OPL4) Most soundcards have a FM synthesizer chip. The OPL2 is a 2 @@ -86,10 +87,10 @@ Yamaha FM synthesizers (OPL2, OPL3 and OPL4) only in the cheapest (8 bit mono) cards. The OPL3 is a 4 operator FM chip which provides better sound quality and/or more available voices than the OPL2. The OPL4 is a new chip which has a OPL3 and - a wave table synthesizer packed on the same chip. VoxWare supports + a wave table synthesizer packed on the same chip. The driver supports just the OPL3 mode directly. Most cards having a OPL4 (like SM Wave and AudioTriX Pro) support the OPL4 mode using MPU401 - emulation. Writing a native OPL4 support to VoxWare is difficult + emulation. Writing a native OPL4 support is difficult since Yamaha doesn't give information about their sample ROM chip. Enable the generic OPL2/OPL3 FM synthesizer support if your @@ -104,7 +105,7 @@ PSS based cards (AD1848 + ADSP-2115 + Echo ESC614 ASIC) There are several cards based on this architecture. The most known ones are Orchid SW32 and Cardinal DSP16. - VoxWare supports downloading DSP algorithms to these cards. + The driver supports downloading DSP algorithms to these cards. MediaTriX AudioTriX Pro The ATP card is built around a CS4231 codec and a OPL4 synthesizer @@ -129,14 +130,15 @@ MAD16 and Mozart based cards Audio Excell DSP16 Support for this card is made by Riccardo Faccetti (riccardo@cdc8g5.cdc.polimi.it). See aedsp16.c for more info. + (This driver is not functional in 3.5 versions of this driver). -Crystal CS4232 based cards such as AcerMagic S23 +Crystal CS4232 based cards such as AcerMagic S23 and many PC motherboards. CS4232 is a PnP multimedia chip which contains a CS3231A codec, SB and MPU401 emulations. There is support for OPL3 too. (Unfortunately the MPU401 mode doesn't work). Turtle Beach Maui and Tropez - VoxWare supports sample, parch and program loading commands + This driver version supports sample, patch and program loading commands described in the Maui/Tropez User's manual. There is no initialization code for Maui so it must be initialized using DOS. Audio side of Tropez is based on the MAD16 chip (see above). @@ -145,7 +147,7 @@ Jumpers and software configuration ---------------------------------- Some of the earliest soundcards were jumper configurable. You have to -configure VoxWare to configure VoxWare use I/O, IRQ and DMA settings +configure the driver use I/O, IRQ and DMA settings that match the jumpers. Just few 8 bit cards are fully jumper configurable (SB 1.x/2.x, SB Pro and clones). Some cards made by Aztech have an EEPROM which contains the @@ -157,14 +159,14 @@ are software configurable. Sometimes there are few other jumpers too. Latest cards are fully software configurable or they are PnP ISA compatible. There are no jumpers on the board. -VoxWare handles software configurable cards automaticly. Just configure +The driver handles software configurable cards automaticly. Just configure the driver to use I/O, IRQ and DMA settings which are known to work. You could usually use the same values than with DOS and/or Windows. Using different settings is possible but not recommended since it may cause some trouble (for example when warm booting from an OS to another or when installing new hardware to the machine). -VoxWare sets the soft configurable parameters of the card automaticly +Sound driver sets the soft configurable parameters of the card automaticly during boot. Usually you don't need to run any extra initialization programs when booting Linux but there are some exceptions. See the card specific instructions (below) for more info. @@ -179,7 +181,7 @@ What if your card was not listed above? The first thing to do is to look at the major IC chips on the card. Many of the latest soundcards are based on some standard chips. If you -are lucky, all of them could be supported by VoxWare. The most common ones +are lucky, all of them could be supported by the driver. The most common ones are the OPTi MAD16, Mozart, SoundScape (Ensoniq) and the PSS architectures listed above. Also look at the end of this file for list of unsupported cards and the ones which could be supported later. @@ -194,20 +196,17 @@ such as SB, MSS and/or MPU401. In this case there is a chance to get the card to work by booting DOS before starting Linux (boot DOS, hit ctrl-alt-del and boot Linux without hard resetting the machine). In this method the DOS based driver initializes the hardware to use a known I/O, IRQ and DMA -settings. If VoxWare is configured to use the same settings, everything should +settings. If sound driver is configured to use the same settings, everything should work OK. -Configuring VoxWare (with Linux) -================================ +Configuring sound driver (with Linux) +===================================== -VoxWare sound driver is currently a part of Linux kernel distribution. The +Sound driver is currently a part of Linux kernel distribution. The driver files are located in directory /usr/src/linux/drivers/sound. **************************************************************************** -* VoxWare MUST BE CONFIGURED AND COMPILED WITH THE KERNEL. TRYING * -* TO COMPILE IT ALONE WILL _NOT_ WORK. * -* * * ALWAYS USE THE SOUND DRIVER VERSION WHICH IS DISTRIBUTED WITH * * THE KERNEL SOURCE PACKAGE YOU ARE USING. SOME ALPHA AND BETA TEST * * VERSIONS CAN BE INSTALLED FROM A SEPARATELY DISTRIBUTED PACKAGE * @@ -322,7 +321,7 @@ select some options automaticly as well. safe to answer 'y' in case you have the original Windows Sound System card made by Microsoft or Aztech SG 16 Pro (or NX16 Pro). Also you may answer 'y' in case your card was not listed earlier - in this file. For cards having native support in VoxWare, consult + in this file. For cards having native support in the driver, consult the card specific instructions later in this file. Some drivers have their own MSS support and enabling this option wil cause a conflict. @@ -338,7 +337,7 @@ select some options automaticly as well. currently quite common so it's possible that many no-name cards 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). + Reveal (some models) and Diamond (some recent models). "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 @@ -382,7 +381,7 @@ Card specific information This section gives additional instructions about configuring some cards. Please refer manual of your card for valid I/O, IRQ and DMA numbers. Using -the same settings with DOS/Windows and VoxWare is recommended. Using +the same settings with DOS/Windows and Linux is recommended. Using different values could cause some problems when switching between different operating systems. @@ -497,6 +496,11 @@ just one 8 bit DMA channel. Recording will not work with one DMA channel if it's a 16 bit one. +GUS ACE works too but any attempt to record or to use the MIDI port +will fail. + +GUS PnP (with RAM) is supported but it needs to be initialized using +DOS before booting Linux. This may fail on machines having PnP BIOS. MPU401 and Windows Sound System ------------------------------- @@ -509,7 +513,7 @@ you should propably enable the OPL3 synth also since most MSS compatible cards have it. However check that this is true before enabling OPL3. -VoxWare supports more than one MPU401 compatible cards at the same time +Sound driver supports more than one MPU401 compatible cards at the same time but the config program asks config info for just the first of them. Adding the second or third MPU interfaces must be done manually by editing sound/local.h (after running the config program). Add defines for @@ -542,7 +546,7 @@ the file when configuring the driver. The easiest way is to mount the DOS partition containing the file with Linux. It's possible to load your own DSP algorithms and run them with the card. -Look at the directory sound/pss_test for more info (in the VoxWare-3.0.tar.gz) +Look at the directory pss_test of snd-util-3.0.tar.gz for more info.§ package. AudioTriX Pro @@ -586,9 +590,9 @@ that's the reason why it's there. It's possible that 'primary' pcm channel becomes supported later. Currently the card's firmware doesn't contain support for it. -With 3.0 of VoxWare you have to change your system to use /dev/dsp1 by default -so execute: cd /dev;rm dsp;ln -s dsp1 dsp after you have installed VoxWare -3.0 (first time). +With 3.0 of the driver you have to change your system to use /dev/dsp1 by default +so execute: cd /dev;rm dsp;ln -s dsp1 dsp after you have installed driver +version 3.0 (or later) first time. The configuration program asks two DMA channels and two interrupts. One IRQ and one DMA is used by the MSS codec. The second IRQ is required for the @@ -653,16 +657,21 @@ It can be used by enabling the stand alone MPU401 support but you have to initialize it by using the MS-DOS SNDSETUP program. There are some other OPTi chips which may be used in soundcards such as -82C930 and MAC32. These chips are not supported by VoxWare yet. Please +82C930 and MAC32. These chips are not supported by the driver yet. Please contact me if you have a soundcard which uses these chips. Some MAD16 based cards may cause feedback, whistle or terrible noise if the -line3 mixer channel is turned too high. +line3 mixer channel is turned too high. This happens at least with Shuttle +Sound System. If you have a MAD16 card which have an OPL4 (FM + Wave table) synthesizer chip (_not_ an OPL3), you have to apped line containing #define MAD16_OPL4 to the file linux/dirvers/sound/local.h (after running make config). +MAD16 cards having a CS4231 codec support full duplex mode. This mode +can be enabled by configuring the card to use two DMA channels. Possible +DMA channel pairs are: 0&1, 1&0 and 3&0. + MV Jazz (ProSonic) ------------------ @@ -714,7 +723,7 @@ The older 16 bit cards (SG Pro16, SG NX Pro16, Nova and Lyra) have an EEPROM chip for storing the configuration data. There is a microcontroller which initializes the card to match the EEPROM settigs when the machine is powered on. These cards actually behave just like they have jumpers -for all of the settings. Configure VoxWare for MSS, MPU, SB/SB Pro and OPL3 +for all of the settings. Configure driver for MSS, MPU, SB/SB Pro and OPL3 supports with these cards. The config program asks if you want support for the mixer of @@ -742,7 +751,7 @@ Diamond The oldest (Sierra Aria based) soundcards made by Diamond are not supported (they may work if the card is initialized using DOS). The recent (LX?) -models are based on the MAD16 chip which is supported by VoxWare. +models are based on the MAD16 chip which is supported by the driver. Audio Excel DSP16 ----------------- @@ -810,7 +819,7 @@ Some companies don't give low level technical information about their products to public or at least their require signing a NDA. I have also made decicion to not accept code based on reverse engineering -to VoxWare. There are three main reasons: First I don't want to break +to the driver. There are three main reasons: First I don't want to break relationships to sound card manufacturers. The second reason is that maintaining and supporting a driver withoun any specs will be a pain. The third reason is that why shoud we help such companies in selling their @@ -831,12 +840,12 @@ same with many DOS based freeware/shareware games and utilities). If you want to use Linux/Unix with their cards, please don't try to push me. It's a better idea to contact the manufacturer and explain that you want to use your card with Linux/Unix. You could also try to sell -your card to somebody else and then buy a card that is supported by VoxWare. +your card to somebody else and then buy a card that is supported by the driver. However it's possible that things change and a driver gets written for some of the banned cards. Please, don't send me messages asking if 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). +will put any news to sound driver's www home page (see below). There are some common audio chipsets that are not supported yet. For example Sierra Aria and IBM Mwave. It's possible that these architectures @@ -850,5 +859,5 @@ If you have any corrections and/or comments, please contact me. Hannu Savolainen hannu@voxware.pp.fi -VoxWare www home page: http://personal.eunet.fi/pp/voxware +Sound driver's www home page: http://personal.eunet.fi/pp/voxware diff --git a/drivers/sound/Readme.linux b/drivers/sound/Readme.linux index 5c5da08784cd..72def564d372 100644 --- a/drivers/sound/Readme.linux +++ b/drivers/sound/Readme.linux @@ -215,8 +215,14 @@ hannu@voxware.pp.fi if [ -e /dev/mixer ]; then rm -f /dev/mixer fi + +if [ -e /dev/mixer0 ]; then + rm -f /dev/mixer0 +fi -mknod -m 666 /dev/mixer c 14 0 +mknod -m 666 /dev/mixer0 c 14 0 +ln -sf /dev/mixer0 /dev/mixer + if [ -e /dev/mixer1 ]; then rm -f /dev/mixer1 fi @@ -260,6 +266,7 @@ fi rm -f /dev/midi00 fi mknod -m 666 /dev/midi00 c 14 2 + ln -sf /dev/midi00 /dev/midi if [ -e /dev/midi01 ]; then rm -f /dev/midi01 diff --git a/drivers/sound/Readme.modules b/drivers/sound/Readme.modules index 2dab12552d1b..7fa6a279c792 100644 --- a/drivers/sound/Readme.modules +++ b/drivers/sound/Readme.modules @@ -1,7 +1,7 @@ Building a loadable sound driver ================================ -Loadable module support in version 3.5 of VoxWare is mostly rewritten since +Loadable module support in version 3.5 of the driver is mostly rewritten since the previous version (3.0.1). This means that some things have changed. To compile the sound driver as a loadable module you have to perform diff --git a/drivers/sound/Readme.v30 b/drivers/sound/Readme.v30 index 826710ea09cf..ee352489d72c 100644 --- a/drivers/sound/Readme.v30 +++ b/drivers/sound/Readme.v30 @@ -1,5 +1,5 @@ -VoxWare v3.0 ------------- +Sound driver version v3.0 (and later) +------------------------------------- All features of v2.90-2 should work as earlier. There could be some omissions but they are unintentional. I started this version thread diff --git a/drivers/sound/ad1848.c b/drivers/sound/ad1848.c index 9cc24033afb4..a734d099cd2b 100644 --- a/drivers/sound/ad1848.c +++ b/drivers/sound/ad1848.c @@ -12,8 +12,10 @@ * * CS4232 is a PnP audio chip which contains a CS4231A (and SB, MPU). * CS4232A is an improved version of CS4232. - * - * Copyright by Hannu Savolainen 1994, 1995 + */ + +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -34,11 +36,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * Modified: - * Riccardo Facchetti 24 Mar 1995 - * - Added the Audio Excel DSP 16 initialization routine. */ +#include + #define DEB(x) #define DEB1(x) @@ -83,7 +83,7 @@ typedef struct volatile unsigned long timer_ticks; int timer_running; int irq_ok; - sound_os_info *osp; + int *osp; } ad1848_info; @@ -98,13 +98,14 @@ static int timer_installed = -1; static char mixer2codec[MAX_MIXER_DEV] = {0}; -static int ad_format_mask[5 /*devc->mode */ ] = +static int ad_format_mask[6 /*devc->mode */ ] = { 0, AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW, AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_U16_LE | AFMT_IMA_ADPCM, AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_U16_LE | AFMT_IMA_ADPCM, - AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW /* AD1845 */ + AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW, /* AD1845 */ + AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_U16_LE | AFMT_IMA_ADPCM }; static ad1848_info dev_info[MAX_AUDIO_DEV]; @@ -116,7 +117,7 @@ static ad1848_info dev_info[MAX_AUDIO_DEV]; static int ad1848_open (int dev, int mode); static void ad1848_close (int dev); -static int ad1848_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local); +static int ad1848_ioctl (int dev, unsigned int cmd, caddr_t arg, int local); static void ad1848_output_block (int dev, unsigned long buf, int count, int intrflag, int dma_restart); static void ad1848_start_input (int dev, unsigned long buf, int count, int intrflag, int dma_restart); static int ad1848_prepare_for_IO (int dev, int bsize, int bcount); @@ -461,7 +462,7 @@ ad1848_mixer_reset (ad1848_info * devc) } static int -ad1848_mixer_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +ad1848_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg) { ad1848_info *devc; @@ -781,7 +782,7 @@ set_format (ad1848_info * devc, int arg) } static int -ad1848_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local) +ad1848_ioctl (int dev, unsigned int cmd, caddr_t arg, int local) { ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; @@ -1126,7 +1127,7 @@ ad1848_trigger (int dev, int state) } int -ad1848_detect (int io_base, int *ad_flags, sound_os_info * osp) +ad1848_detect (int io_base, int *ad_flags, int *osp) { unsigned char tmp; @@ -1369,7 +1370,7 @@ ad1848_detect (int io_base, int *ad_flags, sound_os_info * osp) } void -ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture, int share_dma, sound_os_info * osp) +ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture, int share_dma, int *osp) { /* * NOTE! If irq < 0, there is another driver which has allocated the IRQ @@ -1654,6 +1655,7 @@ void check_opl3 (int base, struct address_info *hw_config) { +#ifdef CONFIG_YM3812 if (check_region (base, 4)) { printk ("\n\nopl3.c: I/O port %x already in use\n\n", base); @@ -1665,6 +1667,7 @@ check_opl3 (int base, struct address_info *hw_config) opl3_init (0, base, hw_config->osp); request_region (base, 4, "OPL3/OPL2"); +#endif } int @@ -1686,15 +1689,6 @@ probe_ms_sound (struct address_info *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. - */ - - InitAEDSP16_MSS (hw_config); -#endif - /* * Check if the IO port returns valid signature. The original MS Sound * system returns 0x04 while some cards (AudioTriX Pro for example) diff --git a/drivers/sound/ad1848_mixer.h b/drivers/sound/ad1848_mixer.h index 3fcacf75503d..4f4879be74cc 100644 --- a/drivers/sound/ad1848_mixer.h +++ b/drivers/sound/ad1848_mixer.h @@ -2,9 +2,11 @@ * sound/ad1848_mixer.h * * Definitions for the mixer of AD1848 and compatible codecs. - * - * Copyright by Hannu Savolainen 1994 - * + */ + +/* + * Copyright by Hannu Savolainen 1993-1996 + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -12,7 +14,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -25,6 +27,8 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ + + /* * The AD1848 codec has generic input lines called Line, Aux1 and Aux2. * Soundcard manufacturers have connected actual inputs (CD, synth, line, diff --git a/drivers/sound/adlib_card.c b/drivers/sound/adlib_card.c index 769698560082..18682ba371c1 100644 --- a/drivers/sound/adlib_card.c +++ b/drivers/sound/adlib_card.c @@ -2,8 +2,10 @@ * sound/adlib_card.c * * Detection routine for the AdLib card. - * - * Copyright by Hannu Savolainen 1993 + */ + +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -24,8 +26,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ +#include + #include "sound_config.h" diff --git a/drivers/sound/aedsp16.c b/drivers/sound/aedsp16.c index 9dbdc1ca06d0..c85d22ba4c99 100644 --- a/drivers/sound/aedsp16.c +++ b/drivers/sound/aedsp16.c @@ -29,6 +29,7 @@ * Include the main voxware header file. It include all the os/voxware/etc * headers needed by this source. */ +#include #include "sound_config.h" #ifndef AEDSP16_BASE diff --git a/drivers/sound/audio.c b/drivers/sound/audio.c index 12e071efe54c..3212dc1f7aad 100644 --- a/drivers/sound/audio.c +++ b/drivers/sound/audio.c @@ -2,8 +2,10 @@ * sound/audio.c * * Device file manager for /dev/audio - * - * Copyright by Hannu Savolainen 1993 + */ + +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -24,8 +26,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ +#include + #include "sound_config.h" @@ -64,7 +67,7 @@ set_format (int dev, int fmt) else fmt = AFMT_U8; /* This is always supported */ - audio_format[dev] = DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, (ioctl_arg) fmt, 1); + audio_format[dev] = DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, (caddr_t) fmt, 1); } if (local_conversion[dev]) /* This shadows the HW format */ @@ -103,7 +106,7 @@ audio_open (int dev, struct fileinfo *file) local_conversion[dev] = 0; - if (DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, (ioctl_arg) bits, 1) != bits) + if (DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, (caddr_t) bits, 1) != bits) { audio_release (dev, file); return -ENXIO; @@ -181,7 +184,7 @@ translate_bytes (const void *table, void *buff, int n) #endif int -audio_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count) +audio_write (int dev, struct fileinfo *file, const char *buf, int count) { int c, p, l, buf_no, buf_ptr, buf_size; int err; @@ -267,7 +270,7 @@ audio_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count) } int -audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) +audio_read (int dev, struct fileinfo *file, char *buf, int count) { int c, p, l; char *dmabuf; @@ -330,7 +333,7 @@ audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) int audio_ioctl (int dev, struct fileinfo *file, - unsigned int cmd, ioctl_arg arg) + unsigned int cmd, caddr_t arg) { dev = dev >> 4; @@ -376,7 +379,7 @@ audio_ioctl (int dev, struct fileinfo *file, { audio_buf_info info; - int err = DMAbuf_ioctl (dev, cmd, (ioctl_arg) & info, 1); + int err = DMAbuf_ioctl (dev, cmd, (caddr_t) & info, 1); if (err < 0) return err; @@ -394,7 +397,7 @@ audio_ioctl (int dev, struct fileinfo *file, char *dma_buf; int buf_no, buf_ptr, buf_size; - int err = DMAbuf_ioctl (dev, cmd, (ioctl_arg) & info, 1); + int err = DMAbuf_ioctl (dev, cmd, (caddr_t) & info, 1); if (err < 0) return err; @@ -457,15 +460,19 @@ audio_select (int dev, struct fileinfo *file, int sel_type, select_table_handle switch (sel_type) { case SEL_IN: - if (!(audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX)) - return 0; /* Not recording */ + if (audio_mode[dev] & AM_WRITE && !(audio_devs[dev]->flags & DMA_DUPLEX)) + { + return 0; /* Not recording */ + } return DMAbuf_select (dev, file, sel_type, wait); break; case SEL_OUT: - if (!(audio_mode[dev] & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX)) - return 0; /* Wrong direction */ + if (audio_mode[dev] & AM_READ && !(audio_devs[dev]->flags & DMA_DUPLEX)) + { + return 0; /* Wrong direction */ + } if (DMAbuf_get_curr_buffer (dev, &buf_no, &dma_buf, &buf_ptr, &buf_size) >= 0) { diff --git a/drivers/sound/configure.c b/drivers/sound/configure.c index 770e17d2a094..802b881c8611 100644 --- a/drivers/sound/configure.c +++ b/drivers/sound/configure.c @@ -1,8 +1,13 @@ +/* + * PnP support is not included in this driver version. + * AEDSP16 will not work without significant changes. + */ #define DISABLED_OPTIONS (B(OPT_PNP)|B(OPT_AEDSP16)) /* * sound/configure.c - Configuration program for the Linux Sound Driver - * - * Copyright by Hannu Savolainen 1993-1995 + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -23,9 +28,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ + #include #include #include @@ -662,7 +667,7 @@ ask_parameters (void) if (selected_options & B (OPT_PAS)) { - fprintf (stderr, "\nEnable Joystick port on ProAudioSpectrum (n/y) ? "); + fprintf (stderr, "\nEnable Joystick port on ProAudioSpectrum (y/N) ? "); if (think_positively (0)) printf ("#define PAS_JOYSTICK_ENABLE\n"); @@ -671,7 +676,7 @@ ask_parameters (void) "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) ?"); + "Do you have to use this switch with DOS (Y/n) ?"); if (think_positively (0)) printf ("#define BROKEN_BUS_CLOCK\n"); } @@ -1111,7 +1116,7 @@ main (int argc, char *argv[]) if (access (oldconf, R_OK) == 0) { - fprintf (stderr, "Old configuration exists in %s. Use it (y/n) ? ", + fprintf (stderr, "Old configuration exists in %s. Use it (Y/n) ? ", oldconf); if (think_positively (1)) if (use_old_config (oldconf)) @@ -1149,7 +1154,7 @@ main (int argc, char *argv[]) int def_answ = hw_table[i].default_answ; fprintf (stderr, - def_answ ? " %s (y/n) ? " : " %s (n/y) ? ", + def_answ ? " %s (Y/n) ? " : " %s (y/N) ? ", questions[i]); if (think_positively (def_answ)) if (hw_table[i].alias) @@ -1172,7 +1177,7 @@ main (int argc, char *argv[]) fprintf (stderr, "Do you want support for the MV Jazz16 (ProSonic etc.) ? "); if (think_positively (0)) { - fprintf (stderr, "Do you have SoundMan Wave (n/y) ? "); + fprintf (stderr, "Do you have SoundMan Wave (y/N) ? "); if (think_positively (0)) { @@ -1184,7 +1189,7 @@ main (int argc, char *argv[]) "Logitech SoundMan Wave has a microcontroller which must be initialized\n" "before MIDI emulation works. This is possible only if the microcode\n" "file is compiled into the driver.\n" - "Do you have access to the MIDI0001.BIN file (y/n) ? "); + "Do you have access to the MIDI0001.BIN file (Y/n) ? "); if (think_positively (1)) { char path[512]; @@ -1223,7 +1228,7 @@ main (int argc, char *argv[]) "\n" "DANGER! Read the above once again before answering 'y'\n" "Answer 'n' in case you are unsure what to do!\n"); - fprintf (stderr, "Do you have a Logitech SoundMan Games (n/y) ? "); + fprintf (stderr, "Do you have a Logitech SoundMan Games (y/N) ? "); if (think_positively (0)) printf ("#define SM_GAMES\n"); } @@ -1272,7 +1277,7 @@ main (int argc, char *argv[]) (stderr, "if you wish to emulate the soundblaster and you have a DSPxxx.LD.\n" "then you must include the LD in the kernel.\n" - "Do you wish to include a LD (y/n) ? "); + "Do you wish to include a LD (Y/n) ? "); if (think_positively (1)) { char path[512]; @@ -1318,7 +1323,7 @@ main (int argc, char *argv[]) "modes of AudioTriX Pro will not work without\n" "this file!\n" "\n" - "Do you want to include TRXPRO.HEX in your kernel (y/n) ? "); + "Do you want to include TRXPRO.HEX in your kernel (Y/n) ? "); if (think_positively (1)) { @@ -1377,7 +1382,7 @@ main (int argc, char *argv[]) if (!old_config_used) { - fprintf (stderr, "Save copy of this configuration to %s (y/n)", oldconf); + fprintf (stderr, "Save copy of this configuration to %s (Y/n)", oldconf); if (think_positively (1)) { char cmd[200]; diff --git a/drivers/sound/cs4232.c b/drivers/sound/cs4232.c index 0fa6dd120167..f5fe0464a165 100644 --- a/drivers/sound/cs4232.c +++ b/drivers/sound/cs4232.c @@ -7,8 +7,9 @@ * interfaces. This is just a temporary driver until full PnP support * gets inplemented. Just the WSS codec, FM synth and the MIDI ports are * supported. Other interfaces are left uninitialized. - * - * Copyright by Hannu Savolainen 1995 + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -29,8 +30,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ +#include + #include "sound_config.h" @@ -39,7 +41,13 @@ #define KEY_PORT 0x279 /* Same as LPT1 status port */ #define CSN_NUM 0x99 /* Just a random number */ -#define CS_OUT(a) outb( a, KEY_PORT) +static int *osp; + +static void +CS_OUT (unsigned char a) +{ + outb (a, KEY_PORT); +} #define CS_OUT2(a, b) {CS_OUT(a);CS_OUT(b);} #define CS_OUT3(a, b, c) {CS_OUT(a);CS_OUT(b);CS_OUT(c);} @@ -55,6 +63,7 @@ probe_cs4232_mpu (struct address_info *hw_config) mpu_base = hw_config->io_base; mpu_irq = hw_config->irq; + return 0; } @@ -79,6 +88,8 @@ probe_cs4232 (struct address_info *hw_config) int base = hw_config->io_base, irq = hw_config->irq; int dma1 = hw_config->dma, dma2 = hw_config->dma2; + osp = hw_config->osp; + /* * Verify that the I/O port range is free. */ diff --git a/drivers/sound/dev_table.c b/drivers/sound/dev_table.c index be3a034d3268..b067621be14e 100644 --- a/drivers/sound/dev_table.c +++ b/drivers/sound/dev_table.c @@ -2,8 +2,9 @@ * sound/dev_table.c * * Device call tables. - * - * Copyright by Hannu Savolainen 1993 + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -24,8 +25,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ +#include + #define _DEV_TABLE_C_ #include "sound_config.h" diff --git a/drivers/sound/dev_table.h b/drivers/sound/dev_table.h index 74b5e94f3052..07d169b2f920 100644 --- a/drivers/sound/dev_table.h +++ b/drivers/sound/dev_table.h @@ -2,31 +2,32 @@ * dev_table.h * * Global definitions for device call tables - * - * Copyright by Hannu Savolainen 1993 + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. + * modification, are permitted provided that the following conditions are + * met: 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. 2. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * -*/ + */ +#include + #ifndef _DEV_TABLE_H_ #define _DEV_TABLE_H_ @@ -134,7 +135,7 @@ typedef struct coproc_operations { char name[32]; int (*open) (void *devc, int sub_device); void (*close) (void *devc, int sub_device); - int (*ioctl) (void *devc, unsigned int cmd, ioctl_arg arg, int local); + int (*ioctl) (void *devc, unsigned int cmd, caddr_t arg, int local); void (*reset) (void *devc); void *devc; /* Driver specific info */ @@ -155,14 +156,14 @@ struct audio_operations { int count, int intrflag, int dma_restart); void (*start_input) (int dev, unsigned long buf, int count, int intrflag, int dma_restart); - int (*ioctl) (int dev, unsigned int cmd, ioctl_arg arg, int local); + int (*ioctl) (int dev, unsigned int cmd, caddr_t arg, int local); int (*prepare_for_input) (int dev, int bufsize, int nbufs); int (*prepare_for_output) (int dev, int bufsize, int nbufs); void (*reset) (int dev); void (*halt_xfer) (int dev); int (*local_qlen)(int dev); void (*copy_from_user)(int dev, char *localbuf, int localoffs, - const snd_rw_buf *userbuf, int useroffs, int len); + const char *userbuf, int useroffs, int len); void (*halt_input) (int dev); void (*halt_output) (int dev); void (*trigger) (int dev, int bits); @@ -178,7 +179,7 @@ struct audio_operations { struct mixer_operations { char name[32]; - int (*ioctl) (int dev, unsigned int cmd, ioctl_arg arg); + int (*ioctl) (int dev, unsigned int cmd, caddr_t arg); }; struct synth_operations { @@ -189,13 +190,13 @@ struct synth_operations { int (*open) (int dev, int mode); void (*close) (int dev); - int (*ioctl) (int dev, unsigned int cmd, ioctl_arg arg); + int (*ioctl) (int dev, unsigned int cmd, caddr_t arg); int (*kill_note) (int dev, int voice, int note, int velocity); int (*start_note) (int dev, int voice, int note, int velocity); int (*set_instr) (int dev, int voice, int instr); void (*reset) (int dev); void (*hw_control) (int dev, unsigned char *event); - int (*load_patch) (int dev, int format, const snd_rw_buf *addr, + int (*load_patch) (int dev, int format, const char *addr, int offs, int count, int pmgr_flag); void (*aftertouch) (int dev, int voice, int pressure); void (*controller) (int dev, int voice, int ctrl_num, int value); @@ -233,7 +234,7 @@ struct midi_operations { void (*outputintr)(int dev) ); void (*close) (int dev); - int (*ioctl) (int dev, unsigned int cmd, ioctl_arg arg); + int (*ioctl) (int dev, unsigned int cmd, caddr_t arg); int (*putc) (int dev, unsigned char data); int (*start_read) (int dev); int (*end_read) (int dev); @@ -259,7 +260,7 @@ struct sound_timer_operations { void (*close)(int dev); int (*event)(int dev, unsigned char *ev); unsigned long (*get_time)(int dev); - int (*ioctl) (int dev, unsigned int cmd, ioctl_arg arg); + int (*ioctl) (int dev, unsigned int cmd, caddr_t arg); void (*arm_timer)(int dev, long time); }; @@ -341,9 +342,6 @@ struct sound_timer_operations { {"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 -#ifdef CONFIG_PNP - {"AD1848", 0, 500, "PnP MSS", attach_pnp_ad1848, probe_pnp_ad1848, unload_pnp_ad1848}, #endif {NULL, 0, 0, "*?*", NULL, NULL, NULL} }; diff --git a/drivers/sound/dmabuf.c b/drivers/sound/dmabuf.c index 7cacc7f99314..92aedf407cec 100644 --- a/drivers/sound/dmabuf.c +++ b/drivers/sound/dmabuf.c @@ -2,8 +2,9 @@ * sound/dmabuf.c * * The DMA buffer manager for digitized voice applications - * - * Copyright by Hannu Savolainen 1993, 1994, 1995 + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -24,8 +25,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ +#include + #include "sound_config.h" @@ -109,10 +111,20 @@ reorganize_buffers (int dev, struct dma_buffparms *dmap) if (bsz == dsp_dev->buffsize) bsz /= 2; /* Needs at least 2 buffers */ +/* + * Split the computed fragment to smaller parts. After 3.5a9 + * the default subdivision is 4 which should give better + * results when recording. + */ + if (dmap->subdivision == 0) /* Not already set */ - dmap->subdivision = 1; /* Init to default value */ - else - bsz /= dmap->subdivision; +#ifdef V35A9_COMPATIBLE + dmap->subdivision = 1; /* Init to the default value */ +#else + dmap->subdivision = 4; /* Init to the default value */ +#endif + + bsz /= dmap->subdivision; if (bsz < 16) bsz = 16; /* Just a sanity check */ @@ -170,7 +182,7 @@ dma_init_buffers (int dev, struct dma_buffparms *dmap) dmap->dma_mode = DMODE_NONE; dmap->mapping_flags = 0; - dmap->neutral_byte = 0x00; + dmap->neutral_byte = 0x80; dmap->cfrag = -1; dmap->closing = 0; } @@ -270,9 +282,9 @@ DMAbuf_open (int dev, int mode) 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); - audio_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_RATE, (ioctl_arg) DSP_DEFAULT_SPEED, 1); + audio_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_BITS, (caddr_t) 8, 1); + audio_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_CHANNELS, (caddr_t) 1, 1); + audio_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_RATE, (caddr_t) DSP_DEFAULT_SPEED, 1); return 0; } @@ -343,7 +355,7 @@ dma_sync (int dev) cli (); while (!current_got_fatal_signal () - && audio_devs[dev]->dmap_out->qlen > 1) + && audio_devs[dev]->dmap_out->qlen) { { @@ -352,7 +364,7 @@ dma_sync (int dev) if (HZ) current_set_timeout (tl = jiffies + (HZ)); else - tl = 0xffffffff; + tl = (unsigned long) -1; out_sleep_flag[dev].mode = WK_SLEEP; module_interruptible_sleep_on (&out_sleeper[dev]); if (!(out_sleep_flag[dev].mode & WK_WAKEUP)) @@ -389,7 +401,7 @@ dma_sync (int dev) if (HZ) current_set_timeout (tl = jiffies + (HZ)); else - tl = 0xffffffff; + tl = (unsigned long) -1; out_sleep_flag[dev].mode = WK_SLEEP; module_interruptible_sleep_on (&out_sleeper[dev]); if (!(out_sleep_flag[dev].mode & WK_WAKEUP)) @@ -418,6 +430,10 @@ DMAbuf_release (int dev, int mode) && (audio_devs[dev]->dmap_out->dma_mode == DMODE_OUTPUT)) { dma_sync (dev); + + memset (audio_devs[dev]->dmap_out->raw_buf, + audio_devs[dev]->dmap_out->neutral_byte, + audio_devs[dev]->dmap_out->bytes_in_use); } save_flags (flags); @@ -494,15 +510,12 @@ DMAbuf_getrdbuffer (int dev, char **buf, int *len, int dontblock) 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) + else if (!dmap->qlen) { int timeout; @@ -539,7 +552,7 @@ DMAbuf_getrdbuffer (int dev, char **buf, int *len, int dontblock) if (timeout) current_set_timeout (tl = jiffies + (timeout)); else - tl = 0xffffffff; + tl = (unsigned long) -1; in_sleep_flag[dev].mode = WK_SLEEP; module_interruptible_sleep_on (&in_sleeper[dev]); if (!(in_sleep_flag[dev].mode & WK_WAKEUP)) @@ -577,15 +590,12 @@ DMAbuf_rmchars (int dev, int buff_no, int c) 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) + else if (p >= dmap->fragment_size) { /* This buffer is completely empty */ dmap->counts[dmap->qhead] = 0; if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs) @@ -601,7 +611,7 @@ DMAbuf_rmchars (int dev, int buff_no, int c) } static int -dma_subdivide (int dev, struct dma_buffparms *dmap, ioctl_arg arg, int fact) +dma_subdivide (int dev, struct dma_buffparms *dmap, caddr_t arg, int fact) { if (fact == 0) { @@ -626,7 +636,7 @@ dma_subdivide (int dev, struct dma_buffparms *dmap, ioctl_arg arg, int fact) } static int -dma_set_fragment (int dev, struct dma_buffparms *dmap, ioctl_arg arg, int fact) +dma_set_fragment (int dev, struct dma_buffparms *dmap, caddr_t arg, int fact) { int bytes, count; @@ -700,7 +710,7 @@ get_buffer_pointer (int dev, int chan, struct dma_buffparms *dmap) } int -DMAbuf_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local) +DMAbuf_ioctl (int dev, unsigned int cmd, caddr_t arg, int local) { struct dma_buffparms *dmap_out = audio_devs[dev]->dmap_out; struct dma_buffparms *dmap_in = audio_devs[dev]->dmap_in; @@ -770,10 +780,8 @@ DMAbuf_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local) 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); @@ -844,7 +852,6 @@ DMAbuf_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local) 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) @@ -855,7 +862,6 @@ DMAbuf_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local) 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) @@ -889,10 +895,8 @@ DMAbuf_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local) 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; } @@ -911,10 +915,8 @@ DMAbuf_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local) 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; } @@ -990,13 +992,11 @@ DMAbuf_getwrbuffer (int dev, char **buf, int *size, int dontblock) 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 */ { @@ -1061,7 +1061,7 @@ DMAbuf_getwrbuffer (int dev, char **buf, int *size, int dontblock) if (timeout) current_set_timeout (tl = jiffies + (timeout)); else - tl = 0xffffffff; + tl = (unsigned long) -1; out_sleep_flag[dev].mode = WK_SLEEP; module_interruptible_sleep_on (&out_sleeper[dev]); if (!(out_sleep_flag[dev].mode & WK_WAKEUP)) @@ -1094,6 +1094,11 @@ DMAbuf_getwrbuffer (int dev, char **buf, int *size, int dontblock) *buf = dmap->raw_buf + dmap->qtail * dmap->fragment_size; *size = dmap->fragment_size; +#if 1 + memset (*buf, + dmap->neutral_byte, + *size); +#endif dmap->counts[dmap->qtail] = 0; return dmap->qtail; @@ -1138,7 +1143,6 @@ DMAbuf_start_output (int dev, int buff_no, int l) * 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; @@ -1147,9 +1151,6 @@ DMAbuf_start_output (int dev, int buff_no, int l) dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; } else -#else - if (dmap != NULL) -#endif { @@ -1281,18 +1282,16 @@ DMAbuf_outputintr (int dev, int event_type) 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 */ + int p; p = dmap->fragment_size * dmap->qhead; memset (dmap->raw_buf + p, @@ -1316,9 +1315,7 @@ DMAbuf_outputintr (int dev, int event_type) } dmap->flags |= DMA_ACTIVE; } - else -#endif - if (event_type != 2) + else if (event_type != 2) { if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs) { @@ -1345,10 +1342,9 @@ DMAbuf_outputintr (int dev, int event_type) 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); + memset (audio_devs[dev]->dmap_out->raw_buf, + audio_devs[dev]->dmap_out->neutral_byte, + audio_devs[dev]->dmap_out->bytes_in_use); } } @@ -1392,7 +1388,6 @@ DMAbuf_inputintr (int dev) 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; @@ -1411,9 +1406,7 @@ DMAbuf_inputintr (int dev) dmap->flags |= DMA_ACTIVE; } - else -#endif - if (dmap->qlen == (dmap->nbufs - 1)) + else if (dmap->qlen == (dmap->nbufs - 1)) { printk ("Sound: Recording overrun\n"); dmap->underrun_count++; @@ -1541,7 +1534,6 @@ DMAbuf_select (int dev, struct fileinfo *file, int sel_type, select_table_handle case SEL_IN: dmap = audio_devs[dev]->dmap_in; -#ifdef ALLOW_BUFFER_MAPPING if (dmap->mapping_flags & DMA_MAP_MAPPED) { if (dmap->qlen) @@ -1554,7 +1546,6 @@ DMAbuf_select (int dev, struct fileinfo *file, int sel_type, select_table_handle restore_flags (flags); return 0; } -#endif if (dmap->dma_mode != DMODE_INPUT) { @@ -1587,7 +1578,6 @@ DMAbuf_select (int dev, struct fileinfo *file, int sel_type, select_table_handle case SEL_OUT: dmap = audio_devs[dev]->dmap_out; -#ifdef ALLOW_BUFFER_MAPPING if (dmap->mapping_flags & DMA_MAP_MAPPED) { if (dmap->qlen) @@ -1600,7 +1590,6 @@ DMAbuf_select (int dev, struct fileinfo *file, int sel_type, select_table_handle restore_flags (flags); return 0; } -#endif if (dmap->dma_mode == DMODE_INPUT) { @@ -1674,7 +1663,7 @@ DMAbuf_start_output (int dev, int buff_no, int l) } int -DMAbuf_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local) +DMAbuf_ioctl (int dev, unsigned int cmd, caddr_t arg, int local) { return -EIO; } diff --git a/drivers/sound/finetune.h b/drivers/sound/finetune.h index b86a0eb15a1f..2a6119dd8b0d 100644 --- a/drivers/sound/finetune.h +++ b/drivers/sound/finetune.h @@ -1,30 +1,29 @@ #ifdef SEQUENCER_C /* - * Copyright by Hannu Savolainen 1993 + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. + * modification, are permitted provided that the following conditions are + * met: 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. 2. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ + unsigned short finetune_table[128] = { /* 0 */ 9439, 9447, 9456, 9464, 9473, 9481, 9490, 9499, diff --git a/drivers/sound/gus_card.c b/drivers/sound/gus_card.c index 85ffdd18075f..5c3b9ec24338 100644 --- a/drivers/sound/gus_card.c +++ b/drivers/sound/gus_card.c @@ -2,8 +2,9 @@ * sound/gus_card.c * * Detection routine for the Gravis Ultrasound. - * - * Copyright by Hannu Savolainen 1993 + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -24,8 +25,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ +#include + #include "sound_config.h" @@ -40,7 +42,7 @@ extern int gus_wave_volume; extern int gus_pcm_volume; extern int have_gus_max; -sound_os_info *gus_osp; +int *gus_osp; long attach_gus_card (long mem_start, struct address_info *hw_config) diff --git a/drivers/sound/gus_midi.c b/drivers/sound/gus_midi.c index b5879a90d5dc..809a031d4872 100644 --- a/drivers/sound/gus_midi.c +++ b/drivers/sound/gus_midi.c @@ -2,8 +2,9 @@ * sound/gus2_midi.c * * The low level driver for the GUS Midi Interface. - * - * Copyright by Hannu Savolainen 1993 + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -24,8 +25,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ +#include + #include "sound_config.h" @@ -44,9 +46,13 @@ static unsigned char tmp_queue[256]; static volatile int qlen; static volatile unsigned char qhead, qtail; extern int gus_base, gus_irq, gus_dma; -extern sound_os_info *gus_osp; +extern int *gus_osp; -#define GUS_MIDI_STATUS() inb( u_MidiStatus) +static int +GUS_MIDI_STATUS (void) +{ + return inb (u_MidiStatus); +} static int gus_midi_open (int dev, int mode, @@ -188,7 +194,7 @@ gus_midi_end_read (int dev) } static int -gus_midi_ioctl (int dev, unsigned cmd, ioctl_arg arg) +gus_midi_ioctl (int dev, unsigned cmd, caddr_t arg) { return -EINVAL; } @@ -262,13 +268,14 @@ gus_midi_init (long mem_start) void gus_midi_interrupt (int dummy) { - unsigned char stat, data; + volatile unsigned char stat, data; unsigned long flags; + int timeout = 10; save_flags (flags); cli (); - while ((stat = GUS_MIDI_STATUS ()) & (MIDI_RCV_FULL | MIDI_XMIT_EMPTY)) + while (timeout-- > 0 && (stat = GUS_MIDI_STATUS ()) & (MIDI_RCV_FULL | MIDI_XMIT_EMPTY)) { if (stat & MIDI_RCV_FULL) { diff --git a/drivers/sound/gus_vol.c b/drivers/sound/gus_vol.c index f817da59fa7c..1154ebb4cd91 100644 --- a/drivers/sound/gus_vol.c +++ b/drivers/sound/gus_vol.c @@ -1,8 +1,31 @@ /* * gus_vol.c - Compute volume for GUS. + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * - * Greg Lee 1993. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. 2. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ +#include + #include "sound_config.h" #ifdef CONFIG_GUS #include "gus_linearvol.h" diff --git a/drivers/sound/gus_wave.c b/drivers/sound/gus_wave.c index 7ba2698efcb0..28a0bf45b31a 100644 --- a/drivers/sound/gus_wave.c +++ b/drivers/sound/gus_wave.c @@ -2,8 +2,9 @@ * sound/gus_wave.c * * Driver for the Gravis UltraSound wave table synth. - * - * Copyright by Hannu Savolainen 1993, 1994 + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -24,8 +25,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ +#include + #include "sound_config.h" #include @@ -36,6 +38,8 @@ #define MAX_SAMPLE 150 #define MAX_PATCH 256 +#define NOT_SAMPLE 0xffff + struct voice_info { unsigned long orig_freq; @@ -133,7 +137,7 @@ static unsigned long pcm_current_buf; static int pcm_current_count; static int pcm_current_intrflag; -extern sound_os_info *gus_osp; +extern int *gus_osp; struct voice_info voices[32]; @@ -204,7 +208,7 @@ reset_sample_memory (void) free_sample = 0; for (i = 0; i < MAX_PATCH; i++) - patch_table[i] = -1; + patch_table[i] = NOT_SAMPLE; } void @@ -889,7 +893,7 @@ gus_wave_detect (int baseaddr) static int guswave_ioctl (int dev, - unsigned int cmd, ioctl_arg arg) + unsigned int cmd, caddr_t arg) { switch (cmd) @@ -1222,7 +1226,7 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume) return -EINVAL; } - if ((samplep = patch_table[patch]) == -1) + if ((samplep = patch_table[patch]) == NOT_SAMPLE) { return -EINVAL; } @@ -1237,7 +1241,7 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume) best_sample = samplep; best_delta = 1000000; - while (samplep >= 0 && sample == -1) + while (samplep != 0 && samplep != NOT_SAMPLE && sample == -1) { delta_freq = note_freq - samples[samplep].base_note; if (delta_freq < 0) @@ -1251,9 +1255,7 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume) note_freq <= samples[samplep].high_note) sample = samplep; else - samplep = samples[samplep].key; /* - * Follow link - */ + samplep = samples[samplep].key; /* Link to next sample */ } if (sample == -1) sample = best_sample; @@ -1505,14 +1507,14 @@ guswave_close (int dev) } static int -guswave_load_patch (int dev, int format, const snd_rw_buf * addr, +guswave_load_patch (int dev, int format, const char *addr, int offs, int count, int pmgr_flag) { struct patch_info patch; int instr; long sizeof_patch; - unsigned long blk_size, blk_end, left, src_offs, target; + unsigned long blk_sz, blk_end, left, src_offs, target; sizeof_patch = (long) &patch.data[0] - (long) &patch; /* Header size */ @@ -1638,21 +1640,21 @@ guswave_load_patch (int dev, int format, const snd_rw_buf * addr, while (left) /* Not completely transferred yet */ { - /* blk_size = audio_devs[gus_devnum]->buffsize; */ - blk_size = audio_devs[gus_devnum]->dmap_out->bytes_in_use; - if (blk_size > left) - blk_size = left; + /* blk_sz = audio_devs[gus_devnum]->buffsize; */ + blk_sz = audio_devs[gus_devnum]->dmap_out->bytes_in_use; + if (blk_sz > left) + blk_sz = left; /* * DMA cannot cross 256k bank boundaries. Check for that. */ - blk_end = target + blk_size; + blk_end = target + blk_sz; if ((target >> 18) != (blk_end >> 18)) { /* Split the block */ blk_end &= ~(256 * 1024 - 1); - blk_size = blk_end - target; + blk_sz = blk_end - target; } if (gus_no_dma) @@ -1664,7 +1666,7 @@ guswave_load_patch (int dev, int format, const snd_rw_buf * addr, unsigned char data; - for (i = 0; i < blk_size; i++) + for (i = 0; i < blk_sz; i++) { data = get_fs_byte (&((addr)[sizeof_patch + i])); if (patch.mode & WAVE_UNSIGNED) @@ -1684,7 +1686,7 @@ guswave_load_patch (int dev, int format, const snd_rw_buf * addr, * OK, move now. First in and then out. */ - memcpy_fromfs (audio_devs[gus_devnum]->dmap_out->raw_buf, &((addr)[sizeof_patch + src_offs]), blk_size); + memcpy_fromfs (audio_devs[gus_devnum]->dmap_out->raw_buf, &((addr)[sizeof_patch + src_offs]), blk_sz); save_flags (flags); cli (); @@ -1692,7 +1694,7 @@ guswave_load_patch (int dev, int format, const snd_rw_buf * addr, gus_write8 (0x41, 0); /* Disable GF1 DMA */ DMAbuf_start_dma (gus_devnum, audio_devs[gus_devnum]->dmap_out->raw_buf_phys, - blk_size, DMA_MODE_WRITE); + blk_sz, DMA_MODE_WRITE); /* * Set the DRAM address for the wave data @@ -1736,7 +1738,7 @@ guswave_load_patch (int dev, int format, const snd_rw_buf * addr, if (HZ) current_set_timeout (tl = jiffies + (HZ)); else - tl = 0xffffffff; + tl = (unsigned long) -1; dram_sleep_flag.mode = WK_SLEEP; module_interruptible_sleep_on (&dram_sleeper); if (!(dram_sleep_flag.mode & WK_WAKEUP)) @@ -1755,9 +1757,9 @@ guswave_load_patch (int dev, int format, const snd_rw_buf * addr, * Now the next part */ - left -= blk_size; - src_offs += blk_size; - target += blk_size; + left -= blk_sz; + src_offs += blk_sz; + target += blk_sz; gus_write8 (0x41, 0); /* Stop DMA */ } @@ -1771,17 +1773,18 @@ guswave_load_patch (int dev, int format, const snd_rw_buf * addr, } static void -guswave_hw_control (int dev, unsigned char *event) +guswave_hw_control (int dev, unsigned char *event_rec) { int voice, cmd; unsigned short p1, p2; - unsigned long plong, flags; + unsigned int plong; + unsigned flags; - cmd = event[2]; - voice = event[3]; - p1 = *(unsigned short *) &event[4]; - p2 = *(unsigned short *) &event[6]; - plong = *(unsigned long *) &event[4]; + cmd = event_rec[2]; + voice = event_rec[3]; + p1 = *(unsigned short *) &event_rec[4]; + p2 = *(unsigned short *) &event_rec[6]; + plong = *(unsigned int *) &event_rec[4]; if ((voices[voice].volume_irq_mode == VMODE_START_NOTE) && (cmd != _GUS_VOICESAMPLE) && (cmd != _GUS_VOICE_POS)) @@ -1985,7 +1988,7 @@ gus_sampling_set_bits (int bits) } static int -gus_sampling_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local) +gus_sampling_ioctl (int dev, unsigned int cmd, caddr_t arg, int local) { switch (cmd) { @@ -2425,7 +2428,7 @@ gus_local_qlen (int dev) static void gus_copy_from_user (int dev, char *localbuf, int localoffs, - const snd_rw_buf * userbuf, int useroffs, int len) + const char *userbuf, int useroffs, int len) { if (gus_sampling_channels == 1) { @@ -2823,7 +2826,7 @@ set_input_volumes (void) } int -gus_default_mixer_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +gus_default_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg) { #define MIX_DEVS (SOUND_MASK_MIC|SOUND_MASK_LINE| \ SOUND_MASK_SYNTH|SOUND_MASK_PCM) @@ -3098,7 +3101,24 @@ gus_wave_init (long mem_start, struct address_info *hw_config) */ } - sprintf (gus_info.name, "Gravis UltraSound %s (%dk)", model_num, (int) gus_mem_size / 1024); + if (hw_config->name) + { + strncpy (gus_info.name, hw_config->name, sizeof (gus_info.name)); + gus_info.name[sizeof (gus_info.name) - 1] = 0; + } + else + sprintf (gus_info.name, "Gravis UltraSound %s (%dk)", model_num, (int) gus_mem_size / 1024); + + + samples = (struct patch_info *) (sound_mem_blocks[sound_num_blocks] = kmalloc ((MAX_SAMPLE + 1) * sizeof (*samples), GFP_KERNEL)); + if (sound_num_blocks < 1024) + sound_num_blocks++;; + if (samples == NULL) + { + printk ("GUS Error: Cant allocate memory for instrument tables\n"); + return mem_start; + } + conf_printf (gus_info.name, hw_config); if (num_synths >= MAX_SYNTH_DEV) @@ -3112,11 +3132,6 @@ gus_wave_init (long mem_start, struct address_info *hw_config) #endif } - - samples = (struct patch_info *) (sound_mem_blocks[sound_num_blocks] = kmalloc ((MAX_SAMPLE + 1) * sizeof (*samples), GFP_KERNEL)); - if (sound_num_blocks < 1024) - sound_num_blocks++;; - reset_sample_memory (); gus_initialize (); diff --git a/drivers/sound/hex2hex.h b/drivers/sound/hex2hex.h index 5c909174780d..876546f8827d 100644 --- a/drivers/sound/hex2hex.h +++ b/drivers/sound/hex2hex.h @@ -9,30 +9,12 @@ #define MAX_SIZE (256*1024) #define ABANDON(why) { \ fprintf(stderr, "%s: " why "\n", source); \ - fclose(inf);fclose(outf);return 0; \ + return 0; \ } -int hex2hex(char *source, char *target, char *varline) +int loadhex(FILE *inf, unsigned char *buf, char *source) { - FILE *inf, *outf; - - int i,l, c; - unsigned char buf[MAX_SIZE]; - - if ((inf=fopen(source, "r"))==NULL) - { - perror(source); - return 0; - } - - if ((outf=fopen(target, "w"))==NULL) - { - perror(target); - fclose(inf); - return 0; - } - - l=0; + int l=0, c, i; while ((c=getc(inf))!=EOF) { @@ -80,7 +62,40 @@ int hex2hex(char *source, char *target, char *varline) } } + return l; +} + +int hex2hex(char *source, char *target, char *varline) +{ + FILE *inf, *outf; + + int i,l; + unsigned char buf[MAX_SIZE]; + + if ((inf=fopen(source, "r"))==NULL) + { + perror(source); + return 0; + } + + if ((outf=fopen(target, "w"))==NULL) + { + perror(target); + fclose(inf); + return 0; + } + + l=loadhex(inf, buf, source); + if (l<=0) + { + fclose(inf); + fclose(outf); + return l; + } + + fprintf(outf, "/*\n *\t Computer generated file. Do not edit.\n */\n"); + fprintf(outf, "static int %s_len = %d\n", l); fprintf(outf, "static unsigned char %s[] = {\n", varline); for (i=0;i + #include "sound_config.h" #if defined(CONFIG_GUS) @@ -37,7 +39,7 @@ SOUND_MASK_SYNTH| \ SOUND_MASK_CD | SOUND_MASK_VOLUME) -extern sound_os_info *gus_osp; +extern int *gus_osp; extern int gus_base; static int volumes[ICS_MIXDEVS]; static int left_fix[ICS_MIXDEVS] = @@ -130,7 +132,7 @@ set_volumes (int dev, int vol) } static int -ics2101_mixer_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +ics2101_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg) { if (((cmd >> 8) & 0xff) == 'M') { diff --git a/drivers/sound/mad16.c b/drivers/sound/mad16.c index 80bfb2e4bebe..39f52e7bf3a7 100644 --- a/drivers/sound/mad16.c +++ b/drivers/sound/mad16.c @@ -1,3 +1,29 @@ +/* + * Copyright by Hannu Savolainen 1993-1996 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. 2. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include + + /* * sound/mad16.c * @@ -45,29 +71,6 @@ * CD-ROM DMA (Mitsumi or IDE): 0x00=DMA5, 0x01=DMA6, 0x02=DMA7 or 0x03=disabled * * For use with sbpcd, address 0x340, set MAD16_CDSEL to 0x03 or 0x23. - * - * Copyright by Hannu Savolainen 1995 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * */ #include "sound_config.h" @@ -100,7 +103,7 @@ static int already_initialized = 0; static int board_type = C928; -static sound_os_info *mad16_osp; +static int *mad16_osp; #ifndef DDB #define DDB(x) @@ -424,6 +427,13 @@ attach_mad16 (long mem_start, struct address_info *hw_config) (dma == 3 && dma2 == 0)) { dma2_bit = 0x04; /* Enable capture DMA */ + + /* Change SB DMA so that it doesn't conflict with codec's DMAs */ + + if (dma == 3) + mad_write (MC3_PORT, (mad_read (MC3_PORT) & ~0x30) | 0x00); /*DMA1 */ + else + mad_write (MC3_PORT, (mad_read (MC3_PORT) & ~0x30) | 0x20); /*DMA3 */ } else { diff --git a/drivers/sound/mad16_sb_midi.c b/drivers/sound/mad16_sb_midi.c index 565b8ed8047a..122e2a3eab5e 100644 --- a/drivers/sound/mad16_sb_midi.c +++ b/drivers/sound/mad16_sb_midi.c @@ -2,8 +2,9 @@ * sound/mad16_sb_midi.c * * The low level driver for MAD16 SoundBlaster-DS-chip-based MIDI. - * - * Copyright by Hannu Savolainen 1993, Aaron Ucko 1995 + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -24,7 +25,11 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + */ +#include + +/* + * Modifications by Aaron Ucko 1995 */ #include "sound_config.h" @@ -40,7 +45,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; +static int *midi_osp; int mad16_sb_midi_mode = NORMAL_MIDI; int mad16_sb_midi_busy = 0; @@ -303,7 +308,7 @@ mad16_sb_midi_end_read (int dev) } static int -mad16_sb_midi_ioctl (int dev, unsigned cmd, ioctl_arg arg) +mad16_sb_midi_ioctl (int dev, unsigned cmd, caddr_t arg) { return -EPERM; } diff --git a/drivers/sound/maui.c b/drivers/sound/maui.c index 4b1096ee51db..4870faa39bd6 100644 --- a/drivers/sound/maui.c +++ b/drivers/sound/maui.c @@ -2,8 +2,9 @@ * sound/maui.c * * The low level driver for Turtle Beach Maui and Tropez. - * - * Copyright by Hannu Savolainen 1995 + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -24,8 +25,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ +#include + #define USE_SEQ_MACROS #define USE_SIMPLE_MACROS @@ -37,7 +39,7 @@ static int maui_base = 0x330; static volatile int irq_ok = 0; -static sound_os_info *maui_osp; +static int *maui_osp; #define HOST_DATA_PORT (maui_base + 2) #define HOST_STAT_PORT (maui_base + 3) @@ -50,7 +52,7 @@ static sound_os_info *maui_osp; #define STAT_RX_AVAIL 0x02 #define STAT_RX_IENA 0x01 -static int (*orig_load_patch) (int dev, int format, const snd_rw_buf * addr, +static int (*orig_load_patch) (int dev, int format, const char *addr, int offs, int count, int pmgr_flag) = NULL; static int @@ -98,7 +100,7 @@ mauiintr (int irq, struct pt_regs *dummy) int -maui_load_patch (int dev, int format, const snd_rw_buf * addr, +maui_load_patch (int dev, int format, const char *addr, int offs, int count, int pmgr_flag) { diff --git a/drivers/sound/midi_synth.c b/drivers/sound/midi_synth.c index b396af8860b7..474926f08ae3 100644 --- a/drivers/sound/midi_synth.c +++ b/drivers/sound/midi_synth.c @@ -2,8 +2,9 @@ * sound/midi_synth.c * * High level midi sequencer manager for dumb MIDI interfaces. - * - * Copyright by Hannu Savolainen 1993 + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -24,8 +25,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ +#include + #define USE_SEQ_MACROS #define USE_SIMPLE_MACROS @@ -279,7 +281,7 @@ midi_synth_output (int dev) int midi_synth_ioctl (int dev, - unsigned int cmd, ioctl_arg arg) + unsigned int cmd, caddr_t arg) { /* * int orig_dev = synth_devs[dev]->midi_dev; @@ -498,7 +500,7 @@ midi_synth_hw_control (int dev, unsigned char *event) } int -midi_synth_load_patch (int dev, int format, const snd_rw_buf * addr, +midi_synth_load_patch (int dev, int format, const char *addr, int offs, int count, int pmgr_flag) { int orig_dev = synth_devs[dev]->midi_dev; @@ -576,7 +578,7 @@ midi_synth_load_patch (int dev, int format, const snd_rw_buf * addr, if (1) current_set_timeout (tl = jiffies + (1)); else - tl = 0xffffffff; + tl = (unsigned long) -1; sysex_sleep_flag.mode = WK_SLEEP; module_interruptible_sleep_on (&sysex_sleeper); if (!(sysex_sleep_flag.mode & WK_WAKEUP)) diff --git a/drivers/sound/midi_synth.h b/drivers/sound/midi_synth.h index 55386c455677..a2c812b30c22 100644 --- a/drivers/sound/midi_synth.h +++ b/drivers/sound/midi_synth.h @@ -1,5 +1,5 @@ int midi_synth_ioctl (int dev, - unsigned int cmd, ioctl_arg arg); + unsigned int cmd, caddr_t arg); int midi_synth_kill_note (int dev, int channel, int note, int velocity); int midi_synth_set_instr (int dev, int channel, int instr_no); int midi_synth_start_note (int dev, int channel, int note, int volume); @@ -7,7 +7,7 @@ void midi_synth_reset (int dev); int midi_synth_open (int dev, int mode); void midi_synth_close (int dev); void midi_synth_hw_control (int dev, unsigned char *event); -int midi_synth_load_patch (int dev, int format, const snd_rw_buf * addr, +int midi_synth_load_patch (int dev, int format, const char * addr, int offs, int count, int pmgr_flag); void midi_synth_panning (int dev, int channel, int pressure); void midi_synth_aftertouch (int dev, int channel, int pressure); diff --git a/drivers/sound/midibuf.c b/drivers/sound/midibuf.c index 9270cafff930..89681a117fd2 100644 --- a/drivers/sound/midibuf.c +++ b/drivers/sound/midibuf.c @@ -2,8 +2,9 @@ * sound/midibuf.c * * Device file manager for /dev/midi# - * - * Copyright by Hannu Savolainen 1993 + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -24,8 +25,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ +#include + #include "sound_config.h" @@ -115,7 +117,7 @@ drain_midi_queue (int dev) if (HZ / 10) current_set_timeout (tl = jiffies + (HZ / 10)); else - tl = 0xffffffff; + tl = (unsigned long) -1; midi_sleep_flag[dev].mode = WK_SLEEP; module_interruptible_sleep_on (&midi_sleeper[dev]); if (!(midi_sleep_flag[dev].mode & WK_WAKEUP)) @@ -305,7 +307,7 @@ MIDIbuf_release (int dev, struct fileinfo *file) if (0) current_set_timeout (tl = jiffies + (0)); else - tl = 0xffffffff; + tl = (unsigned long) -1; midi_sleep_flag[dev].mode = WK_SLEEP; module_interruptible_sleep_on (&midi_sleeper[dev]); if (!(midi_sleep_flag[dev].mode & WK_WAKEUP)) @@ -337,7 +339,7 @@ MIDIbuf_release (int dev, struct fileinfo *file) } int -MIDIbuf_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count) +MIDIbuf_write (int dev, struct fileinfo *file, const char *buf, int count) { unsigned long flags; int c, n, i; @@ -368,7 +370,7 @@ MIDIbuf_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count if (0) current_set_timeout (tl = jiffies + (0)); else - tl = 0xffffffff; + tl = (unsigned long) -1; midi_sleep_flag[dev].mode = WK_SLEEP; module_interruptible_sleep_on (&midi_sleeper[dev]); if (!(midi_sleep_flag[dev].mode & WK_WAKEUP)) @@ -405,7 +407,7 @@ MIDIbuf_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count int -MIDIbuf_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) +MIDIbuf_read (int dev, struct fileinfo *file, char *buf, int count) { int n, c = 0; unsigned long flags; @@ -427,7 +429,7 @@ MIDIbuf_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) if (parms[dev].prech_timeout) current_set_timeout (tl = jiffies + (parms[dev].prech_timeout)); else - tl = 0xffffffff; + tl = (unsigned long) -1; input_sleep_flag[dev].mode = WK_SLEEP; module_interruptible_sleep_on (&input_sleeper[dev]); if (!(input_sleep_flag[dev].mode & WK_WAKEUP)) @@ -467,7 +469,7 @@ MIDIbuf_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) int MIDIbuf_ioctl (int dev, struct fileinfo *file, - unsigned int cmd, ioctl_arg arg) + unsigned int cmd, caddr_t arg) { int val; diff --git a/drivers/sound/mpu401.c b/drivers/sound/mpu401.c index d4507ee266d1..53dab5b29536 100644 --- a/drivers/sound/mpu401.c +++ b/drivers/sound/mpu401.c @@ -2,8 +2,9 @@ * sound/mpu401.c * * The low level driver for Roland MPU-401 compatible Midi cards. - * - * Copyright by Hannu Savolainen 1993 + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -24,11 +25,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * Modified: - * Riccardo Facchetti 24 Mar 1995 - * - Added the Audio Excel DSP 16 initialization routine. */ +#include + #define USE_SEQ_MACROS #define USE_SIMPLE_MACROS @@ -82,20 +81,36 @@ struct mpu_config unsigned char last_status; void (*inputintr) (int dev, unsigned char data); int shared_irq; - sound_os_info *osp; + int *osp; }; #define DATAPORT(base) (base) #define COMDPORT(base) (base+1) #define STATPORT(base) (base+1) -#define mpu401_status(devc) inb( STATPORT(devc->base)) +static int +mpu401_status (struct mpu_config *devc) +{ + return inb (STATPORT (devc->base)); +} #define input_avail(devc) (!(mpu401_status(devc)&INPUT_AVAIL)) #define output_ready(devc) (!(mpu401_status(devc)&OUTPUT_READY)) -#define write_command(devc, cmd) outb( cmd, COMDPORT(devc->base)) -#define read_data(devc) inb( DATAPORT(devc->base)) +static void +write_command (struct mpu_config *devc, unsigned char cmd) +{ + outb (cmd, COMDPORT (devc->base)); +} +static int +read_data (struct mpu_config *devc) +{ + return inb (DATAPORT (devc->base)); +} -#define write_data(devc, byte) outb( byte, DATAPORT(devc->base)) +static void +write_data (struct mpu_config *devc, unsigned char byte) +{ + outb (byte, DATAPORT (devc->base)); +} #define OUTPUT_READY 0x40 #define INPUT_AVAIL 0x80 @@ -619,11 +634,11 @@ mpu401_command (int dev, mpu_command_rec * cmd) mpu401_input_loop (devc); /* - * Sometimes it takes about 30000 loops before the output becomes ready + * Sometimes it takes about 50000 loops before the output becomes ready * (After reset). Normally it takes just about 10 loops. */ - timeout = 30000; + timeout = 50000; retry: if (timeout-- <= 0) { @@ -641,19 +656,22 @@ retry: } write_command (devc, cmd->cmd); + ok = 0; for (timeout = 50000; timeout > 0 && !ok; timeout--) if (input_avail (devc)) - if (devc->opened && devc->mode == MODE_SYNTH) - { - if (mpu_input_scanner (devc, read_data (devc)) == MPU_ACK) - ok = 1; - } - else - { /* Device is not currently open. Use simplier method */ - if (read_data (devc) == MPU_ACK) - ok = 1; - } + { + if (devc->opened && devc->mode == MODE_SYNTH) + { + if (mpu_input_scanner (devc, read_data (devc)) == MPU_ACK) + ok = 1; + } + else + { /* Device is not currently open. Use simplier method */ + if (read_data (devc) == MPU_ACK) + ok = 1; + } + } if (!ok) { @@ -769,7 +787,7 @@ mpu401_end_read (int dev) } static int -mpu401_ioctl (int dev, unsigned cmd, ioctl_arg arg) +mpu401_ioctl (int dev, unsigned cmd, caddr_t arg) { struct mpu_config *devc; @@ -827,7 +845,7 @@ mpu401_buffer_status (int dev) static int mpu_synth_ioctl (int dev, - unsigned int cmd, ioctl_arg arg) + unsigned int cmd, caddr_t arg) { int midi_dev; struct mpu_config *devc; @@ -998,23 +1016,35 @@ static void mpu401_chk_version (struct mpu_config *devc) { int tmp; + unsigned long flags; devc->version = devc->revision = 0; + save_flags (flags); + cli (); if ((tmp = mpu_cmd (num_midis, 0xAC, 0)) < 0) - return; + { + restore_flags (flags); + return; + } if ((tmp & 0xf0) > 0x20) /* Why it's larger than 2.x ??? */ - return; + { + restore_flags (flags); + return; + } devc->version = tmp; if ((tmp = mpu_cmd (num_midis, 0xAD, 0)) < 0) { devc->version = 0; + restore_flags (flags); return; } devc->revision = tmp; + + restore_flags (flags); } long @@ -1064,6 +1094,7 @@ attach_mpu401 (long mem_start, struct address_info *hw_config) if (!devc->shared_irq) if (snd_set_irq_handler (devc->irq, mpuintr, "mpu401", devc->osp) < 0) { + printk ("MPU401: Failed to allocate IRQ%d\n", devc->irq); return mem_start; } @@ -1267,13 +1298,6 @@ probe_mpu401 (struct address_info *hw_config) tmp_devc.opened = 0; tmp_devc.osp = hw_config->osp; -#if defined(CONFIG_AEDSP16) && defined(AEDSP16_MPU401) - /* - * Initialize Audio Excel DSP 16 to MPU-401, before any operation. - */ - InitAEDSP16_MPU401 (hw_config); -#endif - if (hw_config->always_detect) return 1; @@ -1360,7 +1384,7 @@ tmr_reset (void) save_flags (flags); cli (); - next_event_time = 0xffffffff; + next_event_time = (unsigned long) -1; prev_event_time = 0; curr_ticks = curr_clocks = 0; restore_flags (flags); @@ -1569,7 +1593,7 @@ mpu_timer_get_time (int dev) static int mpu_timer_ioctl (int dev, - unsigned int command, ioctl_arg arg) + unsigned int command, caddr_t arg) { int midi_dev = sound_timer_devs[dev]->devlink; @@ -1708,7 +1732,7 @@ mpu_timer_interrupt (void) if (curr_ticks >= next_event_time) { - next_event_time = 0xffffffff; + next_event_time = (unsigned long) -1; sequencer_timer (0); } } diff --git a/drivers/sound/opl3.c b/drivers/sound/opl3.c index 0a1de665db0e..2e5cdf762b5a 100644 --- a/drivers/sound/opl3.c +++ b/drivers/sound/opl3.c @@ -2,8 +2,9 @@ * sound/opl3.c * * A low level driver for Yamaha YM3812 and OPL-3 -chips - * - * Copyright by Hannu Savolainen 1993 + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -24,8 +25,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ +#include + /* * Major improvements to the FM handling 30AUG92 by Rob Hooft, @@ -74,7 +76,7 @@ typedef struct opl_devinfo unsigned char cmask; int is_opl4; - sound_os_info *osp; + int *osp; } opl_devinfo; @@ -121,7 +123,7 @@ enter_4op_mode (void) static int opl3_ioctl (int dev, - unsigned int cmd, ioctl_arg arg) + unsigned int cmd, caddr_t arg) { switch (cmd) { @@ -167,7 +169,7 @@ opl3_ioctl (int dev, } int -opl3_detect (int ioaddr, sound_os_info * osp) +opl3_detect (int ioaddr, int *osp) { /* * This function returns 1 if the FM chicp is present at the given I/O port @@ -876,7 +878,7 @@ opl3_hw_control (int dev, unsigned char *event) } static int -opl3_load_patch (int dev, int format, const snd_rw_buf * addr, +opl3_load_patch (int dev, int format, const char *addr, int offs, int count, int pmgr_flag) { struct sbi_instrument ins; @@ -1171,7 +1173,7 @@ static struct synth_operations opl3_operations = }; long -opl3_init (long mem_start, int ioaddr, sound_os_info * osp) +opl3_init (long mem_start, int ioaddr, int *osp) { int i; @@ -1191,7 +1193,7 @@ opl3_init (long mem_start, int ioaddr, sound_os_info * osp) devc->osp = osp; devc->nr_voice = 9; - strcpy (devc->fm_info.name, "OPL2-"); + strcpy (devc->fm_info.name, "OPL2"); devc->fm_info.device = 0; devc->fm_info.synth_type = SYNTH_TYPE_FM; diff --git a/drivers/sound/opl3.h b/drivers/sound/opl3.h index afa8d16459e7..550756cc0046 100644 --- a/drivers/sound/opl3.h +++ b/drivers/sound/opl3.h @@ -1,29 +1,28 @@ /* * opl3.h - Definitions of the OPL-3 registers - * - * Copyright by Hannu Savolainen 1993 + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. + * modification, are permitted provided that the following conditions are + * met: 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. 2. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ /* diff --git a/drivers/sound/os.h b/drivers/sound/os.h index 07e39c66e1eb..b52ff967c481 100644 --- a/drivers/sound/os.h +++ b/drivers/sound/os.h @@ -3,8 +3,6 @@ #undef NO_INLINE_ASM #define SHORT_BANNERS -#include - #ifdef MODULE #define __NO_VERSION__ #include @@ -37,9 +35,6 @@ #include -typedef char snd_rw_buf; -typedef caddr_t ioctl_arg; - #define FALSE 0 #define TRUE 1 @@ -57,6 +52,5 @@ extern void sound_close_dma(int chn); extern caddr_t sound_mem_blocks[1024]; extern int sound_num_blocks; -typedef int sound_os_info; - #undef PSEUDO_DMA_AUTOINIT +#define ALLOW_BUFFER_MAPPING diff --git a/drivers/sound/pas2_card.c b/drivers/sound/pas2_card.c index c9917052cf65..d875d87b8046 100644 --- a/drivers/sound/pas2_card.c +++ b/drivers/sound/pas2_card.c @@ -3,8 +3,9 @@ * sound/pas2_card.c * * Detection routine for the Pro Audio Spectrum cards. - * - * Copyright by Hannu Savolainen 1993 + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -25,8 +26,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ +#include + #include "sound_config.h" @@ -44,7 +46,7 @@ int translat_code; static int pas_intr_mask = 0; static int pas_irq = 0; -sound_os_info *pas_osp; +int *pas_osp; char pas_model; static char *pas_model_names[] = diff --git a/drivers/sound/pas2_midi.c b/drivers/sound/pas2_midi.c index 690773d395a7..00ab64722a8d 100644 --- a/drivers/sound/pas2_midi.c +++ b/drivers/sound/pas2_midi.c @@ -2,8 +2,9 @@ * sound/pas2_midi.c * * The low level driver for the PAS Midi Interface. - * - * Copyright by Hannu Savolainen 1993 + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -24,8 +25,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ +#include + #include "sound_config.h" @@ -215,7 +217,7 @@ pas_midi_end_read (int dev) } static int -pas_midi_ioctl (int dev, unsigned cmd, ioctl_arg arg) +pas_midi_ioctl (int dev, unsigned cmd, caddr_t arg) { return -EINVAL; } diff --git a/drivers/sound/pas2_mixer.c b/drivers/sound/pas2_mixer.c index 851091da3844..1de40c3f8001 100644 --- a/drivers/sound/pas2_mixer.c +++ b/drivers/sound/pas2_mixer.c @@ -4,8 +4,9 @@ * sound/pas2_mixer.c * * Mixer routines for the Pro Audio Spectrum cards. - * - * Copyright by Hannu Savolainen 1993 + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -26,8 +27,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ +#include + #include "sound_config.h" @@ -39,7 +41,7 @@ extern int translat_code; extern char pas_model; -extern sound_os_info *pas_osp; +extern int *pas_osp; static int rec_devices = (SOUND_MASK_MIC); /* Default recording source */ static int mode_control = 0; @@ -258,7 +260,7 @@ pas_mixer_reset (void) } int -pas_mixer_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +pas_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg) { TRACE (printk ("pas2_mixer.c: int pas_mixer_ioctl(unsigned int cmd = %X, unsigned int arg = %X)\n", cmd, arg)); diff --git a/drivers/sound/pas2_pcm.c b/drivers/sound/pas2_pcm.c index b4a185843680..24da509bfcef 100644 --- a/drivers/sound/pas2_pcm.c +++ b/drivers/sound/pas2_pcm.c @@ -3,8 +3,9 @@ * sound/pas2_pcm.c * * The low level driver for the Pro Audio Spectrum ADC/DAC. - * - * Copyright by Hannu Savolainen 1993 + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -25,8 +26,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ +#include + #include "sound_config.h" @@ -53,6 +55,7 @@ static unsigned char pcm_filter = 0; /* filter FLAG */ static unsigned char pcm_mode = PCM_NON; static unsigned long pcm_count = 0; static unsigned short pcm_bitsok = 8; /* mask of OK bits */ +static int pcm_busy = 0; static int my_devnum = 0; int @@ -66,11 +69,16 @@ pcm_set_speed (int arg) if (arg < 5000) arg = 5000; - foo = (1193180 + (arg / 2)) / arg; - arg = 1193180 / foo; - if (pcm_channels & 2) - foo = foo >> 1; + { + foo = (596590 + (arg / 2)) / arg; + arg = 596590 / foo; + } + else + { + foo = (1193180 + (arg / 2)) / arg; + arg = 1193180 / foo; + } pcm_speed = arg; @@ -152,7 +160,7 @@ pcm_set_bits (int arg) } static int -pas_pcm_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local) +pas_pcm_ioctl (int dev, unsigned int cmd, caddr_t arg, int local) { TRACE (printk ("pas2_pcm.c: static int pas_pcm_ioctl(unsigned int cmd = %X, unsigned int arg = %X)\n", cmd, arg)); @@ -230,9 +238,21 @@ static int pas_pcm_open (int dev, int mode) { int err; + unsigned long flags; TRACE (printk ("pas2_pcm.c: static int pas_pcm_open(int mode = %X)\n", mode)); + save_flags (flags); + cli (); + if (pcm_busy) + { + restore_flags (flags); + return -EBUSY; + } + + pcm_busy = 1; + restore_flags (flags); + if ((err = pas_set_intr (PAS_PCM_INTRBITS)) < 0) return err; @@ -256,6 +276,7 @@ pas_pcm_close (int dev) pas_remove_intr (PAS_PCM_INTRBITS); pcm_mode = PCM_NON; + pcm_busy = 0; restore_flags (flags); } diff --git a/drivers/sound/patmgr.c b/drivers/sound/patmgr.c index 7456d31d07e0..d872d0a23204 100644 --- a/drivers/sound/patmgr.c +++ b/drivers/sound/patmgr.c @@ -2,8 +2,9 @@ * sound/patmgr.c * * The patch maneger interface for the /dev/sequencer - * - * Copyright by Hannu Savolainen 1993 + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -24,8 +25,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ +#include + #define PATMGR_C #include "sound_config.h" @@ -91,7 +93,7 @@ pmgr_release (int dev) } int -pmgr_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) +pmgr_read (int dev, struct fileinfo *file, char *buf, int count) { unsigned long flags; int ok = 0; @@ -133,7 +135,7 @@ pmgr_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) } int -pmgr_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count) +pmgr_write (int dev, struct fileinfo *file, const char *buf, int count) { unsigned long flags; diff --git a/drivers/sound/pss.c b/drivers/sound/pss.c index 4f365fb4a8a8..dc58c42c5990 100644 --- a/drivers/sound/pss.c +++ b/drivers/sound/pss.c @@ -2,8 +2,9 @@ * sound/pss.c * * The low level driver for the Personal Sound System (ECHO ESC614). - * - * Copyright by Hannu Savolainen 1993 + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -24,8 +25,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ +#include + #include "sound_config.h" @@ -77,7 +79,7 @@ typedef struct pss_config int base; int irq; int dma; - sound_os_info *osp; + int *osp; } pss_config; @@ -489,7 +491,7 @@ download_boot_block (void *dev_info, copr_buffer * buf) } static int -pss_coproc_ioctl (void *dev_info, unsigned int cmd, ioctl_arg arg, int local) +pss_coproc_ioctl (void *dev_info, unsigned int cmd, caddr_t arg, int local) { /* printk("PSS coproc ioctl %x %x %d\n", cmd, arg, local); */ diff --git a/drivers/sound/pss.h b/drivers/sound/pss.h deleted file mode 100644 index e020af6ae9b1..000000000000 --- a/drivers/sound/pss.h +++ /dev/null @@ -1,371 +0,0 @@ -/****************************************************************************** - - def.h - - Version 1.3 11/2/93 - - Copyright (c) 1993 Analog Devices Inc. All rights reserved - -******************************************************************************/ -/* Port offsets from base port for Sound Blaster DSP */ -#define DSP_PORT_CMSD0 0x00 /* C/MS music voice 1-6 data port, write only */ -#define DSP_PORT_CMSR0 0x01 /* C/MS music voice 1-6 register port, write only */ -#define DSP_PORT_CMSD1 0x02 /* C/MS music voice 7-12 data port, write only */ -#define DSP_PORT_CMSR1 0x03 /* C/MS music voice 7-12 register port, write only */ - -#define DSP_PORT_STATUS 0x04 /* DSP Status bits, read only */ -#define DSP_PORT_CONTROL 0x04 /* DSP Control bits, write only */ -#define DSP_PORT_DATA_LSB 0x05 /* Read or write LSB of 16 bit data */ - - -#define DSP_PORT_RESET 0x06 /* DSP Reset, write only */ -#define DSP_PORT_07h 0x07 /* reserved port */ - -#define DSP_PORT_FMD0 0x08 /* FM music data/status port, read/write */ -#define DSP_PORT_FMR0 0x09 /* FM music data/status port, write only */ - -#define DSP_PORT_RDDATA 0x0A /* DSP Read data, read only reading signals DSP */ -#define DSP_PORT_0Bh 0x0B /* reserved port */ -#define DSP_PORT_WRDATA 0x0C /* DSP Write data or command, write */ -#define DSP_PORT_WRBUSY 0x0C /* DSP Write buffer status (bit 7), read */ -#define DSP_PORT_0Dh 0x0D /* reserved port */ -#define DSP_PORT_DATAAVAIL 0x0E /* DSP Data available status (bit 7), read only */ -#define DSP_PORT_INTERFACE 0x0E /* Sets DMA Channel and Interrupt, write only */ -#define DSP_PORT_0Fh 0x0F /* reserved port (used on Pro cards) */ - -#define ADDR_MASK 0x003f - -#define INT_MASK 0xffc7 -#define INT_3_BITS 0x0008 -#define INT_5_BITS 0x0010 -#define INT_7_BITS 0x0018 -#define INT_9_BITS 0x0020 -#define INT_10_BITS 0x0028 -#define INT_11_BITS 0x0030 -#define INT_12_BITS 0x0038 - -#define GAME_BIT 0x0400 -#define GAME_BIT_MASK 0xfbff - -#define INT_TEST_BIT 0x0200 -#define INT_TEST_PASS 0x0100 -#define INT_TEST_BIT_MASK 0xFDFF - -#define DMA_MASK 0xfff8 -#define DMA_0_BITS 0x0001 -#define DMA_1_BITS 0x0002 -#define DMA_3_BITS 0x0003 -#define DMA_5_BITS 0x0004 -#define DMA_6_BITS 0x0005 -#define DMA_7_BITS 0x0006 - -#define DMA_TEST_BIT 0x0080 -#define DMA_TEST_PASS 0x0040 -#define DMA_TEST_BIT_MASK 0xFF7F - - -/* Echo DSP Flags */ - -#define DSP_FLAG3 0x10 -#define DSP_FLAG2 0x08 -#define DSP_FLAG1 0x80 -#define DSP_FLAG0 0x40 - -#define PSS_CONFIG 0x10 -#define PSS_WSS_CONFIG 0x12 -#define SB_CONFIG 0x14 -#define MIDI_CONFIG 0x18 -#define CD_CONFIG 0x16 -#define UART_CONFIG 0x1a - -#define PSS_DATA 0x00 -#define PSS_STATUS 0x02 -#define PSS_CONTROL 0x02 -#define PSS_ID_VERS 0x04 - -#define PSS_FLAG3 0x0800 -#define PSS_FLAG2 0x0400 -#define PSS_FLAG1 0x1000 -#define PSS_FLAG0 0x0800 - -/*_____ WSS defines */ -#define WSS_BASE_ADDRESS 0x530 -#define WSS_CONFIG 0x0 -#define WSS_VERSION 0x03 -#define WSS_SP0 0x04 -#define WSS_SP1 0x05 -#define WSS_SP2 0x06 -#define WSS_SP3 0x07 - -/*_____ SoundPort register addresses */ - -#define SP_LIN_SOURCE_CTRL 0x00 -#define SP_RIN_SOURCE_CTRL 0x01 -#define SP_LIN_GAIN_CTRL 0x10 -#define SP_RIN_GAIN_CTRL 0x11 -#define SP_LAUX1_CTRL 0x02 -#define SP_RAUX1_CTRL 0x03 -#define SP_LAUX2_CTRL 0x04 -#define SP_RAUX2_CTRL 0x05 -#define SP_LOUT_CTRL 0x06 -#define SP_ROUT_CTRL 0x07 -#define SP_CLK_FORMAT 0x48 -#define SP_INT_CONF 0x09 -#define SP_INT_CONF_MCE 0x49 -#define SP_PIN_CTRL 0x0a -#define SP_TEST_INIT 0x0b -#define SP_MISC_CTRL 0x0c -#define SP_MIX_CTRL 0x0d -#define SP_DMA_UCNT 0x0e -#define SP_DMA_LCNT 0x0f - -/*_____ Gain constants */ - -#define GAIN_0 0x00 -#define GAIN_1_5 0x01 -#define GAIN_3 0x02 -#define GAIN_4_5 0x03 -#define GAIN_6 0x04 -#define GAIN_7_5 0x05 -#define GAIN_9 0x06 -#define GAIN_10_5 0x07 -#define GAIN_12 0x08 -#define GAIN_13_5 0x09 -#define GAIN_15 0x0a -#define GAIN_16_5 0x0b -#define GAIN_18 0x0c -#define GAIN_19_5 0x0d -#define GAIN_21 0x0e -#define GAIN_22_5 0x0f -#define MUTE 0XFFFF - -/*_____ Attenuation constants */ - -#define ATTEN_0 0x00 -#define ATTEN_1_5 0x01 -#define ATTEN_3 0x02 -#define ATTEN_4_5 0x03 -#define ATTEN_6 0x04 -#define ATTEN_7_5 0x05 -#define ATTEN_9 0x06 -#define ATTEN_10_5 0x07 -#define ATTEN_12 0x08 -#define ATTEN_13_5 0x09 -#define ATTEN_15 0x0a -#define ATTEN_16_5 0x0b -#define ATTEN_18 0x0c -#define ATTEN_19_5 0x0d -#define ATTEN_21 0x0e -#define ATTEN_22_5 0x0f - - -#define PSS_WRITE_EMPTY 0x8000 - -#define CD_POL_MASK 0xFFBF -#define CD_POL_BIT 0x0040 - - - -/****************************************************************************** - - host.h - - Version 1.2 9/27/93 - - Copyright (c) 1993 Analog Devices Inc. All rights reserved - -******************************************************************************/ -#define SB_WRITE_FULL 0x80 -#define SB_READ_FULL 0x80 -#define SB_WRITE_STATUS 0x0C -#define SB_READ_STATUS 0x0E -#define SB_READ_DATA 0x0A -#define SB_WRITE_DATA 0x0C - -#define PSS_DATA_REG 0x00 -#define PSS_STATUS_REG 0x02 -#define PSS_WRITE_EMPTY 0x8000 -#define PSS_READ_FULL 0x4000 - -/*_____ 1848 Sound Port bit defines */ - -#define SP_IN_INIT 0x80 -#define MODE_CHANGE_ENABLE 0x40 -#define MODE_CHANGE_MASK 0xbf -#define TRANSFER_DISABLE 0x20 -#define TRANSFER_DISABLE_MASK 0xdf -#define ADDRESS_MASK 0xf0 - -/*_____ Status bits */ -#define INTERRUPT_STATUS 0x01 -#define PLAYBACK_READY 0x02 -#define PLAYBACK_LEFT 0x04 -/*_____ pbright is not left */ -#define PLAYBACK_UPPER 0x08 -/*_____ bplower is not upper */ - -#define SAMPLE_OVERRUN 0x10 -#define SAMPLE_UNDERRUN 0x10 -#define CAPTURE_READY 0x20 -#define CAPTURE_LEFT 0x40 -/*_____ cpright is not left */ -#define CAPTURE_UPPER 0x08 -/*_____ cplower is not upper */ - -/*_____ Input & Output regs bits */ -#define LINE_INPUT 0x80 -#define AUX_INPUT 0x40 -#define MIC_INPUT 0x80 -#define MIXED_DAC_INPUT 0xC0 -#define INPUT_GAIN_MASK 0xf0 -#define INPUT_MIC_GAIN_ENABLE 0x20 -#define INPUT_MIC_GAIN_MASK 0xdf -#define INPUT_SOURCE_MASK 0x3f -#define AUX_INPUT_ATTEN_MASK 0xf0 -#define AUX_INPUT_MUTE 0x80 -#define AUX_INPUT_MUTE_MASK 0x7f -#define OUTPUT_MUTE 0x80 -#define OUTPUT_MUTE_MASK 0x7f -#define OUTPUT_ATTEN_MASK 0xc0 - -/*_____ Clock and Data format reg bits */ -#define CLOCK_SELECT_MASK 0xfe -#define CLOCK_XTAL2 0x01 -#define CLOCK_XTAL1 0x00 -#define CLOCK_FREQ_MASK 0xf1 -#define STEREO_MONO_MASK 0xef -#define STEREO 0x10 -#define AUDIO_MONO 0x00 -#define LINEAR_COMP_MASK 0xdf -#define LINEAR 0x00 -#define COMPANDED 0x20 -#define FORMAT_MASK 0xbf -#define PCM 0x00 -#define ULAW 0x00 -#define TWOS_COMP 0x40 -#define ALAW 0x40 - -/*_____ Interface Configuration reg bits */ -#define PLAYBACK_ENABLE 0x01 -#define PLAYBACK_ENABLE_MASK 0xfe -#define CAPTURE_ENABLE 0x02 -#define CAPTURE_ENABLE_MASK 0xfd -#define SINGLE_DMA 0x04 -#define SINGLE_DMA_MASK 0xfb -#define DUAL_DMA 0x00 -#define AUTO_CAL_ENABLE 0x08 -#define AUTO_CAL_DISABLE_MASK 0xf7 -#define PLAYBACK_PIO_ENABLE 0x40 -#define PLAYBACK_DMA_MASK 0xbf -#define CAPTURE_PIO_ENABLE 0x80 -#define CAPTURE_DMA_MASK 0x7f - -/*_____ Pin control bits */ -#define INTERRUPT_ENABLE 0x02 -#define INTERRUPT_MASK 0xfd - -/*_____ Test and init reg bits */ -#define OVERRANGE_LEFT_MASK 0xfc -#define OVERRANGE_RIGHT_MASK 0xf3 -#define DATA_REQUEST_STATUS 0x10 -#define AUTO_CAL_IN_PROG 0x20 -#define PLAYBACK_UNDERRUN 0x40 -#define CAPTURE_UNDERRUN 0x80 - -/*_____ Miscellaneous Control reg bits */ -#define ID_MASK 0xf0 - -/*_____ Digital Mix Control reg bits */ -#define DIGITAL_MIX1_MUTE_MASK 0xfe -#define MIX_ATTEN_MASK 0x03 - -/*_____ 1848 Sound Port reg defines */ - -#define SP_LEFT_INPUT_CONTROL 0x0 -#define SP_RIGHT_INPUT_CONTROL 0x1 -#define SP_LEFT_AUX1_CONTROL 0x2 -#define SP_RIGHT_AUX1_CONTROL 0x3 -#define SP_LEFT_AUX2_CONTROL 0x4 -#define SP_RIGHT_AUX2_CONTROL 0x5 -#define SP_LEFT_OUTPUT_CONTROL 0x6 -#define SP_RIGHT_OUTPUT_CONTROL 0x7 -#define SP_CLOCK_DATA_FORMAT 0x8 -#define SP_INTERFACE_CONFIG 0x9 -#define SP_PIN_CONTROL 0xA -#define SP_TEST_AND_INIT 0xB -#define SP_MISC_INFO 0xC -#define SP_DIGITAL_MIX 0xD -#define SP_UPPER_BASE_COUNT 0xE -#define SP_LOWER_BASE_COUNT 0xF - -#define HOST_SP_ADDR (0x534) -#define HOST_SP_DATA (0x535) - - -/****************************************************************************** - - phillips.h - - Version 1.2 9/27/93 - - Copyright (c) 1993 Analog Devices Inc. All rights reserved - -******************************************************************************/ -/*_____ Phillips control SW defines */ - -/*_____ Settings and ranges */ -#define VOLUME_MAX 6 -#define VOLUME_MIN (-64) -#define VOLUME_RANGE 70 -#define VOLUME_STEP 2 -#define BASS_MAX 15 -#define BASS_MIN (-12) -#define BASS_STEP 2 -#define BASS_RANGE 27 -#define TREBLE_MAX 12 -#define TREBLE_MIN (-12) -#define TREBLE_STEP 2 -#define TREBLE_RANGE 24 - -#define VOLUME_CONSTANT 252 -#define BASS_CONSTANT 246 -#define TREBLE_CONSTANT 246 - -/*_____ Software commands */ -#define SET_MASTER_COMMAND 0x0010 -#define MASTER_VOLUME_LEFT 0x0000 -#define MASTER_VOLUME_RIGHT 0x0100 -#define MASTER_BASS 0x0200 -#define MASTER_TREBLE 0x0300 -#define MASTER_SWITCH 0x0800 - -#define STEREO_MODE 0x00ce -#define PSEUDO_MODE 0x00d6 -#define SPATIAL_MODE 0x00de -#define MONO_MODE 0x00c6 - - -#define PSS_STEREO 0x00ce -#define PSS_PSEUDO 0x00d6 -#define PSS_SPATIAL 0x00de -#define PSS_MONO 0x00c6 - -#define PHILLIPS_VOL_MIN -64 -#define PHILLIPS_VOL_MAX 6 -#define PHILLIPS_VOL_DELTA 70 -#define PHILLIPS_VOL_INITIAL -20 -#define PHILLIPS_VOL_CONSTANT 252 -#define PHILLIPS_VOL_STEP 2 -#define PHILLIPS_BASS_MIN -12 -#define PHILLIPS_BASS_MAX 15 -#define PHILLIPS_BASS_DELTA 27 -#define PHILLIPS_BASS_INITIAL 0 -#define PHILLIPS_BASS_CONSTANT 246 -#define PHILLIPS_BASS_STEP 2 -#define PHILLIPS_TREBLE_MIN -12 -#define PHILLIPS_TREBLE_MAX 12 -#define PHILLIPS_TREBLE_DELTA 24 -#define PHILLIPS_TREBLE_INITIAL 0 -#define PHILLIPS_TREBLE_CONSTANT 246 -#define PHILLIPS_TREBLE_STEP 2 - diff --git a/drivers/sound/sb16_dsp.c b/drivers/sound/sb16_dsp.c index a32d86d89bdb..00034661ac5b 100644 --- a/drivers/sound/sb16_dsp.c +++ b/drivers/sound/sb16_dsp.c @@ -2,10 +2,9 @@ * sound/sb16_dsp.c * * The low level driver for the SoundBlaster DSP chip. - * - * (C) 1993 J. Schubert (jsb@sth.ruhr-uni-bochum.de) - * - * based on SB-driver by (C) Hannu Savolainen + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -26,8 +25,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ +#include + #define DEB(x) #define DEB1(x) @@ -41,7 +41,7 @@ #if defined(CONFIG_SB) && defined(CONFIG_AUDIO) extern int sbc_base; -extern sound_os_info *sb_osp; +extern int *sb_osp; static int sb16_dsp_ok = 0; static int dsp_16bit = 0; @@ -61,7 +61,7 @@ static int sb16_dsp_open (int dev, int mode); static void sb16_dsp_close (int dev); static void sb16_dsp_output_block (int dev, unsigned long buf, int count, int intrflag, int dma_restart); static void sb16_dsp_start_input (int dev, unsigned long buf, int count, int intrflag, int dma_restart); -static int sb16_dsp_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local); +static int sb16_dsp_ioctl (int dev, unsigned int cmd, caddr_t arg, int local); static int sb16_dsp_prepare_for_input (int dev, int bsize, int bcount); static int sb16_dsp_prepare_for_output (int dev, int bsize, int bcount); static void sb16_dsp_reset (int dev); @@ -151,7 +151,7 @@ dsp_set_bits (int arg) } static int -sb16_dsp_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local) +sb16_dsp_ioctl (int dev, unsigned int cmd, caddr_t arg, int local) { switch (cmd) { @@ -250,7 +250,7 @@ sb16_dsp_close (int dev) save_flags (flags); cli (); - audio_devs[dev]->dmachan1 = dma8; + audio_devs[dev]->dmachan1 = audio_devs[dev]->dmachan2 = dma8; if (dma16 != dma8) sound_close_dma (dma16); @@ -285,22 +285,6 @@ actually_output_block (int dev, unsigned long buf, int count, int intrflag, int cnt >>= 1; cnt--; -#ifdef DEB_DMARES - printk ("output_block: %x %d %d\n", buf, count, intrflag); - if (intrflag) - { - int pos, chan = audio_devs[dev]->dmachan; - - save_flags (flags); - cli (); - clear_dma_ff (chan); - disable_dma (chan); - pos = get_dma_residue (chan); - enable_dma (chan); - restore_flags (flags); - printk ("dmapos=%d %x\n", pos, pos); - } -#endif if (audio_devs[dev]->flags & DMA_AUTOMODE && intrflag && cnt == dsp_count) @@ -354,22 +338,6 @@ actually_start_input (int dev, unsigned long buf, int count, int intrflag, int d cnt >>= 1; cnt--; -#ifdef DEB_DMARES - printk ("start_input: %x %d %d\n", buf, count, intrflag); - if (intrflag) - { - int pos, chan = audio_devs[dev]->dmachan; - - save_flags (flags); - cli (); - clear_dma_ff (chan); - disable_dma (chan); - pos = get_dma_residue (chan); - enable_dma (chan); - restore_flags (flags); - printk ("dmapos=%d %x\n", pos, pos); - } -#endif if (audio_devs[dev]->flags & DMA_AUTOMODE && intrflag && cnt == dsp_count) @@ -385,13 +353,14 @@ actually_start_input (int dev, unsigned long buf, int count, int intrflag, int d if (dma_restart) { - sb_reset_dsp (); + sb16_dsp_halt (dev); DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ); } sb_dsp_command (0x42); sb_dsp_command ((unsigned char) ((dsp_current_speed >> 8) & 0xff)); sb_dsp_command ((unsigned char) (dsp_current_speed & 0xff)); + sb_dsp_command ((unsigned char) (dsp_16bit ? 0xbe : 0xce)); dsp_count = cnt; sb_dsp_command ((unsigned char) ((dsp_stereo ? 0x20 : 0) + @@ -407,22 +376,24 @@ actually_start_input (int dev, unsigned long buf, int count, int intrflag, int d static int sb16_dsp_prepare_for_input (int dev, int bsize, int bcount) { - audio_devs[my_dev]->dmachan1 = dsp_16bit ? dma16 : dma8; + audio_devs[my_dev]->dmachan1 = + audio_devs[my_dev]->dmachan2 = + dsp_16bit ? dma16 : dma8; dsp_count = 0; dsp_cleanup (); trigger_bits = 0; - sb_dsp_command (0xd4); return 0; } static int sb16_dsp_prepare_for_output (int dev, int bsize, int bcount) { - audio_devs[my_dev]->dmachan1 = dsp_16bit ? dma16 : dma8; + audio_devs[my_dev]->dmachan1 = + audio_devs[my_dev]->dmachan2 = + dsp_16bit ? dma16 : dma8; dsp_count = 0; dsp_cleanup (); trigger_bits = 0; - sb_dsp_command (0xd4); return 0; } @@ -432,19 +403,23 @@ sb16_dsp_trigger (int dev, int bits) trigger_bits = bits; if (!bits) - sb_dsp_command (0xd0); /* Halt DMA */ + { + sb_dsp_command (0xd0); /* Halt DMA */ + } else if (bits & irq_mode) 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; + } } @@ -526,7 +501,7 @@ sb16_dsp_init (long mem_start, struct address_info *hw_config) if (num_audiodevs < MAX_AUDIO_DEV) { audio_devs[my_dev = num_audiodevs++] = &sb16_dsp_operations; - audio_devs[my_dev]->dmachan1 = dma8; + audio_devs[my_dev]->dmachan1 = audio_devs[my_dev]->dmachan2 = dma8; audio_devs[my_dev]->buffsize = DSP_BUFFSIZE; if (sound_alloc_dma (dma8, "SB16 (8bit)")) @@ -560,6 +535,7 @@ sb16_dsp_detect (struct address_info *hw_config) if (Jazz16_detected) { Jazz16_set_dma16 (hw_config->dma); + sb16_dsp_ok = 1; return 0; } diff --git a/drivers/sound/sb16_midi.c b/drivers/sound/sb16_midi.c index cc553e7d951a..566d66110864 100644 --- a/drivers/sound/sb16_midi.c +++ b/drivers/sound/sb16_midi.c @@ -2,8 +2,9 @@ * sound/sb16_midi.c * * The low level driver for the MPU-401 UART emulation of the SB16. - * - * Copyright by Hannu Savolainen 1993 + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -24,8 +25,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ +#include + #include "sound_config.h" @@ -37,14 +39,31 @@ #define COMDPORT (sb16midi_base+1) #define STATPORT (sb16midi_base+1) -extern sound_os_info *sb_osp; +extern int *sb_osp; +static int sb16midi_base = 0x330; -#define sb16midi_status() inb( STATPORT) +static int +sb16midi_status (void) +{ + return inb (STATPORT); +} #define input_avail() (!(sb16midi_status()&INPUT_AVAIL)) #define output_ready() (!(sb16midi_status()&OUTPUT_READY)) -#define sb16midi_cmd(cmd) outb( cmd, COMDPORT) -#define sb16midi_read() inb( DATAPORT) -#define sb16midi_write(byte) outb( byte, DATAPORT) +static void +sb16midi_cmd (unsigned char cmd) +{ + outb (cmd, COMDPORT); +} +static int +sb16midi_read (void) +{ + return inb (DATAPORT); +} +static void +sb16midi_write (unsigned char byte) +{ + outb (byte, DATAPORT); +} #define OUTPUT_READY 0x40 #define INPUT_AVAIL 0x80 @@ -53,7 +72,6 @@ extern sound_os_info *sb_osp; #define UART_MODE_ON 0x3F static int sb16midi_opened = 0; -static int sb16midi_base = 0x330; static int sb16midi_detected = 0; static int my_dev; extern int sbc_base; @@ -168,7 +186,7 @@ sb16midi_end_read (int dev) } static int -sb16midi_ioctl (int dev, unsigned cmd, ioctl_arg arg) +sb16midi_ioctl (int dev, unsigned cmd, caddr_t arg) { return -EINVAL; } diff --git a/drivers/sound/sb_card.c b/drivers/sound/sb_card.c index 08171e45fba3..a9acfbaca3c9 100644 --- a/drivers/sound/sb_card.c +++ b/drivers/sound/sb_card.c @@ -2,8 +2,9 @@ * sound/sb_card.c * * Detection routine for the SoundBlaster cards. - * - * Copyright by Hannu Savolainen 1993 + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -24,11 +25,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * Modified: - * Riccardo Facchetti 24 Mar 1995 - * - Added the Audio Excel DSP 16 initialization routine. */ +#include + #include "sound_config.h" @@ -59,12 +58,6 @@ probe_sb (struct address_info *hw_config) return 0; } -#if defined(CONFIG_AEDSP16) && defined(AEDSP16_SBPRO) - /* - * Initialize Audio Excel DSP 16 to SBPRO. - */ - InitAEDSP16_SBPRO (hw_config); -#endif return sb_dsp_detect (hw_config); } diff --git a/drivers/sound/sb_dsp.c b/drivers/sound/sb_dsp.c index 5741d3279fd4..8352e46366d1 100644 --- a/drivers/sound/sb_dsp.c +++ b/drivers/sound/sb_dsp.c @@ -2,8 +2,9 @@ * sound/sb_dsp.c * * The low level driver for the SoundBlaster DSP chip (SB1.0 to 2.1, SB Pro). - * - * Copyright by Hannu Savolainen 1994 + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -24,7 +25,10 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + */ +#include + +/* * Modified: * Hunyue Yau Jan 6 1994 * Added code to support Sound Galaxy NX Pro @@ -102,9 +106,8 @@ volatile int sb_intr_active = 0; static int dsp_speed (int); static int dsp_set_stereo (int mode); static void sb_dsp_reset (int dev); -sound_os_info *sb_osp = NULL; - -static void ess_init (void); +static void dsp_get_vers (struct address_info *hw_config); +int *sb_osp = NULL; #if defined(CONFIG_MIDI) || defined(CONFIG_AUDIO) @@ -478,7 +481,7 @@ actually_output_block (int dev, unsigned long buf, int nr_bytes, if (AudioDrive) { - int c = 0x10000 - count; /* ES1688 increments the count */ + int c = 0xffff - nr_bytes; /* ES1688 increments the count */ ess_write (0xa4, (unsigned char) (c & 0xff)); ess_write (0xa5, (unsigned char) ((c >> 8) & 0xff)); @@ -525,6 +528,11 @@ static void sb_dsp_start_input (int dev, unsigned long buf, int count, int intrflag, int restart_dma) { + if (sb_no_recording) + { + return; + } + trg_buf = buf; trg_bytes = count; trg_intrflag = intrflag; @@ -533,14 +541,14 @@ sb_dsp_start_input (int dev, unsigned long buf, int count, int intrflag, } static void -actually_start_input (int dev, unsigned long buf, int count, int intrflag, +actually_start_input (int dev, unsigned long buf, int nr_bytes, int intrflag, int restart_dma) { unsigned long flags; + int count = nr_bytes; if (sb_no_recording) { - printk ("SB Error: This device doesn't support recording\n"); return; } @@ -563,7 +571,7 @@ actually_start_input (int dev, unsigned long buf, int count, int intrflag, if (AudioDrive) { - int c = 0x10000 - count; /* ES1688 increments the count */ + int c = 0xffff - nr_bytes; /* ES1688 increments the count */ ess_write (0xa4, (unsigned char) (c & 0xff)); ess_write (0xa5, (unsigned char) ((c >> 8) & 0xff)); @@ -641,6 +649,12 @@ dsp_cleanup (void) static int sb_dsp_prepare_for_input (int dev, int bsize, int bcount) { + if (sb_no_recording) + { + printk ("SB Error: This device doesn't support recording\n"); + return 0; + } + dsp_cleanup (); dsp_speaker (OFF); @@ -651,7 +665,6 @@ sb_dsp_prepare_for_input (int dev, int bsize, int bcount) if (AudioDrive) { - /* ess_init(); */ ess_write (0xb8, 0x0e); /* Auto init DMA mode */ ess_write (0xa8, (ess_read (0xa8) & ~0x04) | (2 - dsp_stereo)); /* Mono/stereo */ @@ -693,7 +706,9 @@ sb_dsp_prepare_for_input (int dev, int bsize, int bcount) /* Select correct dma channel * for 16/8 bit acccess */ - audio_devs[my_dev]->dmachan1 = dsp_16bit ? dma16 : dma8; + audio_devs[my_dev]->dmachan1 = + audio_devs[my_dev]->dmachan2 = + dsp_16bit ? dma16 : dma8; if (dsp_stereo) sb_dsp_command (dsp_16bit ? 0xac : 0xa8); else @@ -718,7 +733,6 @@ sb_dsp_prepare_for_output (int dev, int bsize, int bcount) if (AudioDrive) { - /* ess_init(); */ ess_write (0xb8, 4); /* Auto init DMA mode */ ess_write (0xa8, ess_read (0xa8) | (2 - dsp_stereo)); /* Mono/stereo */ @@ -763,7 +777,9 @@ sb_dsp_prepare_for_output (int dev, int bsize, int bcount) /* 16 bit specific instructions (Jazz16) */ - audio_devs[my_dev]->dmachan1 = dsp_16bit ? dma16 : dma8; + audio_devs[my_dev]->dmachan1 = + audio_devs[my_dev]->dmachan2 = + dsp_16bit ? dma16 : dma8; if (Jazz16_detected != 2) /* SM Wave */ sb_mixer_set_stereo (dsp_stereo); if (dsp_stereo) @@ -828,7 +844,9 @@ sb_dsp_open (int dev, int mode) /* Allocate 8 bit dma */ - audio_devs[my_dev]->dmachan1 = dma8; + audio_devs[my_dev]->dmachan1 = + audio_devs[my_dev]->dmachan2 = + dma8; /* Allocate 16 bit dma (jazz16) */ @@ -858,7 +876,9 @@ sb_dsp_close (int dev) */ if (Jazz16_detected) { - audio_devs[my_dev]->dmachan1 = dma8; + audio_devs[my_dev]->dmachan1 = + audio_devs[my_dev]->dmachan2 = + dma8; if (dma16 != dma8) sound_close_dma (dma16); @@ -897,7 +917,7 @@ dsp_set_bits (int arg) } static int -sb_dsp_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local) +sb_dsp_ioctl (int dev, unsigned int cmd, caddr_t arg, int local) { switch (cmd) { @@ -1137,7 +1157,7 @@ initialize_smw (int mpu_base) /* * Make the OPL4 chip visible on the PC bus at 0x380. * - * There is no need to enable this feature since VoxWare + * There is no need to enable this feature since this driver * doesn't support OPL4 yet. Also there is no RAM in SM Wave so * enabling OPL4 is pretty useless. */ @@ -1205,7 +1225,16 @@ sb_dsp_detect (struct address_info *hw_config) */ dma8 = dma16 = hw_config->dma; - if (!initialize_ProSonic16 ()) + if (sb_reset_dsp ()) + dsp_get_vers (hw_config); + else + sbc_major = 0; + + if (sbc_major == 3 || sbc_major == 0) + if (initialize_ProSonic16 ()) + return 1; + + if (!sb_reset_dsp ()) return 0; return 1; /* @@ -1239,12 +1268,15 @@ static struct audio_operations sb_dsp_operations = #endif static void -ess_init (void) /* ESS1688 Initialization */ +ess_init (int ess_minor) /* ESS1688 Initialization */ { unsigned char cfg, irq_bits = 0, dma_bits = 0; AudioDrive = 1; - midi_disabled = 1; + sb_no_recording = 1; /* Temporary kludge */ + + if (ess_minor >= 8) /* ESS1688 doesn't support SB MIDI */ + midi_disabled = 1; sb_reset_dsp (); /* Turn on extended mode */ @@ -1366,10 +1398,16 @@ ess_midi_init (struct address_info *hw_config) /* called from sb16_midi.c */ void Jazz16_midi_init (struct address_info *hw_config) { + extern void smw_mixer_init (void); + extern void sb_mixer_reset (void); + mpu_base = hw_config->io_base; mpu_irq = hw_config->irq; initialize_ProSonic16 (); + + smw_mixer_init (); + sb_mixer_reset (); } void @@ -1377,6 +1415,17 @@ Jazz16_set_dma16 (int dma) { dma16 = dma; +/* Allocate 16 bit dma (Jazz16) + */ + if (dma16 != dma8) + { + if (sound_alloc_dma (dma16, "Jazz16 16 bit")) + { + printk ("Jazz16: Can't allocate 16 bit DMA channel\n"); + Jazz16_detected = 0; + return; + } + } initialize_ProSonic16 (); } @@ -1504,7 +1553,7 @@ sb_dsp_init (long mem_start, struct address_info *hw_config) "ESS ES1688 AudioDrive (rev %d)", ess_minor & 0x0f); sb_dsp_operations.format_mask |= AFMT_S16_LE; - ess_init (); + ess_init (ess_minor); } } else @@ -1532,20 +1581,9 @@ sb_dsp_init (long mem_start, struct address_info *hw_config) audio_devs[my_dev]->buffsize = DSP_BUFFSIZE; dma8 = audio_devs[my_dev]->dmachan1 = hw_config->dma; - audio_devs[my_dev]->dmachan2 = -1; + dma16 = audio_devs[my_dev]->dmachan2 = hw_config->dma; if (sound_alloc_dma (hw_config->dma, "SoundBlaster")) printk ("sb_dsp.c: Can't allocate DMA channel\n"); - - /* Allocate 16 bit dma (Jazz16) - */ - if (Jazz16_detected != 0) - if (dma16 != dma8) - { - if (sound_alloc_dma (dma16, "Jazz16 16 bit")) - { - printk ("Jazz16: Can't allocate 16 bit DMA channel\n"); - } - } } else printk ("SB: Too many DSP devices available\n"); @@ -1562,6 +1600,7 @@ sb_dsp_init (long mem_start, struct address_info *hw_config) #endif sb_dsp_ok = 1; + sb_reset_dsp (); return mem_start; } diff --git a/drivers/sound/sb_midi.c b/drivers/sound/sb_midi.c index 9e92383daf25..3f396f9230f9 100644 --- a/drivers/sound/sb_midi.c +++ b/drivers/sound/sb_midi.c @@ -2,8 +2,9 @@ * sound/sb_dsp.c * * The low level driver for the SoundBlaster DS chips. - * - * Copyright by Hannu Savolainen 1993 + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -24,8 +25,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ +#include + #include "sound_config.h" @@ -61,7 +63,7 @@ extern int sb_intr_active; int input_opened = 0; static int my_dev; -extern sound_os_info *sb_osp; +extern int *sb_osp; void (*midi_input_intr) (int dev, unsigned char data); @@ -192,7 +194,7 @@ sb_midi_end_read (int dev) } static int -sb_midi_ioctl (int dev, unsigned cmd, ioctl_arg arg) +sb_midi_ioctl (int dev, unsigned cmd, caddr_t arg) { return -EPERM; } diff --git a/drivers/sound/sb_mixer.c b/drivers/sound/sb_mixer.c index 0b951e627f69..d88a5d6bab03 100644 --- a/drivers/sound/sb_mixer.c +++ b/drivers/sound/sb_mixer.c @@ -3,8 +3,9 @@ * sound/sb_mixer.c * * The low level mixer driver for the SoundBlaster Pro and SB16 cards. - * - * Copyright by Hannu Savolainen 1994 + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -25,7 +26,10 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + */ +#include + +/* * Modified: * Hunyue Yau Jan 6 1994 * Added code to support the Sound Galaxy NX Pro mixer. @@ -43,7 +47,7 @@ extern int sbc_base; extern int Jazz16_detected; -extern sound_os_info *sb_osp; +extern int *sb_osp; extern int AudioDrive; static int mixer_initialized = 0; @@ -223,7 +227,7 @@ static char smw_mix_regs[] = /* Left mixer registers */ 0x00 /* SOUND_MIXER_LINE3 */ }; -static void +void smw_mixer_init (void) { int i; @@ -441,7 +445,7 @@ set_recmask (int mask) } static int -sb_mixer_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +sb_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg) { if (((cmd >> 8) & 0xff) == 'M') { @@ -499,7 +503,7 @@ static struct mixer_operations sb_mixer_operations = sb_mixer_ioctl }; -static void +void sb_mixer_reset (void) { int i; diff --git a/drivers/sound/sb_mixer.h b/drivers/sound/sb_mixer.h index 0a92e5e33d67..fa094e3bcf1e 100644 --- a/drivers/sound/sb_mixer.h +++ b/drivers/sound/sb_mixer.h @@ -2,9 +2,10 @@ * sound/sb_mixer.h * * Definitions for the SB Pro and SB16 mixers - * - * Copyright by Hannu Savolainen 1993 - * + */ +/* + * Copyright by Hannu Savolainen 1993-1996 + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -12,7 +13,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,7 +25,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + */ + +/* * Modified: * Hunyue Yau Jan 6 1994 * Added defines for the Sound Galaxy NX Pro mixer. @@ -213,6 +216,7 @@ static unsigned short levels[SOUND_MIXER_NRDEVICES] = 0x4040, /* Line1 */ 0x4040, /* Line2 */ 0x1515 /* Line3 */ +}; #else /* If the user selected just plain SB Pro */ diff --git a/drivers/sound/sequencer.c b/drivers/sound/sequencer.c index be651ae1bbf2..5654aaac5548 100644 --- a/drivers/sound/sequencer.c +++ b/drivers/sound/sequencer.c @@ -2,8 +2,9 @@ * sound/sequencer.c * * The sequencer personality manager. - * - * Copyright by Hannu Savolainen 1993 + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -24,8 +25,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ +#include + #define SEQUENCER_C #include "sound_config.h" @@ -99,7 +101,7 @@ static int pmgr_present[MAX_SYNTH_DEV] = #endif int -sequencer_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) +sequencer_read (int dev, struct fileinfo *file, char *buf, int count) { int c = count, p = 0; int ev_len; @@ -132,7 +134,7 @@ sequencer_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) if (pre_event_timeout) current_set_timeout (tl = jiffies + (pre_event_timeout)); else - tl = 0xffffffff; + tl = (unsigned long) -1; midi_sleep_flag.mode = WK_SLEEP; module_interruptible_sleep_on (&midi_sleeper); if (!(midi_sleep_flag.mode & WK_WAKEUP)) @@ -174,7 +176,7 @@ sequencer_midi_output (int dev) } void -seq_copy_to_input (unsigned char *event, int len) +seq_copy_to_input (unsigned char *event_rec, int len) { unsigned long flags; @@ -192,7 +194,7 @@ seq_copy_to_input (unsigned char *event, int len) save_flags (flags); cli (); - memcpy (&iqueue[iqtail * IEV_SZ], event, len); + memcpy (&iqueue[iqtail * IEV_SZ], event_rec, len); iqlen++; iqtail = (iqtail + 1) % SEQ_MAX_QUEUE; @@ -210,7 +212,7 @@ static void sequencer_midi_input (int dev, unsigned char data) { unsigned int tstamp; - unsigned char event[4]; + unsigned char event_rec[4]; if (data == 0xfe) /* Ignore active sensing */ return; @@ -224,16 +226,16 @@ sequencer_midi_input (int dev, unsigned char data) prev_input_time = tstamp; } - event[0] = SEQ_MIDIPUTC; - event[1] = data; - event[2] = dev; - event[3] = 0; + event_rec[0] = SEQ_MIDIPUTC; + event_rec[1] = data; + event_rec[2] = dev; + event_rec[3] = 0; - seq_copy_to_input (event, 4); + seq_copy_to_input (event_rec, 4); } void -seq_input_event (unsigned char *event, int len) +seq_input_event (unsigned char *event_rec, int len) { unsigned long this_time; @@ -250,19 +252,19 @@ seq_input_event (unsigned char *event, int len) tmp_event[1] = TMR_WAIT_ABS; tmp_event[2] = 0; tmp_event[3] = 0; - *(unsigned long *) &tmp_event[4] = this_time; + *(unsigned int *) &tmp_event[4] = this_time; seq_copy_to_input (tmp_event, 8); prev_input_time = this_time; } - seq_copy_to_input (event, len); + seq_copy_to_input (event_rec, len); } int -sequencer_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count) +sequencer_write (int dev, struct fileinfo *file, const char *buf, int count) { - unsigned char event[EV_SZ], ev_code; + unsigned char event_rec[EV_SZ], ev_code; int p = 0, c, ev_size; int err; int mode = file->mode & O_ACCMODE; @@ -281,21 +283,21 @@ sequencer_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int cou while (c >= 4) { - memcpy_fromfs ((char *) event, &((buf)[p]), 4); - ev_code = event[0]; + memcpy_fromfs ((char *) event_rec, &((buf)[p]), 4); + ev_code = event_rec[0]; if (ev_code == SEQ_FULLSIZE) { int err; - dev = *(unsigned short *) &event[2]; + dev = *(unsigned short *) &event_rec[2]; if (dev < 0 || dev >= max_synthdev) return -ENXIO; if (!(synth_open_mask & (1 << dev))) return -ENXIO; - err = synth_devs[dev]->load_patch (dev, *(short *) &event[0], buf, p + 4, c, 0); + err = synth_devs[dev]->load_patch (dev, *(short *) &event_rec[0], buf, p + 4, c, 0); if (err < 0) return err; @@ -319,7 +321,7 @@ sequencer_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int cou return count - c; } - memcpy_fromfs ((char *) &event[4], &((buf)[p + 4]), 4); + memcpy_fromfs ((char *) &event_rec[4], &((buf)[p + 4]), 4); } else @@ -332,13 +334,13 @@ sequencer_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int cou ev_size = 4; } - if (event[0] == SEQ_MIDIPUTC) + if (event_rec[0] == SEQ_MIDIPUTC) { - if (!midi_opened[event[2]]) + if (!midi_opened[event_rec[2]]) { int mode; - int dev = event[2]; + int dev = event_rec[2]; if (dev >= max_mididev) { @@ -361,8 +363,8 @@ sequencer_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int cou } - if (!seq_queue (event, (file->flags & (O_NONBLOCK) ? - 1 : 0))) + if (!seq_queue (event_rec, (file->flags & (O_NONBLOCK) ? + 1 : 0))) { int processed = count - c; @@ -464,7 +466,7 @@ extended_event (unsigned char *q) break; case SEQ_CONTROLLER: - synth_devs[dev]->controller (dev, q[3], q[4], *(short *) &q[5]); + synth_devs[dev]->controller (dev, q[3], q[4], (short) (q[5] | (q[6] << 8))); break; case SEQ_VOLMODE: @@ -511,13 +513,13 @@ alloc_voice (int dev, int chn, int note) } static void -seq_chn_voice_event (unsigned char *event) +seq_chn_voice_event (unsigned char *event_rec) { - unsigned char dev = event[1]; - unsigned char cmd = event[2]; - unsigned char chn = event[3]; - unsigned char note = event[4]; - unsigned char parm = event[5]; + unsigned char dev = event_rec[1]; + unsigned char cmd = event_rec[2]; + unsigned char chn = event_rec[3]; + unsigned char note = event_rec[4]; + unsigned char parm = event_rec[5]; int voice = -1; if ((int) dev > max_synthdev) @@ -593,15 +595,15 @@ seq_chn_voice_event (unsigned char *event) } static void -seq_chn_common_event (unsigned char *event) +seq_chn_common_event (unsigned char *event_rec) { - unsigned char dev = event[1]; - unsigned char cmd = event[2]; - unsigned char chn = event[3]; - unsigned char p1 = event[4]; + unsigned char dev = event_rec[1]; + unsigned char cmd = event_rec[2]; + unsigned char chn = event_rec[3]; + unsigned char p1 = event_rec[4]; - /* unsigned char p2 = event[5]; */ - unsigned short w14 = *(short *) &event[6]; + /* unsigned char p2 = event_rec[5]; */ + unsigned short w14 = *(short *) &event_rec[6]; if ((int) dev > max_synthdev) return; @@ -691,16 +693,16 @@ seq_chn_common_event (unsigned char *event) } static int -seq_timing_event (unsigned char *event) +seq_timing_event (unsigned char *event_rec) { - unsigned char cmd = event[1]; - unsigned int parm = *(int *) &event[4]; + unsigned char cmd = event_rec[1]; + unsigned int parm = *(int *) &event_rec[4]; if (seq_mode == SEQ_2) { int ret; - if ((ret = tmr->event (tmr_no, event)) == TIMER_ARMED) + if ((ret = tmr->event (tmr_no, event_rec)) == TIMER_ARMED) { if ((SEQ_MAX_QUEUE - qlen) >= output_treshold) { @@ -779,7 +781,7 @@ seq_timing_event (unsigned char *event) case TMR_ECHO: if (seq_mode == SEQ_2) - seq_copy_to_input (event, 8); + seq_copy_to_input (event_rec, 8); else { parm = (parm << 8 | SEQ_ECHO); @@ -794,10 +796,10 @@ seq_timing_event (unsigned char *event) } static void -seq_local_event (unsigned char *event) +seq_local_event (unsigned char *event_rec) { - unsigned char cmd = event[1]; - unsigned int parm = *((unsigned int *) &event[4]); + unsigned char cmd = event_rec[1]; + unsigned int parm = *((unsigned int *) &event_rec[4]); switch (cmd) { @@ -812,11 +814,11 @@ seq_local_event (unsigned char *event) } static void -seq_sysex_message (unsigned char *event) +seq_sysex_message (unsigned char *event_rec) { - int dev = event[1]; + int dev = event_rec[1]; int i, l = 0; - unsigned char *buf = &event[2]; + unsigned char *buf = &event_rec[2]; if ((int) dev > max_synthdev) return; @@ -844,7 +846,7 @@ play_event (unsigned char *q) * 1 = Timer armed. Suspend playback until timer callback. * 2 = MIDI output buffer full. Restore queue and suspend until timer */ - unsigned long *delay; + unsigned int *delay; switch (q[0]) { @@ -862,7 +864,7 @@ play_event (unsigned char *q) break; case SEQ_WAIT: - delay = (unsigned long *) q; /* + delay = (unsigned int *) q; /* * Bytes 1 to 3 are containing the * * delay in jiffies */ @@ -1270,7 +1272,7 @@ seq_drain_midi_queues (void) if (HZ / 10) current_set_timeout (tl = jiffies + (HZ / 10)); else - tl = 0xffffffff; + tl = (unsigned long) -1; seq_sleep_flag.mode = WK_SLEEP; module_interruptible_sleep_on (&seq_sleeper); if (!(seq_sleep_flag.mode & WK_WAKEUP)) @@ -1370,7 +1372,7 @@ seq_sync (void) if (HZ) current_set_timeout (tl = jiffies + (HZ)); else - tl = 0xffffffff; + tl = (unsigned long) -1; seq_sleep_flag.mode = WK_SLEEP; module_interruptible_sleep_on (&seq_sleeper); if (!(seq_sleep_flag.mode & WK_WAKEUP)) @@ -1415,7 +1417,7 @@ midi_outc (int dev, unsigned char data) if (4) current_set_timeout (tl = jiffies + (4)); else - tl = 0xffffffff; + tl = (unsigned long) -1; seq_sleep_flag.mode = WK_SLEEP; module_interruptible_sleep_on (&seq_sleeper); if (!(seq_sleep_flag.mode & WK_WAKEUP)) @@ -1538,7 +1540,7 @@ seq_panic (void) int sequencer_ioctl (int dev, struct fileinfo *file, - unsigned int cmd, ioctl_arg arg) + unsigned int cmd, caddr_t arg) { int midi_dev, orig_dev; int mode = file->mode & O_ACCMODE; @@ -1749,14 +1751,14 @@ sequencer_ioctl (int dev, struct fileinfo *file, case SNDCTL_SEQ_OUTOFBAND: { - struct seq_event_rec event; + struct seq_event_rec event_rec; unsigned long flags; - memcpy_fromfs ((char *) &event, &(((char *) arg)[0]), sizeof (event)); + memcpy_fromfs ((char *) &event_rec, &(((char *) arg)[0]), sizeof (event_rec)); save_flags (flags); cli (); - play_event (event.arr); + play_event (event_rec.arr); restore_flags (flags); return 0; @@ -2048,15 +2050,27 @@ long sequencer_init (long mem_start) { - sequencer_ok = 1; queue = (unsigned char *) (sound_mem_blocks[sound_num_blocks] = kmalloc (SEQ_MAX_QUEUE * EV_SZ, GFP_KERNEL)); if (sound_num_blocks < 1024) sound_num_blocks++;; + if (queue == NULL) + { + printk ("Sound: Can't allocate memory for sequencer output queue\n"); + return mem_start; + } + iqueue = (unsigned char *) (sound_mem_blocks[sound_num_blocks] = kmalloc (SEQ_MAX_QUEUE * IEV_SZ, GFP_KERNEL)); if (sound_num_blocks < 1024) sound_num_blocks++;; + if (queue == NULL) + { + printk ("Sound: Can't allocate memory for sequencer input queue\n"); + return mem_start; + } + + sequencer_ok = 1; return mem_start; } diff --git a/drivers/sound/sound_calls.h b/drivers/sound/sound_calls.h index 381cf2aac035..ca67db1e103a 100644 --- a/drivers/sound/sound_calls.h +++ b/drivers/sound/sound_calls.h @@ -10,7 +10,7 @@ int DMAbuf_getrdbuffer(int dev, char **buf, int *len, int dontblock); int DMAbuf_rmchars(int dev, int buff_no, int c); int DMAbuf_start_output(int dev, int buff_no, int l); int DMAbuf_set_count(int dev, int buff_no, int l); -int DMAbuf_ioctl(int dev, unsigned int cmd, ioctl_arg arg, int local); +int DMAbuf_ioctl(int dev, unsigned int cmd, caddr_t arg, int local); long DMAbuf_init(long mem_start); int DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode); int DMAbuf_open_dma (int dev); @@ -25,12 +25,12 @@ void DMAbuf_start_devices(unsigned int devmask); * System calls for /dev/dsp and /dev/audio */ -int audio_read (int dev, struct fileinfo *file, snd_rw_buf *buf, int count); -int audio_write (int dev, struct fileinfo *file, const snd_rw_buf *buf, int count); +int audio_read (int dev, struct fileinfo *file, char *buf, int count); +int audio_write (int dev, struct fileinfo *file, const char *buf, int count); int audio_open (int dev, struct fileinfo *file); void audio_release (int dev, struct fileinfo *file); int audio_ioctl (int dev, struct fileinfo *file, - unsigned int cmd, ioctl_arg arg); + unsigned int cmd, caddr_t arg); int audio_lseek (int dev, struct fileinfo *file, off_t offset, int orig); long audio_init (long mem_start); @@ -40,12 +40,12 @@ int audio_select(int dev, struct fileinfo *file, int sel_type, select_table_hand * System calls for the /dev/sequencer */ -int sequencer_read (int dev, struct fileinfo *file, snd_rw_buf *buf, int count); -int sequencer_write (int dev, struct fileinfo *file, const snd_rw_buf *buf, int count); +int sequencer_read (int dev, struct fileinfo *file, char *buf, int count); +int sequencer_write (int dev, struct fileinfo *file, const char *buf, int count); int sequencer_open (int dev, struct fileinfo *file); void sequencer_release (int dev, struct fileinfo *file); int sequencer_ioctl (int dev, struct fileinfo *file, - unsigned int cmd, ioctl_arg arg); + unsigned int cmd, caddr_t arg); int sequencer_lseek (int dev, struct fileinfo *file, off_t offset, int orig); long sequencer_init (long mem_start); void sequencer_timer(unsigned long dummy); @@ -60,12 +60,12 @@ int sequencer_select(int dev, struct fileinfo *file, int sel_type, select_table_ * System calls for the /dev/midi */ -int MIDIbuf_read (int dev, struct fileinfo *file, snd_rw_buf *buf, int count); -int MIDIbuf_write (int dev, struct fileinfo *file, const snd_rw_buf *buf, int count); +int MIDIbuf_read (int dev, struct fileinfo *file, char *buf, int count); +int MIDIbuf_write (int dev, struct fileinfo *file, const char *buf, int count); int MIDIbuf_open (int dev, struct fileinfo *file); void MIDIbuf_release (int dev, struct fileinfo *file); int MIDIbuf_ioctl (int dev, struct fileinfo *file, - unsigned int cmd, ioctl_arg arg); + unsigned int cmd, caddr_t arg); int MIDIbuf_lseek (int dev, struct fileinfo *file, off_t offset, int orig); void MIDIbuf_bytes_received(int dev, unsigned char *buf, int count); long MIDIbuf_init(long mem_start); @@ -79,11 +79,11 @@ int MIDIbuf_select(int dev, struct fileinfo *file, int sel_type, select_table_ha /* From soundcard.c */ void soundcard_init(void); -void tenmicrosec(sound_os_info *osp); +void tenmicrosec(int *osp); void request_sound_timer (int count); void sound_stop_timer(void); int snd_ioctl_return(int *addr, int value); -int snd_set_irq_handler (int interrupt_level, void(*hndlr)(int, struct pt_regs *), char *name, sound_os_info *osp); +int snd_set_irq_handler (int interrupt_level, void(*hndlr)(int, struct pt_regs *), char *name, int *osp); void snd_release_irq(int vect); void sound_dma_malloc(int dev); void sound_dma_free(int dev); @@ -91,12 +91,12 @@ 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); -int sound_write_sw (int dev, struct fileinfo *file, const snd_rw_buf *buf, int count); +int sound_read_sw (int dev, struct fileinfo *file, char *buf, int count); +int sound_write_sw (int dev, struct fileinfo *file, const char *buf, int count); int sound_open_sw (int dev, struct fileinfo *file); void sound_release_sw (int dev, struct fileinfo *file); int sound_ioctl_sw (int dev, struct fileinfo *file, - unsigned int cmd, ioctl_arg arg); + unsigned int cmd, caddr_t arg); /* From sb_dsp.c */ int sb_dsp_detect (struct address_info *hw_config); @@ -130,8 +130,8 @@ void sb_mixer_set_stereo(int mode); int sb_mixer_init(int major_model); /* From opl3.c */ -int opl3_detect (int ioaddr, sound_os_info *osp); -long opl3_init(long mem_start, int ioaddr, sound_os_info *osp); +int opl3_detect (int ioaddr, int *osp); +long opl3_init(long mem_start, int ioaddr, int *osp); /* From sb_card.c */ long attach_sb_card(long mem_start, struct address_info *hw_config); @@ -177,7 +177,7 @@ unsigned char gus_read8 (int reg); void gus_write8(int reg, unsigned int data); void guswave_dma_irq(void); void gus_delay(void); -int gus_default_mixer_ioctl (int dev, unsigned int cmd, ioctl_arg arg); +int gus_default_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg); void gus_timer_command (unsigned int addr, unsigned int val); /* From gus_midi.c */ @@ -199,8 +199,8 @@ void enable_opl3_mode(int left, int right, int both); /* From patmgr.c */ int pmgr_open(int dev); void pmgr_release(int dev); -int pmgr_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count); -int pmgr_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count); +int pmgr_read (int dev, struct fileinfo *file, char * buf, int count); +int pmgr_write (int dev, struct fileinfo *file, const char * buf, int count); int pmgr_access(int dev, struct patmgr_info *rec); int pmgr_inform(int dev, int event, unsigned long parm1, unsigned long parm2, unsigned long parm3, unsigned long parm4); @@ -213,10 +213,10 @@ void sound_timer_interrupt(void); void sound_timer_syncinterval(unsigned int new_usecs); /* From ad1848.c */ -void ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture, int share_dma, sound_os_info *osp); +void ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture, int share_dma, int *osp); void ad1848_unload (int io_base, int irq, int dma_playback, int dma_capture, int share_dma); -int ad1848_detect (int io_base, int *flags, sound_os_info *osp); +int ad1848_detect (int io_base, int *flags, int *osp); #define AD_F_CS4231 0x0001 /* Returned if a CS4232 (or compatible) detected */ #define AD_F_CS4248 0x0001 /* Returned if a CS4248 (or compatible) detected */ @@ -241,12 +241,12 @@ long attach_sscape (long mem_start, struct address_info *hw_config); int probe_ss_ms_sound (struct address_info *hw_config); long attach_ss_ms_sound(long mem_start, struct address_info * hw_config); -int pss_read (int dev, struct fileinfo *file, snd_rw_buf *buf, int count); -int pss_write (int dev, struct fileinfo *file, snd_rw_buf *buf, int count); +int pss_read (int dev, struct fileinfo *file, char *buf, int count); +int pss_write (int dev, struct fileinfo *file, char *buf, int count); int pss_open (int dev, struct fileinfo *file); void pss_release (int dev, struct fileinfo *file); int pss_ioctl (int dev, struct fileinfo *file, - unsigned int cmd, ioctl_arg arg); + unsigned int cmd, caddr_t arg); int pss_lseek (int dev, struct fileinfo *file, off_t offset, int orig); long pss_init(long mem_start); diff --git a/drivers/sound/sound_config.h b/drivers/sound/sound_config.h index 2dd122ec6d3d..ae08a8e5a2e4 100644 --- a/drivers/sound/sound_config.h +++ b/drivers/sound/sound_config.h @@ -1,33 +1,32 @@ /* sound_config.h * * A driver for Soundcards, misc configuration parameters. - * - * - * Copyright by Hannu Savolainen 1995 + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. + * modification, are permitted provided that the following conditions are + * met: 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. 2. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ + #include "os.h" #include "local.h" #include "soundvers.h" @@ -144,7 +143,7 @@ struct address_info { char *name; int driver_use_1; /* Driver defined field 1 */ int driver_use_2; /* Driver defined field 2 */ - sound_os_info *osp; /* OS spesific info */ + int *osp; /* OS spesific info */ int card_subtype; /* Driver spesific. Usually 0 */ }; diff --git a/drivers/sound/sound_pnp.c b/drivers/sound/sound_pnp.c deleted file mode 100644 index 0732235ac608..000000000000 --- a/drivers/sound/sound_pnp.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - * sound/sound_pnp.c - * - * PnP soundcard support (Linux spesific) - * - * Copyright by Hannu Savolainen 1995 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ -#include "sound_config.h" - -#if defined(CONFIG_PNP) - -#include - -static struct pnp_sounddev *pnp_devs[20] = -{ - NULL -}; - -static int max_pnpdevs = 20; -static int nr_pnpdevs = 0; -static int pnp_sig = 0; - -void -install_pnp_sounddrv (struct pnp_sounddev *drv) -{ - if (nr_pnpdevs < max_pnpdevs) - { - pnp_devs[nr_pnpdevs++] = drv; - } - else - printk ("Sound: More than 20 PnP drivers defined\n"); -} - -void -cs4232_pnp (void *parm) -{ - struct pnp_dev *dev = (struct pnp_dev *) parm; - char *name; - - int portmask = 0x00, irqmask = 0x01, dmamask = 0x03; - int opl3_driver, wss_driver; - - printk ("CS4232 driver waking up\n"); - - if (dev->card && dev->card->name) - name = dev->card->name; - else - name = "PnP WSS"; - - if ((wss_driver = sndtable_identify_card ("AD1848"))) - portmask |= 0x01; /* MSS */ - else - printk ("Sound: MSS/WSS device detected but no driver enabled\n"); - - if ((opl3_driver = sndtable_identify_card ("OPL3"))) - portmask |= 0x02; /* OPL3 */ - else - printk ("Sound: OPL3/4 device detected but no driver enabled\n"); - - printk ("WSS driver %d, OPL3 driver %d\n", wss_driver, opl3_driver); - - if (!portmask) /* No drivers available */ - return; - - if (!pnp_allocate_device (pnp_sig, dev, portmask, irqmask, dmamask, 0x00)) - printk ("Device activation failed\n"); - else - { - struct address_info hw_config; - int wss_base, opl3_base; - int irq; - int dma1, dma2; - - printk ("Device activation OK\n"); - wss_base = pnp_get_port (dev, 0); - opl3_base = pnp_get_port (dev, 1); - irq = pnp_get_irq (dev, 0); - dma1 = pnp_get_dma (dev, 0); - dma2 = pnp_get_dma (dev, 1); - - printk ("I/O0 %03x\n", wss_base); - printk ("I/O1 %03x\n", opl3_base); - printk ("IRQ %d\n", irq); - printk ("DMA0 %d\n", dma1); - printk ("DMA1 %d\n", dma2); - - if (opl3_base && opl3_driver) - { - hw_config.io_base = opl3_base; - hw_config.irq = 0; - hw_config.dma = -1; - hw_config.dma2 = -1; - hw_config.always_detect = 0; - hw_config.name = ""; - hw_config.driver_use_1 = 0; - hw_config.driver_use_2 = 0; - hw_config.osp = NULL; - hw_config.card_subtype = 0; - - if (sndtable_probe (opl3_driver, &hw_config)) - sndtable_init_card (opl3_driver, &hw_config); - - } - - if (wss_base && wss_driver) - { - hw_config.io_base = wss_base; - hw_config.irq = irq; - hw_config.dma = dma1; - hw_config.dma2 = (dma2 == NO_DMA) ? dma1 : dma2; - hw_config.always_detect = 0; - hw_config.name = name; - hw_config.driver_use_1 = 0; - hw_config.driver_use_2 = 0; - hw_config.osp = NULL; - hw_config.card_subtype = 0; - - if (sndtable_probe (wss_driver, &hw_config)) - sndtable_init_card (wss_driver, &hw_config); - - } - } -} - -static int -pnp_activate (int id, struct pnp_dev *dev) -{ - int i; - - for (i = 0; i < nr_pnpdevs; i++) - if (pnp_devs[i]->id == id) - { - - printk ("PnP dev: %08x, %s\n", id, - pnp_devid2asc (id)); - - pnp_devs[i]->setup ((void *) dev); - return 1; - } - - return 0; -} - -void -sound_pnp_init (void) -{ - static struct pnp_sounddev cs4232_dev = - {PNP_DEVID ('C', 'S', 'C', 0x0000), cs4232_pnp, "CS4232"}; - - struct pnp_dev *dev; - - install_pnp_sounddrv (&cs4232_dev); - - dev = NULL; - - if ((pnp_sig = pnp_connect ("sound")) == -1) - { - printk ("Sound: Can't connect to kernel PnP services.\n"); - return; - } - - while ((dev = pnp_get_next_device (pnp_sig, dev)) != NULL) - { - if (!pnp_activate (dev->key, dev)) - { - /* Scan all compatible devices */ - - int i; - - for (i = 0; i < dev->ncompat; i++) - if (pnp_activate (dev->compat_keys[i], dev)) - break; - } - } -} - -void -sound_pnp_disconnect (void) -{ - pnp_disconnect (pnp_sig); -} -#endif diff --git a/drivers/sound/sound_switch.c b/drivers/sound/sound_switch.c index 5405a3cbabd2..16779b30f5dc 100644 --- a/drivers/sound/sound_switch.c +++ b/drivers/sound/sound_switch.c @@ -1,9 +1,10 @@ /* * sound/sound_switch.c * - * The system call switch - * - * Copyright by Hannu Savolainen 1993 + * The system call switch handler + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -24,8 +25,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ +#include + #include "sound_config.h" @@ -34,11 +36,7 @@ struct sbc_device int usecount; }; -static int in_use = 0; /* - - - * * * * Total # of open device files - * (excluding * * * minor 0) */ +static int in_use = 0; /* Total # of open devices */ /* * /dev/sndstatus -device @@ -106,12 +104,12 @@ init_status (void) status_ptr = 0; #ifdef SOUND_UNAME_A - put_status ("VoxWare Sound Driver:" SOUND_VERSION_STRING + put_status ("Sound Driver:" SOUND_VERSION_STRING " (" SOUND_CONFIG_DATE " " SOUND_CONFIG_BY ",\n" SOUND_UNAME_A ")" "\n"); #else - put_status ("VoxWare Sound Driver:" SOUND_VERSION_STRING + put_status ("Sound Driver:" SOUND_VERSION_STRING " (" SOUND_CONFIG_DATE " " SOUND_CONFIG_BY "@" SOUND_CONFIG_HOST "." SOUND_CONFIG_DOMAIN ")" "\n"); @@ -301,7 +299,7 @@ init_status (void) } static int -read_status (snd_rw_buf * buf, int count) +read_status (char *buf, int count) { /* * Return at most 'count' bytes from the status_buf. @@ -323,7 +321,7 @@ read_status (snd_rw_buf * buf, int count) } int -sound_read_sw (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) +sound_read_sw (int dev, struct fileinfo *file, char *buf, int count) { DEB (printk ("sound_read_sw(dev=%d, count=%d)\n", dev, count)); @@ -361,7 +359,7 @@ sound_read_sw (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) } int -sound_write_sw (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count) +sound_write_sw (int dev, struct fileinfo *file, const char *buf, int count) { DEB (printk ("sound_write_sw(dev=%d, count=%d)\n", dev, count)); @@ -506,7 +504,7 @@ sound_release_sw (int dev, struct fileinfo *file) int sound_ioctl_sw (int dev, struct fileinfo *file, - unsigned int cmd, ioctl_arg arg) + unsigned int cmd, caddr_t arg) { DEB (printk ("sound_ioctl_sw(dev=%d, cmd=0x%x, arg=0x%x)\n", dev, cmd, arg)); diff --git a/drivers/sound/sound_timer.c b/drivers/sound/sound_timer.c index b19e0e2e94b1..bcc471c8954b 100644 --- a/drivers/sound/sound_timer.c +++ b/drivers/sound/sound_timer.c @@ -1,7 +1,8 @@ /* * sound/sound_timer.c - * - * Copyright by Hannu Savolainen 1993 + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -22,8 +23,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ +#include + #define SEQUENCER_C #include "sound_config.h" @@ -98,7 +100,7 @@ tmr_reset (void) tmr_offs = 0; ticks_offs = 0; tmr_ctr = 0; - next_event_time = 0xffffffff; + next_event_time = (unsigned long) -1; prev_event_time = 0; curr_ticks = 0; restore_flags (flags); @@ -112,7 +114,7 @@ timer_open (int dev, int mode) tmr_reset (); curr_tempo = 60; - curr_timebase = HZ; + curr_timebase = 100; opened = 1; reprogram_timer (); @@ -202,7 +204,7 @@ timer_get_time (int dev) static int timer_ioctl (int dev, - unsigned int cmd, ioctl_arg arg) + unsigned int cmd, caddr_t arg) { switch (cmd) { @@ -323,7 +325,7 @@ sound_timer_interrupt (void) if (curr_ticks >= next_event_time) { - next_event_time = 0xffffffff; + next_event_time = (unsigned long) -1; sequencer_timer (0); } } diff --git a/drivers/sound/soundcard.c b/drivers/sound/soundcard.c index e4e066780286..d9cb4e66713f 100644 --- a/drivers/sound/soundcard.c +++ b/drivers/sound/soundcard.c @@ -2,8 +2,9 @@ * linux/kernel/chr_drv/sound/soundcard.c * * Soundcard driver for Linux - * - * Copyright by Hannu Savolainen 1993 + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -24,20 +25,14 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - */ -/* - * Created modular version by Peter Trattler (peter@sbox.tu-graz.ac.at) */ +#include + #include "sound_config.h" #include -#ifdef CONFIG_PNP -#include -#endif - static int chrdev_registered = 0; static int is_unloading = 0; @@ -235,12 +230,11 @@ sound_select (inode_handle * inode, file_handle * file, int sel_type, select_tab 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; + unsigned long size; struct dma_buffparms *dmap = NULL; dev = inode_get_rdev (inode); @@ -324,7 +318,6 @@ sound_mmap (inode_handle * inode, file_handle * file, vm_area_handle * vma) dmap->bytes_in_use); return 0; } -#endif static struct file_operation_handle sound_fops = { @@ -334,11 +327,7 @@ static struct file_operation_handle sound_fops = NULL, /* sound_readdir */ sound_select, sound_ioctl, -#ifdef ALLOW_BUFFER_MAPPING sound_mmap, -#else - NULL, -#endif sound_open, sound_release }; @@ -356,9 +345,6 @@ soundcard_init (void) sndtable_init (0); /* Initialize call tables and * detect cards */ -#ifdef CONFIG_PNP - sound_pnp_init (); -#endif if (sndtable_get_cardcount () == 0) return; /* No cards detected */ @@ -383,7 +369,7 @@ soundcard_init (void) } -static unsigned long irqs = 0; +static unsigned int irqs = 0; #ifdef MODULE static void @@ -481,16 +467,12 @@ cleanup_module (void) sound_free_dma (i); } -#ifdef CONFIG_PNP - sound_pnp_disconnect (); -#endif - } } #endif void -tenmicrosec (sound_os_info * osp) +tenmicrosec (int *osp) { int i; @@ -499,7 +481,7 @@ tenmicrosec (sound_os_info * osp) } int -snd_set_irq_handler (int interrupt_level, void (*hndlr) (int, struct pt_regs *), char *name, sound_os_info * osp) +snd_set_irq_handler (int interrupt_level, void (*hndlr) (int, struct pt_regs *), char *name, int *osp) { int retcode; @@ -629,9 +611,7 @@ sound_alloc_dmap (int dev, struct dma_buffparms *dmap, int chan) 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 */ @@ -721,10 +701,8 @@ sound_free_dmap (int dev, struct dma_buffparms *dmap) 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; diff --git a/drivers/sound/soundvers.h b/drivers/sound/soundvers.h index 95fca0fee8dd..87b6a652834e 100644 --- a/drivers/sound/soundvers.h +++ b/drivers/sound/soundvers.h @@ -1,2 +1,2 @@ -#define SOUND_VERSION_STRING "3.5-alpha8-960109" +#define SOUND_VERSION_STRING "3.5-beta2-960210" #define SOUND_INTERNAL_VERSION 0x030505 diff --git a/drivers/sound/sscape.c b/drivers/sound/sscape.c index 6f9fe07ccd86..3c72ef21b3b5 100644 --- a/drivers/sound/sscape.c +++ b/drivers/sound/sscape.c @@ -2,8 +2,9 @@ * sound/sscape.c * * Low level driver for Ensoniq Soundscape - * - * Copyright by Hannu Savolainen 1994 + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -24,8 +25,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ +#include + #include "sound_config.h" @@ -94,7 +96,7 @@ typedef struct sscape_info int dma_allocated; int my_audiodev; int opened; - sound_os_info *osp; + int *osp; } sscape_info; @@ -438,6 +440,7 @@ sscape_download_boot (struct sscape_info *devc, unsigned char *block, int size, unsigned long flags; unsigned char temp; int done, timeout_val; + static int already_done = 0; if (flag & CPF_FIRST) { @@ -446,6 +449,13 @@ sscape_download_boot (struct sscape_info *devc, unsigned char *block, int size, * before continuing. */ + if (already_done) + { + printk ("Can't run 'ssinit' twice\n"); + return 0; + } + already_done = 1; + save_flags (flags); cli (); if (devc->dma_allocated == 0) @@ -497,7 +507,7 @@ sscape_download_boot (struct sscape_info *devc, unsigned char *block, int size, if (1) current_set_timeout (tl = jiffies + (1)); else - tl = 0xffffffff; + tl = (unsigned long) -1; sscape_sleep_flag.mode = WK_SLEEP; module_interruptible_sleep_on (&sscape_sleeper); if (!(sscape_sleep_flag.mode & WK_WAKEUP)) @@ -545,7 +555,7 @@ sscape_download_boot (struct sscape_info *devc, unsigned char *block, int size, if (1) current_set_timeout (tl = jiffies + (1)); else - tl = 0xffffffff; + tl = (unsigned long) -1; sscape_sleep_flag.mode = WK_SLEEP; module_interruptible_sleep_on (&sscape_sleeper); if (!(sscape_sleep_flag.mode & WK_WAKEUP)) @@ -578,7 +588,7 @@ sscape_download_boot (struct sscape_info *devc, unsigned char *block, int size, if (1) current_set_timeout (tl = jiffies + (1)); else - tl = 0xffffffff; + tl = (unsigned long) -1; sscape_sleep_flag.mode = WK_SLEEP; module_interruptible_sleep_on (&sscape_sleeper); if (!(sscape_sleep_flag.mode & WK_WAKEUP)) @@ -638,7 +648,7 @@ download_boot_block (void *dev_info, copr_buffer * buf) } static int -sscape_coproc_ioctl (void *dev_info, unsigned int cmd, ioctl_arg arg, int local) +sscape_coproc_ioctl (void *dev_info, unsigned int cmd, caddr_t arg, int local) { switch (cmd) @@ -745,7 +755,7 @@ set_format (sscape_info * devc, int arg) } static int -sscape_audio_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local) +sscape_audio_ioctl (int dev, unsigned int cmd, caddr_t arg, int local) { sscape_info *devc = (sscape_info *) audio_devs[dev]->devc; diff --git a/drivers/sound/sys_timer.c b/drivers/sound/sys_timer.c index 15e0232e3db2..18b63235a328 100644 --- a/drivers/sound/sys_timer.c +++ b/drivers/sound/sys_timer.c @@ -2,9 +2,10 @@ * sound/sys_timer.c * * The default timer for the Level 2 sequencer interface - * Uses the (100HZ) timer of kernel. - * - * Copyright by Hannu Savolainen 1993 + * Uses the (1/HZ sec) timer of kernel. + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -25,8 +26,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ +#include + #define SEQUENCER_C #include "sound_config.h" @@ -55,7 +57,7 @@ tmr2ticks (int tmr_value) * (divide # of MIDI ticks/minute by # of system ticks/minute). */ - return ((tmr_value * curr_tempo * curr_timebase) + (30 * HZ)) / (60 * HZ); + return ((tmr_value * curr_tempo * curr_timebase) + (30 * 100)) / (60 * HZ); } static void @@ -77,7 +79,7 @@ poll_def_tmr (unsigned long dummy) if (curr_ticks >= next_event_time) { - next_event_time = 0xffffffff; + next_event_time = (unsigned long) -1; sequencer_timer (0); } } @@ -94,7 +96,7 @@ tmr_reset (void) tmr_offs = 0; ticks_offs = 0; tmr_ctr = 0; - next_event_time = 0xffffffff; + next_event_time = (unsigned long) -1; prev_event_time = 0; curr_ticks = 0; restore_flags (flags); @@ -108,7 +110,7 @@ def_tmr_open (int dev, int mode) tmr_reset (); curr_tempo = 60; - curr_timebase = HZ; + curr_timebase = 100; opened = 1; ; @@ -201,7 +203,7 @@ def_tmr_get_time (int dev) static int def_tmr_ioctl (int dev, - unsigned int cmd, ioctl_arg arg) + unsigned int cmd, caddr_t arg) { switch (cmd) { diff --git a/drivers/sound/trix.c b/drivers/sound/trix.c index 53a5aae06e8c..352e31bc1c78 100644 --- a/drivers/sound/trix.c +++ b/drivers/sound/trix.c @@ -3,8 +3,9 @@ * * Low level driver for the MediaTriX AudioTriX Pro * (MT-0002-PC Control Chip) - * - * Copyright by Hannu Savolainen 1995 + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -25,8 +26,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ +#include + #include "sound_config.h" @@ -34,6 +36,10 @@ #ifdef INCLUDE_TRIX_BOOT #include "trix_boot.h" +#else +static unsigned char *trix_boot = NULL; +static int trix_boot_len = 0; + #endif @@ -41,7 +47,7 @@ static int kilroy_was_here = 0; /* Don't detect twice */ static int sb_initialized = 0; static int mpu_initialized = 0; -static sound_os_info *trix_osp = NULL; +static int *trix_osp = NULL; static unsigned char trix_read (int addr) @@ -60,8 +66,10 @@ trix_write (int addr, int data) static void download_boot (int base) { -#ifdef INCLUDE_TRIX_BOOT - int i = 0, n = sizeof (trix_boot); + int i = 0, n = trix_boot_len; + + if (trix_boot_len == 0) + return; trix_write (0xf8, 0x00); /* ??????? */ outb (0x01, base + 6); /* Clear the internal data pointer */ @@ -80,7 +88,6 @@ download_boot (int base) outb (0x00, 0x391); outb (0x00, base + 6); /* Reset */ outb (0x50, 0x390); /* ?????? */ -#endif } @@ -104,8 +111,6 @@ trix_set_wss_port (struct address_info *hw_config) return 0; } - request_region (0x390, 2, "AudioTriX"); - kilroy_was_here = 1; /* @@ -149,6 +154,8 @@ trix_set_wss_port (struct address_info *hw_config) int probe_trix_wss (struct address_info *hw_config) { + int ret; + /* * Check if the IO port returns valid signature. The original MS Sound * system returns 0x04 while some cards (AudioTriX Pro for example) @@ -156,7 +163,7 @@ probe_trix_wss (struct address_info *hw_config) */ if (check_region (hw_config->io_base, 8)) { - printk ("AudioTriX: MSS I/O port conflict\n"); + printk ("AudioTriX: MSS I/O port conflict (%x)\n", hw_config->io_base); return 0; } @@ -206,7 +213,12 @@ probe_trix_wss (struct address_info *hw_config) return 0; } - return ad1848_detect (hw_config->io_base + 4, NULL, hw_config->osp); + ret = ad1848_detect (hw_config->io_base + 4, NULL, hw_config->osp); + + if (ret) + request_region (0x390, 2, "AudioTriX"); + + return ret; } long @@ -282,9 +294,9 @@ probe_trix_sb (struct address_info *hw_config) static char irq_translate[] = {-1, -1, -1, 0, 1, 2, -1, 3}; -#ifndef INCLUDE_TRIX_BOOT - return 0; /* No boot code -> no fun */ -#endif + if (trix_boot_len == 0) + return 0; /* No boot code -> no fun */ + if (!kilroy_was_here) return 0; /* AudioTriX Pro has not been detected earlier */ @@ -293,7 +305,7 @@ probe_trix_sb (struct address_info *hw_config) if (check_region (hw_config->io_base, 16)) { - printk ("AudioTriX: SB I/O port conflict\n"); + printk ("AudioTriX: SB I/O port conflict (%x)\n", hw_config->io_base); return 0; } @@ -374,7 +386,7 @@ probe_trix_mpu (struct address_info *hw_config) if (check_region (hw_config->io_base, 4)) { - printk ("AudioTriX: MPU I/O port conflict\n"); + printk ("AudioTriX: MPU I/O port conflict (%x)\n", hw_config->io_base); return 0; } diff --git a/drivers/sound/uart6850.c b/drivers/sound/uart6850.c index 5b148115eaa1..52d0b1ee5ebf 100644 --- a/drivers/sound/uart6850.c +++ b/drivers/sound/uart6850.c @@ -1,10 +1,8 @@ /* * sound/uart6850.c - * - * Copyright by Hannu Savolainen 1993 - * - * Mon Nov 22 22:38:35 MET 1993 marco@driq.home.usn.nl: - * added 6850 support, used with COVOX SoundMaster II and custom cards. + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -25,40 +23,53 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + */ +#include + +/* Mon Nov 22 22:38:35 MET 1993 marco@driq.home.usn.nl: + * added 6850 support, used with COVOX SoundMaster II and custom cards. */ #include "sound_config.h" #if defined(CONFIG_UART6850) && defined(CONFIG_MIDI) -#define DATAPORT (uart6850_base) /* - * * * Midi6850 Data I/O Port on IBM - * */ -#define COMDPORT (uart6850_base+1) /* - * * * Midi6850 Command Port on IBM */ -#define STATPORT (uart6850_base+1) /* - * * * Midi6850 Status Port on IBM */ +static int uart6850_base = 0x330; + +#define DATAPORT (uart6850_base) +#define COMDPORT (uart6850_base+1) +#define STATPORT (uart6850_base+1) -#define uart6850_status() inb( STATPORT) +static int +uart6850_status (void) +{ + return inb (STATPORT); +} #define input_avail() (uart6850_status()&INPUT_AVAIL) #define output_ready() (uart6850_status()&OUTPUT_READY) -#define uart6850_cmd(cmd) outb( cmd, COMDPORT) -#define uart6850_read() inb( DATAPORT) -#define uart6850_write(byte) outb( byte, DATAPORT) +static void +uart6850_cmd (unsigned char cmd) +{ + outb (cmd, COMDPORT); +} +static int +uart6850_read (void) +{ + return inb (DATAPORT); +} +static void +uart6850_write (unsigned char byte) +{ + outb (byte, DATAPORT); +} -#define OUTPUT_READY 0x02 /* - * * * Mask for Data Read Ready Bit */ -#define INPUT_AVAIL 0x01 /* - * * * Mask for Data Send Ready Bit */ +#define OUTPUT_READY 0x02 /* Mask for data ready Bit */ +#define INPUT_AVAIL 0x01 /* Mask for Data Send Ready Bit */ -#define UART_RESET 0x95 /* - * * * 6850 Total Reset Command */ -#define UART_MODE_ON 0x03 /* - * * * 6850 Send/Receive UART Mode */ +#define UART_RESET 0x95 +#define UART_MODE_ON 0x03 static int uart6850_opened = 0; -static int uart6850_base = 0x330; static int uart6850_irq; static int uart6850_detected = 0; static int my_dev; @@ -67,7 +78,7 @@ static int reset_uart6850 (void); static void (*midi_input_intr) (int dev, unsigned char data); static void poll_uart6850 (unsigned long dummy); -static sound_os_info *uart6850_osp; +static int *uart6850_osp; static struct timer_list uart6850_timer = @@ -225,7 +236,7 @@ uart6850_end_read (int dev) } static int -uart6850_ioctl (int dev, unsigned cmd, ioctl_arg arg) +uart6850_ioctl (int dev, unsigned cmd, caddr_t arg) { return -EINVAL; } diff --git a/fs/dquot.c b/fs/dquot.c index c09766c31069..f068dc4d18e7 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -16,6 +16,9 @@ * Version: $Id: dquot.c,v 5.6 1995/11/15 20:30:27 mvw Exp mvw $ * * Author: Marco van Wieringen + * + * Fixes: Dmitry Gorodchanin , 11 Feb 96 + * removed race conditions in dqput(), dqget() and iput(). * * (C) Copyright 1994, 1995 Marco van Wieringen * @@ -678,6 +681,7 @@ void dquot_initialize(struct inode *inode, short type) { unsigned int id = 0; short cnt; + struct dquot *tmp; if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) { for (cnt = 0; cnt < MAXQUOTAS; cnt++) { @@ -694,7 +698,16 @@ void dquot_initialize(struct inode *inode, short type) id = inode->i_gid; break; } - inode->i_dquot[cnt] = dqget(inode->i_dev, id, cnt); + + tmp = dqget(inode->i_dev, id, cnt); + /* We may sleep in dqget(), so check it again. + * Dmitry Gorodchanin 02/11/96 + */ + if (inode->i_dquot[cnt] != NODQUOT) { + dqput(tmp); + continue; + } + inode->i_dquot[cnt] = tmp; inode->i_flags |= S_WRITE; } } @@ -704,12 +717,17 @@ void dquot_initialize(struct inode *inode, short type) void dquot_drop(struct inode *inode) { short cnt; + struct dquot * tmp; for (cnt = 0; cnt < MAXQUOTAS; cnt++) { if (inode->i_dquot[cnt] == NODQUOT) continue; - dqput(inode->i_dquot[cnt]); + /* We can sleep at dqput(). So we must do it this way. + * Dmitry Gorodchanin 02/11/96 + */ + tmp = inode->i_dquot[cnt]; inode->i_dquot[cnt] = NODQUOT; + dqput(tmp); } inode->i_flags &= ~S_WRITE; } diff --git a/fs/inode.c b/fs/inode.c index 1ac5bfcda53f..7e8794259b84 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -429,11 +429,19 @@ repeat: goto repeat; } - inode->i_count--; if (IS_WRITABLE(inode)) { - if (inode->i_sb && inode->i_sb->dq_op) + if (inode->i_sb && inode->i_sb->dq_op) { + /* Here we can sleep also. Let's do it again + * Dmitry Gorodchanin 02/11/96 + */ + inode->i_lock = 1; inode->i_sb->dq_op->drop(inode); + unlock_inode(inode); + goto repeat; + } } + + inode->i_count--; if (inode->i_mmap) { printk("iput: inode %lu on device %s still has mappings.\n", diff --git a/fs/msdos/msdosfs_syms.c b/fs/msdos/msdosfs_syms.c index 61d1de80aa45..6c918d8668b4 100644 --- a/fs/msdos/msdosfs_syms.c +++ b/fs/msdos/msdosfs_syms.c @@ -25,6 +25,8 @@ static struct symbol_table msdos_syms = { X(msdos_rmdir), X(msdos_unlink), X(msdos_unlink_umsdos), + X(msdos_read_super), + X(msdos_put_super), #include }; diff --git a/fs/proc/array.c b/fs/proc/array.c index eed832f0c431..f5539ddf1884 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -14,8 +14,8 @@ * EVERY character on the current page. * * - * Danny ter Haar : Some minor additions for cpuinfo - * + * Danny ter Haar : added cpuinfo + * * * Alessandro Rubini : profile extension. * diff --git a/include/linux/blk.h b/include/linux/blk.h index 1e333021fbb6..77fa556aed88 100644 --- a/include/linux/blk.h +++ b/include/linux/blk.h @@ -5,13 +5,6 @@ #include #include -/* - * NR_REQUEST is the number of entries in the request-queue. - * NOTE that writes may use only the low 2/3 of these: reads - * take precedence. - */ -#define NR_REQUEST 64 - /* * This is used in the elevator algorithm. We don't prioritise reads * over writes any more --- although reads are more time-critical than @@ -67,6 +60,9 @@ extern int optcd_init(void); #ifdef CONFIG_SJCD extern int sjcd_init(void); #endif CONFIG_SJCD +#ifdef CONFIG_CDI_INIT +extern int cdi_init(void); +#endif CONFIG_CDI_INIT #ifdef CONFIG_BLK_DEV_HD extern int hd_init(void); #endif diff --git a/include/linux/if_slip.h b/include/linux/if_slip.h index b86c05998f97..5bd77e520a67 100644 --- a/include/linux/if_slip.h +++ b/include/linux/if_slip.h @@ -20,7 +20,7 @@ */ #define SIOCSKEEPALIVE (SIOCDEVPRIVATE) /* Set keepalive timeout in sec */ -#define SIOCGKEEPALIVE (SICODEVPRIVATE+1) /* Get keepalive timeout */ +#define SIOCGKEEPALIVE (SIOCDEVPRIVATE+1) /* Get keepalive timeout */ #define SIOCSOUTFILL (SIOCDEVPRIVATE+2) /* Set outfill timeout */ #define SIOCGOUTFILL (SIOCDEVPRIVATE+3) /* Get outfill timeout */ diff --git a/include/linux/isp16.h b/include/linux/isp16.h new file mode 100644 index 000000000000..9945bb34c451 --- /dev/null +++ b/include/linux/isp16.h @@ -0,0 +1,75 @@ +/* -- isp16.h + * + * Header for detection and initialisation of cdrom interface (only) on + * ISP16 (MAD16, Mozart) sound card. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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. + * + */ + +/* These are the default values */ +#define ISP16_CDROM_TYPE "Sanyo" +#define ISP16_CDROM_IO_BASE 0x340 +#define ISP16_CDROM_IRQ 0 +#define ISP16_CDROM_DMA 0 + +/* 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 to avoid sound card conflicts */ +#define ISP16_IRQ_7 0x08 /* shouldn't be used to avoid sound card 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 */ + +#define ISP16_IO_BASE 0xF8D +#define ISP16_IO_SIZE 5 /* ports used from 0xF8D up to 0xF91 */ + +void isp16_setup(char *str, int *ints); +int isp16_init(void); diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 8e7128167fd7..0f29a2808b6c 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -124,6 +124,7 @@ enum scsi_directory_inos { PROC_SCSI_EATA2X, PROC_SCSI_AM53C974, PROC_SCSI_SSC, + PROC_SCSI_NCR53C406A, PROC_SCSI_SCSI_DEBUG, PROC_SCSI_NOT_PRESENT, PROC_SCSI_FILE, /* I'm asuming here that we */ diff --git a/include/linux/sched.h b/include/linux/sched.h index e881efdf08af..7f5fecf88ab4 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -112,9 +112,14 @@ extern void trap_init(void); asmlinkage void schedule(void); +/* ??? */ struct files_struct { + /* ??? */ int count; + /* bit mask to close fds on exec */ fd_set close_on_exec; + /* do we have at most NR_OPEN available fds? I assume fd i maps into + * each open file */ struct file * fd[NR_OPEN]; }; @@ -187,10 +192,17 @@ struct task_struct { unsigned long saved_kernel_stack; unsigned long kernel_stack_page; int exit_code, exit_signal; + /* ??? */ unsigned long personality; int dumpable:1; int did_exec:1; - int pid,pgrp,tty_old_pgrp,session,leader; + /* shouldn't this be pid_t? */ + int pid; + int pgrp; + int tty_old_pgrp; + int session; + /* boolean value for session group leader */ + int leader; int groups[NGROUPS]; /* * pointers to (original) parent process, youngest child, younger sibling, @@ -348,6 +360,20 @@ extern void release_thread(struct task_struct *); extern int do_execve(char *, char **, char **, struct pt_regs *); extern int do_fork(unsigned long, unsigned long, struct pt_regs *); + +/* See if we have a valid user level fd. + * If it makes sense, return the file structure it references. + * Otherwise return NULL. + */ +extern inline struct file *file_from_fd(const unsigned int fd) +{ + + if (fd >= NR_OPEN) + return NULL; + /* either valid or null */ + return current->files->fd[fd]; +} + /* * The wait-queues are circular lists, and you have to be *very* sure * to keep them correct. Use only these two functions to add/remove diff --git a/include/linux/sjcd.h b/include/linux/sjcd.h index 707616025e87..79bb1aa254a8 100644 --- a/include/linux/sjcd.h +++ b/include/linux/sjcd.h @@ -6,7 +6,7 @@ * vadim@rbrf.msk.su * vadim@ipsun.ras.ru * Eric van der Maarel - * maarel@marin.nl + * H.T.M.v.d.Maarel@marin.nl * * This information is based on mcd.c from M. Harriss and sjcd102.lst from * E. Moenkeberg. @@ -57,7 +57,7 @@ * Port access macro. Three ports are available: S-data port (command port), * status port (read only) and D-data port (read only). */ -#define SJCDPORT( x ) ( sjcd_port + ( x ) ) +#define SJCDPORT( x ) ( sjcd_base + ( x ) ) #define SJCD_STATUS_PORT SJCDPORT( 1 ) #define SJCD_S_DATA_PORT SJCDPORT( 0 ) #define SJCD_COMMAND_PORT SJCDPORT( 0 ) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index be9ecf390a06..797a5bcc38ee 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -63,6 +63,8 @@ struct sk_buff struct iphdr *iph; struct udphdr *uh; unsigned char *raw; + /* for passing an fd in a unix domain socket */ + struct file *filp; } h; union @@ -167,8 +169,10 @@ extern void skb_trim(struct sk_buff *skb, int len); */ extern __inline__ struct sk_buff *skb_peek(struct sk_buff_head *list_) { - struct sk_buff *list = (struct sk_buff *)list_; - return (list->next != list)? list->next : NULL; + struct sk_buff *list = ((struct sk_buff *)list_)->next; + if (list == (struct sk_buff *)list_) + list = NULL; + return list; } /* @@ -197,21 +201,32 @@ extern __inline__ void skb_queue_head_init(struct sk_buff_head *list) /* * Insert an sk_buff at the start of a list. + * + * The "__skb_xxxx()" functions are the non-atomic ones that + * can only be called with interrupts disabled. */ -extern __inline__ void skb_queue_head(struct sk_buff_head *list_,struct sk_buff *newsk) +extern __inline__ void __skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk) +{ + struct sk_buff *prev, *next; + + newsk->list = list; + list->qlen++; + prev = (struct sk_buff *)list; + next = prev->next; + newsk->next = next; + newsk->prev = prev; + next->prev = newsk; + prev->next = newsk; +} + +extern __inline__ void skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk) { unsigned long flags; - struct sk_buff *list = (struct sk_buff *)list_; save_flags(flags); cli(); - newsk->next = list->next; - newsk->prev = list; - newsk->next->prev = newsk; - newsk->prev->next = newsk; - newsk->list = list_; - list_->qlen++; + __skb_queue_head(list, newsk); restore_flags(flags); } @@ -219,78 +234,89 @@ extern __inline__ void skb_queue_head(struct sk_buff_head *list_,struct sk_buff * Insert an sk_buff at the end of a list. */ -extern __inline__ void skb_queue_tail(struct sk_buff_head *list_, struct sk_buff *newsk) +extern __inline__ void __skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk) +{ + struct sk_buff *prev, *next; + + newsk->list = list; + list->qlen++; + next = (struct sk_buff *)list; + prev = next->prev; + newsk->next = next; + newsk->prev = prev; + next->prev = newsk; + prev->next = newsk; +} + +extern __inline__ void skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk) { unsigned long flags; - struct sk_buff *list = (struct sk_buff *)list_; save_flags(flags); cli(); - - newsk->next = list; - newsk->prev = list->prev; - - newsk->next->prev = newsk; - newsk->prev->next = newsk; - newsk->list=list_; - list_->qlen++; + __skb_queue_tail(list, newsk); restore_flags(flags); } /* - * Remove an sk_buff from a list. This routine is also interrupt safe - * so you can grab read and free buffers as another process adds them. - * - * Note we now do the ful list + * Remove an sk_buff from a list. */ -extern __inline__ struct sk_buff *skb_dequeue(struct sk_buff_head *list_) +extern __inline__ struct sk_buff *__skb_dequeue(struct sk_buff_head *list) +{ + struct sk_buff *next, *prev, *result; + + prev = (struct sk_buff *) list; + next = prev->next; + result = NULL; + if (next != prev) { + result = next; + next = next->next; + list->qlen--; + next->prev = prev; + prev->next = next; + result->next = NULL; + result->prev = NULL; + result->list = NULL; + } + return result; +} + +extern __inline__ struct sk_buff *skb_dequeue(struct sk_buff_head *list) { long flags; struct sk_buff *result; - struct sk_buff *list = (struct sk_buff *)list_; save_flags(flags); cli(); - - result = list->next; - if (result == list) - { - restore_flags(flags); - return NULL; - } - else - { - result->next->prev = list; - list->next = result->next; - - result->next = NULL; - result->prev = NULL; - - list_->qlen--; - result->list=NULL; - restore_flags(flags); - - return result; - } + result = __skb_dequeue(list); + restore_flags(flags); + return result; } /* * Insert a packet before another one in a list. */ +extern __inline__ void __skb_insert(struct sk_buff *next, struct sk_buff *newsk) +{ + struct sk_buff * prev = next->prev; + + newsk->next = next; + newsk->prev = prev; + next->prev = newsk; + prev->next = newsk; + newsk->list = next->list; + newsk->list->qlen++; +} + extern __inline__ void skb_insert(struct sk_buff *old, struct sk_buff *newsk) { unsigned long flags; save_flags(flags); cli(); - newsk->next = old; - newsk->prev = old->prev; - old->prev = newsk; - newsk->prev->next = newsk; - newsk->list = old->list; - newsk->list->qlen++; + __skb_insert(old, newsk); restore_flags(flags); } @@ -298,23 +324,45 @@ extern __inline__ void skb_insert(struct sk_buff *old, struct sk_buff *newsk) * Place a packet after a given packet in a list. */ +extern __inline__ void __skb_append(struct sk_buff *prev, struct sk_buff *newsk) +{ + struct sk_buff * next = prev->next; + + newsk->next = next; + newsk->prev = prev; + next->prev = newsk; + prev->next = newsk; + newsk->list = prev->list; + newsk->list->qlen++; +} + extern __inline__ void skb_append(struct sk_buff *old, struct sk_buff *newsk) { unsigned long flags; save_flags(flags); cli(); - - newsk->prev = old; - newsk->next = old->next; - newsk->next->prev = newsk; - old->next = newsk; - newsk->list = old->list; - newsk->list->qlen++; - + __skb_append(old, newsk); restore_flags(flags); } +/* + * remove sk_buff from list. _Must_ be called atomically, and with + * the list known.. + */ +extern __inline__ void __skb_unlink(struct sk_buff *skb, struct sk_buff_head *list) +{ + struct sk_buff * next, * prev; + + list->qlen--; + next = skb->next; + prev = skb->prev; + skb->next = NULL; + skb->prev = NULL; + skb->list = NULL; + (next->prev = prev)->next = next; +} + /* * Remove an sk_buff from its list. Works even without knowing the list it * is sitting on, which can be handy at times. It also means that THE LIST @@ -328,16 +376,8 @@ extern __inline__ void skb_unlink(struct sk_buff *skb) save_flags(flags); cli(); - if(skb->list) - { - skb->list->qlen--; - skb->next->prev = skb->prev; - skb->prev->next = skb->next; - skb->next = NULL; - skb->prev = NULL; - skb->list = NULL; - } + __skb_unlink(skb, skb->list); restore_flags(flags); } diff --git a/include/linux/soundcard.h b/include/linux/soundcard.h index c4035bc90390..0f0da6858a77 100644 --- a/include/linux/soundcard.h +++ b/include/linux/soundcard.h @@ -1,51 +1,29 @@ #ifndef SOUNDCARD_H #define SOUNDCARD_H /* - * Copyright by Hannu Savolainen 1993 + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. + * modification, are permitted provided that the following conditions are + * met: 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. 2. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * */ - /* - * If you make modifications to this file, please contact me before - * distributing the modified version. There is already enough - * diversity in the world. - * - * Regards, - * Hannu Savolainen - * hannu@voxware.pp.fi - * - ********************************************************************** - * PS. The Hacker's Guide to VoxWare available from - * nic.funet.fi:pub/OS/Linux/ALPHA/sound. The file is - * snd-sdk-doc-0.1.ps.gz (gzipped postscript). It contains - * some useful information about programming with VoxWare. - * (NOTE! The pub/OS/Linux/ALPHA/ directories are hidden. You have - * to cd inside them before the files are accessible.) - ********************************************************************** - */ - #define SOUND_VERSION 301 #define VOXWARE @@ -172,7 +150,7 @@ struct patch_info { short device_no; /* Synthesizer number */ short instr_no; /* Midi pgm# */ - unsigned long mode; + unsigned int mode; /* * The least significant byte has the same format than the GUS .PAT * files @@ -191,8 +169,8 @@ struct patch_info { #define WAVE_SCALE 0x00040000 /* The scaling info is valid */ /* Other bits must be zeroed */ - long len; /* Size of the wave data in bytes */ - long loop_start, loop_end; /* Byte offsets from the beginning */ + int len; /* Size of the wave data in bytes */ + int loop_start, loop_end; /* Byte offsets from the beginning */ /* * The base_freq and base_note fields are used when computing the @@ -211,9 +189,9 @@ struct patch_info { */ unsigned int base_freq; - unsigned long base_note; - unsigned long high_note; - unsigned long low_note; + unsigned int base_note; + unsigned int high_note; + unsigned int low_note; int panning; /* -128=left, 127=right */ int detuning; @@ -250,7 +228,7 @@ struct sysex_info { #define SYSEX_PATCH _PATCHKEY(0x05) #define MAUI_PATCH _PATCHKEY(0x06) short device_no; /* Synthesizer number */ - long len; /* Size of the sysex data in bytes */ + int len; /* Size of the sysex data in bytes */ unsigned char data[1]; /* Sysex data starts here */ }; @@ -281,7 +259,7 @@ struct sysex_info { */ struct patmgr_info { /* Note! size must be < 4k since kmalloc() is used */ - unsigned long key; /* Don't worry. Reserved for communication + unsigned int key; /* Don't worry. Reserved for communication between the patch manager and the driver. */ #define PM_K_EVENT 1 /* Event from the /dev/sequencer driver */ #define PM_K_COMMAND 2 /* Request from a application */ @@ -315,14 +293,14 @@ struct patmgr_info { /* Note! size must be < 4k since kmalloc() is used */ * Commands above 0xffff reserved for device specific use */ - long parm1; - long parm2; - long parm3; + int parm1; + int parm2; + int parm3; union { unsigned char data8[4000]; unsigned short data16[2000]; - unsigned long data32[1000]; + unsigned int data32[1000]; struct patch_info patch; } data; }; @@ -526,7 +504,7 @@ struct synth_info { /* Read only */ int nr_voices; int nr_drums; /* Obsolete field */ int instr_bank_size; - unsigned long capabilities; + unsigned int capabilities; #define SYNTH_CAP_PERCMODE 0x00000001 /* No longer used */ #define SYNTH_CAP_OPL3 0x00000002 /* Set if OPL3 supported */ #define SYNTH_CAP_INPUT 0x00000004 /* Input (MIDI) device */ @@ -543,7 +521,7 @@ struct sound_timer_info { struct midi_info { char name[30]; int device; /* 0-N. INITIALIZE BEFORE CALLING */ - unsigned long capabilities; /* To be defined later */ + unsigned int capabilities; /* To be defined later */ int dev_type; int dummies[18]; /* Reserve space */ }; @@ -1081,7 +1059,8 @@ void seqbuf_dump(void); /* This function must be provided by programs */ _seqbuf[_seqbufptr+2] = (dev);\ _seqbuf[_seqbufptr+3] = (voice);\ _seqbuf[_seqbufptr+4] = (controller);\ - *(short *)&_seqbuf[_seqbufptr+5] = (value);\ + _seqbuf[_seqbufptr+5] = ((value)&0xff);\ + _seqbuf[_seqbufptr+6] = ((value>>8)&0xff);\ _seqbuf[_seqbufptr+7] = 0;\ _SEQ_ADVBUF(8);} /* diff --git a/include/linux/time.h b/include/linux/time.h index be81225b8ff2..269e9dc6f579 100644 --- a/include/linux/time.h +++ b/include/linux/time.h @@ -2,8 +2,8 @@ #define _LINUX_TIME_H struct timespec { - long ts_sec; /* seconds */ - long ts_nsec; /* nanoseconds */ + long tv_sec; /* seconds */ + long tv_nsec; /* nanoseconds */ }; struct timeval { diff --git a/include/linux/ultrasound.h b/include/linux/ultrasound.h index 40e2443e6f65..3e80057506f8 100644 --- a/include/linux/ultrasound.h +++ b/include/linux/ultrasound.h @@ -1,35 +1,32 @@ #ifndef _ULTRASOUND_H_ #define _ULTRASOUND_H_ /* - * Copyright by Hannu Savolainen 1993 + * ultrasound.h - Macros for programming the Gravis Ultrasound + * These macros are extremely device dependent + * and not portable. + */ +/* + * Copyright by Hannu Savolainen 1993-1996 * * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. + * modification, are permitted provided that the following conditions are + * met: 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. 2. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - */ - -/* - * ultrasound.h - Macros for programming the Gravis Ultrasound - * These macros are extremely device dependent - * and not portable. */ /* diff --git a/include/net/tcp.h b/include/net/tcp.h index 4a820364ca15..9493e774f8e1 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -95,7 +95,7 @@ extern __inline int before(__u32 seq1, __u32 seq2) extern __inline int after(__u32 seq1, __u32 seq2) { - return (__s32)(seq1-seq2) > 0; + return (__s32)(seq2-seq1) < 0; } @@ -132,7 +132,7 @@ extern void tcp_time_wait(struct sock *); extern void tcp_retransmit(struct sock *, int); extern void tcp_do_retransmit(struct sock *, int); extern void tcp_send_check(struct tcphdr *th, unsigned long saddr, - unsigned long daddr, int len, struct sock *sk); + unsigned long daddr, int len, struct sk_buff *skb); /* tcp_output.c */ diff --git a/init/main.c b/init/main.c index f615ba367a4d..2b0913462b16 100644 --- a/init/main.c +++ b/init/main.c @@ -56,6 +56,7 @@ extern void sysctl_init(void); extern void swap_setup(char *str, int *ints); extern void buff_setup(char *str, int *ints); +extern void panic_setup(char *str, int *ints); extern void bmouse_setup(char *str, int *ints); extern void eth_setup(char *str, int *ints); extern void xd_setup(char *str, int *ints); @@ -107,6 +108,9 @@ extern void optcd_setup(char *str, int *ints); #ifdef CONFIG_SJCD extern void sjcd_setup(char *str, int *ints); #endif CONFIG_SJCD +#ifdef CONFIG_ISP16_CDI +extern void isp16_setup(char *str, int *ints); +#endif CONFIG_ISP16_CDI #ifdef CONFIG_BLK_DEV_RAM static void ramdisk_start_setup(char *str, int *ints); static void load_ramdisk(char *str, int *ints); @@ -194,6 +198,7 @@ struct { #endif { "swap=", swap_setup }, { "buff=", buff_setup }, + { "panic=", panic_setup }, #ifdef CONFIG_BUGi386 { "no-hlt", no_halt }, { "no387", no_387 }, @@ -287,6 +292,9 @@ struct { #ifdef CONFIG_SJCD { "sjcd=", sjcd_setup }, #endif CONFIG_SJCD +#ifdef CONFIG_ISP16_CDI + { "isp16=", isp16_setup }, +#endif CONFIG_ISP16_CDI #ifdef CONFIG_SOUND { "sound=", sound_setup }, #endif diff --git a/kernel/ksyms.c b/kernel/ksyms.c index 87da8404e6c4..c4552d9ae0dd 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -209,7 +209,6 @@ struct symbol_table symbol_table = { X(add_blkdev_randomness), X(generic_file_read), X(generic_readpage), - X(mark_buffer_uptodate), /* device registration */ X(register_chrdev), diff --git a/kernel/panic.c b/kernel/panic.c index 4c67c8f0a4df..b109ee4c2672 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -12,13 +12,24 @@ #include #include +#include asmlinkage void sys_sync(void); /* it's really int */ +extern void hard_reset_now(void); + +static int timeout = -1; + +void panic_setup(char *str, int *ints) +{ + if (ints[0] == 1) + timeout = ints[1]; +} NORET_TYPE void panic(const char * fmt, ...) { static char buf[1024]; va_list args; + int i; va_start(args, fmt); vsprintf(buf, fmt, args); @@ -28,6 +39,17 @@ NORET_TYPE void panic(const char * fmt, ...) printk(KERN_EMERG "In swapper task - not syncing\n"); else sys_sync(); + if (timeout >= 0) + { + /* + * Delay timeout seconds before rebooting the machine. + * We can't use the "normal" timers since we just paniced.. + */ + printk(KERN_EMERG "Rebooting in %d seconds..",timeout); + for(i = 0; i < (timeout*1000); i++) + udelay(1000); + hard_reset_now(); + } for(;;); } diff --git a/kernel/sched.c b/kernel/sched.c index aaa8867c337b..848c14db2730 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1115,8 +1115,8 @@ asmlinkage int sys_sched_rr_get_interval(pid_t pid, struct timespec *interval) if (error) return error; - t.ts_sec = 0; - t.ts_nsec = 0; /* <-- Linus, please fill correct value in here */ + t.tv_sec = 0; + t.tv_nsec = 0; /* <-- Linus, please fill correct value in here */ return -ENOSYS; /* and then delete this line. Thanks! */ memcpy_tofs(interval, &t, sizeof(struct timespec)); diff --git a/net/core/dev.c b/net/core/dev.c index 1ebe258fa444..efe1acc98b79 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -329,8 +329,8 @@ int unregister_netdevice_notifier(struct notifier_block *nb) void dev_queue_xmit(struct sk_buff *skb, struct device *dev, int pri) { unsigned long flags; - struct packet_type *ptype; - int where = 0; /* used to say if the packet should go */ + struct sk_buff_head *list; + int retransmission = 0; /* used to say if the packet should go */ /* at the front or the back of the */ /* queue - front is a retransmit try */ @@ -350,7 +350,7 @@ void dev_queue_xmit(struct sk_buff *skb, struct device *dev, int pri) if (pri < 0) { pri = -pri-1; - where = 1; + retransmission = 1; } #ifdef CONFIG_NET_DEBUG @@ -382,46 +382,44 @@ void dev_queue_xmit(struct sk_buff *skb, struct device *dev, int pri) if (net_alias_is(dev)) skb->dev = dev = net_alias_main_dev(dev); #endif + list = dev->buffs + pri; save_flags(flags); - cli(); - if (!where) /* Always keep order. It helps other hosts - far more than it costs us */ - { - /* - * Check we are not overruning the device queue length. - */ - - if(skb_queue_len(dev->buffs + pri) > dev->tx_queue_len) - { - dev_kfree_skb(skb, FREE_WRITE); - return; + /* if this isn't a retransmission, use the first packet instead... */ + if (!retransmission) { + if (skb_queue_len(list)) { + /* avoid overrunning the device queue.. */ + if (skb_queue_len(list) > dev->tx_queue_len) { + dev_kfree_skb(skb, FREE_WRITE); + return; + } + cli(); + skb_device_unlock(skb); /* Buffer is on the device queue and can be freed safely */ + __skb_queue_tail(list, skb); + skb = __skb_dequeue(list); + skb_device_lock(skb); /* New buffer needs locking down */ + restore_flags(flags); } - skb_queue_tail(dev->buffs + pri,skb); - skb_device_unlock(skb); /* Buffer is on the device queue and can be freed safely */ - skb = skb_dequeue(dev->buffs + pri); - skb_device_lock(skb); /* New buffer needs locking down */ - } - restore_flags(flags); - - /* copy outgoing packets to any sniffer packet handlers */ - if(!where && dev_nit) - { - skb->stamp=xtime; - for (ptype = ptype_all; ptype!=NULL; ptype = ptype->next) - { - /* Never send packets back to the socket - * they originated from - MvS (miquels@drinkel.ow.org) - */ - if ((ptype->dev == dev || !ptype->dev) && - ((struct sock *)ptype->data != skb->sk)) + + /* copy outgoing packets to any sniffer packet handlers */ + if (dev_nit) { + struct packet_type *ptype; + skb->stamp=xtime; + for (ptype = ptype_all; ptype!=NULL; ptype = ptype->next) { - struct sk_buff *skb2; - if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) - break; - skb2->h.raw = skb2->data + dev->hard_header_len; - skb2->mac.raw = skb2->data; - ptype->func(skb2, skb->dev, ptype); + /* Never send packets back to the socket + * they originated from - MvS (miquels@drinkel.ow.org) + */ + if ((ptype->dev == dev || !ptype->dev) && + ((struct sock *)ptype->data != skb->sk)) + { + struct sk_buff *skb2; + if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) + break; + skb2->h.raw = skb2->data + dev->hard_header_len; + skb2->mac.raw = skb2->data; + ptype->func(skb2, skb->dev, ptype); + } } } } @@ -441,7 +439,7 @@ void dev_queue_xmit(struct sk_buff *skb, struct device *dev, int pri) */ cli(); skb_device_unlock(skb); - skb_queue_head(dev->buffs + pri,skb); + __skb_queue_head(list,skb); restore_flags(flags); } @@ -585,7 +583,7 @@ void net_bh(void *tmp) * While the queue is not empty */ - while((skb=skb_dequeue(&backlog))!=NULL) + while((skb=__skb_dequeue(&backlog))!=NULL) { /* * We have a packet. Therefore the queue has shrunk @@ -671,7 +669,7 @@ void net_bh(void *tmp) * [Ought to take this out judging by tests it slows * us down not speeds us up] */ -#ifdef CONFIG_XMIT_EVERY +#ifdef XMIT_EVERY dev_transmit(); #endif cli(); @@ -687,8 +685,10 @@ void net_bh(void *tmp) /* * One last output flush. */ - + +#ifdef XMIT_AFTER dev_transmit(); +#endif } @@ -700,8 +700,8 @@ void net_bh(void *tmp) void dev_tint(struct device *dev) { int i; - struct sk_buff *skb; unsigned long flags; + struct sk_buff_head * head; /* * aliases do not transmit (for now :) ) @@ -710,21 +710,19 @@ void dev_tint(struct device *dev) #ifdef CONFIG_NET_ALIAS if (net_alias_is(dev)) return; #endif - save_flags(flags); + head = dev->buffs; + save_flags(flags); + cli(); + /* * Work the queues in priority order - */ - - for(i = 0;i < DEV_NUMBUFFS; i++) + */ + for(i = 0;i < DEV_NUMBUFFS; i++,head++) { - /* - * Pull packets from the queue - */ - + struct sk_buff *skb = skb_peek(head); - cli(); - while((skb=skb_dequeue(&dev->buffs[i]))!=NULL) - { + if (skb) { + __skb_unlink(skb, head); /* * Stop anyone freeing the buffer while we retransmit it */ diff --git a/net/core/iovec.c b/net/core/iovec.c index 3b12b6e3a3d6..2601f103392b 100644 --- a/net/core/iovec.c +++ b/net/core/iovec.c @@ -33,9 +33,10 @@ int verify_iovec(struct msghdr *m, struct iovec *iov, char *address, int mode) if(m->msg_name!=NULL) { - if(mode==VERIFY_READ) + if(mode==VERIFY_READ) { err=move_addr_to_kernel(m->msg_name, m->msg_namelen, address); - else + m->msg_name = address; + } else err=verify_area(mode, m->msg_name, m->msg_namelen); if(err<0) return err; diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 0627a9aa7e29..686a3522dd48 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -50,11 +50,11 @@ * Resource tracking variables */ -volatile unsigned long net_skbcount = 0; -volatile unsigned long net_locked = 0; -volatile unsigned long net_allocs = 0; -volatile unsigned long net_fails = 0; -volatile unsigned long net_free_locked = 0; +unsigned long net_skbcount = 0; +unsigned long net_locked = 0; +unsigned long net_allocs = 0; +unsigned long net_fails = 0; +unsigned long net_free_locked = 0; extern unsigned long ip_frag_mem; @@ -517,7 +517,6 @@ void kfree_skb(struct sk_buff *skb, int rw) struct sk_buff *alloc_skb(unsigned int size,int priority) { struct sk_buff *skb; - unsigned long flags; int len=size; unsigned char *bptr; @@ -574,10 +573,7 @@ struct sk_buff *alloc_skb(unsigned int size,int priority) skb->localroute = 0; skb->ip_summed = 0; memset(skb->proto_priv, 0, sizeof(skb->proto_priv)); - save_flags(flags); - cli(); net_skbcount++; - restore_flags(flags); #if CONFIG_SKB_CHECK skb->magic_debug_cookie = SK_GOOD_SKB; #endif @@ -596,6 +592,15 @@ struct sk_buff *alloc_skb(unsigned int size,int priority) * Free an skbuff by memory */ +static inline void __kfree_skbmem(struct sk_buff *skb) +{ + /* don't do anything if somebody still uses us */ + if (--skb->count <= 0) { + kfree(skb->head); + net_skbcount--; + } +} + void kfree_skbmem(struct sk_buff *skb) { unsigned long flags; @@ -608,7 +613,7 @@ void kfree_skbmem(struct sk_buff *skb) /* free the skb that contains the actual data if we've clone()'d */ if (skb->data_skb) { addr = skb; - kfree_skbmem(skb->data_skb); + __kfree_skbmem(skb->data_skb); } kfree(addr); net_skbcount--; @@ -623,8 +628,8 @@ void kfree_skbmem(struct sk_buff *skb) struct sk_buff *skb_clone(struct sk_buff *skb, int priority) { - struct sk_buff *n; unsigned long flags; + struct sk_buff *n; IS_SKB(skb); n = kmalloc(sizeof(*n), priority); @@ -649,22 +654,6 @@ struct sk_buff *skb_clone(struct sk_buff *skb, int priority) n->tries = 0; n->lock = 0; n->users = 0; - n->h.raw=skb->h.raw; - n->mac.raw=skb->mac.raw; - n->dev=skb->dev; - n->ip_hdr=skb->ip_hdr; - n->saddr=skb->saddr; - n->daddr=skb->daddr; - n->raddr=skb->raddr; - n->seq=skb->seq; - n->end_seq=skb->end_seq; - n->ack_seq=skb->ack_seq; - n->acked=skb->acked; - memcpy(n->proto_priv, skb->proto_priv, sizeof(skb->proto_priv)); - n->used=skb->used; - n->arp=skb->arp; - n->pkt_type=skb->pkt_type; - n->stamp=skb->stamp; return n; } diff --git a/net/core/sock.c b/net/core/sock.c index a864b34a631d..ef2c0b4993f8 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -544,45 +544,37 @@ struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size, unsigne void release_sock(struct sock *sk) { - unsigned long flags; #ifdef CONFIG_INET struct sk_buff *skb; #endif + /* + * First, mark it not in use: this ensures that we will not + * get any new backlog packets.. + */ + sk->inuse = 0; + +#ifdef CONFIG_INET if (!sk->prot) return; + /* - * Make the backlog atomic. If we don't do this there is a tiny - * window where a packet may arrive between the sk->blog being - * tested and then set with sk->inuse still 0 causing an extra - * unwanted re-entry into release_sock(). + * This is only ever called from a user process context, hence + * (until fine grained SMP) its safe. sk->inuse must be volatile + * so the compiler doesn't do anything unfortunate with it. */ - save_flags(flags); - cli(); - if (sk->blog) - { - restore_flags(flags); - return; - } - sk->blog=1; - sk->inuse = 1; - restore_flags(flags); -#ifdef CONFIG_INET /* See if we have any packets built up. */ - while((skb = skb_dequeue(&sk->back_log)) != NULL) + while ((skb = __skb_dequeue(&sk->back_log)) != NULL) { - sk->blog = 1; + sk->inuse = 1; /* Very important.. */ if (sk->prot->rcv) sk->prot->rcv(skb, skb->dev, (struct options*)skb->proto_priv, skb->saddr, skb->len, skb->daddr, 1, /* Only used for/by raw sockets. */ (struct inet_protocol *)sk->pair); + sk->inuse = 0; } -#endif - sk->blog = 0; - sk->inuse = 0; -#ifdef CONFIG_INET if (sk->dead && sk->state == TCP_CLOSE) { /* Should be about 2 rtt's */ diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 98aaa4abd220..1f2e8862187a 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -587,8 +587,9 @@ static int inet_create(struct socket *sock, int protocol) if (sk == NULL) return(-ENOBUFS); memset(sk,0,sizeof(*sk)); /* Efficient way to set most fields to zero */ -/* sk->num = 0; - * sk->reuse = 0;*/ + /* + * Note for tcp that also wiped the dummy_th block for us. + */ switch(sock->type) { case SOCK_STREAM: @@ -653,8 +654,6 @@ static int inet_create(struct socket *sock, int protocol) sk->socket = sock; #ifdef CONFIG_TCP_NAGLE_OFF sk->nonagle = 1; -#else -/* sk->nonagle = 0;*/ #endif sk->type = sock->type; sk->protocol = protocol; @@ -693,6 +692,13 @@ static int inet_create(struct socket *sock, int protocol) *sk->ip_mc_name=0; sk->ip_mc_list=NULL; #endif + /* + * Speed up by setting some standard state for the dummy_th + * if TCP uses it (maybe move to tcp_init later) + */ + + sk->dummy_th.ack=1; + sk->dummy_th.doff=sizeof(struct tcphdr)>>2; sk->state_change = def_callback1; sk->data_ready = def_callback2; diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 1f97b19b506d..3600b9f97482 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -802,14 +802,31 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg) * Modified January 1995 from a go-faster DOS routine by * Jorge Cwik */ - +#undef DEBUG_TCP_CHECK void tcp_send_check(struct tcphdr *th, unsigned long saddr, - unsigned long daddr, int len, struct sock *sk) + unsigned long daddr, int len, struct sk_buff *skb) { +#ifdef DEBUG_TCP_CHECK + u16 check; +#endif + th->check = 0; + th->check = tcp_check(th, len, saddr, daddr, + csum_partial((char *)th,sizeof(*th),skb->csum)); + +#ifdef DEBUG_TCP_CHECK + check = th->check; th->check = 0; th->check = tcp_check(th, len, saddr, daddr, csum_partial((char *)th,len,0)); - return; + if (check != th->check) { + static int count = 0; + if (++count < 10) { + printk("Checksum %x (%x) from %p\n", th->check, check, + (&th)[-1]); + printk("TCP=\n", th->doff*4, th->ack, th->syn, th->fin); + } + } +#endif } @@ -823,9 +840,6 @@ extern __inline int tcp_build_header(struct tcphdr *th, struct sock *sk, int pus memcpy(th,(void *) &(sk->dummy_th), sizeof(*th)); th->seq = htonl(sk->write_seq); th->psh =(push == 0) ? 1 : 0; - th->doff = sizeof(*th)/4; - th->ack = 1; - th->fin = 0; sk->ack_backlog = 0; sk->bytes_rcv = 0; sk->ack_timed = 0; @@ -1003,30 +1017,29 @@ static int tcp_sendmsg(struct sock *sk, struct msghdr *msg, if ((skb = tcp_dequeue_partial(sk)) != NULL) { - int hdrlen; + int tcp_size; - /* IP header + TCP header */ - hdrlen = ((unsigned long)skb->h.th - (unsigned long)skb->data) - + sizeof(struct tcphdr); + tcp_size = skb->tail - (unsigned char *)(skb->h.th + 1); /* Add more stuff to the end of skb->len */ if (!(flags & MSG_OOB)) { - copy = min(sk->mss - (skb->len - hdrlen), seglen); + copy = min(sk->mss - tcp_size, seglen); if (copy <= 0) { printk("TCP: **bug**: \"copy\" <= 0\n"); return -EFAULT; - } + } + tcp_size += copy; memcpy_fromfs(skb_put(skb,copy), from, copy); + skb->csum = csum_partial(skb->tail - tcp_size, tcp_size, 0); from += copy; copied += copy; len -= copy; sk->write_seq += copy; seglen -= copy; } - if ((skb->len - hdrlen) >= sk->mss || - (flags & MSG_OOB) || !sk->packets_out) + if (tcp_size >= sk->mss || (flags & MSG_OOB) || !sk->packets_out) tcp_send_skb(sk, skb); else tcp_enqueue_partial(skb, sk); @@ -1058,6 +1071,11 @@ static int tcp_sendmsg(struct sock *sk, struct msghdr *msg, send_tmp = NULL; if (copy < sk->mss && !(flags & MSG_OOB) && sk->packets_out) { +#if EXTRA_RELEASE +/* + * we don't really need to release even if we sleep: our packets + * will be backlogged for us, and that's just fine. + */ /* * We will release the socket in case we sleep here. */ @@ -1066,16 +1084,19 @@ static int tcp_sendmsg(struct sock *sk, struct msghdr *msg, * NB: following must be mtu, because mss can be increased. * mss is always <= mtu */ +#endif skb = sock_wmalloc(sk, sk->mtu + 128 + prot->max_header + 15, 0, GFP_KERNEL); sk->inuse = 1; send_tmp = skb; } else { +#if EXTRA_RELEASE /* * We will release the socket in case we sleep here. */ release_sock(sk); +#endif skb = sock_wmalloc(sk, copy + prot->max_header + 15 , 0, GFP_KERNEL); sk->inuse = 1; } @@ -1156,7 +1177,8 @@ static int tcp_sendmsg(struct sock *sk, struct msghdr *msg, skb->h.th->urg_ptr = ntohs(copy); } - memcpy_fromfs(skb_put(skb,copy), from, copy); + skb->csum = csum_partial_copy_fromuser(from, + skb_put(skb,copy), copy, 0); from += copy; copied += copy; @@ -1240,6 +1262,7 @@ void tcp_read_wakeup(struct sock *sk) buff->sk = sk; buff->localroute = sk->localroute; + buff->csum = 0; /* * Put in the IP header and routing stuff. @@ -1258,14 +1281,6 @@ void tcp_read_wakeup(struct sock *sk) memcpy(t1,(void *) &sk->dummy_th, sizeof(*t1)); t1->seq = htonl(sk->sent_seq); - t1->ack = 1; - t1->res1 = 0; - t1->res2 = 0; - t1->rst = 0; - t1->urg = 0; - t1->syn = 0; - t1->psh = 0; - sk->ack_backlog = 0; sk->bytes_rcv = 0; @@ -1274,12 +1289,89 @@ void tcp_read_wakeup(struct sock *sk) t1->window = htons(sk->window); t1->ack_seq = htonl(sk->acked_seq); t1->doff = sizeof(*t1)/4; - tcp_send_check(t1, sk->saddr, sk->daddr, sizeof(*t1), sk); + tcp_send_check(t1, sk->saddr, sk->daddr, sizeof(*t1), buff); sk->prot->queue_xmit(sk, dev, buff, 1); tcp_statistics.TcpOutSegs++; } +/* + * Handle reading urgent data. BSD has very simple semantics for + * this, no blocking and very strange errors 8) + */ + +static int tcp_recv_urg(struct sock * sk, int nonblock, + struct msghdr *msg, int len, int flags, int *addr_len) +{ + /* + * No URG data to read + */ + if (sk->urginline || !sk->urg_data || sk->urg_data == URG_READ) + return -EINVAL; /* Yes this is right ! */ + + if (sk->err) + return sock_error(sk); + + if (sk->state == TCP_CLOSE || sk->done) + { + if (!sk->done) + { + sk->done = 1; + return 0; + } + return -ENOTCONN; + } + + if (sk->shutdown & RCV_SHUTDOWN) + { + sk->done = 1; + return 0; + } + sk->inuse = 1; + if (sk->urg_data & URG_VALID) + { + char c = sk->urg_data; + if (!(flags & MSG_PEEK)) + sk->urg_data = URG_READ; + memcpy_toiovec(msg->msg_iov, &c, 1); + if(msg->msg_name) + { + struct sockaddr_in *sin=(struct sockaddr_in *)msg->msg_name; + sin->sin_family=AF_INET; + sin->sin_addr.s_addr=sk->daddr; + sin->sin_port=sk->dummy_th.dest; + } + if(addr_len) + *addr_len=sizeof(struct sockaddr_in); + release_sock(sk); + return 1; + } + release_sock(sk); + + /* + * Fixed the recv(..., MSG_OOB) behaviour. BSD docs and + * the available implementations agree in this case: + * this call should never block, independent of the + * blocking state of the socket. + * Mike + */ + return -EAGAIN; +} + +/* + * Release a skb if it is no longer needed. This routine + * must be called with interrupts disabled or "sk->inuse = 1" + * so that the sk_buff queue operation is ok. + */ + +static inline void tcp_eat_skb(struct sock *sk, struct sk_buff * skb) +{ + sk->ack_backlog++; + skb->sk = sk; + __skb_unlink(skb, &sk->receive_queue); + kfree_skb(skb, FREE_READ); +} + /* * FIXME: * This routine frees used buffers. @@ -1289,36 +1381,19 @@ void tcp_read_wakeup(struct sock *sk) static void cleanup_rbuf(struct sock *sk) { - unsigned long flags; struct sk_buff *skb; unsigned long rspace; - save_flags(flags); - cli(); - /* - * See if we have anything to free up? + * NOTE! 'sk->inuse' must be set, so that we don't get + * a messed-up receive queue. */ - - skb = skb_peek(&sk->receive_queue); - if (!skb || !skb->used || skb->users) { - restore_flags(flags); - return; + while ((skb=skb_peek(&sk->receive_queue)) != NULL) { + if (!skb->used || skb->users) + break; + tcp_eat_skb(sk, skb); } - /* - * We have to loop through all the buffer headers, - * and try to free up all the space we can. - */ - - do { - skb_unlink(skb); - skb->sk = sk; - kfree_skb(skb, FREE_READ); - skb = skb_peek(&sk->receive_queue); - } while (skb && skb->used && !skb->users); - restore_flags(flags); - /* * FIXME: * At this point we should send an ack if the difference @@ -1339,7 +1414,6 @@ static void cleanup_rbuf(struct sock *sk) * immediately. Otherwise we will wait up to .5 seconds in case * the user reads some more. */ - sk->ack_backlog++; /* * It's unclear whether to use sk->mtu or sk->mss here. They differ only @@ -1369,70 +1443,6 @@ static void cleanup_rbuf(struct sock *sk) } -/* - * Handle reading urgent data. BSD has very simple semantics for - * this, no blocking and very strange errors 8) - */ - -static int tcp_recv_urg(struct sock * sk, int nonblock, - struct msghdr *msg, int len, int flags, int *addr_len) -{ - /* - * No URG data to read - */ - if (sk->urginline || !sk->urg_data || sk->urg_data == URG_READ) - return -EINVAL; /* Yes this is right ! */ - - if (sk->err) - return sock_error(sk); - - if (sk->state == TCP_CLOSE || sk->done) - { - if (!sk->done) - { - sk->done = 1; - return 0; - } - return -ENOTCONN; - } - - if (sk->shutdown & RCV_SHUTDOWN) - { - sk->done = 1; - return 0; - } - sk->inuse = 1; - if (sk->urg_data & URG_VALID) - { - char c = sk->urg_data; - if (!(flags & MSG_PEEK)) - sk->urg_data = URG_READ; - memcpy_toiovec(msg->msg_iov, &c, 1); - if(msg->msg_name) - { - struct sockaddr_in *sin=(struct sockaddr_in *)msg->msg_name; - sin->sin_family=AF_INET; - sin->sin_addr.s_addr=sk->daddr; - sin->sin_port=sk->dummy_th.dest; - } - if(addr_len) - *addr_len=sizeof(struct sockaddr_in); - release_sock(sk); - return 1; - } - release_sock(sk); - - /* - * Fixed the recv(..., MSG_OOB) behaviour. BSD docs and - * the available implementations agree in this case: - * this call should never block, independent of the - * blocking state of the socket. - * Mike - */ - return -EAGAIN; -} - - /* * This routine copies from a sock struct into the user buffer. */ @@ -1637,6 +1647,8 @@ static int tcp_recvmsg(struct sock *sk, struct msghdr *msg, if (flags & MSG_PEEK) continue; skb->used = 1; + if (!skb->users) + tcp_eat_skb(sk, skb); continue; found_fin_ok: @@ -2001,13 +2013,7 @@ static int tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len) buff->end_seq = sk->write_seq; t1->ack = 0; t1->window = 2; - t1->res1=0; - t1->res2=0; - t1->rst = 0; - t1->urg = 0; - t1->psh = 0; t1->syn = 1; - t1->urg_ptr = 0; t1->doff = 6; /* use 512 or whatever user asked for */ @@ -2056,8 +2062,9 @@ static int tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len) ptr[1] = 4; ptr[2] = (sk->mtu) >> 8; ptr[3] = (sk->mtu) & 0xff; + buff->csum = csum_partial(ptr, 4, 0); tcp_send_check(t1, sk->saddr, sk->daddr, - sizeof(struct tcphdr) + 4, sk); + sizeof(struct tcphdr) + 4, buff); /* * This must go first otherwise a really quick response will get reset. diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 6e33c14d6771..8dbf27f22034 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -23,11 +23,98 @@ #include #include +/* + * Policy code extracted so its now seperate + */ + +/* + * Called each time to estimate the delayed ack timeout. This is + * how it should be done so a fast link isnt impacted by ack delay. + */ + +extern __inline__ void tcp_delack_estimator(struct sock *sk) +{ + /* + * Delayed ACK time estimator. + */ + + if (sk->lrcvtime == 0) + { + sk->lrcvtime = jiffies; + sk->ato = HZ/3; + } + else + { + int m; + + m = jiffies - sk->lrcvtime; + + sk->lrcvtime = jiffies; + + if (m <= 0) + m = 1; + + if (m > (sk->rtt >> 3)) + { + sk->ato = sk->rtt >> 3; + /* + * printk(KERN_DEBUG "ato: rtt %lu\n", sk->ato); + */ + } + else + { + sk->ato = (sk->ato >> 1) + m; + /* + * printk(KERN_DEBUG "ato: m %lu\n", sk->ato); + */ + } + } +} + +/* + * Called on frames that were known _not_ to have been + * retransmitted [see Karn/Partridge Proceedings SIGCOMM 87]. + * The algorithm is from the SIGCOMM 88 piece by Van Jacobson. + */ + +extern __inline__ void tcp_rtt_estimator(struct sock *sk, struct sk_buff *oskb) +{ + long m; + /* + * The following amusing code comes from Jacobson's + * article in SIGCOMM '88. Note that rtt and mdev + * are scaled versions of rtt and mean deviation. + * This is designed to be as fast as possible + * m stands for "measurement". + */ + + m = jiffies - oskb->when; /* RTT */ + if(m<=0) + m=1; /* IS THIS RIGHT FOR <0 ??? */ + m -= (sk->rtt >> 3); /* m is now error in rtt est */ + sk->rtt += m; /* rtt = 7/8 rtt + 1/8 new */ + if (m < 0) + m = -m; /* m is now abs(error) */ + m -= (sk->mdev >> 2); /* similar update on mdev */ + sk->mdev += m; /* mdev = 3/4 mdev + 1/4 new */ + + /* + * Now update timeout. Note that this removes any backoff. + */ + + sk->rto = ((sk->rtt >> 2) + sk->mdev) >> 1; + if (sk->rto > 120*HZ) + sk->rto = 120*HZ; + 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; +} + /* * Cached last hit socket */ -static volatile unsigned long th_cache_saddr,th_cache_daddr; +static volatile unsigned long th_cache_saddr, th_cache_daddr; static volatile unsigned short th_cache_dport, th_cache_sport; static volatile struct sock *th_cache_sk; @@ -37,8 +124,10 @@ void tcp_cache_zap(void) } /* - * Find the socket, using the last hit cache if applicable. + * Find the socket, using the last hit cache if applicable. The cache is not quite + * right... */ + static inline struct sock * get_tcp_sock(u32 saddr, u16 sport, u32 daddr, u16 dport) { struct sock * sk; @@ -61,6 +150,7 @@ static inline struct sock * get_tcp_sock(u32 saddr, u16 sport, u32 daddr, u16 dp /* * React to a out-of-window TCP sequence number in an incoming packet */ + static void bad_tcp_sequence(struct sock *sk, struct tcphdr *th, short len, struct options *opt, unsigned long saddr, struct device *dev) { @@ -79,8 +169,16 @@ static void bad_tcp_sequence(struct sock *sk, struct tcphdr *th, short len, tcp_send_reset(sk->saddr,sk->daddr,th,sk->prot,NULL,dev, sk->ip_tos,sk->ip_ttl); return; } - - /* Try to resync things. */ + + /* + * 4.3reno machines look for these kind of acks so they can do fast + * recovery. Three identical 'old' acks lets it know that one frame has + * been lost and should be resent. Because this is before the whole window + * of data has timed out it can take one lost frame per window without + * stalling. [See Jacobson RFC1323, Stevens TCP/IP illus vol2] + * + * We also should be spotting triple bad sequences. + */ tcp_send_ack(sk->sent_seq, sk->acked_seq, sk, th, saddr); return; } @@ -99,20 +197,29 @@ extern __inline__ int tcp_sequence(struct sock *sk, u32 seq, u32 end_seq) } /* - * When we get a reset we do this. + * When we get a reset we do this. This probably is a tcp_output routine + * really. */ static int tcp_reset(struct sock *sk, struct sk_buff *skb) { sk->zapped = 1; + /* + * We want the right error as BSD sees it (and indeed as we do). + */ sk->err = ECONNRESET; if (sk->state == TCP_SYN_SENT) sk->err = ECONNREFUSED; if (sk->state == TCP_CLOSE_WAIT) sk->err = EPIPE; -#ifdef TCP_DO_RFC1337 +#ifdef CONFIG_TCP_RFC1337 /* * Time wait assassination protection [RFC1337] + * + * This is a good idea, but causes more sockets to take time to close. + * + * Ian Heavens has since shown this is an inadequate fix for the protocol + * bug in question. */ if(sk->state!=TCP_TIME_WAIT) { @@ -228,8 +335,11 @@ static void tcp_conn_request(struct sock *sk, struct sk_buff *skb, } /* - * Make sure we can accept more. This will prevent a - * flurry of syns from eating up all our memory. + * Make sure we can accept more. This will prevent a + * flurry of syns from eating up all our memory. + * + * BSD does some funnies here and allows 3/2 times the + * set backlog as a fudge factor. Thats just too gross. */ if (sk->ack_backlog >= sk->max_ack_backlog) @@ -259,21 +369,24 @@ static void tcp_conn_request(struct sock *sk, struct sk_buff *skb, memcpy(newsk, sk, sizeof(*newsk)); newsk->opt = NULL; newsk->ip_route_cache = NULL; - if (opt && opt->optlen) { - sk->opt = (struct options*)kmalloc(sizeof(struct options)+opt->optlen, GFP_ATOMIC); - if (!sk->opt) { - kfree_s(newsk, sizeof(struct sock)); - tcp_statistics.TcpAttemptFails++; - kfree_skb(skb, FREE_READ); - return; - } - if (ip_options_echo(sk->opt, opt, daddr, saddr, skb)) { - kfree_s(sk->opt, sizeof(struct options)+opt->optlen); - kfree_s(newsk, sizeof(struct sock)); - tcp_statistics.TcpAttemptFails++; - kfree_skb(skb, FREE_READ); - return; - } + if (opt && opt->optlen) + { + sk->opt = (struct options*)kmalloc(sizeof(struct options)+opt->optlen, GFP_ATOMIC); + if (!sk->opt) + { + kfree_s(newsk, sizeof(struct sock)); + tcp_statistics.TcpAttemptFails++; + kfree_skb(skb, FREE_READ); + return; + } + if (ip_options_echo(sk->opt, opt, daddr, saddr, skb)) + { + kfree_s(sk->opt, sizeof(struct options)+opt->optlen); + kfree_s(newsk, sizeof(struct sock)); + tcp_statistics.TcpAttemptFails++; + kfree_skb(skb, FREE_READ); + return; + } } skb_queue_head_init(&newsk->write_queue); skb_queue_head_init(&newsk->receive_queue); @@ -336,15 +449,6 @@ static void tcp_conn_request(struct sock *sk, struct sk_buff *skb, newsk->rcv_saddr = daddr; put_sock(newsk->num,newsk); - newsk->dummy_th.res1 = 0; - newsk->dummy_th.doff = 6; - newsk->dummy_th.fin = 0; - newsk->dummy_th.syn = 0; - newsk->dummy_th.rst = 0; - newsk->dummy_th.psh = 0; - newsk->dummy_th.ack = 0; - newsk->dummy_th.urg = 0; - newsk->dummy_th.res2 = 0; newsk->acked_seq = skb->seq + 1; newsk->copied_seq = skb->seq + 1; newsk->socket = NULL; @@ -409,14 +513,83 @@ static void tcp_conn_request(struct sock *sk, struct sk_buff *skb, tcp_send_synack(newsk, sk, skb); } + +/* + * Handle a TCP window that shrunk on us. It shouldn't happen, + * but.. + * + * We may need to move packets from the send queue + * to the write queue, if the window has been shrunk on us. + * The RFC says you are not allowed to shrink your window + * like this, but if the other end does, you must be able + * to deal with it. + */ +void tcp_window_shrunk(struct sock * sk, u32 window_seq) +{ + struct sk_buff *skb; + struct sk_buff *skb2; + struct sk_buff *wskb = NULL; + + skb2 = sk->send_head; + sk->send_head = NULL; + sk->send_tail = NULL; + + /* + * This is an artifact of a flawed concept. We want one + * queue and a smarter send routine when we send all. + */ + cli(); + while (skb2 != NULL) + { + skb = skb2; + skb2 = skb->link3; + skb->link3 = NULL; + if (after(skb->end_seq, window_seq)) + { + if (sk->packets_out > 0) + sk->packets_out--; + /* We may need to remove this from the dev send list. */ + if (skb->next != NULL) + { + skb_unlink(skb); + } + /* Now add it to the write_queue. */ + if (wskb == NULL) + skb_queue_head(&sk->write_queue,skb); + else + skb_append(wskb,skb); + wskb = skb; + } + else + { + if (sk->send_head == NULL) + { + sk->send_head = skb; + sk->send_tail = skb; + } + else + { + sk->send_tail->link3 = skb; + sk->send_tail = skb; + } + skb->link3 = NULL; + } + } + sti(); +} + + /* * This routine deals with incoming acks, but not outgoing ones. + * + * This routine is totally _WRONG_. The list structuring is wrong, + * the algorithm is wrong, the code is wrong. */ static int tcp_ack(struct sock *sk, struct tcphdr *th, u32 ack, int len) { int flag = 0; - unsigned window; + u32 window_seq; /* * 1 - there was data in packet as well as ack or new data is sent or @@ -428,30 +601,12 @@ static int tcp_ack(struct sock *sk, struct tcphdr *th, u32 ack, int len) if(sk->zapped) return(1); /* Dead, cant ack any more so why bother */ - /* - * Have we discovered a larger window - */ - - window = ntohs(th->window); - - if (window > sk->max_window) - { - sk->max_window = window; -#ifdef CONFIG_INET_PCTCP - /* Hack because we don't send partial packets to non SWS - handling hosts */ - sk->mss = min(window>>1, sk->mtu); -#else - sk->mss = min(window, sk->mtu); -#endif - } - /* * We have dropped back to keepalive timeouts. Thus we have * no retransmits pending. */ - if (sk->retransmits && sk->ip_xmit_timeout == TIME_KEEPOPEN) + if (sk->ip_xmit_timeout == TIME_KEEPOPEN) sk->retransmits = 0; /* @@ -460,30 +615,7 @@ static int tcp_ack(struct sock *sk, struct tcphdr *th, u32 ack, int len) */ if (after(ack, sk->sent_seq) || before(ack, sk->rcv_ack_seq)) - { - if(sk->debug) - printk("Ack ignored %u %u\n",ack,sk->sent_seq); - - /* - * Keepalive processing. - */ - - if (after(ack, sk->sent_seq)) - { - return(0); - } - - /* - * Restart the keepalive timer. - */ - - if (sk->keepopen) - { - if(sk->ip_xmit_timeout==TIME_KEEPOPEN) - tcp_reset_xmit_timer(sk, TIME_KEEPOPEN, TCP_TIMEOUT_LEN); - } - return(1); - } + goto uninteresting_ack; /* * If there is data set flag 1 @@ -493,78 +625,38 @@ static int tcp_ack(struct sock *sk, struct tcphdr *th, u32 ack, int len) flag |= 1; /* - * See if our window has been shrunk. + * Have we discovered a larger window */ - - if (after(sk->window_seq, ack+window)) + window_seq = ntohs(th->window); + if (window_seq > sk->max_window) { - /* - * We may need to move packets from the send queue - * to the write queue, if the window has been shrunk on us. - * The RFC says you are not allowed to shrink your window - * like this, but if the other end does, you must be able - * to deal with it. - */ - struct sk_buff *skb; - struct sk_buff *skb2; - struct sk_buff *wskb = NULL; - - skb2 = sk->send_head; - sk->send_head = NULL; - sk->send_tail = NULL; - - /* - * This is an artifact of a flawed concept. We want one - * queue and a smarter send routine when we send all. - */ - - flag |= 4; /* Window changed */ - - sk->window_seq = ack + window; - cli(); - while (skb2 != NULL) - { - skb = skb2; - skb2 = skb->link3; - skb->link3 = NULL; - if (after(skb->end_seq, sk->window_seq)) - { - if (sk->packets_out > 0) - sk->packets_out--; - /* We may need to remove this from the dev send list. */ - if (skb->next != NULL) - { - skb_unlink(skb); - } - /* Now add it to the write_queue. */ - if (wskb == NULL) - skb_queue_head(&sk->write_queue,skb); - else - skb_append(wskb,skb); - wskb = skb; - } - else - { - if (sk->send_head == NULL) - { - sk->send_head = skb; - sk->send_tail = skb; - } - else - { - sk->send_tail->link3 = skb; - sk->send_tail = skb; - } - skb->link3 = NULL; - } - } - sti(); + sk->max_window = window_seq; +#ifdef CONFIG_INET_PCTCP + /* Hack because we don't send partial packets to non SWS + handling hosts */ + sk->mss = min(window_seq>>1, sk->mtu); +#else + sk->mss = min(window_seq, sk->mtu); +#endif } + window_seq += ack; /* - * Pipe has emptied + * See if our window has been shrunk. */ - + if (after(sk->window_seq, window_seq)) { + flag |= 4; + tcp_window_shrunk(sk, window_seq); + } + + /* + * Update the right hand window edge of the host + */ + sk->window_seq = window_seq; + + /* + * Pipe has emptied + */ if (sk->send_tail == NULL || sk->send_head == NULL) { sk->send_head = NULL; @@ -572,12 +664,6 @@ static int tcp_ack(struct sock *sk, struct tcphdr *th, u32 ack, int len) sk->packets_out= 0; } - /* - * Update the right hand window edge of the host - */ - - sk->window_seq = ack + window; - /* * We don't want too many packets out there. */ @@ -585,6 +671,7 @@ static int tcp_ack(struct sock *sk, struct tcphdr *th, u32 ack, int len) if (sk->ip_xmit_timeout == TIME_WRITE && sk->cong_window < 2048 && after(ack, sk->rcv_ack_seq)) { + /* * This is Jacobson's slow start and congestion avoidance. * SIGCOMM '88, p. 328. Because we keep cong_window in integral @@ -722,38 +809,7 @@ static int tcp_ack(struct sock *sk, struct tcphdr *th, u32 ack, int len) oskb = sk->send_head; if (!(flag&2)) /* Not retransmitting */ - { - long m; - - /* - * The following amusing code comes from Jacobson's - * article in SIGCOMM '88. Note that rtt and mdev - * are scaled versions of rtt and mean deviation. - * This is designed to be as fast as possible - * m stands for "measurement". - */ - - m = jiffies - oskb->when; /* RTT */ - if(m<=0) - m=1; /* IS THIS RIGHT FOR <0 ??? */ - m -= (sk->rtt >> 3); /* m is now error in rtt est */ - sk->rtt += m; /* rtt = 7/8 rtt + 1/8 new */ - if (m < 0) - m = -m; /* m is now abs(error) */ - m -= (sk->mdev >> 2); /* similar update on mdev */ - sk->mdev += m; /* mdev = 3/4 mdev + 1/4 new */ - - /* - * Now update timeout. Note that this removes any backoff. - */ - - sk->rto = ((sk->rtt >> 2) + sk->mdev) >> 1; - if (sk->rto > 120*HZ) - sk->rto = 120*HZ; - 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; - } + tcp_rtt_estimator(sk,oskb); flag |= (2|4); /* 2 is really more like 'don't adjust the rtt In this case as we just set it up */ cli(); @@ -1000,7 +1056,31 @@ static int tcp_ack(struct sock *sk, struct tcphdr *th, u32 ack, int len) } } - return(1); + return 1; + +uninteresting_ack: + if(sk->debug) + printk("Ack ignored %u %u\n",ack,sk->sent_seq); + + /* + * Keepalive processing. + */ + + if (after(ack, sk->sent_seq)) + { + return 0; + } + + /* + * Restart the keepalive timer. + */ + + if (sk->keepopen) + { + if(sk->ip_xmit_timeout==TIME_KEEPOPEN) + tcp_reset_xmit_timer(sk, TIME_KEEPOPEN, TCP_TIMEOUT_LEN); + } + return 1; } @@ -1515,12 +1595,14 @@ int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt, /* * Pull up the IP header. */ + skb_pull(skb, skb->h.raw-skb->data); /* * Try to use the device checksum if provided. */ - switch (skb->ip_summed) { + switch (skb->ip_summed) + { case CHECKSUM_NONE: skb->csum = csum_partial((char *)th, len, 0); case CHECKSUM_HW: @@ -1539,7 +1621,7 @@ int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt, skb->acked = 0; skb->used = 0; - skb->free = 0; + skb->free = 1; skb->saddr = daddr; skb->daddr = saddr; @@ -1580,7 +1662,11 @@ int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt, skb->sk=sk; sk->rmem_alloc += skb->truesize; - + + /* + * We should now do header prediction. + */ + /* * This basically follows the flow suggested by RFC793, with the corrections in RFC1122. We * don't implement precedence and we process URG incorrectly (deliberately so) for BSD bug @@ -1627,13 +1713,19 @@ int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt, * and Solaris 2.1 gives you a protocol error. For now we just ignore * it, that fits the spec precisely and avoids incompatibilities. It * would be nice in future to drop through and process the data. + * + * Now TTCP is starting to use we ought to queue this data. */ release_sock(sk); return 0; } - /* retransmitted SYN? */ + /* + * Retransmitted SYN for our socket. This is uninteresting. If sk->state==TCP_LISTEN + * then its a new connection + */ + if (sk->state == TCP_SYN_RECV && th->syn && skb->seq+1 == sk->acked_seq) { kfree_skb(skb, FREE_READ); @@ -1643,7 +1735,8 @@ int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt, /* * SYN sent means we have to look for a suitable ack and either reset - * for bad matches or go to connected + * for bad matches or go to connected. The SYN_SENT case is unusual and should + * not be in line code. [AC] */ if(sk->state==TCP_SYN_SENT) @@ -1796,43 +1889,8 @@ int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt, return tcp_reset(sk,skb); } - - /* - * Delayed ACK time estimator. - */ + tcp_delack_estimator(sk); - if (sk->lrcvtime == 0) - { - sk->lrcvtime = jiffies; - sk->ato = HZ/3; - } - else - { - int m; - - m = jiffies - sk->lrcvtime; - - sk->lrcvtime = jiffies; - - if (m <= 0) - m = 1; - - if (m > (sk->rtt >> 3)) - { - sk->ato = sk->rtt >> 3; - /* - * printk(KERN_DEBUG "ato: rtt %lu\n", sk->ato); - */ - } - else - { - sk->ato = (sk->ato >> 1) + m; - /* - * printk(KERN_DEBUG "ato: m %lu\n", sk->ato); - */ - } - } - /* * Process the ACK */ @@ -1880,11 +1938,7 @@ rfc_step6: /* I'll clean this up later */ */ if(tcp_data(skb,sk, saddr, len)) - { kfree_skb(skb, FREE_READ); - release_sock(sk); - return 0; - } /* * And done diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 85704eaf36b2..c8bf6ea6ddb1 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -97,13 +97,6 @@ void tcp_send_skb(struct sock *sk, struct sk_buff *skb) } skb_queue_tail(&sk->write_queue, skb); - /* - * If we don't fit we have to start the zero window - * probes. This is broken - we really need to do a partial - * send _first_ (This is what causes the Cisco and PC/TCP - * grief). - */ - if (before(sk->window_seq, sk->write_queue.next->end_seq) && sk->send_head == NULL && sk->ack_backlog == 0) tcp_reset_xmit_timer(sk, TIME_PROBE0, sk->rto); @@ -117,7 +110,7 @@ void tcp_send_skb(struct sock *sk, struct sk_buff *skb) th->ack_seq = htonl(sk->acked_seq); th->window = htons(tcp_select_window(sk)); - tcp_send_check(th, sk->saddr, sk->daddr, size, sk); + tcp_send_check(th, sk->saddr, sk->daddr, size, skb); sk->sent_seq = sk->write_seq; @@ -288,7 +281,7 @@ void tcp_write_xmit(struct sock *sk) th->ack_seq = htonl(sk->acked_seq); th->window = htons(tcp_select_window(sk)); - tcp_send_check(th, sk->saddr, sk->daddr, size, sk); + tcp_send_check(th, sk->saddr, sk->daddr, size, skb); sk->sent_seq = skb->end_seq; @@ -344,9 +337,9 @@ void tcp_do_retransmit(struct sock *sk, int all) /* anyway, so we don't need all the fuss to prepare */ /* the buffer in this case. */ /* (the skb_pull() changes skb->data while we may */ - /* actually try to send the data. Ough. A side */ + /* actually try to send the data. Ouch. A side */ /* effect is that we'll send some unnecessary data, */ - /* but the alternative is desastrous... */ + /* but the alternative is disasterous... */ if (skb_device_locked(skb)) break; @@ -439,7 +432,7 @@ void tcp_do_retransmit(struct sock *sk, int all) sk->ack_backlog = 0; sk->bytes_rcv = 0; th->window = ntohs(tcp_select_window(sk)); - tcp_send_check(th, sk->saddr, sk->daddr, size, sk); + tcp_send_check(th, sk->saddr, sk->daddr, size, skb); /* * If the interface is (still) up and running, kick it. @@ -523,6 +516,7 @@ void tcp_send_reset(unsigned long saddr, unsigned long daddr, struct tcphdr *th, buff->sk = NULL; buff->dev = dev; buff->localroute = 0; + buff->csum = 0; /* * Put in the IP header and routing stuff. @@ -546,31 +540,26 @@ void tcp_send_reset(unsigned long saddr, unsigned long daddr, struct tcphdr *th, t1->dest = th->source; t1->source = th->dest; - t1->rst = 1; - t1->window = 0; + t1->syn = 0; + t1->fin = 0; + t1->urg = 0; + t1->rst = 1; + t1->psh = 0; if(th->ack) { t1->ack = 0; t1->seq = th->ack_seq; - t1->ack_seq = 0; } else { - t1->ack = 1; if(!th->syn) t1->ack_seq = th->seq; else t1->ack_seq = htonl(ntohl(th->seq)+1); - t1->seq = 0; } - t1->syn = 0; - t1->urg = 0; - t1->fin = 0; - t1->psh = 0; - t1->doff = sizeof(*t1)/4; - tcp_send_check(t1, saddr, daddr, sizeof(*t1), NULL); + tcp_send_check(t1, saddr, daddr, sizeof(*t1), buff); prot->queue_xmit(NULL, ndev, buff, 1); tcp_statistics.TcpOutSegs++; } @@ -606,6 +595,7 @@ void tcp_send_fin(struct sock *sk) buff->sk = sk; buff->localroute = sk->localroute; + buff->csum = 0; /* * Put in the IP header and routing stuff. @@ -645,13 +635,10 @@ void tcp_send_fin(struct sock *sk) sk->write_seq++; buff->end_seq = sk->write_seq; t1->seq = htonl(buff->seq); - t1->ack = 1; t1->ack_seq = htonl(sk->acked_seq); t1->window = htons(sk->window=tcp_select_window(sk)); t1->fin = 1; - t1->rst = 0; - t1->doff = sizeof(*t1)/4; - tcp_send_check(t1, sk->saddr, sk->daddr, sizeof(*t1), sk); + tcp_send_check(t1, sk->saddr, sk->daddr, sizeof(*t1), buff); /* * If there is data in the write queue, the fin must be appended to @@ -737,15 +724,13 @@ void tcp_send_synack(struct sock * newsk, struct sock * sk, struct sk_buff * skb t1->dest = skb->h.th->source; t1->source = newsk->dummy_th.source; t1->seq = ntohl(buff->seq); - t1->ack = 1; newsk->sent_seq = newsk->write_seq; t1->window = ntohs(tcp_select_window(newsk)); - t1->res1 = 0; - t1->res2 = 0; - t1->rst = 0; + t1->syn = 1; + t1->ack = 1; t1->urg = 0; + t1->rst = 0; t1->psh = 0; - t1->syn = 1; t1->ack_seq = htonl(newsk->acked_seq); t1->doff = sizeof(*t1)/4+1; ptr = skb_put(buff,4); @@ -753,8 +738,8 @@ void tcp_send_synack(struct sock * newsk, struct sock * sk, struct sk_buff * skb ptr[1] = 4; ptr[2] = ((newsk->mtu) >> 8) & 0xff; ptr[3] =(newsk->mtu) & 0xff; - - tcp_send_check(t1, newsk->saddr, newsk->daddr, sizeof(*t1)+4, newsk); + buff->csum = csum_partial(ptr, 4, 0); + tcp_send_check(t1, newsk->saddr, newsk->daddr, sizeof(*t1)+4, buff); newsk->prot->queue_xmit(newsk, ndev, buff, 0); tcp_reset_xmit_timer(newsk, TIME_WRITE , TCP_TIMEOUT_INIT); skb->sk = newsk; @@ -817,6 +802,7 @@ void tcp_send_ack(u32 sequence, u32 ack, buff->sk = sk; buff->localroute = sk->localroute; + buff->csum = 0; /* * Put in the IP header and routing stuff. @@ -832,7 +818,7 @@ void tcp_send_ack(u32 sequence, u32 ack, } t1 =(struct tcphdr *)skb_put(buff,sizeof(struct tcphdr)); - memcpy(t1, th, sizeof(*t1)); + memcpy(t1, &sk->dummy_th, sizeof(*t1)); /* * Swap the send and the receive. @@ -841,16 +827,8 @@ void tcp_send_ack(u32 sequence, u32 ack, t1->dest = th->source; t1->source = th->dest; t1->seq = ntohl(sequence); - t1->ack = 1; sk->window = tcp_select_window(sk); t1->window = ntohs(sk->window); - t1->res1 = 0; - t1->res2 = 0; - t1->rst = 0; - t1->urg = 0; - t1->syn = 0; - t1->psh = 0; - t1->fin = 0; /* * If we have nothing queued for transmit and the transmit timer @@ -876,8 +854,7 @@ void tcp_send_ack(u32 sequence, u32 ack, */ t1->ack_seq = htonl(ack); - t1->doff = sizeof(*t1)/4; - tcp_send_check(t1, sk->saddr, daddr, sizeof(*t1), sk); + tcp_send_check(t1, sk->saddr, daddr, sizeof(*t1), buff); if (sk->debug) printk("\rtcp_ack: seq %x ack %x\n", sequence, ack); sk->prot->queue_xmit(sk, dev, buff, 1); @@ -930,7 +907,6 @@ void tcp_write_wakeup(struct sock *sk) #if 0 unsigned long ow_size; #endif - void * tcp_data_start; /* * How many bytes can we send ? @@ -985,9 +961,9 @@ void tcp_write_wakeup(struct sock *sk) buff->dev = dev; - nth = (struct tcphdr *) skb_put(buff,th->doff*4); + nth = (struct tcphdr *) skb_put(buff,sizeof(*th)); - memcpy(nth, th, th->doff * 4); + memcpy(nth, th, sizeof(*th)); /* * Correct the new header @@ -999,16 +975,11 @@ void tcp_write_wakeup(struct sock *sk) nth->check = 0; /* - * Find the first data byte. - */ - - tcp_data_start = (char *) th + (th->doff << 2); - - /* - * Add it to our new buffer + * Copy TCP options and data start to our new buffer */ - memcpy(skb_put(buff,win_size), tcp_data_start, win_size); + buff->csum = csum_partial_copy((void *)(th + 1), skb_put(buff,win_size), + win_size + th->doff*4 - sizeof(*th), 0); /* * Remember our right edge sequence number. @@ -1024,7 +995,7 @@ void tcp_write_wakeup(struct sock *sk) */ tcp_send_check(nth, sk->saddr, sk->daddr, - nth->doff * 4 + win_size , sk); + nth->doff * 4 + win_size , buff); } else { @@ -1035,6 +1006,7 @@ void tcp_write_wakeup(struct sock *sk) buff->free = 1; buff->sk = sk; buff->localroute = sk->localroute; + buff->csum = 0; /* * Put in the IP header and routing stuff. @@ -1057,18 +1029,10 @@ void tcp_write_wakeup(struct sock *sk) */ t1->seq = htonl(sk->sent_seq-1); - t1->ack = 1; - t1->res1= 0; - t1->res2= 0; - t1->rst = 0; - t1->urg = 0; - t1->psh = 0; - t1->fin = 0; /* We are sending a 'previous' sequence, and 0 bytes of data - thus no FIN bit */ - t1->syn = 0; +/* t1->fin = 0; -- We are sending a 'previous' sequence, and 0 bytes of data - thus no FIN bit */ t1->ack_seq = htonl(sk->acked_seq); t1->window = htons(tcp_select_window(sk)); - t1->doff = sizeof(*t1)/4; - tcp_send_check(t1, sk->saddr, sk->daddr, sizeof(*t1), sk); + tcp_send_check(t1, sk->saddr, sk->daddr, sizeof(*t1), buff); } diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 8f5bdebbc207..c23b3782093f 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -40,6 +40,8 @@ void tcp_reset_xmit_timer(struct sock *sk, int why, unsigned long when) } /* + * POLICY: + * * This is the normal code called for timeouts. It does the retransmission * and then does backoff. tcp_do_retransmit is separated out because * tcp_ack needs to send stuff from the retransmit queue without @@ -76,6 +78,9 @@ static void tcp_retransmit_time(struct sock *sk, int all) } /* + * POLICY: + * Congestion control. + * * A timer event has trigger a tcp retransmit timeout. The * socket xmit queue is ready and set up to send. Because * the ack receive code keeps the queue straight we do @@ -101,7 +106,7 @@ void tcp_retransmit(struct sock *sk, int all) } /* - * A write timeout has occurred. Process the after effects. + * A write timeout has occurred. Process the after effects. BROKEN (badly) */ static int tcp_write_timeout(struct sock *sk) diff --git a/net/socket.c b/net/socket.c index 61ab750e992e..367537a06243 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1089,19 +1089,25 @@ asmlinkage int sys_sendmsg(int fd, struct msghdr *msg, unsigned int flags) if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK); + if(sock->ops->sendmsg==NULL) + return -EOPNOTSUPP; + + err=verify_area(VERIFY_READ, msg,sizeof(struct msghdr)); if(err) return err; + memcpy_fromfs(&msg_sys,msg,sizeof(struct msghdr)); + + /* do not move before msg_sys is valid */ if(msg_sys.msg_iovlen>MAX_IOVEC) return -EINVAL; + err=verify_iovec(&msg_sys,iov,address, VERIFY_READ); if(err<0) return err; total_len=err; - - if(sock->ops->sendmsg==NULL) - return -EOPNOTSUPP; + return sock->ops->sendmsg(sock, &msg_sys, total_len, (file->f_flags&O_NONBLOCK), flags); } diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 278693ca4fe6..3ba44b32f6ad 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -677,6 +677,9 @@ static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_ return 0; } +/* if msg->accrights != NULL, we have fds to pass. + * Current implementation passes at most one fd. + */ static int unix_sendmsg(struct socket *sock, struct msghdr *msg, int len, int nonblock, int flags) { unix_socket *sk=sock->data; @@ -686,6 +689,8 @@ static int unix_sendmsg(struct socket *sock, struct msghdr *msg, int len, int no struct sk_buff *skb; int limit=0; int sent=0; + /* for passing fd, NULL indicates no fd */ + struct file *filp; if(sk->err) return sock_error(sk); @@ -693,7 +698,7 @@ static int unix_sendmsg(struct socket *sock, struct msghdr *msg, int len, int no if(flags&MSG_OOB) return -EOPNOTSUPP; - if(flags || msg->msg_accrights) /* For now */ + if(flags) /* For now */ return -EINVAL; if(sunaddr!=NULL) @@ -706,6 +711,7 @@ static int unix_sendmsg(struct socket *sock, struct msghdr *msg, int len, int no return -EOPNOTSUPP; } } + if(sunaddr==NULL) { if(sk->protinfo.af_unix.other==NULL) @@ -713,6 +719,26 @@ static int unix_sendmsg(struct socket *sock, struct msghdr *msg, int len, int no } + /* see if we want to access rights (fd) -- at the moment, + * we can pass none or 1 fd + */ + filp = NULL; + if(msg->msg_accrights) { + /* then accrightslen is meaningful */ + if(msg->msg_accrightslen == sizeof(int)) { + int fd; + + fd = get_user_long(msg->msg_accrights); + filp = file_from_fd(fd); + if(!filp) + return -EBADF; + } else if(msg->msg_accrightslen != 0) { + /* if we have accrights, we fail here */ + return -EINVAL; + } + } + + /* invariant -- flip points to a file to pass or NULL */ while(sent < len) { /* @@ -792,8 +818,16 @@ static int unix_sendmsg(struct socket *sock, struct msghdr *msg, int len, int no return err; } } + /* at this point, we want to add an fd if we have one */ + skb->h.filp = filp; + if (filp) { + filp->f_count++; + } + skb_queue_tail(&other->receive_queue, skb); sti(); + /* if we sent an fd, only do it once */ + filp = NULL; other->data_ready(other,size); sent+=size; } @@ -815,6 +849,36 @@ static void unix_data_wait(unix_socket * sk) sti(); } + +/* + * return 0 if we can stick the fd, negative errno if we can't + */ +static int stick_fd(struct file *filp, int *uaddr, int size) +{ + int slot; + int upper_bound; + + if (!uaddr || size < sizeof(int)) + return -EINVAL; + + upper_bound = current->rlim[RLIMIT_NOFILE].rlim_cur; + + if (upper_bound > NR_OPEN) + upper_bound = NR_OPEN; + + for (slot = 0; slot < upper_bound; slot++) { + if (current->files->fd[slot]) + continue; + /* have an fd */ + current->files->fd[slot] = filp; + FD_CLR(slot, ¤t->files->close_on_exec); + /* need verify area here? */ + put_user_long(slot, uaddr); + return 0; + } + return -EMFILE; +} + static int unix_recvmsg(struct socket *sock, struct msghdr *msg, int size, int noblock, int flags, int *addr_len) { unix_socket *sk=sock->data; @@ -826,7 +890,8 @@ static int unix_recvmsg(struct socket *sock, struct msghdr *msg, int size, int n int num; struct iovec *iov=msg->msg_iov; int ct=msg->msg_iovlen; - + struct file *filp; + if(flags&MSG_OOB) return -EOPNOTSUPP; @@ -879,8 +944,16 @@ static int unix_recvmsg(struct socket *sock, struct msghdr *msg, int size, int n if(addr_len) *addr_len=sizeof(short); } + num=min(skb->len,size-copied); memcpy_tofs(sp, skb->data, num); + + if ((filp = skb->h.filp) != NULL) { + skb->h.filp = NULL; + if (stick_fd(filp, msg->msg_accrights, msg->msg_accrightslen) < 0) + close_fp(filp); + } + copied+=num; done+=num; sp+=num; diff --git a/scripts/Configure b/scripts/Configure index c3ed3b8bc157..5329a6e03880 100644 --- a/scripts/Configure +++ b/scripts/Configure @@ -25,6 +25,8 @@ # 281295 Paul Gortmaker - make tri_state functions collapse to boolean # if module support is not enabled. # +# 010296 Aaron Ucko (ucko@vax1.rockhurst.edu) - fix int and hex to accept +# arbitrary ranges # # Make sure we're really running bash. @@ -64,15 +66,15 @@ function help () { var=$(echo "$1"|sed 's/[][\/.^$*]/\\&/g') #now pick out the right help text: text=$(sed -n "/^$var[ ]*\$/,\${ - /^$var[ ]*\$/b - /^#.*/b;/^[ ]*\$/q - p - }" Documentation/Configure.help) + /^$var[ ]*\$/b + /^#.*/b;/^[ ]*\$/q + p + }" Documentation/Configure.help) if [ -z "$text" ] then - echo; echo " Sorry, no help available for this option yet.";echo + echo; echo " Sorry, no help available for this option yet.";echo else - (echo; echo "$text"; echo) | more + (echo; echo "$text"; echo) | more fi else echo; @@ -116,21 +118,21 @@ function comment () { # define_bool define value # function define_bool () { - case "$2" in - "y") + case "$2" in + "y") echo "$1=y" >>$CONFIG echo "#define $1 1" >>$CONFIG_H ;; - "m") + "m") echo "$1=m" >>$CONFIG echo "#undef $1" >>$CONFIG_H ;; - "n") + "n") echo "# $1 is not set" >>$CONFIG echo "#undef $1" >>$CONFIG_H - ;; + ;; esac eval "$1=$2" } @@ -142,24 +144,24 @@ function define_bool () { # function bool () { def=$(eval echo "\${$2:-'n'}") - case "$def" in - "y" | "m") defprompt="Y/n/?" - def="y" - ;; - "n") defprompt="N/y/?" - ;; - esac - while :; do - readln "$1 ($2) [$defprompt] " "$def" - case "$ans" in - [yY] | [yY]es ) define_bool "$2" "y" - break;; - [nN] | [nN]o ) define_bool "$2" "n" - break;; - * ) help "$2" - ;; - esac - done + case "$def" in + "y" | "m") defprompt="Y/n/?" + def="y" + ;; + "n") defprompt="N/y/?" + ;; + esac + while :; do + readln "$1 ($2) [$defprompt] " "$def" + case "$ans" in + [yY] | [yY]es ) define_bool "$2" "y" + break;; + [nN] | [nN]o ) define_bool "$2" "n" + break;; + * ) help "$2" + ;; + esac + done } # @@ -168,32 +170,32 @@ function bool () { # tristate question define # function tristate () { - if [ "$CONFIG_MODULES" != "y" ]; then - bool "$1" "$2" - else + if [ "$CONFIG_MODULES" != "y" ]; then + bool "$1" "$2" + else def=$(eval echo "\${$2:-'n'}") - case "$def" in - "y") defprompt="Y/m/n/?" - ;; - "m") defprompt="M/n/y/?" - ;; - "n") defprompt="N/y/m/?" - ;; - esac - while :; do - readln "$1 ($2) [$defprompt] " "$def" - case "$ans" in - [yY] | [yY]es ) define_bool "$2" "y" - break ;; - [nN] | [nN]o ) define_bool "$2" "n" - break ;; - [mM] ) define_bool "$2" "m" - break ;; + case "$def" in + "y") defprompt="Y/m/n/?" + ;; + "m") defprompt="M/n/y/?" + ;; + "n") defprompt="N/y/m/?" + ;; + esac + while :; do + readln "$1 ($2) [$defprompt] " "$def" + case "$ans" in + [yY] | [yY]es ) define_bool "$2" "y" + break ;; + [nN] | [nN]o ) define_bool "$2" "n" + break ;; + [mM] ) define_bool "$2" "m" + break ;; * ) help "$2" - ;; - esac - done - fi + ;; + esac + done + fi } # @@ -208,37 +210,39 @@ function tristate () { # function dep_tristate () { def=$(eval echo "\${$2:-'n'}") - if [ "$3" != "m" ]; then + if [ "$3" = "n" ]; then + define_bool "$2" "n" + elif [ "$3" = "y" ]; then tristate "$1" "$2" else - if [ "$CONFIG_MODULES" = "y" ]; then - case "$def" in - "y" | "m") defprompt="M/n/?" + if [ "$CONFIG_MODULES" = "y" ]; then + case "$def" in + "y" | "m") defprompt="M/n/?" def="m" - ;; - "n") defprompt="N/m/?" - ;; - esac - while :; do - readln "$1 ($2) [$defprompt] " "$def" - case "$ans" in - [nN] | [nN]o ) define_bool "$2" "n" - break ;; - [mM] ) define_bool "$2" "m" - break ;; - [yY] | [yY]es ) echo + ;; + "n") defprompt="N/m/?" + ;; + esac + while :; do + readln "$1 ($2) [$defprompt] " "$def" + case "$ans" in + [nN] | [nN]o ) define_bool "$2" "n" + break ;; + [mM] ) define_bool "$2" "m" + break ;; + [yY] | [yY]es ) echo echo " This answer is not allowed, because it is not consistent with" echo " your other choices." echo " This driver depends on another one which you chose to compile" echo " as a module. This means that you can either compile this one" echo " as a module as well (with M) or leave it out altogether (N)." - echo - ;; - * ) help "$2" - ;; - esac - done - fi + echo + ;; + * ) help "$2" + ;; + esac + done + fi fi } @@ -260,17 +264,15 @@ function define_int () { # function int () { def=$(eval echo "\${$2:-$3}") - while :; do - readln "$1 ($2) [$def] " "$def" - case "$ans" in - -1 | [1-9] | [1-9][0-9] |\ - [1-9][0-9][0-9] | [1-9][0-9][0-9][0-9] | [1-9][0-9][0-9][0-9][0-9]) - define_int "$2" "$ans" - break;; - * ) help "$2" - ;; - esac - done + while :; do + readln "$1 ($2) [$def] " "$def" + if expr "$ans" : '0$\|-?[1-9][0-9]*$' > /dev/null; then + define_int "$2" "$ans" + break + else + help "$2" + fi + done } # # define_hex sets the value of a hexadecimal argument @@ -291,20 +293,16 @@ function define_hex () { function hex () { def=$(eval echo "\${$2:-$3}") def=${def#*[x,X]} - while :; do - readln "$1 ($2) [$def] " "$def" - ans=${ans#*[x,X]} - case "$ans" in - [0-9,a-f,A-F] |\ - [0-9,a-f,A-F][0-9,a-f,A-F] |\ - [0-9,a-f,A-F][0-9,a-f,A-F][0-9,a-f,A-F] |\ - [0-9,a-f,A-F][0-9,a-f,A-F][0-9,a-f,A-F][0-9,a-f,A-F])\ - define_hex "$2" "$ans" - break;; - * ) help "$2" - ;; - esac - done + while :; do + readln "$1 ($2) [$def] " "$def" + ans=${ans#*[x,X]} + if expr "$ans" : '[0-9a-fA-F]+$' > /dev/null; then + define_hex "$2" "$ans" + break + else + help "$2" + fi + done } # @@ -329,7 +327,7 @@ function choice () { # determine default answer: names="" set -- $choices - firstvar=$2 + firstvar=$2 while [ -n "$2" ]; do if [ -n "$names" ]; then names="$names, $1" @@ -344,7 +342,7 @@ function choice () { val="" while [ -z "$val" ]; do - ambg=n + ambg=n readln "$question ($names) [$def] " "$def" ans=$(echo $ans | tr a-z A-Z) set -- $choices @@ -359,19 +357,19 @@ function choice () { if [ -n "$val" ]; then echo;echo \ " Sorry, \"$ans\" is ambiguous; please enter a longer string." - echo + echo val="" - ambg=y + ambg=y break else val="$2" fi;; esac shift; shift - done - if [ "$val" = "" -a "$ambg" = "n" ]; then - help "$firstvar" - fi + done + if [ "$val" = "" -a "$ambg" = "n" ]; then + help "$firstvar" + fi done set -- $choices while [ -n "$2" ]; do -- 2.39.5