diff -u --recursive --new-file v2.1.105/linux/CREDITS linux/CREDITS --- v2.1.105/linux/CREDITS Sun Jun 7 11:16:25 1998 +++ linux/CREDITS Sat Jun 13 10:23:41 1998 @@ -1492,6 +1492,12 @@ E: rubini@ipvvis.unipv.it D: the gpm mouse server and kernel support for it +N: Paul Russell +E: Paul.Russell@rustcorp.com.au +W: http://www.adelaide.net.au/~rustcorp +D: Ruggedly handsome. +D: Developed Generic IP Firewalling Chains with Michael Neuling. + N: Thomas Sailer E: sailer@ife.ee.ethz.ch E: HB9JNX@HB9W.CHE.EU (packet radio) @@ -1786,6 +1792,11 @@ S: Chudenicka 8 S: 10200 Prague 10, Hostivar S: Czech Republic + +N: Andrew Veliath +E: andrewtv@usa.net +D: Turtle Beach MultiSound sound driver +S: USA N: Dirk Verworner D: Co-author of german book ``Linux-Kernel-Programmierung'' diff -u --recursive --new-file v2.1.105/linux/Documentation/Changes linux/Documentation/Changes --- v2.1.105/linux/Documentation/Changes Sun Jun 7 11:16:25 1998 +++ linux/Documentation/Changes Thu Jun 11 22:52:32 1998 @@ -33,7 +33,7 @@ Also, don't forget http://www.linuxhq.com/ for all your Linux kernel needs. -Last updated: May 12, 1998 +Last updated: May 31, 1998 Current Author: Chris Ricker (kaboom@gatech.edu). Current Minimal Requirements @@ -47,10 +47,10 @@ - Gnu C 2.7.2.3 ; gcc --version - Binutils 2.8.1.0.23 ; ld -v - Linux C Library 5.4.44 ; ls -l /lib/libc.so.* -- Dynamic Linker (ld.so) 1.9.5 ; ldd --version +- Dynamic Linker (ld.so) 1.9.9 ; ldd --version or ldd -v - Linux C++ Library 2.7.2.8 ; ls -l /usr/lib/libg++.so.* - Procps 1.2.7 ; ps --version -- Procinfo 13 ; procinfo -v +- Procinfo 14 ; procinfo -v - Mount 2.7l ; mount --version - Net-tools 1.45 ; hostname -V - Loadlin 1.6a @@ -190,6 +190,17 @@ of /proc/net/dev changed; as a result, an older ifconfig will incorrectly report errors. + As of 2.1.102, the firewalling code has been replaced with +firewalling chains. See +http://www.adelaide.net.au/~rustcorp/ipfwchains/ipfwchains.html for +more information. Among other things, you'll now need to use ipchains +instead of ipfwadm to configure your filters. + + The IP firewalling code has been replaced: ipfwadm will no longer +work. You need to obtain `ipchains', available from +http://www.adelaide.net.au/~rustcorp/ipfwchains/ipfwchains.html +which includes an ipfwadm wrapper. + Memory ====== @@ -209,8 +220,8 @@ RPM === - If you run Red Hat Linux or any other distribution that uses RPM, you -need to upgrade RPM to version 2.2.7 or later. + If you run Red Hat Linux or any other distribution that uses RPM, +you need to upgrade RPM to version 2.2.7 or later. DOSEMU ====== @@ -344,9 +355,9 @@ Dynamic Linker ============== -The 1.9.5 release: -ftp://tsx-11.mit.edu/pub/linux/packages/GCC/ld.so-1.9.5.tar.gz -ftp://sunsite.unc.edu/pub/Linux/GCC/ld.so-1.9.5.tar.gz +The 1.9.9 release: +ftp://tsx-11.mit.edu/pub/linux/packages/GCC/ld.so-1.9.9.tar.gz +ftp://sunsite.unc.edu/pub/Linux/GCC/ld.so-1.9.9.tar.gz Modules utilities ================= @@ -364,21 +375,21 @@ Procinfo utilities ================== -The 13 release: -ftp://ftp.cistron.nl/pub/people/svm/procinfo-13.tar.gz +The 14 release: +ftp://ftp.cistron.nl/pub/people/svm/procinfo-14.tar.gz RPM utilities ============= The 2.2.7 release for Intel: -ftp://ftp.redhat.com/pub/redhat/redhat-4.0/updates/i386/rpm-2.2.7-1.i386.rpm -ftp://ftp.redhat.com/pub/redhat/redhat-4.0/updates/i386/rpm-devel-2.2.7-1.i386.rpm +ftp://ftp.redhat.com/pub/redhat/old-releases/redhat-4.0/updates/i386/rpm-2.2.7-1.i386.rpm +ftp://ftp.redhat.com/pub/redhat/old-releases/redhat-4.0/updates/i386/rpm-devel-2.2.7-1.i386.rpm The 2.2.7 release for Alpha: -ftp://ftp.redhat.com/pub/redhat/redhat-4.0/updates/axp/rpm-2.2.7-1.axp.rpm -ftp://ftp.redhat.com/pub/redhat/redhat-4.0/updates/axp/rpm-devel-2.2.7-1.axp.rpm +ftp://ftp.redhat.com/pub/redhat/old-releases/redhat-4.0/updates/axp/rpm-2.2.7-1.axp.rpm +ftp://ftp.redhat.com/pub/redhat/old-releases/redhat-4.0/updates/axp/rpm-devel-2.2.7-1.axp.rpm The 2.2.7 release for SPARC: -ftp://ftp.redhat.com/pub/redhat/redhat-4.0/updates/i386/rpm-2.2.7-1.sparc.rpm -ftp://ftp.redhat.com/pub/redhat/redhat-4.0/updates/i386/rpm-devel-2.2.7-1.sparc.rpm +ftp://ftp.redhat.com/pub/redhat/old-releases/redhat-4.0/updates/sparc/rpm-2.2.7-1.sparc.rpm +ftp://ftp.redhat.com/pub/redhat/old-releases/redhat-4.0/updates/sparc/rpm-devel-2.2.7-1.sparc.rpm DOSEMU ====== @@ -455,6 +466,13 @@ The 2.3.5 release: ftp://cs.anu.edu.au/pub/software/ppp/ppp-2.3.5.tar.gz + +IP Chains +========= + +The 1.3.3 release: +http://www.adelaide.net.au/~rustcorp/ipfwchains/ipchains-source-1.3.3.tar.gz +http://www.adelaide.net.au/~rustcorp/ipfwchains/ipchains-source-1.3.3.tar.bz2 Other Info ========== diff -u --recursive --new-file v2.1.105/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.1.105/linux/Documentation/Configure.help Tue Jun 9 11:57:28 1998 +++ linux/Documentation/Configure.help Sat Jun 13 12:59:16 1998 @@ -154,14 +154,22 @@ CONFIG_BLK_DEV_LOOP Saying Y here will allow you to mount a file as a file system. This is useful if you want to check an ISO9660 file system before burning - the CD, or want to use floppy images without first writing them to - floppy. This option also allows you to mount a filesystem with - encryption. To use these features, you need a recent version of - mount (available via FTP (user: anonymous) from - ftp://ftp.win.tue.nl/pub/linux/util/). Note that this loop device - has nothing to do with the loopback device used for network - connections from the machine to itself. Most users will answer N - here. + the CD, or if you want to use floppy images without first writing + them to floppy. + + This option also allows you to mount a filesystem with encryption. + (Note that an alternative way to encrypt filesystems is provided by + the cfs package, which can be gotten via FTP (user: anonymous) from + ftp://ftp.replay.com/pub/crypto/disk). + + To use the loop device, you need a recent version of mount + (available via FTP (user: anonymous) from + ftp://ftp.win.tue.nl/pub/linux/util/). + + Note that this loop device has nothing to do with the loopback + device used for network connections from the machine to itself. + + Most users will answer N here. Network Block Device support CONFIG_BLK_DEV_NBD @@ -314,12 +322,21 @@ CONFIG_BLK_DEV_IDESCSI This will provide SCSI host adapter emulation for IDE ATAPI devices, and will allow you to use a SCSI device driver instead of a native - ATAPI driver. This is useful if you have an ATAPI device for which - no native driver has been written (for example, an ATAPI PD-CD or - CDR drive); you can then use this emulation together with an - appropriate SCSI device driver. If both this SCSI emulation and - native ATAPI support are compiled into the kernel, the native - support will be used. Normally, say N. + ATAPI driver. + + This is useful if you have an ATAPI device for which no native + driver has been written (for example, an ATAPI PD-CD or CDR drive); + you can then use this emulation together with an appropriate SCSI + device driver. In order to do this, say Y here and to "SCSI support" + and "SCSI generic support", below. + + Note that this option does NOT allow you to attach SCSI devices to a + box that doesn't have a SCSI host adapter installed. + + If both this SCSI emulation and native ATAPI support are compiled + into the kernel, the native support will be used. + + If unsure, say N. CMD640 chipset bugfix/support CONFIG_BLK_DEV_CMD640 @@ -451,46 +468,51 @@ CONFIG_BLK_DEV_NS87415 This driver adds detection and support for the NS87415 chip (used in SPARC64, among others). + Please read the comments at the top of drivers/block/ns87415.c. QDI QD6580 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 - Documentation/ide.txt and qd6580.c files for more info. + files Documentation/ide.txt and qd6580.c for more info. UMC 8672 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 Documentation/ide.txt and umc8672.c files for more info. + See the files Documentation/ide.txt and umc8672.c for more info. ALI M14xx 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 ALI M1439/1443/1445/1487/1489 chipsets, and permits faster - I/O speeds to be set as well. See the Documentation/ide.txt and - ali14xx.c files for more info. + I/O speeds to be set as well. See the files Documentation/ide.txt + and ali14xx.c for more info. Apple Macintosh builtin IDE interface support (EXPERIMENTAL) CONFIG_BLK_DEV_MAC_IDE This is the IDE driver for the builtin IDE interface on some Apple Macintosh models. It supports both the Quadra/Performa/LC 630 and the PowerBook 190 IDE interface. + Say Y if you have such a Macintosh model and want to use IDE devices (hard disks, CD-ROM drives, etc.) that are connected to the builtin IDE interface. XT hard disk support CONFIG_BLK_DEV_XD - Very old 8 bit hard disk controllers used in the IBM XT computer. To - include a driver for these, say Y. If you want to compile the driver - as a module ( = code which can be inserted in and removed from the - running kernel whenever you want), say M here and read - Documentation/modules.txt. The module will be called xd.o. It's - pretty unlikely that you have one of these: say N. + Very old 8 bit hard disk controllers used in the IBM XT computer + will be supported if you say Y here. + + If you want to compile the driver as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called xd.o. + + It's pretty unlikely that you have one of these: say N. Parallel port IDE device support CONFIG_PARIDE @@ -560,12 +582,27 @@ This option enables the high-level driver for ATAPI tape devices connected through a parallel port. If you chose to build PARIDE support into your kernel, you may answer Y here to build in the - parallel port ATAPI disk driver, otherwise you should answer M + parallel port ATAPI tape driver, otherwise you should answer M to build it as a loadable module. The module will be called pt.o. You must also have at least one parallel port protocol driver in your system. Among the devices supported by this driver is the parallel port version of the HP 5GB drive. +Parallel port generic ATAPI devices +CONFIG_PARIDE_PG + This option enables a special high-level driver for generic ATAPI + devices connected through a parallel port. The driver allows user + programs, such as cdrecord, to send ATAPI commands directly to a + device. If you chose to build PARIDE support into your kernel, you + may answer Y here to build in the parallel port generic ATAPI driver, + otherwise you should answer M to build it as a loadable module. + The module will be called pg.o. You must also have at least one + parallel port protocol driver in your system. This driver + implements an API loosely related to the generic SCSI driver. + See /usr/include/linux/pg.h for details, or visit + http://www.torque.net/parport/cdr.html for more information and + the required patches to cdrecord. + ATEN EH-100 protocol CONFIG_PARIDE_ATEN This option enables support for the ATEN EH-100 parallel port IDE @@ -633,10 +670,21 @@ adapter that is used in some portable hard drives. If you chose to build PARIDE support into your kernel, you may answer Y here to build in the protocol driver, otherwise you should answer M to - build it as a loadable module. The module will be called ktti.o. + build it as a loadable module. The module will be called fit2.o. You must also have a high-level driver for the type of device that you want to support. +FIT TD-3000 protocol +CONFIG_PARIDE_FIT3 + This option enables support for the TD-3000 parallel port IDE protocol + from Fidelity International Technology. This protocol is used in newer + models of their portable disk, CD-ROM and PD/CD devices. If you chose + to build PARIDE support into your kernel, you may answer Y here to + build in the protocol driver, otherwise you should answer M to + build it as a loadable module. The module will be called fit3.o. + You must also have a high-level driver for the type of device + that you want to support. + FreeCom power protocol CONFIG_PARIDE_FRPW This option enables support for the Freecom power parallel port IDE @@ -766,6 +814,24 @@ IDE card support CONFIG_BLK_DEV_IDE_CARDS + On Acorn systems, say Y here if you wish to use an IDE interface + expansion card. If you do not or are unsure, say N. + +ICS IDE interface +CONFIG_BLK_DEV_IDE_ICS + On Acorn systems, say Y here if you wish to use the ICS IDE + interface card. This is not required for ICS partition support. If + you are unsure, say. + +ADFS partition support +CONFIG_BLK_DEV_PART + This allows Linux on Acorn systems to determine its partitions in + the 'non-ADFS' partition area of the hard disk - usually located + after the ADFS partition. You are probably using this system, so + you should say Y here. + +IDE card support +CONFIG_BLK_DEV_IDE_CARDS On Acorn systems, enable this if you wish to use an IDE interface expansion card. If you do not or are unsure, say N to this. @@ -920,11 +986,10 @@ is talking to the firewall box -- makes the local network completely invisible to the outside world and avoids the need to allocate globally valid IP host addresses for the machines on the local net) - and IP packet accounting (keeping track of what is using up all your - network bandwidth) and IP transparent proxying (makes the computers - on the local network think they're talking to a remote computer, - while in reality the traffic is redirected by your Linux firewall to - a local proxy server). + and IP transparent proxying (makes the computers on the local + network think they're talking to a remote computer, while in reality + the traffic is redirected by your Linux firewall to a local proxy + server). Make sure to say N to "Fast switching" below if you intend to say Y here. @@ -948,6 +1013,11 @@ about SYN cookies, check out ftp://koobera.math.uic.edu/pub/docs/syncookies-archive. + If you are SYN flooded, the source address reported by the kernel is + likely to have been forged by the attacker; it is only reported as + an aid in tracing the packets to their actual source and should not + be taken as absolute truth. + If you say Y here, note that SYN cookies aren't enabled by default; you can enable them by saying Y to "/proc filesystem support" and "Sysctl support" below and executing the command @@ -1060,18 +1130,15 @@ serial ports on the same board to share a single IRQ. To enable support for this in the serial driver, say Y here. -Autodetect IRQ on standard ports (unsafe) +Auto detect IRQ on standard ports (unsafe) CONFIG_SERIAL_DETECT_IRQ - Enable this option if you want the kernel to try to guess which IRQ - is configured during the boot sequence and you're too lazy to edit - the boot scripts to use the setserial command. This option can be - unsafe and should not be enabled on most machines. It is far - better to dynamically request autoconfiguration during the boot-time - scripts using the setserial command. You can change the IRQ and/or - request automatic IRQ configuration at any time by using the - "setserial" program. I wouldn't include this config option at all except - people keep bellyaching about it. I guess they are really are too lazy - to edit their boot scripts. :-) If unsure, say No. + Say Y here if you want the kernel to try to guess which IRQ + to use for your serial port. + + This is considered unsafe; it is far better to configure the IRQ in + a boot script using the setserial command. + + If unsure, say N. Support special multiport boards CONFIG_SERIAL_MULTIPORT @@ -1099,9 +1166,10 @@ bus system, i.e. the way the CPU talks to the other stuff inside your box. Other bus systems are ISA, EISA, Microchannel (MCA) or VESA. If you have PCI, say Y, otherwise N. The PCI-HOWTO, available - via FTP (user: anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO, - contains valuable information about which PCI hardware does work - under Linux and which doesn't. + via FTP (user: anonymous) in + ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO, contains valuable + information about which PCI hardware does work under Linux and which + doesn't. If some of your PCI devices don't work and you get a warning during boot time ("man dmesg"), please follow the instructions at the top @@ -1131,8 +1199,9 @@ PCI quirks CONFIG_PCI_QUIRKS If you have a broken BIOS, it may fail to set up the PCI bus in a - correct or optimal fashion. If your BIOS is fine you can say N here - for a very slightly smaller kernel. If unsure, say Y. + correct or optimal fashion. Saying Y here will correct that problem. + If your BIOS is fine you can say N here for a very slightly smaller + kernel. If unsure, say Y. PCI bridge optimization (experimental) CONFIG_PCI_OPTIMIZE @@ -1588,10 +1657,10 @@ CONFIG_IP_ROUTE_TOS The header of every IP packet carries a TOS (Type of Service) value with which the packet requests a certain treatment, e.g. low latency - (for interactive traffic), high throughput, or high - reliability. Normally, these values are ignored, but if you say Y - here, you will be able to specify different routes for packets with - different TOS values. + (for interactive traffic), high throughput, or high reliability. + Normally, these values are ignored, but if you say Y here, you will + be able to specify different routes for packets with different TOS + values. IP: verbose route monitoring CONFIG_IP_ROUTE_VERBOSE @@ -1641,22 +1710,19 @@ More powerful than the old IP firewalling but also provides similar structure to original firewalling for experienced users. IP accounting and packet logging are automatically included with firewall - chains, so you don't need them them if you say Y here. See + chains. See http://www.adelaide.net.au/~rustcorp for new ipfwadm (called ipchains). If in doubt, say N here. IP: firewall packet netlink device CONFIG_IP_FIREWALL_NETLINK - If you say Y here and then packets hit your Linux firewall and are - blocked, the first 128 bytes of each such packet are passed on to - optional user space monitoring software that can then look for - attacks and take actions such as paging the administrator of the - site. To use this, you need to create a character special file under - /dev with major number 36 and minor number 3 using mknod ("man - mknod"), and you need (to write) a program that reads from that - device and takes appropriate action. - With the current generic firewalling chains you can specify which - packets go to this device, as well as how many bytes. + If you say Y here, then packets which hit your Linux firewall can + be copied to optional user space monitoring software that can then + respond accordingly: see the ipchains source distributions for an + example if this. To use this, you need to create a character + special file under /dev with major number 36 and minor number 3 + using mknod ("man mknod"), and you need (to write) a program that + reads from that device and takes appropriate action. IP: kernel level autoconfiguration CONFIG_IP_PNP @@ -1728,12 +1794,6 @@ Network), but can be distributed all over the Internet. If you want to do that, say Y here and to "IP: multicast routing" below. -IP: firewall packet logging -CONFIG_IP_FIREWALL_VERBOSE - This gives you information about what your firewall did with - packets it received. The information is handled by the klogd daemon - which is responsible for kernel messages ("man klogd"). - IP: transparent proxying CONFIG_IP_TRANSPARENT_PROXY This enables your Linux firewall to transparently redirect any @@ -1775,7 +1835,9 @@ Details on how to set things up are contained in the IP Masquerade mini-HOWTO, available via FTP (user: anonymous) from - ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/mini. + ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/mini; there's also some + information on the WWW at + http://www.tor.shaw.wave.ca/~ambrose/kernel21.html. If you say Y here, you should also say Y to "IP: always defragment", below. If you say Y here, then the modules ip_masq_ftp.o (for ftp @@ -1814,13 +1876,23 @@ IP: ipportfw masquerade support CONFIG_IP_MASQUERADE_IPPORTFW - ipportfw is an addition to IP Masquerading written by Steven Clarke - to allow some forwarding of packets from outside to inside a - firewall on given ports. Information and source for ipportfw is - available from + Port Forwarding is an addition to IP Masquerading written by Steven + Clarke to allow some forwarding of packets from outside to inside a + firewall on given ports. This could be useful if, for example, you + want to run a web server behind the firewall or masquerading host + and this web server should be visible to the outside world. An + external client connects to port 80 of the firewall, the firewall + forwards requests to this port to the web server, the web server + handles the request and the results are sent through the firewall to + the original client. The client thinks that the firewall machine + itself is running the web server. + + Information about it is available from http://www.monmouth.demon.co.uk/ipsubs/portforwarding.html (to browse the WWW, you need to have access to a machine on the Internet - that has a program like lynx or netscape). + that has a program like lynx or netscape). You will need the user + space program ipportfw which can be downloaded from + ftp://ftp.compsoc.net/users/steve/ipportfw/linux21/ The portfw code is still under development and so is currently marked EXPERIMENTAL. If you want to try it, say Y. @@ -2005,18 +2077,20 @@ Unix domain sockets CONFIG_UNIX This includes Unix domain sockets, the standard Unix mechanism for - establishing and accessing network connections. Unless you are - working on an embedded system or something, you definitely want to - say Y here. + establishing and accessing network connections. Many commonly used + programs such as the X Window system and syslog use these sockets + even if your machine is not connected to any network. Unless you are + working on an embedded system or something similar, you therefore + definitely want to say Y here. The socket support is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). The module will be called unix.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. If you try building this as a module and you are running kerneld, be sure - to add 'alias net-pf-1 unix' to your /etc/conf.module file. If - unsure, say Y. (NOTE: X Windows and syslog probably won't work - if you say N to this or fail to configure it correctly) + to add 'alias net-pf-1 unix' to your /etc/conf.module file. + + If unsure, say Y. The IPv6 protocol CONFIG_IPV6 @@ -2056,26 +2130,45 @@ some problems caused by the presence of two link-local addresses on an interface. +IPv6: routing messages via old netlink +CONFIG_IPV6_NETLINK + You can say Y here to receive routing messages from the IPv6 code + through the old netlink interface. However, a better option is to + say Y to "Kernel/User network link driver" and to "Routing + messages" instead. + IPX networking CONFIG_IPX This is support for the Novell networking protocol, IPX, commonly used for local networks of Windows machines. You need it if you want to access Novell NetWare file or print servers using the Linux Novell client ncpfs (available via FTP (user: anonymous) from - sunsite.unc.edu:/pub/Linux/system/filesystems/) or from within the - Linux DOS emulator dosemu (read the DOSEMU-HOWTO, available in - sunsite.unc.edu:/pub/Linux/docs/HOWTO). In order to do the former, - you'll also have to say Y to "NCP filesystem support", below. To - turn your Linux box into a fully featured NetWare file server and + ftp://sunsite.unc.edu/pub/Linux/system/filesystems/) or from within + the Linux DOS emulator dosemu (read the DOSEMU-HOWTO, available in + ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO). In order to do the + former, you'll also have to say Y to "NCP filesystem support", + below. + + IPX is similar in scope to IP, while SPX, which runs on top of IPX, + is similar to TCP. There is also experimental support for SPX in + Linux (see "SPX networking", below). + + To turn your Linux box into a fully featured NetWare file server and IPX router, say Y here and fetch either lwared from - sunsite.unc.edu:/pub/Linux/system/network/daemons/ or mars_nwe from - ftp.gwdg.de:/pub/linux/misc/ncpfs. For more information, read the - IPX-HOWTO in sunsite.unc.edu:/pub/Linux/docs/howto. The IPX driver - would enlarge your kernel by about 5 kB. This driver is also - available as a module ( = code which can be inserted in and removed - from the running kernel whenever you want). The module will be - called ipx.o. If you want to compile it as a module, say M here - and read Documentation/modules.txt. Unless you want to integrate + ftp://sunsite.unc.edu/pub/Linux/system/network/daemons/ or mars_nwe from + ftp://ftp.gwdg.de/pub/linux/misc/ncpfs. For more information, read the + IPX-HOWTO in ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. + + General information about how to connect Linux, Windows machines and + Macs is on the WWW at http://www.eats.com/linux_mac_win.html (to + browse the WWW, you need to have access to a machine on the Internet + that has a program like lynx or netscape). + + The IPX driver would enlarge your kernel by about 5 kB. This driver + is also available as a module ( = code which can be inserted in and + removed from the running kernel whenever you want). The module will + be called ipx.o. If you want to compile it as a module, say M here + and read Documentation/modules.txt. Unless you want to integrate your Linux box with a local Novell network, say N. IPX: Full internal IPX network @@ -2083,11 +2176,12 @@ Every IPX network has an address that identifies it. Sometimes it is useful to give an IPX "network" address to your Linux box as well (for example if your box is acting as a fileserver for different IPX - networks: it will then be accessible form everywhere using the same + networks: it will then be accessible from everywhere using the same address). The way this is done is to create a virtual internal "network" inside your box and to assign an IPX address to this network. Say Y here if you want to do this; read the IPX-HOWTO at - sunsite.unc.edu:/pub/Linux/docs/howto for details. + ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO for details. + The full internal IPX network enables you to allocate sockets on different virtual nodes of the internal network. This is done by evaluating the field sipx_node of the socket address given to the @@ -2099,14 +2193,28 @@ 'special' sockets to sockets listening on the primary network is disabled. This might break existing applications, especially RIP/SAP daemons. A RIP/SAP daemon that works well with the full internal net - can be found on ftp.gwdg.de:/pub/linux/misc/ncpfs. If you don't + can be found on ftp://ftp.gwdg.de/pub/linux/misc/ncpfs. If you don't know what you are doing, say N. IPX: SPX networking (EXPERIMENTAL) CONFIG_SPX - The (SPP-derived) Sequenced Packet eXchange (SPX) protocol. Novell's - networking protocol which monitors transmissions to guarantee - successful delivery. It is safe to say Y/M here. + The Sequenced Packet eXchange protocol is a transport layer protocol + built on top of IPX. It is used in Novell NetWare systems for + client-server applications and is similar to TCP (which runs on top + of IP). + + Note that Novell NetWare file sharing does not use SPX; it uses a + protocol called NCP, for which separate Linux support is available + ("NCP filesystem support" below for the client side, and the user + space programs lwared or mars_nwe for the server side). + + Say Y here if you have use for SPX; read the IPX-HOWTO at + ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO for details. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called af_spx.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. Appletalk DDP CONFIG_ATALK @@ -2115,36 +2223,42 @@ want to join the conversation, say Y. You will need to use the netatalk package so that your Linux box can act as a print and file server for Macs as well as access Appletalk printers. Check out - http://artoo.hitchcock.org/~flowerpt/projects/linux-netatalk/ on the - WWW for details (to browse the WWW, you need to have access to a - machine on the Internet that has a program like lynx or - netscape). EtherTalk is the name used for Appletalk over Ethernet - and the cheaper and slower LocalTalk is appletalk over a proprietary - apple network using serial links. Ethertalk and Localtalk are fully - supported by Linux. The NET-2-HOWTO, available via FTP (user: anonymous) - in sunsite.unc.edu:/pub/Linux/docs/HOWTO contains valuable information - as well. This driver is also available as a module ( = code which - can be inserted in and removed from the running kernel whenever you - want). The module is called appletalk.o. If you want to compile - it as a module, say M here and read Documentation/modules.txt. I - hear that the GNU boycott of Apple is over, so even politically - correct people are allowed to say Y here. + http://threepio.hitchcock.org/cgi-bin/faq/netatalk/faq.pl on the WWW + for details (to browse the WWW, you need to have access to a machine + on the Internet that has a program like lynx or netscape). EtherTalk + is the name used for Appletalk over Ethernet and the cheaper and + slower LocalTalk is appletalk over a proprietary apple network using + serial links. Ethertalk and Localtalk are fully supported by Linux. + The NET-2-HOWTO, available via FTP (user: anonymous) in + ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO contains valuable + information as well. + + General information about how to connect Linux, Windows machines and + Macs is on the WWW at http://www.eats.com/linux_mac_win.html + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module is called appletalk.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. I hear that + the GNU boycott of Apple is over, so even politically correct people + are allowed to say Y here. Appletalk-IP driver support CONFIG_IPDDP This allows IP networking for users who only have Appletalk networking available. This feature is experimental. With this driver, you can either encapsulate IP inside Appletalk (e.g. if your - Linux box is stuck on an appletalk only network) or decapsulate - (e.g. if you want your Linux box to act as a Internet gateway for a + Linux box is stuck on an Appletalk only network) or decapsulate + (e.g. if you want your Linux box to act as an Internet gateway for a zoo of appletalk connected Macs). You decide which one of the two you want in the following two questions; you can say Y to only one of them. Please see Documentation/networking/ipddp.txt for more - information. This driver is also available as a module ( = code - which can be inserted in and removed from the running kernel - whenever you want). The module is called ipddp.o. If you want to - compile it as a module, say M here and read - Documentation/modules.txt. + information. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module is called ipddp.o. If you want to compile it as a module, + say M here and read Documentation/modules.txt. IP to Appletalk-IP Encapsulation support CONFIG_IPDDP_ENCAP @@ -2406,6 +2520,21 @@ say M here and read Documentation/modules.txt. This is recommended. The module will be called baycom_par.o. +BAYCOM epp driver for AX.25 +CONFIG_BAYCOM_EPP + This is a driver for Baycom style simple amateur radio modems that + connect to a parallel interface. The driver supports the epp + designs. To configure the driver, use the sethdlc utility available + in the standard ax25 utilities package. For information on the + modems, see http://www.baycom.de (to browse the WWW, you need to + have access to a machine on the Internet that has a program like + lynx or netscape) and Documentation/networking/baycom.txt. + + If you want to compile this driver as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. This is recommended. + The module will be called baycom_par.o. + BAYCOM ser12 full duplex driver for AX.25 CONFIG_BAYCOM_SER_FDX This is one of two drivers for Baycom style simple amateur radio @@ -2915,7 +3044,7 @@ BusLogic SCSI support CONFIG_SCSI_BUSLOGIC This is support for BusLogic MultiMaster and FlashPoint SCSI Host - Adapters. Consult the SCSI-HOWTO, available via anonymous ftp from + Adapters. Consult the SCSI-HOWTO, available via anonymous FTP from ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO, and the files README.BusLogic and README.FlashPoint in drivers/scsi for more information. If this driver does not work correctly without @@ -3197,7 +3326,7 @@ interface. If all the boards of your system are genuine SYMBIOS boards or use - BIOS and drivers from SYMBIOS, you would want to enable this option. + BIOS and drivers from SYMBIOS, you would want to say Y here. The driver behaves correctly on my system with this option enabled. (SDMS 4.0 + Promise SCSI ULTRA 875 rev 0x3 + ASUS SC200 810A rev 0x12). This option must be set to N if your system has at least one @@ -3205,10 +3334,10 @@ DC-390/U/W/F). However, if all your non Symbios compatible boards have NVRAM, - setting option "detect and read serial NVRAMs" + saying Y to "detect and read serial NVRAMs" (CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT) above allows the driver to - distinguish Symbios compatible boards from other ones. So, you can - answer Y if all non Symbios compatible boards have NVRAM. + distinguish Symbios compatible boards from other ones; you can then + also answer Y here. If unsure, say N. @@ -3428,7 +3557,7 @@ This driver supports all the EATA/DMA-compliant SCSI host adapters and does not need any BIOS32 service. DPT ISA and all EISA i/o addresses are probed looking for the "EATA" signature. If you said Y - to "PCI bios support", the addresses of all the PCI SCSI controllers + to "PCI BIOS support", the addresses of all the PCI SCSI controllers reported by BIOS32 are probed as well. You want to read the start of drivers/scsi/eata.c and the SCSI-HOWTO, available via FTP (user: anonymous) at ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. @@ -3560,6 +3689,59 @@ CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE Say Y here to enable tagged queuing support on the Acorn SCSI card. + This is a feature of SCSI-2 which improves performance: the host + adapter can send several SCSI commands to a device's queue even if + previous commands haven't finished yet. Some SCSI devices don't + implement this properly, so the safe answer is N. + +Acorn SCSI Synchronous transfers support +CONFIG_SCSI_ACORNSCSI_SYNC + Say Y here to enable synchronous transfer negotiation with all targets + on the Acorn SCSI card. + + In general, this improves performance; however some SCSI devices + don't implement it properly, so the safe answer is N. + +Oak SCSI support +CONFIG_SCSI_OAK1 + This enables support for the Oak SCSI card. If you have an Acorn system + with one of these, say Y. If unsure, say N. + +Cumana SCSI I support +CONFIG_SCSI_CUMANA_1 + This enables support for the Cumana SCSI I card. If you have an Acorn + system with one of these, say Y. If unsure, say N. + +Cumana SCSI II support +CONFIG_SCSI_CUMANA_2 + This enables support for the Cumana SCSI II card. If you have an Acorn + system with one of these, say Y. If unsure, say N. + +EcoSCSI support +CONFIG_SCSI_ECOSCSI + This enables support for the EcoSCSI card - a small card that sits in + the Econet socket. If you have an Acorn system with one of these, + say Y. If unsure, say N. + +EESOX SCSI support +CONFIG_SCSI_EESOXSCSI + This enables support for the EESOX SCSI card. If you have an Acorn + system with one of these, say Y, otherwise say N. + +Powertec SCSI support +CONFIG_SCSI_POWERTECSCSI + This enables support for the Powertec SCSI card on Acorn systems. If + you have one of these, say Y. If unsure, say N. + +AcornSCSI support +CONFIG_SCSI_ACORNSCSI_3 + This enables support for the Acorn SCSI card (aka30). If you have an + Acorn system with one of these, say Y. If unsure, say N. + +Acorn SCSI tagged queue support +CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE + Say Y here to enable tagged queuing support on the Acorn SCSI card. + Acorn SCSI Synchronous transfers support CONFIG_SCSI_ACORNSCSI_SYNC Say Y here to enable synchronous transfer negociation with all targets @@ -3788,18 +3970,23 @@ AT&T WaveLAN & DEC RoamAbout DS support CONFIG_WAVELAN - The Lucent Wavelan (formerly NCR and AT&T ; or DEC RoamAbout DS) is + The Lucent WaveLAN (formerly NCR and AT&T; or DEC RoamAbout DS) is a Radio LAN (wireless Ethernet-like Local Area Network) using the radio frequencies 900 MHz and 2.4 GHz. This driver support the ISA version of the Wavelan card. A separate - driver for the pcmcia hardware is available in David Hinds's pcmcia - package. If you want to use an ISA Wavelan card under Linux, say Y - and read the Ethernet-HOWTO, available via FTP (user: anonymous) in + driver for the pcmcia hardware is available in David Hinds's + pcmcia-cs package (see the file Documentation/Changes for location). + + If you want to use an ISA Wavelan card under Linux, say Y and read + the Ethernet-HOWTO, available via FTP (user: anonymous) in ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. Some more specific - information is contained in Documentation/networking/wavelan.txt. + information is contained in Documentation/networking/wavelan.txt and + in the source code drivers/net/wavelan.p.h. + You will also need the wireless tools package available from ftp://ftp.inka.de/pub/comp/Linux/networking/NetTools/contrib/. + Please read the man pages contained therein. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -3817,10 +4004,21 @@ something at ftp://ftp.lmh.ox.ac.uk/users/weejock/linux/, but I haven't written anything too useful yet...) -AIMSlab RadioTrack card +AIMSlab RadioTrack (aka RadioReveal) support CONFIG_RADIO_RTRACK - Choose Y here if you have one of these, and then fill in the port - address below. + Choose Y here if you have one of these FM radio cards, and then fill + in the port address below. + + In order to control your radio card under the X window system, you + may use the program X-Tuner, available on the WWW at + http://gatekeeper.dec.com/pub/X11/R6-contrib/applications/; to + browse the WWW, you need to have access to a machine on the Internet + that has a program like lynx or netscape. + + If you want to compile this driver as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called radio-aimslab.o. RadioTrack i/o port CONFIG_RADIO_RTRACK_PORT @@ -3829,8 +4027,13 @@ Aztech/Packard Bell Radio CONFIG_RADIO_AZTECH - Choose Y here if you have one of these, and then fill in the port - address below. + Choose Y here if you have one of these FM radio cards, and then fill + in the port address below. + + If you want to compile this driver as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called radio-aztech.o. Aztech/Packard Bell radio card i/o port CONFIG_RADIO_AZTECH_PORT @@ -3838,6 +4041,20 @@ haven't changed the setting of jumper JP3 on the card. Removing the jumper sets the card to 0x358. +SF16FMI Radio +CONFIG_RADIO_SF16FMI + Choose Y here if you have one of these FM radio cards, and then fill + in the port address below. + + If you want to compile this driver as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called radio-sf16fmi.o + +SF16FMI I/O port (0x284 or 0x384) +CONFIG_RADIO_SF16FMI_PORT + Enter the I/O port of your SF16FMI radio card. + LAPB over Ethernet driver CONFIG_LAPBETHER This is a driver for a pseudo device (typically called /dev/lapb0) @@ -4005,6 +4222,35 @@ The module will be called sdla.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. +Acorn Econet/AUN protocols (EXPERIMENTAL) +CONFIG_ECONET + Econet is a fairly old and slow networking protocol mainly used by + Acorn computers to access file and print servers. It uses native + Econet network cards. AUN is an implementation of the higher level + parts of Econet that runs over ordinary Ethernet connections, on + top of the UDP packet protocol, which in turn runs on top of the + Internet protocol IP. + + If you say Y here, you can choose with the next two options whether + to send Econet/AUN traffic over a UDP Ethernet connection or over + a native Econet network card. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called econet.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. + +AUN over UDP +CONFIG_ECONET_AUNUDP + Say Y here if you want to send Econet/AUN traffic over a a UDP + connection (UDP is a packet based protocol that runs on top of the + Internet protocol IP) using an ordinary Ethernet network card. + +Native Econet +CONFIG_ECONET_NATIVE + Say Y here if you have a native Econet network card installed in + your computer. + WAN Router CONFIG_WAN_ROUTER Wide Area Networks (WANs), such as X.25, frame relay and leased @@ -4074,14 +4320,18 @@ called packet schedulers. You can attach different schedulers to different network devices. If you want to stick to the default scheduling algorithm, say N here. If you want to experiment with a - couple of different algorithms, say Y. + couple of different algorithms, say Y. Currently, this is only + recommended for experts. To administer these schedulers, you'll need the user-level utilities from the package iproute2+tc at ftp://ftp.inr.ac.ru/ip-routing/ - The available schedulers are - listed in the following questions; you can say Y to as many as you - like. If unsure, say N now. + If you say Y here and to "/proc filesystem" below, you will be able + to read status information about priority schedulers from + the file /proc/net/psched. + + The available schedulers are listed in the following questions; you + can say Y to as many as you like. If unsure, say N now. CBQ packet scheduler CONFIG_NET_SCH_CBQ @@ -4090,8 +4340,8 @@ algorithm classifies the waiting packets into a tree-like hierarchy of classes; the leaves of this tree are in turn scheduled by separate algorithms (called "disciplines" in this context) which you - can choose below from among the "auxiliary disciplines". See the top - of net/sched/sch_cbq.c for references about the CBQ algorithm. + can choose below from among the various queueing algorithms. See the + top of net/sched/sch_cbq.c for references about the CBQ algorithm. This code is also available as a module called sch_cbq.o ( = code which can be inserted in and removed from the running kernel @@ -4113,7 +4363,18 @@ whenever you want). If you want to compile it as a module, say M here and read Documentation/modules.txt. -RED queueing discipline +The simplest PRIO pseudo scheduler +CONFIG_NET_SCH_PRIO + Say Y here if you want to use an n-band priority queue packet + "scheduler" for some of your network devices or as a leaf discipline + for the CBQ scheduling algorithm. + + This code is also available as a module called sch_prio.o ( = code + which can be inserted in and removed from the running kernel + whenever you want). If you want to compile it as a module, say M + here and read Documentation/modules.txt. + +RED queue CONFIG_NET_SCH_RED Say Y here if you want to use the Random Early Detection (RED) packet scheduling algorithm for some of your network devices (see @@ -4125,7 +4386,7 @@ whenever you want). If you want to compile it as a module, say M here and read Documentation/modules.txt. -SFQ queueing discipline +SFQ queue CONFIG_NET_SCH_SFQ Say Y here if you want to use the Stochastic Fairness Queueing (SFQ) packet scheduling algorithm for some of your network devices or as a @@ -4138,7 +4399,21 @@ whenever you want). If you want to compile it as a module, say M here and read Documentation/modules.txt. -auxiliary TBF queue +TEQL queue +CONFIG_NET_SCH_TEQL + Say Y here if you want to use the True Link Equalizer (TLE) packet + scheduling algorithm for some of your network devices or as a leaf + discipline for the CBQ scheduling algorithm. This queueing + discipline allows the combination of several physical devices into + one virtual device. (see the top of net/sched/sch_teql.c for + details). + + This code is also available as a module called sch_teql.o ( = code + which can be inserted in and removed from the running kernel + whenever you want). If you want to compile it as a module, say M + here and read Documentation/modules.txt. + +TBF queue CONFIG_NET_SCH_TBF Say Y here if you want to use the Simple Token Bucket Filter (TBF) packet scheduling algorithm for some of your network devices or as a @@ -4150,27 +4425,49 @@ whenever you want). If you want to compile it as a module, say M here and read Documentation/modules.txt. -auxiliary FIFO queue -CONFIG_NET_SCH_PFIFO - Say Y here if you want to use a simple FIFO (first in - first out) - packet "scheduler" for some of your network devices or as a leaf - discipline for the CBQ scheduling algorithm. - - This code is also available as a module called sch_fifo.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read Documentation/modules.txt. +QoS support +CONFIG_NET_QOS + Say Y here if you want to include Quality Of Service scheduling + features, which means that you will be able to request certain + rate-of-flow limits for your net devices. -auxiliary PRIO queue -CONFIG_NET_SCH_PRIO - Say Y here if you want to use an n-band priority queue packet - "scheduler" for some of your network devices or as a leaf discipline - for the CBQ scheduling algorithm. + Note that the answer to this question won't directly affect the + kernel: saying N will just cause this configure script to skip all + the questions about QoS support. - This code is also available as a module called sch_prio.o ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read Documentation/modules.txt. +Rate estimator +CONFIG_NET_ESTIMATOR + In order for Quality of Service scheduling to work, the current + rate-of-flow for a network device has to be estimated; if you say Y + here, the kernel will do just that. + +Packet classifier API +CONFIG_NET_CLS + The CBQ scheduling algorithm requires that network packets which are + scheduled to be sent out over a network device be classified in some + way. If you say Y here, you will get a choice of several different + packet classifiers with the following questions. +# +# Routing tables based classifier +# CONFIG_NET_CLS_ROUTE +# +# Firewall based classifier +# CONFIG_NET_CLS_FW +# +# U32 classifier +# CONFIG_NET_CLS_U32 +# +# Special RSVP classifier +# CONFIG_NET_CLS_RSVP +# +# Special RSVP classifier for IPv6 +# CONFIG_NET_CLS_RSVP6 +# +# Ingres traffic policing +# CONFIG_NET_CLS_POLICE +### +### Some expert please fill these in +### Network code profiler CONFIG_NET_PROFILE @@ -4245,9 +4542,9 @@ Ethernet (10 or 100Mbit) CONFIG_NET_ETHERNET Ethernet (also called IEEE 802.3 or ISO 8802-2) is the most common - type of Local Area Networks (LANs) in universities or - companies. 10-base-2 or Thinnet (10 Mbps over coaxial cable, linking - computers in a chain), 10-base-T (10 Mbps over twisted pair + type of Local Area Networks (LANs) in universities or companies. + 10-base-2 or Thinnet (10 Mbps over coaxial cable, linking computers + in a chain), 10-base-T or TwistedPair (10 Mbps over twisted pair telephone cable, linking computers to a central hub) and 100-base- (100 Mbps) are common types of Ethernet. @@ -4359,6 +4656,18 @@ it as a module, say M here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. +PCI NE2000 support +CONFIG_NE2K_PCI + If you have a network (Ethernet) card of this type, say Y and read + the Ethernet-HOWTO, available via FTP (user: anonymous) in + ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called ne2k-pci.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt as well as + Documentation/networking/net-modules.txt. + Racal-Interlan (Micom) NI cards CONFIG_NET_VENDOR_RACAL If you have a network (Ethernet) card belonging to this class, such @@ -4408,6 +4717,32 @@ module, say M here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. +RealTek 8129/8139 (not 8019/8029!) support +CONFIG_RTL8139 + This is a driver for the Fast Ethernet PCI network cards based on + the RTL8129 and RTL8139 chips. If you have one of those, say Y and + read the Ethernet-HOWTO, available via FTP (user: anonymous) in + ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. + + If you want to compile this driver as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. This is recommended. + The module will be called rtl8139.o. + +Packet Engines Yellowfin Gigabit-NIC support +CONFIG_YELLOWFIN + Say Y here if you have a Packet Engines G-NIC PCI Gigabit Ethernet + adapter. This adapter is used by the Beowulf Linux cluster project. + See http://cesdis.gsfc.nasa.gov/linux/drivers/yellowfin.html for + more information about this driver in particular and Beowulf in + general (to browse the WWW, you need to have access to a machine on + the Internet that has a program like lynx or netscape). + + If you want to compile this driver as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. This is recommended. + The module will be called yellowfin.o. + AMD LANCE and PCnet (AT1500 and NE2100) support CONFIG_LANCE If you have a network (Ethernet) card of this type, say Y and read @@ -4509,10 +4844,10 @@ 3c590 series (592/595/597) "Vortex" support CONFIG_VORTEX - If you have a 3Com "Vortex" or "Boomerang" series network (Ethernet) - card (Fast EtherLink 3c590/3c592/3c595/3c597 or the EtherLink XL - 3c900 or 3c905), say Y and read the Ethernet-HOWTO, available via - FTP (user: anonymous) in ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. + If you have a 3Com "Vortex" (Fast EtherLink 3c590/3c592/3c595/3c597) + or "Boomerang" series (EtherLink XL 3c900 or 3c905) network + (Ethernet) card, say Y and read the Ethernet-HOWTO, available via FTP + (user: anonymous) in ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. More specific information is in Documentation/networking/vortex.txt and in the comments at the beginning of drivers/net/3c59x.c. @@ -4820,6 +5155,12 @@ Y here and read the Ethernet-HOWTO, available via FTP (user: anonymous) in ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called pcnet32.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt as well as + Documentation/networking/net-modules.txt. + Ansel Communications EISA 3200 support CONFIG_AC3200 If you have a network (Ethernet) card of this type, say Y and read @@ -4941,6 +5282,20 @@ module, say M here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. +PCI NE2000 Support +CONFIG_NE2K_PCI + This driver is for NE2000 compatible PCI cards. It will not work + with ISA NE2000 cards. If you have a network (Ethernet) card of + this type, say Y and read the Ethernet-HOWTO, available via FTP + (user: anonymous) in ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called ne2k-pci.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt as well as + Documentation/networking/net-modules.txt. + + TI ThunderLAN support (EXPERIMENTAL) CONFIG_TLAN If you have a TLAN based network card which is supported by this @@ -4987,7 +5342,7 @@ If you want to plug a network card into the PCMCIA slot of your laptop instead (PCMCIA is the standard for credit card size - extension cards used by all modern laptops), look on the ftp site + extension cards used by all modern laptops), look on the FTP site (user: anonymous) ftp://cb-iris.stanford.edu/pub/pcmcia and say N here. @@ -5115,6 +5470,26 @@ If you wish to compile a kernel for the EBSA-110, then you should always answer Y to this. +Acorn Ether1 card +CONFIG_ARM_ETHER1 + If you have an Acorn system with one of these (AKA25) network cards, + you should say Y to this option if you wish to use it with Linux. + +Acorn/ANT Ether3 card +CONFIG_ARM_ETHER3 + If you have an Acorn system with one of these network cards, you + should say Y to this option if you wish to use it with Linux. + +I Cubed EtherH card +CONFIG_ARM_ETHERH + If you have an Acorn system with one of these network cards, you + should say Y to this option if you wish to use it with Linux. + +EBSA-110 ethernet interface +CONFIG_AM79C961A + If you wish to compile a kernel for the EBSA-110, then you should + always answer Y to this. + Support CDROM drives that are not SCSI or IDE/ATAPI CONFIG_CD_NO_IDESCSI If you have a CDROM drive that is neither SCSI nor IDE/ATAPI, say Y @@ -5577,28 +5952,35 @@ Second extended fs support CONFIG_EXT2_FS This is the de facto standard Linux filesystem (= method to organize - files on a storage device) for hard disks. You want to say Y, unless - you intend to use Linux exclusively from inside a DOS partition - using the umsdos filesystem. The advantage of the latter is that you - can get away without repartitioning your hard drive (which often - implies backing everything up and restoring afterwards); the - disadvantage is that Linux becomes susceptible to DOS viruses and - that umsdos is somewhat slower than ext2fs. Even if you want to run - Linux in this fashion, it might be a good idea to have ext2fs - around: it enables you to read more floppy disks and facilitates the - transition to a *real* Linux partition later. Another (rare) case - which doesn't require ext2fs is a diskless Linux box which mounts - all files over the network using NFS (in this case it's sufficient - to say Y to "NFS filesystem support" below). Saying Y here will - enlarge your kernel by about 41 kB. + files on a storage device) for hard disks. + + You want to say Y here, unless you intend to use Linux exclusively + from inside a DOS partition using the umsdos filesystem. The + advantage of the latter is that you can get away without + repartitioning your hard drive (which often implies backing + everything up and restoring afterwards); the disadvantage is that + Linux becomes susceptible to DOS viruses and that umsdos is somewhat + slower than ext2fs. Even if you want to run Linux in this fashion, + it might be a good idea to have ext2fs around: it enables you to + read more floppy disks and facilitates the transition to a *real* + Linux partition later. Another (rare) case which doesn't require + ext2fs is a diskless Linux box which mounts all files over the + network using NFS (in this case it's sufficient to say Y to "NFS + filesystem support" below). Saying Y here will enlarge your kernel + by about 41 kB. The Ext2fs-Undeletion mini-HOWTO, available via FTP (user: anonymous) from ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/mini, gives information about how to retrieve deleted files on ext2fs filesystems. - To change the behavior of ext2fs filesystems, you can use the - tune2fs utility ("man tune2fs"). + To change the behavior of ext2 filesystems, you can use the tune2fs + utility ("man tune2fs"). To modify attributes of files and + directories on ext2 filesystems, use chattr ("man chattr"). + + Ext2fs partitions can be read from within DOS using the ext2tool + package available via FTP (user: anonymous) from + ftp://sunsite.unc.edu/pub/Linux/system/filesystems/ext2. If you want to compile this filesystem as a module ( = code which can be inserted in and removed from the running kernel whenever you @@ -5930,7 +6312,7 @@ The automounter is a tool to automatically mount remote filesystems on demand. This implementation is partially kernel-based to reduce overhead in the already-mounted case; this is unlike the BSD - automounter (amd), which is only in user space. + automounter (amd), which is a pure user space daemon. To use the automounter you need the user-space tools from ftp://ftp.kernel.org/pub/linux/daemons/autofs; you also want to say Y to @@ -6005,13 +6387,15 @@ ADFS filesystem support (read only) (EXPERIMENTAL) CONFIG_ADFS_FS - The Acorn Disc Filing System is the standard filesystem of the RiscOS - operating system which runs on Acorn's ARM based Risc PC systems and - the Acorn Archimedes range of machines. These should be the first - partition (ie, /dev/[hs]d?1) on each of your drives. If you say Y + The Acorn Disc Filing System is the standard filesystem of the + RiscOS operating system which runs on Acorn's ARM based Risc PC + systems and the Acorn Archimedes range of machines. If you say Y here, Linux will be able to read from ADFS partitions on hard drives and from ADFS-formatted floppy discs. + The ADFS partition should be the first partition (i.e., + /dev/[hs]d?1) on each of your drives. + This code is also available as a module called adfs.o ( = code which can be inserted in and removed from the running kernel whenever you want). If you want to compile it as a module, say M here and read @@ -6023,7 +6407,7 @@ CONFIG_DEVPTS_FS If you say Y here, you'll get a virtual filesystem which can be mounted on /dev/pts with "mount -t devpts". This, together with the - pseudo terminal master multiplexer /dev/ptmx is used for pseudo + pseudo terminal master multiplexer /dev/ptmx, is used for pseudo terminal support as described in the Open Group's Unix98 standard: in order to acquire a pseudo terminal, a process opens /dev/ptmx; the number of the pseudo terminal is then made available to the @@ -6499,6 +6883,13 @@ or change their color depending on the virtual console you're on. See Documentation/VGA-softcursor.txt for more information. +Acorn's ADFS filesystem support (read only) (EXPERIMENTAL) +CONFIG_ADFS_FS + The Advanced Disk File System is the filesystem used on floppy and + hard disks by Acorn Systems. Currently in development, as a read- + only driver for hard disks. These should be the first partition + (eg. /dev/[sh]d?1) on each of your drives. If unsure, say N. + Standard/generic serial support CONFIG_SERIAL This selects whether you want to include the driver for the standard @@ -6516,8 +6907,12 @@ be lost when kerneld automatically unloads the driver. This limitation may be lifted in the future.] - BTW: If you have a mouseman serial mouse which is not recognized by + BTW1: If you have a mouseman serial mouse which is not recognized by the X window system, try running gpm first. + + BTW2: If you intend to connect a so-called Winmodem to your + machine's serial port, forget it. These modems require proprietary + drivers which are only available under Windows. Most people will say Y or M here, so that they can use serial mice, modems and similar devices connecting to the standard serial ports. @@ -6586,7 +6981,7 @@ Specialix IO8+ card support CONFIG_SPECIALIX - This is a driver for the Specialix IO8+ multiport card, that give + This is a driver for the Specialix IO8+ multiport card which gives you many serial ports. You would need something like this to connect more than two modems to your Linux box, for instance in order to become a BBS. @@ -6598,9 +6993,9 @@ Specialix DTR/RTS pin is RTS CONFIG_SPECIALIX_RTSCTS - The Specialix card can only support either RTS or DTR. When you say + The Specialix card can only support either RTS or DTR. If you say N here, the driver will use the pin as "DTR" when the tty is in - software handshake mode. When you say Y here or hardware handshake + software handshake mode. If you say Y here or hardware handshake is on, it will always be RTS. Read the file Documentation/specialix.txt for more information. @@ -7168,7 +7563,7 @@ MTRR control and configuration CONFIG_MTRR - On Intel Pentium Pro/Pentium II systems the Memory Type Range + On Intel Pentium Pro and Pentium II systems the Memory Type Range Registers (MTRRs) may be used to control processor access to memory ranges. This is most useful when you have a video (VGA) card on a PCI or AGP bus. Enabling write-combining allows bus write transfers @@ -7179,12 +7574,16 @@ your MTRRs. Typically the X server should use this. This should have a reasonably generic interface so that similar control registers on other processors can be easily supported. - This option also fixes a problem with buggy SMP BIOSes which only + + Saying Y here also fixes a problem with buggy SMP BIOSes which only set the MTRRs for the boot CPU and not the secondary CPUs. This can lead to all sorts of problems. - Compiling this as a module is not available because the BIOS fix - needs to be done early in the boot sequence, otherwise your machine - could lock up. + + In general you should compile this into the kernel, rather than as a + loadable module, because the BIOS fix needs to be done early in the + boot sequence. If you compile this as a module, the BIOS fix will be + delayed until when you load the module. You do this at your own risk. + See Documentation/mtrr.txt for more information. Main CPU frequency, only for DEC alpha machine @@ -7242,11 +7641,12 @@ 3) passing the "floppy=nodma" option to the kernel 4) passing the "mem=4M" option to the kernel (thereby disabling all but the first 4M of RAM) - 5) reading the sig11 FAQ at http://www.bitwizard.nl/sig11/ - 6) disabling the cache from your BIOS settings - 7) installing a better fan - 8) exchanging RAM chips - 9) exchanging the motherboard. + 5) making sure that the CPU is not over clocked. + 6) reading the sig11 FAQ at http://www.bitwizard.nl/sig11/ + 7) disabling the cache from your BIOS settings + 8) installing a better fan + 9) exchanging RAM chips + 10) exchanging the motherboard. Ignore USER SUSPEND CONFIG_APM_IGNORE_USER_SUSPEND @@ -7457,6 +7857,17 @@ The module will be called nvram.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. +Atomwide Serial Support +CONFIG_ATOMWIDE_SERIAL + If you have an Atomwide Serial card for an Acorn system, say Y to + this option. The driver can handle 1, 2, or 3 port cards. + If unsure, say N + +The Serial Port Dual Serial Port +CONFIG_DUALSP_SERIAL + If you have the Serial Port's dual serial card for an Acorn system, + say Y to this option. If unsure, say N + PC joystick support CONFIG_JOYSTICK If you have a PC compatible analog or digital joystick, you can say @@ -7509,11 +7920,12 @@ I'm told that even without a sound card, you can make your computer say more than an occasional beep, by programming the PC speaker. Kernel patches and programs to do that are in the pcsndrv package on - sunsite.unc.edu:/pub/Linux/kernel/patches/console/. + ftp://sunsite.unc.edu/pub/Linux/kernel/patches/console/ and in the + pcsp patch at ftp://dwmw2.robinson.cam.ac.uk/pub/kernel/ . Support for Aztech Sound Galaxy (non-Pnp) cards CONFIG_SOUND_SGALAXY - This module initialises the older non Plug and Play sound galaxy cards + This module initializes the older non Plug and Play sound galaxy cards from Aztech. It supports the Waverider Pro 32 - 3D and the Galaxy Washington 16. @@ -7548,12 +7960,12 @@ these cards may cause trouble (I don't currently know of any such cards, however). If unsure, say Y. -Loopback MIDI device support -CONFIG_VMIDI +#Loopback MIDI device support +#CONFIG_SOUND_VMIDI ### ### somebody please fill this in. ### - +# Gravis Ultrasound support CONFIG_SOUND_GUS Say Y here for any type of Gravis Ultrasound card, including @@ -7583,6 +7995,12 @@ card based on the PSS chipset (AD1848 codec + ADSP-2115 DSP chip + Echo ESC614 ASIC CHIP). +#Enable PSS mixer (Beethoven ADSP-16 and other compatible) +#CONFIG_PSS_MIXER +### +### Don't know what this is +### +# Have DSPxxx.LD firmware file CONFIG_PSS_HAVE_BOOT If you want to emulate the Sound Blaster card and you have a DSPxxx.LD @@ -7671,8 +8089,9 @@ Support for Crystal CS4232 based (PnP) cards CONFIG_SOUND_CS4232 Say Y here if you have a card based on the Crystal CS4232 chip set, - which use its own Plug and Play protocol. See Documentation/sound/CS4232 - for more information on configuring this card. + which uses its own Plug and Play protocol. See + Documentation/sound/CS4232 for more information on configuring this + card. Support for Turtle Beach Wave Front (Maui, Tropez) synthesizers CONFIG_SOUND_MAUI @@ -7689,6 +8108,43 @@ CONFIG_MAUI_BOOT_FILE Enter the full pathname of your OSWF.MOT file, starting from /. +Support for Turtle Beach MultiSound Classic, Tahiti, Monterey +CONFIG_SOUND_MSNDCLAS + Say M here if you have a Turtle Beach MultiSound Classic, Tahiti or + Monterey (not for the Pinnacle or Fiji). See + Documentation/sound/MultiSound for important information about this + driver. + +Full pathname of MSNDINIT.BIN firmware file +CONFIG_MSNDCLAS_INIT_FILE + The MultiSound cards have two firmware files which are required for + operation, and are not currently included. These files can be + obtained from Turtle Beach. + +Full pathname of MSNDPERM.BIN firmware file +CONFIG_MSNDCLAS_PERM_FILE + The MultiSound cards have two firmware files which are required for + operation, and are not currently included. These files can be + obtained from Turtle Beach. + +Support for Turtle Beach MultiSound Pinnacle, Fiji +CONFIG_SOUND_MSNDPIN + Say M here if you have a Turtle Beach MultiSound Pinnacle or Fiji. + See Documentation/sound/MultiSound for important information about + this driver. + +Full pathname of PNDSPINI.BIN firmware file +CONFIG_MSNDPIN_INIT_FILE + The MultiSound cards have two firmware files which are required for + operation, and are not currently included. These files can be + obtained from Turtle Beach. + +Full pathname of PNDSPERM.BIN firmware file +CONFIG_MSNDPIN_PERM_FILE + The MultiSound cards have two firmware files which are required for + operation, and are not currently included. These files can be + obtained from Turtle Beach. + /dev/dsp and /dev/audio support CONFIG_SOUND_AUDIO Answering N disables /dev/dsp and /dev/audio, the A/D and D/A @@ -7717,11 +8173,6 @@ affect the kernel; saying Y will simply cause this configure script to present you with more options. If unsure, say Y. -SB32/AWE support -CONFIG_AWE32_SYNTH - Say Y here if you have a SB32 or SB AWE soundcard. See - drivers/sound/lowlevel/README.awe for more info. - ACI mixer (miroPCM12) CONFIG_ACI_MIXER Audio Command Interface (ACI) driver. ACI is a protocol used to @@ -8167,9 +8618,12 @@ Macintosh support CONFIG_MAC - This option enables support for the Apple Macintosh series of computers - (yes, there is experimental support now, at least for part of the series). - Say N unless you're willing to code the remaining necessary support. ;) + This option enables support for the Apple Macintosh series of + computers (yes, there is experimental support now, at least for part + of the series). + + Say N unless you're willing to code the remaining necessary support. + ;) # CONFIG_APOLLO, etc. coming soon (?) @@ -8729,11 +9183,43 @@ from the running kernel whenever you want). If you want to compile it as a module, say M here and read Documentation/modules.txt. +CPU Optimisation +CONFIG_CPU_ARM2 + This selects the processor type of your CPU. This is only used to + determine C compiler optimisation options, and can affect the + compatability of the kernel on other processors. If you specify + ARM6, the kernel should work on all 32-bit processors. If you + specify ARM2, ARM250 or ARM3, it should work on all 26-bit + processors. If you're not sure, set it to "None". + +ARM System type +CONFIG_ARCH_ARC + This selects what ARM system you wish to build the kernel for. It + also selects to some extent the CPU type. If you are unsure what + to set this option to, please consult any information supplied with + your system. + +Build Tools Selection +CONFIG_BINUTILS_NEW + Say Y here if you're using GCC 2.8.1/EGCS with a binutils version >= 2.8.1 + to compile the kernel. Otherwise, say N. + +Compile kernel with frame pointer +CONFIG_FRAME_POINTER + In order to give useful debugging/error results, say Y here, otherwise + say N. + +VIDC Sound +CONFIG_VIDC_SOUND + Say 'Y' here for ARM systems with the VIDC video controller and 16-bit + Linear sound DACs. If unsure, say N. + # # A couple of things I keep forgetting: -# capitalize: DMA, Internet, Intel, IRQ, Linux, NetWare, NFS, PCI, SCSI -# two words: hard drive, hard disk, sound card -# other: it's safe to save; daemon +# capitalize: Appletalk, Ethernet, DMA, FTP, Internet, Intel, IRQ, +# Linux, NetWare, NFS, PCI, SCSI +# two words: hard drive, hard disk, sound card +# other: it's safe to save; daemon # # This is used by Emacs' spell checker ispell.el: # @@ -8753,7 +9239,7 @@ # LocalWords: buslogic DMA DPT ATT eata dma PIO UltraStor fdomain umsdos ext # LocalWords: QLOGIC qlogic TMC seagate Trantor ultrastor FASST wd NETDEVICES # LocalWords: unix BBS linux nullmodem CSLIP PLIP Kirch's LDP CSlip SL SCC IRQ -# LocalWords: Turbo Laplink plip NCSA ReQuest IRQs EQL SMC AMD PCnet NE +# LocalWords: Turbo Laplink plip NCSA port's ReQuest IRQs EQL SMC AMD PCnet NE # LocalWords: COM ELPLUS Com EtherLinkIII VLB Arcnet arcnet Cabletron DEPCA DE # LocalWords: depca EtherWorks EWRK ewrk SEEQ EtherExpressPro EEXPRESS NI xxx # LocalWords: EtherExpress WaveLAN wavelan PCLAN HPLAN VG SK Ansel Xen de ZNET @@ -8774,7 +9260,7 @@ # LocalWords: chipset FB multicast MROUTE appletalk ifconfig IBMTR multiport # LocalWords: Multisession STALDRV EasyIO EC EasyConnection ISTALLION ONboard # LocalWords: Brumby pci TNC cis ohio faq usenet NETLINK dev hydra ca Tyne mem -# LocalWords: carleton Deskstation DECstation SUNFD JENSEN Noname SLiRP +# LocalWords: carleton Deskstation DECstation SUNFD JENSEN Noname XXXM SLiRP # LocalWords: pppd Zilog ZS SRM bootloader ez mainmenu rarp ipfwadm paride pcd # LocalWords: RTNETLINK mknod xos MTU lwared Macs mac netatalk macs cs Wolff # LocalWords: dartmouth flowerpt MultiMaster FlashPoint tudelft etherexpress @@ -8796,10 +9282,10 @@ # LocalWords: ipppd syncppp RFC MPP VJ downloaded icn NICCY Creatix shmem ufr # LocalWords: ibp md ARCnet ether encap NDIS arcether ODI Amigas AmiTCP NetBSD # LocalWords: initrd tue util DES funet des OnNet BIOSP smc Travan Iomega CMS -# LocalWords: FC DC dc PPA ppa RNFS FMV Fujitsu ARPD arpd loran layes +# LocalWords: FC DC dc PPA IOMEGA's ppa RNFS FMV Fujitsu ARPD arpd loran layes # LocalWords: FRAD indiana framerelay DLCI DCLIs Sangoma SDLA mrouted sync sec # LocalWords: Starmode Metricom MosquitoNet mosquitonet kbit nfsroot Digiboard -# LocalWords: DIGI Xe Xeve digiboard UMISC touchscreens mtu HBAs MEX +# LocalWords: DIGI Xe Xeve digiboard UMISC touchscreens mtu ethernets HBAs MEX # LocalWords: Shifflett netcom js jshiffle WIC DECchip ELCP EtherPower dst RTC # LocalWords: rtc SMP lp Digi Intl RightSwitch DGRS dgrs AFFS Amiga UFS SDL AP # LocalWords: Solaris RISCom riscom syncPPP PCBIT pcbit sparc anu au artoo ufs @@ -8808,7 +9294,7 @@ # LocalWords: Bernd informatik rwth aachen uae affs multihosting bytecode java # LocalWords: applets applet JDK ncsa cabi SNI Alphatronix readme LANs scarab # LocalWords: winsock RNIS caltech OSPF honour Honouring Mbit Localtalk DEFRAG -# LocalWords: download Packetwin Baycom baycom interwork ascii JNT +# LocalWords: localtalk download Packetwin Baycom baycom interwork ascii JNT # LocalWords: Camtec proxying indyramp defragment defragmented UDP FAS FASXX # LocalWords: FastSCSI SIO FDC qlogicfas QLogic qlogicisp setbaycom ife ee LJ # LocalWords: ethz ch Travelmates ProAudioSpectrum ProAudio SoundMan SB SBPro @@ -8851,7 +9337,7 @@ # LocalWords: smp HiSax SiemensChipSet Siemens AVM Elsa ITK hisax PCC MICROR # LocalWords: Mircolink EURO DSS Spellcaster BRI sc spellcast Digiboards GPIO # LocalWords: SYMBIOS COMPAT SDMS rev ASUS Tekram HX VX API ibmmcascsi ASY asy -# LocalWords: loader's PCnetPCI automounter AUTOFS amd autofs VT Gallant's PnP +# LocalWords: loader's PCnetPCI automounter AUTOFS amd autofs VT Gallant's Pnp # LocalWords: AEDSP aedsp enskip tik Sysctl sysctl PARPORT parport pnp IDs EPP # LocalWords: Autoprobe bart patrickr HDLS READBACK AB usr DAMA DS SparQ aten # LocalWords: Symbios PCscsi tmscsim RoamAbout GHz Hinds' contrib mathematik @@ -8904,4 +9390,12 @@ # LocalWords: mwave OLDCARD isdnloop linklevel loopctrl Eicon Diehl DIEHLDIVA # LocalWords: ASUSCOM AsusCom TELEINT semiactiv Sedlbauer Sportster TA MIC ITH # LocalWords: NETjet NetJet Niccy Neuhaus sparcs AOC AOCD AOCE Microlink SAA -# LocalWords: teletext WinTV saa iproute tc +# LocalWords: teletext WinTV saa iproute tc Quadra Performa PowerBook tor AUN +# LocalWords: setserial compsoc steve Econet econet AUNUDP psched TEQL TLE CLS +# LocalWords: teql FW Ingres TwistedPair MTRR MTRRs mtrr cfs crypto TD ktti KT +# LocalWords: PHd ICS ipchains adelaide rustcorp syslog epp Cumana +# LocalWords: AcornSCSI EcoSCSI EESOX EESOXSCSI Powertec POWERTECSCSI dec SF +# LocalWords: RadioReveal gatekeeper aimslab aztech FMI sf fmi RTL rtl cesdis +# LocalWords: Yellowfin gsfc nasa gov yellowfin pcnet Mylex LNE lne EtherH hs +# LocalWords: EBSA chattr RiscOS Winmodem AGP Atomwide DUALSP pcsp robinson +# LocalWords: SGALAXY Waverider DSPxxx TRXPRO AudioTrix OSWF MOT diff -u --recursive --new-file v2.1.105/linux/Documentation/filesystems/isofs.txt linux/Documentation/filesystems/isofs.txt --- v2.1.105/linux/Documentation/filesystems/isofs.txt Thu Feb 12 20:56:03 1998 +++ linux/Documentation/filesystems/isofs.txt Sat Jun 13 13:39:15 1998 @@ -21,7 +21,8 @@ check=strict Matches only filenames with the exact same case cruft Try to handle badly formatted CDs. map=off Do not map non-rockridge filenames to lowercase - map=normal Map rockridge filenames to lowercase + map=normal Map non-rockridge filenames to lowecase + map=acorn As map=normal but also apply Acorn extensions if present mode=xxx Sets the permissions on files to xxx nojoliet Ignore Joliet extensions if they are present. norock Ignore rockridge extensions if they are present. diff -u --recursive --new-file v2.1.105/linux/Documentation/paride.txt linux/Documentation/paride.txt --- v2.1.105/linux/Documentation/paride.txt Sun Jun 7 11:16:26 1998 +++ linux/Documentation/paride.txt Sat Jun 13 12:08:19 1998 @@ -44,6 +44,7 @@ Imation Superdisk LS-120 FreeCom Power CD Hewlett-Packard 5GB tape drive + Hewlett-Packard 7100 and 7200 CD-RW drives as well as most of the clone and no-name products on the market. @@ -57,8 +58,9 @@ pcd ATAPI CD-ROM pf ATAPI disk pt ATAPI tape + pg ATAPI generic -(Support for ATAPI CD-R and CD-RW drives is in the design phase.) +(Currently, the pg driver is only used with CD-R drives). The high-level drivers function according to the relevant standards. The third component of PARIDE is a set of low-level protocol drivers @@ -72,7 +74,8 @@ dstr DataStor EP-2000 (TW) epat Shuttle EPAT (UK) epia Shuttle EPIA (UK) - fit2 FIT TD-2000 + fit2 FIT TD-2000 (US) + fit3 FIT TD-3000 (US) frpw Freecom Power (DE) kbic KingByte KBIC-951A and KBIC-971A (TW) ktti KT Technology PHd adapter (SG) @@ -111,6 +114,7 @@ Avatar Shark pd epat FreeCom CD-ROM pcd frpw Hewlett-Packard 5GB Tape pt epat + Hewlett-Packard 7100/7200 pg epat 2.1 Configuring built-in drivers @@ -258,6 +262,7 @@ for u in 0 1 2 3 ; do mkdev pf$u b 47 $u ; done for u in 0 1 2 3 ; do mkdev pt$u c 96 $u ; done for u in 0 1 2 3 ; do mkdev npt$u c 96 $[ $u + 128 ] ; done +for u in 0 1 2 3 ; do mkdev pg$u c 97 $u ; done # # end of mkd @@ -285,6 +290,11 @@ mkdosfs /dev/pf0 mount /dev/pf0 /mnt +2.4 Using the pg driver + +The pg driver can be used in conjunction with the cdrecord program +to create CD-ROMs. For more information, and the required patches +to cdrecord, please visit http://www.torque.net/parport/cdr.html . 3. Troubleshooting @@ -333,6 +343,6 @@ You might also find some useful information on the linux-parport web pages (although they are not always up to date) at - http://www.torque.net/linux-pp.html + http://www.torque.net/parport/ diff -u --recursive --new-file v2.1.105/linux/Documentation/sound/ALS007 linux/Documentation/sound/ALS007 --- v2.1.105/linux/Documentation/sound/ALS007 Wed Dec 31 16:00:00 1969 +++ linux/Documentation/sound/ALS007 Sat Jun 13 10:23:41 1998 @@ -0,0 +1,40 @@ +ALS-007 based soundcards +======================== + +Support for soundcards based around the Avance Logic ALS-007 chip is +included. The ALS-007 is a single chip PnP sound solution which is mostly +hardware compatible with the Sound Blaster 16 card, with most differences +occuring in the use of the mixer registers. For this reason the ALS-007 +code is integrated as part of the Sound Blaster 16 driver (adding only 800 +bytes to the SB16 driver). + +To use an ALS-007 soundcard under Linux, enable the following options in the +sound configuration section of the kernel config: + - 100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support + - FM synthesizer (YM3812/OPL-3) support +Since the ALS-007 is a PnP card, the sound driver probably should be +compiled as a module, with the isapnptools used to wake up the soundcard. +Set the "I/O base for SB", "Sound Blaster IRQ" and "Sound Blaster DMA" (8 bit - +either 0, 1 or 3) to the values used in your particular installation (they +should match the values used to configure the card using isapnp). The +ALS-007 does NOT implement 16 bit DMA, so the "Sound Blaster 16 bit DMA" +should be set to -1. If you wish to use the externel MPU-401 interface on +the card, "MPU401 I/O base of SB16" and "SB MPU401 IRQ" should be set to +the appropriate values for your installation. (Note that the ALS-007 +requires a separate IRQ for the MPU-401, so don't specify -1 here). (Note +that the base port of the internal FM synth is fixed at 0x388 on the ALS007; +in any case the FM synth location is not setable in the kernel config). + +The resulting sound driver will provide the following capabilities: + - 8 and 16 bit audio playback + - 8 and 16 bit audio recording + - Software selection of record source (line in, CD, FM, mic, master) + - Record and playback of midi data via the external MPU-401 + - Playback of midi data using inbuilt FM synthesizer + - Control of the ALS-007 mixer via any OSS-compatible mixer programs. + Controls available are Master (L&R), Line in (L&R), CD (L&R), + DSP/PCM/audio out (L&R), FM (L&R) and Mic in (mono). + +Jonathan Woithe +jwoithe@physics.adelaide.edu.au +30 March 1998 diff -u --recursive --new-file v2.1.105/linux/Documentation/sound/AWE32 linux/Documentation/sound/AWE32 --- v2.1.105/linux/Documentation/sound/AWE32 Sat May 2 14:19:52 1998 +++ linux/Documentation/sound/AWE32 Sat Jun 13 12:10:30 1998 @@ -5,7 +5,7 @@ be issued (of course with the suitable values for the parameters) after PNP setup: -insmod sound.o +modprobe sound.o insmod uart401.o insmod sb.o io=0x220 irq=5 dma=1 dma16=5 mpu_io=0x330 insmod awe_wave.o @@ -59,5 +59,6 @@ rmmod sb rmmod uart401 rmmod sound +rmmod soundcore ----- diff -u --recursive --new-file v2.1.105/linux/Documentation/sound/MultiSound linux/Documentation/sound/MultiSound --- v2.1.105/linux/Documentation/sound/MultiSound Wed Dec 31 16:00:00 1969 +++ linux/Documentation/sound/MultiSound Sat Jun 13 10:23:41 1998 @@ -0,0 +1,146 @@ +Getting Firmware +~~~~~~~~~~~~~~~~ + +See the end of this document on how to obtain and create the necessary +firmware files. + + +Supported Features +~~~~~~~~~~~~~~~~~~ + +Currently digital audio and mixer functionality is supported. (memory +mapped digital audio is not yet supported). MultiSound support is +fully modularized, and can only be used as modules: + +msnd - MultiSound base (requires soundcore) +msnd_classic - Base audio/mixer support for Classic, Monetery and + Tahiti cards +msnd_pinnacle - Base audio/mixer support for Pinnacle and Fiji cards + + +Important Notes - Read Before Using +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* The firmware files are not included (may change in future). You +must obtain these images from Turtle Beach (they are included in the +MultiSound Development Kits), and place them in /etc/sound for +example, and give the full paths in the Linux configuration. Please +note these files must be binary files, not assember. + +* You need the following information to use this driver: the card's +I/O base (i.e. 0x250), the IRQ (i.e. 5), and the shared memory area +(i.e. 0xd8000). + +* Probing is not currently implemented, and only the msnd_classic +driver will actually program the card's IRQ and SMA locations; the +msnd_pinnacle is primarily for use with the card in PnP mode, however +it should work if you know what the card's resource values are (this +will change in the future). + +* Note the Turtle Beach Pinnacle card contains a Kurzweil MA-1 +synthesizer with an MPU compatible interface, which should work with +the mpu401 module. You must know the resource values of the MA-1. + + +Examples +~~~~~~~~ + +* If you have a MultiSound Classic/Monterey/Tahiti: + +insmod soundcore +insmod msnd +insmod msnd_classic io=0x290 irq=7 mem=0xd0000 + +* If you have a MultiSound Pinnacle: + +insmod soundcore +insmod msnd +insmod msnd_pinnacle io=0x210 irq=5 mem=0xd8000 + +* To use the MPU-compatible Kurzweil synth on the Pinnacle, add the +following: + +insmod sound +insmod mpu401 io=0x330 irq=9 + + +msnd_classic, msnd_pinnacle Required Options +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If the following options are not given, the module will not load. +Examine the kernel message log for informative error messages. +WARNING--probing isn't supported so try to make sure you have the +correct shared memory area, otherwise you may experience problems. + +io I/O base of DSP, e.g. io=0x210 +irq IRQ number, e.g. irq=5 +mem Shared memory area, e.g. mem=0xd8000 + + +msnd_classic, msnd_pinnacle Additional Options +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +fifosize The digital audio FIFOs, in kilobytes. The default is + 64kB (two FIFOs are allocated, so this uses up 128kB). + +calibrate_signal Setting this to one calibrates the ADCs to the + signal, zero calibrates to the card (defaults + to zero). + + +Creating and Obtaining Firmware +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + For the Classic/Tahiti/Monterey + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Download to /tmp and unzip the following file from Turtle Beach: + + ftp://ftp.tbeach.com/pub/tbs/pinn/msndvkit.zip + +When unzipped, unzip the file named MsndFiles.zip. Then copy the +following firmware files to /etc/sound (note the file renaming): + + cp DSPCODE/MSNDINIT.BIN /etc/sound/msndinit.bin + cp DSPCODE/MSNDPERM.REB /etc/sound/msndperm.bin + +When configuring the Linux kernel, specify /etc/sound/msndinit.bin and +/etc/sound/msndperm.bin for the two firmware files. + + + For the Pinnacle/Fiji + ~~~~~~~~~~~~~~~~~~~~~ + +Download to /tmp and unzip the following file from Turtle Beach (be +sure to use the entire URL; some have had trouble navigating to the +URL): + + ftp://ftp.tbeach.com/oldpub/tbs/pinn/pnddk100.zip + +Put the following lines into a file named conv.l (between the start +and end lines): + +-- conv.l start -- +%% +[ \n\t,\r] ; +\;.* ; +DB ; +[0-9A-Fa-f]+H { int n; sscanf(yytext, "%xH", &n); printf("%c", n); } +-- conv.l end -- + +Then, compile the conv program with GNU make with the following +command: + + make LEX=flex LOADLIBES=-lfl conv + +This should give you an executable named conv. Now, we create the +binary firmware files by doing the following conversion (assuming the +archive unpacked into a directory named PINNDDK): + + ./conv < PINNDDK/dspcode/pndspini.asm > /etc/sound/pndspini.bin + ./conv < PINNDDK/dspcode/pndsperm.asm > /etc/sound/pndsperm.bin + +The conv (and conv.l) program is not needed after conversion and can +be safely deleted. Then, when configuring the Linux kernel, specify +/etc/sound/pndspini.bin and /etc/sound/pndsperm.bin for the two +firmware files. diff -u --recursive --new-file v2.1.105/linux/Documentation/sound/Multisound linux/Documentation/sound/Multisound --- v2.1.105/linux/Documentation/sound/Multisound Wed Dec 31 16:00:00 1969 +++ linux/Documentation/sound/Multisound Sat Jun 13 11:36:52 1998 @@ -0,0 +1,4 @@ +Turtle Beach Multisound support is not yet integrated. If you'd like +to test it or help out in finishing the module please see + + http://www.rpi.edu/~veliaa/pinlinux.html diff -u --recursive --new-file v2.1.105/linux/Documentation/sound/Soundblaster linux/Documentation/sound/Soundblaster --- v2.1.105/linux/Documentation/sound/Soundblaster Sun Jun 7 11:16:26 1998 +++ linux/Documentation/sound/Soundblaster Sat Jun 13 10:23:52 1998 @@ -32,7 +32,11 @@ to warm boot from DOS/Windows with the required firmware loaded under this OS. IBM are being difficult about documenting how to load this firmware. -Advance Logic ALS007 +Avance Logic ALS007 -This card isn't currently supported. I have patches to merge however that -add limited support. +This card is supported; see the separate file ALS007 for full details. + +Avance Logic ALS100 + +This card is supported; setup should be as for a standard Sound Blaster 16. +The driver will identify the audio device as a "Sound Blaster 16 (ALS-100)". diff -u --recursive --new-file v2.1.105/linux/MAINTAINERS linux/MAINTAINERS --- v2.1.105/linux/MAINTAINERS Sun Jun 7 11:16:26 1998 +++ linux/MAINTAINERS Sat Jun 13 12:59:16 1998 @@ -277,7 +277,7 @@ HIGH-SPEED SCC DRIVER FOR AX.25 P: Klaus Kudielka -M: oe1kib@oe1xtu.ampr.org +M: oe1kib@oe1kib.ampr.org L: linux-hams@vger.rutgers.edu S: Maintained @@ -304,6 +304,12 @@ L: linux-kernel@vger.rutgers.edu S: Maintained +IP FIREWALL +P: Paul Russell +M: Paul.Russell@rustcorp.com.au +W: http://www.adelaide.net.au/~rustcorp/ipfwchains/ipfwchains.html +S: Maintained + IPX/SPX NETWORK LAYER P: Jay Schulist M: Jay Schulist @@ -379,6 +385,11 @@ L: linux-kernel@vger.rutgers.edu S: Maintained +MULTISOUND SOUND DRIVER +P: Andrew Veliath +M: andrewtv@usa.net +S: Maintained + NCP FILESYSTEM: P: Petr Vandrovec M: vandrove@vc.cvut.cz @@ -539,6 +550,12 @@ L: linux-kernel@vger.rutgers.edu ? S: Supported +SPX NETWORK LAYER +P: Jay Schulist +M: Jay.Schulist@spacs.k12.wi.us +L: linux-net@vger.rutgers.edu +S: Supported + STALLION TECHNOLOGIES MULTIPORT SERIAL BOARDS P: Greg Ungerer M: support@stallion.oz.au @@ -571,8 +588,9 @@ TOKEN-RING NETWORK DRIVER P: Paul Norton -M: pnorton@cts.com +M: p.norton@computer.org L: linux-net@vger.rutgers.edu +L: linux-tr@emissary.aus-etc.com S: Maintained U14-34F SCSI DRIVER @@ -629,6 +647,19 @@ W: http://poboxes.com/jreuter/ W: http://qsl.net/dl1bke/ L: linux-hams@vger.rutgers.edu +S: Maintained + +ARM PORT +P: Russell King +M: linux@arm.uk.linux.org +L: linux-arm@vger.rutgers.edu +L: arm-linux@tardis.ed.ac.uk +W: http://www.arm.uk.linux.org/~rmk/armlinux.html +S: Maintained + +ARM MFM AND FLOPPY DRIVERS +P: Dave Gilbert +M: linux@treblig.org S: Maintained REST: diff -u --recursive --new-file v2.1.105/linux/Makefile linux/Makefile --- v2.1.105/linux/Makefile Tue Jun 9 11:57:28 1998 +++ linux/Makefile Sat Jun 13 13:33:50 1998 @@ -1,8 +1,8 @@ VERSION = 2 PATCHLEVEL = 1 -SUBLEVEL = 105 +SUBLEVEL = 106 -ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/) +ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm*/arm/ -e s/sa110/arm/) # # For SMP kernels, set this. We don't want to have this in the config file diff -u --recursive --new-file v2.1.105/linux/README linux/README --- v2.1.105/linux/README Sun Jun 7 11:16:26 1998 +++ linux/README Sat Jun 13 12:59:16 1998 @@ -39,8 +39,8 @@ ON WHAT HARDWARE DOES IT RUN? Linux was first developed for 386/486-based PCs. These days it also - runs on DEC Alphas, SUN Sparcs, M68000 machines (like Atari and Amiga), - MIPS, PowerPC, and others. + runs on ARMs, DEC Alphas, SUN Sparcs, M68000 machines (like Atari and + Amiga), MIPS and PowerPC, and others. DOCUMENTATION: diff -u --recursive --new-file v2.1.105/linux/Rules.make linux/Rules.make --- v2.1.105/linux/Rules.make Tue Jun 9 11:57:28 1998 +++ linux/Rules.make Tue Jun 9 01:40:49 1998 @@ -189,9 +189,14 @@ endif $(MODINCL)/%.ver: %.c - $(CC) $(CFLAGS) -E -D__GENKSYMS__ $<\ - | $(GENKSYMS) $(genksyms_smp_prefix) -k $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) > $@.tmp - mv $@.tmp $@ + @if [ ! -r $(MODINCL)/$*.stamp -o $(MODINCL)/$*.stamp -ot $< ]; then \ + echo '$(CC) $(CFLAGS) -E -D__GENKSYMS__ $<'; \ + echo '| $(GENKSYMS) $(genksyms_smp_prefix) -k $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) > $@.tmp'; \ + $(CC) $(CFLAGS) -E -D__GENKSYMS__ $< \ + | $(GENKSYMS) $(genksyms_smp_prefix) -k $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) > $@.tmp; \ + if [ -r $@ ] && cmp -s $@ $@.tmp; then echo $@ is unchanged; rm -f $@.tmp; \ + else echo mv $@.tmp $@; mv -f $@.tmp $@; fi; \ + fi; touch $(MODINCL)/$*.stamp $(addprefix $(MODINCL)/,$(SYMTAB_OBJS:.o=.ver)): $(TOPDIR)/include/linux/autoconf.h diff -u --recursive --new-file v2.1.105/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S --- v2.1.105/linux/arch/alpha/kernel/entry.S Sun Jun 7 11:16:26 1998 +++ linux/arch/alpha/kernel/entry.S Tue Jun 9 13:34:01 1998 @@ -924,7 +924,7 @@ .quad alpha_ni_syscall .quad alpha_ni_syscall /* 110 */ .quad sys_sigsuspend - .quad sys_ni_syscall + .quad osf_sigstack .quad sys_recvmsg .quad sys_sendmsg .quad alpha_ni_syscall /* 115 */ @@ -1047,7 +1047,7 @@ .quad alpha_ni_syscall .quad sys_getpgid .quad sys_getsid - .quad alpha_ni_syscall /* 235 */ + .quad sys_sigaltstack /* 235 */ .quad alpha_ni_syscall .quad alpha_ni_syscall .quad alpha_ni_syscall @@ -1181,5 +1181,6 @@ .quad sys_wait4 /* 365 */ .quad sys_adjtimex .quad sys_getcwd - .quad sys_ni_syscall - .quad sys_ni_syscall /* 369 */ + .quad sys_capget + .quad sys_capset + .quad sys_ni_syscall /* 370 */ diff -u --recursive --new-file v2.1.105/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c --- v2.1.105/linux/arch/alpha/kernel/osf_sys.c Tue Mar 10 10:03:30 1998 +++ linux/arch/alpha/kernel/osf_sys.c Sat Jun 13 11:36:52 1998 @@ -537,11 +537,15 @@ error = verify_area(VERIFY_WRITE, name, 5 * 32); if (error) goto out; + + down(&uts_sem); copy_to_user(name + 0, system_utsname.sysname, 32); copy_to_user(name + 32, system_utsname.nodename, 32); copy_to_user(name + 64, system_utsname.release, 32); copy_to_user(name + 96, system_utsname.version, 32); copy_to_user(name + 128, system_utsname.machine, 32); + up(&uts_sem); + out: unlock_kernel(); return error; @@ -602,11 +606,13 @@ if (namelen > 32) len = 32; + down(&uts_sem); for (i = 0; i < len; ++i) { - put_user(system_utsname.domainname[i], name + i); + __put_user(system_utsname.domainname[i], name + i); if (system_utsname.domainname[i] == '\0') break; } + up(&uts_sem); out: unlock_kernel(); return error; @@ -743,6 +749,50 @@ return error; } +asmlinkage int osf_sigstack(struct sigstack *uss, struct sigstack *uoss) +{ + unsigned long usp = rdusp(); + unsigned long oss_sp, oss_os; + int error; + + if (uoss) { + oss_sp = current->sas_ss_sp + current->sas_ss_size; + oss_os = on_sig_stack(usp); + } + + if (uss) { + unsigned long ss_sp; + + error = -EFAULT; + if (get_user(ss_sp, &uss->ss_sp)) + goto out; + + /* If the current stack was set with sigaltstack, don't + swap stacks while we are on it. */ + error = -EPERM; + if (current->sas_ss_sp && on_sig_stack(usp)) + goto out; + + /* Since we don't know the extent of the stack, and we don't + track onstack-ness, but rather calculate it, we must + presume a size. Ho hum this interface is lossy. */ + current->sas_ss_sp = ss_sp - SIGSTKSZ; + current->sas_ss_size = SIGSTKSZ; + } + + if (uoss) { + error = -EFAULT; + if (! access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)) + || __put_user(oss_sp, &uoss->ss_sp) + || __put_user(oss_os, &uoss->ss_onstack)) + goto out; + } + + error = 0; +out: + return error; +} + /* * The Linux kernel isn't good at returning values that look * like negative longs (they are mistaken as error values). @@ -799,6 +849,8 @@ printk("sysinfo(%d)", command); goto out; } + + down(&uts_sem); res = sysinfo_table[offset]; len = strlen(res)+1; if (len > count) @@ -807,6 +859,7 @@ err = -EFAULT; else err = 0; + up(&uts_sem); out: unlock_kernel(); return err; diff -u --recursive --new-file v2.1.105/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c --- v2.1.105/linux/arch/alpha/kernel/process.c Wed Apr 1 20:11:47 1998 +++ linux/arch/alpha/kernel/process.c Sat Jun 13 12:48:10 1998 @@ -120,6 +120,7 @@ /* endless idle loop with no priority at all */ current->counter = -100; for (;;) { + check_pgt_cache(); schedule(); } ret = 0; diff -u --recursive --new-file v2.1.105/linux/arch/alpha/kernel/signal.c linux/arch/alpha/kernel/signal.c --- v2.1.105/linux/arch/alpha/kernel/signal.c Fri Jan 30 11:28:05 1998 +++ linux/arch/alpha/kernel/signal.c Tue Jun 9 13:34:01 1998 @@ -203,6 +203,12 @@ } } +asmlinkage int +sys_sigaltstack(const stack_t *uss, stack_t *uoss) +{ + return do_sigaltstack(uss, uoss, rdusp()); +} + /* * Do a signal return; undo the signal stack. */ @@ -225,67 +231,65 @@ #define INSN_LDI_R0 0x201f0000 #define INSN_CALLSYS 0x00000083 - -static void +static long restore_sigcontext(struct sigcontext *sc, struct pt_regs *regs, struct switch_stack *sw) { unsigned long usp; - int i; + long i, err = 0; - __get_user(regs->pc, &sc->sc_pc); + err |= __get_user(regs->pc, &sc->sc_pc); sw->r26 = (unsigned long) ret_from_sys_call; - __get_user(regs->r0, sc->sc_regs+0); - __get_user(regs->r1, sc->sc_regs+1); - __get_user(regs->r2, sc->sc_regs+2); - __get_user(regs->r3, sc->sc_regs+3); - __get_user(regs->r4, sc->sc_regs+4); - __get_user(regs->r5, sc->sc_regs+5); - __get_user(regs->r6, sc->sc_regs+6); - __get_user(regs->r7, sc->sc_regs+7); - __get_user(regs->r8, sc->sc_regs+8); - __get_user(sw->r9, sc->sc_regs+9); - __get_user(sw->r10, sc->sc_regs+10); - __get_user(sw->r11, sc->sc_regs+11); - __get_user(sw->r12, sc->sc_regs+12); - __get_user(sw->r13, sc->sc_regs+13); - __get_user(sw->r14, sc->sc_regs+14); - __get_user(sw->r15, sc->sc_regs+15); - __get_user(regs->r16, sc->sc_regs+16); - __get_user(regs->r17, sc->sc_regs+17); - __get_user(regs->r18, sc->sc_regs+18); - __get_user(regs->r19, sc->sc_regs+19); - __get_user(regs->r20, sc->sc_regs+20); - __get_user(regs->r21, sc->sc_regs+21); - __get_user(regs->r22, sc->sc_regs+22); - __get_user(regs->r23, sc->sc_regs+23); - __get_user(regs->r24, sc->sc_regs+24); - __get_user(regs->r25, sc->sc_regs+25); - __get_user(regs->r26, sc->sc_regs+26); - __get_user(regs->r27, sc->sc_regs+27); - __get_user(regs->r28, sc->sc_regs+28); - __get_user(regs->gp, sc->sc_regs+29); - __get_user(usp, sc->sc_regs+30); + err |= __get_user(regs->r0, sc->sc_regs+0); + err |= __get_user(regs->r1, sc->sc_regs+1); + err |= __get_user(regs->r2, sc->sc_regs+2); + err |= __get_user(regs->r3, sc->sc_regs+3); + err |= __get_user(regs->r4, sc->sc_regs+4); + err |= __get_user(regs->r5, sc->sc_regs+5); + err |= __get_user(regs->r6, sc->sc_regs+6); + err |= __get_user(regs->r7, sc->sc_regs+7); + err |= __get_user(regs->r8, sc->sc_regs+8); + err |= __get_user(sw->r9, sc->sc_regs+9); + err |= __get_user(sw->r10, sc->sc_regs+10); + err |= __get_user(sw->r11, sc->sc_regs+11); + err |= __get_user(sw->r12, sc->sc_regs+12); + err |= __get_user(sw->r13, sc->sc_regs+13); + err |= __get_user(sw->r14, sc->sc_regs+14); + err |= __get_user(sw->r15, sc->sc_regs+15); + err |= __get_user(regs->r16, sc->sc_regs+16); + err |= __get_user(regs->r17, sc->sc_regs+17); + err |= __get_user(regs->r18, sc->sc_regs+18); + err |= __get_user(regs->r19, sc->sc_regs+19); + err |= __get_user(regs->r20, sc->sc_regs+20); + err |= __get_user(regs->r21, sc->sc_regs+21); + err |= __get_user(regs->r22, sc->sc_regs+22); + err |= __get_user(regs->r23, sc->sc_regs+23); + err |= __get_user(regs->r24, sc->sc_regs+24); + err |= __get_user(regs->r25, sc->sc_regs+25); + err |= __get_user(regs->r26, sc->sc_regs+26); + err |= __get_user(regs->r27, sc->sc_regs+27); + err |= __get_user(regs->r28, sc->sc_regs+28); + err |= __get_user(regs->gp, sc->sc_regs+29); + err |= __get_user(usp, sc->sc_regs+30); wrusp(usp); for (i = 0; i < 31; i++) - __get_user(sw->fp[i], sc->sc_fpregs+i); - __get_user(sw->fp[31], &sc->sc_fpcr); + err |= __get_user(sw->fp[i], sc->sc_fpregs+i); + err |= __get_user(sw->fp[31], &sc->sc_fpcr); + + return err; } asmlinkage void do_sigreturn(struct sigframe *frame, struct pt_regs *regs, struct switch_stack *sw) { - unsigned long ps; sigset_t set; /* Verify that it's a good sigcontext before using it */ if (verify_area(VERIFY_READ, frame, sizeof(*frame))) goto give_sigsegv; - if (__get_user(ps, &frame->sc.sc_ps) || ps != 8) - goto give_sigsegv; if (__get_user(set.sig[0], &frame->sc.sc_mask) || (_NSIG_WORDS > 1 && __copy_from_user(&set.sig[1], &frame->extramask, @@ -298,7 +302,8 @@ recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); - restore_sigcontext(&frame->sc, regs, sw); + if (restore_sigcontext(&frame->sc, regs, sw)) + goto give_sigsegv; /* Send SIGTRAP if we're single-stepping: */ if (ptrace_cancel_bpt (current)) @@ -306,22 +311,19 @@ return; give_sigsegv: - lock_kernel(); - do_exit(SIGSEGV); + force_sig(SIGSEGV, current); } asmlinkage void do_rt_sigreturn(struct rt_sigframe *frame, struct pt_regs *regs, struct switch_stack *sw) { - unsigned long ps; sigset_t set; + stack_t st; /* Verify that it's a good sigcontext before using it */ if (verify_area(VERIFY_READ, frame, sizeof(*frame))) goto give_sigsegv; - if (__get_user(ps, &frame->uc.uc_mcontext.sc_ps) || ps != 8) - goto give_sigsegv; if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto give_sigsegv; @@ -331,7 +333,14 @@ recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); - restore_sigcontext(&frame->uc.uc_mcontext, regs, sw); + if (restore_sigcontext(&frame->uc.uc_mcontext, regs, sw)) + goto give_sigsegv; + + if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st))) + goto give_sigsegv; + /* It is more difficult to avoid calling this function than to + call it and ignore errors. */ + do_sigaltstack(&st, NULL, rdusp()); /* Send SIGTRAP if we're single-stepping: */ if (ptrace_cancel_bpt (current)) @@ -339,8 +348,7 @@ return; give_sigsegv: - lock_kernel(); - do_exit(SIGSEGV); + force_sig(SIGSEGV, current); } @@ -348,99 +356,113 @@ * Set up a signal frame. */ -static void +static inline void * +get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) +{ + if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp)) + sp = current->sas_ss_sp + current->sas_ss_size; + + return (void *)((sp - frame_size) & -32ul); +} + +static long setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, struct switch_stack *sw, unsigned long mask, unsigned long sp) { - long i; + long i, err = 0; - __put_user(0, &sc->sc_onstack); - __put_user(mask, &sc->sc_mask); - __put_user(regs->pc, &sc->sc_pc); - __put_user(8, &sc->sc_ps); - - __put_user(regs->r0 , sc->sc_regs+0); - __put_user(regs->r1 , sc->sc_regs+1); - __put_user(regs->r2 , sc->sc_regs+2); - __put_user(regs->r3 , sc->sc_regs+3); - __put_user(regs->r4 , sc->sc_regs+4); - __put_user(regs->r5 , sc->sc_regs+5); - __put_user(regs->r6 , sc->sc_regs+6); - __put_user(regs->r7 , sc->sc_regs+7); - __put_user(regs->r8 , sc->sc_regs+8); - __put_user(sw->r9 , sc->sc_regs+9); - __put_user(sw->r10 , sc->sc_regs+10); - __put_user(sw->r11 , sc->sc_regs+11); - __put_user(sw->r12 , sc->sc_regs+12); - __put_user(sw->r13 , sc->sc_regs+13); - __put_user(sw->r14 , sc->sc_regs+14); - __put_user(sw->r15 , sc->sc_regs+15); - __put_user(regs->r16, sc->sc_regs+16); - __put_user(regs->r17, sc->sc_regs+17); - __put_user(regs->r18, sc->sc_regs+18); - __put_user(regs->r19, sc->sc_regs+19); - __put_user(regs->r20, sc->sc_regs+20); - __put_user(regs->r21, sc->sc_regs+21); - __put_user(regs->r22, sc->sc_regs+22); - __put_user(regs->r23, sc->sc_regs+23); - __put_user(regs->r24, sc->sc_regs+24); - __put_user(regs->r25, sc->sc_regs+25); - __put_user(regs->r26, sc->sc_regs+26); - __put_user(regs->r27, sc->sc_regs+27); - __put_user(regs->r28, sc->sc_regs+28); - __put_user(regs->gp , sc->sc_regs+29); - __put_user(sp, sc->sc_regs+30); - __put_user(0, sc->sc_regs+31); + err |= __put_user(on_sig_stack((unsigned long)sc), &sc->sc_onstack); + err |= __put_user(mask, &sc->sc_mask); + err |= __put_user(regs->pc, &sc->sc_pc); + err |= __put_user(8, &sc->sc_ps); + + err |= __put_user(regs->r0 , sc->sc_regs+0); + err |= __put_user(regs->r1 , sc->sc_regs+1); + err |= __put_user(regs->r2 , sc->sc_regs+2); + err |= __put_user(regs->r3 , sc->sc_regs+3); + err |= __put_user(regs->r4 , sc->sc_regs+4); + err |= __put_user(regs->r5 , sc->sc_regs+5); + err |= __put_user(regs->r6 , sc->sc_regs+6); + err |= __put_user(regs->r7 , sc->sc_regs+7); + err |= __put_user(regs->r8 , sc->sc_regs+8); + err |= __put_user(sw->r9 , sc->sc_regs+9); + err |= __put_user(sw->r10 , sc->sc_regs+10); + err |= __put_user(sw->r11 , sc->sc_regs+11); + err |= __put_user(sw->r12 , sc->sc_regs+12); + err |= __put_user(sw->r13 , sc->sc_regs+13); + err |= __put_user(sw->r14 , sc->sc_regs+14); + err |= __put_user(sw->r15 , sc->sc_regs+15); + err |= __put_user(regs->r16, sc->sc_regs+16); + err |= __put_user(regs->r17, sc->sc_regs+17); + err |= __put_user(regs->r18, sc->sc_regs+18); + err |= __put_user(regs->r19, sc->sc_regs+19); + err |= __put_user(regs->r20, sc->sc_regs+20); + err |= __put_user(regs->r21, sc->sc_regs+21); + err |= __put_user(regs->r22, sc->sc_regs+22); + err |= __put_user(regs->r23, sc->sc_regs+23); + err |= __put_user(regs->r24, sc->sc_regs+24); + err |= __put_user(regs->r25, sc->sc_regs+25); + err |= __put_user(regs->r26, sc->sc_regs+26); + err |= __put_user(regs->r27, sc->sc_regs+27); + err |= __put_user(regs->r28, sc->sc_regs+28); + err |= __put_user(regs->gp , sc->sc_regs+29); + err |= __put_user(sp, sc->sc_regs+30); + err |= __put_user(0, sc->sc_regs+31); for (i = 0; i < 31; i++) - __put_user(sw->fp[i], sc->sc_fpregs+i); - __put_user(0, sc->sc_fpregs+31); - __put_user(sw->fp[31], &sc->sc_fpcr); - - __put_user(regs->trap_a0, &sc->sc_traparg_a0); - __put_user(regs->trap_a1, &sc->sc_traparg_a1); - __put_user(regs->trap_a2, &sc->sc_traparg_a2); + err |= __put_user(sw->fp[i], sc->sc_fpregs+i); + err |= __put_user(0, sc->sc_fpregs+31); + err |= __put_user(sw->fp[31], &sc->sc_fpcr); + + err |= __put_user(regs->trap_a0, &sc->sc_traparg_a0); + err |= __put_user(regs->trap_a1, &sc->sc_traparg_a1); + err |= __put_user(regs->trap_a2, &sc->sc_traparg_a2); + + return err; } static void setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *regs, struct switch_stack * sw) { - unsigned long oldsp; + unsigned long oldsp, r26, err = 0; struct sigframe *frame; oldsp = rdusp(); - frame = (struct sigframe *)((oldsp - sizeof(*frame)) & -32); - - /* XXX: Check here if we would need to switch stacks.. */ + frame = get_sigframe(ka, oldsp, sizeof(*frame)); if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; - setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp); + err |= setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp); if (_NSIG_WORDS > 1) { - __copy_to_user(frame->extramask, &set->sig[1], - sizeof(frame->extramask)); + err |= __copy_to_user(frame->extramask, &set->sig[1], + sizeof(frame->extramask)); } /* Set up to return from userspace. If provided, use a stub already in userspace. */ if (ka->ka_restorer) { - regs->r26 = (unsigned long) ka->ka_restorer; + r26 = (unsigned long) ka->ka_restorer; } else { - __put_user(INSN_MOV_R30_R16, frame->retcode+0); - __put_user(INSN_LDI_R0+__NR_sigreturn, frame->retcode+1); - __put_user(INSN_CALLSYS, frame->retcode+2); + err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0); + err |= __put_user(INSN_LDI_R0+__NR_sigreturn, frame->retcode+1); + err |= __put_user(INSN_CALLSYS, frame->retcode+2); imb(); - regs->r26 = (unsigned long) frame->retcode; + r26 = (unsigned long) frame->retcode; } + /* Check that everything was written properly. */ + if (err) + goto give_sigsegv; + /* "Return" to the handler */ + regs->r26 = r26; regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler; regs->r16 = sig; /* a0: signal number */ regs->r17 = 0; /* a1: exception code */ regs->r18 = (unsigned long) &frame->sc; /* a2: sigcontext pointer */ wrusp((unsigned long) frame); - + #if DEBUG_SIG printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", current->comm, current->pid, frame, regs->pc, regs->r26); @@ -449,47 +471,54 @@ return; give_sigsegv: - lock_kernel(); - do_exit(SIGSEGV); + if (sig == SIGSEGV) + ka->sa.sa_handler = SIG_DFL; + force_sig(SIGSEGV, current); } static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs, struct switch_stack * sw) { - unsigned long oldsp; + unsigned long oldsp, r26, err = 0; struct rt_sigframe *frame; oldsp = rdusp(); - frame = (struct rt_sigframe *)((oldsp - sizeof(*frame)) & -32); - - /* XXX: Check here if we would need to switch stacks.. */ + frame = get_sigframe(ka, oldsp, sizeof(*frame)); if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; - __copy_to_user(&frame->info, info, sizeof(siginfo_t)); + err |= __copy_to_user(&frame->info, info, sizeof(siginfo_t)); - /* Zero all bits of the ucontext besides the sigcontext. */ - __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext)); - - /* Copy in the bits we actually use. */ - __put_user(set->sig[0], &frame->uc.uc_osf_sigmask); - setup_sigcontext(&frame->uc.uc_mcontext, regs, sw, set->sig[0], oldsp); - __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); + /* Create the ucontext. */ + err |= __put_user(0, &frame->uc.uc_flags); + err |= __put_user(0, &frame->uc.uc_link); + err |= __put_user(set->sig[0], &frame->uc.uc_osf_sigmask); + err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); + err |= __put_user(sas_ss_flags(oldsp), &frame->uc.uc_stack.ss_flags); + err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); + err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, sw, + set->sig[0], oldsp); + err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); /* Set up to return from userspace. If provided, use a stub already in userspace. */ if (ka->ka_restorer) { - regs->r26 = (unsigned long) ka->ka_restorer; + r26 = (unsigned long) ka->ka_restorer; } else { - __put_user(INSN_MOV_R30_R16, frame->retcode+0); - __put_user(INSN_LDI_R0+__NR_rt_sigreturn, frame->retcode+1); - __put_user(INSN_CALLSYS, frame->retcode+2); + err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0); + err |= __put_user(INSN_LDI_R0+__NR_rt_sigreturn, + frame->retcode+1); + err |= __put_user(INSN_CALLSYS, frame->retcode+2); imb(); - regs->r26 = (unsigned long) frame->retcode; + r26 = (unsigned long) frame->retcode; } + if (err) + goto give_sigsegv; + /* "Return" to the handler */ + regs->r26 = r26; regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler; regs->r16 = sig; /* a0: signal number */ regs->r17 = (unsigned long) &frame->info; /* a1: siginfo pointer */ @@ -504,8 +533,9 @@ return; give_sigsegv: - lock_kernel(); - do_exit(SIGSEGV); + if (sig == SIGSEGV) + ka->sa.sa_handler = SIG_DFL; + force_sig(SIGSEGV, current); } diff -u --recursive --new-file v2.1.105/linux/arch/alpha/mm/fault.c linux/arch/alpha/mm/fault.c --- v2.1.105/linux/arch/alpha/mm/fault.c Wed Apr 1 20:11:47 1998 +++ linux/arch/alpha/mm/fault.c Tue Jun 9 13:34:23 1998 @@ -114,8 +114,8 @@ (or is suppressed by the PALcode). Support that for older cpu's by ignoring such an instruction. */ if (cause == 0) { - /* No need for get_user.. we know the insn is there. */ - unsigned int insn = *(unsigned int *)regs->pc; + unsigned int insn; + __get_user(insn, (unsigned int *)regs->pc); if ((insn >> 21 & 0x1f) == 0x1f && /* ldq ldl ldt lds ldg ldf ldwu ldbu */ (1ul << (insn >> 26) & 0x30f00001400ul)) { @@ -124,8 +124,8 @@ } } - lock_kernel(); down(&mm->mmap_sem); + lock_kernel(); vma = find_vma(mm, address); if (!vma) goto bad_area; diff -u --recursive --new-file v2.1.105/linux/arch/alpha/mm/init.c linux/arch/alpha/mm/init.c --- v2.1.105/linux/arch/alpha/mm/init.c Wed Apr 1 20:11:47 1998 +++ linux/arch/alpha/mm/init.c Sat Jun 13 12:48:10 1998 @@ -28,6 +28,67 @@ struct thread_struct * original_pcb_ptr; +#ifndef __SMP__ +struct pgtable_cache_struct quicklists; +#endif + +void __bad_pmd(pgd_t *pgd) +{ + printk("Bad pgd in pmd_alloc: %08lx\n", pgd_val(*pgd)); + pgd_set(pgd, BAD_PAGETABLE); +} + +void __bad_pte(pmd_t *pmd) +{ + printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd)); + pmd_set(pmd, (pte_t *) BAD_PAGETABLE); +} + +pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long offset) +{ + pmd_t *pmd; + + pmd = (pmd_t *) __get_free_page(GFP_KERNEL); + if (pgd_none(*pgd)) { + if (pmd) { + clear_page((unsigned long)pmd); + pgd_set(pgd, pmd); + return pmd + offset; + } + pgd_set(pgd, BAD_PAGETABLE); + return NULL; + } + free_page((unsigned long)pmd); + if (pgd_bad(*pgd)) { + __bad_pmd(pgd); + return NULL; + } + return (pmd_t *) pgd_page(*pgd) + offset; +} + +pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset) +{ + pte_t *pte; + + pte = (pte_t *) __get_free_page(GFP_KERNEL); + if (pmd_none(*pmd)) { + if (pte) { + clear_page((unsigned long)pte); + pmd_set(pmd, pte); + return pte + offset; + } + pmd_set(pmd, (pte_t *) BAD_PAGETABLE); + return NULL; + } + free_page((unsigned long)pte); + if (pmd_bad(*pmd)) { + __bad_pte(pmd); + return NULL; + } + return (pte_t *) pmd_page(*pmd) + offset; +} + + /* * BAD_PAGE is the page that is used for page faults when linux * is out-of-memory. Older versions of linux just did a @@ -56,7 +117,7 @@ void show_mem(void) { int i,free = 0,total = 0,reserved = 0; - int shared = 0; + int shared = 0, cached = 0; printk("\nMem-info:\n"); show_free_areas(); @@ -66,6 +127,8 @@ total++; if (PageReserved(mem_map+i)) reserved++; + else if (PageSwapCache(mem_map+i)) + cached++; else if (!atomic_read(&mem_map[i].count)) free++; else @@ -75,6 +138,8 @@ printk("%d free pages\n",free); printk("%d reserved pages\n",reserved); printk("%d pages shared\n",shared); + printk("%d pages swap cached\n",cached); + printk("%d pages in page table cache\n",pgtable_cache_size); show_buffers(); #ifdef CONFIG_NET show_net_buffers(); @@ -213,16 +278,16 @@ void free_initmem (void) { - extern char __init_begin, __init_end; - unsigned long addr; + extern char __init_begin, __init_end; + unsigned long addr; - addr = (unsigned long)(&__init_begin); - for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { - mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved); - atomic_set(&mem_map[MAP_NR(addr)].count, 1); - free_page(addr); - } - printk ("Freeing unused kernel memory: %ldk freed\n", + addr = (unsigned long)(&__init_begin); + for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { + mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved); + atomic_set(&mem_map[MAP_NR(addr)].count, 1); + free_page(addr); + } + printk ("Freeing unused kernel memory: %ldk freed\n", (&__init_end - &__init_begin) >> 10); } diff -u --recursive --new-file v2.1.105/linux/arch/arm/kernel/sys_arm.c linux/arch/arm/kernel/sys_arm.c --- v2.1.105/linux/arch/arm/kernel/sys_arm.c Fri May 8 23:14:42 1998 +++ linux/arch/arm/kernel/sys_arm.c Sat Jun 13 11:36:52 1998 @@ -309,16 +309,20 @@ asmlinkage int sys_uname (struct old_utsname * name) { static int warned = 0; - + int err; + if (warned == 0) { warned ++; printk (KERN_NOTICE "%s (%d): obsolete uname call\n", current->comm, current->pid); } - if (name && !copy_to_user (name, &system_utsname, sizeof (*name))) - return 0; - return -EFAULT; + if(!name) + return -EFAULT; + down(&uts_sem); + err=copy_to_user (name, &system_utsname, sizeof (*name)); + up(&uts_sem); + return err?-EFAULT:0; } asmlinkage int sys_olduname(struct oldold_utsname * name) @@ -338,6 +342,8 @@ if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname))) return -EFAULT; + down(&uts_sem); + error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN); error -= __put_user(0,name->sysname+__OLD_UTS_LEN); error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN); @@ -348,6 +354,9 @@ error -= __put_user(0,name->version+__OLD_UTS_LEN); error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN); error -= __put_user(0,name->machine+__OLD_UTS_LEN); + + up(&uts_sem); + error = error ? -EFAULT : 0; return error; diff -u --recursive --new-file v2.1.105/linux/arch/i386/boot/setup.S linux/arch/i386/boot/setup.S --- v2.1.105/linux/arch/i386/boot/setup.S Mon Feb 23 18:12:02 1998 +++ linux/arch/i386/boot/setup.S Wed Jun 10 14:01:49 1998 @@ -531,6 +531,24 @@ out #0x60,al call empty_8042 +! wait until a20 really *is* enabled; it can take a fair amount of +! time on any + + push ds + push es + xor ax,ax ! segment 0x0000 + mov ds,ax + dec ax ! segment 0xffff (HMA) + mov es,ax +a20_wait: + inc ax + mov [0x7c00],ax ! any unused memory location < 64K + seg es + cmp ax,[0x7c10] ! corresponding HMA address + je a20_wait ! loop until no longer aliased + pop es + pop ds + ! make sure any possible coprocessor is properly reset.. xor ax,ax diff -u --recursive --new-file v2.1.105/linux/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S --- v2.1.105/linux/arch/i386/kernel/entry.S Thu May 14 19:47:38 1998 +++ linux/arch/i386/kernel/entry.S Tue Jun 9 00:55:09 1998 @@ -546,7 +546,8 @@ .long SYMBOL_NAME(sys_getcwd) .long SYMBOL_NAME(sys_capget) .long SYMBOL_NAME(sys_capset) /* 185 */ + .long SYMBOL_NAME(sys_sigaltstack) - .rept NR_syscalls-185 + .rept NR_syscalls-186 .long SYMBOL_NAME(sys_ni_syscall) .endr diff -u --recursive --new-file v2.1.105/linux/arch/i386/kernel/head.S linux/arch/i386/kernel/head.S --- v2.1.105/linux/arch/i386/kernel/head.S Wed May 20 19:10:37 1998 +++ linux/arch/i386/kernel/head.S Wed Jun 10 14:01:52 1998 @@ -104,11 +104,6 @@ * in 16-bit mode for the "real" operations. */ call setup_idt - xorl %eax,%eax -1: incl %eax # check that A20 really IS enabled - movl %eax,0x000000 # loop forever if it isn't - cmpl %eax,0x100000 - je 1b /* * Initialize eflags. Some BIOS's leave bits like NT set. This would * confuse the debugger if this code is traced. diff -u --recursive --new-file v2.1.105/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c --- v2.1.105/linux/arch/i386/kernel/process.c Sun Jun 7 11:16:27 1998 +++ linux/arch/i386/kernel/process.c Sat Jun 13 12:48:10 1998 @@ -125,8 +125,10 @@ * the APM bios knowing only one CPU at a time will do * so. */ - if (!start_idle) + if (!start_idle) { + check_pgt_cache(); start_idle = jiffies; + } if (jiffies - start_idle > HARD_IDLE_TIMEOUT) hard_idle(); else { @@ -158,6 +160,7 @@ if(current_cpu_data.hlt_works_ok && !hlt_counter && !need_resched) __asm("hlt"); + check_pgt_cache(); /* * tq_scheduler currently assumes we're running in a process * context (ie that we hold the kernel lock..) @@ -551,9 +554,9 @@ if ((fpvalid = current->used_math) != 0) { if (boot_cpu_data.hard_math) { - if (last_task_used_math == current) { - __asm__("clts ; fsave %0; fwait": :"m" (*fpu)); - } + if (last_task_used_math == current) { + __asm__("clts ; fsave %0; fwait": :"m" (*fpu)); + } else memcpy(fpu,¤t->tss.i387.hard,sizeof(*fpu)); } else { diff -u --recursive --new-file v2.1.105/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c --- v2.1.105/linux/arch/i386/kernel/setup.c Thu May 14 19:47:38 1998 +++ linux/arch/i386/kernel/setup.c Sat Jun 13 11:48:01 1998 @@ -361,7 +361,7 @@ { X86_VENDOR_AMD, 5, { "K5/SSA5 (PR-75, PR-90, PR-100)", "K5 (PR-120, PR-133)", "K5 (PR-166)", "K5 (PR-200)", NULL, NULL, - "K6 (166 - 266)", "K6 (166 - 300)", "K6-3D (200 - 450)", + "K6 (166 - 266)", "K6 (166 - 300)", "K6-2 (200 - 450)", "K6-3D-Plus (200 - 450)", NULL, NULL, NULL, NULL, NULL, NULL }}, { X86_VENDOR_UMC, 4, { NULL, "U5D", "U5S", NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -442,11 +442,11 @@ { char *p = buffer; int sep_bug; - static const char *x86_cap_flags[] = { - "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce", - "cx8", "apic", "10", "sep", "mtrr", "pge", "mca", "cmov", - "fcmov", "17", "18", "19", "20", "21", "22", "mmx", - "osfxsr", "25", "26", "27", "28", "29", "30", "amd3d" + static char *x86_cap_flags[] = { + "fpu", "vme", "de", "pse", "tsc", "msr", "6", "mce", + "cx8", "9", "10", "sep", "12", "pge", "14", "cmov", + "16", "17", "18", "19", "20", "21", "22", "mmx", + "24", "25", "26", "27", "28", "29", "30", "31" }; struct cpuinfo_x86 *c = cpu_data; int i, n; @@ -473,6 +473,24 @@ p += sprintf(p, "stepping\t: %d\n", c->x86_mask); } else p += sprintf(p, "stepping\t: unknown\n"); + + /* Modify the capabilities according to chip type */ + if (c->x86_mask) { + if (c->x86_vendor == X86_VENDOR_CYRIX) { + x86_cap_flags[24] = "cxmmx"; + } else if (c->x86_vendor == X86_VENDOR_AMD) { + x86_cap_flags[16] = "fcmov"; + x86_cap_flags[31] = "amd3d"; + } else if (c->x86_vendor == X86_VENDOR_INTEL) { + x86_cap_flags[6] = "pae"; + x86_cap_flags[9] = "apic"; + x86_cap_flags[12] = "mtrr"; + x86_cap_flags[14] = "mca"; + x86_cap_flags[16] = "pat"; + x86_cap_flags[17] = "pse"; + x86_cap_flags[24] = "osfxsr"; + } + } sep_bug = c->x86_vendor == X86_VENDOR_INTEL && c->x86 == 0x06 && diff -u --recursive --new-file v2.1.105/linux/arch/i386/kernel/signal.c linux/arch/i386/kernel/signal.c --- v2.1.105/linux/arch/i386/kernel/signal.c Wed Apr 1 20:11:47 1998 +++ linux/arch/i386/kernel/signal.c Tue Jun 9 13:34:01 1998 @@ -116,6 +116,13 @@ return ret; } +asmlinkage int +sys_sigaltstack(const stack_t *uss, stack_t *uoss) +{ + struct pt_regs *regs = (struct pt_regs *) &uss; + return do_sigaltstack(uss, uoss, regs->esp); +} + /* * Do a signal return; undo the signal stack. @@ -144,7 +151,7 @@ }; -static inline void restore_i387_hard(struct _fpstate *buf) +static inline int restore_i387_hard(struct _fpstate *buf) { #ifdef __SMP__ if (current->flags & PF_USEDFPU) { @@ -157,31 +164,33 @@ } #endif current->flags &= ~PF_USEDFPU; - __copy_from_user(¤t->tss.i387.hard, buf, sizeof(*buf)); + return __copy_from_user(¤t->tss.i387.hard, buf, sizeof(*buf)); } -static inline void restore_i387(struct _fpstate *buf) +static inline int restore_i387(struct _fpstate *buf) { + int err; #ifndef CONFIG_MATH_EMULATION - restore_i387_hard(buf); + err = restore_i387_hard(buf); #else if (boot_cpu_data.hard_math) - restore_i387_hard(buf); + err = restore_i387_hard(buf); else - restore_i387_soft(¤t->tss.i387.soft, buf); + err = restore_i387_soft(¤t->tss.i387.soft, buf); #endif current->used_math = 1; + return err; } static int -restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) +restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *peax) { - unsigned int tmp; + unsigned int tmp, err = 0; -#define COPY(x) __get_user(regs->x, &sc->x) +#define COPY(x) err |= __get_user(regs->x, &sc->x) #define COPY_SEG(seg) \ - { __get_user(tmp, &sc->seg); \ + { err |= __get_user(tmp, &sc->seg); \ if ((tmp & 0xfffc) /* not a NULL selectors */ \ && (tmp & 0x4) != 0x4 /* not a LDT selector */ \ && (tmp & 3) != 3) /* not a RPL3 GDT selector */ \ @@ -189,12 +198,12 @@ regs->x##seg = tmp; } #define COPY_SEG_STRICT(seg) \ - { __get_user(tmp, &sc->seg); \ + { err |= __get_user(tmp, &sc->seg); \ if ((tmp & 0xfffc) && (tmp & 3) != 3) goto badframe; \ regs->x##seg = tmp; } #define GET_SEG(seg) \ - { __get_user(tmp, &sc->seg); \ + { err |= __get_user(tmp, &sc->seg); \ if ((tmp & 0xfffc) /* not a NULL selectors */ \ && (tmp & 0x4) != 0x4 /* not a LDT selector */ \ && (tmp & 3) != 3) /* not a RPL3 GDT selector */ \ @@ -216,24 +225,23 @@ COPY_SEG_STRICT(cs); COPY_SEG_STRICT(ss); - __get_user(tmp, &sc->eflags); + err |= __get_user(tmp, &sc->eflags); regs->eflags = (regs->eflags & ~0x40DD5) | (tmp & 0x40DD5); regs->orig_eax = -1; /* disable syscall checks */ - __get_user(tmp, (unsigned long *)&sc->fpstate); + err |= __get_user(tmp, (unsigned long *)&sc->fpstate); if (tmp) { struct _fpstate * buf = (struct _fpstate *) tmp; if (verify_area(VERIFY_READ, buf, sizeof(*buf))) goto badframe; - restore_i387(buf); + err |= restore_i387(buf); } - __get_user(tmp, &sc->eax); - return tmp; + err |= __get_user(*peax, &sc->eax); + return err; badframe: - lock_kernel(); - do_exit(SIGSEGV); + return 1; } asmlinkage int sys_sigreturn(unsigned long __unused) @@ -241,6 +249,7 @@ struct pt_regs *regs = (struct pt_regs *) &__unused; struct sigframe *frame = (struct sigframe *)(regs->esp - 8); sigset_t set; + int eax; if (verify_area(VERIFY_READ, frame, sizeof(*frame))) goto badframe; @@ -256,11 +265,13 @@ recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); - return restore_sigcontext(regs, &frame->sc); + if (restore_sigcontext(regs, &frame->sc, &eax)) + goto badframe; + return eax; badframe: - lock_kernel(); - do_exit(SIGSEGV); + force_sig(SIGSEGV, current); + return 0; } asmlinkage int sys_rt_sigreturn(unsigned long __unused) @@ -268,6 +279,8 @@ struct pt_regs *regs = (struct pt_regs *) &__unused; struct rt_sigframe *frame = (struct rt_sigframe *)(regs->esp - 4); sigset_t set; + stack_t st; + int eax; if (verify_area(VERIFY_READ, frame, sizeof(*frame))) goto badframe; @@ -280,18 +293,27 @@ recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); - return restore_sigcontext(regs, &frame->uc.uc_mcontext); + if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &eax)) + goto badframe; + + if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st))) + goto badframe; + /* It is more difficult to avoid calling this function than to + call it and ignore errors. */ + do_sigaltstack(&st, NULL, regs->esp); + + return eax; badframe: - lock_kernel(); - do_exit(SIGSEGV); + force_sig(SIGSEGV, current); + return 0; } /* * Set up a signal frame. */ -static inline struct _fpstate * save_i387_hard(struct _fpstate * buf) +static inline int save_i387_hard(struct _fpstate * buf) { #ifdef __SMP__ if (current->flags & PF_USEDFPU) { @@ -308,14 +330,15 @@ } #endif current->tss.i387.hard.status = current->tss.i387.hard.swd; - copy_to_user(buf, ¤t->tss.i387.hard, sizeof(*buf)); - return buf; + if (__copy_to_user(buf, ¤t->tss.i387.hard, sizeof(*buf))) + return -1; + return 1; } -static struct _fpstate * save_i387(struct _fpstate *buf) +static int save_i387(struct _fpstate *buf) { if (!current->used_math) - return NULL; + return 0; /* This will cause a "finit" to be triggered by the next attempted FPU operation by the 'current' process. @@ -330,98 +353,116 @@ #endif } -static void +static int setup_sigcontext(struct sigcontext *sc, struct _fpstate *fpstate, struct pt_regs *regs, unsigned long mask) { - unsigned int tmp; + int tmp, err = 0; tmp = 0; __asm__("movl %%gs,%w0" : "=r"(tmp): "0"(tmp)); - __put_user(tmp, (unsigned int *)&sc->gs); + err |= __put_user(tmp, (unsigned int *)&sc->gs); __asm__("movl %%fs,%w0" : "=r"(tmp): "0"(tmp)); - __put_user(tmp, (unsigned int *)&sc->fs); + err |= __put_user(tmp, (unsigned int *)&sc->fs); - __put_user(regs->xes, (unsigned int *)&sc->es); - __put_user(regs->xds, (unsigned int *)&sc->ds); - __put_user(regs->edi, &sc->edi); - __put_user(regs->esi, &sc->esi); - __put_user(regs->ebp, &sc->ebp); - __put_user(regs->esp, &sc->esp); - __put_user(regs->ebx, &sc->ebx); - __put_user(regs->edx, &sc->edx); - __put_user(regs->ecx, &sc->ecx); - __put_user(regs->eax, &sc->eax); - __put_user(current->tss.trap_no, &sc->trapno); - __put_user(current->tss.error_code, &sc->err); - __put_user(regs->eip, &sc->eip); - __put_user(regs->xcs, (unsigned int *)&sc->cs); - __put_user(regs->eflags, &sc->eflags); - __put_user(regs->esp, &sc->esp_at_signal); - __put_user(regs->xss, (unsigned int *)&sc->ss); - - __put_user(save_i387(fpstate), &sc->fpstate); + err |= __put_user(regs->xes, (unsigned int *)&sc->es); + err |= __put_user(regs->xds, (unsigned int *)&sc->ds); + err |= __put_user(regs->edi, &sc->edi); + err |= __put_user(regs->esi, &sc->esi); + err |= __put_user(regs->ebp, &sc->ebp); + err |= __put_user(regs->esp, &sc->esp); + err |= __put_user(regs->ebx, &sc->ebx); + err |= __put_user(regs->edx, &sc->edx); + err |= __put_user(regs->ecx, &sc->ecx); + err |= __put_user(regs->eax, &sc->eax); + err |= __put_user(current->tss.trap_no, &sc->trapno); + err |= __put_user(current->tss.error_code, &sc->err); + err |= __put_user(regs->eip, &sc->eip); + err |= __put_user(regs->xcs, (unsigned int *)&sc->cs); + err |= __put_user(regs->eflags, &sc->eflags); + err |= __put_user(regs->esp, &sc->esp_at_signal); + err |= __put_user(regs->xss, (unsigned int *)&sc->ss); + + tmp = save_i387(fpstate); + if (tmp < 0) + err = 1; + else + err |= __put_user(tmp ? fpstate : NULL, &sc->fpstate); /* non-iBCS2 extensions.. */ - __put_user(mask, &sc->oldmask); - __put_user(current->tss.cr2, &sc->cr2); + err |= __put_user(mask, &sc->oldmask); + err |= __put_user(current->tss.cr2, &sc->cr2); + + return err; } /* * Determine which stack to use.. */ -static inline unsigned long sigstack_esp(struct k_sigaction *ka, struct pt_regs * regs) +static inline void * +get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size) { unsigned long esp; /* Default to using normal stack */ esp = regs->esp; + /* This is the X/Open sanctioned signal stack switching. */ + if (ka->sa.sa_flags & SA_ONSTACK) { + if (! on_sig_stack(esp)) + esp = current->sas_ss_sp + current->sas_ss_size; + } + /* This is the legacy signal stack switching. */ - if ((regs->xss & 0xffff) != __USER_DS && - !(ka->sa.sa_flags & SA_RESTORER) && - ka->sa.sa_restorer) + else if ((regs->xss & 0xffff) != __USER_DS && + !(ka->sa.sa_flags & SA_RESTORER) && + ka->sa.sa_restorer) { esp = (unsigned long) ka->sa.sa_restorer; + } - return esp; + return (void *)((esp - frame_size) & -8ul); } static void setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs * regs) { struct sigframe *frame; + int err = 0; - frame = (struct sigframe *)((sigstack_esp(ka, regs) - sizeof(*frame)) & -8); + frame = get_sigframe(ka, regs, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - goto segv_and_exit; + goto give_sigsegv; - __put_user((current->exec_domain - && current->exec_domain->signal_invmap - && sig < 32 - ? current->exec_domain->signal_invmap[sig] - : sig), - &frame->sig); + err |= __put_user((current->exec_domain + && current->exec_domain->signal_invmap + && sig < 32 + ? current->exec_domain->signal_invmap[sig] + : sig), + &frame->sig); - setup_sigcontext(&frame->sc, &frame->fpstate, regs, set->sig[0]); + err |= setup_sigcontext(&frame->sc, &frame->fpstate, regs, set->sig[0]); if (_NSIG_WORDS > 1) { - __copy_to_user(frame->extramask, &set->sig[1], - sizeof(frame->extramask)); + err |= __copy_to_user(frame->extramask, &set->sig[1], + sizeof(frame->extramask)); } /* Set up to return from userspace. If provided, use a stub already in userspace. */ if (ka->sa.sa_flags & SA_RESTORER) { - __put_user(ka->sa.sa_restorer, &frame->pretcode); + err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); } else { - __put_user(frame->retcode, &frame->pretcode); + err |= __put_user(frame->retcode, &frame->pretcode); /* This is popl %eax ; movl $,%eax ; int $0x80 */ - __put_user(0xb858, (short *)(frame->retcode+0)); - __put_user(__NR_sigreturn, (int *)(frame->retcode+2)); - __put_user(0x80cd, (short *)(frame->retcode+6)); + err |= __put_user(0xb858, (short *)(frame->retcode+0)); + err |= __put_user(__NR_sigreturn, (int *)(frame->retcode+2)); + err |= __put_user(0x80cd, (short *)(frame->retcode+6)); } + if (err) + goto give_sigsegv; + /* Set up registers for signal handler */ regs->esp = (unsigned long) frame; regs->eip = (unsigned long) ka->sa.sa_handler; @@ -443,50 +484,59 @@ return; -segv_and_exit: - lock_kernel(); - do_exit(SIGSEGV); +give_sigsegv: + if (sig == SIGSEGV) + ka->sa.sa_handler = SIG_DFL; + force_sig(SIGSEGV, current); } static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs * regs) { struct rt_sigframe *frame; + int err = 0; - frame = (struct rt_sigframe *)((sigstack_esp(ka, regs) - sizeof(*frame)) & -8); + frame = get_sigframe(ka, regs, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - goto segv_and_exit; + goto give_sigsegv; - __put_user((current->exec_domain - && current->exec_domain->signal_invmap - && sig < 32 - ? current->exec_domain->signal_invmap[sig] - : sig), - &frame->sig); - __put_user(&frame->info, &frame->pinfo); - __put_user(&frame->uc, &frame->puc); - __copy_to_user(&frame->info, info, sizeof(*info)); - - /* Clear all the bits of the ucontext we don't use. */ - __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext)); - - setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate, - regs, set->sig[0]); - __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); + err |= __put_user((current->exec_domain + && current->exec_domain->signal_invmap + && sig < 32 + ? current->exec_domain->signal_invmap[sig] + : sig), + &frame->sig); + err |= __put_user(&frame->info, &frame->pinfo); + err |= __put_user(&frame->uc, &frame->puc); + err |= __copy_to_user(&frame->info, info, sizeof(*info)); + + /* Create the ucontext. */ + err |= __put_user(0, &frame->uc.uc_flags); + err |= __put_user(0, &frame->uc.uc_link); + err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); + err |= __put_user(sas_ss_flags(regs->esp), + &frame->uc.uc_stack.ss_flags); + err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); + err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate, + regs, set->sig[0]); + err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); /* Set up to return from userspace. If provided, use a stub already in userspace. */ if (ka->sa.sa_flags & SA_RESTORER) { - __put_user(ka->sa.sa_restorer, &frame->pretcode); + err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); } else { - __put_user(frame->retcode, &frame->pretcode); + err |= __put_user(frame->retcode, &frame->pretcode); /* This is movl $,%eax ; int $0x80 */ - __put_user(0xb8, (char *)(frame->retcode+0)); - __put_user(__NR_rt_sigreturn, (int *)(frame->retcode+1)); - __put_user(0x80cd, (short *)(frame->retcode+5)); + err |= __put_user(0xb8, (char *)(frame->retcode+0)); + err |= __put_user(__NR_rt_sigreturn, (int *)(frame->retcode+1)); + err |= __put_user(0x80cd, (short *)(frame->retcode+5)); } + if (err) + goto give_sigsegv; + /* Set up registers for signal handler */ regs->esp = (unsigned long) frame; regs->eip = (unsigned long) ka->sa.sa_handler; @@ -508,9 +558,10 @@ return; -segv_and_exit: - lock_kernel(); - do_exit(SIGSEGV); +give_sigsegv: + if (sig == SIGSEGV) + ka->sa.sa_handler = SIG_DFL; + force_sig(SIGSEGV, current); } /* diff -u --recursive --new-file v2.1.105/linux/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c --- v2.1.105/linux/arch/i386/kernel/smp.c Sun Jun 7 11:16:27 1998 +++ linux/arch/i386/kernel/smp.c Sat Jun 13 12:48:10 1998 @@ -597,6 +597,9 @@ struct cpuinfo_x86 *c=&cpu_data[id]; *c = boot_cpu_data; + c->pte_quick = 0; + c->pgd_quick = 0; + c->pgtable_cache_sz = 0; identify_cpu(c); /* * Mask B, Pentium, but not Pentium MMX diff -u --recursive --new-file v2.1.105/linux/arch/i386/kernel/sys_i386.c linux/arch/i386/kernel/sys_i386.c --- v2.1.105/linux/arch/i386/kernel/sys_i386.c Tue Mar 10 10:03:30 1998 +++ linux/arch/i386/kernel/sys_i386.c Sat Jun 13 11:36:52 1998 @@ -63,6 +63,7 @@ struct file * file = NULL; struct mmap_arg_struct a; + down(¤t->mm->mmap_sem); lock_kernel(); if (copy_from_user(&a, arg, sizeof(a))) goto out; @@ -73,11 +74,13 @@ goto out; } a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); + error = do_mmap(file, a.addr, a.len, a.prot, a.flags, a.offset); if (file) fput(file); out: unlock_kernel(); + up(¤t->mm->mmap_sem); return error; } @@ -213,9 +216,13 @@ */ asmlinkage int sys_uname(struct old_utsname * name) { - if (name && !copy_to_user(name, &system_utsname, sizeof (*name))) - return 0; - return -EFAULT; + int err; + if (!name) + return -EFAULT; + down(&uts_sem); + err=copy_to_user(name, &system_utsname, sizeof (*name)); + up(&uts_sem); + return err?-EFAULT:0; } asmlinkage int sys_olduname(struct oldold_utsname * name) @@ -227,6 +234,8 @@ if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname))) return -EFAULT; + down(&uts_sem); + error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN); error |= __put_user(0,name->sysname+__OLD_UTS_LEN); error |= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN); @@ -237,7 +246,9 @@ error |= __put_user(0,name->version+__OLD_UTS_LEN); error |= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN); error |= __put_user(0,name->machine+__OLD_UTS_LEN); - + + up(&uts_sem); + error = error ? -EFAULT : 0; return error; diff -u --recursive --new-file v2.1.105/linux/arch/i386/lib/checksum.c linux/arch/i386/lib/checksum.c --- v2.1.105/linux/arch/i386/lib/checksum.c Tue Apr 14 14:29:20 1998 +++ linux/arch/i386/lib/checksum.c Thu Jun 11 22:52:33 1998 @@ -8,6 +8,9 @@ * Authors: Jorge Cwik, * Arnt Gulbrandsen, * Tom May, + * Pentium Pro/II routines: + * Alexander Kjeldaas + * Finn Arne Gangstad * Lots of code moved from tcp.c and ip.c; see those files * for more names. * @@ -26,6 +29,8 @@ * computes a partial checksum, e.g. for TCP/UDP fragments */ +#if CPU!=686 + unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum) { /* * Experiments with ethernet and slip connections show that buff @@ -97,6 +102,101 @@ return(sum); } +#else /* 686 */ + +unsigned int csum_partial(const unsigned char * buf, int len, unsigned int sum) { + __asm__ (" + testl $2, %%esi + jnz 30f +10: + movl %%ecx, %%edx + movl %%ecx, %%ebx + andl $0x7c, %%ebx + shrl $7, %%ecx + addl %%ebx,%%esi + shrl $2, %%ebx + negl %%ebx + lea 45f(%%ebx,%%ebx,2), %%ebx + testl %%esi, %%esi + jmp %%ebx + + # Handle 2-byte-aligned regions +20: addw (%%esi), %%ax + lea 2(%%esi), %%esi + adcl $0, %%eax + jmp 10b + +30: subl $2, %%ecx + ja 20b + je 32f + movzbl (%%esi),%%ebx # csumming 1 byte, 2-aligned + addl %%ebx, %%eax + adcl $0, %%eax + jmp 80f +32: + addw (%%esi), %%ax # csumming 2 bytes, 2-aligned + adcl $0, %%eax + jmp 80f + +40: + addl -128(%%esi), %%eax + adcl -124(%%esi), %%eax + adcl -120(%%esi), %%eax + adcl -116(%%esi), %%eax + adcl -112(%%esi), %%eax + adcl -108(%%esi), %%eax + adcl -104(%%esi), %%eax + adcl -100(%%esi), %%eax + adcl -96(%%esi), %%eax + adcl -92(%%esi), %%eax + adcl -88(%%esi), %%eax + adcl -84(%%esi), %%eax + adcl -80(%%esi), %%eax + adcl -76(%%esi), %%eax + adcl -72(%%esi), %%eax + adcl -68(%%esi), %%eax + adcl -64(%%esi), %%eax + adcl -60(%%esi), %%eax + adcl -56(%%esi), %%eax + adcl -52(%%esi), %%eax + adcl -48(%%esi), %%eax + adcl -44(%%esi), %%eax + adcl -40(%%esi), %%eax + adcl -36(%%esi), %%eax + adcl -32(%%esi), %%eax + adcl -28(%%esi), %%eax + adcl -24(%%esi), %%eax + adcl -20(%%esi), %%eax + adcl -16(%%esi), %%eax + adcl -12(%%esi), %%eax + adcl -8(%%esi), %%eax + adcl -4(%%esi), %%eax +45: + lea 128(%%esi), %%esi + adcl $0, %%eax + dec %%ecx + jge 40b + movl %%edx, %%ecx +50: andl $3, %%ecx + jz 80f + + # Handle the last 1-3 bytes without jumping + notl %%ecx # 1->2, 2->1, 3->0, higher bits are masked + movl $0xffffff,%%ebx # by the shll and shrl instructions + shll $3,%%ecx + shrl %%cl,%%ebx + andl -128(%%esi),%%ebx # esi is 4-aligned so should be ok + addl %%ebx,%%eax + adcl $0,%%eax +80: " + : "=a"(sum) + : "0"(sum), "c"(len), "S"(buf) + : "bx", "cx", "dx", "si"); + return(sum); +} + +#endif + /* * Copy from ds while checksumming, otherwise like csum_partial * @@ -112,13 +212,15 @@ " 9999: "#y"; \n \ .section __ex_table, \"a\"; \n \ .long 9999b, 6001f \n \ - .previous" + .previous\n" #define DST(y...) \ " 9999: "#y"; \n \ .section __ex_table, \"a\"; \n \ .long 9999b, 6002f \n \ - .previous" + .previous\n" + +#if CPU!=686 unsigned int csum_partial_copy_generic (const char *src, char *dst, int len, int sum, int *src_err_ptr, int *dst_err_ptr) @@ -241,6 +343,79 @@ return(sum); } + +#else /* CPU == 686 */ + +#define ROUND1(x) \ + SRC(movl x(%%esi), %%ebx ) \ + "addl %%ebx, %%eax\n" \ + DST(movl %%ebx, x(%%edi) ) + +#define ROUND(x) \ + SRC(movl x(%%esi), %%ebx ) \ + "adcl %%ebx, %%eax\n" \ + DST(movl %%ebx, x(%%edi) ) + +unsigned int csum_partial_copy_generic (const char *src, char *dst, + int len, int sum, int *src_err_ptr, int *dst_err_ptr) +{ + __asm__ __volatile__ (" + movl %%ecx, %%edx + movl %%ecx, %%ebx + shrl $6, %%ecx + andl $0x3c, %%ebx + negl %%ebx + subl %%ebx, %%esi + subl %%ebx, %%edi + lea 3f(%%ebx,%%ebx), %%ebx + testl %%esi, %%esi + jmp %%ebx +1: addl $64,%%esi + addl $64,%%edi\n" +ROUND1(-64) ROUND(-60) ROUND(-56) ROUND(-52) +ROUND (-48) ROUND(-44) ROUND(-40) ROUND(-36) +ROUND (-32) ROUND(-28) ROUND(-24) ROUND(-20) +ROUND (-16) ROUND(-12) ROUND(-8) ROUND(-4) +"3: adcl $0,%%eax + dec %%ecx + jge 1b +4: andl $3, %%edx + jz 7f + cmpl $2, %%edx + jb 5f + " SRC(movw (%%esi), %%dx )" + leal 2(%%esi), %%esi + " DST(movw %%dx, (%%edi) )" + leal 2(%%edi), %%edi + je 6f + shll $16,%%edx +5:" SRC(movb (%%esi), %%dl )" + " DST(movb %%dl, (%%edi) )" +6: addl %%edx, %%eax + adcl $0, %%eax +7: +.section .fixup, \"ax\" +6000: movl %7, (%%ebx) +# FIXME: do zeroing of rest of the buffer here. + jmp 7b +6001: movl %1, %%ebx + jmp 6000b +6002: movl %2, %%ebx + jmp 6000b +.previous + " + : "=a"(sum), "=m"(src_err_ptr), "=m"(dst_err_ptr) + : "0"(sum), "c"(len), "S"(src), "D" (dst), + "i" (-EFAULT) + : "bx", "cx", "dx", "si", "di" ); + return(sum); +} + +#undef ROUND +#undef ROUND1 + +#endif + #undef SRC #undef DST diff -u --recursive --new-file v2.1.105/linux/arch/i386/math-emu/fpu_entry.c linux/arch/i386/math-emu/fpu_entry.c --- v2.1.105/linux/arch/i386/math-emu/fpu_entry.c Fri Jan 30 11:28:06 1998 +++ linux/arch/i386/math-emu/fpu_entry.c Tue Jun 9 00:55:09 1998 @@ -677,14 +677,15 @@ #define sstatus_word() \ ((S387->swd & ~SW_Top & 0xffff) | ((S387->ftop << SW_Top_Shift) & SW_Top)) -void restore_i387_soft(void *s387, struct _fpstate *buf) +int restore_i387_soft(void *s387, struct _fpstate *buf) { u_char *d = (u_char *)buf; int offset, other, i, tags, regnr, tag, newtop; RE_ENTRANT_CHECK_OFF; FPU_verify_area(VERIFY_READ, d, 7*4 + 8*10); - __copy_from_user(&S387->cwd, d, 7*4); + if (__copy_from_user(&S387->cwd, d, 7*4)) + return -1; RE_ENTRANT_CHECK_ON; d += 7*4; @@ -695,9 +696,11 @@ RE_ENTRANT_CHECK_OFF; /* Copy all registers in stack order. */ - __copy_from_user(((u_char *)&S387->st_space)+offset, d, other); + if (__copy_from_user(((u_char *)&S387->st_space)+offset, d, other)) + return -1; if ( offset ) - __copy_from_user((u_char *)&S387->st_space, d+other, offset); + if (__copy_from_user((u_char *)&S387->st_space, d+other, offset)) + return -1; RE_ENTRANT_CHECK_ON; /* The tags may need to be corrected now. */ @@ -716,10 +719,11 @@ } S387->twd = tags; + return 0; } -struct _fpstate * save_i387_soft(void *s387, struct _fpstate * buf) +int save_i387_soft(void *s387, struct _fpstate * buf) { u_char *d = (u_char *)buf; int offset = (S387->ftop & 7) * 10, other = 80 - offset; @@ -742,10 +746,12 @@ RE_ENTRANT_CHECK_OFF; /* Copy all registers in stack order. */ - __copy_to_user(d, ((u_char *)&S387->st_space)+offset, other); + if (__copy_to_user(d, ((u_char *)&S387->st_space)+offset, other)) + return -1; if ( offset ) - __copy_to_user(d+other, (u_char *)&S387->st_space, offset); + if (__copy_to_user(d+other, (u_char *)&S387->st_space, offset)) + return -1 RE_ENTRANT_CHECK_ON; - return buf; + return 1; } diff -u --recursive --new-file v2.1.105/linux/arch/i386/mm/fault.c linux/arch/i386/mm/fault.c --- v2.1.105/linux/arch/i386/mm/fault.c Tue Jan 20 12:52:09 1998 +++ linux/arch/i386/mm/fault.c Tue Jun 9 16:02:42 1998 @@ -102,11 +102,11 @@ if (local_irq_count[smp_processor_id()]) die_if_kernel("page fault from irq handler",regs,error_code); - lock_kernel(); tsk = current; mm = tsk->mm; down(&mm->mmap_sem); + vma = find_vma(mm, address); if (!vma) goto bad_area; @@ -151,7 +151,7 @@ goto bad_area; } handle_mm_fault(tsk, vma, address, write); - up(&mm->mmap_sem); + /* * Did it hit the DOS screen memory VA from vm86 mode? */ @@ -160,7 +160,8 @@ if (bit < 32) tsk->tss.screen_bitmap |= 1 << bit; } - goto out; + up(&mm->mmap_sem); + return; /* * Something tried to access memory that isn't in our memory map.. @@ -175,7 +176,7 @@ tsk->tss.error_code = error_code; tsk->tss.trap_no = 14; force_sig(SIGSEGV, tsk); - goto out; + return; } /* @@ -187,7 +188,6 @@ nr = (address - (unsigned long) idt) >> 3; if (nr == 6) { - unlock_kernel(); do_invalid_op(regs, 0); return; } @@ -196,7 +196,7 @@ /* Are we prepared to handle this kernel fault? */ if ((fixup = search_exception_table(regs->eip)) != 0) { regs->eip = fixup; - goto out; + return; } /* @@ -215,7 +215,7 @@ * CPU state on certain buggy processors. */ printk("Ok"); - goto out; + return; } if (address < PAGE_SIZE) @@ -234,8 +234,8 @@ page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT]; printk(KERN_ALERT "*pte = %08lx\n", page); } + lock_kernel(); die_if_kernel("Oops", regs, error_code); do_exit(SIGKILL); -out: unlock_kernel(); } diff -u --recursive --new-file v2.1.105/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c --- v2.1.105/linux/arch/i386/mm/init.c Sun Jun 7 11:16:27 1998 +++ linux/arch/i386/mm/init.c Sat Jun 13 12:48:10 1998 @@ -27,11 +27,66 @@ #include #include -const char bad_pmd_string[] = "Bad pmd in pte_alloc: %08lx\n"; - extern void die_if_kernel(char *,struct pt_regs *,long); extern void show_net_buffers(void); +void __bad_pte_kernel(pmd_t *pmd) +{ + printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd)); + pmd_val(*pmd) = _KERNPG_TABLE + __pa(BAD_PAGETABLE); +} + +void __bad_pte(pmd_t *pmd) +{ + printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd)); + pmd_val(*pmd) = _PAGE_TABLE + __pa(BAD_PAGETABLE); +} + +pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long offset) +{ + pte_t *pte; + + pte = (pte_t *) __get_free_page(GFP_KERNEL); + if (pmd_none(*pmd)) { + if (pte) { + clear_page((unsigned long)pte); + pmd_val(*pmd) = _KERNPG_TABLE + __pa(pte); + return pte + offset; + } + pmd_val(*pmd) = _KERNPG_TABLE + __pa(BAD_PAGETABLE); + return NULL; + } + free_page((unsigned long)pte); + if (pmd_bad(*pmd)) { + __bad_pte_kernel(pmd); + return NULL; + } + return (pte_t *) pmd_page(*pmd) + offset; +} + +pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset) +{ + unsigned long pte; + + pte = (unsigned long) __get_free_page(GFP_KERNEL); + if (pmd_none(*pmd)) { + if (pte) { + clear_page(pte); + pmd_val(*pmd) = _PAGE_TABLE + __pa(pte); + return (pte_t *)(pte + offset); + } + pmd_val(*pmd) = _PAGE_TABLE + __pa(BAD_PAGETABLE); + return NULL; + } + free_page(pte); + if (pmd_bad(*pmd)) { + __bad_pte(pmd); + return NULL; + } + return (pte_t *) (pmd_page(*pmd) + offset); +} + + /* * BAD_PAGE is the page that is used for page faults when linux * is out-of-memory. Older versions of linux just did a @@ -82,7 +137,7 @@ total++; if (PageReserved(mem_map+i)) reserved++; - if (PageSwapCache(mem_map+i)) + else if (PageSwapCache(mem_map+i)) cached++; else if (!atomic_read(&mem_map[i].count)) free++; @@ -93,6 +148,7 @@ printk("%d reserved pages\n",reserved); printk("%d pages shared\n",shared); printk("%d pages swap cached\n",cached); + printk("%ld pages in page table cache\n",pgtable_cache_size); show_buffers(); #ifdef CONFIG_NET show_net_buffers(); diff -u --recursive --new-file v2.1.105/linux/arch/m68k/Makefile linux/arch/m68k/Makefile --- v2.1.105/linux/arch/m68k/Makefile Fri May 8 23:14:42 1998 +++ linux/arch/m68k/Makefile Sat Jun 13 13:14:31 1998 @@ -64,6 +64,11 @@ SUBDIRS := $(SUBDIRS) arch/m68k/mac endif +ifdef CONFIG_HP300 +CORE_FILES := $(CORE_FILES) arch/m68k/hp300/hp300.o +SUBDIRS := $(SUBDIRS) arch/m68k/hp300 +endif + ifdef CONFIG_APOLLO CORE_FILES := $(CORE_FILES) arch/m68k/apollo/apollo.o SUBDIRS := $(SUBDIRS) arch/m68k/apollo @@ -72,6 +77,11 @@ ifdef CONFIG_MVME16x CORE_FILES := $(CORE_FILES) arch/m68k/mvme16x/mvme16x.o SUBDIRS := $(SUBDIRS) arch/m68k/mvme16x +endif + +ifdef CONFIG_BVME6000 +CORE_FILES := $(CORE_FILES) arch/m68k/bvme6000/bvme6000.o +SUBDIRS := $(SUBDIRS) arch/m68k/bvme6000 endif ifdef CONFIG_M68040 diff -u --recursive --new-file v2.1.105/linux/arch/m68k/amiga/Makefile linux/arch/m68k/amiga/Makefile --- v2.1.105/linux/arch/m68k/amiga/Makefile Tue Feb 17 13:12:44 1998 +++ linux/arch/m68k/amiga/Makefile Mon Jun 8 11:03:49 1998 @@ -8,7 +8,7 @@ # Note 2! The CFLAGS definitions are now in the main makefile... O_TARGET := amiga.o -O_OBJS := config.o amiints.o cia.o chipram.o amisound.o zorro.o +O_OBJS := config.o amiints.o cia.o chipram.o amisound.o OX_OBJS := amiga_ksyms.o include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.105/linux/arch/m68k/amiga/zorro.c linux/arch/m68k/amiga/zorro.c --- v2.1.105/linux/arch/m68k/amiga/zorro.c Thu Mar 26 15:57:02 1998 +++ linux/arch/m68k/amiga/zorro.c Wed Dec 31 16:00:00 1969 @@ -1,1234 +0,0 @@ -/* - * linux/arch/m68k/amiga/zorro.c - * - * Copyright (C) 1995 Geert Uytterhoeven - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive - * for more details. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include - - -#ifdef CONFIG_ZORRO - - /* - * Zorro Expansion Device Manufacturers and Products - */ - -struct Manufacturer { - const char *Name; - u_short Manuf; - u_short NumProd; - const struct Product *Products; -}; - -struct Product { - const char *Name; - u_char Class; - u_char Prod; -}; - -struct GVP_Product { - const char *Name; - u_char Class; - u_char EPC; -}; - - - /* - * Macro's to make life easier - */ - -#define ARRAYSIZE(x) (sizeof(x)/sizeof(*(x))) - -#define BEGIN_PROD(id) \ - static struct Product Prod_##id[] = { -#define PROD(name, class, id) \ - { name, ZORRO_CLASS_##class, ZORRO_PROD(ZORRO_PROD_##id) }, - -#define BEGIN_GVP_PROD \ - static struct GVP_Product Ext_Prod_GVP[] = { -#define GVP_PROD(name, class, id) \ - { name, ZORRO_CLASS_##class, ZORRO_EPC(ZORRO_PROD_##id) }, - -#define BEGIN_MANUF \ - static struct Manufacturer Manufacturers[] = { -#define MANUF(name, id) \ - { name, ZORRO_MANUF_##id, ARRAYSIZE(Prod_##id), Prod_##id }, - -#define END \ - }; - - - /* - * Recognized Zorro Expansion Devices - */ - -BEGIN_PROD(PACIFIC_PERIPHERALS) - PROD("SE 2000 A500", HD, PACIFIC_PERIPHERALS_SE_2000_A500) - PROD(NULL, SCSI, PACIFIC_PERIPHERALS_SCSI) -END - -BEGIN_PROD(MACROSYSTEMS_USA_2) - PROD("Warp Engine", TURBO_SCSI_RAM, MACROSYSTEMS_WARP_ENGINE) -END - -BEGIN_PROD(KUPKE_1) - PROD("Golem RAM Box 2MB", RAM, KUPKE_GOLEM_RAM_BOX_2MB) -END - -BEGIN_PROD(MEMPHIS) - PROD("Stormbringer", TURBO, MEMPHIS_STORMBRINGER) -END - -BEGIN_PROD(3_STATE) - PROD("Megamix 2000", RAM, 3_STATE_MEGAMIX_2000) -END - -BEGIN_PROD(COMMODORE_BRAUNSCHWEIG) - PROD("A2088 XT/A2286 AT", BRIDGE, CBM_A2088_A2286) - PROD("A2286 AT", BRIDGE, CBM_A2286) - PROD("A4091", SCSI, CBM_A4091_1) - PROD("A2386-SX", BRIDGE, CBM_A2386SX_1) -END - -BEGIN_PROD(COMMODORE_WEST_CHESTER_1) - PROD("A2090/A2090A", SCSI, CBM_A2090A) - PROD("A590/A2091", SCSI, CBM_A590_A2091_1) - PROD("A590/A2091", SCSI, CBM_A590_A2091_2) - PROD("A2090B 2090 Autoboot", SCSI, CBM_A2090B) - PROD("A2060", ARCNET, CBM_A2060) - PROD("A590/A2052/A2058/A2091", RAM, CBM_A590_A2052_A2058_A2091) - PROD("A560", RAM, CBM_A560_RAM) - PROD("A2232 Prototype", MULTIIO, CBM_A2232_PROTOTYPE) - PROD("A2232", MULTIIO, CBM_A2232) - PROD("A2620 68020/RAM", TURBO_RAM, CBM_A2620) - PROD("A2630 68030/RAM", TURBO_RAM, CBM_A2630) - PROD("A4091", SCSI, CBM_A4091_2) - PROD("A2065", ETHERNET, CBM_A2065_1) - PROD("Romulator Card", UNKNOWN, CBM_ROMULATOR) - PROD("A3000 Test Fixture", MISC, CBM_A3000_TEST_FIXTURE) - PROD("A2386-SX", BRIDGE, CBM_A2386SX_2) - PROD("A2065", ETHERNET, CBM_A2065_2) -END - -BEGIN_PROD(COMMODORE_WEST_CHESTER_2) - PROD("A2090/A2090A Combitec/MacroSystem", SCSI, CBM_A2090A_CM) -END - -BEGIN_PROD(PROGRESSIVE_PERIPHERALS_AND_SYSTEMS_2) - PROD("EXP8000", RAM, PPS_EXP8000) -END - -BEGIN_PROD(KOLFF_COMPUTER_SUPPLIES) - PROD("KCS Power PC Board", BRIDGE, KCS_POWER_PC_BOARD) -END - -BEGIN_PROD(CARDCO_1) - PROD("Kronos 2000", SCSI, CARDCO_KRONOS_2000_1) - PROD("A1000", SCSI, CARDCO_A1000_1) - PROD("Escort", SCSI, CARDCO_ESCORT) - PROD("A2410 HiRes", GFX, CARDCO_A2410) -END - -BEGIN_PROD(A_SQUARED) - PROD("Live! 2000", VIDEO, A_SQUARED_LIVE_2000) -END - -BEGIN_PROD(COMSPEC_COMMUNICATIONS) - PROD("AX2000", RAM, COMSPEC_COMMUNICATIONS_AX2000) -END - -BEGIN_PROD(ANAKIN_RESEARCH) - PROD("Easyl", TABLET, ANAKIN_RESEARCH_EASYL) -END - -BEGIN_PROD(MICROBOTICS) - PROD("StarBoard II", RAM, MICROBOTICS_STARBOARD_II) - PROD("StarDrive", SCSI, MICROBOTICS_STARDRIVE) - PROD("8-Up (Rev A)", RAM, MICROBOTICS_8_UP_A) - PROD("8-Up (Rev Z)", RAM, MICROBOTICS_8_UP_Z) - PROD("Delta", RAM, MICROBOTICS_DELTA_RAM) - PROD("8-Star", RAM, MICROBOTICS_8_STAR_RAM) - PROD("8-Star", MISC, MICROBOTICS_8_STAR) - PROD("VXL RAM*32", RAM, MICROBOTICS_VXL_RAM_32) - PROD("VXL-30", TURBO, MICROBOTICS_VXL_68030) - PROD("Delta", MISC, MICROBOTICS_DELTA) - PROD("MBX 1200/1200z", RAM, MICROBOTICS_MBX_1200_1200Z_RAM) - PROD("Hardframe 2000", SCSI, MICROBOTICS_HARDFRAME_2000_1) - PROD("Hardframe 2000", SCSI, MICROBOTICS_HARDFRAME_2000_2) - PROD("MBX 1200/1200z", MISC, MICROBOTICS_MBX_1200_1200Z) -END - -BEGIN_PROD(ACCESS_ASSOCIATES_ALEGRA) -END - -BEGIN_PROD(EXPANSION_TECHNOLOGIES) -END - -BEGIN_PROD(ASDG) - PROD(NULL, RAM, ASDG_MEMORY_1) - PROD(NULL, RAM, ASDG_MEMORY_2) - PROD("EB-920 Lan Rover", ETHERNET, ASDG_EB920_LAN_ROVER) - PROD("GPIB/Dual IEEE-488/Twin-X", MULTIIO, ASDG_GPIB_DUALIEEE488_TWIN_X) -END - -BEGIN_PROD(IMTRONICS_1) - PROD("Hurricane 2800", TURBO_RAM, IMTRONICS_HURRICANE_2800_1) - PROD("Hurricane 2800", TURBO_RAM, IMTRONICS_HURRICANE_2800_2) -END - -BEGIN_PROD(CBM_UNIVERSITY_OF_LOWELL) - PROD("A2410 HiRes", GFX, CBM_A2410) -END - -BEGIN_PROD(AMERISTAR) - PROD("A2065", ETHERNET, AMERISTAR_A2065) - PROD("A560", ARCNET, AMERISTAR_A560) - PROD("A4066", ETHERNET, AMERISTAR_A4066) -END - -BEGIN_PROD(SUPRA) - PROD("SupraDrive 4x4", SCSI, SUPRA_SUPRADRIVE_4x4) - PROD("1000", RAM, SUPRA_1000_RAM) - PROD("2000 DMA", SCSI, SUPRA_2000_DMA) - PROD("500", SCSI_RAM, SUPRA_500) - PROD("500", SCSI, SUPRA_500_SCSI) - PROD("500XP/2000", RAM, SUPRA_500XP_2000_RAM) - PROD("500RX/2000", RAM, SUPRA_500RX_2000_RAM) - PROD("2400zi", MODEM, SUPRA_2400ZI) - PROD("500XP/SupraDrive WordSync", SCSI, SUPRA_500XP_SUPRADRIVE_WORDSYNC) - PROD("SupraDrive WordSync II", SCSI, SUPRA_SUPRADRIVE_WORDSYNC_II) - PROD("2400zi+", MODEM, SUPRA_2400ZIPLUS) -END - -BEGIN_PROD(COMPUTER_SYSTEMS_ASSOCIATES) - PROD("Magnum 40", TURBO_SCSI, CSA_MAGNUM) - PROD("12 Gauge", SCSI, CSA_12_GAUGE) -END - -BEGIN_PROD(MARC_MICHAEL_GROTH) -END - -BEGIN_PROD(M_TECH) - PROD("AT500", RAM, MTEC_AT500_1) -END - -BEGIN_PROD(GREAT_VALLEY_PRODUCTS_1) - PROD("Impact Series I", SCSI_RAM, GVP_IMPACT_SERIES_I) -END - -BEGIN_PROD(BYTEBOX) - PROD("A500", UNKNOWN, BYTEBOX_A500) -END - -BEGIN_PROD(DKB_POWER_COMPUTING) - PROD("SecureKey", UNKNOWN, DKB_POWER_COMPUTING_SECUREKEY) - PROD("DKM 3128", RAM, DKB_POWER_COMPUTING_DKM_3128) - PROD("Rapid Fire", SCSI, DKB_POWER_COMPUTING_RAPID_FIRE) - PROD("DKM 1202", FPU_RAM, DKB_POWER_COMPUTING_DKM_1202) - PROD("Cobra/Viper II 68EC030", TURBO, DKB_POWER_COMPUTING_COBRA_VIPER_II_68EC030) - PROD("WildFire 060", TURBO, DKB_POWER_COMPUTING_WILDFIRE_060_1) - PROD("WildFire 060", TURBO, DKB_POWER_COMPUTING_WILDFIRE_060_2) -END - -BEGIN_PROD(GREAT_VALLEY_PRODUCTS_2) - PROD("Impact Series I (4K)", SCSI, GVP_IMPACT_SERIES_I_4K) - PROD("Impact Series I (16K/2)", SCSI, GVP_IMPACT_SERIES_I_16K_2) - PROD("Impact Series I (16K/2)", SCSI, GVP_IMPACT_SERIES_I_16K_3) - PROD("Impact 3001", IDE, GVP_IMPACT_3001_IDE_1) - PROD("Impact 3001", RAM, GVP_IMPACT_3001_RAM) - PROD("Impact Series II", RAM, GVP_IMPACT_SERIES_II_RAM_1) -/* PROD(NULL, UNKNOWN, GVP_EPC_BASE) */ - PROD("Impact 3001", IDE, GVP_IMPACT_3001_IDE_2) -/* PROD("A2000 030", TURBO, GVP_A2000_030) */ -/* PROD("GForce 040", TURBO_SCSI, GFORCE_040_SCSI_2) */ - PROD("GForce 040/060", TURBO_SCSI, GVP_GFORCE_040_060) - PROD("Impact Vision 24", GFX, GVP_IMPACT_VISION_24) - PROD("GForce 040", TURBO, GVP_GFORCE_040_2) -END - -BEGIN_GVP_PROD /* ZORRO_PROD_GVP_EPC_BASE */ - GVP_PROD("GForce 040", TURBO, GVP_GFORCE_040_1) - GVP_PROD("GForce 040", TURBO_SCSI, GVP_GFORCE_040_SCSI_1) - GVP_PROD("A1291", SCSI, GVP_A1291) - GVP_PROD("Combo 030 R4", TURBO, GVP_COMBO_030_R4) - GVP_PROD("Combo 030 R4", TURBO_SCSI, GVP_COMBO_030_R4_SCSI) - GVP_PROD("Phone Pak", UNKNOWN, GVP_PHONEPAK) - GVP_PROD("IO-Extender", MULTIIO, GVP_IO_EXTENDER) - GVP_PROD("GForce 030", TURBO, GVP_GFORCE_030) - GVP_PROD("GForce 030", TURBO_SCSI, GVP_GFORCE_030_SCSI) - GVP_PROD("A530", TURBO, GVP_A530) - GVP_PROD("A530", TURBO_SCSI, GVP_A530_SCSI) - GVP_PROD("Combo 030 R3", TURBO, GVP_COMBO_030_R3) - GVP_PROD("Combo 030 R3", TURBO_SCSI, GVP_COMBO_030_R3_SCSI) - GVP_PROD("Series-II", SCSI, GVP_SERIES_II) -END - -BEGIN_PROD(CALIFORNIA_ACCESS_SYNERGY) - PROD("Malibu", SCSI, CALIFORNIA_ACCESS_SYNERGY_MALIBU) -END - -BEGIN_PROD(XETEC) - PROD("FastCard", SCSI, XETEC_FASTCARD) - PROD("FastCard", RAM, XETEC_FASTCARD_RAM) - PROD("FastCard Plus", SCSI, XETEC_FASTCARD_PLUS) -END - -BEGIN_PROD(PROGRESSIVE_PERIPHERALS_AND_SYSTEMS) - PROD("Mercury", TURBO, PPS_MERCURY) - PROD("A3000 68040", TURBO, PPS_A3000_68040) - PROD("A2000 68040", TURBO, PPS_A2000_68040) - PROD("Zeus", TURBO_SCSI_RAM, PPS_ZEUS) - PROD("A500 68040", TURBO, PPS_A500_68040) -END - -BEGIN_PROD(XEBEC) -END - -BEGIN_PROD(SPIRIT_TECHNOLOGY) - PROD("Insider IN1000", RAM, SPIRIT_TECHNOLOGY_INSIDER_IN1000) - PROD("Insider IN500", RAM, SPIRIT_TECHNOLOGY_INSIDER_IN500) - PROD("SIN500", RAM, SPIRIT_TECHNOLOGY_SIN500) - PROD("HDA 506", HD, SPIRIT_TECHNOLOGY_HDA_506) - PROD("AX-S", MISC, SPIRIT_TECHNOLOGY_AX_S) - PROD("OctaByte", RAM, SPIRIT_TECHNOLOGY_OCTABYTE) - PROD("Inmate", SCSI_RAM, SPIRIT_TECHNOLOGY_INMATE) -END - -BEGIN_PROD(SPIRIT_TECHNOLOGY_2) -END - -BEGIN_PROD(BSC_ALFADATA_1) - PROD("ALF 3", SCSI, BSC_ALF_3_1) -END - -BEGIN_PROD(BSC_ALFADATA_2) - PROD("ALF 2", SCSI, BSC_ALF_2_1) - PROD("ALF 2", SCSI, BSC_ALF_2_2) - PROD("ALF 3", SCSI, BSC_ALF_3_2) -END - -BEGIN_PROD(CARDCO_2) - PROD("Kronos", SCSI, CARDCO_KRONOS_2000_2) - PROD("A1000", SCSI, CARDCO_A1000_2) -END - -BEGIN_PROD(JOCHHEIM) - PROD(NULL, RAM, JOCHHEIM_RAM) -END - -BEGIN_PROD(CHECKPOINT_TECHNOLOGIES) - PROD("Serial Solution", SERIAL, CHECKPOINT_TECHNOLOGIES_SERIAL_SOLUTION) -END - -BEGIN_PROD(EDOTRONIK) - PROD("IEEE-488 Interface Board", UNKNOWN, EDOTRONIK_IEEE_488) - PROD("CBM-8032 Board", UNKNOWN, EDOTRONIK_8032) - PROD(NULL, SERIAL, EDOTRONIK_MULTISERIAL) - PROD("24Bit Realtime Video Digitizer", UNKNOWN, EDOTRONIK_VIDEODIGITIZER) - PROD("32Bit Parallel I/O Interface", UNKNOWN, EDOTRONIK_PARALLEL_IO) - PROD("PIC Prototyping Board", UNKNOWN, EDOTRONIK_PIC_PROTOYPING) - PROD("16 Channel ADC Interface", UNKNOWN, EDOTRONIK_ADC) - PROD("VME-Bus Controller", UNKNOWN, EDOTRONIK_VME) - PROD("DSP96000 Realtime Data Acquisition", DSP, EDOTRONIK_DSP96000) -END - -BEGIN_PROD(NES_INC) - PROD(NULL, RAM, NES_INC_RAM) -END - -BEGIN_PROD(ICD) - PROD("Advantage 2000", SCSI, ICD_ADVANTAGE_2000_SCSI) - PROD("Advantage", IDE, ICD_ADVANTAGE_2000_SCSI) - PROD("Advantage 2080", RAM, ICD_ADVANTAGE_2080_RAM) -END - -BEGIN_PROD(KUPKE_2) - PROD("Omti", HD, KUPKE_OMTI) - PROD("Golem SCSI-II", SCSI, KUPKE_SCSI_II) - PROD("Golem Box", UNKNOWN, KUPKE_GOLEM_BOX) - PROD("030/882", TURBO, KUPKE_030_882) - PROD("Golem", SCSI, KUPKE_SCSI_AT) -END - -BEGIN_PROD(GREAT_VALLEY_PRODUCTS_3) - PROD("A2000-RAM8/2", MISC, GVP_A2000_RAM8) - PROD("Impact Series II", RAM, GVP_IMPACT_SERIES_II_RAM_2) -END - -BEGIN_PROD(INTERWORKS_NETWORK) -END - -BEGIN_PROD(HARDITAL_SYNTHESIS) - PROD("TQM 68030+68882", TURBO, HARDITAL_SYNTHESIS_TQM_68030_68882) -END - -BEGIN_PROD(APPLIED_ENGINEERING) - PROD("DL2000", MODEM, APPLIED_ENGINEERING_DL2000) - PROD("RAM Works", RAM, APPLIED_ENGINEERING_RAM_WORKS) -END - -BEGIN_PROD(BSC_ALFADATA_3) - PROD("Oktagon 2008", SCSI, BSC_OKTAGON_2008) - PROD("Tandem AT-2008/508", IDE, BSC_TANDEM_AT_2008_508) - PROD("Alpha RAM 1200", RAM, BSC_ALFA_RAM_1200) - PROD("Oktagon 2008", RAM, BSC_OKTAGON_2008_RAM) - PROD("MultiFace I", MULTIIO, BSC_MULTIFACE_I) - PROD("MultiFace II", MULTIIO, BSC_MULTIFACE_II) - PROD("MultiFace III", MULTIIO, BSC_MULTIFACE_III) - PROD("Framebuffer", MISC, BSC_FRAMEBUFFER) - PROD("Graffiti", GFXRAM, BSC_GRAFFITI_RAM) - PROD("Graffiti", GFX, BSC_GRAFFITI_REG) - PROD("ISDN MasterCard", ISDN, BSC_ISDN_MASTERCARD) - PROD("ISDN MasterCard II", ISDN, BSC_ISDN_MASTERCARD_II) -END - -BEGIN_PROD(PHOENIX) - PROD("ST506", HD, PHOENIX_ST506) - PROD(NULL, SCSI, PHOENIX_SCSI) - PROD(NULL, RAM, PHOENIX_RAM) -END - -BEGIN_PROD(ADVANCED_STORAGE_SYSTEMS) - PROD("Nexus", SCSI, ADVANCED_STORAGE_SYSTEMS_NEXUS) - PROD("Nexus", RAM, ADVANCED_STORAGE_SYSTEMS_NEXUS_RAM) -END - -BEGIN_PROD(IMPULSE) - PROD("FireCracker 24", GFX, IMPULSE_FIRECRACKER_24) -END - -BEGIN_PROD(IVS) - PROD("GrandSlam PIC 2", RAM, IVS_GRANDSLAM_PIC_2) - PROD("GrandSlam PIC 1", RAM, IVS_GRANDSLAM_PIC_1) - PROD("OverDrive", HD, IVS_OVERDRIVE) - PROD("TrumpCard Classic", SCSI, IVS_TRUMPCARD_CLASSIC) - PROD("TrumpCard Pro/GrandSlam", SCSI, IVS_TRUMPCARD_PRO_GRANDSLAM) - PROD("Meta-4", RAM, IVS_META_4) - PROD("Wavetools", AUDIO, IVS_WAVETOOLS) - PROD("Vector", SCSI, IVS_VECTOR_1) - PROD("Vector", SCSI, IVS_VECTOR_2) -END - -BEGIN_PROD(VECTOR_1) - PROD("Connection", MULTIIO, VECTOR_CONNECTION_1) -END - -BEGIN_PROD(XPERT_PRODEV) - PROD("Visiona", GFXRAM, XPERT_PRODEV_VISIONA_RAM) - PROD("Visiona", GFX, XPERT_PRODEV_VISIONA_REG) - PROD("Merlin", GFXRAM, XPERT_PRODEV_MERLIN_RAM) - PROD("Merlin", GFX, XPERT_PRODEV_MERLIN_REG_1) - PROD("Merlin", GFX, XPERT_PRODEV_MERLIN_REG_2) -END - -BEGIN_PROD(HYDRA_SYSTEMS) - PROD("Amiganet", ETHERNET, HYDRA_SYSTEMS_AMIGANET) -END - -BEGIN_PROD(SUNRIZE_INDUSTRIES) - PROD("AD1012", AUDIO, SUNRIZE_INDUSTRIES_AD1012) - PROD("AD516", AUDIO, SUNRIZE_INDUSTRIES_AD516) - PROD("DD512", AUDIO, SUNRIZE_INDUSTRIES_DD512) -END - -BEGIN_PROD(TRICERATOPS) - PROD(NULL, MULTIIO, TRICERATOPS_MULTI_IO) -END - -BEGIN_PROD(APPLIED_MAGIC) - PROD("DMI Resolver", GFX, APPLIED_MAGIC_DMI_RESOLVER) - PROD("Digital Broadcaster", VIDEO, APPLIED_MAGIC_DIGITAL_BROADCASTER) -END - -BEGIN_PROD(GFX_BASE) - PROD("GDA-1 VRAM", GFX, GFX_BASE_GDA_1_VRAM) - PROD("GDA-1", GFX, GFX_BASE_GDA_1) -END - -BEGIN_PROD(ROCTEC) - PROD("RH 800C", HD, ROCTEC_RH_800C) - PROD("RH 800C", RAM, ROCTEC_RH_800C_RAM) -END - -BEGIN_PROD(KATO) - PROD("Melody MPEG", AUDIO, KATO_MELODY) - PROD("Rainbow II", GFX, HELFRICH_RAINBOW_II) /* ID clash!! */ - PROD("Rainbow III", GFX, HELFRICH_RAINBOW_III) /* ID clash!! */ -END - -BEGIN_PROD(ATLANTIS) -END - -BEGIN_PROD(PROTAR) -END - -BEGIN_PROD(ACS) -END - -BEGIN_PROD(SOFTWARE_RESULTS_ENTERPRISES) - PROD("Golden Gate 2 Bus+", BRIDGE, SOFTWARE_RESULTS_ENTERPRISES_GOLDEN_GATE_2_BUS_PLUS) -END - -BEGIN_PROD(MASOBOSHI) - PROD("MasterCard SC201", RAM, MASOBOSHI_MASTER_CARD_SC201) - PROD("MasterCard MC702", SCSI_IDE, MASOBOSHI_MASTER_CARD_MC702) - PROD("MVD 819", UNKNOWN, MASOBOSHI_MVD_819) -END - -BEGIN_PROD(MAINHATTAN_DATA) - PROD(NULL, IDE, MAINHATTAN_DATA_IDE) -END - -BEGIN_PROD(VILLAGE_TRONIC) - PROD("Domino", GFXRAM, VILLAGE_TRONIC_DOMINO_RAM) - PROD("Domino", GFX, VILLAGE_TRONIC_DOMINO_REG) - PROD("Domino 16M Prototype", GFX, VILLAGE_TRONIC_DOMINO_16M_PROTOTYPE) - PROD("Picasso II/II+", GFXRAM, VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM) - PROD("Picasso II/II+", GFX, VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG) - PROD("Picasso II/II+ (Segmented Mode)", GFX, VILLAGE_TRONIC_PICASSO_II_II_PLUS_SEGMENTED_MODE) - PROD("Picasso IV Z2", GFXRAM, VILLAGE_TRONIC_PICASSO_IV_Z2_MEM1) - PROD("Picasso IV Z2", GFXRAM, VILLAGE_TRONIC_PICASSO_IV_Z2_MEM2) - PROD("Picasso IV Z2", GFX, VILLAGE_TRONIC_PICASSO_IV_Z2_REG) - PROD("Picasso IV Z3", GFX, VILLAGE_TRONIC_PICASSO_IV_Z3) - PROD("Ariadne", ETHERNET_PARALLEL, VILLAGE_TRONIC_ARIADNE) -END - -BEGIN_PROD(UTILITIES_UNLIMITED) - PROD("Emplant Deluxe", MACEMU, UTILITIES_UNLIMITED_EMPLANT_DELUXE) - PROD("Emplant Deluxe", MACEMU, UTILITIES_UNLIMITED_EMPLANT_DELUXE2) -END - -BEGIN_PROD(AMITRIX) - PROD(NULL, MULTIIO, AMITRIX_MULTI_IO) - PROD("CD-RAM", RAM, AMITRIX_CD_RAM) -END - -BEGIN_PROD(ARMAX) - PROD("OmniBus", GFX, ARMAX_OMNIBUS) -END - -BEGIN_PROD(NEWTEK) - PROD("VideoToaster", VIDEO, NEWTEK_VIDEOTOASTER) -END - -BEGIN_PROD(M_TECH_GERMANY) - PROD("AT500", IDE, MTEC_AT500_2) - PROD("68030", TURBO, MTEC_68030) - PROD("68020i", TURBO, MTEC_68020I) - PROD("A1200 T68030 RTC", TURBO, MTEC_A1200_T68030_RTC) - PROD("Viper Mk V/E-Matrix 530", TURBO_RAM, MTEC_VIPER_MK_V_E_MATRIX_530) - PROD("8MB", RAM, MTEC_8_MB_RAM) - PROD("Viper Mk V/E-Matrix 530 SCSI/IDE", SCSI_IDE, MTEC_VIPER_MK_V_E_MATRIX_530_SCSI_IDE) -END - -BEGIN_PROD(GREAT_VALLEY_PRODUCTS_4) - PROD("EGS 28/24 Spectrum", GFX, GVP_EGS_28_24_SPECTRUM_REG) - PROD("EGS 28/24 Spectrum", GFXRAM, GVP_EGS_28_24_SPECTRUM_RAM) -END - -BEGIN_PROD(APOLLO_1) - PROD("A1200", FPU_RAM, APOLLO_A1200) -END - -BEGIN_PROD(HELFRICH_2) - PROD("Piccolo", GFXRAM, HELFRICH_PICCOLO_RAM) - PROD("Piccolo", GFX, HELFRICH_PICCOLO_REG) - PROD("PeggyPlus MPEG", VIDEO, HELFRICH_PEGGY_PLUS_MPEG) - PROD("VideoCruncher", VIDEO, HELFRICH_VIDEOCRUNCHER) - PROD("Piccolo SD64", GFXRAM, HELFRICH_SD64_RAM) - PROD("Piccolo SD64", GFX, HELFRICH_SD64_REG) -END - -BEGIN_PROD(MACROSYSTEMS_USA) - PROD("Warp Engine 40xx", TURBO_SCSI_RAM, MACROSYSTEMS_WARP_ENGINE_40xx) -END - -BEGIN_PROD(ELBOX_COMPUTER) - PROD("1200/4", RAM, ELBOX_COMPUTER_1200_4) -END - -BEGIN_PROD(HARMS_PROFESSIONAL) - PROD("030 Plus", TURBO, HARMS_PROFESSIONAL_030_PLUS) - PROD("3500 Professional", TURBO_RAM, HARMS_PROFESSIONAL_3500) -END - -BEGIN_PROD(MICRONIK) - PROD("RCA 120", RAM, MICRONIK_RCA_120) -END - -BEGIN_PROD(MICRONIK2) - PROD("Z3i A1200 Zorro III + SCSI", SCSI, MICRONIK2_Z3I) -END - -BEGIN_PROD(MEGAMICRO) - PROD("SCRAM 500", SCSI, MEGAMICRO_SCRAM_500) - PROD("SCRAM 500", RAM, MEGAMICRO_SCRAM_500_RAM) -END - -BEGIN_PROD(IMTRONICS_2) - PROD("Hurricane 2800", TURBO_RAM, IMTRONICS_HURRICANE_2800_3) - PROD("Hurricane 2800", TURBO_RAM, IMTRONICS_HURRICANE_2800_4) -END - -BEGIN_PROD(INDIVIDUAL_COMPUTERS) - PROD("Buddha", IDE, INDIVIDUAL_COMPUTERS_BUDDHA) - PROD("Catweasel", IDE_FLOPPY, INDIVIDUAL_COMPUTERS_CATWEASEL) -END - -BEGIN_PROD(KUPKE_3) - PROD("Golem HD 3000", HD, KUPKE_GOLEM_HD_3000) -END - -BEGIN_PROD(ITH) - PROD("ISDN-Master II", ISDN, ITH_ISDN_MASTER_II) -END - -BEGIN_PROD(VMC) - PROD("ISDN Blaster Z2", ISDN, VMC_ISDN_BLASTER_Z2) - PROD("HyperCom 4", MULTIIO, VMC_HYPERCOM_4) -END - -BEGIN_PROD(INFORMATION) - PROD("ISDN Engine I", ISDN, INFORMATION_ISDN_ENGINE_I) -END - -BEGIN_PROD(VORTEX) - PROD("Golden Gate 80386SX", BRIDGE, VORTEX_GOLDEN_GATE_80386SX) - PROD("Golden Gate", RAM, VORTEX_GOLDEN_GATE_RAM) - PROD("Golden Gate 80486", BRIDGE, VORTEX_GOLDEN_GATE_80486) -END - -BEGIN_PROD(EXPANSION_SYSTEMS) - PROD("DataFlyer 4000SX", SCSI, EXPANSION_SYSTEMS_DATAFLYER_4000SX) - PROD("DataFlyer 4000SX", RAM, EXPANSION_SYSTEMS_DATAFLYER_4000SX_RAM) -END - -BEGIN_PROD(READYSOFT) - PROD("AMax II/IV", MACEMU, READYSOFT_AMAX_II_IV) -END - -BEGIN_PROD(PHASE5) - PROD("Blizzard", RAM, PHASE5_BLIZZARD_RAM) - PROD("Blizzard", TURBO, PHASE5_BLIZZARD) - PROD("Blizzard 1220-IV", TURBO, PHASE5_BLIZZARD_1220_IV) - PROD("FastLane Z3", RAM, PHASE5_FASTLANE_Z3_RAM) - PROD("Blizzard 1230-II/Fastlane Z3/CyberSCSI/CyberStorm060", TURBO_SCSI, PHASE5_BLIZZARD_1230_II_FASTLANE_Z3_CYBERSCSI_CYBERSTORM060) - PROD("Blizzard 1220/CyberStorm", TURBO_SCSI, PHASE5_BLIZZARD_1220_CYBERSTORM) - PROD("Blizzard 1230", TURBO, PHASE5_BLIZZARD_1230) - PROD("Blizzard 1230-IV/1260", TURBO, PHASE5_BLIZZARD_1230_IV_1260) - PROD("Blizzard 2060", TURBO, PHASE5_BLIZZARD_2060) - PROD("CyberStorm Mk II", FLASHROM, PHASE5_CYBERSTORM_MK_II) - PROD("CyberVision64", GFX, PHASE5_CYBERVISION64) - PROD("CyberVision64-3D Prototype", GFX, PHASE5_CYBERVISION64_3D_PROTOTYPE) - PROD("CyberVision64-3D", GFX, PHASE5_CYBERVISION64_3D) - PROD("CyberStorm Mk III", TURBO_SCSI, PHASE5_CYBERSTORM_MK_III) -END - -BEGIN_PROD(DPS) - PROD("Personal Animation Recorder", VIDEO, DPS_PERSONAL_ANIMATION_RECORDER) -END - -BEGIN_PROD(APOLLO_2) - PROD("A620 68020", TURBO, APOLLO_A620_68020_1) - PROD("A620 68020", TURBO, APOLLO_A620_68020_2) -END - -BEGIN_PROD(APOLLO_3) - PROD("AT-Apollo", UNKNOWN, APOLLO_AT_APOLLO) - PROD("1230/1240/1260/2030/4040/4060", TURBO, APOLLO_1230_1240_1260_2030_4040_4060) -END - -BEGIN_PROD(PETSOFF_LP) - PROD("Delfina", AUDIO, PETSOFF_LP_DELFINA) - PROD("Delfina Lite", AUDIO, PETSOFF_LP_DELFINA_LITE) -END - -BEGIN_PROD(UWE_GERLACH) - PROD("RAM/ROM", MISC, UWE_GERLACH_RAM_ROM) -END - -BEGIN_PROD(MACROSYSTEMS_GERMANY) - PROD("Maestro", AUDIO, MACROSYSTEMS_MAESTRO) - PROD("VLab", VIDEO, MACROSYSTEMS_VLAB) - PROD("Maestro Pro", AUDIO, MACROSYSTEMS_MAESTRO_PRO) - PROD("Retina", GFX, MACROSYSTEMS_RETINA) - PROD("MultiEvolution", SCSI, MACROSYSTEMS_MULTI_EVOLUTION) - PROD("Toccata", AUDIO, MACROSYSTEMS_TOCCATA) - PROD("Retina Z3", GFX, MACROSYSTEMS_RETINA_Z3) - PROD("VLab Motion", VIDEO, MACROSYSTEMS_VLAB_MOTION) - PROD("Altais", GFX, MACROSYSTEMS_ALTAIS) - PROD("Falcon '040", TURBO, MACROSYSTEMS_FALCON_040) -END - -BEGIN_PROD(COMBITEC) -END - -BEGIN_PROD(SKI_PERIPHERALS) - PROD("MAST Fireball", SCSI, SKI_PERIPHERALS_MAST_FIREBALL) - PROD("SCSI/Dual Serial", SCSI_SERIAL, SKI_PERIPHERALS_SCSI_DUAL_SERIAL) -END - -BEGIN_PROD(REIS_WARE_2) - PROD("Scan King", SCANNER, REIS_WARE_SCAN_KING) -END - -BEGIN_PROD(CAMERON) - PROD("Personal A4", SCANNER, CAMERON_PERSONAL_A4) -END - -BEGIN_PROD(REIS_WARE) - PROD("Handyscanner", SCANNER, REIS_WARE_HANDYSCANNER) -END - -BEGIN_PROD(PHOENIX_2) - PROD("ST506", HD, PHOENIX_ST506_2) - PROD(NULL, SCSI, PHOENIX_SCSI_2) - PROD(NULL, RAM, PHOENIX_RAM_2) -END - -BEGIN_PROD(COMBITEC_2) - PROD(NULL, HD, COMBITEC_HD) - PROD("SRAM", RAM, COMBITEC_SRAM) -END - -BEGIN_PROD(HACKER) /* Unused */ -END - - -BEGIN_MANUF - MANUF("Pacific Peripherals", PACIFIC_PERIPHERALS) - MANUF("MacroSystems USA", MACROSYSTEMS_USA_2) - MANUF("Kupke", KUPKE_1) - MANUF("Memphis", MEMPHIS) - MANUF("3-State", 3_STATE) - MANUF("Commodore Braunschweig", COMMODORE_BRAUNSCHWEIG) - MANUF("Commodore West Chester", COMMODORE_WEST_CHESTER_1) - MANUF("Commodore West Chester", COMMODORE_WEST_CHESTER_2) - MANUF("Progressive Peripherals & Systems", PROGRESSIVE_PERIPHERALS_AND_SYSTEMS_2) - MANUF("Kolff Computer Supplies", KOLFF_COMPUTER_SUPPLIES) - MANUF("Cardco Ltd.", CARDCO_1) - MANUF("A-Squared", A_SQUARED) - MANUF("Comspec Communications", COMSPEC_COMMUNICATIONS) - MANUF("Anakin Research", ANAKIN_RESEARCH) - MANUF("Microbotics", MICROBOTICS) - MANUF("Access Associates Alegra", ACCESS_ASSOCIATES_ALEGRA) - MANUF("Expansion Technologies (Pacific Cypress)", EXPANSION_TECHNOLOGIES) - MANUF("ASDG", ASDG) - MANUF("Ronin/Imtronics", IMTRONICS_1) - MANUF("Commodore/University of Lowell", CBM_UNIVERSITY_OF_LOWELL) - MANUF("Ameristar", AMERISTAR) - MANUF("Supra", SUPRA) - MANUF("Computer Systems Assosiates", COMPUTER_SYSTEMS_ASSOCIATES) - MANUF("Marc Michael Groth", MARC_MICHAEL_GROTH) - MANUF("M-Tech", M_TECH) - MANUF("Great Valley Products", GREAT_VALLEY_PRODUCTS_1) - MANUF("ByteBox", BYTEBOX) - MANUF("DKB/Power Computing", DKB_POWER_COMPUTING) - MANUF("Great Valley Products", GREAT_VALLEY_PRODUCTS_2) - MANUF("California Access (Synergy)", CALIFORNIA_ACCESS_SYNERGY) - MANUF("Xetec", XETEC) - MANUF("Progressive Peripherals & Systems", PROGRESSIVE_PERIPHERALS_AND_SYSTEMS) - MANUF("Xebec", XEBEC) - MANUF("Spirit Technology", SPIRIT_TECHNOLOGY) - MANUF("Spirit Technology", SPIRIT_TECHNOLOGY_2) - MANUF("BSC/Alfadata", BSC_ALFADATA_1) - MANUF("BSC/Alfadata", BSC_ALFADATA_2) - MANUF("Cardco Ltd.", CARDCO_2) - MANUF("Jochheim", JOCHHEIM) - MANUF("Checkpoint Technologies", CHECKPOINT_TECHNOLOGIES) - MANUF("Edotronik", EDOTRONIK) - MANUF("NES Inc.", NES_INC) - MANUF("ICD", ICD) - MANUF("Kupke", KUPKE_2) - MANUF("Great Valley Products", GREAT_VALLEY_PRODUCTS_3) - MANUF("Interworks Network", INTERWORKS_NETWORK) - MANUF("Hardital Synthesis", HARDITAL_SYNTHESIS) - MANUF("Applied Engineering", APPLIED_ENGINEERING) - MANUF("BSC/Alfadata", BSC_ALFADATA_3) - MANUF("Phoenix", PHOENIX) - MANUF("Advanced Storage Systems", ADVANCED_STORAGE_SYSTEMS) - MANUF("Impulse", IMPULSE) - MANUF("IVS", IVS) - MANUF("Vector", VECTOR_1) - MANUF("XPert ProDev", XPERT_PRODEV) - MANUF("Hydra Systems", HYDRA_SYSTEMS) - MANUF("Sunrize Industries", SUNRIZE_INDUSTRIES) - MANUF("Triceratops", TRICERATOPS) - MANUF("Applied Magic Inc.", APPLIED_MAGIC) - MANUF("GFX-Base", GFX_BASE) - MANUF("RocTec", ROCTEC) - MANUF("Kato", KATO) - MANUF("Atlantis", ATLANTIS) - MANUF("Protar", PROTAR) - MANUF("ACS", ACS) - MANUF("Software Results Enterprises", SOFTWARE_RESULTS_ENTERPRISES) - MANUF("Masoboshi", MASOBOSHI) - MANUF("Mainhattan-Data (A-Team)", MAINHATTAN_DATA) - MANUF("Village Tronic", VILLAGE_TRONIC) - MANUF("Utilities Unlimited", UTILITIES_UNLIMITED) - MANUF("Amitrix", AMITRIX) - MANUF("ArMax", ARMAX) - MANUF("NewTek", NEWTEK) - MANUF("M-Tech Germany", M_TECH_GERMANY) - MANUF("Great Valley Products", GREAT_VALLEY_PRODUCTS_4) - MANUF("Apollo", APOLLO_1) - MANUF("Ingenieurbüro Helfrich", HELFRICH_2) - MANUF("MacroSystems USA", MACROSYSTEMS_USA) - MANUF("ElBox Computer", ELBOX_COMPUTER) - MANUF("Harms Professional", HARMS_PROFESSIONAL) - MANUF("Micronik", MICRONIK) - MANUF("Micronik", MICRONIK2) - MANUF("MegaMicro", MEGAMICRO) - MANUF("Ronin/Imtronics", IMTRONICS_2) - MANUF("Individual Computers", INDIVIDUAL_COMPUTERS) - MANUF("Kupke", KUPKE_3) - MANUF("ITH", ITH) - MANUF("VMC", VMC) - MANUF("Information", INFORMATION) - MANUF("Vortex", VORTEX) - MANUF("Expansion Systems", EXPANSION_SYSTEMS) - MANUF("ReadySoft", READYSOFT) - MANUF("Phase 5", PHASE5) - MANUF("DPS", DPS) - MANUF("Apollo", APOLLO_2) - MANUF("Apollo", APOLLO_3) - MANUF("Petsoff LP", PETSOFF_LP) - MANUF("Uwe Gerlach", UWE_GERLACH) - MANUF("MacroSystems Germany", MACROSYSTEMS_GERMANY) - MANUF("Combitec", COMBITEC) - MANUF("SKI Peripherals", SKI_PERIPHERALS) - MANUF("Reis-Ware", REIS_WARE_2) - MANUF("Cameron", CAMERON) - MANUF("Reis-Ware", REIS_WARE) - MANUF("Hacker Test Board", HACKER) /* Unused */ - MANUF("Phoenix", PHOENIX_2) - MANUF("Combitec", COMBITEC_2) -END - -#define NUM_MANUF (ARRAYSIZE(Manufacturers)) -#define NUM_GVP_PROD (ARRAYSIZE(Ext_Prod_GVP)) - - - /* - * Zorro product classes - * - * Make sure to keep these in sync with include/linux/zorro.h! - */ - -static const char *classnames[] = { - NULL, /* ZORRO_CLASS_UNKNOWN */ - "ArcNet Card", /* ZORRO_CLASS_ARCNET */ - "Audio Board", /* ZORRO_CLASS_AUDIO */ - "ISA Bus Bridge", /* ZORRO_CLASS_BRIDGE */ - "DSP Board", /* ZORRO_CLASS_DSP */ - "Ethernet Card", /* ZORRO_CLASS_ETHERNET */ - "Ethernet Card and Parallel Ports", /* ZORRO_CLASS_ETHERNET_PARALLEL */ - "Flash ROM", /* ZORRO_CLASS_FLASHROM */ - "FPU and RAM Expansion", /* ZORRO_CLASS_FPU_RAM */ - "Graphics Board", /* ZORRO_CLASS_GFX */ - "Graphics Board (RAM)", /* ZORRO_CLASS_GFXRAM */ - "HD Controller", /* ZORRO_CLASS_HD */ - "HD Controller and RAM Expansion", /* ZORRO_CLASS_HD_RAM */ - "IDE Interface", /* ZORRO_CLASS_IDE */ - "IDE Interface and RAM Expansion", /* ZORRO_CLASS_IDE_RAM */ - "IDE Interface and Floppy Controller", /* ZORRO_CLASS_IDE_FLOPPY */ - "ISDN Interface", /* ZORRO_CLASS_ISDN */ - "Macintosh Emulator", /* ZORRO_CLASS_MACEMU */ - "Miscellaneous Expansion Card", /* ZORRO_CLASS_MISC */ - "Modem", /* ZORRO_CLASS_MODEM */ - "Multi I/O", /* ZORRO_CLASS_MULTIIO */ - "RAM Expansion", /* ZORRO_CLASS_RAM */ - "Scanner Interface", /* ZORRO_CLASS_SCANNER */ - "SCSI Host Adapter", /* ZORRO_CLASS_SCSI */ - "SCSI Host Adapter and IDE Interface", /* ZORRO_CLASS_SCSI_IDE */ - "SCSI Host Adapter and RAM Expansion", /* ZORRO_CLASS_SCSI_RAM */ - "SCSI Host Adapter and Serial Card", /* ZORRO_CLASS_SCSI_SERIAL */ - "Multi Serial", /* ZORRO_CLASS_SERIAL */ - "Drawing Tablet Interface", /* ZORRO_CLASS_TABLET */ - "Accelerator", /* ZORRO_CLASS_TURBO */ - "Accelerator and RAM Expansion", /* ZORRO_CLASS_TURBO_RAM */ - "Accelerator and HD Controller", /* ZORRO_CLASS_TURBO_HD */ - "Accelerator and IDE Interface", /* ZORRO_CLASS_TURBO_IDE */ - "Accelerator and SCSI Host Adapter", /* ZORRO_CLASS_TURBO_SCSI */ - "Accelerator, SCSI Host Adapter and RAM Expansion", /* ZORRO_CLASS_TURBO_SCSI */ - "Video Board", /* ZORRO_CLASS_VIDEO */ -}; - -static inline const char *get_class_name(enum Zorro_Classes class) -{ - if (class < ARRAYSIZE(classnames)) - return(classnames[class]); - else - return("(**Illegal**)"); -} - -#endif /* CONFIG_ZORRO */ - - - /* - * Expansion Devices - */ - -u_int zorro_num_autocon; -struct ConfigDev zorro_autocon[ZORRO_NUM_AUTO]; -static u32 BoardPartFlags[ZORRO_NUM_AUTO] = { 0, }; - - - /* - * Find the key for the next unconfigured expansion device of a specific - * type. - * - * Part is a device specific number (0 <= part <= 31) to allow for the - * independent configuration of independent parts of an expansion board. - * Thanks to Jes Soerensen for this idea! - * - * Index is used to specify the first board in the autocon list - * to be tested. It was inserted in order to solve the problem - * with the GVP boards that uses the same product code, but - * it should help if there are other companies which use the same - * method as GVP. Drivers for boards which are not using this - * method do not need to think of this - just set index = 0. - * - * Example: - * - * while ((key = zorro_find(ZORRO_PROD_MY_BOARD, MY_PART, 0))) { - * cd = zorro_get_board(key); - * initialise_this_board; - * zorro_config_board(key, MY_PART); - * } - */ - -u_int zorro_find(zorro_id id, u_int part, u_int index) -{ - u_int manuf = ZORRO_MANUF(id); - u_int prod = ZORRO_PROD(id); - u_int epc = ZORRO_EPC(id); - u_int key; - const struct ConfigDev *cd; - u_long addr; - - if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(ZORRO)) - return(0); - - if (part > 31) { - printk("zorro_find: bad part %d\n", part); - return(0); - } - - for (key = index + 1; key <= zorro_num_autocon; key++) { - cd = &zorro_autocon[key-1]; - addr = (u_long)cd->cd_BoardAddr; - if ((cd->cd_Rom.er_Manufacturer == manuf) && - (cd->cd_Rom.er_Product == prod) && - !(BoardPartFlags[key-1] & (1< zorro_num_autocon)) - printk("zorro_get_board: bad key %d\n", key); - else - cd = &zorro_autocon[key-1]; - - return(cd); -} - - - /* - * Mark a part of a board as configured - */ - -void zorro_config_board(u_int key, u_int part) -{ - if ((key < 1) || (key > zorro_num_autocon)) - printk("zorro_config_board: bad key %d\n", key); - else if (part > 31) - printk("zorro_config_board: bad part %d\n", part); - else if (BoardPartFlags[key-1] & (1< zorro_num_autocon)) - printk("zorro_unconfig_board: bad key %d\n", key); - else if (part > 31) - printk("zorro_unconfig_board: bad part %d\n", part); - else if (!(BoardPartFlags[key-1] & (1<cd_Rom.er_Manufacturer; - u_int prod = cd->cd_Rom.er_Product; - u_int class = ZORRO_CLASS_UNKNOWN; - u_int epc = 0; - const char *manufname = "Unknown"; - const char *prodname = "Unknown"; - const char *classname; - u_int i, j, k, len = 0; - u_long addr = (u_long)cd->cd_BoardAddr; - u_long size = cd->cd_BoardSize; - char mag; - int identified = 0, gvp = 0; - - if (manuf != ZORRO_MANUF(ZORRO_PROD_GVP_EPC_BASE) || - prod != ZORRO_PROD(ZORRO_PROD_GVP_EPC_BASE)) { - for (i = 0; i < NUM_MANUF; i++) - if (Manufacturers[i].Manuf == manuf) { - manufname = Manufacturers[i].Name; - for (j = 0; j < Manufacturers[i].NumProd; j++) - if (Manufacturers[i].Products[j].Prod == prod) { - prodname = Manufacturers[i].Products[j].Name; - class = Manufacturers[i].Products[j].Class; - identified = 1; - break; - } - } - /* Put workarounds for ID clashes here */ - if (manuf == ZORRO_MANUF(ZORRO_PROD_HELFRICH_RAINBOW_III) && - prod == ZORRO_PROD(ZORRO_PROD_HELFRICH_RAINBOW_III)) - manufname = "Ingenieurbüro Helfrich"; - } else { - manufname = "Great Valley Products"; - gvp = 1; - epc = *(u_short *)ZTWO_VADDR(addr+0x8000) & GVP_PRODMASK; - for (k = 0; k < NUM_GVP_PROD; k++) - if (epc == Ext_Prod_GVP[k].EPC) { - prodname = Ext_Prod_GVP[k].Name; - class = Ext_Prod_GVP[k].Class; - identified = 1; - break; - } - } - classname = get_class_name(class); - if (size & 0xfffff) { - size >>= 10; - mag = 'K'; - } else { - size >>= 20; - mag = 'M'; - } - if (verbose) { - const char *zorro; - int is_mem = cd->cd_Rom.er_Type & ERTF_MEMLIST; - switch (cd->cd_Rom.er_Type & ERT_TYPEMASK) { - case ERT_ZORROII: - zorro = "Zorro II"; - break; - case ERT_ZORROIII: - zorro = "Zorro III"; - break; - default: - zorro = "Unknown Zorro"; - break; - } - if (!prodname) - prodname = "Unknown"; - if (!classname) - classname = "Unknown"; - len = sprintf(buf, " Device %d at 0x%08lx: ID=%04x:%02x", devnum, - addr, manuf, prod); - if (gvp) - len += sprintf(buf+len, ":%02x", epc); - len += sprintf(buf+len, ", %s, %ld%c", zorro, size, mag); - if (is_mem) - len += sprintf(buf+len, ", System RAM"); - else - len += sprintf(buf+len, ", Configured=%08x", configured); - len += sprintf(buf+len, "\n" - " Manufacturer: %s\n" - " Product Name: %s\n" - " Board Class : %s\n", - manufname, prodname, classname); - } else { - len = sprintf(buf, " %c%08lx: ", configured ? '*' : ' ', addr); - if (identified) { - len += sprintf(buf+len, "%s", manufname); - if (prodname) - len += sprintf(buf+len, " %s", prodname); - if (classname) - len += sprintf(buf+len, " %s", classname); - } else if (manuf == ZORRO_MANUF_HACKER) - len += sprintf(buf+len, "Hacker Test Board %02x", prod); - else if (gvp) - len += sprintf(buf+len, "[%04x:%02x:%02x] made by %s", manuf, prod, - epc, manufname); - else - len += sprintf(buf+len, "[%04x:%02x] made by %s", manuf, prod, - manufname); - len += sprintf(buf+len, " (%ld%c)\n", size, mag); - if (!identified && manuf != ZORRO_MANUF_HACKER) - len += sprintf(buf+len, " Please report this unknown device to " - "zorro@linux-m68k.org\n"); - } - return(len); -} - - - /* - * Identify all known AutoConfig Expansion Devices - */ - -void zorro_identify(void) -{ - u_int i; - char tmp[256]; - - if (!AMIGAHW_PRESENT(ZORRO)) - return; - - printk("Probing AutoConfig expansion device(s):\n"); - for (i = 0; i < zorro_num_autocon; i++) { - identify(i, tmp, 0); - printk(tmp); - } - if (!zorro_num_autocon) - printk("No AutoConfig expansion devices present.\n"); -} - - - /* - * Get the list of all AutoConfig Expansion Devices - */ - -int zorro_get_list(char *buffer) -{ - u_int i, len = 0, len2; - char tmp[256]; - - if (MACH_IS_AMIGA && AMIGAHW_PRESENT(ZORRO)) { - len = sprintf(buffer, "AutoConfig expansion devices:\n"); - for (i = 0; i < zorro_num_autocon; i++) { - len2 = identify(i, tmp, 1); - if (len+len2 >= 4075) { - len += sprintf(buffer+len, "4K limit reached!\n"); - break; - } - strcpy(buffer+len, tmp); - len += len2; - } - } - return(len); -} - -#endif /* CONFIG_ZORRO */ - - - /* - * Bitmask indicating portions of available Zorro II RAM that are unused - * by the system. Every bit represents a 64K chunk, for a maximum of 8MB - * (128 chunks, physical 0x00200000-0x009fffff). - * - * If you want to use (= allocate) portions of this RAM, you should clear - * the corresponding bits. - * - * Possible uses: - * - z2ram device - * - SCSI DMA bounce buffers - */ - -u32 zorro_unused_z2ram[4] = { 0, 0, 0, 0 }; - - -static void mark_region(u_long addr, u_long size, int flag) -{ - u_long start, end, chunk; - - if (flag) { - start = (addr+Z2RAM_CHUNKMASK) & ~Z2RAM_CHUNKMASK; - end = (addr+size) & ~Z2RAM_CHUNKMASK; - } else { - start = addr & ~Z2RAM_CHUNKMASK; - end = (addr+size+Z2RAM_CHUNKMASK) & ~Z2RAM_CHUNKMASK; - } - if (end <= Z2RAM_START || start >= Z2RAM_END) - return; - start = start < Z2RAM_START ? 0x00000000 : start-Z2RAM_START; - end = end > Z2RAM_END ? Z2RAM_SIZE : end-Z2RAM_START; - while (start < end) { - chunk = start>>Z2RAM_CHUNKSHIFT; - if (flag) - set_bit( chunk, zorro_unused_z2ram ); - else - clear_bit( chunk, zorro_unused_z2ram ); - start += Z2RAM_CHUNKSIZE; - } -} - - - /* - * Initialization - */ - -void zorro_init(void) -{ - u_int i; - const struct ConfigDev *cd; - - if (!AMIGAHW_PRESENT(ZORRO)) - return; - - /* Mark all available Zorro II memory */ - for (i = 0; i < zorro_num_autocon; i++) { - cd = &zorro_autocon[i]; - if (cd->cd_Rom.er_Type & ERTF_MEMLIST) - mark_region((u_long)cd->cd_BoardAddr, cd->cd_BoardSize, 1); - } - - /* Unmark all used Zorro II memory */ - for (i = 0; i < m68k_num_memory; i++) - mark_region(m68k_memory[i].addr, m68k_memory[i].size, 0); -} diff -u --recursive --new-file v2.1.105/linux/arch/m68k/atari/ataints.c linux/arch/m68k/atari/ataints.c --- v2.1.105/linux/arch/m68k/atari/ataints.c Tue Feb 17 13:12:44 1998 +++ linux/arch/m68k/atari/ataints.c Sat Jun 13 13:14:32 1998 @@ -294,7 +294,7 @@ addql #8,%%sp addql #4,%%sp jbra "SYMBOL_NAME_STR(ret_from_interrupt) - : : "i" (&kstat.irqs), "n" (PT_OFF_FORMATVEC) + : : "i" (&kstat.irqs[0]), "n" (PT_OFF_FORMATVEC) ); } diff -u --recursive --new-file v2.1.105/linux/arch/m68k/atari/atakeyb.c linux/arch/m68k/atari/atakeyb.c --- v2.1.105/linux/arch/m68k/atari/atakeyb.c Thu Mar 26 15:57:02 1998 +++ linux/arch/m68k/atari/atakeyb.c Sat Jun 13 13:14:32 1998 @@ -28,7 +28,6 @@ #include #include #include -#include #include #include @@ -193,7 +192,7 @@ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200 }; -static u_short atashift_alt_map[NR_KEYS] = { +static u_short atashift_alt_map[NR_KEYS] __initdata = { 0xf200, 0xf81b, 0xf821, 0xf840, 0xf823, 0xf824, 0xf825, 0xf85e, 0xf826, 0xf82a, 0xf828, 0xf829, 0xf85f, 0xf82b, 0xf808, 0xf809, 0xf851, 0xf857, 0xf845, 0xf852, 0xf854, 0xf859, 0xf855, 0xf849, @@ -767,14 +766,17 @@ __initfunc(int atari_keyb_init(void)) { /* setup key map */ - memcpy(plain_map, ataplain_map, sizeof(plain_map)); - memcpy(shift_map, atashift_map, sizeof(shift_map)); + memcpy(key_maps[0], ataplain_map, sizeof(plain_map)); + memcpy(key_maps[1], atashift_map, sizeof(plain_map)); + memcpy(key_maps[4], atactrl_map, sizeof(plain_map)); + memcpy(key_maps[5], atashift_ctrl_map, sizeof(plain_map)); + memcpy(key_maps[8], ataalt_map, sizeof(plain_map)); + /* Atari doesn't have an altgr_map, so we can reuse its memory for + atashift_alt_map */ + memcpy(key_maps[2], atashift_alt_map, sizeof(plain_map)); + key_maps[9] = key_maps[2]; key_maps[2] = 0; /* ataaltgr_map */ - memcpy(ctrl_map, atactrl_map, sizeof(ctrl_map)); - memcpy(shift_ctrl_map, atashift_ctrl_map, sizeof(shift_ctrl_map)); - memcpy(alt_map, ataalt_map, sizeof(alt_map)); - key_maps[9] = atashift_alt_map; - memcpy(ctrl_alt_map, atactrl_alt_map, sizeof(ctrl_alt_map)); + memcpy(key_maps[12], atactrl_alt_map, sizeof(plain_map)); key_maps[13] = atashift_ctrl_alt_map; keymap_count = 8; @@ -859,4 +861,9 @@ k->rate = key_repeat_rate * 1000 / HZ; return( 0 ); +} + +/* for "kbd-reset" cmdline param */ +__initfunc(void kbd_reset_setup(char *str, int *ints)) +{ } diff -u --recursive --new-file v2.1.105/linux/arch/m68k/atari/atasound.c linux/arch/m68k/atari/atasound.c --- v2.1.105/linux/arch/m68k/atari/atasound.c Tue Feb 17 13:12:44 1998 +++ linux/arch/m68k/atari/atasound.c Sat Jun 13 13:14:32 1998 @@ -10,6 +10,9 @@ * License. See the file COPYING in the main directory of this archive * for more details. * + * 1998-05-31 ++andreas: atari_mksound rewritten to always use the envelope, + * no timer, atari_nosound removed. + * */ @@ -31,22 +34,6 @@ * stuff from the old atasound.c */ - -static void atari_nosound (unsigned long ignored) -{ - unsigned char tmp; - unsigned long flags; - - /* turn off generator A in mixer control */ - save_flags(flags); - cli(); - sound_ym.rd_data_reg_sel = 7; - tmp = sound_ym.rd_data_reg_sel; - sound_ym.wd_data = tmp | 0x39; - restore_flags(flags); -} - - void atari_microwire_cmd (int cmd) { tt_microwire.mask = 0x7ff; @@ -58,90 +45,62 @@ } -#define PC_FREQ 1192180 +/* PSG base frequency */ #define PSG_FREQ 125000 +/* PSG envelope base frequency times 10 */ +#define PSG_ENV_FREQ_10 78125 - -void atari_mksound (unsigned int count, unsigned int ticks) +void atari_mksound (unsigned int hz, unsigned int ticks) { - static struct timer_list sound_timer = { NULL, NULL, 0, 0, - atari_nosound }; - /* - * Generates sound of some count for some number of clock ticks - * [count = 1193180 / frequency] - */ + /* Generates sound of some frequency for some number of clock + ticks. */ unsigned long flags; unsigned char tmp; + int period; save_flags(flags); cli(); - if (count == 750 && ticks == HZ/8) { - /* Special case: These values are used by console.c to - * generate the console bell. They are cached here and the - * sound actually generated is somehow special: it uses the - * generator B and an envelope. No timer is needed therefore - * and the bell doesn't disturb an other ongoing sound. - */ + /* Convert from frequency value to PSG period value (base + frequency 125 kHz). */ + period = PSG_FREQ / hz; - /* set envelope duration to 492 ms */ + if (period > 0xfff) period = 0xfff; + + /* Disable generator A in mixer control. */ + sound_ym.rd_data_reg_sel = 7; + tmp = sound_ym.rd_data_reg_sel; + tmp |= 011; + sound_ym.wd_data = tmp; + /* Set generator A frequency to hz. */ + sound_ym.rd_data_reg_sel = 0; + sound_ym.wd_data = period & 0xff; + sound_ym.rd_data_reg_sel = 1; + sound_ym.wd_data = (period >> 8) & 0xf; + if (ticks) { + /* Set length of envelope (max 8 sec). */ + int length = (ticks * PSG_ENV_FREQ_10) / HZ / 10; + + if (length > 0xffff) length = 0xffff; sound_ym.rd_data_reg_sel = 11; - sound_ym.wd_data = 0; + sound_ym.wd_data = length & 0xff; sound_ym.rd_data_reg_sel = 12; - sound_ym.wd_data = 15; - /* envelope form: max -> min single */ + sound_ym.wd_data = length >> 8; + /* Envelope form: max -> min single. */ sound_ym.rd_data_reg_sel = 13; - sound_ym.wd_data = 9; - /* set generator B frequency to 2400 Hz */ - sound_ym.rd_data_reg_sel = 2; - sound_ym.wd_data = 52; - sound_ym.rd_data_reg_sel = 3; sound_ym.wd_data = 0; - /* set volume of generator B to envelope control */ - sound_ym.rd_data_reg_sel = 9; + /* Use envelope for generator A. */ + sound_ym.rd_data_reg_sel = 8; sound_ym.wd_data = 0x10; - /* enable generator B in the mixer control */ - sound_ym.rd_data_reg_sel = 7; - tmp = sound_ym.rd_data_reg_sel; - sound_ym.wd_data = (tmp & ~0x02) | 0x38; - - restore_flags(flags); - return; - } - - del_timer( &sound_timer ); - - if (!count) { - atari_nosound( 0 ); - } - else { - - /* convert from frequency value - * to PSG period value (base frequency 125 kHz). - */ - int period = PSG_FREQ / count; - - if (period > 0xfff) period = 0xfff; - - /* set generator A frequency to 0 */ - sound_ym.rd_data_reg_sel = 0; - sound_ym.wd_data = period & 0xff; - sound_ym.rd_data_reg_sel = 1; - sound_ym.wd_data = (period >> 8) & 0xf; - /* turn on generator A in mixer control (but not noise - * generator!) */ - sound_ym.rd_data_reg_sel = 7; - tmp = sound_ym.rd_data_reg_sel; - sound_ym.wd_data = (tmp & ~0x01) | 0x38; - /* set generator A level to maximum, no envelope */ + } else { + /* Set generator A level to maximum, no envelope. */ sound_ym.rd_data_reg_sel = 8; sound_ym.wd_data = 15; - - if (ticks) { - sound_timer.expires = jiffies + ticks; - add_timer( &sound_timer ); - } } + /* Turn on generator A in mixer control. */ + sound_ym.rd_data_reg_sel = 7; + tmp &= ~1; + sound_ym.wd_data = tmp; restore_flags(flags); } diff -u --recursive --new-file v2.1.105/linux/arch/m68k/atari/config.c linux/arch/m68k/atari/config.c --- v2.1.105/linux/arch/m68k/atari/config.c Fri May 8 23:14:42 1998 +++ linux/arch/m68k/atari/config.c Sat Jun 13 13:14:32 1998 @@ -38,6 +38,7 @@ #include #include #include +#include u_long atari_mch_cookie; u_long atari_mch_type = 0; @@ -98,39 +99,15 @@ extern void (*kd_mksound)(unsigned int, unsigned int); -/* This function tests for the presence of an address, specially a - * hardware register address. It is called very early in the kernel - * initialization process, when the VBR register isn't set up yet. On - * an Atari, it still points to address 0, which is unmapped. So a bus - * error would cause another bus error while fetching the exception - * vector, and the CPU would do nothing at all. So we needed to set up - * a temporary VBR and a vector table for the duration of the test. +/* I've moved hwreg_present() and hwreg_present_bywrite() out into + * mm/hwtest.c, to avoid having multiple copies of the same routine + * in the kernel [I wanted them in hp300 and they were already used + * in the nubus code. NB: I don't have an Atari so this might (just + * conceivably) break something. + * I've preserved the #if 0 version of hwreg_present_bywrite() here + * for posterity. + * -- Peter Maydell , 05/1998 */ - -__initfunc(static int hwreg_present( volatile void *regp )) -{ - int ret = 0; - long save_sp, save_vbr; - long tmp_vectors[3]; - - __asm__ __volatile__ - ( "movec %/vbr,%2\n\t" - "movel #Lberr1,%4@(8)\n\t" - "movec %4,%/vbr\n\t" - "movel %/sp,%1\n\t" - "moveq #0,%0\n\t" - "tstb %3@\n\t" - "nop\n\t" - "moveq #1,%0\n" - "Lberr1:\n\t" - "movel %1,%/sp\n\t" - "movec %2,%/vbr" - : "=&d" (ret), "=&r" (save_sp), "=&r" (save_vbr) - : "a" (regp), "a" (tmp_vectors) - ); - - return( ret ); -} #if 0 __initfunc(static int @@ -163,35 +140,6 @@ } #endif -/* Basically the same, but writes a value into a word register, protected - * by a bus error handler */ - -__initfunc(static int hwreg_write( volatile void *regp, unsigned short val )) -{ - int ret; - long save_sp, save_vbr; - long tmp_vectors[3]; - - __asm__ __volatile__ - ( "movec %/vbr,%2\n\t" - "movel #Lberr2,%4@(8)\n\t" - "movec %4,%/vbr\n\t" - "movel %/sp,%1\n\t" - "moveq #0,%0\n\t" - "movew %5,%3@\n\t" - "nop \n\t" /* If this nop isn't present, 'ret' may already be - * loaded with 1 at the time the bus error - * happens! */ - "moveq #1,%0\n" - "Lberr2:\n\t" - "movel %1,%/sp\n\t" - "movec %2,%/vbr" - : "=&d" (ret), "=&r" (save_sp), "=&r" (save_vbr) - : "a" (regp), "a" (tmp_vectors), "g" (val) - ); - - return( ret ); -} /* ++roman: This is a more elaborate test for an SCC chip, since the plain * Medusa board generates DTACK at the SCC's standard addresses, but a SCC diff -u --recursive --new-file v2.1.105/linux/arch/m68k/atari/joystick.c linux/arch/m68k/atari/joystick.c --- v2.1.105/linux/arch/m68k/atari/joystick.c Tue Mar 10 10:03:30 1998 +++ linux/arch/m68k/atari/joystick.c Sat Jun 13 13:14:32 1998 @@ -15,7 +15,6 @@ #include #include -#include #include #define MAJOR_NR JOYSTICK_MAJOR diff -u --recursive --new-file v2.1.105/linux/arch/m68k/atari/stram.c linux/arch/m68k/atari/stram.c --- v2.1.105/linux/arch/m68k/atari/stram.c Sun Jun 7 11:16:27 1998 +++ linux/arch/m68k/atari/stram.c Sat Jun 13 13:14:32 1998 @@ -954,7 +954,7 @@ return( -ENOMEM ); } DPRINTK( "unswap: reading swap page %lu to %08lx\n", i, page ); - read_swap_page( entry, (char *)page ); + rw_swap_page( READ, entry, (char *)page, 1 ); for_each_task(p) { if (unswap_process( p->mm, entry, page, 0 )) { diff -u --recursive --new-file v2.1.105/linux/arch/m68k/atari/time.c linux/arch/m68k/atari/time.c --- v2.1.105/linux/arch/m68k/atari/time.c Thu Mar 26 15:57:02 1998 +++ linux/arch/m68k/atari/time.c Sat Jun 13 13:14:32 1998 @@ -83,7 +83,7 @@ #define RTC_READ(reg) \ ({ unsigned char __val; \ - writeb(reg,&tt_rtc.regsel); \ + (void) writeb(reg,&tt_rtc.regsel); \ __val = tt_rtc.data; \ __val; \ }) diff -u --recursive --new-file v2.1.105/linux/arch/m68k/bvme6000/Makefile linux/arch/m68k/bvme6000/Makefile --- v2.1.105/linux/arch/m68k/bvme6000/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/m68k/bvme6000/Makefile Sat Jun 13 13:14:31 1998 @@ -0,0 +1,14 @@ +# +# Makefile for Linux arch/m68k/bvme6000 source directory +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definitions are now in the main makefile... + +O_TARGET := bvme6000.o +O_OBJS := config.o bvmeints.o rtc.o +#OX_OBJS = ksyms.o + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.105/linux/arch/m68k/bvme6000/bvmeints.c linux/arch/m68k/bvme6000/bvmeints.c --- v2.1.105/linux/arch/m68k/bvme6000/bvmeints.c Wed Dec 31 16:00:00 1969 +++ linux/arch/m68k/bvme6000/bvmeints.c Sat Jun 13 13:14:31 1998 @@ -0,0 +1,154 @@ +/* + * arch/m68k/bvme6000/bvmeints.c + * + * Copyright (C) 1997 Richard Hirst [richard@sleepie.demon.co.uk] + * + * based on amiints.c -- Amiga Linux interrupt handling code + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file README.legal in the main directory of this archive + * for more details. + * + */ + +#include +#include +#include + +#include +#include +#include +#include + +static void bvme6000_defhand (int irq, void *dev_id, struct pt_regs *fp); + +/* + * This should ideally be 4 elements only, for speed. + */ + +static struct { + void (*handler)(int, void *, struct pt_regs *); + unsigned long flags; + void *dev_id; + const char *devname; + unsigned count; +} irq_tab[256]; + +/* + * void bvme6000_init_IRQ (void) + * + * Parameters: None + * + * Returns: Nothing + * + * This function is called during kernel startup to initialize + * the bvme6000 IRQ handling routines. + */ + +void bvme6000_init_IRQ (void) +{ + int i; + + for (i = 0; i < 256; i++) { + irq_tab[i].handler = bvme6000_defhand; + irq_tab[i].flags = IRQ_FLG_STD; + irq_tab[i].dev_id = NULL; + irq_tab[i].devname = NULL; + irq_tab[i].count = 0; + } +} + +int bvme6000_request_irq(unsigned int irq, + void (*handler)(int, void *, struct pt_regs *), + unsigned long flags, const char *devname, void *dev_id) +{ + if (irq > 255) { + printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname); + return -ENXIO; + } +#if 0 + /* Nothing special about auto-vectored devices for the BVME6000, + * but treat it specially to avoid changes elsewhere. + */ + + if (irq >= VEC_INT1 && irq <= VEC_INT7) + return sys_request_irq(irq - VEC_SPUR, handler, flags, + devname, dev_id); +#endif + if (!(irq_tab[irq].flags & IRQ_FLG_STD)) { + if (irq_tab[irq].flags & IRQ_FLG_LOCK) { + printk("%s: IRQ %d from %s is not replaceable\n", + __FUNCTION__, irq, irq_tab[irq].devname); + return -EBUSY; + } + if (flags & IRQ_FLG_REPLACE) { + printk("%s: %s can't replace IRQ %d from %s\n", + __FUNCTION__, devname, irq, irq_tab[irq].devname); + return -EBUSY; + } + } + irq_tab[irq].handler = handler; + irq_tab[irq].flags = flags; + irq_tab[irq].dev_id = dev_id; + irq_tab[irq].devname = devname; + return 0; +} + +void bvme6000_free_irq(unsigned int irq, void *dev_id) +{ + if (irq > 255) { + printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq); + return; + } +#if 0 + if (irq >= VEC_INT1 && irq <= VEC_INT7) { + sys_free_irq(irq - VEC_SPUR, dev_id); + return; + } +#endif + if (irq_tab[irq].dev_id != dev_id) + printk("%s: Removing probably wrong IRQ %d from %s\n", + __FUNCTION__, irq, irq_tab[irq].devname); + + irq_tab[irq].handler = bvme6000_defhand; + irq_tab[irq].flags = IRQ_FLG_STD; + irq_tab[irq].dev_id = NULL; + irq_tab[irq].devname = NULL; +} + +void bvme6000_process_int (unsigned long vec, struct pt_regs *fp) +{ + if (vec > 255) + panic ("bvme6000_process_int: Illegal vector %ld", vec); + irq_tab[vec].count++; + irq_tab[vec].handler(vec, irq_tab[vec].dev_id, fp); +} + +int bvme6000_get_irq_list (char *buf) +{ + int i, len = 0; + + for (i = 0; i < 256; i++) { + if (irq_tab[i].count) + len += sprintf (buf+len, "Vec 0x%02x: %8d %s\n", + i, irq_tab[i].count, + irq_tab[i].devname ? irq_tab[i].devname : "free"); + } + return len; +} + + +static void bvme6000_defhand (int irq, void *dev_id, struct pt_regs *fp) +{ + printk ("Unknown interrupt 0x%02x\n", irq); +} + +void bvme6000_enable_irq (unsigned int irq) +{ +} + + +void bvme6000_disable_irq (unsigned int irq) +{ +} + diff -u --recursive --new-file v2.1.105/linux/arch/m68k/bvme6000/config.c linux/arch/m68k/bvme6000/config.c --- v2.1.105/linux/arch/m68k/bvme6000/config.c Wed Dec 31 16:00:00 1969 +++ linux/arch/m68k/bvme6000/config.c Sat Jun 13 13:14:31 1998 @@ -0,0 +1,453 @@ +/* + * arch/m68k/bvme6000/config.c + * + * Copyright (C) 1997 Richard Hirst [richard@sleepie.demon.co.uk] + * + * Based on: + * + * linux/amiga/config.c + * + * Copyright (C) 1993 Hamish Macdonald + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file README.legal in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +extern void bvme6000_process_int (int level, struct pt_regs *regs); +extern void bvme6000_init_IRQ (void); +extern void bvme6000_free_irq (unsigned int, void *); +extern int bvme6000_get_irq_list (char *); +extern void bvme6000_enable_irq (unsigned int); +extern void bvme6000_disable_irq (unsigned int); +static void bvme6000_get_model(char *model); +static int bvme6000_get_hardware_list(char *buffer); +extern int bvme6000_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id); +extern void bvme6000_sched_init(void (*handler)(int, void *, struct pt_regs *)); +extern int bvme6000_keyb_init(void); +extern int bvme6000_kbdrate (struct kbd_repeat *); +extern unsigned long bvme6000_gettimeoffset (void); +extern void bvme6000_gettod (int *year, int *mon, int *day, int *hour, + int *min, int *sec); +extern int bvme6000_hwclk (int, struct hwclk_time *); +extern int bvme6000_set_clock_mmss (unsigned long); +extern void bvme6000_check_partition (struct gendisk *hd, unsigned int dev); +extern void bvme6000_mksound( unsigned int count, unsigned int ticks ); +extern void bvme6000_reset (void); +extern void bvme6000_waitbut(void); +void bvme6000_set_vectors (void); + +static unsigned char bcd2bin (unsigned char b); +static unsigned char bin2bcd (unsigned char b); + +/* Save tick handler routine pointer, will point to do_timer() in + * kernel/sched.c, called via bvme6000_process_int() */ + +static void (*tick_handler)(int, void *, struct pt_regs *); + +int bvme6000_kbdrate (struct kbd_repeat *k) +{ + return 0; +} + +void bvme6000_mksound( unsigned int count, unsigned int ticks ) +{ +} + +void bvme6000_reset() +{ + volatile PitRegsPtr pit = (PitRegsPtr)BVME_PIT_BASE; + + printk ("\r\n\nCalled bvme6000_reset\r\n" + "\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r"); + /* The string of returns is to delay the reset until the whole + * message is output. */ + /* Enable the watchdog, via PIT port C bit 4 */ + + pit->pcddr |= 0x10; /* WDOG enable */ + + while(1) + ; +} + +static void bvme6000_get_model(char *model) +{ + /* XXX Need to detect if BVME4000 or BVME6000 */ + sprintf(model, "BVME6000"); +} + + +/* No hardware options on BVME6000? */ + +static int bvme6000_get_hardware_list(char *buffer) +{ + *buffer = '\0'; + return 0; +} + + +__initfunc(void config_bvme6000(void)) +{ + volatile PitRegsPtr pit = (PitRegsPtr)BVME_PIT_BASE; + +#if 0 + /* Call bvme6000_set_vectors() so ABORT will work, along with BVMBug + * debugger. Note trap_init() will splat the abort vector, but + * bvme6000_init_IRQ() will put it back again. Hopefully. */ + + bvme6000_set_vectors(); +#endif + + mach_sched_init = bvme6000_sched_init; + mach_keyb_init = bvme6000_keyb_init; + mach_kbdrate = bvme6000_kbdrate; + mach_init_IRQ = bvme6000_init_IRQ; + mach_gettimeoffset = bvme6000_gettimeoffset; + mach_gettod = bvme6000_gettod; + mach_hwclk = bvme6000_hwclk; + mach_set_clock_mmss = bvme6000_set_clock_mmss; +/* mach_mksound = bvme6000_mksound; */ + mach_reset = bvme6000_reset; + mach_free_irq = bvme6000_free_irq; + mach_process_int = bvme6000_process_int; + mach_get_irq_list = bvme6000_get_irq_list; + mach_request_irq = bvme6000_request_irq; + enable_irq = bvme6000_enable_irq; + disable_irq = bvme6000_disable_irq; + mach_get_model = bvme6000_get_model; + mach_get_hardware_list = bvme6000_get_hardware_list; + + printk ("Board is %sconfigured as a System Controller\n", + *config_reg_ptr & BVME_CONFIG_SW1 ? "" : "not "); + + /* Now do the PIT configuration */ + + pit->pgcr = 0x00; /* Unidirectional 8 bit, no handshake for now */ + pit->psrr = 0x18; /* PIACK and PIRQ fucntions enabled */ + pit->pacr = 0x00; /* Sub Mode 00, H2 i/p, no DMA */ + pit->padr = 0x00; /* Just to be tidy! */ + pit->paddr = 0x00; /* All inputs for now (safest) */ + pit->pbcr = 0x80; /* Sub Mode 1x, H4 i/p, no DMA */ + pit->pbdr = 0xbc | (*config_reg_ptr & BVME_CONFIG_SW1 ? 0 : 0x40); + /* PRI, SYSCON?, Level3, SCC clks from xtal */ + pit->pbddr = 0xf3; /* Mostly outputs */ + pit->pcdr = 0x01; /* PA transceiver disabled */ + pit->pcddr = 0x03; /* WDOG disable */ +} + + +void bvme6000_abort_int (int irq, void *dev_id, struct pt_regs *fp) +{ + unsigned long *new = (unsigned long *)vectors; + unsigned long *old = (unsigned long *)0xf8000000;; + + /* Wait for button release */ + while (*config_reg_ptr & BVME_ABORT_STATUS) + ; + + *(new+4) = *(old+4); /* Illegal instruction */ + *(new+9) = *(old+9); /* Trace */ + *(new+47) = *(old+47); /* Trap #15 */ + *(new+0x1f) = *(old+0x1f); /* ABORT switch */ +} + + +static void bvme6000_timer_int (int irq, void *dev_id, struct pt_regs *fp) +{ + volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE; + unsigned char msr = rtc->msr & 0xc0; + + rtc->msr = msr | 0x20; /* Ack the interrupt */ + + tick_handler(irq, dev_id, fp); +} + +/* + * Set up the RTC timer 1 to mode 2, so T1 output toggles every 5ms + * (40000 x 125ns). It will interrupt every 10ms, when T1 goes low. + * So, when reading the elapsed time, you should read timer1, + * subtract it from 39999, and then add 40000 if T1 is high. + * That gives you the number of 125ns ticks in to the 10ms period, + * so divide by 8 to get the microsecond result. + */ + +void bvme6000_sched_init (void (*timer_routine)(int, void *, struct pt_regs *)) +{ + volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE; + unsigned char msr = rtc->msr & 0xc0; + + rtc->msr = 0; /* Ensure timer registers accessible */ + + tick_handler = timer_routine; + if (request_irq(BVME_IRQ_RTC, bvme6000_timer_int, 0, + "timer", bvme6000_timer_int)) + panic ("Couldn't register timer int"); + + rtc->t1cr_omr = 0x04; /* Mode 2, ext clk */ + rtc->t1msb = 39999 >> 8; + rtc->t1lsb = 39999 & 0xff; + rtc->irr_icr1 &= 0xef; /* Route timer 1 to INTR pin */ + rtc->msr = 0x40; /* Access int.cntrl, etc */ + rtc->pfr_icr0 = 0x80; /* Just timer 1 ints enabled */ + rtc->irr_icr1 = 0; + rtc->t1cr_omr = 0x0a; /* INTR+T1 active lo, push-pull */ + rtc->t0cr_rtmr &= 0xdf; /* Stop timers in standby */ + rtc->msr = 0; /* Access timer 1 control */ + rtc->t1cr_omr = 0x05; /* Mode 2, ext clk, GO */ + + rtc->msr = msr; + + if (request_irq(BVME_IRQ_ABORT, bvme6000_abort_int, 0, + "abort", bvme6000_abort_int)) + panic ("Couldn't register abort int"); +} + + +/* This is always executed with interrupts disabled. */ + +/* + * NOTE: Don't accept any readings within 5us of rollover, as + * the T1INT bit may be a little slow getting set. There is also + * a fault in the chip, meaning that reads may produce invalid + * results... + */ + +unsigned long bvme6000_gettimeoffset (void) +{ + volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE; + volatile PitRegsPtr pit = (PitRegsPtr)BVME_PIT_BASE; + unsigned char msr = rtc->msr & 0xc0; + unsigned char t1int, t1op; + unsigned long v = 800000, ov; + + rtc->msr = 0; /* Ensure timer registers accessible */ + + do { + ov = v; + t1int = rtc->msr & 0x20; + t1op = pit->pcdr & 0x04; + rtc->t1cr_omr |= 0x40; /* Latch timer1 */ + v = rtc->t1msb << 8; /* Read timer1 */ + v |= rtc->t1lsb; /* Read timer1 */ + } while (t1int != (rtc->msr & 0x20) || + t1op != (pit->pcdr & 0x04) || + abs(ov-v) > 80 || + v > 39960); + + v = 39999 - v; + if (!t1op) /* If in second half cycle.. */ + v += 40000; + v /= 8; /* Convert ticks to microseconds */ + if (t1int) + v += 10000; /* Int pending, + 10ms */ + rtc->msr = msr; + + return v; +} + +extern void bvme6000_gettod (int *year, int *mon, int *day, int *hour, + int *min, int *sec) +{ + volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE; + unsigned char msr = rtc->msr & 0xc0; + + rtc->msr = 0; /* Ensure clock accessible */ + + do { /* Loop until we get a reading with a stable seconds field */ + *sec = bcd2bin (rtc->bcd_sec); + *min = bcd2bin (rtc->bcd_min); + *hour = bcd2bin (rtc->bcd_hr); + *day = bcd2bin (rtc->bcd_dom); + *mon = bcd2bin (rtc->bcd_mth); + *year = bcd2bin (rtc->bcd_year); + } while (bcd2bin (rtc->bcd_sec) != *sec); + + rtc->msr = msr; +} + +static unsigned char bcd2bin (unsigned char b) +{ + return ((b>>4)*10 + (b&15)); +} + +static unsigned char bin2bcd (unsigned char b) +{ + return (((b/10)*16) + (b%10)); +} + + +/* + * Looks like op is non-zero for setting the clock, and zero for + * reading the clock. + * + * struct hwclk_time { + * unsigned sec; 0..59 + * unsigned min; 0..59 + * unsigned hour; 0..23 + * unsigned day; 1..31 + * unsigned mon; 0..11 + * unsigned year; 00... + * int wday; 0..6, 0 is Sunday, -1 means unknown/don't set + * }; + */ + +int bvme6000_hwclk(int op, struct hwclk_time *t) +{ + volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE; + unsigned char msr = rtc->msr & 0xc0; + + rtc->msr = 0x40; /* Ensure clock and real-time-mode-register + * are accessible */ + if (op) + { /* Write.... */ + rtc->t0cr_rtmr = t->year%4; + rtc->bcd_tenms = 0; + rtc->bcd_sec = bin2bcd(t->sec); + rtc->bcd_min = bin2bcd(t->min); + rtc->bcd_hr = bin2bcd(t->hour); + rtc->bcd_dom = bin2bcd(t->day); + rtc->bcd_mth = bin2bcd(t->mon + 1); + rtc->bcd_year = bin2bcd(t->year%100); + if (t->wday >= 0) + rtc->bcd_dow = bin2bcd(t->wday+1); + rtc->t0cr_rtmr = t->year%4 | 0x08; + } + else + { /* Read.... */ + do { + t->sec = bcd2bin(rtc->bcd_sec); + t->min = bcd2bin(rtc->bcd_min); + t->hour = bcd2bin(rtc->bcd_hr); + t->day = bcd2bin(rtc->bcd_dom); + t->mon = bcd2bin(rtc->bcd_mth)-1; + t->year = bcd2bin(rtc->bcd_year); + if (t->year < 70) + t->year += 100; + t->wday = bcd2bin(rtc->bcd_dow)-1; + } while (t->sec != bcd2bin(rtc->bcd_sec)); + } + + rtc->msr = msr; + + return 0; +} + +/* + * Set the minutes and seconds from seconds value 'nowtime'. Fail if + * clock is out by > 30 minutes. Logic lifted from atari code. + * Algorithm is to wait for the 10ms register to change, and then to + * wait a short while, and then set it. + */ + +int bvme6000_set_clock_mmss (unsigned long nowtime) +{ + int retval = 0; + short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60; + unsigned char rtc_minutes, rtc_tenms; + volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE; + unsigned char msr = rtc->msr & 0xc0; + unsigned long flags; + volatile int i; + + rtc->msr = 0; /* Ensure clock accessible */ + rtc_minutes = bcd2bin (rtc->bcd_min); + + if ((rtc_minutes < real_minutes + ? real_minutes - rtc_minutes + : rtc_minutes - real_minutes) < 30) + { + save_flags(flags); + cli(); + rtc_tenms = rtc->bcd_tenms; + while (rtc_tenms == rtc->bcd_tenms) + ; + for (i = 0; i < 1000; i++) + ; + rtc->bcd_min = bin2bcd(real_minutes); + rtc->bcd_sec = bin2bcd(real_seconds); + restore_flags(flags); + } + else + retval = -1; + + rtc->msr = msr; + + return retval; +} + + +int bvme6000_keyb_init (void) +{ + return 0; +} + +/*------------------- Serial console stuff ------------------------*/ + +static void bvme_scc_write(struct console *co, const char *str, unsigned cnt); + + +void bvme6000_init_console_port (struct console *co, int cflag) +{ + co->write = bvme_scc_write; +} + + +static void scc_delay (void) +{ + int n; + char i; + + for (n = 0; n < 20; n++) + i = *(volatile char *)0; +} + +static void scc_write (char ch) +{ + volatile char *p = (volatile char *)BVME_SCC_A_ADDR; + + do { + scc_delay(); + } + while (!(*p & 4)); + scc_delay(); + *p = 8; + scc_delay(); + *p = ch; +} + + +static void bvme_scc_write (struct console *co, const char *str, unsigned count) +{ + unsigned long flags; + + save_flags(flags); + cli(); + + while (count--) + { + if (*str == '\n') + scc_write ('\r'); + scc_write (*str++); + } + restore_flags(flags); +} + diff -u --recursive --new-file v2.1.105/linux/arch/m68k/bvme6000/rtc.c linux/arch/m68k/bvme6000/rtc.c --- v2.1.105/linux/arch/m68k/bvme6000/rtc.c Wed Dec 31 16:00:00 1969 +++ linux/arch/m68k/bvme6000/rtc.c Sat Jun 13 13:14:31 1998 @@ -0,0 +1,175 @@ +/* + * Real Time Clock interface for Linux on the BVME6000 + * + * Based on the PC driver by Paul Gortmaker. + */ + +#define RTC_VERSION "1.00" + +#include +#include +#include +#include +#include +#include +#include +#include +#include /* For struct rtc_time and ioctls, etc */ +#include + +#include +#include +#include +#include + +/* + * We sponge a minor off of the misc major. No need slurping + * up another valuable major dev number for this. If you add + * an ioctl, make sure you don't conflict with SPARC's RTC + * ioctls. + */ + +#define BCD2BIN(val) (((val)&15) + ((val)>>4)*10) +#define BIN2BCD(val) ((((val)/10)<<4) + (val)%10) + +static unsigned char days_in_mo[] = +{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + +static char rtc_status = 0; + +static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE; + unsigned char msr; + unsigned long flags; + struct rtc_time wtime; + + switch (cmd) { + case RTC_RD_TIME: /* Read the time/date from RTC */ + { + save_flags(flags); + cli(); + /* Ensure clock and real-time-mode-register are accessible */ + msr = rtc->msr & 0xc0; + rtc->msr = 0x40; + do { + wtime.tm_sec = BCD2BIN(rtc->bcd_sec); + wtime.tm_min = BCD2BIN(rtc->bcd_min); + wtime.tm_hour = BCD2BIN(rtc->bcd_hr); + wtime.tm_mday = BCD2BIN(rtc->bcd_dom); + wtime.tm_mon = BCD2BIN(rtc->bcd_mth)-1; + wtime.tm_year = BCD2BIN(rtc->bcd_year); + if (wtime.tm_year < 70) + wtime.tm_year += 100; + wtime.tm_wday = BCD2BIN(rtc->bcd_dow)-1; + } while (wtime.tm_sec != BCD2BIN(rtc->bcd_sec)); + rtc->msr = msr; + restore_flags(flags); + return copy_to_user((void *)arg, &wtime, sizeof wtime) ? + -EFAULT : 0; + } + case RTC_SET_TIME: /* Set the RTC */ + { + unsigned char leap_yr; + struct rtc_time rtc_tm; + + if (!suser()) + return -EACCES; + + if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, + sizeof(struct rtc_time))) + return -EFAULT; + + leap_yr = ((!(rtc_tm.tm_year % 4) && (rtc_tm.tm_year % 100)) || !(rtc_tm.tm_year % 400)); + + if ((rtc_tm.tm_mon > 12) || (rtc_tm.tm_mday == 0)) + return -EINVAL; + + if (rtc_tm.tm_mday > (days_in_mo[rtc_tm.tm_mon] + ((rtc_tm.tm_mon == 2) && leap_yr))) + return -EINVAL; + + if ((rtc_tm.tm_hour >= 24) || (rtc_tm.tm_min >= 60) || (rtc_tm.tm_sec >= 60)) + return -EINVAL; + + save_flags(flags); + cli(); + /* Ensure clock and real-time-mode-register are accessible */ + msr = rtc->msr & 0xc0; + rtc->msr = 0x40; + + rtc->t0cr_rtmr = rtc_tm.tm_year%4; + rtc->bcd_tenms = 0; + rtc->bcd_sec = BIN2BCD(rtc_tm.tm_sec); + rtc->bcd_min = BIN2BCD(rtc_tm.tm_min); + rtc->bcd_hr = BIN2BCD(rtc_tm.tm_hour); + rtc->bcd_dom = BIN2BCD(rtc_tm.tm_mday); + rtc->bcd_mth = BIN2BCD(rtc_tm.tm_mon + 1); + rtc->bcd_year = BIN2BCD(rtc_tm.tm_year%100); + if (rtc_tm.tm_wday >= 0) + rtc->bcd_dow = BIN2BCD(rtc_tm.tm_wday+1); + rtc->t0cr_rtmr = rtc_tm.tm_year%4 | 0x08; + + rtc->msr = msr; + restore_flags(flags); + return 0; + } + default: + return -EINVAL; + } +} + +/* + * We enforce only one user at a time here with the open/close. + * Also clear the previous interrupt data on an open, and clean + * up things on a close. + */ + +static int rtc_open(struct inode *inode, struct file *file) +{ + if(rtc_status) + return -EBUSY; + + rtc_status = 1; + return 0; +} + +static int rtc_release(struct inode *inode, struct file *file) +{ + rtc_status = 0; + return 0; +} + +/* + * The various file operations we support. + */ + +static struct file_operations rtc_fops = { + NULL, + NULL, + NULL, /* No write */ + NULL, /* No readdir */ + NULL, + rtc_ioctl, + NULL, /* No mmap */ + rtc_open, + rtc_release +}; + +static struct miscdevice rtc_dev= +{ + RTC_MINOR, + "rtc", + &rtc_fops +}; + +__initfunc(int rtc_DP8570A_init(void)) +{ + if (!MACH_IS_BVME6000) + return -ENODEV; + + printk(KERN_INFO "DP8570A Real Time Clock Driver v%s\n", RTC_VERSION); + misc_register(&rtc_dev); + return 0; +} + diff -u --recursive --new-file v2.1.105/linux/arch/m68k/config.in linux/arch/m68k/config.in --- v2.1.105/linux/arch/m68k/config.in Sun Jun 7 11:16:27 1998 +++ linux/arch/m68k/config.in Sat Jun 13 13:14:32 1998 @@ -19,7 +19,7 @@ endmenu mainmenu_option next_comment -comment 'Platform-dependent setup' +comment 'Platform dependent setup' bool 'Amiga support' CONFIG_AMIGA bool 'Atari support' CONFIG_ATARI @@ -30,13 +30,19 @@ fi fi bool 'Macintosh support' CONFIG_MAC +if [ "$CONFIG_MAC" = "y" ]; then + define_bool CONFIG_NUBUS y +fi bool 'Apollo support' CONFIG_APOLLO bool 'VME (Motorola and BVM) support' CONFIG_VME if [ "$CONFIG_VME" = "y" ]; then bool 'MVME162, 166 and 167 support' CONFIG_MVME16x -# bool 'BVME4000 and BVME6000 support' CONFIG_BVME6000 + bool 'BVME4000 and BVME6000 support' CONFIG_BVME6000 +fi +bool 'HP9000/300 support' CONFIG_HP300 +if [ "$CONFIG_HP300" = "y" ]; then + bool 'DIO bus support' CONFIG_DIO fi - if [ "$CONFIG_PCI" = "y" ]; then bool 'Backward-compatible /proc/pci' CONFIG_PCI_OLD_PROC fi @@ -57,6 +63,7 @@ bool 'Advanced processor options' CONFIG_ADVANCED_CPU if [ "$CONFIG_ADVANCED_CPU" = "y" ]; then bool 'Use read-modify-write instructions' CONFIG_RMW_INSNS + bool 'Use write-through caching for 68060 supervisor accesses' CONFIG_060_WRITETHROUGH fi endmenu @@ -73,11 +80,6 @@ if [ "$CONFIG_AMIGA" = "y" ]; then bool 'Amiga AutoConfig Identification' CONFIG_ZORRO -# bool 'Amiga GSP (TMS340x0) support' CONFIG_AMIGA_GSP -# if [ "$CONFIG_AMIGA_GSP" = "y" ]; then -# bool 'DMI Resolver support' CONFIG_GSP_RESOLVER -# bool 'A2410 support' CONFIG_GSP_A2410 -# fi fi if [ "$CONFIG_ATARI" = "y" ]; then bool 'Support for ST-RAM as swap space' CONFIG_STRAM_SWAP @@ -85,73 +87,17 @@ fi if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_ATARI" = "y" ]; then bool 'Use power LED as a heartbeat' CONFIG_HEARTBEAT -fi -endmenu - -# -# Block device driver configuration -# -mainmenu_option next_comment -comment 'Floppy, IDE, and other block devices' - -if [ "$CONFIG_AMIGA" = "y" ]; then - tristate 'Amiga floppy support' CONFIG_AMIGA_FLOPPY -fi -if [ "$CONFIG_ATARI" = "y" ]; then - tristate 'Atari floppy support' CONFIG_ATARI_FLOPPY -fi -if [ "$CONFIG_MAC" = "y" ]; then - tristate 'Macintosh IWM floppy support' CONFIG_MAC_FLOPPY -fi -#Normal floppy disk support' CONFIG_BLK_DEV_FD - -tristate 'Enhanced IDE/MFM/RLL disk/cdrom/tape/floppy support' CONFIG_BLK_DEV_IDE -if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then - dep_tristate ' Include IDE/ATA-2 DISK support' CONFIG_BLK_DEV_IDEDISK $CONFIG_BLK_DEV_IDE - dep_tristate ' Include IDE/ATAPI CDROM support' CONFIG_BLK_DEV_IDECD $CONFIG_BLK_DEV_IDE - dep_tristate ' Include IDE/ATAPI TAPE support' CONFIG_BLK_DEV_IDETAPE $CONFIG_BLK_DEV_IDE - dep_tristate ' Include IDE/ATAPI FLOPPY support' CONFIG_BLK_DEV_IDEFLOPPY $CONFIG_BLK_DEV_IDE - dep_tristate ' SCSI emulation support' CONFIG_BLK_DEV_IDESCSI $CONFIG_BLK_DEV_IDE - if [ "$CONFIG_AMIGA" = "y" ]; then - bool ' Amiga Gayle IDE interface support' CONFIG_BLK_DEV_GAYLE - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - bool ' Buddha/Catweasel IDE interface support' CONFIG_BLK_DEV_BUDDHA - bool ' Amiga IDE Doubler support' CONFIG_BLK_DEV_IDEDOUBLER $CONFIG_BLK_DEV_GAYLE - fi - fi - if [ "$CONFIG_ATARI" = "y" ]; then - bool ' Falcon IDE interface support' CONFIG_BLK_DEV_FALCON_IDE - fi -fi -if [ "$CONFIG_AMIGA" = "y" ]; then - tristate 'Amiga Zorro II ramdisk support' CONFIG_AMIGA_Z2RAM -fi -if [ "$CONFIG_ATARI" = "y" ]; then - tristate 'Atari ACSI support' CONFIG_ATARI_ACSI - if [ "$CONFIG_ATARI_ACSI" != "n" ]; then - comment 'Some devices (e.g. CD jukebox) support multiple LUNs' - bool 'Probe all LUNs on each ACSI device' CONFIG_ACSI_MULTI_LUN - dep_tristate 'Atari SLM laser printer support' CONFIG_ATARI_SLM $CONFIG_ATARI_ACSI +else + if [ "$CONFIG_HP300" = "y" ]; then +# We have a dedicated heartbeat LED. :-) + define_bool CONFIG_HEARTBEAT y fi fi - -comment 'Additional Block Devices' - -tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP -bool 'Multiple devices driver support' CONFIG_BLK_DEV_MD -if [ "$CONFIG_BLK_DEV_MD" = "y" ]; then - tristate ' Linear (append) mode' CONFIG_MD_LINEAR - tristate ' RAID-0 (striping) mode' CONFIG_MD_STRIPED -fi -if [ "$CONFIG_MD_LINEAR" = "y" -o "$CONFIG_MD_STRIPED" = "y" ]; then - bool ' Boot support (linear, striped)' CONFIG_MD_BOOT -fi -tristate 'RAM disk support' CONFIG_BLK_DEV_RAM -if [ "$CONFIG_BLK_DEV_RAM" = "y" ]; then - bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD -fi +bool '/proc/hardware support' CONFIG_PROC_HARDWARE endmenu +source drivers/block/Config.in + if [ "$CONFIG_NET" = "y" ]; then source net/Config.in fi @@ -196,15 +142,21 @@ bool 'A4000T SCSI support' CONFIG_A4000T_SCSI bool 'A4091 SCSI support' CONFIG_A4091_SCSI bool 'WarpEngine SCSI support' CONFIG_WARPENGINE_SCSI - bool 'Cyberstorm Mk III SCSI support' CONFIG_CYBERSTORMIII_SCSI +# bool 'Cyberstorm Mk III SCSI support' CONFIG_CYBERSTORMIII_SCSI # bool 'GVP Turbo 040/060 SCSI support' CONFIG_GVP_TURBO_SCSI fi + if [ "$CONFIG_MAC" = "y" ]; then + bool ' Macintosh Quadra/Powerbook IDE interface support' CONFIG_BLK_DEV_MAC_IDE + fi fi if [ "$CONFIG_ATARI" = "y" ]; then dep_tristate 'Atari native SCSI support' CONFIG_ATARI_SCSI $CONFIG_SCSI - bool 'Long delays for Toshiba CD-ROMs' CONFIG_ATARI_SCSI_TOSHIBA_DELAY - if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_HADES" = "y" ]; then - bool 'Hades SCSI DMA emulator (EXPERIMENTAL)' CONFIG_TT_DMA_EMUL + if [ "$CONFIG_ATARI_SCSI" != "n" ]; then + bool ' Long delays for Toshiba CD-ROMs' CONFIG_ATARI_SCSI_TOSHIBA_DELAY + bool ' Reset SCSI-devices at boottime' CONFIG_ATARI_SCSI_RESET_BOOT + if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_HADES" = "y" ]; then + bool ' Hades SCSI DMA emulator (EXPERIMENTAL)' CONFIG_TT_DMA_EMUL + fi fi fi if [ "$CONFIG_MAC" = "y" ]; then @@ -216,6 +168,10 @@ bool 'NCR53C710 SCSI driver for MVME16x' CONFIG_MVME16x_SCSI fi +if [ "$CONFIG_VME" = "y" -a "$CONFIG_BVME6000" = "y" ]; then + bool 'NCR53C710 SCSI driver for BVME6000' CONFIG_BVME6000_SCSI +fi + endmenu fi @@ -264,6 +220,9 @@ if [ "$CONFIG_VME" = "y" -a "$CONFIG_MVME16x" = "y" ]; then bool 'MVME16x Ethernet support' CONFIG_APRICOT fi +if [ "$CONFIG_VME" = "y" -a "$CONFIG_BVME6000" = "y" ]; then + bool 'BVME6000 Ethernet support' CONFIG_APRICOT +fi fi endmenu @@ -322,20 +281,31 @@ tristate 'Multiface Card III serial support' CONFIG_MULTIFACE_III_TTY bool 'Hisoft Whippet PCMCIA serial support' CONFIG_WHIPPET fi -if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_ATARI" = "y" ]; then +if [ "$CONFIG_MAC" = "y" ]; then + bool 'Mac SCC serial support' CONFIG_MAC_SCC +fi +if [ "$CONFIG_HP300" = "y" -a "$CONFIG_DIO" = "y" ]; then + tristate 'HP DCA serial support' CONFIG_HPDCA +fi +if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_ATARI" = "y" -o \ + "$CONFIG_MAC" = "y" -o "$CONFIG_HP300" = "y" ]; then if [ "$CONFIG_ATARI_MFPSER" = "y" -o "$CONFIG_ATARI_SCC" = "y" -o \ - "$CONFIG_ATARI_MIDI" = "y" -o "$CONFIG_AMIGA_BUILTIN_SERIAL" = "y" -o \ - "$CONFIG_GVPIOEXT" = "y" -o "$CONFIG_MULTIFACE_III_TTY" = "y" ]; then + "$CONFIG_ATARI_MIDI" = "y" -o "$CONFIG_MAC_SCC" = "y" -o \ + "$CONFIG_AMIGA_BUILTIN_SERIAL" = "y" -o \ + "$CONFIG_GVPIOEXT" = "y" -o "$CONFIG_MULTIFACE_III_TTY" = "y" -o \ + "$CONFIG_HPDCA" = "y" ]; then bool 'Support for serial port console' CONFIG_SERIAL_CONSOLE fi fi -if [ "$CONFIG_MAC" = "y" ]; then - bool 'Mac SCC serial support' CONFIG_MAC_SCC -fi if [ "$CONFIG_VME" = "y" ]; then define_bool CONFIG_SERIAL_CONSOLE y - bool 'CD2401 support for MVME166/7 serial ports' CONFIG_SERIAL167 - bool 'SCC support for MVME162 serial ports' CONFIG_MVME162_SCC + if [ "$CONFIG_MVME16x" = "y" ]; then + bool 'CD2401 support for MVME166/7 serial ports' CONFIG_SERIAL167 + bool 'SCC support for MVME162 serial ports' CONFIG_MVME162_SCC + fi + if [ "$CONFIG_BVME6000" = "y" ]; then + bool 'SCC support for BVME6000 serial ports' CONFIG_BVME6000_SCC + fi fi if [ "$CONFIG_APOLLO" = "y" ]; then bool 'Support for DN serial port (dummy)' CONFIG_SERIAL @@ -348,7 +318,7 @@ bool ' Software Watchdog' CONFIG_SOFT_WATCHDOG fi bool 'Support for user misc device modules' CONFIG_UMISC -if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_ATARI" = "y" ]; then +if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_ATARI" = "y" -o "$CONFIG_MAC" = "y" ]; then define_bool CONFIG_ABSTRACT_CONSOLE y fi if [ "$CONFIG_ATARI" = "y" ]; then diff -u --recursive --new-file v2.1.105/linux/arch/m68k/defconfig linux/arch/m68k/defconfig --- v2.1.105/linux/arch/m68k/defconfig Tue Mar 17 22:18:14 1998 +++ linux/arch/m68k/defconfig Sat Jun 13 13:14:32 1998 @@ -45,6 +45,8 @@ # CONFIG_AMIGA_GSP is not set # CONFIG_GSP_RESOLVER is not set # CONFIG_GSP_A2410 is not set +# CONFIG_HEARTBEAT is not set +CONFIG_PROC_HARDWARE=y # # Block device driver configuration @@ -133,6 +135,8 @@ # CONFIG_A4091_SCSI is not set # CONFIG_WARPENGINE_SCSI is not set CONFIG_ATARI_SCSI=y +# CONFIG_ATARI_SCSI_TOSHIBA_DELAY is not set +# CONFIG_ATARI_SCSI_RESET_BOOT is not set # # Network device support diff -u --recursive --new-file v2.1.105/linux/arch/m68k/hp300/Makefile linux/arch/m68k/hp300/Makefile --- v2.1.105/linux/arch/m68k/hp300/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/m68k/hp300/Makefile Sat Jun 13 13:14:31 1998 @@ -0,0 +1,13 @@ +# +# Makefile for Linux arch/m68k/hp300 source directory +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definitions are now in the main makefile... + +O_TARGET := hp300.o +O_OBJS := ksyms.o config.o ints.o time.o reboot.o hil.o + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.105/linux/arch/m68k/hp300/README.hp300 linux/arch/m68k/hp300/README.hp300 --- v2.1.105/linux/arch/m68k/hp300/README.hp300 Wed Dec 31 16:00:00 1969 +++ linux/arch/m68k/hp300/README.hp300 Sat Jun 13 13:14:31 1998 @@ -0,0 +1,14 @@ +HP300 notes +----------- + +The Linux/HP web page is at + +Currently only 9000/340 machines have been tested. Any amount of RAM should +work now but I've only tried 16MB and 12MB. + +The serial console is probably broken at the moment but the Topcat/HIL keyboard +combination seems to work for me. Your mileage may vary. + +The LANCE driver works after a fashion but only if you reset the chip before +every packet. This doesn't make for very speedy operation. + diff -u --recursive --new-file v2.1.105/linux/arch/m68k/hp300/config.c linux/arch/m68k/hp300/config.c --- v2.1.105/linux/arch/m68k/hp300/config.c Wed Dec 31 16:00:00 1969 +++ linux/arch/m68k/hp300/config.c Sat Jun 13 13:14:31 1998 @@ -0,0 +1,78 @@ +/* + * linux/arch/m68k/hp300/config.c + * + * Copyright (C) 1998 Philip Blundell + * + * This file contains the HP300-specific initialisation code. It gets + * called by setup.c. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* readb() and writeb() */ +#include /* hwreg_present() */ + +#include "ints.h" +#include "time.h" + +extern void hp300_reset(void); +extern void hp300_hil_init(void); + +#ifdef CONFIG_HEARTBEAT +static void hp300_pulse(int x) +{ + if (x) + blinken_leds(0xfe); + else + blinken_leds(0xff); +} +#endif + +static int hp300_kbdrate(struct kbd_repeat *k) +{ + return 0; +} + +static void hp300_kbd_leds(unsigned int leds) +{ +} + +__initfunc(void config_hp300(void)) +{ + mach_sched_init = hp300_sched_init; + mach_keyb_init = hp300_hil_init; + mach_kbdrate = hp300_kbdrate; + mach_kbd_leds = hp300_kbd_leds; + mach_init_IRQ = hp300_init_IRQ; + mach_request_irq = hp300_request_irq; + mach_free_irq = hp300_free_irq; +#if 0 + mach_get_model = hp300_get_model; + mach_get_irq_list = hp300_get_irq_list; +#endif + mach_gettimeoffset = hp300_gettimeoffset; +#if 0 + mach_gettod = hp300_gettod; +#endif + mach_reset = hp300_reset; +#ifdef CONFIG_HEARTBEAT + mach_heartbeat = hp300_pulse; +#endif +#ifdef CONFIG_FB + conswitchp = &fb_con; +#endif + mach_max_dma_address = 0xffffffff; +} + +/* for "kbd-reset" cmdline param */ +__initfunc(void kbd_reset_setup(char *str, int *ints)) +{ +} diff -u --recursive --new-file v2.1.105/linux/arch/m68k/hp300/hil.c linux/arch/m68k/hp300/hil.c --- v2.1.105/linux/arch/m68k/hp300/hil.c Wed Dec 31 16:00:00 1969 +++ linux/arch/m68k/hp300/hil.c Sat Jun 13 13:14:31 1998 @@ -0,0 +1,250 @@ +/* + * linux/arch/m68k/hp300/hil.c + * + * Copyright (C) 1998 Philip Blundell + * + * HP300 Human Interface Loop driver. This handles the keyboard and mouse. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define HILBASE 0xf0428000 +#define HIL_DATA 0x1 +#define HIL_CMD 0x3 + +#define HIL_BUSY 0x02 +#define HIL_DATA_RDY 0x01 + +#define hil_busy() (readb(HILBASE + HIL_CMD) & HIL_BUSY) +#define hil_data_available() (readb(HILBASE + HIL_CMD) & HIL_DATA_RDY) +#define hil_status() (readb(HILBASE + HIL_CMD)) +#define hil_command(x) do { writeb((x), HILBASE + HIL_CMD); } while (0) +#define hil_read_data() (readb(HILBASE + HIL_DATA)) +#define hil_write_data(x) do { writeb((x), HILBASE + HIL_DATA); } while (0) + +#define HIL_SETARD 0xA0 /* set auto-repeat delay */ +#define HIL_SETARR 0xA2 /* set auto-repeat rate */ +#define HIL_SETTONE 0xA3 /* set tone generator */ +#define HIL_CNMT 0xB2 /* clear nmi */ +#define HIL_INTON 0x5C /* Turn on interrupts. */ +#define HIL_INTOFF 0x5D /* Turn off interrupts. */ +#define HIL_TRIGGER 0xC5 /* trigger command */ +#define HIL_STARTCMD 0xE0 /* start loop command */ +#define HIL_TIMEOUT 0xFE /* timeout */ +#define HIL_READTIME 0x13 /* Read real time register */ + +#define HIL_READBUSY 0x02 /* internal "busy" register */ +#define HIL_READKBDLANG 0x12 /* read keyboard language code */ +#define HIL_READKBDSADR 0xF9 +#define HIL_WRITEKBDSADR 0xE9 +#define HIL_READLPSTAT 0xFA +#define HIL_WRITELPSTAT 0xEA +#define HIL_READLPCTRL 0xFB +#define HIL_WRITELPCTRL 0xEB + +#define HIL_IRQ 1 + +static u_short hp_plain_map[NR_KEYS] __initdata = { + 0xf200, 0xf01b, 0xf20e, 0xf700, 0xf700, 0xf700, 0xf702, 0xf036, + 0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf008, 0xf009, + 0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69, + 0xfb62, 0xfb76, 0xf063, 0xfb78, 0xfb7a, 0xf702, 0xfb61, 0xfb73, + 0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b, + 0xfb68, 0xfb67, 0xfb66, 0xfb64, 0xfb73, 0xfb61, 0xfb63, 0xfb76, + 0xfb75, 0xfb79, 0xfb74, 0xfb72, 0xfb65, 0xfb77, 0xfb71, 0xf200, + 0xf037, 0xf036, 0xf035, 0xf034, 0xf033, 0xf032, 0xf031, 0xf104, + 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf200, 0xf200, 0xf114, + 0xf603, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200, + 0xf600, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf038, 0xf039, 0xf030, 0xf200, 0xf200, 0xf008, 0xf200, 0xf200, + 0xfb69, 0xfb6f, 0xfb70, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307, + 0xfb6a, 0xfb6b, 0xfb6c, 0xf305, 0xf306, 0xf00d, 0xf302, 0xf303, + 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf200, 0xf200, 0xf200, 0xf200, + 0xfb6e, 0xf020, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200 +}; + +static u_short hp_shift_map[NR_KEYS] __initdata = { + 0xf200, 0xf01b, 0xf20e, 0xf700, 0xf700, 0xf700, 0xf002, 0xf036, + 0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf008, 0xf009, + 0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69, + 0xfb62, 0xfb76, 0xf063, 0xfb78, 0xfb7a, 0xf702, 0xfb61, 0xfb73, + 0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b, + 0xfb68, 0xfb67, 0xfb66, 0xfb64, 0xfb73, 0xfb61, 0xfb63, 0xfb76, + 0xfb75, 0xfb79, 0xfb74, 0xfb72, 0xfb65, 0xfb77, 0xfb71, 0xf200, + 0xf037, 0xf036, 0xf035, 0xf034, 0xf033, 0xf032, 0xf031, 0xf104, + 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf200, 0xf200, 0xf114, + 0xf603, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200, + 0xf600, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf038, 0xf039, 0xf030, 0xf200, 0xf200, 0xf008, 0xf200, 0xf200, + 0xfb69, 0xfb6f, 0xfb70, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307, + 0xfb6a, 0xfb6b, 0xfb6c, 0xf305, 0xf306, 0xf00d, 0xf302, 0xf303, + 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf200, 0xf200, 0xf200, 0xf200, + 0xfb6e, 0xf020, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200 +}; + +static u_short hp_ctrl_map[NR_KEYS] __initdata = { + 0xf200, 0xf200, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01d, 0xf01e, + 0xf01f, 0xf07f, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf008, 0xf200, + 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009, + 0xf00f, 0xf010, 0xf003, 0xf01d, 0xf201, 0xf702, 0xf001, 0xf013, + 0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200, + 0xf007, 0xf000, 0xf700, 0xf01c, 0xf01a, 0xf018, 0xf003, 0xf016, + 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf200, 0xf07f, 0xf700, 0xf200, + 0xf703, 0xf000, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104, + 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf200, 0xf200, 0xf114, + 0xf603, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200, + 0xf600, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf1ff, 0xf202, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307, + 0xf308, 0xf309, 0xf304, 0xf305, 0xf306, 0xf301, 0xf302, 0xf303, + 0xf300, 0xf310, 0xf30e, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200 +}; + +struct { + unsigned char s, c; + int valid; +} hil_last; + +#define hil_getlast(s,c) do { s = hil_last.s; c = hil_last.c; hil_last.valid = 0; } while (0) + +struct { + unsigned char data[16]; + unsigned int ptr; +} poll; + +unsigned char curdev = 0; + +static void poll_finished(void) +{ + switch (poll.data[0]) + { + case 0x40: + { + unsigned char scode = (poll.data[1] >> 1) | ((poll.data[1] & 1)?0x80:0); +#if 0 + if (scode & 0x80) + printk("[%02x]", scode & 0x7f); +#endif + handle_scancode(scode); + } + break; + } + curdev = 0; +} + +static inline void handle_status(unsigned char s, unsigned char c) +{ + if (c & 0x8) { + /* End of block */ + if (c & 0x10) + poll_finished(); + } else { + if (c & 0x10) { + if (curdev) + poll_finished(); /* just in case */ + curdev = c & 7; + poll.ptr = 0; + } + } +} + +static inline void handle_data(unsigned char s, unsigned char c) +{ + if (curdev) + poll.data[poll.ptr++] = c; +} + +/* + * Handle HIL interrupts. + */ + +static void hil_interrupt(int irq, void *handle, struct pt_regs *regs) +{ + unsigned char s, c; + s = hil_status(); c = hil_read_data(); + switch (s >> 4) + { + case 0x5: + handle_status(s, c); + break; + case 0x6: + handle_data(s, c); + break; + case 0x4: + hil_last.s = s; + hil_last.c = c; + mb(); + hil_last.valid = 1; + break; + } +} + +/* + * Send a command to the HIL + */ + +static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len) +{ + unsigned long flags; + save_flags(flags); cli(); + while (hil_busy()); + hil_command(cmd); + while (len--) { + while (hil_busy()); + hil_write_data(*(data++)); + } + restore_flags(flags); +} + +/* + * Initialise HIL. + */ + +__initfunc(void hp300_hil_init(void)) +{ + unsigned char s, c, kbid; + unsigned int n = 0; + + memcpy(key_maps[0], hp_plain_map, sizeof(plain_map)); + memcpy(key_maps[1], hp_shift_map, sizeof(plain_map)); + memcpy(key_maps[4], hp_ctrl_map, sizeof(plain_map)); + + if (!hwreg_present((void *)(HILBASE + HIL_DATA))) + return; /* maybe this can happen */ + + request_irq(HIL_IRQ, hil_interrupt, 0, "HIL", NULL); + + /* Turn on interrupts */ + hil_do(HIL_INTON, NULL, 0); + + /* Look for keyboards */ + hil_do(HIL_READKBDSADR, NULL, 0); + while (!hil_last.valid) { + if (n++ > 1000) { + printk("HIL: timed out, assuming no keyboard present.\n"); + return; + } + mb(); + } + hil_getlast(s, c); + if (c == 0) { + printk("HIL: no keyboard present.\n"); + return; + } + for (kbid = 0; (kbid < 8) && ((c & (1< + * + * This file contains the HP300-specific interrupt handling. There + * isn't much here -- we only use the autovector interrupts and at the + * moment everything difficult is handled by the generic code. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ints.h" + +static void hp300_nmi_handler(int irq, void *dev_id, struct pt_regs *fp) +{ + extern void hp300_reset(void); + printk("RESET pressed - self destruct sequence initiated.\n"); + hp300_reset(); +} + +int hp300_request_irq(unsigned int irq, + void (*handler) (int, void *, struct pt_regs *), + unsigned long flags, const char *devname, void *dev_id) +{ + return sys_request_irq(irq, handler, flags, devname, dev_id); +} + +void hp300_free_irq(unsigned int irq, void *dev_id) +{ + sys_free_irq(irq, dev_id); +} + +__initfunc(void hp300_init_IRQ(void)) +{ + /* IPL6 - NMI (keyboard reset) */ + sys_request_irq(7, hp300_nmi_handler, IRQ_FLG_STD, "NMI", hp300_nmi_handler); +} diff -u --recursive --new-file v2.1.105/linux/arch/m68k/hp300/ints.h linux/arch/m68k/hp300/ints.h --- v2.1.105/linux/arch/m68k/hp300/ints.h Wed Dec 31 16:00:00 1969 +++ linux/arch/m68k/hp300/ints.h Sat Jun 13 13:14:31 1998 @@ -0,0 +1,6 @@ +extern void hp300_init_IRQ(void); +extern void (*hp300_handlers[8])(int, void *, struct pt_regs *); +extern void hp300_free_irq(unsigned int irq, void *dev_id); +extern int hp300_request_irq(unsigned int irq, + void (*handler) (int, void *, struct pt_regs *), + unsigned long flags, const char *devname, void *dev_id); diff -u --recursive --new-file v2.1.105/linux/arch/m68k/hp300/ksyms.c linux/arch/m68k/hp300/ksyms.c --- v2.1.105/linux/arch/m68k/hp300/ksyms.c Wed Dec 31 16:00:00 1969 +++ linux/arch/m68k/hp300/ksyms.c Sat Jun 13 13:14:31 1998 @@ -0,0 +1,9 @@ +/* + * linux/arch/m68k/hp300/ksyms.c + * + * Copyright (C) 1998 Philip Blundell + * + * This file contains the HP300-specific kernel symbols. None yet. :-) + */ + +#include diff -u --recursive --new-file v2.1.105/linux/arch/m68k/hp300/reboot.S linux/arch/m68k/hp300/reboot.S --- v2.1.105/linux/arch/m68k/hp300/reboot.S Wed Dec 31 16:00:00 1969 +++ linux/arch/m68k/hp300/reboot.S Sat Jun 13 13:14:31 1998 @@ -0,0 +1,35 @@ +/* + * linux/arch/m68k/hp300/reboot.S + * + * Copyright (C) 1998 Philip Blundell + * + * Do the dirty work of rebooting the machine. Basically we need to undo all the + * good stuff that head.S did when we started up. The caches and MMU must be + * disabled and then we jump back to the PROM. This is a bit gruesome but we put + * a brave face on it. + */ + +/* XXX Doesn't work yet. Not sure why and can't be bothered to fix it at the moment. */ + + .globl hp300_reset +hp300_reset: + .chip 68030 + oriw #0x0700,%sr /* cli() */ + movel hp300_phys_ram_base, %d1 + movel #0, %d0 + movec %d0, %vbr /* reset vector table */ + lea zero, %a0 + lea 1f, %a1 + add %d1, %a0 + add %d1, %a1 + pmove %tc, %a0@ + bclr #7, %a0@ + pmove %a0@, %tc /* goodbye MMU */ + jmp %a1@ +1: movel #0x808, %d0 + movec %d0, %cacr /* cache off */ + moveb #0, 0x1ffff + movel #0x1a4, %a0 + jmp %a0@ + +zero: .quad 0 diff -u --recursive --new-file v2.1.105/linux/arch/m68k/hp300/time.c linux/arch/m68k/hp300/time.c --- v2.1.105/linux/arch/m68k/hp300/time.c Wed Dec 31 16:00:00 1969 +++ linux/arch/m68k/hp300/time.c Sat Jun 13 13:14:31 1998 @@ -0,0 +1,63 @@ +/* + * linux/arch/m68k/hp300/time.c + * + * Copyright (C) 1998 Philip Blundell + * + * This file contains the HP300-specific time handling code. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ints.h" + +/* Clock hardware definitions */ + +#define CLOCKBASE 0xf05f8000 + +#define CLKCR1 0x1 +#define CLKCR2 0x3 +#define CLKCR3 CLKCR1 +#define CLKSR CLKCR2 +#define CLKMSB1 0x5 +#define CLKMSB2 0x9 +#define CLKMSB3 0xD + +unsigned long hp300_gettimeoffset (void) +{ + return 0L; +} + +static void hp300_tick(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned long tmp; + void (*vector)(int, void *, struct pt_regs *) = dev_id; + readb(CLOCKBASE + CLKSR); + asm volatile ("movpw %1@(5),%0" : "=r" (tmp) : "a" (CLOCKBASE)); + vector(irq, NULL, regs); +} + +__initfunc(void hp300_sched_init(void (*vector)(int, void *, struct pt_regs *))) +{ + unsigned int intval = (10000 / 4) - 1; + + writeb(0x1, CLOCKBASE + CLKCR2); /* select CR1 */ + writeb(0x1, CLOCKBASE + CLKCR1); /* reset */ + + asm volatile(" movpw %0,%1@(5)" : : "d" (intval), "a" (CLOCKBASE)); + + sys_request_irq(6, hp300_tick, IRQ_FLG_STD, "timer tick", vector); + + writeb(0x1, CLOCKBASE + CLKCR2); /* select CR1 */ + writeb(0x40, CLOCKBASE + CLKCR1); /* enable irq */ +} + diff -u --recursive --new-file v2.1.105/linux/arch/m68k/hp300/time.h linux/arch/m68k/hp300/time.h --- v2.1.105/linux/arch/m68k/hp300/time.h Wed Dec 31 16:00:00 1969 +++ linux/arch/m68k/hp300/time.h Sat Jun 13 13:14:31 1998 @@ -0,0 +1,4 @@ +extern void hp300_sched_init(void (*vector)(int, void *, struct pt_regs *)); +extern unsigned long hp300_gettimeoffset (void); + + diff -u --recursive --new-file v2.1.105/linux/arch/m68k/kernel/bios32.c linux/arch/m68k/kernel/bios32.c --- v2.1.105/linux/arch/m68k/kernel/bios32.c Tue Feb 17 13:12:45 1998 +++ linux/arch/m68k/kernel/bios32.c Sat Jun 13 13:14:32 1998 @@ -33,7 +33,6 @@ * been removed in this version. */ -#include #include #include #include @@ -49,7 +48,7 @@ #define GB (1024*MB) #define MAJOR_REV 0 -#define MINOR_REV 0 +#define MINOR_REV 1 /* * Base addresses of the PCI memory and I/O areas on the Hades. @@ -264,12 +263,14 @@ #define MAX(val1, val2) ( ((val1) > (val2)) ? val1 : val2) -__initfunc(static void layout_dev(struct pci_dev *dev)) +__initfunc(static void layout_dev(struct pci_dev *dev, unsigned long pci_mem_base, + unsigned long pci_io_base)) { struct pci_bus *bus; unsigned short cmd; unsigned int base, mask, size, reg; unsigned int alignto; + int i; /* * Skip video cards for the time being. @@ -283,7 +284,7 @@ bus = dev->bus; pcibios_read_config_word(bus->number, dev->devfn, PCI_COMMAND, &cmd); - for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4) + for (reg = PCI_BASE_ADDRESS_0, i = 0; reg <= PCI_BASE_ADDRESS_5; reg += 4, i++) { /* * Figure out how much space and of what type this @@ -297,6 +298,7 @@ if (!base) { /* this base-address register is unused */ + dev->base_address[i] = 0; continue; } @@ -322,6 +324,7 @@ io_base = base + size; pcibios_write_config_dword(bus->number, dev->devfn, reg, base | 0x1); + dev->base_address[i] = (pci_io_base + base) | 1; DBG_DEVS(("layout_dev: IO address: %lX\n", base)); } else @@ -369,6 +372,7 @@ mem_base = base + size; pcibios_write_config_dword(bus->number, dev->devfn, reg, base); + dev->base_address[i] = pci_mem_base + base; } } @@ -396,7 +400,8 @@ bus->number, PCI_SLOT(dev->devfn), dev->vendor, dev->device, dev->class)); } -__initfunc(static void layout_bus(struct pci_bus *bus)) +__initfunc(static void layout_bus(struct pci_bus *bus, unsigned long pci_mem_base, + unsigned long pci_io_base)) { struct pci_dev *dev; @@ -438,7 +443,7 @@ for (dev = bus->devices; dev; dev = dev->sibling) { if (dev->class >> 16 != PCI_BASE_CLASS_BRIDGE) - layout_dev(dev); + layout_dev(dev, pci_mem_base, pci_io_base); } } @@ -507,8 +512,7 @@ return 0; } -__initfunc(unsigned long pcibios_init(unsigned long mem_start, - unsigned long mem_end)) +__initfunc(void pcibios_init(void)) { printk("Linux/m68k PCI BIOS32 revision %x.%02x\n", MAJOR_REV, MINOR_REV); @@ -516,7 +520,8 @@ printk("...NOT modifying existing PCI configuration\n"); #endif - return mem_start; + pci_mem_base = 0x80000000; + pci_io_base = 0xB0000000; } /* @@ -555,26 +560,35 @@ } } -__initfunc(unsigned long pcibios_fixup(unsigned long mem_start, - unsigned long mem_end)) +__initfunc(void pcibios_fixup(void)) { #if PCI_MODIFY + unsigned long orig_mem_base, orig_io_base; + + orig_mem_base = pci_mem_base; + orig_io_base = pci_io_base; + pci_mem_base = 0; + pci_io_base = 0; + /* * Scan the tree, allocating PCI memory and I/O space. */ - layout_bus(&pci_root); -#endif + layout_bus(&pci_root, orig_mem_base, orig_io_base); - pci_mem_base = 0x80000000; - pci_io_base = 0xB0000000; + pci_mem_base = orig_mem_base; + pci_io_base = orig_io_base; +#endif /* * Now is the time to do all those dirty little deeds... */ hades_fixup(); +} - return mem_start; +__initfunc(char *pcibios_setup(char *str)) +{ + return str; } #endif /* CONFIG_PCI */ diff -u --recursive --new-file v2.1.105/linux/arch/m68k/kernel/entry.S linux/arch/m68k/kernel/entry.S --- v2.1.105/linux/arch/m68k/kernel/entry.S Tue Feb 17 13:12:45 1998 +++ linux/arch/m68k/kernel/entry.S Sat Jun 13 13:14:32 1998 @@ -579,6 +579,9 @@ .long SYMBOL_NAME(sys_pread) /* 180 */ .long SYMBOL_NAME(sys_pwrite) .long SYMBOL_NAME(sys_lchown); + .long SYMBOL_NAME(sys_getcwd) + .long SYMBOL_NAME(sys_capget) + .long SYMBOL_NAME(sys_capset) /* 185 */ .rept NR_syscalls-(.-SYMBOL_NAME(sys_call_table))/4 .long SYMBOL_NAME(sys_ni_syscall) .endr diff -u --recursive --new-file v2.1.105/linux/arch/m68k/kernel/head.S linux/arch/m68k/kernel/head.S --- v2.1.105/linux/arch/m68k/kernel/head.S Tue Feb 17 13:12:45 1998 +++ linux/arch/m68k/kernel/head.S Sat Jun 13 13:14:32 1998 @@ -17,6 +17,7 @@ ** 95/11/18 Richard Hirst: Added MVME166 support ** 96/04/26 Guenther Kelleter: fixed identity mapping for Falcon with ** Magnum- and FX-alternate ram +** 98/04/25 Phil Blundell: added HP300 support ** ** This file is subject to the terms and conditions of the GNU General Public ** License. See the file README.legal in the main directory of this archive @@ -73,10 +74,25 @@ #include .globl SYMBOL_NAME(kernel_pg_dir), SYMBOL_NAME(kpt) -.globl SYMBOL_NAME(availmem), SYMBOL_NAME(mvme_bdid_ptr) +.globl SYMBOL_NAME(availmem) .globl SYMBOL_NAME(m68k_pgtable_cachemode) .globl SYMBOL_NAME(kernel_pmd_table), SYMBOL_NAME(swapper_pg_dir) +#if defined(CONFIG_MVME16x) +.globl SYMBOL_NAME(mvme_bdid_ptr) +#endif + +/* + * Added m68k_supervisor_cachemode for 68060 boards where some drivers + * need writethrough caching for supervisor accesses. Drivers known to + * be effected are 53c7xx.c and apricot.c (when used on VME boards). + * Richard Hirst. + */ + +#ifdef CONFIG_060_WRITETHROUGH +.globl SYMBOL_NAME(m68k_supervisor_cachemode) +#endif + D6B_0460 = 16 /* indicates 680[46]0 in d6 */ D6B_060 = 17 /* indicates 68060 in d6 */ D6F_040 = 1< 0x00xxxxxx) using an 030 early + termination page descriptor. The ROM mapping is needed because the LEDs + are mapped there too. */ + + movel #_PAGE_NOCACHE030+_PAGE_PRESENT+_PAGE_ACCESSED,%d0 + movel %d0,%a5@(0x78<<2) + +Lnothp300: + +#endif + #if defined(CONFIG_MVME16x) is_not_mvme16x(Lnot16x) @@ -639,6 +706,25 @@ Lnot16x: #endif +#if defined(CONFIG_BVME6000) + is_not_bvme6000(Lnotbvm) + + /* + * On BVME6000 we have already created kernel page tables for + * 4MB of RAM at address 0, so now need to do a transparent + * mapping of the top of memory space. Make it 0.5GByte for now. + */ + + movel #0xe01f0000,%d2 /* logical address base */ + orw #0xa040,%d2 /* add in magic bits */ + .long 0x4e7b2005 /* movec d2,ittr1 */ + .long 0x4e7b2007 /* movec d2,dttr1 */ + .long 0x4e7b2004 /* movec d2,ittr0 */ + .long 0x4e7b2006 /* movec d2,dttr0 */ + +Lnotbvm: +#endif + /* * Setup a transparent mapping of the physical memory we are executing in. * @@ -647,6 +733,7 @@ */ Lmapphys: putc('J') + leds(0x8) #ifdef CONFIG_AMIGA is_not_amiga(Lmapphysnotamiga) @@ -853,6 +940,80 @@ #endif +#if defined(CONFIG_HP300) + is_not_hp300(Lmapphysnothp300) + +/* + * Physical RAM is at 0xff000000. We want to map the kernel at 0x00000000. + * In order to avoid disaster when we enable the MMU we need to make a + * transparent mapping of the RAM we're executing out of as well. + */ + /* + * save physaddr of phys mem in register a3 + */ + + .chip 68030 + lea %pc@(Lmmu),%a3 + movel %d5,%d0 + andl #0xff000000,%d0 /* logical address base */ + orw #TTR_ENABLE+TTR_CI+TTR_RWM+TTR_FCB2+TTR_FCM1+TTR_FCM0,%d0 + movel %d0,%a3@ + pmove %a3@,%tt0 + /* no limit, 4byte descriptors */ + movel #0x80000002,%a3@ + movel %a5,%a3@(4) + pmove %a3@,%srp + pmove %a3@,%crp + pflusha + /* + * enable,super root enable,4096 byte pages,7 bit root index, + * 7 bit pointer index, 6 bit page table index. + */ + movel #0x82c07760,%a3@ + pmove %a3@,%tc /* enable the MMU */ + jmp 1f +1: + .chip 68k + + /* + * Fix up the custom register to point to the new location of the LEDs. + */ + lea %pc@(Lcustom),%a1 + movel #0xf0000000,%a1@ + + /* + * Energise the FPU and caches. + */ + orl #0x64, 0xf05f400c + +Lmapphysnothp300: + +#endif + +#if defined(CONFIG_BVME6000) + is_not_bvme6000(Lmapphysnotbvm) + /* + * save physaddr of phys mem in register a3 + */ + moveq #'L',%d7 + jbsr Lserial_putc + + .word 0xf4d8 /* CINVA I/D */ + .word 0xf518 /* pflusha */ + .long 0x4e7bd807 /* movec a5,srp */ + .long 0x4e7bd806 /* movec a5,urp */ + movel #(TC_ENABLE+TC_PAGE4K),%d0 + /* + * this value is also ok for the 68060, we don`t use the cache + * mode/protection defaults + */ + .long 0x4e7b0003 /* movec d0,tc (enable the MMU) */ + jra LdoneMMUenable /* branch to continuation of startup */ + +Lmapphysnotbvm: + +#endif + LdoneMMUenable: /* @@ -861,6 +1022,7 @@ */ putc('M') + leds(0x10) /* * d5 contains physaddr of kernel start @@ -917,6 +1079,7 @@ /* jump to the kernel start */ putr() + leds(0x55) subl %a6,%a6 /* clear a6 for gdb */ jbsr SYMBOL_NAME(start_kernel) @@ -998,6 +1161,11 @@ #endif #endif +#if defined (CONFIG_BVME6000) +BVME_SCC_CTRL_A = 0xffb0000b +BVME_SCC_DATA_A = 0xffb0000f +#endif + /* * Serial port output support. */ @@ -1062,6 +1230,17 @@ 9: rts +#ifdef CONFIG_HP300 +/* Set LEDs to %d7 */ + .even +Lset_leds: + moveml %a0/%a1,%sp@- + movel %pc@(Lcustom),%a1 + moveb %d7,%a1@(0x1ffff) + moveml %sp@+,%a0/%a1 + rts +#endif + /* * Output character in d7 on serial port. * d7 thrashed. @@ -1073,6 +1252,16 @@ jne 2f moveb %d7,%sp@- .long 0x4e4f0020 + jra 9f +2: +#endif +#ifdef CONFIG_BVME6000 + cmpil #MACH_BVME6000,%d4 + jne 2f +1: btst #2,BVME_SCC_CTRL_A + jeq 1b + moveb %d7,BVME_SCC_DATA_A + jra 9f 2: #endif #ifdef CONFIG_AMIGA @@ -1199,5 +1388,11 @@ .long 0 SYMBOL_NAME_LABEL(m68k_pgtable_cachemode) .long 0 +#ifdef CONFIG_060_WRITETHROUGH +SYMBOL_NAME_LABEL(m68k_supervisor_cachemode) + .long 0 +#endif +#if defined(CONFIG_MVME16x) SYMBOL_NAME_LABEL(mvme_bdid_ptr) .long 0 +#endif diff -u --recursive --new-file v2.1.105/linux/arch/m68k/kernel/ints.c linux/arch/m68k/kernel/ints.c --- v2.1.105/linux/arch/m68k/kernel/ints.c Tue Feb 17 13:12:45 1998 +++ linux/arch/m68k/kernel/ints.c Sat Jun 13 13:14:32 1998 @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -212,7 +213,7 @@ asmlinkage void process_int(unsigned long vec, struct pt_regs *fp) { - if (vec >= VEC_INT1 && vec <= VEC_INT7) { + if (vec >= VEC_INT1 && vec <= VEC_INT7 && !MACH_IS_BVME6000) { vec -= VEC_SPUR; kstat.irqs[0][vec]++; irq_list[vec].handler(vec, irq_list[vec].dev_id, fp); diff -u --recursive --new-file v2.1.105/linux/arch/m68k/kernel/m68k_ksyms.c linux/arch/m68k/kernel/m68k_ksyms.c --- v2.1.105/linux/arch/m68k/kernel/m68k_ksyms.c Thu May 14 19:47:38 1998 +++ linux/arch/m68k/kernel/m68k_ksyms.c Sat Jun 13 13:14:32 1998 @@ -62,7 +62,3 @@ EXPORT_SYMBOL_NOVERS(__down_failed); EXPORT_SYMBOL_NOVERS(__down_failed_interruptible); EXPORT_SYMBOL_NOVERS(__up_wakeup); - -#ifdef CONFIG_PCI -EXPORT_SYMBOL(pci_devices); -#endif diff -u --recursive --new-file v2.1.105/linux/arch/m68k/kernel/ptrace.c linux/arch/m68k/kernel/ptrace.c --- v2.1.105/linux/arch/m68k/kernel/ptrace.c Thu May 7 22:51:46 1998 +++ linux/arch/m68k/kernel/ptrace.c Sat Jun 13 13:14:32 1998 @@ -347,9 +347,13 @@ goto out; child->flags |= PF_PTRACED; if (child->p_pptr != current) { + unsigned long flags; + + write_lock_irqsave(&tasklist_lock, flags); REMOVE_LINKS(child); child->p_pptr = current; SET_LINKS(child); + write_unlock_irqrestore(&tasklist_lock, flags); } send_sig(SIGSTOP, child, 1); ret = 0; @@ -491,6 +495,7 @@ } case PTRACE_DETACH: { /* detach a process that was attached. */ + unsigned long flags; long tmp; ret = -EIO; @@ -499,9 +504,11 @@ child->flags &= ~(PF_PTRACED|PF_TRACESYS); wake_up_process(child); child->exit_code = data; + write_lock_irqsave(&tasklist_lock, flags); REMOVE_LINKS(child); child->p_pptr = child->p_opptr; SET_LINKS(child); + write_unlock_irqrestore(&tasklist_lock, flags); /* make sure the single step bit is not set. */ tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16); put_reg(child, PT_SR, tmp); diff -u --recursive --new-file v2.1.105/linux/arch/m68k/kernel/setup.c linux/arch/m68k/kernel/setup.c --- v2.1.105/linux/arch/m68k/kernel/setup.c Tue Feb 17 13:12:45 1998 +++ linux/arch/m68k/kernel/setup.c Sat Jun 13 13:14:32 1998 @@ -102,6 +102,8 @@ extern void config_sun3(void); extern void config_apollo(void); extern void config_mvme16x(void); +extern void config_bmve6000(void); +extern void config_hp300(void); #define MASK_256K 0xfffc0000 @@ -249,6 +251,16 @@ case MACH_MVME16x: config_mvme16x(); break; +#endif +#ifdef CONFIG_BVME6000 + case MACH_BVME6000: + config_bvme6000(); + break; +#endif +#ifdef CONFIG_HP300 + case MACH_HP300: + config_hp300(); + break; #endif default: panic ("No configuration setup"); diff -u --recursive --new-file v2.1.105/linux/arch/m68k/kernel/signal.c linux/arch/m68k/kernel/signal.c --- v2.1.105/linux/arch/m68k/kernel/signal.c Tue Feb 17 13:12:45 1998 +++ linux/arch/m68k/kernel/signal.c Sat Jun 13 13:14:32 1998 @@ -875,6 +875,30 @@ do_exit(SIGSEGV); } +static inline void +handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler) +{ + switch (regs->d0) { + case -ERESTARTNOHAND: + if (!has_handler) + goto do_restart; + regs->d0 = -EINTR; + break; + + case -ERESTARTSYS: + if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) { + regs->d0 = -EINTR; + break; + } + /* fallthrough */ + case -ERESTARTNOINTR: + do_restart: + regs->d0 = regs->orig_d0; + regs->pc -= 2; + break; + } +} + /* * OK, we're invoking a handler */ @@ -883,24 +907,9 @@ sigset_t *oldset, struct pt_regs *regs) { /* are we from a system call? */ - if (regs->orig_d0 >= 0) { + if (regs->orig_d0 >= 0) /* If so, check system call restarting.. */ - switch (regs->d0) { - case -ERESTARTNOHAND: - regs->d0 = -EINTR; - break; - - case -ERESTARTSYS: - if (!(ka->sa.sa_flags & SA_RESTART)) { - regs->d0 = -EINTR; - break; - } - /* fallthrough */ - case -ERESTARTNOINTR: - regs->d0 = regs->orig_d0; - regs->pc -= 2; - } - } + handle_restart(regs, ka, 1); /* set up the stack frame */ if (ka->sa.sa_flags & SA_SIGINFO) @@ -952,13 +961,14 @@ /* Did we come from a system call? */ if (regs->orig_d0 >= 0) { - /* Restart the system call */ - if (regs->d0 == -ERESTARTNOHAND || - regs->d0 == -ERESTARTSYS || - regs->d0 == -ERESTARTNOINTR) { - regs->d0 = regs->orig_d0; - regs->pc -= 2; - } + /* Restart the system call the same way as + if the process were not traced. */ + struct k_sigaction *ka = + ¤t->sig->action[signr-1]; + int has_handler = + (ka->sa.sa_handler != SIG_IGN && + ka->sa.sa_handler != SIG_DFL); + handle_restart(regs, ka, has_handler); } notify_parent(current, SIGCHLD); schedule(); @@ -1052,15 +1062,9 @@ } /* Did we come from a system call? */ - if (regs->orig_d0 >= 0) { + if (regs->orig_d0 >= 0) /* Restart the system call - no handlers present */ - if (regs->d0 == -ERESTARTNOHAND || - regs->d0 == -ERESTARTSYS || - regs->d0 == -ERESTARTNOINTR) { - regs->d0 = regs->orig_d0; - regs->pc -= 2; - } - } + handle_restart(regs, NULL, 0); /* If we are about to discard some frame stuff we must copy over the remaining frame. */ diff -u --recursive --new-file v2.1.105/linux/arch/m68k/kernel/sys_m68k.c linux/arch/m68k/kernel/sys_m68k.c --- v2.1.105/linux/arch/m68k/kernel/sys_m68k.c Thu May 7 22:51:46 1998 +++ linux/arch/m68k/kernel/sys_m68k.c Sat Jun 13 13:14:32 1998 @@ -73,11 +73,14 @@ if (!(a.flags & MAP_ANONYMOUS)) { error = -EBADF; - if (a.fd >= NR_OPEN || !(file = current->files->fd[a.fd])) + file = fget(a.fd); + if (!file) goto out; } a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); error = do_mmap(file, a.addr, a.len, a.prot, a.flags, a.offset); + if (file) + fput(file); out: unlock_kernel(); return error; diff -u --recursive --new-file v2.1.105/linux/arch/m68k/mac/Makefile linux/arch/m68k/mac/Makefile --- v2.1.105/linux/arch/m68k/mac/Makefile Tue Feb 17 13:12:45 1998 +++ linux/arch/m68k/mac/Makefile Sat Jun 13 13:14:32 1998 @@ -10,7 +10,8 @@ EXTRA_CFLAGS := -Wa,-m68020 O_TARGET := mac.o -O_OBJS := config.o ksyms.o bootparse.o macints.o via6522.o \ +O_OBJS := config.o bootparse.o macints.o via6522.o \ mackeyb.o adb-bus.o macboing.o debug.o +OX_OBJS := mac_ksyms.o include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.105/linux/arch/m68k/mac/adb-bus.c linux/arch/m68k/mac/adb-bus.c --- v2.1.105/linux/arch/m68k/mac/adb-bus.c Fri May 8 23:14:42 1998 +++ linux/arch/m68k/mac/adb-bus.c Sat Jun 13 13:14:33 1998 @@ -93,6 +93,9 @@ static int status = ST_IDLE|TREQ; static int last_status; + +static int driver_running = 0; + /*static int adb_delay;*/ int in_keybinit = 1; @@ -106,11 +109,15 @@ static void adb_hw_setup_IIsi(void); /* - * Misc. defines for testing + * debug level 10 required for ADB logging (should be && debug_adb, ideally) */ extern int console_loglevel; +/* + * Misc. defines for testing - should go to header :-( + */ + #define ADBDEBUG_STATUS (1) #define ADBDEBUG_STATE (2) #define ADBDEBUG_READ (4) @@ -128,7 +135,7 @@ #define ADBDEBUG_IISI (8192) -#define DEBUG_ADB +/*#define DEBUG_ADB*/ #ifdef DEBUG_ADB #define ADBDEBUG (ADBDEBUG_INPUT | ADBDEBUG_READ | ADBDEBUG_START | ADBDEBUG_WRITE | ADBDEBUG_SRQ | ADBDEBUG_REQUEST) @@ -857,10 +864,22 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) { int x, adbdir; + unsigned long flags; struct adb_request *req; last_status = status; + /* prevent races due to SCSI enabling ints */ + save_flags(flags); + cli(); + + if (driver_running) { + restore_flags(flags); + return; + } + + driver_running = 1; + #ifdef USE_ORIG status = (~via_read(via1, vBufB) & (TIP|TREQ)) | (via_read(via1, vACR) & SR_OUT); #else @@ -877,7 +896,6 @@ adb_state, status, last_status, adbdir); #endif - switch (adb_state) { case idle: @@ -1614,6 +1632,9 @@ printk("adb_interrupt: unknown adb_state %d?\n", adb_state); #endif } + /* reset mutex and interrupts */ + driver_running = 0; + restore_flags(flags); } /* diff -u --recursive --new-file v2.1.105/linux/arch/m68k/mac/config.c linux/arch/m68k/mac/config.c --- v2.1.105/linux/arch/m68k/mac/config.c Fri May 8 23:14:42 1998 +++ linux/arch/m68k/mac/config.c Sat Jun 13 13:14:33 1998 @@ -38,17 +38,12 @@ #include "via6522.h" -/* old bootinfo stuff */ +/* Mac bootinfo struct */ struct mac_booter_data mac_bi_data = {0,}; int mac_bisize = sizeof mac_bi_data; -struct compat_bootinfo compat_boot_info ={0,}; -int compat_bisize = sizeof compat_boot_info; - -int compat_bi = 0; - -/* New bootinfo stuff */ +/* New m68k bootinfo stuff and videobase */ extern int m68k_num_memory; extern struct mem_info m68k_memory[NUM_MEMINFO]; @@ -59,7 +54,7 @@ void *mac_env; /* Loaded by the boot asm */ -/* The locgial video addr. determined by head.S - testing */ +/* The logical video addr. determined by head.S - testing */ extern unsigned long mac_videobase; /* The phys. video addr. - might be bogus on some machines */ @@ -84,23 +79,22 @@ extern void mac_debug_init(void); #ifdef CONFIG_MAGIC_SYSRQ + +/* XXX FIXME: Atari scancodes still */ static char mac_sysrq_xlate[128] = - "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */ - "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */ - "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */ - "bnm,./\000\000\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */ + "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */ + "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */ + "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */ + "bnm,./\000\000\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */ "\206\207\210\211\212\000\000\000\000\000-\000\000\000+\000"/* 0x40 - 0x4f */ "\000\000\000\177\000\000\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */ - "\000\000\000()/*789456123" /* 0x60 - 0x6f */ + "\000\000\000()/*789456123" /* 0x60 - 0x6f */ "0.\r\000\000\000\000\000\000\000\000\000\000\000\000\000"; /* 0x70 - 0x7f */ #endif extern void (*kd_mksound)(unsigned int, unsigned int); -void mac_get_model(char *str) -{ - strcpy(str,"Macintosh"); -} +static void mac_get_model(char *str); void mac_bang(int irq, void *vector, struct pt_regs *p) { @@ -120,20 +114,21 @@ extern int console_loglevel; +/* + * This function translates the boot timeval into a proper date, to initialize + * the system time. + * Known problem: off by one after Feb. 27 on leap years + */ + void mac_gettod (int *yearp, int *monp, int *dayp, int *hourp, int *minp, int *secp) { unsigned long time; int leap, oldleap, isleap; - int mon_days[14] = { -1, 31, 27, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, -1 }; + int mon_days[14] = { -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, -1 }; time = mac_bi_data.boottime - 60*mac_bi_data.gmtbias; /* seconds */ -#if 0 - printk("mac_gettod: boottime 0x%lx gmtbias %ld \n", - mac_bi_data.boottime, mac_bi_data.gmtbias); -#endif - *minp = time / 60; *secp = time - (*minp * 60); time = *minp; /* minutes now */ @@ -149,7 +144,7 @@ /* for leap day calculation */ *yearp = (time / 365) + 1970; /* approx. year */ - /* leap year calculation - there's an easier way, I bet */ + /* leap year calculation - there's an easier way, I bet. And it's broken :-( */ /* calculate leap days up to previous year */ oldleap = (*yearp-1)/4 - (*yearp-1)/100 + (*yearp-1)/400; /* calculate leap days incl. this year */ @@ -167,7 +162,7 @@ time = *dayp; if (isleap) /* add leap day ?? */ - mon_days[2] = 28; + mon_days[2] += 1; /* count the months */ for (*monp = 1; time > mon_days[*monp]; (*monp)++) @@ -175,12 +170,6 @@ *dayp = time; -#if 1 - printk("mac_gettod: %d-%d-%d %d:%d.%d GMT (GMT offset %d)\n", - *yearp, *monp, *dayp, *hourp, *minp, *secp, - (signed long) mac_bi_data.gmtbias); -#endif - return; } @@ -189,13 +178,10 @@ ; } +extern struct consw fb_con; +extern struct fb_info *mac_fb_init(long *); extern void mac_video_setup(char *, int *); -void mac_debug_init (void) -{ - ; -} - void (*mac_handlers[8])(int, void *, struct pt_regs *)= { mac_default_handler, @@ -222,6 +208,7 @@ mac_bi_data.id = *data; break; case BI_MAC_VADDR: + /* save booter supplied videobase; use the one mapped in head.S! */ mac_orig_videoaddr = *data; mac_bi_data.videoaddr = mac_videobase; break; @@ -265,8 +252,6 @@ printk("ERROR: no Mac, but config_mac() called!! \n"); } - mac_debugging_penguin(5); - mac_debug_init(); mach_sched_init = mac_sched_init; @@ -289,9 +274,6 @@ mach_mksound = mac_mksound; #endif mach_reset = mac_reset; -#ifdef CONFIG_MAC_FLOPPY - mach_floppy_setup = mac_floppy_setup; -#endif conswitchp = &fb_con; mach_max_dma_address = 0xffffffff; #if 0 @@ -330,12 +312,19 @@ nubus_sweep_video(); - mac_debugging_penguin(6); } /* - * Macintosh Table + * Macintosh Table: hardcoded model configuration data. + * + * Much of this was defined by Alan, based on who knows what docs. + * I've added a lot more, and some of that was pure guesswork based + * on hardware pages present on the Mac web site. Possibly wildly + * inaccurate, so look here if a new Mac model won't run. Example: if + * a Mac crashes immediately after the VIA1 registers have been dumped + * to the screen, it probably died attempting to read DirB on a RBV. + * Meaning it should have MAC_VIA_IIci here :-) */ struct mac_model *macintosh_config; @@ -359,10 +348,11 @@ * * The IIfx apparently has different ADB hardware, and stuff * so zany nobody knows how to drive it. + * Even so, with Marten's help we'll try to deal with it :-) */ { MAC_MODEL_IICI, "IIci", MAC_ADB_II, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_IIFX, "IIfx", MAC_ADB_NONE, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_IIFX, "IIfx", MAC_ADB_II, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_IISI, "IIsi", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_IIVI, "IIvi", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_IIVX, "IIvx", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, @@ -378,6 +368,7 @@ * Some Mac LC machines. Basically the same as the IIci, ADB like IIsi */ + { MAC_MODEL_LC, "LC", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_LCII, "LC II", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_LCIII,"LC III", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, @@ -389,32 +380,35 @@ * place to confuse us. The 840 seems to have a scsi location of its own */ - { MAC_MODEL_Q605, "Quadra 605", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, - { MAC_MODEL_Q610, "Quadra 610", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, - { MAC_MODEL_Q630, "Quadra 630", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, - { MAC_MODEL_Q650, "Quadra 650", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, + { MAC_MODEL_Q605, "Quadra 605", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, + { MAC_MODEL_Q610, "Quadra 610", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, + { MAC_MODEL_Q630, "Quadra 630", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_QUADRA, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, + { MAC_MODEL_Q650, "Quadra 650", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, /* The Q700 does have a NS Sonic */ - { MAC_MODEL_Q700, "Quadra 700", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_QUADRA2, MAC_ETHER_SONIC, MAC_NUBUS}, - { MAC_MODEL_Q800, "Quadra 800", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, + { MAC_MODEL_Q700, "Quadra 700", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_QUADRA2, MAC_ETHER_SONIC, MAC_NUBUS}, + { MAC_MODEL_Q800, "Quadra 800", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, /* Does the 840 have ethernet ??? documents seem to indicate its not quite a Quadra in this respect ? */ - { MAC_MODEL_Q840, "Quadra 840", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA3, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_Q840, "Quadra 840", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA3, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, /* These might have IOP problems */ - { MAC_MODEL_Q900, "Quadra 900", MAC_ADB_IISI, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_QUADRA2, MAC_ETHER_SONIC, MAC_NUBUS}, - { MAC_MODEL_Q950, "Quadra 950", MAC_ADB_IISI, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_QUADRA2, MAC_ETHER_SONIC, MAC_NUBUS}, + { MAC_MODEL_Q900, "Quadra 900", MAC_ADB_IISI, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_IOP, MAC_ETHER_SONIC, MAC_NUBUS}, + { MAC_MODEL_Q950, "Quadra 950", MAC_ADB_IISI, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_IOP, MAC_ETHER_SONIC, MAC_NUBUS}, /* * Performa - more LC type machines */ - { MAC_MODEL_P460, "Performa 460", MAC_ADB_IISI, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_P475, "Performa 475", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_P520, "Performa 520", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_P550, "Performa 550", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_P575, "Performa 575", MAC_ADB_CUDA, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_TV, "TV", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_P460, "Performa 460", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_P475, "Performa 475", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_P475F, "Performa 475", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_P520, "Performa 520", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_P550, "Performa 550", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_P575, "Performa 575", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_P588, "Performa 588", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_TV, "TV", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_P600, "Performa 600", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, #if 0 /* other sources seem to suggest the P630/Q630/LC630 is more like LCIII */ - { MAC_MODEL_P630, "Performa 630", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_P630, "Performa 630", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, #endif /* * Centris - just guessing again; maybe like Quadra @@ -431,14 +425,14 @@ { MAC_MODEL_PB140, "PowerBook 140", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_PB145, "PowerBook 145", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, /* The PB150 has IDE, and IIci style VIA */ - { MAC_MODEL_PB150, "PowerBook 150", MAC_ADB_PB1, MAC_VIA_IIci, MAC_SCSI_QUADRA, MAC_IDE_PB, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB150, "PowerBook 150", MAC_ADB_PB1, MAC_VIA_IIci, MAC_SCSI_QUADRA, MAC_IDE_PB, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_PB160, "PowerBook 160", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_PB165, "PowerBook 165", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_PB165C, "PowerBook 165c", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_PB170, "PowerBook 170", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_PB180, "PowerBook 180", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_PB180C, "PowerBook 180c", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_PB190, "PowerBook 190cs", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB190, "PowerBook 190cs", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_PB, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_PB520, "PowerBook 520", MAC_ADB_PB2, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, /* @@ -446,7 +440,7 @@ */ { MAC_MODEL_PB210, "PowerBook Duo 210", MAC_ADB_PB2, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_PB230, "PowerBook Duo 230", MAC_ADB_PB2, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB230, "PowerBook Duo 230", MAC_ADB_PB2, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_PB250, "PowerBook Duo 250", MAC_ADB_PB2, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_PB270C, "PowerBook Duo 270c", MAC_ADB_PB2, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_PB280, "PowerBook Duo 280", MAC_ADB_PB2, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, @@ -483,8 +477,6 @@ { printk("\nUnknown macintosh model %d, probably unsupported.\n", model); - mac_debugging_long(1, (long) 0x55555555); - mac_debugging_long(1, (long) model); model = MAC_MODEL_Q800; printk("Defaulting to: Quadra800, model id %d\n", model); printk("Please report this case to linux-mac68k@wave.lm.com\n"); @@ -502,7 +494,7 @@ /* * Report booter data: */ - printk (" Penguin (bootinfo version %d) data:\n", 2-compat_bi); + printk (" Penguin bootinfo data:\n"); printk (" Video: addr 0x%lx row 0x%lx depth %lx dimensions %d x %d\n", mac_bi_data.videoaddr, mac_bi_data.videorow, mac_bi_data.videodepth, mac_bi_data.dimensions & 0xFFFF, @@ -534,6 +526,12 @@ void mac_report_hardware(void) { printk("Apple Macintosh %s\n", macintosh_config->name); +} + +static void mac_get_model(char *str) +{ + strcpy(str,"Macintosh "); + strcat(str, macintosh_config->name); } /* diff -u --recursive --new-file v2.1.105/linux/arch/m68k/mac/debug.c linux/arch/m68k/mac/debug.c --- v2.1.105/linux/arch/m68k/mac/debug.c Fri May 8 23:14:42 1998 +++ linux/arch/m68k/mac/debug.c Sat Jun 13 13:14:33 1998 @@ -36,6 +36,9 @@ extern unsigned long mac_videodepth; extern unsigned long mac_rowbytes; +#define DEBUG_SCREEN +#define DEBUG_SERIAL + /* * These two auxiliary debug functions should go away ASAP. Only usage: * before the console output is up (after head.S come some other crucial @@ -46,21 +49,30 @@ * The 'pos' argument now simply means 'linefeed after print' ... */ +#ifdef DEBUG_SCREEN static int peng=0, line=0; +#endif void mac_debugging_short(int pos, short num) { +#ifdef DEBUG_SCREEN unsigned char *pengoffset; unsigned char *pptr; int i; +#endif + +#ifdef DEBUG_SERIAL + printk("debug: %d !\n", num); +#endif +#ifdef DEBUG_SCREEN if (!MACH_IS_MAC) { /* printk("debug: %d !\n", num); */ return; } /* calculate current offset */ - pengoffset=(unsigned char *)(mac_videobase+(20+line*2)*mac_rowbytes) + pengoffset=(unsigned char *)(mac_videobase+(150+line*2)*mac_rowbytes) +80*peng; pptr=pengoffset; @@ -77,20 +89,28 @@ line++; peng = 0; } +#endif } void mac_debugging_long(int pos, long addr) { +#ifdef DEBUG_SCREEN unsigned char *pengoffset; unsigned char *pptr; int i; +#endif +#ifdef DEBUG_SERIAL + printk("debug: #%ld !\n", addr); +#endif + +#ifdef DEBUG_SCREEN if (!MACH_IS_MAC) { /* printk("debug: #%ld !\n", addr); */ return; } - pengoffset=(unsigned char *)(mac_videobase+(20+line*2)*mac_rowbytes) + pengoffset=(unsigned char *)(mac_videobase+(150+line*2)*mac_rowbytes) +80*peng; pptr=pengoffset; @@ -106,6 +126,7 @@ line++; peng = 0; } +#endif } /* @@ -115,20 +136,29 @@ #include "that_penguin.h" }; +#ifdef DEBUG_SCREEN /* * B/W version of penguin, unfinished - any takers?? */ static char bw_penguin[]={ #include "bw_penguin.h" }; +#endif void mac_debugging_penguin(int peng) { +#ifdef DEBUG_SCREEN unsigned char *pengoffset; unsigned char *pptr; unsigned char *bwpdptr=bw_penguin; int i; +#endif +#ifdef DEBUG_SERIAL + printk("Penguin: #%d !\n", peng); +#endif + +#ifdef DEBUG_SCREEN if (!MACH_IS_MAC) return; @@ -147,15 +177,19 @@ bwpdptr+=4; pptr+=mac_rowbytes; } +#endif } +#ifdef DEBUG_SCREEN /* * B/W version of flaming Mac, unfinished (see above). */ static char bw_kaboom_map[]={ #include "bw_mac.h" }; +#endif +#ifdef DEBUG_SCREEN static void mac_boom_boom(void) { static unsigned char *boomoffset=NULL; @@ -163,6 +197,13 @@ unsigned char *bwpdptr=bw_kaboom_map; int i; +#ifdef DEBUG_SERIAL + printk("BOOM !\n"); +#endif + + if (!MACH_IS_MAC) + return; + if(!boomoffset) if (mac_videodepth == 1) { boomoffset=(unsigned char *)(mac_videobase+160*mac_rowbytes); @@ -184,25 +225,43 @@ pptr+=mac_rowbytes; } } +#endif void mac_boom(int booms) { +#ifdef DEBUG_SCREEN int i; +#endif if (!MACH_IS_MAC) return; +#ifdef DEBUG_SCREEN for(i=0;i 0; --i ) + barrier(); } while (!(scc.cha_b_ctrl & 0x04)); /* wait for tx buf empty */ - MFPDELAY(); + for( i = US; i > 0; --i ) + barrier(); scc.cha_b_data = c; } -void mac_scc_console_write (struct console *co, const char *str, +static inline void mac_scca_out (char c) +{ + int i; + do { + for( i = US; i > 0; --i ) + barrier(); + } while (!(scc.cha_a_ctrl & 0x04)); /* wait for tx buf empty */ + for( i = US; i > 0; --i ) + barrier(); + scc.cha_a_data = c; +} + +void mac_sccb_console_write (struct console *co, const char *str, unsigned int count) { while (count--) { if (*str == '\n') - mac_scc_out( '\r' ); - mac_scc_out( *str++ ); + mac_sccb_out( '\r' ); + mac_sccb_out( *str++ ); + } +} + +void mac_scca_console_write (struct console *co, const char *str, + unsigned int count) +{ + while (count--) { + if (*str == '\n') + mac_scca_out( '\r' ); + mac_scca_out( *str++ ); } } #ifdef CONFIG_SERIAL_CONSOLE -int mac_scc_console_wait_key(struct console *co) +int mac_sccb_console_wait_key(struct console *co) { + int i; do { - MFPDELAY(); + for( i = US; i > 0; --i ) + barrier(); } while( !(scc.cha_b_ctrl & 0x01) ); /* wait for rx buf filled */ - MFPDELAY(); + for( i = US; i > 0; --i ) + barrier(); return( scc.cha_b_data ); } + +int mac_scca_console_wait_key(struct console *co) +{ + int i; + do { + for( i = US; i > 0; --i ) + barrier(); + } while( !(scc.cha_a_ctrl & 0x01) ); /* wait for rx buf filled */ + for( i = US; i > 0; --i ) + barrier(); + return( scc.cha_a_data ); +} #endif /* The following two functions do a quick'n'dirty initialization of the MFP or * SCC serial ports. They're used by the debugging interface, kgdb, and the * serial console code. */ -#define SCC_WRITE(reg,val) \ +#define SCCB_WRITE(reg,val) \ do { \ + int i; \ scc.cha_b_ctrl = (reg); \ - MFPDELAY(); \ + for( i = US; i > 0; --i ) \ + barrier(); \ scc.cha_b_ctrl = (val); \ - MFPDELAY(); \ + for( i = US; i > 0; --i ) \ + barrier(); \ + } while(0) + +#define SCCA_WRITE(reg,val) \ + do { \ + int i; \ + scc.cha_a_ctrl = (reg); \ + for( i = US; i > 0; --i ) \ + barrier(); \ + scc.cha_a_ctrl = (val); \ + for( i = US; i > 0; --i ) \ + barrier(); \ } while(0) /* loops_per_sec isn't initialized yet, so we can't use udelay(). This does a * delay of ~ 60us. */ +/* Mac: loops_per_sec min. 1900000 ^= .5 us; MFPDELAY was 0.6 us*/ #define LONG_DELAY() \ do { \ int i; \ - for( i = 100; i > 0; --i ) \ - MFPDELAY(); \ + for( i = 60*US; i > 0; --i ) \ + barrier(); \ } while(0) #ifndef CONFIG_SERIAL_CONSOLE @@ -310,30 +428,56 @@ reg3 = (cflag & CSIZE) == CS8 ? 0xc0 : 0x40; reg5 = (cflag & CSIZE) == CS8 ? 0x60 : 0x20 | 0x82 /* assert DTR/RTS */; - - (void)scc.cha_b_ctrl; /* reset reg pointer */ - SCC_WRITE( 9, 0xc0 ); /* reset */ - LONG_DELAY(); /* extra delay after WR9 access */ - SCC_WRITE( 4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 | - 0x04 /* 1 stopbit */ | - clkmode ); - SCC_WRITE( 3, reg3 ); - SCC_WRITE( 5, reg5 ); - SCC_WRITE( 9, 0 ); /* no interrupts */ - LONG_DELAY(); /* extra delay after WR9 access */ - SCC_WRITE( 10, 0 ); /* NRZ mode */ - SCC_WRITE( 11, clksrc ); /* main clock source */ - SCC_WRITE( 12, div ); /* BRG value */ - SCC_WRITE( 13, 0 ); /* BRG high byte */ - SCC_WRITE( 14, brgsrc_table[baud] ); - SCC_WRITE( 14, brgsrc_table[baud] | (div ? 1 : 0) ); - SCC_WRITE( 3, reg3 | 1 ); - SCC_WRITE( 5, reg5 | 8 ); - + +#if 0 + if (port) { +#endif + (void)scc.cha_b_ctrl; /* reset reg pointer */ + SCCB_WRITE( 9, 0xc0 ); /* reset */ + LONG_DELAY(); /* extra delay after WR9 access */ + SCCB_WRITE( 4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 | + 0x04 /* 1 stopbit */ | + clkmode ); + SCCB_WRITE( 3, reg3 ); + SCCB_WRITE( 5, reg5 ); + SCCB_WRITE( 9, 0 ); /* no interrupts */ + LONG_DELAY(); /* extra delay after WR9 access */ + SCCB_WRITE( 10, 0 ); /* NRZ mode */ + SCCB_WRITE( 11, clksrc ); /* main clock source */ + SCCB_WRITE( 12, div ); /* BRG value */ + SCCB_WRITE( 13, 0 ); /* BRG high byte */ + SCCB_WRITE( 14, brgsrc_table[baud] ); + SCCB_WRITE( 14, brgsrc_table[baud] | (div ? 1 : 0) ); + SCCB_WRITE( 3, reg3 | 1 ); + SCCB_WRITE( 5, reg5 | 8 ); +#if 0 + } else { +#endif + (void)scc.cha_a_ctrl; /* reset reg pointer */ + SCCA_WRITE( 9, 0xc0 ); /* reset */ + LONG_DELAY(); /* extra delay after WR9 access */ + SCCA_WRITE( 4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 | + 0x04 /* 1 stopbit */ | + clkmode ); + SCCA_WRITE( 3, reg3 ); + SCCA_WRITE( 5, reg5 ); + SCCA_WRITE( 9, 0 ); /* no interrupts */ + LONG_DELAY(); /* extra delay after WR9 access */ + SCCA_WRITE( 10, 0 ); /* NRZ mode */ + SCCA_WRITE( 11, clksrc ); /* main clock source */ + SCCA_WRITE( 12, div ); /* BRG value */ + SCCA_WRITE( 13, 0 ); /* BRG high byte */ + SCCA_WRITE( 14, brgsrc_table[baud] ); + SCCA_WRITE( 14, brgsrc_table[baud] | (div ? 1 : 0) ); + SCCA_WRITE( 3, reg3 | 1 ); + SCCA_WRITE( 5, reg5 | 8 ); +#if 0 + } +#endif mac_SCC_reset_done = 1; mac_SCC_init_done = 1; } - +#endif /* DEBUG_SERIAL */ __initfunc(void mac_debug_init(void)) { @@ -341,23 +485,24 @@ /* the m68k_debug_device is used by the GDB stub, do nothing here */ return; #endif +#ifdef DEBUG_SERIAL if (!strcmp( m68k_debug_device, "ser" )) { strcpy( m68k_debug_device, "ser1" ); } if (!strcmp( m68k_debug_device, "ser1" )) { /* ST-MFP Modem1 serial port */ mac_init_scc_port( B9600|CS8, 0 ); - mac_console_driver.write = mac_scc_console_write; + mac_console_driver.write = mac_scca_console_write; } else if (!strcmp( m68k_debug_device, "ser2" )) { /* SCC Modem2 serial port */ mac_init_scc_port( B9600|CS8, 1 ); - mac_console_driver.write = mac_scc_console_write; + mac_console_driver.write = mac_sccb_console_write; } if (mac_console_driver.write) register_console(&mac_console_driver); -} #endif +} /* * Local variables: diff -u --recursive --new-file v2.1.105/linux/arch/m68k/mac/ksyms.c linux/arch/m68k/mac/ksyms.c --- v2.1.105/linux/arch/m68k/mac/ksyms.c Wed Apr 8 19:36:25 1998 +++ linux/arch/m68k/mac/ksyms.c Wed Dec 31 16:00:00 1969 @@ -1,7 +0,0 @@ -#include -#include -#include -/* Hook for mouse driver */ -extern void (*mac_mouse_interrupt_hook) (char *); - -EXPORT_SYMBOL(mac_mouse_interrupt_hook); diff -u --recursive --new-file v2.1.105/linux/arch/m68k/mac/mac_ksyms.c linux/arch/m68k/mac/mac_ksyms.c --- v2.1.105/linux/arch/m68k/mac/mac_ksyms.c Wed Dec 31 16:00:00 1969 +++ linux/arch/m68k/mac/mac_ksyms.c Sat Jun 13 13:14:33 1998 @@ -0,0 +1,7 @@ +#include +#include +#include +/* Hook for mouse driver */ +extern void (*mac_mouse_interrupt_hook) (char *); + +EXPORT_SYMBOL(mac_mouse_interrupt_hook); diff -u --recursive --new-file v2.1.105/linux/arch/m68k/mac/macints.c linux/arch/m68k/mac/macints.c --- v2.1.105/linux/arch/m68k/mac/macints.c Fri May 8 23:14:42 1998 +++ linux/arch/m68k/mac/macints.c Sat Jun 13 13:14:33 1998 @@ -28,6 +28,12 @@ * * 7 - Debug output * + * AV Macs only, handled by PSC: + * + * 3 - MACE ethernet IRQ (DMA complete on level 4) + * + * 5 - DSP ?? + * * Using the autovector irq numbers for Linux/m68k hardware interrupts without * the IRQ_MACHSPEC bit set would interfere with the general m68k interrupt * handling in kernel versions 2.0.x, so the following strategy is used: @@ -57,6 +63,10 @@ * should be sufficient to use the same numbers (everything > 7 is assumed * to be machspec, according to Jes!). * + * TODO: + * - integrate Nubus interrupts in request/free_irq + * + * - */ #include @@ -64,6 +74,7 @@ #include #include #include /* for intr_count */ +#include #include #include @@ -98,7 +109,10 @@ static struct irqhandler via1_handler[8]; static struct irqhandler via2_handler[8]; static struct irqhandler rbv_handler[8]; +static struct irqhandler psc3_handler[8]; static struct irqhandler scc_handler[8]; +static struct irqhandler psc5_handler[8]; +static struct irqhandler psc6_handler[8]; static struct irqhandler nubus_handler[8]; static struct irqhandler *handler_table[8]; @@ -111,7 +125,10 @@ static struct irqparam via1_param[8]; static struct irqparam via2_param[8]; static struct irqparam rbv_param[8]; +static struct irqparam psc3_param[8]; static struct irqparam scc_param[8]; +static struct irqparam psc5_param[8]; +static struct irqparam psc6_param[8]; static struct irqparam nubus_param[8]; static struct irqparam *param_table[8]; @@ -125,27 +142,51 @@ /* * This array holds the pointers to the various VIA or other interrupt - * controllers + * controllers, indexed by interrupt level */ static volatile unsigned char *via_table[8]; -#ifdef VIABASE_WEIRDNESS /* - * VIA2 / RBV default base address + * Arrays with irq statistics */ +static unsigned long via1_irqs[8]; +static unsigned long via2_irqs[8]; +static unsigned long rbv_irqs[8]; +static unsigned long psc3_irqs[8]; +static unsigned long scc_irqs[8]; +static unsigned long psc5_irqs[8]; +static unsigned long psc6_irqs[8]; +static unsigned long nubus_irqs[8]; -volatile unsigned char *via2_regp = ((volatile unsigned char *)VIA2_BAS); -volatile unsigned char *rbv_regp = ((volatile unsigned char *)VIA2_BAS_IIci); -#endif +static unsigned long *mac_irqs[8]; + +/* + * VIA2 / RBV register base pointers + */ + +volatile unsigned char *via2_regp=(volatile unsigned char *)VIA2_BAS; +volatile unsigned char *rbv_regp=(volatile unsigned char *)VIA2_BAS_IIci; +volatile unsigned char *oss_regp=(volatile unsigned char *)OSS_BAS; +volatile unsigned char *psc_regp=(volatile unsigned char *)PSC_BAS; /* * Flags to control via2 / rbv behaviour */ static int via2_is_rbv = 0; +static int via2_is_oss = 0; static int rbv_clear = 0; +/* fake VIA2 to OSS bit mapping */ +static int oss_map[8] = {2, 7, 0, 1, 3, 4, 5}; + +void oss_irq(int irq, void *dev_id, struct pt_regs *regs); +static void oss_do_nubus(int irq, void *dev_id, struct pt_regs *regs); + +/* PSC ints */ +void psc_irq(int irq, void *dev_id, struct pt_regs *regs); + /* * console_loglevel determines NMI handler function */ @@ -177,6 +218,10 @@ #ifdef DEBUG_MACINTS printk("Mac interrupt stuff initializing ...\n"); #endif + + via2_regp = (unsigned char *)VIA2_BAS; + rbv_regp = (unsigned char *)VIA2_BAS_IIci; + /* initialize the hardwired (primary, autovector) IRQs */ /* level 1 IRQ: VIA1, always present */ @@ -184,17 +229,34 @@ /* via2 or rbv?? */ if (macintosh_config->via_type == MAC_VIA_IIci) { - /* VIA2 is part of the RBV: different base, other offsets */ - via2_is_rbv = 1; - /* LC III weirdness: IFR seems to behave like VIA2 */ - /* FIXME: maybe also for LC II ?? */ - if (macintosh_config->ident == MAC_MODEL_LCIII) { - rbv_clear = 0x0; + /* + * A word of caution: the definitions here only affect interrupt + * handling, see via6522.c for yet another file to change + * base addresses and RBV flags + */ + + /* yes, this is messy - the IIfx deserves a class of his own */ + if (macintosh_config->ident == MAC_MODEL_IIFX) { + /* no real VIA2, the OSS seems _very_different */ + via2_is_oss = 1; + /* IIfx has OSS, at a different base address than RBV */ + if (macintosh_config->ident == MAC_MODEL_IIFX) + rbv_regp = (unsigned char *) OSS_BAS; + sys_request_irq(2, oss_irq, IRQ_FLG_LOCK, "oss", oss_irq); } else { - rbv_clear = 0x80; + /* VIA2 is part of the RBV: different base, other offsets */ + via2_is_rbv = 1; + + /* LC III weirdness: IFR seems to behave like VIA2 */ + /* FIXME: maybe also for LC II ?? */ + if (macintosh_config->ident == MAC_MODEL_LCIII) { + rbv_clear = 0x0; + } else { + rbv_clear = 0x80; + } + /* level 2 IRQ: RBV/OSS; we only care about RBV for now */ + sys_request_irq(2, rbv_irq, IRQ_FLG_LOCK, "rbv", rbv_irq); } - /* level 2 IRQ: RBV/OSS; we only care about RBV for now */ - sys_request_irq(2, rbv_irq, IRQ_FLG_LOCK, "rbv", rbv_irq); } else /* level 2 IRQ: VIA2 */ sys_request_irq(2, via2_irq, IRQ_FLG_LOCK, "via2", via2_irq); @@ -205,7 +267,7 @@ * Currently, one interrupt per channel is used, solely * to pass the correct async_info as parameter! */ -#if 0 /* doesn't seem to work yet */ +#if 0 /* want to install debug/SCC shutup routine until SCC init */ sys_request_irq(4, mac_SCC_handler, IRQ_FLG_STD, "INT4", mac_SCC_handler); #else sys_request_irq(4, mac_debug_handler, IRQ_FLG_STD, "INT4", mac_debug_handler); @@ -253,24 +315,64 @@ via_table[0] = via1_regp; handler_table[0] = &via1_handler[0]; param_table[0] = &via1_param[0]; + mac_irqs[0] = &via1_irqs[0]; if (via2_is_rbv) { via_table[1] = rbv_regp; handler_table[1] = &rbv_handler[0]; param_table[1] = &rbv_param[0]; + mac_irqs[1] = &rbv_irqs[0]; } else { via_table[1] = via2_regp; handler_table[1] = &via2_handler[0]; param_table[1] = &via2_param[0]; + mac_irqs[1] = &via2_irqs[0]; } via_table[2] = NULL; via_table[3] = NULL; handler_table[2] = &rbv_handler[0]; - handler_table[3] = &nubus_handler[0]; + handler_table[3] = &scc_handler[0]; + handler_table[4] = NULL; + handler_table[5] = NULL; + handler_table[6] = NULL; + handler_table[7] = &nubus_handler[0]; param_table[2] = &rbv_param[0]; - param_table[3] = &nubus_param[0]; + param_table[3] = &scc_param[0]; + param_table[7] = &nubus_param[0]; + + mac_irqs[2] = &rbv_irqs[0]; + mac_irqs[3] = &scc_irqs[0]; + mac_irqs[7] = &nubus_irqs[0]; + + /* + * AV Macs: shutup the PSC ints + */ + if (macintosh_config->ident == MAC_MODEL_C660 + || macintosh_config->ident == MAC_MODEL_Q840) { + psc_init(); + + handler_table[2] = &psc3_handler[0]; + /* handler_table[3] = &psc4_handler[0]; */ + handler_table[4] = &psc5_handler[0]; + handler_table[5] = &psc6_handler[0]; + + param_table[2] = &psc3_param[0]; + /* param_table[3] = &psc4_param[0]; */ + param_table[4] = &psc5_param[0]; + param_table[5] = &psc6_param[0]; + + mac_irqs[2] = &psc3_irqs[0]; + /* mac_irqs[3] = &psc4_irqs[0]; */ + mac_irqs[4] = &psc5_irqs[0]; + mac_irqs[5] = &psc6_irqs[0]; + + sys_request_irq(3, psc_irq, IRQ_FLG_STD, "PSC3", psc_irq); + sys_request_irq(4, psc_irq, IRQ_FLG_STD, "PSC4", psc_irq); + sys_request_irq(5, psc_irq, IRQ_FLG_STD, "PSC5", psc_irq); + sys_request_irq(6, psc_irq, IRQ_FLG_STD, "PSC6", psc_irq); + } #ifdef DEBUG_MACINTS printk("Mac interrupt init done!\n"); @@ -281,7 +383,7 @@ * We have no machine specific interrupts on a macintoy * Yet, we need to register/unregister interrupts ... :-) * Currently unimplemented: Test for valid irq number, chained irqs, - * Nubus interrupts. + * Nubus interrupts (use nubus_request_irq!). */ int mac_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_regs *), @@ -312,8 +414,8 @@ return -EINVAL; } - /* figure out if SCC pseudo-irq */ - if (irq >= IRQ_IDX(IRQ_SCC) && irq < IRQ_IDX(IRQ_NUBUS_1)) { + /* figure out if SCC pseudo-irq (redundant ??) */ + if (irq >= IRQ_IDX(IRQ_SCC) && irq < IRQ_IDX(IRQ_PSC5_0)) { /* set specific SCC handler */ scc_handler[irqidx].handler = handler; scc_handler[irqidx].dev_id = dev_id; @@ -323,6 +425,8 @@ return 0; } + /* add similar hack for Nubus pseudo-irq here - hide nubus_request_irq */ + via = (volatile unsigned char *) via_table[srcidx]; if (!via) return -EINVAL; @@ -338,9 +442,11 @@ via_param[irqidx].flags = flags; via_param[irqidx].devname = devname; - /* and turn it on ... */ + /* and turn it on ... careful, that's VIA only ... */ if (srcidx == SRC_VIA2 && via2_is_rbv) via_write(via, rIER, via_read(via, rIER)|0x80|(1<<(irqidx))); + else if (srcidx == SRC_VIA2 && via2_is_oss) + via_write(oss_regp, oss_map[irqidx]+8, 2); else via_write(via, vIER, via_read(via, vIER)|0x80|(1<<(irqidx))); @@ -348,8 +454,18 @@ if (irq == IRQ_IDX(IRQ_MAC_SCSI)) { /* * Set vPCR for SCSI interrupts. (what about RBV here?) + * 980429 MS: RBV is ok, OSS seems to be differentt */ - via_write(via, vPCR, 0x66); + if (!via2_is_oss) + /* CB2 (IRQ) indep. interrupt input, positive edge */ + /* CA2 (DRQ) indep. interrupt input, positive edge */ + via_write(via, vPCR, 0x66); +#if 0 + else + /* CB2 (IRQ) indep. interrupt input, negative edge */ + /* CA2 (DRQ) indep. interrupt input, negative edge */ + via_write(via, vPCR, 0x22); +#endif } return 0; @@ -379,7 +495,7 @@ cli(); /* figure out if SCC pseudo-irq */ - if (irq >= IRQ_IDX(IRQ_SCC) && irq < IRQ_IDX(IRQ_NUBUS_1)) { + if (irq >= IRQ_IDX(IRQ_SCC) && irq < IRQ_IDX(IRQ_PSC5_0)) { /* clear specific SCC handler */ scc_handler[irqidx].handler = mac_default_handler; scc_handler[irqidx].dev_id = NULL; @@ -408,6 +524,8 @@ /* and turn it off */ if (srcidx == SRC_VIA2 && via2_is_rbv) via_write(via, rIER, (via_read(via, rIER)&(1<>3) - 1; - int irqidx = (irq & IRQ_IDX_MASK); + int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1; + int irqidx = (irq & IRQ_IDX_MASK); irq_flags[srcidx].disabled &= ~(1<>3) - 1; - int irqidx = (irq & IRQ_IDX_MASK); + int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1; + int irqidx = (irq & IRQ_IDX_MASK); irq_flags[srcidx].disabled |= (1<>3) - 1; - int irqidx = (irq & IRQ_IDX_MASK); + int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1; + int irqidx = (irq & IRQ_IDX_MASK); volatile unsigned char *via; via = (volatile unsigned char *) via_table[srcidx]; @@ -488,6 +606,11 @@ if (srcidx == SRC_VIA2 && via2_is_rbv) via_write(via, rIER, via_read(via, rIER)|0x80|(1<<(irqidx))); + else if (srcidx == SRC_VIA2 && via2_is_oss) + via_write(oss_regp, oss_map[irqidx]+8, 2); + else if (srcidx >= SRC_VIA2) + via_write(via, (0x104 + 0x10*srcidx), + via_read(via, (0x104 + 0x10*srcidx))|0x80|(1<<(irqidx))); else via_write(via, vIER, via_read(via, vIER)|0x80|(1<<(irqidx))); @@ -495,8 +618,8 @@ void mac_turnoff_irq( unsigned int irq ) { - int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1; - int irqidx = (irq & IRQ_IDX_MASK); + int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1; + int irqidx = (irq & IRQ_IDX_MASK); volatile unsigned char *via; via = (volatile unsigned char *) via_table[srcidx]; @@ -505,6 +628,11 @@ if (srcidx == SRC_VIA2 && via2_is_rbv) via_write(via, rIER, (via_read(via, rIER)&(1<= SRC_VIA2) + via_write(via, (0x104 + 0x10*srcidx), + via_read(via, (0x104 + 0x10*srcidx))|(1<<(irqidx))); else via_write(via, vIER, (via_read(via, vIER)&(1<>3) - 1; - int irqidx = (irq & IRQ_IDX_MASK); + int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1; + int irqidx = (irq & IRQ_IDX_MASK); irq_flags[srcidx].pending &= ~(1<>3) - 1; - int irqidx = (irq & IRQ_IDX_MASK); + int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1; + int irqidx = (irq & IRQ_IDX_MASK); return (irq_flags[srcidx].pending & (1<>3) - 1; + irqidx = (i & IRQ_IDX_MASK); + + /* + * Not present: skip + */ + + if (mac_irqs[srcidx] == NULL) + continue; + + /* + * never used by VIAs, unused by others so far, counts + * the magic 'nothing pending' cases ... + */ + if (irqidx == 7 && mac_irqs[srcidx][irqidx]) { + len += sprintf(buf+len, "Level %01d: %10u (spurious) \n", + srcidx, + mac_irqs[srcidx][irqidx]); + continue; + } + + /* + * Nothing registered for this IPL: skip + */ + + if (handler_table[srcidx] == NULL) + continue; + + /* + * No handler installed: skip + */ + + if (handler_table[srcidx][irqidx].handler == mac_default_handler || + handler_table[srcidx][irqidx].handler == nubus_wtf) + continue; + + + if (i < VIA2_SOURCE_BASE) + len += sprintf(buf+len, "via1 %01d: %10u ", + irqidx, + mac_irqs[srcidx][irqidx]); + else if (i < RBV_SOURCE_BASE) + len += sprintf(buf+len, "via2 %01d: %10u ", + irqidx, + mac_irqs[srcidx][irqidx]); + else if (i < MAC_SCC_SOURCE_BASE) + len += sprintf(buf+len, "rbv %01d: %10u ", + irqidx, + mac_irqs[srcidx][irqidx]); + else if (i < NUBUS_SOURCE_BASE) + len += sprintf(buf+len, "scc %01d: %10u ", + irqidx, + mac_irqs[srcidx][irqidx]); + else /* Nubus */ + len += sprintf(buf+len, "nubus %01d: %10u ", + irqidx, + mac_irqs[srcidx][irqidx]); + + len += sprintf(buf+len, "%s\n", + param_table[srcidx][irqidx].devname); + + } + if (num_spurious) + len += sprintf(buf+len, "spurio.: %10u\n", num_spurious); + return len; } void via_scsi_clear(void) @@ -544,6 +740,9 @@ if (via2_is_rbv) { via_write(rbv_regp, rIFR, (1<<3)|(1<<0)|0x80); deep_magic = via_read(rbv_regp, rBufB); + } else if (via2_is_oss) { + /* nothing */ + /* via_write(oss_regp, 9, 0) */; } else deep_magic = via_read(via2_regp, vBufB); mac_enable_irq( IRQ_IDX(IRQ_MAC_SCSI) ); @@ -567,12 +766,24 @@ } } +void scsi_mac_debug(void); +void scsi_mac_polled(void); + void mac_nmi_handler(int irq, void *dev_id, struct pt_regs *fp) { + int i; /* * generate debug output on NMI switch if 'debug' kernel option given * (only works with Penguin!) */ +#if 0 + scsi_mac_debug(); + printk("PC: %08lx\nSR: %04x SP: %p\n", fp->pc, fp->sr, fp); +#endif + for (i=0; i<100; i++) + udelay(1000); + scsi_mac_polled(); + if ( console_loglevel >= 8 ) { #if 0 show_state(); @@ -607,6 +818,7 @@ int ct = 0; struct irqhandler *via_handler = handler_table[*viaidx]; struct irqparam *via_param = param_table[*viaidx]; + unsigned long *via_irqs = mac_irqs[*viaidx]; /* to be changed, possibly: for each non'masked', enabled IRQ, read * flag bit, ack and call handler ... @@ -623,7 +835,12 @@ if(events==0) { - printk("via%d_irq: nothing pending!\n", *viaidx + 1); +#ifdef DEBUG_VIA + /* should go away; mostly missing timer ticks and ADB events */ + printk("via%d_irq: nothing pending, flags %x mask %x!\n", + *viaidx + 1, via_read(via, vIFR), via_read(via,vIER)); +#endif + via_irqs[7]++; return; } @@ -658,9 +875,12 @@ /* call corresponding handlers */ if (events&(1< mark pending */ irq_flags[*viaidx].pending |= (1< call handler */ (via_handler[i].handler)(irq, via, regs); } @@ -683,7 +903,9 @@ ct++; if(events && ct>8) { +#ifdef DEBUG_VIA printk("via%d: stuck events %x\n", (*viaidx)+1, events); +#endif break; } } @@ -740,6 +962,23 @@ struct irqhandler *via_handler = handler_table[srcidx]; struct irqparam *via_param = param_table[srcidx]; + /* shouldn't we disable interrupts here ?? */ + + + /* + * Shouldnt happen + */ + + if(events==0) + { +#ifdef DEBUG_VIA + printk("rbv_irq: nothing pending, flags %x mask %x!\n", + via_read(via, rIFR), via_read(via,rIER)); +#endif + rbv_irqs[7]++; + return; + } + #ifdef DEBUG_VIA /* * limited verbosity for RBV interrupts (add more if needed) @@ -754,19 +993,6 @@ * If ack for masked IRQ required: keep 'pending' info separate. */ - /* shouldn't we disable interrupts here ?? */ - - - /* - * Shouldnt happen - */ - - if(events==0) - { - printk("rbv_irq: nothing pending!\n"); - return; - } - do { /* * Clear the pending flag @@ -784,12 +1010,16 @@ int irq = (srcidx+1)* 8 + i; /* call corresponding handlers */ if (events&(1< mark pending */ irq_flags[srcidx].pending |= (1< call handler */ (via_handler[i].handler)(irq, via, regs); + } } /* and call handlers for pending irqs - first ?? */ if ( (irq_flags[srcidx].pending & (1< mark pending */ + irq_flags[srcidx].pending |= (1< call handler */ + (via_handler[i].handler)(irq, via, regs); + } + } + /* and call handlers for pending irqs - first ?? */ + if ( (irq_flags[srcidx].pending & (1<8) + { + printk("oss: stuck events %x\n",events); + for(i=0;i<7;i++) + { + if(events&(1< mark pending */ + irq_flags[srcidx].pending |= (1< call handler */ + (via_handler[i].handler)(irq, via, regs); + } + } + /* and call handlers for pending irqs - first ?? */ + if ( (irq_flags[srcidx].pending & (1<8) + { + printk("psc: stuck events %x\n",events); + for(i=0;i<7;i++) + { + if(events&(1<2) { +#ifdef DEBUG_NUBUS_INT printk("nubus stuck events - %d/%d\n", map, nubus_active); +#endif return; } @@ -961,6 +1475,7 @@ { if(map&(1<2) + { +#if 0 + printk("nubus stuck events - %d/%d\n", map, nubus_active); +#endif + return; + } + + for(i=0;i<7;i++) + { + if(map&(1< #include #include #include @@ -13,75 +13,27 @@ #include #include #include "via6522.h" +#include "psc.h" volatile unsigned char *via1=(unsigned char *)VIABASE; volatile unsigned char *via2=(unsigned char *)VIABASE2; +volatile unsigned char *psc=(unsigned char *)PSCBASE; unsigned char via1_clock, via1_datab; static int rbv=0; +static int oss=0; + +extern void adb_interrupt(int slot, void *via, struct pt_regs *regs); /* - * Debugging the VBL ints + * hardware reset vector */ - -extern int console_loglevel; +static void (*rom_reset)(void); /* - * VIA1 - hardwired vectors + * Timer defs. */ - -#if 0 /* gone to macints.[ch] */ -extern void via_wtf(int slot, void *via, struct pt_regs *regs); -static void via_do_nubus(int slot, volatile void *via, struct pt_regs *regs); - -extern void adb_interrupt(int slot, void *via, struct pt_regs *regs); - -static struct via_irq_tab via1_func_tab= -{ - { - via_wtf, /* One second interrupt */ - via_wtf, /* Vblank */ - via_wtf, /* ADB data ready */ - via_wtf, /* ADB data */ - via_wtf, /* ADB clock */ - via_wtf, - via_wtf, /* Slot 6 is replaced by the timer */ - via_wtf - } -}; - -static struct via_irq_tab via2_func_tab= -{ - { - via_wtf, - via_do_nubus, - via_wtf, - via_wtf, - via_wtf, - via_wtf, - via_wtf, - via_wtf - } -}; - -static struct via_irq_tab nubus_func_tab= -{ - { - via_wtf, - via_wtf, - via_wtf, - via_wtf, - via_wtf, - via_wtf, - via_wtf, - via_wtf - } -}; -#endif - -extern void adb_interrupt(int slot, void *via, struct pt_regs *regs); - #define MAC_CLOCK_TICK (783300/HZ) /* ticks per HZ */ #define MAC_CLOCK_LOW (MAC_CLOCK_TICK&0xFF) #define MAC_CLOCK_HIGH (MAC_CLOCK_TICK>>8) @@ -91,8 +43,6 @@ { unsigned char c; -/* mac_debugging_penguin(6);*/ - switch(macintosh_config->via_type) { /* @@ -102,6 +52,10 @@ via1=(void *)0x50F00000; via2=(void *)0x50F26000; rbv=1; + if (macintosh_config->ident == MAC_MODEL_IIFX) { + via2=(void *)0x50F1A000; + oss=1; + } break; /* * Quadra and early MacIIs agree on the VIA locations @@ -162,7 +116,7 @@ via_write(via2,vT2CH,0); via_write(via2,vIER, 0x7F); } - else + else if (oss==0) { /* * Init the RBV chip a bit @@ -201,30 +155,18 @@ request_irq(IRQ_MAC_TIMER_1, func, IRQ_FLG_LOCK, "timer", func); -/* mac_debugging_penguin(7);*/ - /* * SE/30: disable video int. * XXX: testing for SE/30 VBL */ - if (macintosh_config->ident == MAC_MODEL_SE30 - && console_loglevel != 10) { + if (macintosh_config->ident == MAC_MODEL_SE30) { c = via_read(via1, vBufB); via_write(via1, vBufB, c|(0x40)); c = via_read(via1, vDirB); via_write(via1, vDirB, c|(0x40)); } - /* - * XXX: use positive edge - */ - - if (console_loglevel == 10) { - c = via_read(via1, vPCR); - via_write(via1, vPCR, c|(0x1)); - } - #if 0 /* gone to mac_init_IRQ */ /* * Set vPCR for SCSI interrupts. @@ -237,172 +179,29 @@ } -#if 0 /* moved to macints.c */ - -static void via_irq(volatile unsigned char *via, struct via_irq_tab *irqtab, - struct pt_regs *regs) -{ - unsigned char events=(via_read(via, vIFR)&via_read(via,vIER))&0x7F; - int i; - int ct=0; - - /* - * Shouldnt happen - */ - - if(events==0) - { - printk("via_irq: nothing pending!\n"); - return; - } - - do { - /* - * Clear the pending flag - */ - - /* HACK HACK - FIXME !!! - just testing some keyboard ideas */ - - /* events&=~(1<<4); */ - via_write(via, vIFR, events); - - /* - * Now see what bits are raised - */ - - for(i=0;i<7;i++) - { - if(events&(1<vector[i])(i, via, regs); - } - - /* - * And done.. - */ - events=(via_read(via, vIFR)&via_read(via,vIER))&0x7F; - ct++; - if(events && ct>8) - { - printk("via: stuck events %x\n",events); - break; - } - } - while(events); - - scsi_mac_polled(); -} - -/* - * - * The RBV is different. RBV appears to stand for randomly broken - * VIA. - */ - -static void rbv_irq(volatile unsigned char *via, struct via_irq_tab *irqtab, - struct pt_regs *regs) -{ - unsigned char events=(via_read(via, rIFR)&via_read(via,rIER))&0x7F; - int i; - int ct=0; - - /* - * Shouldnt happen - */ - - if(events==0) - { - printk("rbv_irq: nothing pending!\n"); - return; - } - - do { - /* - * Clear the pending flag - */ - - /* HACK HACK - FIXME !!! - just testing some keyboard ideas */ - - /* events&=~(1<<4); */ - via_write(via, rIFR, events); - - /* - * Now see what bits are raised - */ - - for(i=0;i<7;i++) - { - if(events&(1<vector[i])(i, via, regs); - } - - /* - * And done.. - */ - events=(via_read(via, rIFR)&via_read(via,rIER))&0x7F; - ct++; - if(events && ct>8) - { - printk("rbv: stuck events %x\n",events); - for(i=0;i<7;i++) - { - if(events&(1<2) - { - printk("nubus stuck events - %d/%d\n", map, nubus_active); - return; - } - for(i=0;i<7;i++) - { - if(map&(1<vm_flags & VM_IO) + goto bad_area; if (vma->vm_start <= address) goto good_area; if (!(vma->vm_flags & VM_GROWSDOWN)) diff -u --recursive --new-file v2.1.105/linux/arch/m68k/mm/hwtest.c linux/arch/m68k/mm/hwtest.c --- v2.1.105/linux/arch/m68k/mm/hwtest.c Wed Dec 31 16:00:00 1969 +++ linux/arch/m68k/mm/hwtest.c Sat Jun 13 13:14:33 1998 @@ -0,0 +1,81 @@ +/* Tests for presence or absence of hardware registers. + * This code was originally in atari/config.c, but I noticed + * that it was also in drivers/nubus/nubus.c and I wanted to + * use it in hp300/config.c, so it seemed sensible to pull it + * out into its own file. + * + * The test is for use when trying to read a hardware register + * that isn't present would cause a bus error. We set up a + * temporary handler so that this doesn't kill the kernel. + * + * There is a test-by-reading and a test-by-writing; I present + * them here complete with the comments from the original atari + * config.c... + * -- PMM , 05/1998 + */ + +/* This function tests for the presence of an address, specially a + * hardware register address. It is called very early in the kernel + * initialization process, when the VBR register isn't set up yet. On + * an Atari, it still points to address 0, which is unmapped. So a bus + * error would cause another bus error while fetching the exception + * vector, and the CPU would do nothing at all. So we needed to set up + * a temporary VBR and a vector table for the duration of the test. + */ + +int hwreg_present( volatile void *regp ) +{ + int ret = 0; + long save_sp, save_vbr; + long tmp_vectors[3]; + + __asm__ __volatile__ + ( "movec %/vbr,%2\n\t" + "movel #Lberr1,%4@(8)\n\t" + "movec %4,%/vbr\n\t" + "movel %/sp,%1\n\t" + "moveq #0,%0\n\t" + "tstb %3@\n\t" + "nop\n\t" + "moveq #1,%0\n" + "Lberr1:\n\t" + "movel %1,%/sp\n\t" + "movec %2,%/vbr" + : "=&d" (ret), "=&r" (save_sp), "=&r" (save_vbr) + : "a" (regp), "a" (tmp_vectors) + ); + + return( ret ); +} + +/* Basically the same, but writes a value into a word register, protected + * by a bus error handler. Returns 1 if successful, 0 otherwise. + */ + +int hwreg_write( volatile void *regp, unsigned short val ) +{ + int ret; + long save_sp, save_vbr; + long tmp_vectors[3]; + + __asm__ __volatile__ + ( "movec %/vbr,%2\n\t" + "movel #Lberr2,%4@(8)\n\t" + "movec %4,%/vbr\n\t" + "movel %/sp,%1\n\t" + "moveq #0,%0\n\t" + "movew %5,%3@\n\t" + "nop \n\t" /* If this nop isn't present, 'ret' may already be + * loaded with 1 at the time the bus error + * happens! */ + "moveq #1,%0\n" + "Lberr2:\n\t" + "movel %1,%/sp\n\t" + "movec %2,%/vbr" + : "=&d" (ret), "=&r" (save_sp), "=&r" (save_vbr) + : "a" (regp), "a" (tmp_vectors), "g" (val) + ); + + return( ret ); +} + diff -u --recursive --new-file v2.1.105/linux/arch/m68k/mm/init.c linux/arch/m68k/mm/init.c --- v2.1.105/linux/arch/m68k/mm/init.c Fri May 8 23:14:42 1998 +++ linux/arch/m68k/mm/init.c Sat Jun 13 13:14:33 1998 @@ -30,40 +30,6 @@ extern void die_if_kernel(char *,struct pt_regs *,long); extern void init_kpointer_table(void); extern void show_net_buffers(void); -extern const char PgtabStr_bad_pmd[]; - -struct pgtable_cache_struct quicklists; - -void __bad_pte(pmd_t *pmd) -{ - printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd)); - pmd_set(pmd, BAD_PAGETABLE); -} - -pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset) -{ - pte_t *pte; - - pte = (pte_t *) __get_free_page(GFP_KERNEL); - if (pmd_none(*pmd)) { - if (pte) { - memset(pte, 0, PAGE_SIZE) - flush_page_to_ram((unsigned long)pte); - flush_tlb_kernel_page((unsigned long)pte); - nocache_page((unsigned long)pte); - pmd_set(pmd, pte); - return pte + offset; - } - pmd_set(pmd, BAD_PAGETABLE); - return NULL; - } - free_page((unsigned long)pte); - if (pmd_bad(*pmd)) { - __bad_pte(pmd); - return NULL; - } - return (pte_t *) pmd_page(*pmd) + offset; -} /* * BAD_PAGE is the page that is used for page faults when linux @@ -110,7 +76,7 @@ total++; if (PageReserved(mem_map+i)) reserved++; - else if (PageSwapCache(mem_map+i)) + if (PageSwapCache(mem_map+i)) cached++; else if (!atomic_read(&mem_map[i].count)) free++; @@ -125,7 +91,6 @@ printk("%d pages nonshared\n",nonshared); printk("%d pages shared\n",shared); printk("%d pages swap cached\n",cached); - printk("%d pages in page table cache\n",pgtable_cache_size); show_buffers(); #ifdef CONFIG_NET show_net_buffers(); @@ -266,7 +231,7 @@ */ for (i = 0; i < 64; i++) { pte_val(ktablep[i]) = physaddr | _PAGE_PRESENT - | _PAGE_CACHE040 | _PAGE_GLOBAL040 + | m68k_supervisor_cachemode | _PAGE_GLOBAL040 | _PAGE_ACCESSED; physaddr += PAGE_SIZE; } diff -u --recursive --new-file v2.1.105/linux/arch/m68k/mm/memory.c linux/arch/m68k/mm/memory.c --- v2.1.105/linux/arch/m68k/mm/memory.c Sun Jun 7 11:16:27 1998 +++ linux/arch/m68k/mm/memory.c Sat Jun 13 13:14:33 1998 @@ -4,6 +4,7 @@ * Copyright (C) 1995 Hamish Macdonald */ +#include #include #include #include @@ -16,7 +17,9 @@ #include #include #include +#ifdef CONFIG_AMIGA #include +#endif /* Strings for `extern inline' functions in . If put directly into these functions, they are output for every file that @@ -451,12 +454,14 @@ * */ +#ifdef CONFIG_AMIGA /* * if on an amiga and address is in first 16M, move it * to the ZTWO_VADDR range */ if (MACH_IS_AMIGA && paddr < 16*1024*1024) return ZTWO_VADDR(paddr); +#endif return paddr; } diff -u --recursive --new-file v2.1.105/linux/arch/m68k/mvme16x/16xints.c linux/arch/m68k/mvme16x/16xints.c --- v2.1.105/linux/arch/m68k/mvme16x/16xints.c Mon Feb 23 18:12:02 1998 +++ linux/arch/m68k/mvme16x/16xints.c Sat Jun 13 13:14:33 1998 @@ -127,7 +127,7 @@ static void mvme16x_defhand (int irq, void *dev_id, struct pt_regs *fp) { - panic ("Unknown interrupt 0x%02x", irq); + printk ("Unknown interrupt 0x%02x\n", irq); } diff -u --recursive --new-file v2.1.105/linux/arch/m68k/mvme16x/Makefile linux/arch/m68k/mvme16x/Makefile --- v2.1.105/linux/arch/m68k/mvme16x/Makefile Tue Feb 17 13:12:45 1998 +++ linux/arch/m68k/mvme16x/Makefile Sat Jun 13 13:14:33 1998 @@ -8,7 +8,7 @@ # Note 2! The CFLAGS definitions are now in the main makefile... O_TARGET := mvme16x.o -O_OBJS := config.o 16xints.o +O_OBJS := config.o 16xints.o rtc.o #OX_OBJS = ksyms.o include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.105/linux/arch/m68k/mvme16x/config.c linux/arch/m68k/mvme16x/config.c --- v2.1.105/linux/arch/m68k/mvme16x/config.c Tue Feb 17 13:12:45 1998 +++ linux/arch/m68k/mvme16x/config.c Sat Jun 13 13:14:33 1998 @@ -34,26 +34,10 @@ #include #include -typedef struct { - unsigned char - ctrl, - bcd_sec, - bcd_min, - bcd_hr, - bcd_dow, - bcd_dom, - bcd_mth, - bcd_year; -} MK48T08; - -#define RTC_WRITE 0x80 -#define RTC_READ 0x40 -#define RTC_STOP 0x20 - int atari_SCC_reset_done = 1; /* So SCC doesn't get reset */ u_long atari_mch_cookie = 0; -MK48T08 * volatile rtc = (MK48T08 *)0xfffc1ff8; +static MK48T08ptr_t volatile rtc = (MK48T08ptr_t)MVME_RTC_BASE; extern void mvme16x_process_int (int level, struct pt_regs *regs); extern void mvme16x_init_IRQ (void); @@ -143,6 +127,11 @@ } +#define pcc2chip ((volatile u_char *)0xfff42000) +#define PccSCCMICR 0x1d +#define PccSCCTICR 0x1e +#define PccSCCRICR 0x1f + __initfunc(void config_mvme16x(void)) { p_bdid p = (p_bdid)mvme_bdid_ptr; @@ -197,7 +186,43 @@ rev & MVME16x_CONFIG_NO_ETHERNET ? "NOT " : ""); } else + { mvme16x_config = MVME16x_CONFIG_GOT_LP | MVME16x_CONFIG_GOT_CD2401; + + /* Dont allow any interrupts from the CD2401 until the interrupt */ + /* handlers are installed */ + + pcc2chip[PccSCCMICR] = 0x10; + pcc2chip[PccSCCTICR] = 0x10; + pcc2chip[PccSCCRICR] = 0x10; + } +} + +static void mvme16x_abort_int (int irq, void *dev_id, struct pt_regs *fp) +{ + p_bdid p = (p_bdid)mvme_bdid_ptr; + unsigned long *new = (unsigned long *)vectors; + unsigned long *old = (unsigned long *)0xffe00000; + volatile unsigned char uc, *ucp; + + if (p->brdno == 0x0162 || p->brdno == 0x172) + { + ucp = (volatile unsigned char *)0xfff42043; + uc = *ucp | 8; + *ucp = uc; + } + else + { + *(volatile unsigned long *)0xfff40074 = 0x40000000; + } + *(new+4) = *(old+4); /* Illegal instruction */ + *(new+9) = *(old+9); /* Trace */ + *(new+47) = *(old+47); /* Trap #15 */ + + if (p->brdno == 0x0162 || p->brdno == 0x172) + *(new+0x5e) = *(old+0x5e); /* ABORT switch */ + else + *(new+0x6e) = *(old+0x6e); /* ABORT switch */ } static void mvme16x_timer_int (int irq, void *dev_id, struct pt_regs *fp) @@ -208,15 +233,26 @@ void mvme16x_sched_init (void (*timer_routine)(int, void *, struct pt_regs *)) { + p_bdid p = (p_bdid)mvme_bdid_ptr; + int irq; + tick_handler = timer_routine; /* Using PCCchip2 or MC2 chip tick timer 1 */ *(volatile unsigned long *)0xfff42008 = 0; *(volatile unsigned long *)0xfff42004 = 10000; /* 10ms */ *(volatile unsigned char *)0xfff42017 |= 3; *(volatile unsigned char *)0xfff4201b = 0x16; - if (request_irq(IRQ_MVME16x_TIMER, mvme16x_timer_int, 0, + if (request_irq(MVME16x_IRQ_TIMER, mvme16x_timer_int, 0, "timer", mvme16x_timer_int)) panic ("Couldn't register timer int"); + + if (p->brdno == 0x0162 || p->brdno == 0x172) + irq = MVME162_IRQ_ABORT; + else + irq = MVME167_IRQ_ABORT; + if (request_irq(irq, mvme16x_abort_int, 0, + "abort", mvme16x_abort_int)) + panic ("Couldn't register abort int"); } @@ -254,76 +290,11 @@ return 0; } -/* - * console_map_init(), here to avoid having to modify drivers/block/genhd.c - */ - -void console_map_init(void) -{ -} - -/* - * fbmem_init(), here to avoid having to modify drivers/char/mem.c - */ - -void fbmem_init(void) -{ -} - -/* Avoid mods to drivers/char/tty_io.c */ - -unsigned long con_init(unsigned long kmem_start) -{ - return (kmem_start); -} - -/* Avoid mods to drivers/char/tty_io.c */ - -int vcs_init(void) -{ - return (0); -} - -/* Avoid mods to drivers/char/tty_io.c */ - -int kbd_init(void) -{ - return (0); -} - -/* Avoid mods to init/main.c */ - -void no_scroll(char *str, int *ints) -{ -} - -/* Avoid mods to kernel/panic.c */ - -void do_unblank_screen(void) -{ -} - int mvme16x_keyb_init (void) { return 0; } -void mvme16x_set_vectors (void) -{ - p_bdid p = (p_bdid)mvme_bdid_ptr; - unsigned long *new = (unsigned long *)vectors; - unsigned long *old = (unsigned long *)0xffe00000;; - - *(new+4) = *(old+4); /* Illegal instruction */ - *(new+9) = *(old+9); /* Trace */ - *(new+47) = *(old+47); /* Trap #15 */ - - if (p->brdno == 0x0162 || p->brdno == 0x172) - *(new+0x5e) = *(old+0x5e); /* ABORT switch */ - else - *(new+0x6e) = *(old+0x6e); /* ABORT switch */ -} - /*------------------- Serial console stuff ------------------------*/ extern void mvme167_serial_console_setup(int cflag); @@ -372,7 +343,7 @@ static void scc_write (char ch) { - volatile char *p = (volatile char *)SCC_A_ADDR; + volatile char *p = (volatile char *)MVME_SCC_A_ADDR; do { scc_delay(); diff -u --recursive --new-file v2.1.105/linux/arch/m68k/mvme16x/rtc.c linux/arch/m68k/mvme16x/rtc.c --- v2.1.105/linux/arch/m68k/mvme16x/rtc.c Wed Dec 31 16:00:00 1969 +++ linux/arch/m68k/mvme16x/rtc.c Sat Jun 13 13:14:33 1998 @@ -0,0 +1,166 @@ +/* + * Real Time Clock interface for Linux on the MVME16x + * + * Based on the PC driver by Paul Gortmaker. + */ + +#define RTC_VERSION "1.00" + +#include +#include +#include +#include +#include +#include +#include +#include +#include /* For struct rtc_time and ioctls, etc */ +#include + +#include +#include +#include +#include + +/* + * We sponge a minor off of the misc major. No need slurping + * up another valuable major dev number for this. If you add + * an ioctl, make sure you don't conflict with SPARC's RTC + * ioctls. + */ + +#define BCD2BIN(val) (((val)&15) + ((val)>>4)*10) +#define BIN2BCD(val) ((((val)/10)<<4) + (val)%10) + +static unsigned char days_in_mo[] = +{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + +static char rtc_status = 0; + +static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + volatile MK48T08ptr_t rtc = (MK48T08ptr_t)MVME_RTC_BASE; + unsigned long flags; + struct rtc_time wtime; + + switch (cmd) { + case RTC_RD_TIME: /* Read the time/date from RTC */ + { + save_flags(flags); + cli(); + /* Ensure clock and real-time-mode-register are accessible */ + rtc->ctrl = RTC_READ; + wtime.tm_sec = BCD2BIN(rtc->bcd_sec); + wtime.tm_min = BCD2BIN(rtc->bcd_min); + wtime.tm_hour = BCD2BIN(rtc->bcd_hr); + wtime.tm_mday = BCD2BIN(rtc->bcd_dom); + wtime.tm_mon = BCD2BIN(rtc->bcd_mth)-1; + wtime.tm_year = BCD2BIN(rtc->bcd_year); + if (wtime.tm_year < 70) + wtime.tm_year += 100; + wtime.tm_wday = BCD2BIN(rtc->bcd_dow)-1; + rtc->ctrl = 0; + restore_flags(flags); + return copy_to_user((void *)arg, &wtime, sizeof wtime) ? + -EFAULT : 0; + } + case RTC_SET_TIME: /* Set the RTC */ + { + unsigned char leap_yr; + struct rtc_time rtc_tm; + + if (!suser()) + return -EACCES; + + if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, + sizeof(struct rtc_time))) + return -EFAULT; + + leap_yr = ((!(rtc_tm.tm_year % 4) && (rtc_tm.tm_year % 100)) || !(rtc_tm.tm_year % 400)); + + if ((rtc_tm.tm_mon > 12) || (rtc_tm.tm_mday == 0)) + return -EINVAL; + + if (rtc_tm.tm_mday > (days_in_mo[rtc_tm.tm_mon] + ((rtc_tm.tm_mon == 2) && leap_yr))) + return -EINVAL; + + if ((rtc_tm.tm_hour >= 24) || (rtc_tm.tm_min >= 60) || (rtc_tm.tm_sec >= 60)) + return -EINVAL; + + save_flags(flags); + cli(); + rtc->ctrl = RTC_WRITE; + + rtc->bcd_sec = BIN2BCD(rtc_tm.tm_sec); + rtc->bcd_min = BIN2BCD(rtc_tm.tm_min); + rtc->bcd_hr = BIN2BCD(rtc_tm.tm_hour); + rtc->bcd_dom = BIN2BCD(rtc_tm.tm_mday); + rtc->bcd_mth = BIN2BCD(rtc_tm.tm_mon + 1); + rtc->bcd_year = BIN2BCD(rtc_tm.tm_year%100); + if (rtc_tm.tm_wday >= 0) + rtc->bcd_dow = BIN2BCD(rtc_tm.tm_wday+1); + + rtc->ctrl = 0; + restore_flags(flags); + return 0; + } + default: + return -EINVAL; + } +} + +/* + * We enforce only one user at a time here with the open/close. + * Also clear the previous interrupt data on an open, and clean + * up things on a close. + */ + +static int rtc_open(struct inode *inode, struct file *file) +{ + if(rtc_status) + return -EBUSY; + + rtc_status = 1; + return 0; +} + +static int rtc_release(struct inode *inode, struct file *file) +{ + rtc_status = 0; + return 0; +} + +/* + * The various file operations we support. + */ + +static struct file_operations rtc_fops = { + NULL, + NULL, + NULL, /* No write */ + NULL, /* No readdir */ + NULL, + rtc_ioctl, + NULL, /* No mmap */ + rtc_open, + rtc_release +}; + +static struct miscdevice rtc_dev= +{ + RTC_MINOR, + "rtc", + &rtc_fops +}; + +__initfunc(int rtc_MK48T08_init(void)) +{ + if (!MACH_IS_MVME16x) + return -ENODEV; + + printk(KERN_INFO "MK48T08 Real Time Clock Driver v%s\n", RTC_VERSION); + misc_register(&rtc_dev); + return 0; +} + diff -u --recursive --new-file v2.1.105/linux/arch/sparc/kernel/sys_sparc.c linux/arch/sparc/kernel/sys_sparc.c --- v2.1.105/linux/arch/sparc/kernel/sys_sparc.c Thu Apr 23 20:21:30 1998 +++ linux/arch/sparc/kernel/sys_sparc.c Sat Jun 13 11:36:52 1998 @@ -334,15 +334,23 @@ asmlinkage int sys_getdomainname(char *name, int len) { - int nlen = strlen(system_utsname.domainname); + int nlen; + int err = -EFAULT; + + down(&uts_sem); + + nlen = strlen(system_utsname.domainname); if (nlen < len) len = nlen; if(len > __NEW_UTS_LEN) - return -EFAULT; + goto done if(copy_to_user(name, system_utsname.domainname, len)) - return -EFAULT; - return 0; + goto done; + err=0; +done: + up(&uts_sem); + return err; } diff -u --recursive --new-file v2.1.105/linux/drivers/block/amiflop.c linux/drivers/block/amiflop.c --- v2.1.105/linux/drivers/block/amiflop.c Thu Mar 26 15:57:02 1998 +++ linux/drivers/block/amiflop.c Mon Jun 8 11:03:49 1998 @@ -68,11 +68,11 @@ #include #include #include +#include +#include #include #include -#include -#include #include #include #include diff -u --recursive --new-file v2.1.105/linux/drivers/block/floppy.c linux/drivers/block/floppy.c --- v2.1.105/linux/drivers/block/floppy.c Fri May 8 23:14:47 1998 +++ linux/drivers/block/floppy.c Tue Jun 9 01:21:49 1998 @@ -3,6 +3,7 @@ * * Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 1993, 1994 Alain Knaff + * Copyright (C) 1998 Alan Cox */ /* * 02.12.91 - Changed to static variables to indicate need for reset @@ -95,7 +96,11 @@ * 1995/10/18 -- Ralf Baechle -- Portability cleanup; move machine dependent * features to asm/floppy.h. */ - + +/* + * 1998/06/07 -- Alan Cox -- Merged the 2.0.34 fixes for resource allocation + * failures. + */ #define FLOPPY_SANITY_CHECK #undef FLOPPY_SILENT_DCL_CLEAR @@ -114,9 +119,11 @@ * motor of these drives causes system hangs on some PCI computers. drive * 0 is the low bit (0x1), and drive 7 is the high bit (0x80). Bits are on if * a drive is allowed. */ + static int FLOPPY_IRQ=6; static int FLOPPY_DMA=2; static int allowed_drive_mask = 0x33; +static int irqdma_allocated = 0; #include @@ -759,6 +766,11 @@ UDRS->select_date = jiffies; } } + /* + * We should propogate failures to grab the resources back + * nicely from here. Actually we ought to rewrite the fd + * driver some day too. + */ if (newdor & FLOPPY_MOTOR_MASK) floppy_grab_irq_and_dma(); if (olddor & FLOPPY_MOTOR_MASK) @@ -818,10 +830,11 @@ unsigned long flags; if (!usage_count){ - printk("trying to lock fdc while usage count=0\n"); + printk(KERN_ERR "Trying to lock fdc while usage count=0\n"); return -1; } - floppy_grab_irq_and_dma(); + if(floppy_grab_irq_and_dma()==-1) + return -EBUSY; INT_OFF; while (fdc_busy && NO_SIGNAL) interruptible_sleep_on(&fdc_wait); @@ -4208,7 +4221,12 @@ for (fdc = 0; fdc < N_FDC; fdc++) if (FDCS->address != -1) fd_outb(FDCS->dor, FD_DOR); + /* + * The driver will try and free resources and relies on us + * to know if they were allocated or not. + */ fdc = 0; + irqdma_allocated = 1; return 0; } @@ -4230,10 +4248,13 @@ return; } INT_ON; - fd_disable_dma(); - fd_free_dma(); - fd_free_irq(); - + if(irqdma_allocated) + { + fd_disable_dma(); + fd_free_dma(); + fd_free_irq(); + irqdma_allocated=0; + } set_dor(0, ~0, 8); #if N_FDC > 1 set_dor(1, ~8, 0); @@ -4384,10 +4405,12 @@ int dummy; if(have_no_fdc) return; - floppy_grab_irq_and_dma(); - lock_fdc(MAXTIMEOUT,0); - dummy=fd_eject(0); - process_fd_request(); - floppy_release_irq_and_dma(); + if(floppy_grab_irq_and_dma()==0) + { + lock_fdc(MAXTIMEOUT,0); + dummy=fd_eject(0); + process_fd_request(); + floppy_release_irq_and_dma(); + } } #endif diff -u --recursive --new-file v2.1.105/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c --- v2.1.105/linux/drivers/block/ll_rw_blk.c Fri May 8 23:14:47 1998 +++ linux/drivers/block/ll_rw_blk.c Sat Jun 13 12:59:16 1998 @@ -463,6 +463,7 @@ case IDE4_MAJOR: case IDE5_MAJOR: case ACSI_MAJOR: + case MFM_ACORN_MAJOR: /* * The scsi disk and cdrom drivers completely remove the request * from the queue when they start processing an entry. For this @@ -816,6 +817,9 @@ #endif #ifdef CONFIG_BLK_DEV_XD xd_init(); +#endif +#ifdef CONFIG_BLK_DEV_MFM + mfm_init(); #endif #ifdef CONFIG_PARIDE { extern void paride_init(void); paride_init(); }; diff -u --recursive --new-file v2.1.105/linux/drivers/block/paride/Config.in linux/drivers/block/paride/Config.in --- v2.1.105/linux/drivers/block/paride/Config.in Wed May 20 19:10:38 1998 +++ linux/drivers/block/paride/Config.in Sat Jun 13 12:08:19 1998 @@ -6,12 +6,14 @@ dep_tristate ' Parallel port ATAPI CD-ROMs' CONFIG_PARIDE_PCD $CONFIG_PARIDE dep_tristate ' Parallel port ATAPI disks' CONFIG_PARIDE_PF $CONFIG_PARIDE dep_tristate ' Parallel port ATAPI tapes' CONFIG_PARIDE_PT $CONFIG_PARIDE +dep_tristate ' Parallel port generic ATAPI devices' CONFIG_PARIDE_PG $CONFIG_PARIDE comment 'Parallel IDE protocol modules' dep_tristate ' ATEN EH-100 protocol' CONFIG_PARIDE_ATEN $CONFIG_PARIDE dep_tristate ' MicroSolutions backpack protocol' CONFIG_PARIDE_BPCK $CONFIG_PARIDE dep_tristate ' DataStor Commuter protocol' CONFIG_PARIDE_COMM $CONFIG_PARIDE dep_tristate ' DataStor EP-2000 protocol' CONFIG_PARIDE_DSTR $CONFIG_PARIDE dep_tristate ' FIT TD-2000 protocol' CONFIG_PARIDE_FIT2 $CONFIG_PARIDE +dep_tristate ' FIT TD-3000 protocol' CONFIG_PARIDE_FIT3 $CONFIG_PARIDE dep_tristate ' Shuttle EPAT/EPEZ protocol' CONFIG_PARIDE_EPAT $CONFIG_PARIDE dep_tristate ' Shuttle EPIA protocol' CONFIG_PARIDE_EPIA $CONFIG_PARIDE dep_tristate ' FreeCom power protocol' CONFIG_PARIDE_FRPW $CONFIG_PARIDE diff -u --recursive --new-file v2.1.105/linux/drivers/block/paride/Makefile linux/drivers/block/paride/Makefile --- v2.1.105/linux/drivers/block/paride/Makefile Wed May 20 19:10:38 1998 +++ linux/drivers/block/paride/Makefile Sat Jun 13 12:08:19 1998 @@ -58,6 +58,14 @@ endif endif +ifeq ($(CONFIG_PARIDE_PG),y) + LX_OBJS += pg.o +else + ifeq ($(CONFIG_PARIDE_PG),m) + MX_OBJS += pg.o + endif +endif + ifeq ($(CONFIG_PARIDE_ATEN),y) LX_OBJS += aten.o else @@ -119,6 +127,14 @@ else ifeq ($(CONFIG_PARIDE_FIT2),m) MX_OBJS += fit2.o + endif +endif + +ifeq ($(CONFIG_PARIDE_FIT3),y) + LX_OBJS += fit3.o +else + ifeq ($(CONFIG_PARIDE_FIT3),m) + MX_OBJS += fit3.o endif endif diff -u --recursive --new-file v2.1.105/linux/drivers/block/paride/fit3.c linux/drivers/block/paride/fit3.c --- v2.1.105/linux/drivers/block/paride/fit3.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/block/paride/fit3.c Sat Jun 13 12:08:19 1998 @@ -0,0 +1,221 @@ +/* + fit3.c (c) 1998 Grant R. Guenther + Under the terms of the GNU public license. + + fit3.c is a low-level protocol driver for newer models + of the Fidelity International Technology parallel port adapter. + This adapter is used in their TransDisk 3000 portable + hard-drives, as well as CD-ROM, PD-CD and other devices. + + The TD-2000 and certain older devices use a different protocol. + Try the fit2 protocol module with them. + + NB: The FIT adapters do not appear to support the control + registers. So, we map ALT_STATUS to STATUS and NO-OP writes + to the device control register - this means that IDE reset + will not work on these devices. + +*/ + +#define FIT3_VERSION "1.0" + +#include +#include +#include +#include +#include + +#include "paride.h" + +#define j44(a,b) (((a>>3)&0x0f)|((b<<1)&0xf0)) + +#define w7(byte) {out_p(7,byte);} +#define r7() (in_p(7) & 0xff) + +/* cont = 0 - access the IDE register file + cont = 1 - access the IDE command set + +*/ + +static void fit3_write_regr( PIA *pi, int cont, int regr, int val) + +{ if (cont == 1) return; + + switch (pi->mode) { + + case 0: + case 1: w2(0xc); w0(regr); w2(0x8); w2(0xc); + w0(val); w2(0xd); + w0(0); w2(0xc); + break; + + case 2: w2(0xc); w0(regr); w2(0x8); w2(0xc); + w4(val); w4(0); + w2(0xc); + break; + + } +} + +static int fit3_read_regr( PIA *pi, int cont, int regr ) + +{ int a, b; + + if (cont) { + if (regr != 6) return 0xff; + regr = 7; + } + + switch (pi->mode) { + + case 0: w2(0xc); w0(regr + 0x10); w2(0x8); w2(0xc); + w2(0xd); a = r1(); + w2(0xf); b = r1(); + w2(0xc); + return j44(a,b); + + case 1: w2(0xc); w0(regr + 0x90); w2(0x8); w2(0xc); + w2(0xec); w2(0xee); w2(0xef); a = r0(); + w2(0xc); + return a; + + case 2: w2(0xc); w0(regr + 0x90); w2(0x8); w2(0xc); + w2(0xec); + a = r4(); b = r4(); + w2(0xc); + return a; + + } + return -1; + +} + +static void fit3_read_block( PIA *pi, char * buf, int count ) + +{ int k, a, b, c, d; + + switch (pi->mode) { + + case 0: w2(0xc); w0(0x10); w2(0x8); w2(0xc); + for (k=0;kmode) { + + case 0: + case 1: w2(0xc); w0(0); w2(0x8); w2(0xc); + for (k=0;ksaved_r0 = r0(); + pi->saved_r2 = r2(); + w2(0xc); w0(0); w2(0xa); + if (pi->mode == 2) { + w2(0xc); w0(0x9); w2(0x8); w2(0xc); + } +} + +static void fit3_disconnect ( PIA *pi ) + +{ w2(0xc); w0(0xa); w2(0x8); w2(0xc); + w0(pi->saved_r0); + w2(pi->saved_r2); +} + +static void fit3_log_adapter( PIA *pi, char * scratch, int verbose ) + +{ char *mode_string[3] = {"4-bit","8-bit","EPP"}; + + printk("%s: fit3 %s, FIT 3000 adapter at 0x%x, " + "mode %d (%s), delay %d\n", + pi->device,FIT3_VERSION,pi->port, + pi->mode,mode_string[pi->mode],pi->delay); + +} + +static void fit3_init_proto(PIA *pi) + +{ MOD_INC_USE_COUNT; +} + +static void fit3_release_proto(PIA *pi) + +{ MOD_DEC_USE_COUNT; +} + +struct pi_protocol fit3 = {"fit3",0,3,2,1,1, + fit3_write_regr, + fit3_read_regr, + fit3_write_block, + fit3_read_block, + fit3_connect, + fit3_disconnect, + 0, + 0, + 0, + fit3_log_adapter, + fit3_init_proto, + fit3_release_proto + }; + + +#ifdef MODULE + +int init_module(void) + +{ return pi_register( &fit3 ) - 1; +} + +void cleanup_module(void) + +{ pi_unregister( &fit3 ); +} + +#endif + +/* end of fit3.c */ diff -u --recursive --new-file v2.1.105/linux/drivers/block/paride/mkd linux/drivers/block/paride/mkd --- v2.1.105/linux/drivers/block/paride/mkd Wed May 20 19:10:38 1998 +++ linux/drivers/block/paride/mkd Sat Jun 13 12:08:19 1998 @@ -2,6 +2,9 @@ # # mkd -- a script to create the device special files for the PARIDE subsystem # +# block devices: pd (45), pcd (46), pf (47) +# character devices: pt (96), pg (97) +# function mkdev { mknod $1 $2 $3 $4 ; chmod 0660 $1 ; chown root:disk $1 } @@ -21,5 +24,7 @@ for u in 0 1 2 3 ; do mkdev pf$u b 47 $u ; done for u in 0 1 2 3 ; do mkdev pt$u c 96 $u ; done for u in 0 1 2 3 ; do mkdev npt$u c 96 $[ $u + 128 ] ; done +for u in 0 1 2 3 ; do mkdev pg$u c 97 $u ; done # # end of mkd + diff -u --recursive --new-file v2.1.105/linux/drivers/block/paride/paride.c linux/drivers/block/paride/paride.c --- v2.1.105/linux/drivers/block/paride/paride.c Wed May 20 19:10:38 1998 +++ linux/drivers/block/paride/paride.c Sat Jun 13 12:08:19 1998 @@ -454,6 +454,11 @@ pi_register(&fit2); }; #endif +#ifdef CONFIG_PARIDE_FIT3 + { extern struct pi_protocol fit3; + pi_register(&fit3); + }; +#endif #ifdef CONFIG_PARIDE_KBIC { extern struct pi_protocol k951; extern struct pi_protocol k971; diff -u --recursive --new-file v2.1.105/linux/drivers/block/paride/paride.h linux/drivers/block/paride/paride.h --- v2.1.105/linux/drivers/block/paride/paride.h Wed May 20 19:10:38 1998 +++ linux/drivers/block/paride/paride.h Sat Jun 13 12:08:19 1998 @@ -23,6 +23,7 @@ #define PI_PCD 1 /* ATAPI CDrom */ #define PI_PF 2 /* ATAPI disk */ #define PI_PT 3 /* ATAPI tape */ +#define PI_PG 4 /* ATAPI generic */ /* The paride module contains no state, instead the drivers allocate a pi_adapter data structure and pass it to paride in every operation. diff -u --recursive --new-file v2.1.105/linux/drivers/block/paride/pg.c linux/drivers/block/paride/pg.c --- v2.1.105/linux/drivers/block/paride/pg.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/block/paride/pg.c Sat Jun 13 12:08:19 1998 @@ -0,0 +1,691 @@ +/* + pg.c (c) 1998 Grant R. Guenther + Under the terms of the GNU public license. + + The pg driver provides a simple character device interface for + sending ATAPI commands to a device. With the exception of the + ATAPI reset operation, all operations are performed by a pair + of read and write operations to the appropriate /dev/pgN device. + A write operation delivers a command and any outbound data in + a single buffer. Normally, the write will succeed unless the + device is offline or malfunctioning, or there is already another + command pending. If the write succeeds, it should be followed + immediately by a read operation, to obtain any returned data and + status information. A read will fail if there is no operation + in progress. + + As a special case, the device can be reset with a write operation, + and in this case, no following read is expected, or permitted. + + There are no ioctl() operations. Any single operation + may transfer at most PG_MAX_DATA bytes. Note that the driver must + copy the data through an internal buffer. In keeping with all + current ATAPI devices, command packets are assumed to be exactly + 12 bytes in length. + + To permit future changes to this interface, the headers in the + read and write buffers contain a single character "magic" flag. + Currently this flag must be the character "P". + + By default, the driver will autoprobe for a single parallel + port ATAPI device, but if their individual parameters are + specified, the driver can handle up to 4 devices. + + To use this device, you must have the following device + special files defined: + + /dev/pg0 b 97 0 + /dev/pg1 b 97 1 + /dev/pg2 b 97 2 + /dev/pg3 b 97 3 + + (You'll need to change the 97 to something else if you use + the 'major' parameter to install the driver on a different + major number.) + + The behaviour of the pg driver can be altered by setting + some parameters from the insmod command line. The following + parameters are adjustable: + + drive0 These four arguments can be arrays of + drive1 1-6 integers as follows: + drive2 + drive3 ,,,,, + + Where, + + is the base of the parallel port address for + the corresponding drive. (required) + + is the protocol number for the adapter that + supports this drive. These numbers are + logged by 'paride' when the protocol modules + are initialised. (0 if not given) + + for those adapters that support chained + devices, this is the unit selector for the + chain of devices on the given port. It should + be zero for devices that don't support chaining. + (0 if not given) + + this can be -1 to choose the best mode, or one + of the mode numbers supported by the adapter. + (-1 if not given) + + ATAPI devices can be jumpered to master or slave. + Set this to 0 to choose the master drive, 1 to + choose the slave, -1 (the default) to choose the + first drive found. + + some parallel ports require the driver to + go more slowly. -1 sets a default value that + should work with the chosen protocol. Otherwise, + set this to a small integer, the larger it is + the slower the port i/o. In some cases, setting + this to zero will speed up the device. (default -1) + + major You may use this parameter to overide the + default major number (97) that this driver + will use. Be sure to change the device + name as well. + + name This parameter is a character string that + contains the name the kernel will use for this + device (in /proc output, for instance). + (default "pg"). + + verbose This parameter controls the amount of logging + that is done by the driver. Set it to 0 for + quiet operation, to 1 to enable progress + messages while the driver probes for devices, + or to 2 for full debug logging. (default 0) + + If this driver is built into the kernel, you can use + the following command line parameters, with the same values + as the corresponding module parameters listed above: + + pg.drive0 + pg.drive1 + pg.drive2 + pg.drive3 + + In addition, you can use the parameter pg.disable to disable + the driver entirely. + +*/ + +#define PG_VERSION "1.0" +#define PG_MAJOR 97 +#define PG_NAME "pg" +#define PG_UNITS 4 + +/* Here are things one can override from the insmod command. + Most are autoprobed by paride unless set here. Verbose is 0 + by default. + +*/ + +static int verbose = 0; +static int major = PG_MAJOR; +static char *name = PG_NAME; +static int disable = 0; + +static int drive0[6] = {0,0,0,-1,-1,-1}; +static int drive1[6] = {0,0,0,-1,-1,-1}; +static int drive2[6] = {0,0,0,-1,-1,-1}; +static int drive3[6] = {0,0,0,-1,-1,-1}; + +static int (*drives[4])[6] = {&drive0,&drive1,&drive2,&drive3}; +static int pg_drive_count; + +#define D_PRT 0 +#define D_PRO 1 +#define D_UNI 2 +#define D_MOD 3 +#define D_SLV 4 +#define D_DLY 5 + +#define DU (*drives[unit]) + +/* end of parameters */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifndef MODULE + +#include "setup.h" + +static STT pg_stt[5] = {{"drive0",6,drive0}, + {"drive1",6,drive1}, + {"drive2",6,drive2}, + {"drive3",6,drive3}, + {"disable",1,&disable}}; + +void pg_setup( char *str, int *ints) + +{ generic_setup(pg_stt,5,str); +} + +#endif + +MODULE_PARM(verbose,"i"); +MODULE_PARM(major,"i"); +MODULE_PARM(name,"s"); +MODULE_PARM(drive0,"1-6i"); +MODULE_PARM(drive1,"1-6i"); +MODULE_PARM(drive2,"1-6i"); +MODULE_PARM(drive3,"1-6i"); + +#include "paride.h" + +#define PG_SPIN_DEL 50 /* spin delay in micro-seconds */ +#define PG_SPIN 200 +#define PG_TMO HZ + +#define STAT_ERR 0x01 +#define STAT_INDEX 0x02 +#define STAT_ECC 0x04 +#define STAT_DRQ 0x08 +#define STAT_SEEK 0x10 +#define STAT_WRERR 0x20 +#define STAT_READY 0x40 +#define STAT_BUSY 0x80 + +#define ATAPI_IDENTIFY 0x12 + +int pg_init(void); +#ifdef MODULE +void cleanup_module( void ); +#endif + +static int pg_open(struct inode *inode, struct file *file); +static int pg_release (struct inode *inode, struct file *file); +static ssize_t pg_read(struct file * filp, char * buf, + size_t count, loff_t *ppos); +static ssize_t pg_write(struct file * filp, const char * buf, + size_t count, loff_t *ppos); +static int pg_detect(void); + +static int pg_identify (int unit, int log); + +#define PG_NAMELEN 8 + +struct pg_unit { + struct pi_adapter pia; /* interface to paride layer */ + struct pi_adapter *pi; + int busy; /* write done, read expected */ + int start; /* jiffies at command start */ + int dlen; /* transfer size requested */ + int timeout; /* timeout requested */ + int status; /* last sense key */ + int drive; /* drive */ + int access; /* count of active opens ... */ + int present; /* device present ? */ + char *bufptr; + char name[PG_NAMELEN]; /* pg0, pg1, ... */ + }; + +struct pg_unit pg[PG_UNITS]; + +/* 'unit' must be defined in all functions - either as a local or a param */ + +#define PG pg[unit] +#define PI PG.pi + +static char pg_scratch[512]; /* scratch block buffer */ + +/* kernel glue structures */ + +static struct file_operations pg_fops = { + NULL, /* lseek - default */ + pg_read, /* read */ + pg_write, /* write */ + NULL, /* readdir - bad */ + NULL, /* select */ + NULL, /* ioctl */ + NULL, /* mmap */ + pg_open, /* open */ + pg_release, /* release */ + NULL, /* fsync */ + NULL, /* fasync */ + NULL, /* media change ? */ + NULL /* revalidate new media */ +}; + +void pg_init_units( void ) + +{ int unit, j; + + pg_drive_count = 0; + for (unit=0;unitstate = TASK_INTERRUPTIBLE; + current->timeout = jiffies + cs; + schedule(); +} + +static int pg_wait( int unit, int go, int stop, int tmo, char * msg ) + +{ int j, r, e, s, p; + + PG.status = 0; + + j = 0; + while ((((r=RR(1,6))&go)||(stop&&(!(r&stop))))&&(jiffies=tmo)) { + s = RR(0,7); + e = RR(0,1); + p = RR(0,2); + if (verbose > 1) + printk("%s: %s: stat=0x%x err=0x%x phase=%d%s\n", + PG.name,msg,s,e,p,(jiffies>=tmo)?" timeout":""); + + + if (jiffies>=tmo) e |= 0x100; + PG.status = (e >> 4) & 0xff; + return -1; + } + return 0; +} + +static int pg_command( int unit, char * cmd, int dlen, int tmo ) + +{ int k; + + pi_connect(PI); + + WR(0,6,DRIVE); + + if (pg_wait(unit,STAT_BUSY|STAT_DRQ,0,tmo,"before command")) { + pi_disconnect(PI); + return -1; + } + + WR(0,4,dlen % 256); + WR(0,5,dlen / 256); + WR(0,7,0xa0); /* ATAPI packet command */ + + if (pg_wait(unit,STAT_BUSY,STAT_DRQ,tmo,"command DRQ")) { + pi_disconnect(PI); + return -1; + } + + if (RR(0,2) != 1) { + printk("%s: command phase error\n",PG.name); + pi_disconnect(PI); + return -1; + } + + pi_write_block(PI,cmd,12); + + if (verbose > 1) { + printk("%s: Command sent, dlen=%d packet= ", PG.name,dlen); + for (k=0;k<12;k++) printk("%02x ",cmd[k]&0xff); + printk("\n"); + } + return 0; +} + +static int pg_completion( int unit, char * buf, int tmo) + +{ int r, s, d, n, p; + + r = pg_wait(unit,STAT_BUSY,STAT_DRQ|STAT_READY|STAT_ERR, + tmo,"completion"); + + PG.dlen = 0; + + if (RR(0,7)&STAT_DRQ) { + d = (RR(0,4)+256*RR(0,5)); + n = ((d+3)&0xfffc); + p = RR(0,2)&3; + if (p == 0) pi_write_block(PI,buf,n); + if (p == 2) pi_read_block(PI,buf,n); + if (verbose > 1) printk("%s: %s %d bytes\n",PG.name, + p?"Read":"Write",n); + PG.dlen = (1-p)*d; + } + + s = pg_wait(unit,STAT_BUSY,STAT_READY|STAT_ERR,tmo,"data done"); + + pi_disconnect(PI); + + return (r?r:s); +} + +static int pg_reset( int unit ) + +{ int i, k, flg; + int expect[5] = {1,1,1,0x14,0xeb}; + + pi_connect(PI); + WR(0,6,DRIVE); + WR(0,7,8); + + pg_sleep(2); + + k = 0; + while ((k++ < PG_TMO) && (RR(1,6)&STAT_BUSY)) + pg_sleep(1); + + flg = 1; + for(i=0;i<5;i++) flg &= (RR(0,i+1) == expect[i]); + + if (verbose) { + printk("%s: Reset (%d) signature = ",PG.name,k); + for (i=0;i<5;i++) printk("%3x",RR(0,i+1)); + if (!flg) printk(" (incorrect)"); + printk("\n"); + } + + pi_disconnect(PI); + return flg-1; +} + +static void xs( char *buf, char *targ, int offs, int len ) + +{ int j,k,l; + + j=0; l=0; + for (k=0;ki_rdev); + + if ((unit >= PG_UNITS) || (!PG.present)) return -ENODEV; + + PG.access++; + + if (PG.access > 1) { + PG.access--; + return -EBUSY; + } + + MOD_INC_USE_COUNT; + + if (PG.busy) { + pg_reset(unit); + PG.busy = 0; + } + + pg_identify(unit,(verbose>1)); + + + PG.bufptr = kmalloc(PG_MAX_DATA,GFP_KERNEL); + if (PG.bufptr == NULL) { + PG.access--; + MOD_DEC_USE_COUNT; + printk("%s: buffer allocation failed\n",PG.name); + return -ENOMEM; + } + + return 0; +} + +static int pg_release (struct inode *inode, struct file *file) +{ + int unit = DEVICE_NR(inode->i_rdev); + + if ((unit >= PG_UNITS) || (PG.access <= 0)) + return -EINVAL; + + PG.access--; + + kfree(PG.bufptr); + PG.bufptr = NULL; + + MOD_DEC_USE_COUNT; + + return 0; + +} + +static ssize_t pg_write(struct file * filp, const char * buf, + size_t count, loff_t *ppos) + +{ struct inode *ino = filp->f_dentry->d_inode; + int unit = DEVICE_NR(ino->i_rdev); + struct pg_write_hdr hdr; + int hs = sizeof(hdr); + + if (PG.busy) return -EBUSY; + if (count < hs) return -EINVAL; + + copy_from_user((char *)&hdr,buf,hs); + + if (hdr.magic != PG_MAGIC) return -EINVAL; + if (hdr.dlen > PG_MAX_DATA) return -EINVAL; + if ((count - hs) > PG_MAX_DATA) return -EINVAL; + + if (hdr.func == PG_RESET) { + if (count != hs) return -EINVAL; + if (pg_reset(unit)) return -EIO; + return count; + } + + if (hdr.func != PG_COMMAND) return -EINVAL; + + PG.start = jiffies; + PG.timeout = hdr.timeout*HZ + HZ/2 + jiffies; + + if (pg_command(unit,hdr.packet,hdr.dlen,jiffies+PG_TMO)) { + if (PG.status & 0x10) return -ETIME; + return -EIO; + } + + PG.busy = 1; + + copy_from_user(PG.bufptr,buf+hs,count-hs); + + return count; +} + +static ssize_t pg_read(struct file * filp, char * buf, + size_t count, loff_t *ppos) + +{ struct inode *ino = filp->f_dentry->d_inode; + int unit = DEVICE_NR(ino->i_rdev); + struct pg_read_hdr hdr; + int hs = sizeof(hdr); + int copy; + + if (!PG.busy) return -EINVAL; + if (count < hs) return -EINVAL; + + PG.busy = 0; + + if (pg_completion(unit,PG.bufptr,PG.timeout)) + if (PG.status & 0x10) return -ETIME; + + hdr.magic = PG_MAGIC; + hdr.dlen = PG.dlen; + copy = 0; + + if (hdr.dlen < 0) { + hdr.dlen = -1 * hdr.dlen; + copy = hdr.dlen; + if (copy > (count - hs)) copy = count - hs; + } + + hdr.duration = (jiffies - PG.start + HZ/2) / HZ; + hdr.scsi = PG.status & 0x0f; + + copy_to_user(buf,(char *)&hdr,hs); + if (copy > 0) copy_to_user(buf+hs,PG.bufptr,copy); + + return copy+hs; +} + +/* end of pg.c */ + diff -u --recursive --new-file v2.1.105/linux/drivers/block/paride/pseudo.h linux/drivers/block/paride/pseudo.h --- v2.1.105/linux/drivers/block/paride/pseudo.h Wed May 20 19:10:38 1998 +++ linux/drivers/block/paride/pseudo.h Sat Jun 13 12:08:20 1998 @@ -45,7 +45,7 @@ static int ps_timer_active = 0; static int ps_tq_active = 0; -spinlock_t ps_spinlock = SPIN_LOCK_UNLOCKED; +static spinlock_t ps_spinlock = SPIN_LOCK_UNLOCKED; static struct timer_list ps_timer = {0,0,0,0,ps_timer_int}; static struct tq_struct ps_tq = {0,0,ps_tq_int,NULL}; diff -u --recursive --new-file v2.1.105/linux/drivers/cdrom/mcd.c linux/drivers/cdrom/mcd.c --- v2.1.105/linux/drivers/cdrom/mcd.c Thu Feb 12 20:56:05 1998 +++ linux/drivers/cdrom/mcd.c Sat Jun 13 13:05:22 1998 @@ -157,6 +157,7 @@ static short mcd_port = MCD_BASE_ADDR; /* used as "mcd" by "insmod" */ static int mcd_irq = MCD_INTR_NR; /* must directly follow mcd_port */ +MODULE_PARM(mcd, "1-2i"); static int McdTimeout, McdTries; static struct wait_queue *mcd_waitq = NULL; diff -u --recursive --new-file v2.1.105/linux/drivers/char/adbmouse.c linux/drivers/char/adbmouse.c --- v2.1.105/linux/drivers/char/adbmouse.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/adbmouse.c Sat Jun 13 13:44:30 1998 @@ -0,0 +1,304 @@ +/* + * Macintosh ADB Mouse driver for Linux + * + * 27 Oct 1997 Michael Schmitz + * logitech fixes by anthony tong + * + * Apple mouse protocol according to: + * + * Device code shamelessly stolen from: + */ +/* + * Atari Mouse Driver for Linux + * by Robert de Vries (robert@and.nl) 19Jul93 + * + * 16 Nov 1994 Andreas Schwab + * Compatibility with busmouse + * Support for three button mouse (shamelessly stolen from MiNT) + * third button wired to one of the joystick directions on joystick 1 + * + * 1996/02/11 Andreas Schwab + * Module support + * Allow multiple open's + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static struct mouse_status mouse; +static int adb_mouse_x_threshold = 2, adb_mouse_y_threshold = 2; +static int adb_mouse_buttons = 0; + +extern void (*adb_mouse_interrupt_hook) (char *, int); + +extern int console_loglevel; + +/* + * XXX: need to figure out what ADB mouse packets mean ... + * This is the stuff stolen from the Atari driver ... + */ +static void adb_mouse_interrupt(char *buf, int nb) +{ + static int buttons = 7; + + /* + Handler 1 -- 100cpi original Apple mouse protocol. + Handler 2 -- 200cpi original Apple mouse protocol. + + For Apple's standard one-button mouse protocol the data array will + contain the following values: + + BITS COMMENTS + data[0] = 0000 0000 ADB packet identifer. + data[1] = ???? ???? (?) + data[2] = ???? ??00 Bits 0-1 should be zero for a mouse device. + data[3] = bxxx xxxx First button and x-axis motion. + data[4] = byyy yyyy Second button and y-axis motion. + + NOTE: data[0] is confirmed by the parent function and need not be + checked here. + */ + + /* + Handler 4 -- Apple Extended mouse protocol. + + For Apple's 3-button mouse protocol the data array will contain the + following values: + + BITS COMMENTS + data[0] = 0000 0000 ADB packet identifer. + data[1] = 0100 0000 Extended protocol register. + Bits 6-7 are the device id, which should be 1. + Bits 4-5 are resolution which is in "units/inch". + The Logitech MouseMan returns these bits clear but it has + 200/300cpi resolution. + Bits 0-3 are unique vendor id. + data[2] = 0011 1100 Bits 0-1 should be zero for a mouse device. + Bits 2-3 should be 8 + 4. + Bits 4-7 should be 3 for a mouse device. + data[3] = bxxx xxxx Left button and x-axis motion. + data[4] = byyy yyyy Second button and y-axis motion. + data[5] = byyy bxxx Third button and fourth button. + Y is additiona. high bits of y-axis motion. + X is additional high bits of x-axis motion. + + NOTE: data[0] and data[2] are confirmed by the parent function and + need not be checked here. + */ + + /* + * 'buttons' here means 'button down' states! + * Button 1 (left) : bit 2, busmouse button 3 + * Button 2 (right) : bit 0, busmouse button 1 + * Button 3 (middle): bit 1, busmouse button 2 + */ + + /* x/y and buttons swapped */ + + if (nb > 0) { /* real packet : use buttons? */ + if (console_loglevel >= 8) + printk("adb_mouse: real data; "); + /* button 1 (left, bit 2) : always significant ! */ + buttons = (buttons&3) | (buf[1] & 0x80 ? 4 : 0); /* 1+2 unchanged */ + /* button 2 (middle) */ + buttons = (buttons&5) | (buf[2] & 0x80 ? 2 : 0); /* 2+3 unchanged */ + /* button 3 (right) present? + * on a logitech mouseman, the right and mid buttons sometimes behave + * strangely until they both have been pressed after booting. */ + /* data valid only if extended mouse format ! (buf[3] = 0 else) */ + if ( nb == 6 ) + buttons = (buttons&6) | (buf[3] & 0x80 ? 1 : 0); /* 1+3 unchanged */ + } else { /* fake packet : use 2+3 */ + if (console_loglevel >= 8) + printk("adb_mouse: fake data; "); + /* we only see state changes here, but the fake driver takes care + * to preserve state... button 1 state must stay unchanged! */ + buttons = (buttons&4) | ((buf[2] & 0x80 ? 1 : 0) | + (buf[3] & 0x80 ? 2 : 0)); + } + + add_mouse_randomness(((~buttons & 7) << 16) + ((buf[2]&0x7f) << 8) + (buf[1]&0x7f)); + mouse.buttons = buttons & 7; + mouse.dx += ((buf[2]&0x7f) < 64 ? (buf[2]&0x7f) : (buf[2]&0x7f)-128 ); + mouse.dy -= ((buf[1]&0x7f) < 64 ? (buf[1]&0x7f) : (buf[1]&0x7f)-128 ); + + if (console_loglevel >= 8) + printk(" %X %X %X buttons %x dx %d dy %d \n", + buf[1], buf[2], buf[3], mouse.buttons, mouse.dx, mouse.dy); + + mouse.ready = 1; + wake_up_interruptible(&mouse.wait); + if (mouse.fasyncptr) + kill_fasync(mouse.fasyncptr, SIGIO); + +} + +static int fasync_mouse(struct file *filp, int on) +{ + int retval; + + retval = fasync_helper(filp, on, &mouse.fasyncptr); + if (retval < 0) + return retval; + return 0; +} + +static int release_mouse(struct inode *inode, struct file *file) +{ + fasync_mouse(file, 0); + if (--mouse.active) + return 0; + + adb_mouse_interrupt_hook = NULL; + MOD_DEC_USE_COUNT; + return 0; +} + +static int open_mouse(struct inode *inode, struct file *file) +{ + if (mouse.active++) + return 0; + + mouse.ready = 0; + + mouse.dx = mouse.dy = 0; + adb_mouse_buttons = 0; + MOD_INC_USE_COUNT; + adb_mouse_interrupt_hook = adb_mouse_interrupt; + return 0; +} + +static ssize_t write_mouse(struct file *file, const char *buffer, + size_t count, loff_t *ppos) +{ + return -EINVAL; +} + +static ssize_t read_mouse(struct file *file, char *buffer, size_t count, + loff_t *ppos) +{ + int dx, dy, buttons; + + if (count < 3) + return -EINVAL; + if (!mouse.ready) + return -EAGAIN; + dx = mouse.dx; + dy = mouse.dy; + buttons = mouse.buttons; + if (dx > 127) + dx = 127; + else if (dx < -128) + dx = -128; + if (dy > 127) + dy = 127; + else if (dy < -128) + dy = -128; + mouse.dx -= dx; + mouse.dy -= dy; + if (mouse.dx == 0 && mouse.dy == 0) + mouse.ready = 0; + if (put_user(buttons | 0x80, buffer++) || + put_user((char) dx, buffer++) || + put_user((char) dy, buffer++)) + return -EFAULT; + if (count > 3) + if (clear_user(buffer, count - 3)) + return -EFAULT; + return count; +} + +static unsigned int mouse_poll(struct file *file, poll_table *wait) +{ + poll_wait(file, &mouse.wait, wait); + if (mouse.ready) + return POLLIN | POLLRDNORM; + return 0; +} + +struct file_operations adb_mouse_fops = { + NULL, /* mouse_seek */ + read_mouse, + write_mouse, + NULL, /* mouse_readdir */ + mouse_poll, + NULL, /* mouse_ioctl */ + NULL, /* mouse_mmap */ + open_mouse, + release_mouse, + NULL, + fasync_mouse, +}; + +#define ADB_MOUSE_MINOR 10 + +static struct miscdevice adb_mouse = { + ADB_MOUSE_MINOR, "adbmouse", &adb_mouse_fops +}; + +__initfunc(int adb_mouse_init(void)) +{ + mouse.active = 0; + mouse.ready = 0; + mouse.wait = NULL; + + if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) ) + return -ENODEV; + printk(KERN_INFO "Macintosh ADB mouse installed.\n"); + misc_register(&adb_mouse); + return 0; +} + + +#define MIN_THRESHOLD 1 +#define MAX_THRESHOLD 20 /* more seems not reasonable... */ + +__initfunc(void adb_mouse_setup(char *str, int *ints)) +{ + if (ints[0] < 1) { + printk( "adb_mouse_setup: no arguments!\n" ); + return; + } + else if (ints[0] > 2) { + printk( "adb_mouse_setup: too many arguments\n" ); + } + + if (ints[1] < MIN_THRESHOLD || ints[1] > MAX_THRESHOLD) + printk( "adb_mouse_setup: bad threshold value (ignored)\n" ); + else { + adb_mouse_x_threshold = ints[1]; + adb_mouse_y_threshold = ints[1]; + if (ints[0] > 1) { + if (ints[2] < MIN_THRESHOLD || ints[2] > MAX_THRESHOLD) + printk("adb_mouse_setup: bad threshold value (ignored)\n" ); + else + adb_mouse_y_threshold = ints[2]; + } + } + +} + +#ifdef MODULE +#include + +int init_module(void) +{ + return adb_mouse_init(); +} + +void cleanup_module(void) +{ + misc_deregister(&adb_mouse); +} +#endif diff -u --recursive --new-file v2.1.105/linux/drivers/char/bttv.c linux/drivers/char/bttv.c --- v2.1.105/linux/drivers/char/bttv.c Tue Jun 9 11:57:29 1998 +++ linux/drivers/char/bttv.c Sat Jun 13 11:38:49 1998 @@ -1922,7 +1922,7 @@ } btv->win.sheight=v.height; btv->win.swidth=v.width; -+ btv->win.bpp=((v.depth+1)&0x18)/8; + btv->win.bpp=((v.depth+1)&0x38)/8; btv->win.depth=v.depth; btv->win.bpl=v.bytesperline; @@ -2313,6 +2313,8 @@ "DEC DC21030", PCI_BASE_ADDRESS_0}, { PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL, "Matrox Millennium", PCI_BASE_ADDRESS_1}, + { PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL_2, + "Matrox Millennium II", PCI_BASE_ADDRESS_0}, { PCI_VENDOR_ID_MATROX, 0x051a, "Matrox Mystique", PCI_BASE_ADDRESS_1}, { PCI_VENDOR_ID_N9, PCI_DEVICE_ID_N9_I128, "Number Nine Imagine 128", PCI_BASE_ADDRESS_0}, diff -u --recursive --new-file v2.1.105/linux/drivers/char/console.c linux/drivers/char/console.c --- v2.1.105/linux/drivers/char/console.c Wed May 20 19:10:38 1998 +++ linux/drivers/char/console.c Fri Jun 12 10:43:31 1998 @@ -1254,18 +1254,15 @@ } } -static void insert_char(int currcons) +static void insert_char(int currcons, unsigned int nr) { - unsigned int i = x; - unsigned short tmp, old = video_erase_char; - unsigned short * p = (unsigned short *) pos; + unsigned short *p, *q = (unsigned short *) pos; - while (i++ < video_num_columns) { - tmp = scr_readw(p); - scr_writew(old, p); - old = tmp; - p++; - } + p = q + video_num_columns - nr - x; + while (--p >= q) + scr_writew(scr_readw(p), p + nr); + + memsetw(q, video_erase_char, nr*2); need_wrap = 0; } @@ -1275,16 +1272,16 @@ need_wrap = 0; } -static void delete_char(int currcons) +static void delete_char(int currcons, unsigned int nr) { unsigned int i = x; unsigned short * p = (unsigned short *) pos; - while (++i < video_num_columns) { - scr_writew(scr_readw(p+1), p); + while (++i <= video_num_columns - nr) { + scr_writew(scr_readw(p+nr), p); p++; } - scr_writew(video_erase_char, p); + memsetw(p, video_erase_char, nr*2); need_wrap = 0; } @@ -1300,8 +1297,7 @@ nr = video_num_columns; else if (!nr) nr = 1; - while (nr--) - insert_char(currcons); + insert_char(currcons, nr); } static void csi_L(int currcons, unsigned int nr) @@ -1319,8 +1315,7 @@ nr = video_num_columns; else if (!nr) nr = 1; - while (nr--) - delete_char(currcons); + delete_char(currcons, nr); } static void csi_M(int currcons, unsigned int nr) @@ -1583,7 +1578,7 @@ lf(currcons); } if (decim) - insert_char(currcons); + insert_char(currcons, 1); scr_writew( video_mode_512ch ? ((attr & 0xf7) << 8) + ((tc & 0x100) << 3) + (tc & 0x0ff) : (attr << 8) + tc, diff -u --recursive --new-file v2.1.105/linux/drivers/char/lp_intern.c linux/drivers/char/lp_intern.c --- v2.1.105/linux/drivers/char/lp_intern.c Tue May 13 22:41:07 1997 +++ linux/drivers/char/lp_intern.c Sat Jun 13 13:44:30 1998 @@ -35,6 +35,7 @@ #include static int minor = -1; +MODULE_PARM(minor,"i"); static void lp_int_out(int, int); static int lp_int_busy(int); diff -u --recursive --new-file v2.1.105/linux/drivers/char/mac_SCC.c linux/drivers/char/mac_SCC.c --- v2.1.105/linux/drivers/char/mac_SCC.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/mac_SCC.c Sat Jun 13 13:44:30 1998 @@ -0,0 +1,1543 @@ +/* + * mac_SCC.c: m68k version of + * + * macserial.c: Serial port driver for Power Macintoshes. + * Extended for the 68K mac by Alan Cox. + * Rewritten to m68k serial design by Michael Schmitz + * + * Derived from drivers/sbus/char/sunserial.c by Paul Mackerras. + * + * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au) + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +/* + * Design note for the m68k rewrite: + * The structure of the m68k serial code requires separation of the low-level + * functions that talk directly to the hardware from the Linux serial driver + * code interfacing to the tty layer. The reason for this separation is simply + * the fact that the m68k serial hardware is, unlike the i386, based on a + * variety of chips, and the rs_* serial routines need to be shared. + * + * I've tried to make consistent use of the async_struct info populated in the + * midlevel code, and introduced an async_private struct to hold the Macintosh + * SCC internals (this was added to the async_struct for the PowerMac driver). + * Exception: the console and kgdb hooks still use the zs_soft[] data, and this + * is still filled in by the probe_sccs() routine, which provides some data + * for mac_SCC_init as well. Interrupts are registered in mac_SCC_init, so + * the console/kgdb stuff probably won't work before proper serial init, and + * I have to rely on keeping info and zs_soft consistent at least for the + * console/kgdb port. + * + * Update (16-11-97): The SCC interrupt handling was suffering from the problem + * that the autovector SCC interrupt was registered only once, hence only one + * async_struct was passed to the interrupt function and only interrupts from + * the corresponding channel could be handled (yes, major design flaw). + * The autovector interrupt is now registered by the main interrupt initfunc, + * and uses a handler that will call the registered SCC specific interrupts in + * turn. The SCC init has to register these as machspec interrupts now, as is + * done for the VIA interrupts elsewhere. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#ifndef CONFIG_MAC +#include +#endif +#include +#include +#include + +#include "mac_SCC.h" + +/* + * It would be nice to dynamically allocate everything that + * depends on NUM_SERIAL, so we could support any number of + * Z8530s, but for now... + */ +#define NUM_SERIAL 2 /* Max number of ZS chips supported */ +#define NUM_CHANNELS (NUM_SERIAL * 2) /* 2 channels per chip */ + +#ifdef CONFIG_MAC +/* + * All the Macintosh 68K boxes that have an MMU also have hardware + * recovery delays. + */ +#define RECOVERY_DELAY +#else +/* On PowerMacs, the hardware takes care of the SCC recovery time, + but we need the eieio to make sure that the accesses occur + in the order we want. */ +#define RECOVERY_DELAY eieio() +#endif + +struct mac_zschannel *zs_kgdbchan; +struct mac_zschannel zs_channels[NUM_CHANNELS]; + +struct m68k_async_struct zs_soft[NUM_CHANNELS]; +struct m68k_async_private zs_soft_private[NUM_CHANNELS]; +int zs_channels_found; +struct m68k_async_struct *zs_chain; /* list of all channels */ + +struct tty_struct zs_ttys[NUM_CHANNELS]; +/** struct tty_struct *zs_constty; **/ + +/* Console hooks... */ +static int zs_cons_chanout = 0; +static int zs_cons_chanin = 0; +struct m68k_async_struct *zs_consinfo = 0; +struct mac_zschannel *zs_conschan; + +static unsigned char kgdb_regs[16] = { + 0, 0, 0, /* write 0, 1, 2 */ + (Rx8 | RxENABLE), /* write 3 */ + (X16CLK | SB1 | PAR_EVEN), /* write 4 */ + (Tx8 | TxENAB), /* write 5 */ + 0, 0, 0, /* write 6, 7, 8 */ + (NV), /* write 9 */ + (NRZ), /* write 10 */ + (TCBR | RCBR), /* write 11 */ + 1, 0, /* 38400 baud divisor, write 12 + 13 */ + (BRENABL), /* write 14 */ + (DCDIE) /* write 15 */ +}; + +#define ZS_CLOCK 3686400 /* Z8530 RTxC input clock rate */ + +/* Debugging... DEBUG_INTR is bad to use when one of the zs + * lines is your console ;( + */ +#undef SERIAL_DEBUG_INTR +#undef SERIAL_DEBUG_OPEN +#undef SERIAL_DEBUG_FLOW + +#define RS_STROBE_TIME 10 +#define RS_ISR_PASS_LIMIT 256 + +#define _INLINE_ inline + +static void probe_sccs(void); + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + + +/***************************** Prototypes *****************************/ + +static void SCC_init_port( struct m68k_async_struct *info, int type, int channel ); +#if 0 +#ifdef MODULE +static void SCC_deinit_port( struct m68k_async_struct *info, int channel ); +#endif +#endif + +/* FIXME !!! Currently, only autovector interrupt used! */ +#if 0 +static void SCC_rx_int (int irq, void *data, struct pt_regs *fp); +static void SCC_spcond_int (int irq, void *data, struct pt_regs *fp); +static void SCC_tx_int (int irq, void *data, struct pt_regs *fp); +static void SCC_stat_int (int irq, void *data, struct pt_regs *fp); +static void SCC_ri_int (int irq, void *data, struct pt_regs *fp); +#endif + +static int SCC_check_open( struct m68k_async_struct *info, struct tty_struct + *tty, struct file *file ); +static void SCC_init( struct m68k_async_struct *info ); +static void SCC_deinit( struct m68k_async_struct *info, int leave_dtr ); +static void SCC_enab_tx_int( struct m68k_async_struct *info, int enab_flag ); +static int SCC_check_custom_divisor( struct m68k_async_struct *info, int baud_base, + int divisor ); +static void SCC_change_speed( struct m68k_async_struct *info ); +#if 0 +static int SCC_clocksrc( unsigned baud_base, unsigned channel ); +#endif +static void SCC_throttle( struct m68k_async_struct *info, int status ); +static void SCC_set_break( struct m68k_async_struct *info, int break_flag ); +static void SCC_get_serial_info( struct m68k_async_struct *info, struct + serial_struct *retinfo ); +static unsigned int SCC_get_modem_info( struct m68k_async_struct *info ); +static int SCC_set_modem_info( struct m68k_async_struct *info, int new_dtr, int + new_rts ); +static int SCC_ioctl( struct tty_struct *tty, struct file *file, struct + m68k_async_struct *info, unsigned int cmd, unsigned long arg ); +static void SCC_stop_receive (struct m68k_async_struct *info); +static int SCC_trans_empty (struct m68k_async_struct *info); + +/************************* End of Prototypes **************************/ + + +static SERIALSWITCH SCC_switch = { + SCC_init, SCC_deinit, SCC_enab_tx_int, + SCC_check_custom_divisor, SCC_change_speed, + SCC_throttle, SCC_set_break, + SCC_get_serial_info, SCC_get_modem_info, + SCC_set_modem_info, SCC_ioctl, SCC_stop_receive, SCC_trans_empty, + SCC_check_open +}; + +/* + * tmp_buf is used as a temporary buffer by serial_write. We need to + * lock it in case the memcpy_fromfs blocks while swapping in a page, + * and some other program tries to do a serial write at the same time. + * Since the lock will only come under contention when the system is + * swapping and available memory is low, it makes sense to share one + * buffer across all the serial ports, since it significantly saves + * memory if large numbers of serial ports are open. + */ +static unsigned char tmp_buf[4096]; /* This is cheating */ +static struct semaphore tmp_buf_sem = MUTEX; + +/* + * This is used to figure out the divisor speeds and the timeouts + */ +static int baud_table[] = { + 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, + 9600, 19200, 38400, 57600, 115200, 0 }; + +/* + * Reading and writing Z8530 registers. + */ +static inline unsigned char read_zsreg(struct mac_zschannel *channel, + unsigned char reg) +{ + unsigned char retval; + + if (reg != 0) { + *channel->control = reg; + RECOVERY_DELAY; + } + retval = *channel->control; + RECOVERY_DELAY; + return retval; +} + +static inline void write_zsreg(struct mac_zschannel *channel, + unsigned char reg, unsigned char value) +{ + if (reg != 0) { + *channel->control = reg; + RECOVERY_DELAY; + } + *channel->control = value; + RECOVERY_DELAY; + return; +} + +static inline unsigned char read_zsdata(struct mac_zschannel *channel) +{ + unsigned char retval; + + retval = *channel->data; + RECOVERY_DELAY; + return retval; +} + +static inline void write_zsdata(struct mac_zschannel *channel, + unsigned char value) +{ + *channel->data = value; + RECOVERY_DELAY; + return; +} + +static inline void load_zsregs(struct mac_zschannel *channel, + unsigned char *regs) +{ + ZS_CLEARERR(channel); + ZS_CLEARFIFO(channel); + /* Load 'em up */ + write_zsreg(channel, R4, regs[R4]); + write_zsreg(channel, R10, regs[R10]); + write_zsreg(channel, R3, regs[R3] & ~RxENABLE); + write_zsreg(channel, R5, regs[R5] & ~TxENAB); + write_zsreg(channel, R1, regs[R1]); + write_zsreg(channel, R9, regs[R9]); + write_zsreg(channel, R11, regs[R11]); + write_zsreg(channel, R12, regs[R12]); + write_zsreg(channel, R13, regs[R13]); + write_zsreg(channel, R14, regs[R14]); + write_zsreg(channel, R15, regs[R15]); + write_zsreg(channel, R3, regs[R3]); + write_zsreg(channel, R5, regs[R5]); + return; +} + +/* Sets or clears DTR/RTS on the requested line */ +static inline void zs_rtsdtr(struct m68k_async_struct *ss, int set) +{ + if (set) + ss->private->curregs[5] |= (RTS | DTR); + else + ss->private->curregs[5] &= ~(RTS | DTR); + write_zsreg(ss->private->zs_channel, 5, ss->private->curregs[5]); + return; +} + +static inline void kgdb_chaninit(struct m68k_async_struct *ss, int intson, int bps) +{ + int brg; + + if (intson) { + kgdb_regs[R1] = INT_ALL_Rx; + kgdb_regs[R9] |= MIE; + } else { + kgdb_regs[R1] = 0; + kgdb_regs[R9] &= ~MIE; + } + brg = BPS_TO_BRG(bps, ZS_CLOCK/16); + kgdb_regs[R12] = brg; + kgdb_regs[R13] = brg >> 8; + load_zsregs(ss->private->zs_channel, kgdb_regs); +} + +/* Utility routines for the Zilog */ +static inline int get_zsbaud(struct m68k_async_struct *ss) +{ + struct mac_zschannel *channel = ss->private->zs_channel; + int brg; + + /* The baud rate is split up between two 8-bit registers in + * what is termed 'BRG time constant' format in my docs for + * the chip, it is a function of the clk rate the chip is + * receiving which happens to be constant. + */ + brg = (read_zsreg(channel, 13) << 8); + brg |= read_zsreg(channel, 12); + return BRG_TO_BPS(brg, (ZS_CLOCK/(ss->private->clk_divisor))); +} + +/* On receive, this clears errors and the receiver interrupts */ +static inline void SCC_recv_clear(struct mac_zschannel *zsc) +{ + write_zsreg(zsc, 0, ERR_RES); + write_zsreg(zsc, 0, RES_H_IUS); /* XXX this is unnecessary */ +} + +/* + * ---------------------------------------------------------------------- + * + * Here starts the interrupt handling routines. All of the following + * subroutines are declared as inline and are folded into + * rs_interrupt(). They were separated out for readability's sake. + * + * - Ted Ts'o (tytso@mit.edu), 7-Mar-93 + * ----------------------------------------------------------------------- + */ + +extern void breakpoint(void); /* For the KGDB frame character */ + +static /*_INLINE_*/ void receive_chars(struct m68k_async_struct *info, + struct pt_regs *regs) +{ + struct tty_struct *tty = info->tty; + unsigned char ch, stat, flag; + + while ((read_zsreg(info->private->zs_channel, 0) & Rx_CH_AV) != 0) { + + stat = read_zsreg(info->private->zs_channel, R1); + ch = read_zsdata(info->private->zs_channel); + +#ifdef SCC_DEBUG + printk("mac_SCC: receive_chars stat=%X char=%X \n", stat, ch); +#endif + +#if 0 /* KGDB not yet supported */ + /* Look for kgdb 'stop' character, consult the gdb documentation + * for remote target debugging and arch/sparc/kernel/sparc-stub.c + * to see how all this works. + */ + if ((info->kgdb_channel) && (ch =='\003')) { + breakpoint(); + continue; + } +#endif + + if (!tty) + continue; + + if (tty->flip.count >= TTY_FLIPBUF_SIZE) + tty_flip_buffer_push(tty); + + if (stat & Rx_OVR) { + flag = TTY_OVERRUN; + /* reset the error indication */ + write_zsreg(info->private->zs_channel, 0, ERR_RES); + } else if (stat & FRM_ERR) { + /* this error is not sticky */ + flag = TTY_FRAME; + } else if (stat & PAR_ERR) { + flag = TTY_PARITY; + /* reset the error indication */ + write_zsreg(info->private->zs_channel, 0, ERR_RES); + } else + flag = 0; + + if (tty->flip.buf_num + && tty->flip.count >= TTY_FLIPBUF_SIZE) { +#ifdef SCC_DEBUG_OVERRUN + printk("mac_SCC: flip buffer overrun!\n"); +#endif + return; + } + + if (!tty->flip.buf_num + && tty->flip.count >= 2*TTY_FLIPBUF_SIZE) { + printk("mac_SCC: double flip buffer overrun!\n"); + return; + } + + tty->flip.count++; + *tty->flip.flag_buf_ptr++ = flag; + *tty->flip.char_buf_ptr++ = ch; + info->icount.rx++; + tty_flip_buffer_push(tty); + } +#if 0 +clear_and_exit: + SCC_recv_clear(info->private->zs_channel); +#endif +} + +/* that's SCC_enable_tx_int, basically */ + +static void transmit_chars(struct m68k_async_struct *info) +{ + if ((read_zsreg(info->private->zs_channel, 0) & Tx_BUF_EMP) == 0) + return; + info->private->tx_active = 0; + + if (info->x_char) { + /* Send next char */ + write_zsdata(info->private->zs_channel, info->x_char); + info->x_char = 0; + info->private->tx_active = 1; + return; + } + + if ((info->xmit_cnt <= 0) || info->tty->stopped + || info->private->tx_stopped) { + write_zsreg(info->private->zs_channel, 0, RES_Tx_P); + return; + } + + /* Send char */ + write_zsdata(info->private->zs_channel, info->xmit_buf[info->xmit_tail++]); + info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); + info->icount.tx++; + info->xmit_cnt--; + info->private->tx_active = 1; + + if (info->xmit_cnt < WAKEUP_CHARS) + rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); +} + +static /*_INLINE_*/ void status_handle(struct m68k_async_struct *info) +{ + unsigned char status; + + /* Get status from Read Register 0 */ + status = read_zsreg(info->private->zs_channel, 0); + + /* Check for DCD transitions */ + if (((status ^ info->private->read_reg_zero) & DCD) != 0 + && info->tty && C_CLOCAL(info->tty)) { + if (status & DCD) { + wake_up_interruptible(&info->open_wait); + } else if (!(info->flags & ZILOG_CALLOUT_ACTIVE)) { + if (info->tty) + tty_hangup(info->tty); + } + } + + /* Check for CTS transitions */ + if (info->tty && C_CRTSCTS(info->tty)) { + /* + * For some reason, on the Power Macintosh, + * it seems that the CTS bit is 1 when CTS is + * *negated* and 0 when it is asserted. + * The DCD bit doesn't seem to be inverted + * like this. + */ + if ((status & CTS) == 0) { + if (info->private->tx_stopped) { + info->private->tx_stopped = 0; + if (!info->private->tx_active) + transmit_chars(info); + } + } else { + info->private->tx_stopped = 1; + } + } + + /* Clear status condition... */ + write_zsreg(info->private->zs_channel, 0, RES_EXT_INT); + info->private->read_reg_zero = status; +} + +/* + * This is the serial driver's generic interrupt routine + */ +void mac_SCC_interrupt(int irq, void *dev_id, struct pt_regs * regs) +{ + struct m68k_async_struct *info = (struct m68k_async_struct *) dev_id; + unsigned char zs_intreg; + int shift; + + /* NOTE: The read register 3, which holds the irq status, + * does so for both channels on each chip. Although + * the status value itself must be read from the A + * channel and is only valid when read from channel A. + * Yes... broken hardware... + */ +#define CHAN_IRQMASK (CHBRxIP | CHBTxIP | CHBEXT) + +#ifdef SCC_DEBUG + printk("mac_SCC: interrupt; port: %lx channel: %lx \n", + info->port, info->private->zs_channel); +#endif + + if (info->private->zs_chan_a == info->private->zs_channel) + shift = 3; /* Channel A */ + else + shift = 0; /* Channel B */ + + for (;;) { + zs_intreg = read_zsreg(info->private->zs_chan_a, 3); +#ifdef SCC_DEBUG + printk("mac_SCC: status %x shift %d shifted %x \n", + zs_intreg, shift, zs_intreg >> shift); +#endif + zs_intreg = zs_intreg >> shift; + if ((zs_intreg & CHAN_IRQMASK) == 0) + break; + + if (zs_intreg & CHBRxIP) + receive_chars(info, regs); + if (zs_intreg & CHBTxIP) + transmit_chars(info); + if (zs_intreg & CHBEXT) + status_handle(info); + } +} + +/* + * ------------------------------------------------------------------- + * Here ends the serial interrupt routines. + * ------------------------------------------------------------------- + */ + +/* + * ------------------------------------------------------------ + * rs_stop() and rs_start() + * + * This routines are called before setting or resetting tty->stopped. + * ------------------------------------------------------------ + */ + +static void SCC_enab_tx_int( struct m68k_async_struct *info, int enab_flag ) +{ + unsigned long flags; + + if (enab_flag) { +#if 0 + save_flags(flags); cli(); + if (info->private->curregs[5] & TxENAB) { + info->private->curregs[5] &= ~TxENAB; + info->private->pendregs[5] &= ~TxENAB; + write_zsreg(info->private->zs_channel, 5, + info->private->curregs[5]); + } + restore_flags(flags); +#endif + /* FIXME: should call transmit_chars here ??? */ + transmit_chars(info); + } else { + save_flags(flags); cli(); +#if 0 + if ( info->xmit_cnt && info->xmit_buf && + !(info->private->curregs[5] & TxENAB)) { + info->private->curregs[5] |= TxENAB; + info->private->pendregs[5] = info->private->curregs[5]; + write_zsreg(info->private->zs_channel, 5, + info->private->curregs[5]); + } +#else + if ( info->xmit_cnt && info->xmit_buf && + !info->private->tx_active) { + transmit_chars(info); + } +#endif + restore_flags(flags); + } + +} + +#if 0 +/* + * leftover from original driver ... + */ +static int SCC_startup(struct m68k_async_struct * info) +{ + unsigned long flags; + + save_flags(flags); cli(); + +#ifdef SERIAL_DEBUG_OPEN + printk("starting up ttyS%d (irq %d)...", info->line, info->irq); +#endif + + /* + * Clear the receive FIFO. + */ + ZS_CLEARFIFO(info->private->zs_channel); + info->xmit_fifo_size = 1; + + /* + * Clear the interrupt registers. + */ + write_zsreg(info->private->zs_channel, 0, ERR_RES); + write_zsreg(info->private->zs_channel, 0, RES_H_IUS); + + /* + * Turn on RTS and DTR. + */ + zs_rtsdtr(info, 1); + + /* + * Finally, enable sequencing and interrupts + */ + info->private->curregs[1] = (info->private->curregs[1] & ~0x18) + | (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB); + info->private->pendregs[1] = info->private->curregs[1]; + info->private->curregs[3] |= (RxENABLE | Rx8); + info->private->pendregs[3] = info->private->curregs[3]; + info->private->curregs[5] |= (TxENAB | Tx8); + info->private->pendregs[5] = info->private->curregs[5]; + info->private->curregs[9] |= (NV | MIE); + info->private->pendregs[9] = info->private->curregs[9]; + write_zsreg(info->private->zs_channel, 3, info->private->curregs[3]); + write_zsreg(info->private->zs_channel, 5, info->private->curregs[5]); + write_zsreg(info->private->zs_channel, 9, info->private->curregs[9]); + + /* + * Set the speed of the serial port + */ + SCC_change_speed(info); + + /* Save the current value of RR0 */ + info->private->read_reg_zero = read_zsreg(info->private->zs_channel, 0); + + restore_flags(flags); + return 0; +} +#endif + +/* FIXME: are these required ?? */ +static int SCC_check_open( struct m68k_async_struct *info, struct tty_struct *tty, + struct file *file ) +{ + /* check on the basis of info->whatever ?? */ + if (info->private->kgdb_channel || info->private->is_cons) + return -EBUSY; + return( 0 ); +} + +static void SCC_init( struct m68k_async_struct *info ) +{ + /* FIXME: init currently done in probe_sccs() */ + + /* BUT: startup part needs to be done here! */ + +#ifdef SCC_DEBUG + printk("mac_SCC: init, info %lx, info->port %lx \n", info, info->port); +#endif + /* + * Clear the receive FIFO. + */ + ZS_CLEARFIFO(info->private->zs_channel); + info->xmit_fifo_size = 1; + + /* + * Clear the interrupt registers. + */ + write_zsreg(info->private->zs_channel, 0, ERR_RES); + write_zsreg(info->private->zs_channel, 0, RES_H_IUS); + + /* + * Turn on RTS and DTR. + */ + zs_rtsdtr(info, 1); + + /* + * Finally, enable sequencing and interrupts + */ + info->private->curregs[1] = (info->private->curregs[1] & ~0x18) + | (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB); + info->private->pendregs[1] = info->private->curregs[1]; + info->private->curregs[3] |= (RxENABLE | Rx8); + info->private->pendregs[3] = info->private->curregs[3]; + info->private->curregs[5] |= (TxENAB | Tx8); + info->private->pendregs[5] = info->private->curregs[5]; + info->private->curregs[9] |= (NV | MIE); + info->private->pendregs[9] = info->private->curregs[9]; + write_zsreg(info->private->zs_channel, 3, info->private->curregs[3]); + write_zsreg(info->private->zs_channel, 5, info->private->curregs[5]); + write_zsreg(info->private->zs_channel, 9, info->private->curregs[9]); + + /* + * Set the speed of the serial port - done in startup() !! + */ +#if 0 + SCC_change_speed(info); +#endif + + /* Save the current value of RR0 */ + info->private->read_reg_zero = read_zsreg(info->private->zs_channel, 0); + +} + +static void SCC_init_port( struct m68k_async_struct *info, int type, int channel ) +{ + static int got_autovector = 0; + +#ifdef SCC_DEBUG + printk("mac_SCC: init_port, info %x \n", info); +#endif + info->sw = &SCC_switch; + info->private = &zs_soft_private[channel]; + info->private->zs_channel = &zs_channels[channel]; + info->irq = IRQ4; + info->private->clk_divisor = 16; + info->private->zs_baud = get_zsbaud(info); + info->port = (int) info->private->zs_channel->control; + + /* + * MSch: Extended interrupt scheme: + * The generic m68k interrupt code can't use multiple handlers for + * the same interrupt source (no chained interrupts). + * We have to plug in a 'master' interrupt handler instead, calling + * mac_SCC_interrupt with the proper arguments ... + */ + + if (!got_autovector) { + if(sys_request_irq(IRQ4, mac_SCC_handler, 0, "SCC master", info)) + panic("macserial: can't get irq %d", IRQ4); +#ifdef SCC_DEBUG + printk("mac_SCC: got SCC master interrupt %d, channel %d info %p\n", + IRQ4, channel, info); +#endif + got_autovector = 1; + } + + if (info->private->zs_chan_a == info->private->zs_channel) { + /* Channel A */ + if (request_irq(IRQ_SCCA, mac_SCC_interrupt, 0, "SCC A", info)) + panic("mac_SCC: can't get irq %d", IRQ_SCCA); +#ifdef SCC_DEBUG + printk("mac_SCC: got SCC A interrupt %d, channel %d info %p\n", + IRQ_SCCA, channel, info); +#endif + } else { + /* Channel B */ + if (request_irq(IRQ_SCCB, mac_SCC_interrupt, 0, "SCC B", info)) + panic("mac_SCC: can't get irq %d", IRQ_SCCB); +#ifdef SCC_DEBUG + printk("mac_SCC: got SCC B interrupt %d, channel %d info %p\n", + IRQ_SCCB, channel, info); +#endif + } + + /* If console serial line, then enable interrupts. */ + if (info->private->is_cons) { + printk("mac_SCC: console line %lx; enabling interrupt!\n", info); + write_zsreg(info->private->zs_channel, R1, + (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB)); + write_zsreg(info->private->zs_channel, R9, (NV | MIE)); + write_zsreg(info->private->zs_channel, R10, (NRZ)); + write_zsreg(info->private->zs_channel, R3, (Rx8 | RxENABLE)); + write_zsreg(info->private->zs_channel, R5, (Tx8 | TxENAB)); + } + /* If this is the kgdb line, enable interrupts because we + * now want to receive the 'control-c' character from the + * client attached to us asynchronously. + */ + if (info->private->kgdb_channel) { + printk("mac_SCC: kgdb line %lx; enabling interrupt!\n", info); + kgdb_chaninit(info, 1, info->private->zs_baud); + } + /* Report settings (in m68kserial.c) */ +#ifndef CONFIG_MAC + printk("ttyS%d at 0x%08x (irq = %d)", info->line, + info->port, info->irq); + printk(" is a Z8530 SCC\n"); +#endif + +} + +/* + * This routine will shutdown a serial port; interrupts are disabled, and + * DTR is dropped if the hangup on close termio flag is on. + */ +static void SCC_deinit(struct m68k_async_struct * info, int leave_dtr) +{ + unsigned long flags; + + save_flags(flags); cli(); /* Disable interrupts */ + + info->private->pendregs[1] = info->private->curregs[1] = 0; + write_zsreg(info->private->zs_channel, 1, 0); /* no interrupts */ + + info->private->curregs[3] &= ~RxENABLE; + info->private->pendregs[3] = info->private->curregs[3]; + write_zsreg(info->private->zs_channel, 3, info->private->curregs[3]); + + info->private->curregs[5] &= ~TxENAB; + + if (!leave_dtr) + info->private->curregs[5] &= ~(DTR | RTS); + else + info->private->curregs[5] &= ~(RTS); + + info->private->pendregs[5] = info->private->curregs[5]; + write_zsreg(info->private->zs_channel, 5, info->private->curregs[5]); + + restore_flags(flags); +} + +/* FIXME !!! */ +static int SCC_check_custom_divisor( struct m68k_async_struct *info, + int baud_base, int divisor ) +{ + return 0; +} + +/* + * This routine is called to set the UART divisor registers to match + * the specified baud rate for a serial port. + */ +static void SCC_change_speed(struct m68k_async_struct *info) +{ + unsigned short port; + unsigned cflag; + int i; + int brg; + unsigned long flags; + + if (!info->tty || !info->tty->termios) + return; + cflag = info->tty->termios->c_cflag; + if (!(port = info->port)) + return; + i = cflag & CBAUD; + + if (i == 0 && !(info->flags & ASYNC_SPD_MASK)) { + /* speed == 0 -> drop DTR */ + save_flags(flags); + cli(); + info->private->curregs[5] &= ~(DTR | RTS); + write_zsreg(info->private->zs_channel, 5, info->private->curregs[5]); + restore_flags(flags); + return; + } + + + if (i & CBAUDEX) { + /* XXX CBAUDEX is not obeyed. + * It is impossible at a 32bits PPC. XXX?? + * But we have to report this to user ... someday. + */ + i = B9600; + } + + save_flags(flags); cli(); + info->private->zs_baud = baud_table[i]; + info->private->clk_divisor = 16; + + info->private->curregs[4] = X16CLK; + info->private->curregs[11] = TCBR | RCBR; + brg = BPS_TO_BRG(info->private->zs_baud, + ZS_CLOCK/info->private->clk_divisor); + info->private->curregs[12] = (brg & 255); + info->private->curregs[13] = ((brg >> 8) & 255); + info->private->curregs[14] = BRENABL; + + /* byte size and parity */ + info->private->curregs[3] &= ~RxNBITS_MASK; + info->private->curregs[5] &= ~TxNBITS_MASK; + switch (cflag & CSIZE) { + case CS5: + info->private->curregs[3] |= Rx5; + info->private->curregs[5] |= Tx5; + break; + case CS6: + info->private->curregs[3] |= Rx6; + info->private->curregs[5] |= Tx6; + break; + case CS7: + info->private->curregs[3] |= Rx7; + info->private->curregs[5] |= Tx7; + break; + case CS8: + default: /* defaults to 8 bits */ + info->private->curregs[3] |= Rx8; + info->private->curregs[5] |= Tx8; + break; + } + info->private->pendregs[3] = info->private->curregs[3]; + info->private->pendregs[5] = info->private->curregs[5]; + + info->private->curregs[4] &= ~(SB_MASK | PAR_ENA | PAR_EVEN); + if (cflag & CSTOPB) { + info->private->curregs[4] |= SB2; + } else { + info->private->curregs[4] |= SB1; + } + if (cflag & PARENB) { + info->private->curregs[4] |= PAR_ENA; + } + if (!(cflag & PARODD)) { + info->private->curregs[4] |= PAR_EVEN; + } + info->private->pendregs[4] = info->private->curregs[4]; + + info->private->curregs[15] &= ~(DCDIE | CTSIE); + if (!(cflag & CLOCAL)) { + info->private->curregs[15] |= DCDIE; + } + if (cflag & CRTSCTS) { + info->private->curregs[15] |= CTSIE; + if ((read_zsreg(info->private->zs_channel, 0) & CTS) != 0) + info->private->tx_stopped = 1; + } else + info->private->tx_stopped = 0; + info->private->pendregs[15] = info->private->curregs[15]; + + /* Load up the new values */ + load_zsregs(info->private->zs_channel, info->private->curregs); + + restore_flags(flags); +} + +/* This is for console output over ttya/ttyb */ +static void SCC_put_char(char ch) +{ + struct mac_zschannel *chan = zs_conschan; + int loops = 0; + unsigned long flags; + + if(!chan) + return; + + save_flags(flags); cli(); + while ((read_zsreg(chan, 0) & Tx_BUF_EMP) == 0 && loops < 10000) { + loops++; + udelay(5); + } + write_zsdata(chan, ch); + restore_flags(flags); +} + +/* These are for receiving and sending characters under the kgdb + * source level kernel debugger. + */ +void putDebugChar(char kgdb_char) +{ + struct mac_zschannel *chan = zs_kgdbchan; + + while ((read_zsreg(chan, 0) & Tx_BUF_EMP) == 0) + udelay(5); + write_zsdata(chan, kgdb_char); +} + +char getDebugChar(void) +{ + struct mac_zschannel *chan = zs_kgdbchan; + + while ((read_zsreg(chan, 0) & Rx_CH_AV) == 0) + udelay(5); + return read_zsdata(chan); +} + +/* + * Fair output driver allows a process to speak. + */ +static void SCC_fair_output(void) +{ + int left; /* Output no more than that */ + unsigned long flags; + struct m68k_async_struct *info = zs_consinfo; + char c; + + if (info == 0) return; + if (info->xmit_buf == 0) return; + + save_flags(flags); cli(); + left = info->xmit_cnt; + while (left != 0) { + c = info->xmit_buf[info->xmit_tail]; + info->xmit_tail = (info->xmit_tail+1) & (SERIAL_XMIT_SIZE-1); + info->xmit_cnt--; + restore_flags(flags); + + SCC_put_char(c); + + save_flags(flags); cli(); + left = MIN(info->xmit_cnt, left-1); + } + + restore_flags(flags); + return; +} + +/* + * zs_console_print is registered for printk. + */ +static void zs_console_print(const char *p) +{ + char c; + + while ((c = *(p++)) != 0) { + if (c == '\n') + SCC_put_char('\r'); + SCC_put_char(c); + } + + /* Comment this if you want to have a strict interrupt-driven output */ + SCC_fair_output(); +} + +/* FIXME: check with SCC_enab_tx_int!! */ +#if 0 +static void rs_flush_chars(struct tty_struct *tty) +{ + struct m68k_async_struct *info = (struct m68k_async_struct *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_flush_chars")) + return; + + if (info->xmit_cnt <= 0 || tty->stopped || info->private->tx_stopped || + !info->xmit_buf) + return; + + /* Enable transmitter */ + save_flags(flags); cli(); + transmit_chars(info); + restore_flags(flags); +} + +static int rs_write(struct tty_struct * tty, int from_user, + const unsigned char *buf, int count) +{ + int c, total = 0; + struct m68k_async_struct *info = (struct m68k_async_struct *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_write")) + return 0; + + if (!tty || !info->xmit_buf) + return 0; + + save_flags(flags); + while (1) { + cli(); + c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + if (c <= 0) + break; + + if (from_user) { + down(&tmp_buf_sem); + memcpy_fromfs(tmp_buf, buf, c); + c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); + up(&tmp_buf_sem); + } else + memcpy(info->xmit_buf + info->xmit_head, buf, c); + info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); + info->xmit_cnt += c; + restore_flags(flags); + buf += c; + count -= c; + total += c; + } + if (info->xmit_cnt && !tty->stopped && !info->tx_stopped + && !info->tx_active) + transmit_chars(info); + restore_flags(flags); + return total; +} +#endif + +/* + * ------------------------------------------------------------ + * rs_throttle() + * + * This routine is called by the upper-layer tty layer to signal that + * incoming characters should be throttled. + * ------------------------------------------------------------ + */ +static void SCC_throttle(struct m68k_async_struct *info, int status) +{ + unsigned long flags; + + save_flags(flags); + cli(); + + if (status) { + /* + * Here we want to turn off the RTS line. On Macintoshes, + * we only get the DTR line, which goes to both DTR and + * RTS on the modem. RTS doesn't go out to the serial + * port socket. So you should make sure your modem is + * set to ignore DTR if you're using CRTSCTS. + */ + info->private->curregs[5] &= ~(DTR | RTS); + info->private->pendregs[5] &= ~(DTR | RTS); + write_zsreg(info->private->zs_channel, 5, + info->private->curregs[5]); + } else { + /* Assert RTS and DTR lines */ + info->private->curregs[5] |= DTR | RTS; + info->private->pendregs[5] |= DTR | RTS; + write_zsreg(info->private->zs_channel, 5, + info->private->curregs[5]); + } + + restore_flags(flags); + +} + +/* + * ------------------------------------------------------------ + * rs_ioctl() and friends + * ------------------------------------------------------------ + */ + +static void SCC_get_serial_info(struct m68k_async_struct * info, + struct serial_struct * retinfo) +{ + struct serial_struct tmp; + + retinfo->baud_base = info->baud_base; + retinfo->custom_divisor = info->custom_divisor; +} + +/* FIXME: set_serial_info needs check_custom_divisor !!! */ + +/* + * get_lsr_info - get line status register info + * + * Purpose: Let user call ioctl() to get info when the UART physically + * is emptied. On bus types like RS485, the transmitter must + * release the bus after transmitting. This must be done when + * the transmit shift register is empty, not be done when the + * transmit holding register is empty. This functionality + * allows an RS485 driver to be written in user space. + */ +static int SCC_get_lsr_info(struct m68k_async_struct * info, unsigned int *value) +{ + unsigned char status; + + cli(); + status = read_zsreg(info->private->zs_channel, 0); + sti(); + return status; +} + +static unsigned int SCC_get_modem_info(struct m68k_async_struct *info) +{ + unsigned char control, status; + unsigned int result; + + cli(); + control = info->private->curregs[5]; + status = read_zsreg(info->private->zs_channel, 0); + sti(); + result = ((control & RTS) ? TIOCM_RTS: 0) + | ((control & DTR) ? TIOCM_DTR: 0) + | ((status & DCD) ? TIOCM_CAR: 0) + | ((status & CTS) ? 0: TIOCM_CTS); + return result; +} + +/* FIXME: zs_setdtr was used in rs_open ... */ + +static int SCC_set_modem_info(struct m68k_async_struct *info, + int new_dtr, int new_rts) +{ + int error; + unsigned int arg, bits; + + bits = (new_rts ? RTS: 0) + (new_dtr ? DTR: 0); + info->private->curregs[5] = (info->private->curregs[5] & ~(DTR | RTS)) | bits; + info->private->pendregs[5] = info->private->curregs[5]; + write_zsreg(info->private->zs_channel, 5, info->private->curregs[5]); + sti(); + return 0; +} + +/* + * This routine sends a break character out the serial port. + */ +static void SCC_set_break(struct m68k_async_struct * info, int break_flag) +{ + unsigned long flags; + + save_flags(flags); + cli(); + + if (break_flag) { + info->private->curregs[5] |= SND_BRK; + write_zsreg(info->private->zs_channel, 5, + info->private->curregs[5]); + } else { + info->private->curregs[5] &= ~SND_BRK; + write_zsreg(info->private->zs_channel, 5, + info->private->curregs[5]); + } + + restore_flags(flags); +} + +/* FIXME: these have to be enabled in rs_ioctl !! */ + +static int SCC_ioctl(struct tty_struct *tty, struct file * file, + struct m68k_async_struct * info, unsigned int cmd, + unsigned long arg) +{ + int error; + int retval; + + switch (cmd) { + case TIOCSERGETLSR: /* Get line status register */ + error = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(unsigned int)); + if (error) + return error; + else + return SCC_get_lsr_info(info, (unsigned int *) arg); + + case TIOCSERGSTRUCT: + error = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(struct m68k_async_struct)); + if (error) + return error; + copy_to_user((struct m68k_async_struct *) arg, + info, sizeof(struct m68k_async_struct)); + return 0; + + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static void SCC_stop_receive (struct m68k_async_struct *info) +{ + /* disable Rx */ + info->private->curregs[3] &= ~RxENABLE; + info->private->pendregs[3] = info->private->curregs[3]; + write_zsreg(info->private->zs_channel, 3, info->private->curregs[3]); + /* disable Rx interrupts */ + info->private->curregs[1] &= ~(0x18); /* disable any rx ints */ + info->private->pendregs[1] = info->private->curregs[1]; + write_zsreg(info->private->zs_channel, 1, info->private->curregs[1]); + ZS_CLEARFIFO(info->private->zs_channel); +} + +static int SCC_trans_empty (struct m68k_async_struct *info) +{ + return (read_zsreg(info->private->zs_channel, 1) & ALL_SNT) != 0; +} + +/* Finally, routines used to initialize the serial driver. */ + +#ifdef CONFIG_MAC + +/* + * Mac: use boot_info data; assume 2 channels + */ + +static void probe_sccs(void) +{ + int n; + +#define ZS_CONTROL 0x50F04000 +#define ZS_DATA (ZS_CONTROL+4) +#define ZS_IRQ 5 +#define ZS_MOVE -2 +#define ZS_DATA_MOVE 4 +#define ZS_CH_A_FIRST 2 + + /* last-ditch fixup for NetBSD booter case */ + if (mac_bi_data.sccbase == 0) + mac_bi_data.sccbase = ZS_CONTROL; + + /* testing: fix up broken 24 bit addresses (ClassicII) */ + if ((mac_bi_data.sccbase & 0x00FFFFFF) == mac_bi_data.sccbase) + mac_bi_data.sccbase |= 0x50000000; + + for(n=0;n<2;n++) + { +#if 0 + zs_channels[n].control = (volatile unsigned char *) + ZS_CONTROL+ZS_MOVE*n; + zs_channels[n].data = (volatile unsigned char *)ZS_DATA+ZS_MOVE*n; +#else + zs_channels[n].control = (volatile unsigned char *) + (mac_bi_data.sccbase+ZS_CH_A_FIRST)+ZS_MOVE*n; + zs_channels[n].data = (volatile unsigned char *) + (mac_bi_data.sccbase+ZS_CH_A_FIRST+ZS_DATA_MOVE)+ZS_MOVE*n; +#endif + zs_soft[n].private = &zs_soft_private[n]; + zs_soft[n].private->zs_channel = &zs_channels[n]; + zs_soft[n].irq = IRQ4; +#if 0 + if (request_irq(ch->intrs[0], rs_interrupt, 0, + "SCC", &zs_soft[n])) + panic("macserial: can't get irq %d", + ch->intrs[0]); +#endif + if (n & 1) + zs_soft[n].private->zs_chan_a = &zs_channels[n-1]; + else + zs_soft[n].private->zs_chan_a = &zs_channels[n]; + } + + zs_channels_found=2; +} + +#else + +/* + * PowerMAC - query the PROM + */ + +static void show_serial_version(void) +{ + printk("PowerMac Z8530 serial driver version 1.00\n"); +} + +/* Ask the PROM how many Z8530s we have and initialize their zs_channels */ +static void +probe_sccs() +{ + struct device_node *dev, *ch; + struct m68k_async_struct **pp; + int n; + + n = 0; + pp = &zs_chain; + for (dev = find_devices("escc"); dev != 0; dev = dev->next) { + if (n >= NUM_CHANNELS) { + printk("Sorry, can't use %s: no more channels\n", + dev->full_name); + continue; + } + for (ch = dev->child; ch != 0; ch = ch->sibling) { + if (ch->n_addrs < 1 || ch ->n_intrs < 1) { + printk("Can't use %s: %d addrs %d intrs\n", + ch->full_name, ch->n_addrs, ch->n_intrs); + continue; + } + zs_channels[n].control = (volatile unsigned char *) + ch->addrs[0].address; + zs_channels[n].data = zs_channels[n].control + + ch->addrs[0].size / 2; + zs_soft[n].private = &zs_soft_private[n]; + zs_soft[n].private->zs_channel = &zs_channels[n]; + zs_soft[n].irq = ch->intrs[0]; + if (request_irq(ch->intrs[0], mac_SCC_interrupt, 0, + "SCC", &zs_soft[n])) + panic("macserial: can't get irq %d", + ch->intrs[0]); + /* XXX this assumes the prom puts chan A before B */ + if (n & 1) + zs_soft[n].private->zs_chan_a = &zs_channels[n-1]; + else + zs_soft[n].private->zs_chan_a = &zs_channels[n]; + + *pp = &zs_soft[n]; + pp = &zs_soft[n].private->zs_next; + ++n; + } + } + *pp = 0; + zs_channels_found = n; +} + +#endif + +extern void register_console(void (*proc)(const char *)); + +static inline void +rs_cons_check(struct m68k_async_struct *ss, int channel) +{ + int i, o, io; + static consout_registered = 0; + static msg_printed = 0; + + i = o = io = 0; + + /* Is this one of the serial console lines? */ + if ((zs_cons_chanout != channel) && + (zs_cons_chanin != channel)) + return; + zs_conschan = ss->private->zs_channel; + zs_consinfo = ss; + + /* Register the console output putchar, if necessary */ + if (zs_cons_chanout == channel) { + o = 1; + /* double whee.. */ + if (!consout_registered) { + register_console(zs_console_print); + consout_registered = 1; + } + } + + if (zs_cons_chanin == channel) { + i = 1; + } + if (o && i) + io = 1; + if (ss->private->zs_baud != 9600) + panic("Console baud rate weirdness"); + + /* Set flag variable for this port so that it cannot be + * opened for other uses by accident. + */ + ss->private->is_cons = 1; + + if (io) { + if(!msg_printed) { + printk("zs%d: console I/O\n", ((channel>>1)&1)); + msg_printed = 1; + } + } else { + printk("zs%d: console %s\n", ((channel>>1)&1), + (i==1 ? "input" : (o==1 ? "output" : "WEIRD"))); + } + + /* FIXME : register interrupt here??? */ +} + +volatile int test_done; + +/* rs_init inits the driver */ +int mac_SCC_init(void) +{ + int channel, line, nr = 0, i; + unsigned long flags; + struct serial_struct req; + struct m68k_async_struct *info; + + printk("Mac68K Z8530 serial driver version 1.01\n"); + + /* SCC present at all? */ + if (MACH_IS_ATARI || MACH_IS_AMIGA +#if 0 + || !(MACHW_PRESENT(SCC) || MACHW_PRESENT(ST_ESCC)) +#endif + ) + return( -ENODEV ); + + if (zs_chain == 0) + probe_sccs(); + + save_flags(flags); + cli(); + + /* + * FIXME: init of rs_table entry and register_serial now done, + * but possible clash of zs_soft[channel] and rs_table[channel]!! + * zs_soft initialized in probe_sccs(), some settings copied to + * info = &rs_table[channel], which is used by the mid-level code. + * The info->private part is shared among both! + */ + + for (channel = 0; channel < zs_channels_found; ++channel) { + req.line = channel; + req.type = SER_SCC_MAC; + req.port = zs_soft[channel].private->zs_channel->control; + + if ((line = register_serial( &req )) >= 0) { + SCC_init_port( &rs_table[line], req.type, line ); + ++nr; + } + else + printk(KERN_WARNING "Cannot allocate ttyS%d for SCC channel A\n", req.line ); + } + + restore_flags(flags); + + return( nr > 0 ? 0 : -ENODEV ); +} + +/* Hooks for running a serial console. con_init() calls this if the + * console is being run over one of the serial ports. + * 'channel' is decoded as 0=modem 1=printer, 'chip' is ignored. + */ +void +rs_cons_hook(int chip, int out, int channel) +{ + if (zs_chain == 0) + probe_sccs(); + zs_soft[channel].private->clk_divisor = 16; + zs_soft[channel].private->zs_baud = get_zsbaud(&zs_soft[channel]); + rs_cons_check(&zs_soft[channel], channel); + if (out) + zs_cons_chanout = channel; + else + zs_cons_chanin = channel; + + /* FIXME : register interrupt here??? */ +} + +/* This is called at boot time to prime the kgdb serial debugging + * serial line. The 'tty_num' argument is 0 for /dev/ttyS0 and 1 + * for /dev/ttyS1 which is determined in setup_arch() from the + * boot command line flags. + */ +void +rs_kgdb_hook(int tty_num) +{ + if (zs_chain == 0) + probe_sccs(); + zs_kgdbchan = zs_soft[tty_num].private->zs_channel; + zs_soft[tty_num].private->clk_divisor = 16; + zs_soft[tty_num].private->zs_baud = get_zsbaud(&zs_soft[tty_num]); + zs_soft[tty_num].private->kgdb_channel = 1; /* This runs kgdb */ + zs_soft[tty_num ^ 1].private->kgdb_channel = 0; /* This does not */ + /* Turn on transmitter/receiver at 8-bits/char */ + kgdb_chaninit(&zs_soft[tty_num], 0, 9600); + ZS_CLEARERR(zs_kgdbchan); + ZS_CLEARFIFO(zs_kgdbchan); + + /* FIXME : register interrupt here??? */ +} + diff -u --recursive --new-file v2.1.105/linux/drivers/char/mac_SCC.h linux/drivers/char/mac_SCC.h --- v2.1.105/linux/drivers/char/mac_SCC.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/mac_SCC.h Sat Jun 13 13:44:30 1998 @@ -0,0 +1,321 @@ +/* + * macserial.h: Definitions for the Macintosh Z8530 serial driver. + * + * Adapted from drivers/sbus/char/sunserial.h by Paul Mackerras. + * + * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au) + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ +#ifndef _MAC_SCC_H +#define _MAC_SCC_H + +/* + * For the close wait times, 0 means wait forever for serial port to + * flush its output. 65535 means don't wait at all. + */ +#define ZILOG_CLOSING_WAIT_INF 0 +#define ZILOG_CLOSING_WAIT_NONE 65535 + +/* + * Definitions for ZILOG_struct (and serial_struct) flags field + */ +#define ZILOG_HUP_NOTIFY 0x0001 /* Notify getty on hangups and closes + on the callout port */ +#define ZILOG_FOURPORT 0x0002 /* Set OU1, OUT2 per AST Fourport settings */ +#define ZILOG_SAK 0x0004 /* Secure Attention Key (Orange book) */ +#define ZILOG_SPLIT_TERMIOS 0x0008 /* Separate termios for dialin/callout */ + +#define ZILOG_SPD_MASK 0x0030 +#define ZILOG_SPD_HI 0x0010 /* Use 56000 instead of 38400 bps */ + +#define ZILOG_SPD_VHI 0x0020 /* Use 115200 instead of 38400 bps */ +#define ZILOG_SPD_CUST 0x0030 /* Use user-specified divisor */ + +#define ZILOG_SKIP_TEST 0x0040 /* Skip UART test during autoconfiguration */ +#define ZILOG_AUTO_IRQ 0x0080 /* Do automatic IRQ during autoconfiguration */ +#define ZILOG_SESSION_LOCKOUT 0x0100 /* Lock out cua opens based on session */ +#define ZILOG_PGRP_LOCKOUT 0x0200 /* Lock out cua opens based on pgrp */ +#define ZILOG_CALLOUT_NOHUP 0x0400 /* Don't do hangups for cua device */ + +#define ZILOG_FLAGS 0x0FFF /* Possible legal ZILOG flags */ +#define ZILOG_USR_MASK 0x0430 /* Legal flags that non-privileged + * users can set or reset */ + +/* Internal flags used only by kernel/chr_drv/serial.c */ +#define ZILOG_INITIALIZED 0x80000000 /* Serial port was initialized */ +#define ZILOG_CALLOUT_ACTIVE 0x40000000 /* Call out device is active */ +#define ZILOG_NORMAL_ACTIVE 0x20000000 /* Normal device is active */ +#define ZILOG_BOOT_AUTOCONF 0x10000000 /* Autoconfigure port on bootup */ +#define ZILOG_CLOSING 0x08000000 /* Serial port is closing */ +#define ZILOG_CTS_FLOW 0x04000000 /* Do CTS flow control */ +#define ZILOG_CHECK_CD 0x02000000 /* i.e., CLOCAL */ + +/* Software state per channel */ + +#ifdef __KERNEL__ +/* + * This is our internal structure for each serial port's state. + * + * Many fields are paralleled by the structure used by the serial_struct + * structure. + * + * For definitions of the flags field, see tty.h + */ + +/* MSch: gone to */ + +#define SERIAL_MAGIC 0x5301 + +/* + * The size of the serial xmit buffer is 1 page, or 4096 bytes + */ +#define SERIAL_XMIT_SIZE 4096 + +/* + * Events are used to schedule things to happen at timer-interrupt + * time, instead of at rs interrupt time. + */ +#define RS_EVENT_WRITE_WAKEUP 0 + +#endif /* __KERNEL__ */ + +/* Conversion routines to/from brg time constants from/to bits + * per second. + */ +#define BRG_TO_BPS(brg, freq) ((freq) / 2 / ((brg) + 2)) +#define BPS_TO_BRG(bps, freq) ((((freq) + (bps)) / (2 * (bps))) - 2) + +/* The Zilog register set */ + +#define FLAG 0x7e + +/* Write Register 0 */ +#define R0 0 /* Register selects */ +#define R1 1 +#define R2 2 +#define R3 3 +#define R4 4 +#define R5 5 +#define R6 6 +#define R7 7 +#define R8 8 +#define R9 9 +#define R10 10 +#define R11 11 +#define R12 12 +#define R13 13 +#define R14 14 +#define R15 15 + +#define NULLCODE 0 /* Null Code */ +#define POINT_HIGH 0x8 /* Select upper half of registers */ +#define RES_EXT_INT 0x10 /* Reset Ext. Status Interrupts */ +#define SEND_ABORT 0x18 /* HDLC Abort */ +#define RES_RxINT_FC 0x20 /* Reset RxINT on First Character */ +#define RES_Tx_P 0x28 /* Reset TxINT Pending */ +#define ERR_RES 0x30 /* Error Reset */ +#define RES_H_IUS 0x38 /* Reset highest IUS */ + +#define RES_Rx_CRC 0x40 /* Reset Rx CRC Checker */ +#define RES_Tx_CRC 0x80 /* Reset Tx CRC Checker */ +#define RES_EOM_L 0xC0 /* Reset EOM latch */ + +/* Write Register 1 */ + +#define EXT_INT_ENAB 0x1 /* Ext Int Enable */ +#define TxINT_ENAB 0x2 /* Tx Int Enable */ +#define PAR_SPEC 0x4 /* Parity is special condition */ + +#define RxINT_DISAB 0 /* Rx Int Disable */ +#define RxINT_FCERR 0x8 /* Rx Int on First Character Only or Error */ +#define INT_ALL_Rx 0x10 /* Int on all Rx Characters or error */ +#define INT_ERR_Rx 0x18 /* Int on error only */ + +#define WT_RDY_RT 0x20 /* Wait/Ready on R/T */ +#define WT_FN_RDYFN 0x40 /* Wait/FN/Ready FN */ +#define WT_RDY_ENAB 0x80 /* Wait/Ready Enable */ + +/* Write Register #2 (Interrupt Vector) */ + +/* Write Register 3 */ + +#define RxENABLE 0x1 /* Rx Enable */ +#define SYNC_L_INH 0x2 /* Sync Character Load Inhibit */ +#define ADD_SM 0x4 /* Address Search Mode (SDLC) */ +#define RxCRC_ENAB 0x8 /* Rx CRC Enable */ +#define ENT_HM 0x10 /* Enter Hunt Mode */ +#define AUTO_ENAB 0x20 /* Auto Enables */ +#define Rx5 0x0 /* Rx 5 Bits/Character */ +#define Rx7 0x40 /* Rx 7 Bits/Character */ +#define Rx6 0x80 /* Rx 6 Bits/Character */ +#define Rx8 0xc0 /* Rx 8 Bits/Character */ +#define RxNBITS_MASK 0xc0 + +/* Write Register 4 */ + +#define PAR_ENA 0x1 /* Parity Enable */ +#define PAR_EVEN 0x2 /* Parity Even/Odd* */ + +#define SYNC_ENAB 0 /* Sync Modes Enable */ +#define SB1 0x4 /* 1 stop bit/char */ +#define SB15 0x8 /* 1.5 stop bits/char */ +#define SB2 0xc /* 2 stop bits/char */ +#define SB_MASK 0xc + +#define MONSYNC 0 /* 8 Bit Sync character */ +#define BISYNC 0x10 /* 16 bit sync character */ +#define SDLC 0x20 /* SDLC Mode (01111110 Sync Flag) */ +#define EXTSYNC 0x30 /* External Sync Mode */ + +#define X1CLK 0x0 /* x1 clock mode */ +#define X16CLK 0x40 /* x16 clock mode */ +#define X32CLK 0x80 /* x32 clock mode */ +#define X64CLK 0xC0 /* x64 clock mode */ +#define XCLK_MASK 0xC0 + +/* Write Register 5 */ + +#define TxCRC_ENAB 0x1 /* Tx CRC Enable */ +#define RTS 0x2 /* RTS */ +#define SDLC_CRC 0x4 /* SDLC/CRC-16 */ +#define TxENAB 0x8 /* Tx Enable */ +#define SND_BRK 0x10 /* Send Break */ +#define Tx5 0x0 /* Tx 5 bits (or less)/character */ +#define Tx7 0x20 /* Tx 7 bits/character */ +#define Tx6 0x40 /* Tx 6 bits/character */ +#define Tx8 0x60 /* Tx 8 bits/character */ +#define TxNBITS_MASK 0x60 +#define DTR 0x80 /* DTR */ + +/* Write Register 6 (Sync bits 0-7/SDLC Address Field) */ + +/* Write Register 7 (Sync bits 8-15/SDLC 01111110) */ + +/* Write Register 8 (transmit buffer) */ + +/* Write Register 9 (Master interrupt control) */ +#define VIS 1 /* Vector Includes Status */ +#define NV 2 /* No Vector */ +#define DLC 4 /* Disable Lower Chain */ +#define MIE 8 /* Master Interrupt Enable */ +#define STATHI 0x10 /* Status high */ +#define NORESET 0 /* No reset on write to R9 */ +#define CHRB 0x40 /* Reset channel B */ +#define CHRA 0x80 /* Reset channel A */ +#define FHWRES 0xc0 /* Force hardware reset */ + +/* Write Register 10 (misc control bits) */ +#define BIT6 1 /* 6 bit/8bit sync */ +#define LOOPMODE 2 /* SDLC Loop mode */ +#define ABUNDER 4 /* Abort/flag on SDLC xmit underrun */ +#define MARKIDLE 8 /* Mark/flag on idle */ +#define GAOP 0x10 /* Go active on poll */ +#define NRZ 0 /* NRZ mode */ +#define NRZI 0x20 /* NRZI mode */ +#define FM1 0x40 /* FM1 (transition = 1) */ +#define FM0 0x60 /* FM0 (transition = 0) */ +#define CRCPS 0x80 /* CRC Preset I/O */ + +/* Write Register 11 (Clock Mode control) */ +#define TRxCXT 0 /* TRxC = Xtal output */ +#define TRxCTC 1 /* TRxC = Transmit clock */ +#define TRxCBR 2 /* TRxC = BR Generator Output */ +#define TRxCDP 3 /* TRxC = DPLL output */ +#define TRxCOI 4 /* TRxC O/I */ +#define TCRTxCP 0 /* Transmit clock = RTxC pin */ +#define TCTRxCP 8 /* Transmit clock = TRxC pin */ +#define TCBR 0x10 /* Transmit clock = BR Generator output */ +#define TCDPLL 0x18 /* Transmit clock = DPLL output */ +#define RCRTxCP 0 /* Receive clock = RTxC pin */ +#define RCTRxCP 0x20 /* Receive clock = TRxC pin */ +#define RCBR 0x40 /* Receive clock = BR Generator output */ +#define RCDPLL 0x60 /* Receive clock = DPLL output */ +#define RTxCX 0x80 /* RTxC Xtal/No Xtal */ + +/* Write Register 12 (lower byte of baud rate generator time constant) */ + +/* Write Register 13 (upper byte of baud rate generator time constant) */ + +/* Write Register 14 (Misc control bits) */ +#define BRENABL 1 /* Baud rate generator enable */ +#define BRSRC 2 /* Baud rate generator source */ +#define DTRREQ 4 /* DTR/Request function */ +#define AUTOECHO 8 /* Auto Echo */ +#define LOOPBAK 0x10 /* Local loopback */ +#define SEARCH 0x20 /* Enter search mode */ +#define RMC 0x40 /* Reset missing clock */ +#define DISDPLL 0x60 /* Disable DPLL */ +#define SSBR 0x80 /* Set DPLL source = BR generator */ +#define SSRTxC 0xa0 /* Set DPLL source = RTxC */ +#define SFMM 0xc0 /* Set FM mode */ +#define SNRZI 0xe0 /* Set NRZI mode */ + +/* Write Register 15 (external/status interrupt control) */ +#define ZCIE 2 /* Zero count IE */ +#define DCDIE 8 /* DCD IE */ +#define SYNCIE 0x10 /* Sync/hunt IE */ +#define CTSIE 0x20 /* CTS IE */ +#define TxUIE 0x40 /* Tx Underrun/EOM IE */ +#define BRKIE 0x80 /* Break/Abort IE */ + + +/* Read Register 0 */ +#define Rx_CH_AV 0x1 /* Rx Character Available */ +#define ZCOUNT 0x2 /* Zero count */ +#define Tx_BUF_EMP 0x4 /* Tx Buffer empty */ +#define DCD 0x8 /* DCD */ +#define SYNC_HUNT 0x10 /* Sync/hunt */ +#define CTS 0x20 /* CTS */ +#define TxEOM 0x40 /* Tx underrun */ +#define BRK_ABRT 0x80 /* Break/Abort */ + +/* Read Register 1 */ +#define ALL_SNT 0x1 /* All sent */ +/* Residue Data for 8 Rx bits/char programmed */ +#define RES3 0x8 /* 0/3 */ +#define RES4 0x4 /* 0/4 */ +#define RES5 0xc /* 0/5 */ +#define RES6 0x2 /* 0/6 */ +#define RES7 0xa /* 0/7 */ +#define RES8 0x6 /* 0/8 */ +#define RES18 0xe /* 1/8 */ +#define RES28 0x0 /* 2/8 */ +/* Special Rx Condition Interrupts */ +#define PAR_ERR 0x10 /* Parity error */ +#define Rx_OVR 0x20 /* Rx Overrun Error */ +#define FRM_ERR 0x40 /* CRC/Framing Error */ +#define END_FR 0x80 /* End of Frame (SDLC) */ + +/* Read Register 2 (channel b only) - Interrupt vector */ + +/* Read Register 3 (interrupt pending register) ch a only */ +#define CHBEXT 0x1 /* Channel B Ext/Stat IP */ +#define CHBTxIP 0x2 /* Channel B Tx IP */ +#define CHBRxIP 0x4 /* Channel B Rx IP */ +#define CHAEXT 0x8 /* Channel A Ext/Stat IP */ +#define CHATxIP 0x10 /* Channel A Tx IP */ +#define CHARxIP 0x20 /* Channel A Rx IP */ + +/* Read Register 8 (receive data register) */ + +/* Read Register 10 (misc status bits) */ +#define ONLOOP 2 /* On loop */ +#define LOOPSEND 0x10 /* Loop sending */ +#define CLK2MIS 0x40 /* Two clocks missing */ +#define CLK1MIS 0x80 /* One clock missing */ + +/* Read Register 12 (lower byte of baud rate generator constant) */ + +/* Read Register 13 (upper byte of baud rate generator constant) */ + +/* Read Register 15 (value of WR 15) */ + +/* Misc macros */ +#define ZS_CLEARERR(channel) (write_zsreg(channel, 0, ERR_RES)) +#define ZS_CLEARFIFO(channel) do { volatile unsigned char garbage; \ + garbage = read_zsdata(channel); \ + garbage = read_zsdata(channel); \ + garbage = read_zsdata(channel); \ + } while(0) + +#endif /* !(_MAC_SCC_H) */ diff -u --recursive --new-file v2.1.105/linux/drivers/char/mem.c linux/drivers/char/mem.c --- v2.1.105/linux/drivers/char/mem.c Tue Jun 9 11:57:29 1998 +++ linux/drivers/char/mem.c Sat Jun 13 12:10:30 1998 @@ -27,8 +27,14 @@ #include #ifdef CONFIG_SOUND +void soundcore_init(void); +#ifdef CONFIG_SOUND_OSS void soundcard_init(void); #endif +#ifdef CONFIG_DMASOUND +void dmasound_init(void); +#endif +#endif #ifdef CONFIG_ISDN int isdn_init(void); #endif @@ -539,6 +545,9 @@ soundcore_init(); #ifdef CONFIG_SOUND_OSS soundcard_init(); +#endif +#ifdef CONFIG_DMASOUND + dmasound_init(); #endif #endif #ifdef CONFIG_JOYSTICK diff -u --recursive --new-file v2.1.105/linux/drivers/char/misc.c linux/drivers/char/misc.c --- v2.1.105/linux/drivers/char/misc.c Thu May 14 19:47:39 1998 +++ linux/drivers/char/misc.c Sat Jun 13 13:44:30 1998 @@ -72,6 +72,7 @@ extern int amiga_mouse_init(void); extern int atari_mouse_init(void); extern int sun_mouse_init(void); +extern int adb_mouse_init(void); extern void watchdog_init(void); extern void wdt_init(void); extern void acq_init(void); @@ -223,6 +224,9 @@ #ifdef CONFIG_SUN_MOUSE sun_mouse_init(); #endif +#ifdef CONFIG_MACMOUSE + adb_mouse_init(); +#endif #ifdef CONFIG_PC110_PAD pc110pad_init(); #endif @@ -250,7 +254,7 @@ #ifdef CONFIG_H8 h8_init(); #endif -#ifdef CONFIG_RTC +#if defined(CONFIG_RTC) || defined(CONFIG_SUN_MOSTEK_RTC) rtc_init(); #endif #ifdef CONFIG_ATARI_DSP56K diff -u --recursive --new-file v2.1.105/linux/drivers/char/msp3400.c linux/drivers/char/msp3400.c --- v2.1.105/linux/drivers/char/msp3400.c Tue Jun 9 11:57:29 1998 +++ linux/drivers/char/msp3400.c Tue Jun 9 01:21:49 1998 @@ -916,7 +916,7 @@ if (-1 == msp3400c_reset(msp->bus)) { UNLOCK_I2C_BUS(msp->bus); kfree(msp); - return -1; + return -EIO; } msp3400c_setmode(msp, MSP_MODE_FM_TERRA); @@ -1088,6 +1088,8 @@ msp3400c_detach, msp3400c_command }; + +EXPORT_NO_SYMBOLS; #ifdef MODULE int init_module(void) diff -u --recursive --new-file v2.1.105/linux/drivers/char/nvram.c linux/drivers/char/nvram.c --- v2.1.105/linux/drivers/char/nvram.c Thu May 7 22:51:49 1998 +++ linux/drivers/char/nvram.c Sat Jun 13 13:44:30 1998 @@ -156,7 +156,7 @@ * * They're only built if CONFIG_ATARI is defined, because Atari drivers use * them. For other configurations (PC), the rest of the kernel can't rely on - * them being present (this driver couldn't be configured at all, or as a + * them being present (this driver may not be configured at all, or as a * module), so they access config information themselves. */ @@ -227,12 +227,15 @@ return( (offset >= 0) ? (file->f_pos = offset) : -EINVAL ); } -static ssize_t nvram_read( struct file * file, - char * buf, size_t count, loff_t *ppos ) +static ssize_t nvram_read(struct file * file, + char * buf, size_t count, loff_t *ppos ) { unsigned long flags; unsigned i = *ppos; char *tmp = buf; + + if (i != *ppos) + return -EINVAL; save_flags(flags); cli(); @@ -250,12 +253,16 @@ return( tmp - buf ); } -static ssize_t nvram_write( struct file * file, const char * buf, size_t count, loff_t *ppos ) +static ssize_t nvram_write(struct file * file, + const char * buf, size_t count, loff_t *ppos ) { unsigned long flags; unsigned i = *ppos; const char *tmp = buf; char c; + + if (i != *ppos) + return -EINVAL; save_flags(flags); cli(); @@ -411,7 +418,7 @@ if (!CHECK_DRIVER_INIT()) return( -ENXIO ); - printk( "Non-volatile memory driver v%s\n", NVRAM_VERSION ); + printk(KERN_INFO "Non-volatile memory driver v%s\n", NVRAM_VERSION ); misc_register( &nvram_dev ); #ifdef CONFIG_PROC_FS if ((proc_nvram = create_proc_entry( "nvram", 0, 0 ))) @@ -618,7 +625,7 @@ #define fieldsize(a) (sizeof(a)/sizeof(*a)) static int atari_proc_infos( unsigned char *nvram, char *buffer, int *len, - off_t *begin, off_t offset, int size ) + off_t *begin, off_t offset, int size ) { int checksum = nvram_check_checksum(); int i; @@ -645,7 +652,7 @@ /* the following entries are defined only for the Falcon */ if ((atari_mch_cookie >> 16) != ATARI_MCH_FALCON) - return; + return 1; PRINT_PROC( "OS language : " ); if (nvram[6] < fieldsize(languages)) diff -u --recursive --new-file v2.1.105/linux/drivers/char/pc_keyb.c linux/drivers/char/pc_keyb.c --- v2.1.105/linux/drivers/char/pc_keyb.c Sun Jun 7 11:16:30 1998 +++ linux/drivers/char/pc_keyb.c Sat Jun 13 13:44:30 1998 @@ -178,6 +178,20 @@ | KBD_MODE_DISABLE_MOUSE | KBD_MODE_KCC); + /* ibm powerpc portables need this to use scan-code set 1 -- Cort */ + kbd_write(KBD_CNTL_REG, KBD_CCMD_READ_MODE); + if (!(kbd_wait_for_input() & KBD_MODE_KCC)) { + /* + * If the controller does not support conversion, + * Set the keyboard to scan-code set 1. + */ + kbd_write(KBD_DATA_REG, 0xF0); + kbd_wait_for_input(); + kbd_write(KBD_DATA_REG, 0x01); + kbd_wait_for_input(); + } + + kbd_write(KBD_DATA_REG, KBD_CMD_ENABLE); if (kbd_wait_for_input() != KBD_REPLY_ACK) return "Enable keyboard: no ACK"; diff -u --recursive --new-file v2.1.105/linux/drivers/char/radio-aimslab.c linux/drivers/char/radio-aimslab.c --- v2.1.105/linux/drivers/char/radio-aimslab.c Tue Jun 9 11:57:29 1998 +++ linux/drivers/char/radio-aimslab.c Sat Jun 13 10:26:27 1998 @@ -1,6 +1,7 @@ /* radiotrack (radioreveal) driver for Linux radio support * (c) 1997 M. Kirkwood * Coverted to new API by Alan Cox + * Various bugfixes and enhancements by Russell Kroll * * TODO: Allow for more than one of these foolish entities :-) * @@ -47,7 +48,7 @@ /* local things */ -static void sleep_delay(int n) +static void sleep_delay(long n) { /* Sleep nicely for 'n' uS */ int d=n/1000000/HZ; @@ -61,108 +62,129 @@ schedule(); } } - -/* Clock out data to the chip. This looks suspiciously like i2c as usual */ - -static void outbits(int bits, int data, int port) -{ - while(bits--) - { - if(data & 1) - { - outw(5, port); - outw(5, port); - outw(7, port); - outw(7, port); - } - else - { - outw(1, port); - outw(1, port); - outw(3, port); - outw(3, port); - } - data>>=1; - } -} -static void rt_decvol(int port) +static void rt_decvol(void) { - outb(0x48, port); + outb(0x58, io); /* volume down + sigstr + on */ sleep_delay(100000); - outb(0xc8, port); + outb(0xd8, io); /* volume steady + sigstr + on */ } -static void rt_incvol(int port) +static void rt_incvol(void) { - outb(0x88, port); + outb(0x98, io); /* volume up + sigstr + on */ sleep_delay(100000); - outb(0xc8, port); + outb(0xd8, io); /* volume steady + sigstr + on */ } -static void rt_mute(int port) +static void rt_mute(void) { - outb(0, port); - outb(0xc0, port); -} - -static void rt_unmute(int port) -{ - outb(0, port); - outb(0xc8, port); + outb(0x48, io); /* volume down but still "on" */ + sleep_delay(2000000); /* make sure it's totally down */ + outb(0xc0, io); /* volume steady, off */ } static int rt_setvol(struct rt_device *dev, int vol) { int i; - if(vol == dev->curvol) + + if(vol == dev->curvol) /* no change needed */ return 0; - if(vol == 0) - rt_mute(dev->port); + if(vol == 0) { /* volume = 0 means mute the card */ + rt_mute(); + dev->curvol = 0; + return 0; + } if(vol > dev->curvol) - for(i = dev->curvol; i < vol; i++) - rt_incvol(dev->port); + for(i = dev->curvol; i < vol; i++) + rt_incvol(); else - for(i = dev->curvol; i > vol; i--) - rt_decvol(dev->port); + for(i = dev->curvol; i > vol; i--) + rt_decvol(); - if(dev->curvol == 0) - rt_unmute(dev->port); + dev->curvol = vol; return 0; } -static int rt_setfreq(struct rt_device *dev, unsigned long frequency) +/* the 128+64 on these outb's is to keep the volume stable while tuning + * without them, the volume _will_ creep up with each frequency change + * and bit 4 (+16) is to keep the signal strength meter enabled + */ + +void send_0_byte(int port, struct rt_device *dev) +{ + if (dev->curvol == 0) { + outb_p(128+64+16+ 1, port); /* wr-enable + data low */ + outb_p(128+64+16+2+1, port); /* clock */ + } + else { + outb_p(128+64+16+8+ 1, port); /* on + wr-enable + data low */ + outb_p(128+64+16+8+2+1, port); /* clock */ + } + sleep_delay(1000); +} + +void send_1_byte(int port, struct rt_device *dev) { - int myport = dev->port; -#define RTRACK_ENCODE(x) (((((x)*2)/5)-(40*88))+0xf6c) - outbits(16, RTRACK_ENCODE(frequency), myport); - outbits(8, 0xa0, myport); -/* XXX - get rid of this once setvol is implemented properly - XXX */ -/* these insist on turning the thing on. not sure I approve... */ - udelay(1000); - outb(0, myport); - outb(0xc8, myport); + if (dev->curvol == 0) { + outb_p(128+64+16+4 +1, port); /* wr-enable+data high */ + outb_p(128+64+16+4+2+1, port); /* clock */ + } + else { + outb_p(128+64+16+8+4 +1, port); /* on+wr-enable+data high */ + outb_p(128+64+16+8+4+2+1, port); /* clock */ + } - return 0; + sleep_delay(1000); } -int rt_getsigstr(struct rt_device *dev) +static int rt_setfreq(struct rt_device *dev, unsigned long freq) { - int res; - int myport = dev->port; + int i; - outb(0xf8, myport); - sleep_delay(200000); - res = (int)inb(myport); - sleep_delay(10000); - outb(0xe8, myport); - if(res == 0xfd) - return 1; + /* adapted from radio-aztech.c */ + + freq = (freq / 16.0) * 100; /* massage the data a little */ + freq += 1070; /* IF = 10.7 MHz */ + freq /= 5; /* ref = 25 kHz */ + + send_0_byte (io, dev); /* 0: LSB of frequency */ + + for (i = 0; i < 13; i++) /* : frequency bits (1-13) */ + if (freq & (1 << i)) + send_1_byte (io, dev); + else + send_0_byte (io, dev); + + send_0_byte (io, dev); /* 14: test bit - always 0 */ + send_0_byte (io, dev); /* 15: test bit - always 0 */ + + send_0_byte (io, dev); /* 16: band data 0 - always 0 */ + send_0_byte (io, dev); /* 17: band data 1 - always 0 */ + send_0_byte (io, dev); /* 18: band data 2 - always 0 */ + send_0_byte (io, dev); /* 19: time base - always 0 */ + + send_0_byte (io, dev); /* 20: spacing (0 = 25 kHz) */ + send_1_byte (io, dev); /* 21: spacing (1 = 25 kHz) */ + send_0_byte (io, dev); /* 22: spacing (0 = 25 kHz) */ + send_1_byte (io, dev); /* 23: AM/FM (FM = 1, always) */ + + if (dev->curvol == 0) + outb (0xd0, io); /* volume steady + sigstr */ else + outb (0xd8, io); /* volume steady + sigstr + on */ + + return 0; +} + +int rt_getsigstr(struct rt_device *dev) +{ + if (inb(io) & 2) /* bit set = no signal present */ return 0; + return 1; /* signal present */ } static int rt_ioctl(struct video_device *dev, unsigned int cmd, void *arg) @@ -226,7 +248,7 @@ struct video_audio v; memset(&v,0, sizeof(v)); v.flags|=VIDEO_AUDIO_MUTABLE|VIDEO_AUDIO_VOLUME; - v.volume=rt->curvol; + v.volume=rt->curvol * 6554; strcpy(v.name, "Radio"); if(copy_to_user(arg,&v, sizeof(v))) return -EFAULT; @@ -239,12 +261,14 @@ return -EFAULT; if(v.audio) return -EINVAL; - rt->curvol=v.volume; - if(v.flags&VIDEO_AUDIO_MUTE) - rt_mute(rt->port); + if(v.flags&VIDEO_AUDIO_MUTE) { + rt_mute(); + rt->curvol=0; + } else - rt_setvol(rt,rt->curvol/6554); + rt_setvol(rt,v.volume/6554); + return 0; } default: @@ -299,7 +323,8 @@ request_region(io, 2, "rtrack"); printk(KERN_INFO "AIMSlab Radiotrack/radioreveal card driver.\n"); /* mute card - prevents noisy bootups */ - rt_mute(io); + rt_mute(); + rtrack_unit.curvol = 0; return 0; } diff -u --recursive --new-file v2.1.105/linux/drivers/char/random.c linux/drivers/char/random.c --- v2.1.105/linux/drivers/char/random.c Sun Jun 7 11:16:30 1998 +++ linux/drivers/char/random.c Sat Jun 13 11:38:49 1998 @@ -513,6 +513,10 @@ do_gettimeofday(&tv); add_entropy_words(r, tv.tv_sec, tv.tv_usec); + /* + * This doesnt lock system.utsname. Howeve we are generating + * entropy so a race with a name set here is fine. + */ p = (__u32 *)&system_utsname; for (i = sizeof(system_utsname) / sizeof(words); i; i--) { memcpy(words, p, sizeof(words)); diff -u --recursive --new-file v2.1.105/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c --- v2.1.105/linux/drivers/char/tty_io.c Sun Jun 7 11:16:30 1998 +++ linux/drivers/char/tty_io.c Sat Jun 13 13:44:30 1998 @@ -123,6 +123,10 @@ static int tty_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg); static int tty_fasync(struct file * filp, int on); +#ifdef CONFIG_8xx +extern long console_8xx_init(void); +extern int rs_8xx_init(void); +#endif /* CONFIG_8xx */ #ifndef MIN #define MIN(a,b) ((a) < (b) ? (a) : (b)) @@ -2055,6 +2059,9 @@ #ifdef CONFIG_SERIAL rs_init(); #endif +#ifdef CONFIG_MAC_SERIAL + macserial_init(); +#endif #ifdef CONFIG_ROCKETPORT rp_init(); #endif @@ -2079,6 +2086,9 @@ #ifdef CONFIG_SPECIALIX specialix_init(); #endif +#ifdef CONFIG_8xx + rs_8xx_init(); +#endif /* CONFIG_8xx */ pty_init(); #ifdef CONFIG_VT vcs_init(); diff -u --recursive --new-file v2.1.105/linux/drivers/char/tuner.c linux/drivers/char/tuner.c --- v2.1.105/linux/drivers/char/tuner.c Wed Apr 8 19:36:26 1998 +++ linux/drivers/char/tuner.c Tue Jun 9 01:21:49 1998 @@ -243,6 +243,8 @@ tuner_command }; +EXPORT_NO_SYMBOLS; + #ifdef MODULE int init_module(void) #else diff -u --recursive --new-file v2.1.105/linux/drivers/dio/Makefile linux/drivers/dio/Makefile --- v2.1.105/linux/drivers/dio/Makefile Wed Dec 31 16:00:00 1969 +++ linux/drivers/dio/Makefile Sat Jun 13 13:14:31 1998 @@ -0,0 +1,19 @@ +# +# Makefile for the linux kernel. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definitions are now in the main makefile... +# +# NB: cribbed from the drivers/sbus/Makefile -- PMM + +SUB_DIRS := +MOD_SUB_DIRS := $(SUB_DIRS) +ALL_SUB_DIRS := $(SUB_DIRS) + +L_OBJS := dio.o +L_TARGET := dio.a + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.105/linux/drivers/dio/dio.c linux/drivers/dio/dio.c --- v2.1.105/linux/drivers/dio/dio.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/dio/dio.c Sat Jun 13 13:14:31 1998 @@ -0,0 +1,292 @@ +/* Code to support devices on the DIO (and eventually DIO-II) bus + * Copyright (C) 05/1998 Peter Maydell + * + * This code has basically these routines at the moment: + * int dio_find(u_int deviceid) + * Search the list of DIO devices and return the select code + * of the next unconfigured device found that matches the given device ID. + * Note that the deviceid parameter should be the encoded ID. + * This means that framebuffers should pass it as + * DIO_ENCODE_ID(DIO_ID_FBUFFER,DIO_ID2_TOPCAT) + * (or whatever); everybody else just uses DIO_ID_FOOBAR. + * void *dio_scodetoviraddr(int scode) + * Return the virtual address corresponding to the given select code. + * NB: DIO-II devices will have to be mapped in in this routine! + * int dio_scodetoipl(int scode) + * Every DIO card has a fixed interrupt priority level. This function + * returns it, whatever it is. + * const char *dio_scodetoname(int scode) + * Return a character string describing this board [might be "" if + * not CONFIG_DIO_CONSTANTS] + * void dio_config_board(int scode) mark board as configured in the list + * void dio_unconfig_board(int scode) mark board as no longer configured + * + * This file is based on the way the Amiga port handles Zorro II cards, + * although we aren't so complicated... + */ +#include +#include +#include +#include +#include /* kmalloc() */ +#include +#include /* hwreg_present() */ +#include /* readb() */ +/* not a real config option yet! */ +#define CONFIG_DIO_CONSTANTS + +#ifdef CONFIG_DIO_CONSTANTS +/* We associate each numeric ID with an appropriate descriptive string + * using a constant array of these structs. + * FIXME: we should be able to arrange to throw away most of the strings + * using the initdata stuff. Then we wouldn't need to worry about + * carrying them around... + * I think we do this by copying them into newly kmalloc()ed memory and + * marking the names[] array as .initdata ? + */ +struct dioname +{ + int id; + const char *name; +}; + +/* useful macro */ +#define DIONAME(x) { DIO_ID_##x, DIO_DESC_##x } +#define DIOFBNAME(x) { DIO_ENCODE_ID( DIO_ID_FBUFFER, DIO_ID2_##x), DIO_DESC2_##x } + +static struct dioname names[] = +{ + DIONAME(DCA0), DIONAME(DCA0REM), DIONAME(DCA1), DIONAME(DCA1REM), + DIONAME(DCM), DIONAME(DCMREM), + DIONAME(LAN), + DIONAME(FHPIB), DIONAME(NHPIB), DIONAME(IHPIB), + DIONAME(SCSI0), DIONAME(SCSI1), DIONAME(SCSI2), DIONAME(SCSI3), + DIONAME(FBUFFER), + DIONAME(PARALLEL), DIONAME(VME), DIONAME(DCL), DIONAME(DCLREM), + DIONAME(MISC0), DIONAME(MISC1), DIONAME(MISC2), DIONAME(MISC3), + DIONAME(MISC4), DIONAME(MISC5), DIONAME(MISC6), DIONAME(MISC7), + DIONAME(MISC8), DIONAME(MISC9), DIONAME(MISC10), DIONAME(MISC11), + DIONAME(MISC12), DIONAME(MISC13), + DIOFBNAME(GATORBOX), DIOFBNAME(TOPCAT), DIOFBNAME(RENAISSANCE), + DIOFBNAME(LRCATSEYE), DIOFBNAME(HRCCATSEYE), DIOFBNAME(HRMCATSEYE), + DIOFBNAME(DAVINCI), DIOFBNAME(XXXCATSEYE), DIOFBNAME(HYPERION), + DIOFBNAME(XGENESIS), DIOFBNAME(TIGER), DIOFBNAME(YGENESIS) +}; + +#undef DIONAME +#undef DIOFBNAME + +#define NUMNAMES (sizeof(names) / sizeof(struct dioname)) + +static const char *unknowndioname + = "unknown DIO board -- please email !"; + +static const char *dio_getname(int id) +{ + /* return pointer to a constant string describing the board with given ID */ + unsigned int i; + for (i = 0; i < NUMNAMES; i++) + if (names[i].id == id) + return names[i].name; + + return unknowndioname; +} + +#else + +static char dio_no_name[] = { 0 }; +#define dio_getname(_id) (dio_no_name) + +#endif /* CONFIG_DIO_CONSTANTS */ + +/* We represent all the DIO boards in the system with a linked list of these structs. */ +struct dioboard +{ + struct dioboard *next; /* link to next struct in list */ + int ipl; /* IPL of this board */ + int configured; /* has this board been configured? */ + int scode; /* select code of this board */ + int id; /* encoded ID */ + const char *name; +}; + +static struct dioboard *blist = NULL; + +__initfunc(static int dio_find_slow(int deviceid)) +{ + /* Called to find a DIO device before the full bus scan has run. Basically + only used by the console driver. */ + int scode; + for (scode = 0; scode < DIO_SCMAX; scode++) + { + void *va; + + if (DIO_SCINHOLE(scode)) + continue; + + va = dio_scodetoviraddr(scode); + if (!va || !hwreg_present(va + DIO_IDOFF)) + continue; /* no board present at that select code */ + + if (DIO_ID(va) == deviceid) + return scode; + } + return 0; +} + +int dio_find(int deviceid) +{ + if (blist) + { + /* fast way */ + struct dioboard *b; + for (b = blist; b; b = b->next) + if (b->id == deviceid && b->configured == 0) + return b->scode; + return 0; + } + return dio_find_slow(deviceid); +} + +/* This is the function that scans the DIO space and works out what + * hardware is actually present. + */ +__initfunc(void dio_init(void)) +{ + int scode; + struct dioboard *b, *bprev = NULL; + + printk("Scanning for DIO devices...\n"); + + for (scode = 0; scode < DIO_SCMAX; ++scode) + { + u_char prid, secid = 0; /* primary, secondary ID bytes */ + u_char *va; + + if (DIO_SCINHOLE(scode)) + continue; + + va = dio_scodetoviraddr(scode); + if (!va || !hwreg_present(va + DIO_IDOFF)) + continue; /* no board present at that select code */ + + /* Found a board, allocate it an entry in the list */ + b = kmalloc(sizeof(struct dioboard), GFP_KERNEL); + + /* read the ID byte(s) and encode if necessary. Note workaround + * for broken internal HPIB devices... + */ + if (!DIO_ISIHPIB(scode)) + prid = DIO_ID(va); + else + prid = DIO_ID_IHPIB; + + if (DIO_NEEDSSECID(prid)) + { + secid = DIO_SECID(va); + b->id = DIO_ENCODE_ID(prid, secid); + } + else + b->id = prid; + + b->configured = 0; + b->scode = scode; + b->ipl = DIO_IPL(va); + b->name = dio_getname(b->id); + printk("select code %3d: ID %02X", scode, prid); + if (DIO_NEEDSSECID(b->id)) + printk(":%02X", secid); + printk(" %s\n", b->name); + + b->next = NULL; + + if (bprev) + bprev->next = b; + else + blist = b; + bprev = b; + } +} + +/* Bear in mind that this is called in the very early stages of initialisation + * in order to get the virtual address of the serial port for the console... + */ +void *dio_scodetoviraddr(int scode) +{ + if (scode > DIOII_SCBASE) + { + printk("dio_scodetoviraddr: don't support DIO-II yet!\n"); + return 0; + } + else if (scode > DIO_SCMAX || scode < 0) + return 0; + else if (DIO_SCINHOLE(scode)) + return 0; + else if (scode == DIO_IHPIBSCODE) /* this should really be #ifdef CONFIG_IHPIB */ + return (void*)DIO_IHPIBADDR; /* or something similar... */ + + return (void*)(DIO_VIRADDRBASE + DIO_BASE + scode * 0x10000); +} + +int dio_scodetoipl(int scode) +{ + struct dioboard *b; + for (b = blist; b; b = b->next) + if (b->scode == scode) + break; + + if (!b) + { + printk("dio_scodetoipl: bad select code %d\n", scode); + return 0; + } + else + return b->ipl; +} + +const char *dio_scodetoname(int scode) +{ + struct dioboard *b; + for (b = blist; b; b = b->next) + if (b->scode == scode) + break; + + if (!b) + { + printk("dio_scodetoname: bad select code %d\n", scode); + return NULL; + } + else + return b->name; +} + +void dio_config_board(int scode) +{ + struct dioboard *b; + for (b = blist; b; b = b->next) + if (b->scode == scode) + break; + + if (!b) + printk("dio_config_board: bad select code %d\n", scode); + else if (b->configured) + printk("dio_config_board: board at select code %d already configured\n", scode); + else + b->configured = 1; +} + +void dio_unconfig_board(int scode) +{ + struct dioboard *b; + for (b = blist; b; b = b->next) + if (b->scode == scode) + break; + + if (!b) + printk("dio_unconfig_board: bad select code %d\n", scode); + else if (!b->configured) + printk("dio_unconfig_board: board at select code %d not configured\n", + scode); + else + b->configured = 0; +} diff -u --recursive --new-file v2.1.105/linux/drivers/misc/parport_arc.c linux/drivers/misc/parport_arc.c --- v2.1.105/linux/drivers/misc/parport_arc.c Tue Jun 9 11:57:29 1998 +++ linux/drivers/misc/parport_arc.c Sat Jun 13 12:56:46 1998 @@ -82,6 +82,12 @@ arc_release_resources, arc_claim_resources, + NULL, /* epp_write_data */ + NULL, /* epp_read_data */ + NULL, /* epp_write_addr */ + NULL, /* epp_read_addr */ + NULL, /* epp_check_timeout */ + NULL, /* epp_write_block */ NULL, /* epp_read_block */ diff -u --recursive --new-file v2.1.105/linux/drivers/misc/parport_ax.c linux/drivers/misc/parport_ax.c --- v2.1.105/linux/drivers/misc/parport_ax.c Tue Jun 9 11:57:29 1998 +++ linux/drivers/misc/parport_ax.c Sat Jun 13 12:56:46 1998 @@ -39,7 +39,8 @@ #define DATA 0x00 #define STATUS 0x01 #define CONTROL 0x02 -#define EPPREG 0x04 +#define EPPADDR 0x03 +#define EPPDATA 0x04 #define CFIFO 0x400 #define DFIFO 0x400 @@ -57,13 +58,34 @@ void parport_ax_write_epp(struct parport *p, unsigned char d) { - outb(d, p->base + EPPREG); + outb(d, p->base + EPPDATA); } unsigned char parport_ax_read_epp(struct parport *p) { - return inb(p->base + EPPREG); + return inb(p->base + EPPDATA); +} + +void +parport_ax_write_epp_addr(struct parport *p, unsigned char d) +{ + outb(d, p->base + EPPADDR); +} + +unsigned char +parport_ax_read_epp_addr(struct parport *p) +{ + return inb(p->base + EPPADDR); +} + +int +parport_ax_check_epp_timeout(struct parport *p) +{ + if (!(inb(p->base+STATUS) & 1)) + return 0; + parport_ax_epp_clear_timeout(p); + return 1; } unsigned char @@ -302,6 +324,12 @@ parport_ax_release_resources, parport_ax_claim_resources, + parport_ax_write_epp, + parport_ax_read_epp, + parport_ax_write_epp_addr, + parport_ax_read_epp_addr, + parport_ax_check_epp_timeout, + parport_ax_epp_write_block, parport_ax_epp_read_block, @@ -498,7 +526,7 @@ if (!(p = parport_register_port(base, irq, dma, &parport_ax_ops))) return 0; - /* Safe away pointer to our EBus DMA */ + /* Save away pointer to our EBus DMA */ p->private_data = (void *)dev->base_address[2]; p->modes = PARPORT_MODE_PCSPP | parport_PS2_supported(p); diff -u --recursive --new-file v2.1.105/linux/drivers/misc/parport_pc.c linux/drivers/misc/parport_pc.c --- v2.1.105/linux/drivers/misc/parport_pc.c Tue Jun 9 11:57:29 1998 +++ linux/drivers/misc/parport_pc.c Sat Jun 13 12:56:46 1998 @@ -20,8 +20,8 @@ * * In addition, there are some optional registers: * - * base+3 EPP command - * base+4 EPP + * base+3 EPP address + * base+4 EPP data * base+0x400 ECP config A * base+0x401 ECP config B * base+0x402 ECP control @@ -60,12 +60,30 @@ void parport_pc_write_epp(struct parport *p, unsigned char d) { - outb(d, p->base+EPPREG); + outb(d, p->base+EPPDATA); } unsigned char parport_pc_read_epp(struct parport *p) { - return inb(p->base+EPPREG); + return inb(p->base+EPPDATA); +} + +void parport_pc_write_epp_addr(struct parport *p, unsigned char d) +{ + outb(d, p->base+EPPADDR); +} + +unsigned char parport_pc_read_epp_addr(struct parport *p) +{ + return inb(p->base+EPPADDR); +} + +int parport_pc_check_epp_timeout(struct parport *p) +{ + if (!(inb(p->base+STATUS) & 1)) + return 0; + parport_pc_epp_clear_timeout(p); + return 1; } unsigned char parport_pc_read_configb(struct parport *p) @@ -196,7 +214,7 @@ { size_t got = 0; for (; got < length; got++) { - *((char*)buf)++ = inb (p->base+EPPREG); + *((char*)buf)++ = inb (p->base+EPPDATA); if (inb (p->base+STATUS) & 0x01) break; } @@ -207,7 +225,7 @@ { size_t written = 0; for (; written < length; written++) { - outb (*((char*)buf)++, p->base+EPPREG); + outb (*((char*)buf)++, p->base+EPPDATA); if (inb (p->base+STATUS) & 0x01) break; } @@ -267,6 +285,12 @@ parport_pc_release_resources, parport_pc_claim_resources, + parport_pc_write_epp, + parport_pc_read_epp, + parport_pc_write_epp_addr, + parport_pc_read_epp_addr, + parport_pc_check_epp_timeout, + parport_pc_epp_write_block, parport_pc_epp_read_block, @@ -290,7 +314,7 @@ /* * Clear TIMEOUT BIT in EPP MODE */ -static int epp_clear_timeout(struct parport *pb) +int parport_pc_epp_clear_timeout(struct parport *pb) { unsigned char r; @@ -313,6 +337,14 @@ */ static int parport_SPP_supported(struct parport *pb) { + /* + * first clear an eventually pending EPP timeout + * I (sailer@ife.ee.ethz.ch) have an SMSC chipset + * that does not even respond to SPP cycles if an EPP + * timeout is pending + */ + parport_pc_epp_clear_timeout(pb); + /* Do a simple read-write test to make sure the port exists. */ parport_pc_write_control(pb, 0xc); parport_pc_write_data(pb, 0xaa); @@ -406,18 +438,18 @@ static int parport_EPP_supported(struct parport *pb) { /* If EPP timeout bit clear then EPP available */ - if (!epp_clear_timeout(pb)) + if (!parport_pc_epp_clear_timeout(pb)) return 0; /* No way to clear timeout */ parport_pc_write_control(pb, parport_pc_read_control(pb) | 0x20); parport_pc_write_control(pb, parport_pc_read_control(pb) | 0x10); - epp_clear_timeout(pb); + parport_pc_epp_clear_timeout(pb); parport_pc_read_epp(pb); udelay(30); /* Wait for possible EPP timeout */ if (parport_pc_read_status(pb) & 0x01) { - epp_clear_timeout(pb); + parport_pc_epp_clear_timeout(pb); return PARPORT_MODE_PCEPP; } @@ -465,7 +497,7 @@ int ok = 0; unsigned char octr = parport_pc_read_control(pb); - epp_clear_timeout(pb); + parport_pc_epp_clear_timeout(pb); parport_pc_write_control(pb, octr | 0x20); /* try to tri-state the buffer */ @@ -563,10 +595,10 @@ if (pb->modes & PARPORT_MODE_PCECR) parport_pc_frob_econtrol (pb, 0x10, 0x10); - epp_clear_timeout(pb); + parport_pc_epp_clear_timeout(pb); parport_pc_frob_control (pb, 0x20, 0x20); parport_pc_frob_control (pb, 0x10, 0x10); - epp_clear_timeout(pb); + parport_pc_epp_clear_timeout(pb); /* Device isn't expecting an EPP read * and generates an IRQ. @@ -648,12 +680,12 @@ (pb->modes & PARPORT_MODE_PCECPEPP)) pb->irq = irq_probe_EPP(pb); - epp_clear_timeout(pb); + parport_pc_epp_clear_timeout(pb); if (pb->irq == PARPORT_IRQ_NONE && (pb->modes & PARPORT_MODE_PCEPP)) pb->irq = irq_probe_EPP(pb); - epp_clear_timeout(pb); + parport_pc_epp_clear_timeout(pb); if (pb->irq == PARPORT_IRQ_NONE) pb->irq = irq_probe_SPP(pb); diff -u --recursive --new-file v2.1.105/linux/drivers/net/7990.c linux/drivers/net/7990.c --- v2.1.105/linux/drivers/net/7990.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/7990.c Sat Jun 13 13:28:34 1998 @@ -0,0 +1,651 @@ +/* + * 7990.c -- LANCE ethernet IC generic routines. + * This is an attempt to separate out the bits of various ethernet + * drivers that are common because they all use the AMD 7990 LANCE + * (Local Area Network Controller for Ethernet) chip. + * + * Copyright (C) 05/1998 Peter Maydell + * + * Most of this stuff was obtained by looking at other LANCE drivers, + * in particular a2065.[ch]. The AMD C-LANCE datasheet was also helpful. + * NB: this was made easy by the fact that Jes Sorensen had cleaned up + * most of a2025 and sunlance with the aim of merging them, so the + * common code was pretty obvious. + */ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Used for the temporal inet entries and routing */ +#include +#include + +#include + +#include +#include +#include + +#include "7990.h" + +/* Lossage Factor Nine, Mr Sulu. */ +#define WRITERAP(x) (lp->writerap(lp,x)) +#define WRITERDP(x) (lp->writerdp(lp,x)) +#define READRDP() (lp->readrdp(lp)) +/* These used to be ll->rap = x, ll->rdp = x, and (ll->rdp). Sigh. + * If you want to switch them back then + * #define DECLARE_LL volatile struct lance_regs *ll = lp->ll + */ +#define DECLARE_LL /* nothing to declare */ + +/* debugging output macros, various flavours */ +/* #define TEST_HITS */ +#ifdef UNDEF +#define PRINT_RINGS() \ +do { \ + int t; \ + for (t=0; t < RX_RING_SIZE; t++) { \ + printk("R%d: @(%02X %04X) len %04X, mblen %04X, bits %02X\n",\ + t, ib->brx_ring[t].rmd1_hadr, ib->brx_ring[t].rmd0,\ + ib->brx_ring[t].length,\ + ib->brx_ring[t].mblength, ib->brx_ring[t].rmd1_bits);\ + }\ + for (t=0; t < TX_RING_SIZE; t++) { \ + printk("T%d: @(%02X %04X) len %04X, misc %04X, bits %02X\n",\ + t, ib->btx_ring[t].tmd1_hadr, ib->btx_ring[t].tmd0,\ + ib->btx_ring[t].length,\ + ib->btx_ring[t].misc, ib->btx_ring[t].tmd1_bits);\ + }\ +} while (0) +#else +#define PRINT_RINGS() +#endif + +/* Load the CSR registers. The LANCE has to be STOPped when we do this! */ +static void load_csrs (struct lance_private *lp) +{ + volatile struct lance_init_block *aib = lp->lance_init_block; + int leptr; + DECLARE_LL; + + leptr = LANCE_ADDR (aib); + + WRITERAP(LE_CSR1); /* load address of init block */ + WRITERDP(leptr & 0xFFFF); + WRITERAP(LE_CSR2); + WRITERDP(leptr >> 16); + WRITERAP(LE_CSR3); + WRITERDP(lp->busmaster_regval); /* set byteswap/ALEctrl/byte ctrl */ + + /* Point back to csr0 */ + WRITERAP(LE_CSR0); +} + +/* #define to 0 or 1 appropriately */ +#define DEBUG_IRING 0 +/* Set up the Lance Rx and Tx rings and the init block */ +/* Sets dev->tbusy */ +static void lance_init_ring (struct device *dev) +{ + struct lance_private *lp = (struct lance_private *) dev->priv; + volatile struct lance_init_block *ib = lp->init_block; + volatile struct lance_init_block *aib; /* for LANCE_ADDR computations */ + int leptr; + int i; + + aib = lp->lance_init_block; + + /* Lock out other processes while setting up hardware */ + dev->tbusy = 1; + lp->rx_new = lp->tx_new = 0; + lp->rx_old = lp->tx_old = 0; + + ib->mode = LE_MO_PROM; /* normal, enable Tx & Rx */ + + /* Copy the ethernet address to the lance init block + * Notice that we do a byteswap if we're big endian. + * [I think this is the right criterion; at least, sunlance, + * a2065 and atarilance do the byteswap and lance.c (PC) doesn't. + * However, the datasheet says that the BSWAP bit doesn't affect + * the init block, so surely it should be low byte first for + * everybody? Um.] + * We could define the ib->physaddr as three 16bit values and + * use (addr[1] << 8) | addr[0] & co, but this is more efficient. + */ +#ifdef __BIG_ENDIAN + ib->phys_addr [0] = dev->dev_addr [1]; + ib->phys_addr [1] = dev->dev_addr [0]; + ib->phys_addr [2] = dev->dev_addr [3]; + ib->phys_addr [3] = dev->dev_addr [2]; + ib->phys_addr [4] = dev->dev_addr [5]; + ib->phys_addr [5] = dev->dev_addr [4]; +#else + for (i=0; i<6; i++) + ib->phys_addr[i] = dev->dev_addr[i]; +#endif + + if (DEBUG_IRING) + printk ("TX rings:\n"); + + /* Setup the Tx ring entries */ + for (i = 0; i < (1<lance_log_tx_bufs); i++) { + leptr = LANCE_ADDR(&aib->tx_buf[i][0]); + ib->btx_ring [i].tmd0 = leptr; + ib->btx_ring [i].tmd1_hadr = leptr >> 16; + ib->btx_ring [i].tmd1_bits = 0; + ib->btx_ring [i].length = 0xf000; /* The ones required by tmd2 */ + ib->btx_ring [i].misc = 0; + if (DEBUG_IRING) + printk ("%d: 0x%8.8x\n", i, leptr); + } + + /* Setup the Rx ring entries */ + if (DEBUG_IRING) + printk ("RX rings:\n"); + for (i = 0; i < (1<lance_log_rx_bufs); i++) { + leptr = LANCE_ADDR(&aib->rx_buf[i][0]); + + ib->brx_ring [i].rmd0 = leptr; + ib->brx_ring [i].rmd1_hadr = leptr >> 16; + ib->brx_ring [i].rmd1_bits = LE_R1_OWN; + /* 0xf000 == bits that must be one (reserved, presumably) */ + ib->brx_ring [i].length = -RX_BUFF_SIZE | 0xf000; + ib->brx_ring [i].mblength = 0; + if (DEBUG_IRING) + printk ("%d: 0x%8.8x\n", i, leptr); + } + + /* Setup the initialization block */ + + /* Setup rx descriptor pointer */ + leptr = LANCE_ADDR(&aib->brx_ring); + ib->rx_len = (lp->lance_log_rx_bufs << 13) | (leptr >> 16); + ib->rx_ptr = leptr; + if (DEBUG_IRING) + printk ("RX ptr: %8.8x\n", leptr); + + /* Setup tx descriptor pointer */ + leptr = LANCE_ADDR(&aib->btx_ring); + ib->tx_len = (lp->lance_log_tx_bufs << 13) | (leptr >> 16); + ib->tx_ptr = leptr; + if (DEBUG_IRING) + printk ("TX ptr: %8.8x\n", leptr); + + /* Clear the multicast filter */ + ib->filter [0] = 0; + ib->filter [1] = 0; + PRINT_RINGS(); +} + +/* LANCE must be STOPped before we do this, too... */ +static int init_restart_lance (struct lance_private *lp) +{ + int i; + DECLARE_LL; + + WRITERAP(LE_CSR0); + WRITERDP(LE_C0_INIT); + + /* Need a hook here for sunlance ledma stuff */ + + /* Wait for the lance to complete initialization */ + for (i = 0; (i < 100) && !(READRDP() & (LE_C0_ERR | LE_C0_IDON)); i++) + barrier(); + if ((i == 100) || (READRDP() & LE_C0_ERR)) { + printk ("LANCE unopened after %d ticks, csr0=%4.4x.\n", i, READRDP()); + return -1; + } + + /* Clear IDON by writing a "1", enable interrupts and start lance */ + WRITERDP(LE_C0_IDON); + WRITERDP(LE_C0_INEA | LE_C0_STRT); + + return 0; +} + +static int lance_reset (struct device *dev) +{ + struct lance_private *lp = (struct lance_private *)dev->priv; + int status; + DECLARE_LL; + + /* Stop the lance */ + WRITERAP(LE_CSR0); + WRITERDP(LE_C0_STOP); + + load_csrs (lp); + lance_init_ring (dev); + dev->trans_start = jiffies; + dev->interrupt = 0; + dev->start = 1; + dev->tbusy = 0; + status = init_restart_lance (lp); +#ifdef DEBUG_DRIVER + printk ("Lance restart=%d\n", status); +#endif + return status; +} + +static int lance_rx (struct device *dev) +{ + struct lance_private *lp = (struct lance_private *) dev->priv; + volatile struct lance_init_block *ib = lp->init_block; + volatile struct lance_rx_desc *rd; + unsigned char bits; + int len = 0; /* XXX shut up gcc warnings */ + struct sk_buff *skb = 0; /* XXX shut up gcc warnings */ +#ifdef TEST_HITS + int i; +#endif + DECLARE_LL; + +#ifdef TEST_HITS + printk ("["); + for (i = 0; i < RX_RING_SIZE; i++) { + if (i == lp->rx_new) + printk ("%s", + ib->brx_ring [i].rmd1_bits & LE_R1_OWN ? "_" : "X"); + else + printk ("%s", + ib->brx_ring [i].rmd1_bits & LE_R1_OWN ? "." : "1"); + } + printk ("]"); +#endif + + WRITERDP(LE_C0_RINT | LE_C0_INEA); /* ack Rx int, reenable ints */ + for (rd = &ib->brx_ring [lp->rx_new]; /* For each Rx ring we own... */ + !((bits = rd->rmd1_bits) & LE_R1_OWN); + rd = &ib->brx_ring [lp->rx_new]) { + + /* We got an incomplete frame? */ + if ((bits & LE_R1_POK) != LE_R1_POK) { + lp->stats.rx_over_errors++; + lp->stats.rx_errors++; + continue; + } else if (bits & LE_R1_ERR) { + /* Count only the end frame as a rx error, + * not the beginning + */ + if (bits & LE_R1_BUF) lp->stats.rx_fifo_errors++; + if (bits & LE_R1_CRC) lp->stats.rx_crc_errors++; + if (bits & LE_R1_OFL) lp->stats.rx_over_errors++; + if (bits & LE_R1_FRA) lp->stats.rx_frame_errors++; + if (bits & LE_R1_EOP) lp->stats.rx_errors++; + } else { + len = (rd->mblength & 0xfff) - 4; + skb = dev_alloc_skb (len+2); + + if (skb == 0) { + printk ("%s: Memory squeeze, deferring packet.\n", + dev->name); + lp->stats.rx_dropped++; + rd->mblength = 0; + rd->rmd1_bits = LE_R1_OWN; + lp->rx_new = (lp->rx_new + 1) & lp->rx_ring_mod_mask; + return 0; + } + + skb->dev = dev; + skb_reserve (skb, 2); /* 16 byte align */ + skb_put (skb, len); /* make room */ + eth_copy_and_sum(skb, + (unsigned char *)&(ib->rx_buf [lp->rx_new][0]), + len, 0); + skb->protocol = eth_type_trans (skb, dev); + netif_rx (skb); + lp->stats.rx_packets++; + } + + /* Return the packet to the pool */ + rd->mblength = 0; + rd->rmd1_bits = LE_R1_OWN; + lp->rx_new = (lp->rx_new + 1) & lp->rx_ring_mod_mask; + } + return 0; +} + +static int lance_tx (struct device *dev) +{ + struct lance_private *lp = (struct lance_private *) dev->priv; + volatile struct lance_init_block *ib = lp->init_block; + volatile struct lance_tx_desc *td; + int i, j; + int status; + DECLARE_LL; + + /* csr0 is 2f3 */ + WRITERDP(LE_C0_TINT | LE_C0_INEA); + /* csr0 is 73 */ + + j = lp->tx_old; + for (i = j; i != lp->tx_new; i = j) { + td = &ib->btx_ring [i]; + + /* If we hit a packet not owned by us, stop */ + if (td->tmd1_bits & LE_T1_OWN) + break; + + if (td->tmd1_bits & LE_T1_ERR) { + status = td->misc; + + lp->stats.tx_errors++; + if (status & LE_T3_RTY) lp->stats.tx_aborted_errors++; + if (status & LE_T3_LCOL) lp->stats.tx_window_errors++; + + if (status & LE_T3_CLOS) { + lp->stats.tx_carrier_errors++; + if (lp->auto_select) { + lp->tpe = 1 - lp->tpe; + printk("%s: Carrier Lost, trying %s\n", + dev->name, lp->tpe?"TPE":"AUI"); + /* Stop the lance */ + WRITERAP(LE_CSR0); + WRITERDP(LE_C0_STOP); + lance_init_ring (dev); + load_csrs (lp); + init_restart_lance (lp); + return 0; + } + } + + /* buffer errors and underflows turn off the transmitter */ + /* Restart the adapter */ + if (status & (LE_T3_BUF|LE_T3_UFL)) { + lp->stats.tx_fifo_errors++; + + printk ("%s: Tx: ERR_BUF|ERR_UFL, restarting\n", + dev->name); + /* Stop the lance */ + WRITERAP(LE_CSR0); + WRITERDP(LE_C0_STOP); + lance_init_ring (dev); + load_csrs (lp); + init_restart_lance (lp); + return 0; + } + } else if ((td->tmd1_bits & LE_T1_POK) == LE_T1_POK) { + /* + * So we don't count the packet more than once. + */ + td->tmd1_bits &= ~(LE_T1_POK); + + /* One collision before packet was sent. */ + if (td->tmd1_bits & LE_T1_EONE) + lp->stats.collisions++; + + /* More than one collision, be optimistic. */ + if (td->tmd1_bits & LE_T1_EMORE) + lp->stats.collisions += 2; + + lp->stats.tx_packets++; + } + + j = (j + 1) & lp->tx_ring_mod_mask; + } + lp->tx_old = j; + WRITERDP(LE_C0_TINT | LE_C0_INEA); + return 0; +} + +static void lance_interrupt (int irq, void *dev_id, struct pt_regs *regs) +{ + struct device *dev = (struct device *)dev_id; + struct lance_private *lp = (struct lance_private *)dev->priv; + int csr0; + DECLARE_LL; + + WRITERAP(LE_CSR0); /* LANCE Controller Status */ + csr0 = READRDP(); + + PRINT_RINGS(); + + if (!(csr0 & LE_C0_INTR)) /* Check if any interrupt has */ + return; /* been generated by the Lance. */ + + if (dev->interrupt) + printk ("%s: again", dev->name); + + dev->interrupt = 1; + + /* Acknowledge all the interrupt sources ASAP */ + WRITERDP(csr0 & ~(LE_C0_INEA|LE_C0_TDMD|LE_C0_STOP|LE_C0_STRT|LE_C0_INIT)); + + if ((csr0 & LE_C0_ERR)) { + /* Clear the error condition */ + WRITERDP(LE_C0_BABL|LE_C0_ERR|LE_C0_MISS|LE_C0_INEA); + } + + if (csr0 & LE_C0_RINT) + lance_rx (dev); + + if (csr0 & LE_C0_TINT) + lance_tx (dev); + + /* Log misc errors. */ + if (csr0 & LE_C0_BABL) + lp->stats.tx_errors++; /* Tx babble. */ + if (csr0 & LE_C0_MISS) + lp->stats.rx_errors++; /* Missed a Rx frame. */ + if (csr0 & LE_C0_MERR) { + printk("%s: Bus master arbitration failure, status %4.4x.\n", + dev->name, csr0); + /* Restart the chip. */ + WRITERDP(LE_C0_STRT); + } + + if ((TX_BUFFS_AVAIL >= 0) && dev->tbusy) { + dev->tbusy = 0; + mark_bh (NET_BH); + } + + WRITERAP(LE_CSR0); + WRITERDP(LE_C0_BABL|LE_C0_CERR|LE_C0_MISS|LE_C0_MERR|LE_C0_IDON|LE_C0_INEA); + + dev->interrupt = 0; +} + +int lance_open (struct device *dev) +{ + struct lance_private *lp = (struct lance_private *)dev->priv; + DECLARE_LL; + + /* Install the Interrupt handler. Or we could shunt this out to specific drivers? */ + if (request_irq(lp->irq, lance_interrupt, 0, lp->name, dev)) + return -EAGAIN; + + return lance_reset(dev); +} + +int lance_close (struct device *dev) +{ + struct lance_private *lp = (struct lance_private *) dev->priv; + DECLARE_LL; + + dev->start = 0; + dev->tbusy = 1; + + /* Stop the LANCE */ + WRITERAP(LE_CSR0); + WRITERDP(LE_C0_STOP); + + free_irq(lp->irq, dev); + + return 0; +} + +int lance_start_xmit (struct sk_buff *skb, struct device *dev) +{ + struct lance_private *lp = (struct lance_private *)dev->priv; + volatile struct lance_init_block *ib = lp->init_block; + int entry, skblen, len; + int status = 0; + static int outs; + DECLARE_LL; + + lance_reset(dev); + + /* Transmitter timeout, serious problems */ + if (dev->tbusy) { + int tickssofar = jiffies - dev->trans_start; + + if (tickssofar < 100) { + status = -1; + } else { + printk ("%s: transmit timed out, status %04x, resetting\n", + dev->name, READRDP()); + lance_reset (dev); + } + return status; + } + + /* Block a timer-based transmit from overlapping. */ + if (test_and_set_bit (0, (void *) &dev->tbusy) != 0) { + printk ("Transmitter access conflict.\n"); + return -1; + } + + skblen = skb->len; + + if (!TX_BUFFS_AVAIL) + return -1; + +#ifdef DEBUG_DRIVER + /* dump the packet */ + { + int i; + + for (i = 0; i < 64; i++) { + if ((i % 16) == 0) + printk ("\n"); + printk ("%2.2x ", skb->data [i]); + } + } +#endif + len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen; + entry = lp->tx_new & lp->tx_ring_mod_mask; + ib->btx_ring [entry].length = (-len) | 0xf000; + ib->btx_ring [entry].misc = 0; + + memcpy ((char *)&ib->tx_buf [entry][0], skb->data, skblen); + + /* Now, give the packet to the lance */ + ib->btx_ring [entry].tmd1_bits = (LE_T1_POK|LE_T1_OWN); + lp->tx_new = (lp->tx_new+1) & lp->tx_ring_mod_mask; + + outs++; + /* Kick the lance: transmit now */ + WRITERDP(LE_C0_INEA | LE_C0_TDMD); + dev->trans_start = jiffies; + dev_kfree_skb (skb); + + if (TX_BUFFS_AVAIL) + dev->tbusy = 0; + + return status; +} + +struct net_device_stats *lance_get_stats (struct device *dev) +{ + struct lance_private *lp = (struct lance_private *) dev->priv; + + return &lp->stats; +} + +/* taken from the depca driver via a2065.c */ +static void lance_load_multicast (struct device *dev) +{ + struct lance_private *lp = (struct lance_private *) dev->priv; + volatile struct lance_init_block *ib = lp->init_block; + volatile u16 *mcast_table = (u16 *)&ib->filter; + struct dev_mc_list *dmi=dev->mc_list; + char *addrs; + int i, j, bit, byte; + u32 crc, poly = CRC_POLYNOMIAL_LE; + + /* set all multicast bits */ + if (dev->flags & IFF_ALLMULTI){ + ib->filter [0] = 0xffffffff; + ib->filter [1] = 0xffffffff; + return; + } + /* clear the multicast filter */ + ib->filter [0] = 0; + ib->filter [1] = 0; + + /* Add addresses */ + for (i = 0; i < dev->mc_count; i++){ + addrs = dmi->dmi_addr; + dmi = dmi->next; + + /* multicast address? */ + if (!(*addrs & 1)) + continue; + + crc = 0xffffffff; + for (byte = 0; byte < 6; byte++) + for (bit = *addrs++, j = 0; j < 8; j++, bit>>=1) + { + int test; + + test = ((bit ^ crc) & 0x01); + crc >>= 1; + + if (test) + { + crc = crc ^ poly; + } + } + + crc = crc >> 26; + mcast_table [crc >> 4] |= 1 << (crc & 0xf); + } + return; +} + + +void lance_set_multicast (struct device *dev) +{ + struct lance_private *lp = (struct lance_private *) dev->priv; + volatile struct lance_init_block *ib = lp->init_block; + DECLARE_LL; + + while (dev->tbusy) + schedule(); + set_bit (0, (void *) &dev->tbusy); + + while (lp->tx_old != lp->tx_new) + schedule(); + + WRITERAP(LE_CSR0); + WRITERDP(LE_C0_STOP); + lance_init_ring (dev); + + if (dev->flags & IFF_PROMISC) { + ib->mode |= LE_MO_PROM; + } else { + ib->mode &= ~LE_MO_PROM; + lance_load_multicast (dev); + } + load_csrs (lp); + init_restart_lance (lp); + dev->tbusy = 0; +} + diff -u --recursive --new-file v2.1.105/linux/drivers/net/7990.h linux/drivers/net/7990.h --- v2.1.105/linux/drivers/net/7990.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/7990.h Sat Jun 13 13:28:34 1998 @@ -0,0 +1,256 @@ +/* + * 7990.h -- LANCE ethernet IC generic routines. + * This is an attempt to separate out the bits of various ethernet + * drivers that are common because they all use the AMD 7990 LANCE + * (Local Area Network Controller for Ethernet) chip. + * + * Copyright (C) 05/1998 Peter Maydell + * + * Most of this stuff was obtained by looking at other LANCE drivers, + * in particular a2065.[ch]. The AMD C-LANCE datasheet was also helpful. + */ + +#ifndef _7990_H +#define _7990_H + +/* The lance only has two register locations. We communicate mostly via memory. */ +struct lance_regs +{ + unsigned short rdp; /* Register Data Port */ + unsigned short rap; /* Register Address Port */ +}; + +/* Transmit/receive ring definitions. + * We allow the specific drivers to override these defaults if they want to. + * NB: according to lance.c, increasing the number of buffers is a waste + * of space and reduces the chance that an upper layer will be able to + * reorder queued Tx packets based on priority. [Clearly there is a minimum + * limit too: too small and we drop rx packets and can't tx at full speed.] + * 4+4 seems to be the usual setting; the atarilance driver uses 3 and 5. + */ + +/* Blast! This won't work. The problem is that we can't specify a default + * setting because that would cause the lance_init_block struct to be + * too long (and overflow the RAM on shared-memory cards like the HP LANCE. + */ +#ifndef LANCE_LOG_TX_BUFFERS +#define LANCE_LOG_TX_BUFFERS 1 +#define LANCE_LOG_RX_BUFFERS 3 +#endif + +#define TX_RING_SIZE (1<tx_old<=lp->tx_new)?\ + lp->tx_old+lp->tx_ring_mod_mask-lp->tx_new:\ + lp->tx_old - lp->tx_new-1) + +/* The LANCE only uses 24 bit addresses. This does the obvious thing. */ +#define LANCE_ADDR(x) ((int)(x) & ~0xff000000) + +/* Now the prototypes we export */ +extern int lance_open(struct device *dev); +extern int lance_close (struct device *dev); +extern int lance_start_xmit (struct sk_buff *skb, struct device *dev); +extern struct net_device_stats *lance_get_stats (struct device *dev); +extern void lance_set_multicast (struct device *dev); + +#endif /* ndef _7990_H */ diff -u --recursive --new-file v2.1.105/linux/drivers/net/8390.c linux/drivers/net/8390.c --- v2.1.105/linux/drivers/net/8390.c Tue Jun 9 11:57:29 1998 +++ linux/drivers/net/8390.c Tue Jun 9 22:43:52 1998 @@ -334,7 +334,6 @@ } dev->interrupt = 1; - sti(); /* Change to page 0 and read the intr status reg. */ outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD); @@ -850,8 +849,11 @@ outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); } -/* Initialize the rest of the 8390 device structure. */ -__initfunc(int ethdev_init(struct device *dev)) +/* + * Initialize the rest of the 8390 device structure. Do NOT __initfunc + * this, as it is used by 8390 based modular drivers too. + */ +int ethdev_init(struct device *dev) { if (ei_debug > 1) printk(version); diff -u --recursive --new-file v2.1.105/linux/drivers/net/Config.in linux/drivers/net/Config.in --- v2.1.105/linux/drivers/net/Config.in Tue Jun 9 11:57:29 1998 +++ linux/drivers/net/Config.in Sat Jun 13 12:59:15 1998 @@ -24,6 +24,13 @@ # bool 'Ethernet (10 or 100Mbit)' CONFIG_NET_ETHERNET if [ "$CONFIG_NET_ETHERNET" = "y" ]; then + if [ "$CONFIG_ARM" = "y" ]; then + if [ "$CONFIG_ARCH_ACORN" != "y" ]; then + tristate 'AM79C961A support' CONFIG_ARM_AM79C961A + else + source drivers/acorn/net/Config.in + fi + fi if [ "$CONFIG_PMAC" = "y" ]; then bool 'MACE (Power Mac Ethernet) support' CONFIG_MACE fi diff -u --recursive --new-file v2.1.105/linux/drivers/net/Makefile linux/drivers/net/Makefile --- v2.1.105/linux/drivers/net/Makefile Tue Jun 9 11:57:29 1998 +++ linux/drivers/net/Makefile Sat Jun 13 13:28:34 1998 @@ -12,14 +12,16 @@ M_OBJS := MOD_LIST_NAME := NET_MODULES -# Need these to keep track of whether the 8390, PPP and SLHC modules should -# really go in the kernel or a module. +# Need these to keep track of whether the 7990 (LANCE), 8390, PPP and SLHC +# modules should really go in the kernel or a module. CONFIG_8390_BUILTIN := CONFIG_8390_MODULE := CONFIG_SLHC_BUILTIN := CONFIG_SLHC_MODULE := CONFIG_PPPDEF_BUILTIN := CONFIG_PPPDEF_MODULE := +CONFIG_7990_BUILTIN := +CONFIG_7990_MODULE := ifeq ($(CONFIG_ISDN),y) ifeq ($(CONFIG_ISDN_PPP),y) @@ -111,6 +113,13 @@ endif endif +ifeq ($(CONFIG_ETHERH),y) +CONFIG_8390_BUILTIN = y +else + ifeq ($(CONFIG_ETHERH),m) + CONFIG_8390_MODULE = y + endif +endif ifeq ($(CONFIG_WD80x3),y) L_OBJS += wd.o @@ -667,6 +676,24 @@ endif endif +ifeq ($(CONFIG_HPLANCE),y) +L_OBJS += hplance.o +CONFIG_7990_BUILTIN = y +else + ifeq ($(CONFIG_HPLANCE),m) + CONFIG_7990_MODULE = y + M_OBJS += hplance.o + endif +endif +# If we need generic LANCE support, either in the kernel or as a module, +# build it in the appropriate way. +ifdef CONFIG_7990_BUILTIN +L_OBJS += 7990.o +else + ifdef CONFIG_7990_MODULE + M_OBJS += 7990.o + endif +endif ifeq ($(CONFIG_EQUALIZER),y) L_OBJS += eql.o diff -u --recursive --new-file v2.1.105/linux/drivers/net/Space.c linux/drivers/net/Space.c --- v2.1.105/linux/drivers/net/Space.c Tue Jun 9 11:57:29 1998 +++ linux/drivers/net/Space.c Sat Jun 13 13:29:45 1998 @@ -92,12 +92,17 @@ extern int a2065_probe(struct device *); extern int ariadne_probe(struct device *); extern int hydra_probe(struct device *); +extern int bionet_probe(struct device *); +extern int pamsnet_probe(struct device *); extern int tlan_probe(struct device *); extern int mace_probe(struct device *); extern int cs89x0_probe(struct device *dev); extern int ethertap_probe(struct device *dev); +extern int acorn_ethif_probe(struct device *dev); +extern int am79c961_probe(struct device *dev); extern int epic100_probe(struct device *dev); extern int rtl8139_probe(struct device *dev); +extern int hplance_probe(struct device *dev); /* Gigabit Ethernet adapters */ extern int yellowfin_probe(struct device *dev); @@ -276,6 +281,15 @@ #ifdef CONFIG_HYDRA /* Hydra Systems Amiganet Ethernet board */ && hydra_probe(dev) #endif +#ifdef CONFIG_ATARI_BIONET /* Atari Bionet Ethernet board */ + && bionet_probe(dev) +#endif +#ifdef CONFIG_ATARI_PAMSNET /* Atari PAMsNet Ethernet board */ + && pamsnet_probe(dev) +#endif +#ifdef CONFIG_HPLANCE /* HP300 internal Ethernet */ + && hplance_probe(dev) +#endif #ifdef CONFIG_SUNLANCE && sparc_lance_probe(dev) #endif @@ -296,7 +310,7 @@ #endif #ifdef CONFIG_MIPS_JAZZ_SONIC && sonic_probe(dev) -#endif +#endif #ifdef CONFIG_ARCH_ACORN && acorn_ethif_probe(dev) #endif @@ -425,7 +439,7 @@ # define ETH0_IRQ 0 #endif -#ifndef __sparc__ +#if !defined(__sparc__) && !defined(CONFIG_ARCH_ACORN) #define ETH_NOPROBE_ADDR 0xffe0 #else #define ETH_NOPROBE_ADDR 0 diff -u --recursive --new-file v2.1.105/linux/drivers/net/atari_bionet.c linux/drivers/net/atari_bionet.c --- v2.1.105/linux/drivers/net/atari_bionet.c Thu Feb 12 20:56:07 1998 +++ linux/drivers/net/atari_bionet.c Sat Jun 13 13:28:34 1998 @@ -7,6 +7,8 @@ * * Little adaptions for integration into pl7 by Roman Hodek * + * Some changes in bionet_poll_rx by Karl-Heinz Lohner + * What is it ? ------------ This driver controls the BIONET-100 LAN-Adapter which connects @@ -238,7 +240,7 @@ dma_wd.dma_mode_status = 0x9a; dma_wd.dma_mode_status = 0x19a; dma_wd.dma_mode_status = 0x9a; - dma_wd.fdc_acces_seccount = 0x05; /* sector count */ + dma_wd.fdc_acces_seccount = 0x04; /* sector count (was 5) */ dma_wd.dma_lo = (unsigned char)paddr; paddr >>= 8; dma_wd.dma_md = (unsigned char)paddr; @@ -293,7 +295,7 @@ paddr >>= 8; dma_wd.dma_hi = (unsigned char)paddr; - dma_wd.fdc_acces_seccount = 0xaa; /* sector count */ + dma_wd.fdc_acces_seccount = 0x4; /* sector count */ restore_flags(flags); c = sendcmd(0,0x100,NODE_ADR | C_WRITE); /* CMD: WRITE */ @@ -454,6 +456,28 @@ buf = (unsigned long)&((struct nic_pkt_s *)phys_nic_packet)->buffer; } + if (bionet_debug >1) { + u_char *data = nic_packet->buffer, *p; + int i; + + printk( "%s: TX pkt type 0x%4x from ", dev->name, + ((u_short *)data)[6]); + + for( p = &data[6], i = 0; i < 6; i++ ) + printk("%02x%s", *p++,i != 5 ? ":" : "" ); + printk(" to "); + + for( p = data, i = 0; i < 6; i++ ) + printk("%02x%s", *p++,i != 5 ? ":" : "" "\n" ); + + printk( "%s: ", dev->name ); + printk(" data %02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x" + " %02x%02x%02x%02x len %d\n", + data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19], + data[20], data[21], data[22], data[23], data[24], data[25], data[26], data[27], + data[28], data[29], data[30], data[31], data[32], data[33], + length ); + } dma_cache_maintenance(buf, length, 1); stat = hardware_send_packet(buf, length); @@ -499,7 +523,7 @@ while(boguscount--) { status = get_frame((unsigned long)phys_nic_packet, 0); - if( status != 1 ) break; + if( status == 0 ) break; /* Good packet... */ @@ -508,34 +532,63 @@ pkt_len = (nic_packet->l_hi << 8) | nic_packet->l_lo; lp->poll_time = bionet_min_poll_time; /* fast poll */ - if( pkt_len >= 60 && pkt_len <= 1514 ) { - + if( pkt_len >= 60 && pkt_len <= 1520 ) { + /* ^^^^ war 1514 KHL */ /* Malloc up new buffer. */ - struct sk_buff *skb = alloc_skb(pkt_len, GFP_ATOMIC); + struct sk_buff *skb = dev_alloc_skb( pkt_len + 2 ); if (skb == NULL) { printk("%s: Memory squeeze, dropping packet.\n", dev->name); lp->stats.rx_dropped++; break; } - skb->len = pkt_len; + skb->dev = dev; + skb_reserve( skb, 2 ); /* 16 Byte align */ + skb_put( skb, pkt_len ); /* make room */ /* 'skb->data' points to the start of sk_buff data area. */ memcpy(skb->data, nic_packet->buffer, pkt_len); + skb->protocol = eth_type_trans( skb, dev ); netif_rx(skb); lp->stats.rx_packets++; lp->stats.rx_bytes+=pkt_len; - } - } /* If any worth-while packets have been received, dev_rint() has done a mark_bh(INET_BH) for us and will work on them when we get to the bottom-half routine. */ + if (bionet_debug >1) { + u_char *data = nic_packet->buffer, *p; + int i; + + printk( "%s: RX pkt type 0x%4x from ", dev->name, + ((u_short *)data)[6]); + + + for( p = &data[6], i = 0; i < 6; i++ ) + printk("%02x%s", *p++,i != 5 ? ":" : "" ); + printk(" to "); + for( p = data, i = 0; i < 6; i++ ) + printk("%02x%s", *p++,i != 5 ? ":" : "" "\n" ); + + printk( "%s: ", dev->name ); + printk(" data %02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x" + " %02x%02x%02x%02x len %d\n", + data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19], + data[20], data[21], data[22], data[23], data[24], data[25], data[26], data[27], + data[28], data[29], data[30], data[31], data[32], data[33], + pkt_len ); + } + } + else { + printk(" Packet has wrong length: %04d bytes\n", pkt_len); + lp->stats.rx_errors++; + } + } stdma_release(); ENABLE_IRQ(); return; diff -u --recursive --new-file v2.1.105/linux/drivers/net/cops.c linux/drivers/net/cops.c --- v2.1.105/linux/drivers/net/cops.c Tue Jun 9 11:57:29 1998 +++ linux/drivers/net/cops.c Tue Jun 9 01:28:32 1998 @@ -24,13 +24,16 @@ * Hooks for cops_setup routine * (not yet implemented). * 19971101 Jay Schulist Fixes for multiple lt* devices. - * 19980507 Steven Hirsch Fixed the badly broken support - * for Tangent type cards. (COPS - * LT-1 and the like) + * 19980607 Steven Hirsch Fixed the badly broken support + * for Tangent type cards. Only + * tested on Daystar LT200. Some + * cleanup of formatting and program + * logic. Added emacs 'local-vars' + * setup for Jay's brace style. */ static const char *version = - "cops.c:v0.03 3/17/97 Jay Schulist \n"; +"cops.c:v0.04 6/7/98 Jay Schulist \n"; /* * Sources: * COPS Localtalk SDK. This provides almost all of the information @@ -133,6 +136,15 @@ * driver written by Bradford W. Johnson * Farallon PhoneNET PC * Original Apple LocalTalk PC card + * + * N.B. + * + * The Daystar Digital LT200 boards do not support interrupt-driven + * IO. You must specify 'io=0xff' as a module parameter to invoke + * polled mode. I also believe that the port probing logic is quite + * dangerous at best and certainly hopeless for a polled card. Best to + * specify both. - Steve H. + * */ /* @@ -155,7 +167,7 @@ static struct timer_list cops_timer; -/* use 0 for production, 1 for verification, 2 for debug, 3 for very verbose debug */ +/* use 0 for production, 1 for verification, 2 for debug, 3 for verbose debug */ #ifndef COPS_DEBUG #define COPS_DEBUG 1 #endif @@ -192,7 +204,8 @@ static int cops_send_packet (struct sk_buff *skb, struct device *dev); static void set_multicast_list (struct device *dev); static int cops_hard_header (struct sk_buff *skb, struct device *dev, - unsigned short type, void *daddr, void *saddr, unsigned len); + unsigned short type, void *daddr, void *saddr, + unsigned len); static int cops_ioctl (struct device *dev, struct ifreq *rq, int cmd); static int cops_close (struct device *dev); @@ -202,9 +215,8 @@ /* * Check for a network adaptor of this type, and return '0' iff one exists. * If dev->base_addr == 0, probe all likely locations. - * If dev->base_addr == 1, always return failure. - * If dev->base_addr == 2, allocate space for the device and return success - * (detachable devices only). + * If dev->base_addr in [1..0x1ff], always return failure. + * otherwise go with what we pass in. */ __initfunc(int cops_probe(struct device *dev)) { @@ -219,6 +231,11 @@ else if(base_addr != 0) /* Don't probe at all. */ return -ENXIO; + /* FIXME Does this really work for cards which generate irq? + * It's definitely N.G. for polled Tangent. sh + * Dayna cards don't autoprobe well at all, but if your card is + * at IRQ 5 & IO 0x240 we find it every time. ;) JS + */ for(i=0; cops_portlist[i]; i++) { int ioaddr = cops_portlist[i]; if(check_region(ioaddr, COPS_IO_EXTENT)) @@ -239,17 +256,12 @@ { struct cops_local *lp; static unsigned version_printed = 0; - int irqaddr = 0; - int irqval; int board = board_type; if(cops_debug && version_printed++ == 0) printk("%s", version); - /* Fill in the 'dev' fields. */ - dev->base_addr = ioaddr; - /* * Since this board has jumpered interrupts, allocate the interrupt * vector now. There is no point in waiting since no other device @@ -257,37 +269,47 @@ * interrupts are typically not reported by the boards, and we must * used AutoIRQ to find them. */ - - if(dev->irq < 2 && irq) - dev->irq = irq; - - if(dev->irq < 2) + switch (dev->irq) { - irqaddr = cops_irq(ioaddr, board); /* COPS AutoIRQ routine */ - if(irqaddr == 0) - return -EAGAIN; /* No IRQ found on this port */ - else - dev->irq = irqaddr; - } - else if(dev->irq == 2) - /* - * Fixup for users that don't know that IRQ 2 is really + case 0: + /* COPS AutoIRQ routine */ + dev->irq = cops_irq(ioaddr, board); + if(!dev->irq) + return -EINVAL; /* No IRQ found on this port */ + break; + + case 1: + return -EINVAL; + break; + + /* Fixup for users that don't know that IRQ 2 is really * IRQ 9, or don't know which one to set. */ - dev->irq = 9; + case 2: + dev->irq = 9; + break; - /* Snarf the interrupt now. */ - irqval = request_irq(dev->irq, &cops_interrupt, 0, cardname, dev); + /* Polled operation requested. Although irq of zero passed as + * a parameter tells the init routines to probe, we'll + * overload it to denote polled operation at runtime. + */ + case 0xff: + dev->irq = 0; + break; - /* If its in use set it to 0 and disallow open() calls.. users can still - ifconfig the irq one day */ + default: + break; + } - if(irqval) - dev->irq = 0; + /* Reserve any actual interrupt. */ + if(dev->irq && request_irq(dev->irq, &cops_interrupt, 0, cardname, dev)) + return -EINVAL; - dev->hard_start_xmit = &cops_send_packet; + /* Grab the region so no one else tries to probe our ioports. */ + request_region(ioaddr, COPS_IO_EXTENT, cardname); + dev->base_addr = ioaddr; - /* Initialize the device structure. */ + /* Initialize the private device structure. */ dev->priv = kmalloc(sizeof(struct cops_local), GFP_KERNEL); if(dev->priv == NULL) return -ENOMEM; @@ -298,20 +320,10 @@ /* Copy local board variable to lp struct. */ lp->board = board; - /* Tell the user where the card is and what mode were in. */ - if(board==DAYNA) - printk("%s: %s found at %#3x, using IRQ %d, in Dayna mode.\n", - dev->name, cardname, ioaddr, dev->irq); - if(board==TANGENT) - printk("%s: %s found at %#3x, using IRQ %d, in Tangent mode.\n", - dev->name, cardname, ioaddr, dev->irq); - - /* Grab the region so no one else tries to probe our ioports. */ - request_region(ioaddr, COPS_IO_EXTENT, cardname); - /* Fill in the fields of the device structure with LocalTalk values. */ ltalk_setup(dev); + dev->hard_start_xmit = &cops_send_packet; dev->hard_header = cops_hard_header; dev->get_stats = cops_get_stats; dev->open = cops_open; @@ -320,14 +332,17 @@ dev->set_multicast_list = &set_multicast_list; dev->mc_list = NULL; - if(board==TANGENT) /* Poll 20 times per second */ - { - init_timer(&cops_timer); - cops_timer.function = cops_poll; - cops_timer.data = (unsigned long)dev; - cops_timer.expires = jiffies + 5; - add_timer(&cops_timer); - } + /* Tell the user where the card is and what mode we're in. */ + if(board==DAYNA) + printk("%s: %s at %#3x, using IRQ %d, in Dayna mode.\n", + dev->name, cardname, ioaddr, dev->irq); + if(board==TANGENT) + if(dev->irq) + printk("%s: %s at %#3x, IRQ %d, in Tangent mode\n", + dev->name, cardname, ioaddr, dev->irq); + else + printk("%s: %s at %#3x, using polled IO, in Tangent mode.\n", + dev->name, cardname, ioaddr); return 0; } @@ -335,7 +350,7 @@ __initfunc(static int cops_irq (int ioaddr, int board)) { /* * This does not use the IRQ to determine where the IRQ is. We just - * assume that when we get a correct status response that its the IRQ. + * assume that when we get a correct status response that it's the IRQ. * This really just verifies the IO port but since we only have access * to such a small number of IRQs (5, 4, 3) this is not bad. * This will probably not work for more than one card. @@ -383,10 +398,27 @@ */ static int cops_open(struct device *dev) { + struct cops_local *lp = (struct cops_local *)dev->priv; + if(dev->irq==0) { - printk(KERN_WARNING "%s: No irq line set.\n", dev->name); - return -EAGAIN; + /* + * I don't know if the Dayna-style boards support polled + * operation. For now, only allow it for Tangent. + */ + if(lp->board==TANGENT) /* Poll 20 times per second */ + { + init_timer(&cops_timer); + cops_timer.function = cops_poll; + cops_timer.data = (unsigned long)dev; + cops_timer.expires = jiffies + 5; + add_timer(&cops_timer); + } + else + { + printk(KERN_WARNING "%s: No irq line set\n", dev->name); + return -EAGAIN; + } } cops_jumpstart(dev); /* Start the card up. */ @@ -428,18 +460,12 @@ return 0; } -static int tangent_wait_reset(int ioaddr) +static void tangent_wait_reset(int ioaddr) { - long snapt=jiffies; - - while(jiffies-snapt<5*HZ) - { - if((inb(ioaddr+TANG_CARD_STATUS)&TANG_RX_READY)==0) - break; - schedule(); - } + int timeout=0; - return 0; + while(timeout++ < 5 && (inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0) + mdelay(1); /* Wait 1 second */ } /* @@ -452,23 +478,11 @@ if(lp->board==TANGENT) { - inb(ioaddr); /* Clear request latch. */ - outb(0,ioaddr); /* Clear the TANG_TX_READY flop. */ + inb(ioaddr); /* Clear request latch. */ + outb(0,ioaddr); /* Clear the TANG_TX_READY flop. */ outb(0, ioaddr+TANG_RESET); /* Reset the adapter. */ - /* Can take 5 seconds max - youch! */ - if(sleep) - { - long snapt=jiffies; - while(jiffies-snapt<5*HZ) - { - if(inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY) - break; - schedule(); - } - } - else - tangent_wait_reset(ioaddr); + tangent_wait_reset(ioaddr); outb(0, ioaddr+TANG_CLEAR_INT); } if(lp->board==DAYNA) @@ -563,12 +577,13 @@ } if(cops_debug > 1) - printk(KERN_DEBUG "%s: Uploaded firmware - %d bytes of %d bytes.\n", dev->name, i, ltf->length); + printk("%s: Uploaded firmware - %d bytes of %d bytes.\n", + dev->name, i, ltf->length); - if(lp->board==DAYNA) - outb(1, ioaddr+DAYNA_INT_CARD); /* Tell Dayna to run the firmware code. */ - else - inb(ioaddr); /* Tell Tang to run the firmware code. */ + if(lp->board==DAYNA) /* Tell Dayna to run the firmware code. */ + outb(1, ioaddr+DAYNA_INT_CARD); + else /* Tell Tang to run the firmware code. */ + inb(ioaddr); if(lp->board==TANGENT) { @@ -601,10 +616,10 @@ schedule(); } - outb(2, ioaddr); /* Output command packet length as 2. */ + outb(2, ioaddr); /* Output command packet length as 2. */ outb(0, ioaddr); - outb(LAP_INIT, ioaddr); /* Send LAP_INIT command byte. */ - outb(nodeid, ioaddr); /* Suggest node address. */ + outb(LAP_INIT, ioaddr); /* Send LAP_INIT command byte. */ + outb(nodeid, ioaddr); /* Suggest node address. */ } if(lp->board == TANGENT) @@ -612,19 +627,19 @@ /* Empty any pending adapter responses. */ while(inb(ioaddr+TANG_CARD_STATUS)&TANG_RX_READY) { - outb(0, ioaddr+COPS_CLEAR_INT); /* Clear any interrupt. */ - cops_rx(dev); /* Kick out any packet waiting. */ + outb(0, ioaddr+COPS_CLEAR_INT); /* Clear interrupt. */ + cops_rx(dev); /* Kick out packets waiting. */ schedule(); } - /* Not sure what Tangent does if random nodeid we picked is already used. */ + /* Not sure what Tangent does if nodeid picked is used. */ if(nodeid == 0) /* Seed. */ - nodeid = jiffies&0xFF; /* Get a random try .*/ - outb(2, ioaddr); /* Command length LSB. */ - outb(0, ioaddr); /* Command length MSB. */ - outb(LAP_INIT, ioaddr); /* Send LAP_INIT command byte. */ + nodeid = jiffies&0xFF; /* Get a random try */ + outb(2, ioaddr); /* Command length LSB */ + outb(0, ioaddr); /* Command length MSB */ + outb(LAP_INIT, ioaddr); /* Send LAP_INIT byte */ outb(nodeid, ioaddr); /* LAP address hint. */ - outb(0xFF, ioaddr); /* Interrupt level to use (NONE). */ + outb(0xFF, ioaddr); /* Int. level to use */ } lp->node_acquire=0; /* Set nodeid holder to 0. */ @@ -646,7 +661,8 @@ } if(cops_debug > 1) - printk(KERN_DEBUG "%s: Node ID %d has been acquired.\n", dev->name, lp->node_acquire); + printk(KERN_DEBUG "%s: Node ID %d has been acquired.\n", + dev->name, lp->node_acquire); lp->nodeid=1; /* Set got nodeid to 1. */ @@ -658,7 +674,6 @@ */ static void cops_poll(unsigned long ltdev) { - struct cops_local *lp; int ioaddr, status; int boguscount = 0; @@ -670,12 +685,6 @@ return; /* We've been downed */ ioaddr = dev->base_addr; - - /* Clear any interrupt. */ - outb(0, ioaddr + COPS_CLEAR_INT); - dev->interrupt = 0; - - lp = (struct cops_local *)dev->priv; do { status=inb(ioaddr+TANG_CARD_STATUS); if(status & TANG_RX_READY) @@ -704,7 +713,8 @@ if(dev == NULL) { - printk(KERN_WARNING "%s: irq %d for unknown device.\n", cardname, irq); + printk(KERN_WARNING "%s: irq %d for unknown device.\n", + cardname, irq); return; } dev->interrupt = 1; @@ -787,7 +797,8 @@ skb = dev_alloc_skb(pkt_len); if(skb == NULL) { - printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name); + printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", + dev->name); lp->stats.rx_dropped++; while(pkt_len--) /* Discard packet */ inb(ioaddr); @@ -800,14 +811,15 @@ insb(ioaddr, skb->data, pkt_len); /* Eat the Data */ if(lp->board==DAYNA) - outb(1, ioaddr+DAYNA_INT_CARD); /* Interrupt the card. */ + outb(1, ioaddr+DAYNA_INT_CARD); /* Interrupt the card */ sti(); /* Restore interrupts. */ /* Check for bad response length */ if(pkt_len < 0 || pkt_len > MAX_LLAP_SIZE) { - printk(KERN_NOTICE "%s: Bad packet length of %d bytes.\n", dev->name, pkt_len); + printk(KERN_NOTICE "%s: Bad packet length of %d bytes.\n", + dev->name, pkt_len); lp->stats.tx_errors++; kfree_skb(skb); return; @@ -815,8 +827,8 @@ /* Set nodeid and then get out. */ if(rsp_type == LAP_INIT_RSP) - { - lp->node_acquire = skb->data[0]; /* Nodeid taken from received packet. */ + { /* Nodeid taken from received packet. */ + lp->node_acquire = skb->data[0]; kfree_skb(skb); return; } @@ -878,7 +890,8 @@ * done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ if(test_and_set_bit(0, (void*) &dev->tbusy) != 0) - printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name); + printk(KERN_WARNING "%s: Transmitter access conflict.\n", + dev->name); else { cli(); /* Disable interrupts. */ @@ -902,7 +915,7 @@ outsb(ioaddr, skb->data, skb->len); /* Send out the data. */ - if(lp->board==DAYNA) /* The Dayna requires you kick the card. */ + if(lp->board==DAYNA) /* Dayna requires you kick the card */ outb(1, ioaddr+DAYNA_INT_CARD); sti(); /* Restore interrupts. */ @@ -926,7 +939,7 @@ static void set_multicast_list(struct device *dev) { if(cops_debug >= 3) - printk("%s: set_mulicast_list executed. NeatO.\n", dev->name); + printk("%s: set_multicast_list executed\n", dev->name); } /* @@ -934,7 +947,8 @@ */ static int cops_hard_header(struct sk_buff *skb, struct device *dev, - unsigned short type, void *daddr, void *saddr, unsigned len) + unsigned short type, void *daddr, void *saddr, + unsigned len) { if(cops_debug >= 3) printk("%s: cops_hard_header executed. Wow!\n", dev->name); @@ -983,6 +997,13 @@ static int cops_close(struct device *dev) { + struct cops_local *lp = (struct cops_local *)dev->priv; + + /* If we were running polled, yank the timer. + */ + if(lp->board==TANGENT && dev->irq==0) + del_timer(&cops_timer); + dev->tbusy = 1; dev->start = 0; @@ -1024,7 +1045,8 @@ int result, err; if(io == 0) - printk(KERN_WARNING "%s: You shouldn't use auto-probing with insmod!\n", cardname); + printk(KERN_WARNING "%s: You shouldn't autoprobe with insmod\n", + cardname); /* Copy the parameters from insmod into the device structure. */ cops0_dev.base_addr = io; @@ -1046,7 +1068,16 @@ unregister_netdev(&cops0_dev); if(cops0_dev.priv) kfree_s(cops0_dev.priv, sizeof(struct cops_local)); - free_irq(cops0_dev.irq, &cops0_dev); + if(cops0_dev.irq) + free_irq(cops0_dev.irq, &cops0_dev); release_region(cops0_dev.base_addr, COPS_IO_EXTENT); } #endif /* MODULE */ + +/* + * Local variables: + * compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O2 -c cops.c" + * c-basic-offset: 4 + * c-file-offsets: ((substatement-open . 0)) + * End: + */ diff -u --recursive --new-file v2.1.105/linux/drivers/net/hamradio/dmascc.c linux/drivers/net/hamradio/dmascc.c --- v2.1.105/linux/drivers/net/hamradio/dmascc.c Wed May 20 19:10:39 1998 +++ linux/drivers/net/hamradio/dmascc.c Sat Jun 13 10:26:27 1998 @@ -1,5 +1,5 @@ /* - * $Id: dmascc.c,v 1.2.1.3 1997/12/19 13:40:15 oe1kib Exp $ + * $Id: dmascc.c,v 1.2.1.4 1998/06/10 02:24:11 kudielka Exp $ * * Driver for high-speed SCC boards (those with DMA support) * Copyright (C) 1997 Klaus Kudielka diff -u --recursive --new-file v2.1.105/linux/drivers/net/hplance.c linux/drivers/net/hplance.c --- v2.1.105/linux/drivers/net/hplance.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/hplance.c Sat Jun 13 13:28:34 1998 @@ -0,0 +1,249 @@ +/* hplance.c : the Linux/hp300/lance ethernet driver + * + * Copyright (C) 05/1998 Peter Maydell + * Based on the Sun Lance driver and the NetBSD HP Lance driver + * Uses the generic 7990.c LANCE code. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Used for the temporal inet entries and routing */ +#include +#include + +#include + +#include +#include +#include + +#include "hplance.h" + +/* We have 16834 bytes of RAM for the init block and buffers. This places + * an upper limit on the number of buffers we can use. NetBSD uses 8 Rx + * buffers and 2 Tx buffers. + */ +#define LANCE_LOG_TX_BUFFERS 1 +#define LANCE_LOG_RX_BUFFERS 3 + +#include "7990.h" /* use generic LANCE code */ + +/* Our private data structure */ +struct hplance_private { + struct lance_private lance; + unsigned int scode; + void *base; +}; + +/* function prototypes... This is easy because all the grot is in the + * generic LANCE support. All we have to support is probing for boards, + * plus board-specific init, open and close actions. + * Oh, and we need to tell the generic code how to read and write LANCE registers... + */ +int hplance_probe(struct device *dev); +static int hplance_init(struct device *dev, int scode); +static int hplance_open(struct device *dev); +static int hplance_close(struct device *dev); +static void hplance_writerap(struct hplance_private *lp, unsigned short value); +static void hplance_writerdp(struct hplance_private *lp, unsigned short value); +static unsigned short hplance_readrdp(struct hplance_private *lp); + +#ifdef MODULE +static struct hplance_private *root_hplance_dev = NULL; +#endif + +/* Find all the HP Lance boards and initialise them... */ +__initfunc(int hplance_probe(struct device *dev)) +{ + int cards = 0, called = 0; + + if (!MACH_IS_HP300 || called) + return(ENODEV); + called++; + + /* Isn't DIO nice? */ + for(;;) + { + int v, scode = dio_find(DIO_ID_LAN); + + if (!scode) + break; + + if(cards) + dev = NULL; /* don't trash previous device, make a new one */ + cards++; + + v = hplance_init(dev, scode); + if (v) /* error, abort immediately */ + return v; + } + /* OK, return success, or ENODEV if we didn't find any cards */ + if (!cards) + return ENODEV; + return 0; +} + +/* Initialise a single lance board at the given select code */ +__initfunc (static int hplance_init(struct device *dev, int scode)) +{ + /* const char *name = dio_scodetoname(scode); */ + static const char name[] = "HP LANCE"; + void *va = dio_scodetoviraddr(scode); + struct hplance_private *lp; + int i; + + if (dev == NULL) + dev = init_etherdev(0, sizeof(struct hplance_private)); + else + { + dev->priv = kmalloc(sizeof(struct hplance_private), GFP_KERNEL); + if (dev->priv == NULL) + return -ENOMEM; + memset(dev->priv, 0, sizeof(struct hplance_private)); + } + printk("%s: HP LANCE; select code %d, addr", dev->name, scode); + + /* reset the board */ + writeb(0xff,va+DIO_IDOFF); + udelay(100); /* ariba! ariba! udelay! udelay! */ + + /* Fill the dev fields */ + dev->base_addr = (unsigned long)va; + dev->open = &hplance_open; + dev->stop = &hplance_close; + dev->hard_start_xmit = &lance_start_xmit; + dev->get_stats = &lance_get_stats; + dev->set_multicast_list = &lance_set_multicast; + dev->dma = 0; + + for (i=0; i<6; i++) + { + /* The NVRAM holds our ethernet address, one nibble per byte, + * at bytes NVRAMOFF+1,3,5,7,9... + */ + dev->dev_addr[i] = ((readb(va + HPLANCE_NVRAMOFF + i*4 + 1) & 0xF) << 4) + | (readb(va + HPLANCE_NVRAMOFF + i*4 + 3) & 0xF); + printk("%c%2.2x", i == 0 ? ' ' : ':', dev->dev_addr[i]); + } + + lp = (struct hplance_private *)dev->priv; + lp->lance.name = (char*)name; /* discards const, shut up gcc */ + lp->lance.ll = (struct lance_regs *)(va + HPLANCE_REGOFF); + lp->lance.init_block = (struct lance_init_block *)(va + HPLANCE_MEMOFF); /* CPU addr */ + lp->lance.lance_init_block = 0; /* LANCE addr of same RAM */ + lp->lance.busmaster_regval = LE_C3_BSWP; /* we're bigendian */ + lp->lance.irq = dio_scodetoipl(scode); + lp->lance.writerap = hplance_writerap; + lp->lance.writerdp = hplance_writerdp; + lp->lance.readrdp = hplance_readrdp; + lp->lance.lance_log_rx_bufs = LANCE_LOG_RX_BUFFERS; + lp->lance.lance_log_tx_bufs = LANCE_LOG_TX_BUFFERS; + lp->lance.rx_ring_mod_mask = RX_RING_MOD_MASK; + lp->lance.tx_ring_mod_mask = TX_RING_MOD_MASK; + lp->scode = scode; + lp->base = va; + ether_setup(dev); + printk(", irq %d\n", lp->lance.irq); + +#ifdef MODULE + dev->ifindex = dev_new_index(); + lp->next_module = root_hplance_dev; + root_hplance_dev = lp; +#endif /* MODULE */ + + dio_config_board(scode); /* tell bus scanning code this one's taken */ + return 0; +} + +/* This is disgusting. We have to check the DIO status register for ack every + * time we read or write the LANCE registers. + */ +static void hplance_writerap(struct hplance_private *lp, unsigned short value) +{ + struct hplance_reg *hpregs = (struct hplance_reg *)lp->base; + do { + lp->lance.ll->rap = value; + } while ((hpregs->status & LE_ACK) == 0); +} + +static void hplance_writerdp(struct hplance_private *lp, unsigned short value) +{ + struct hplance_reg *hpregs = (struct hplance_reg *)lp->base; + do { + lp->lance.ll->rdp = value; + } while ((hpregs->status & LE_ACK) == 0); +} + +static unsigned short hplance_readrdp(struct hplance_private *lp) +{ + unsigned short val; + struct hplance_reg *hpregs = (struct hplance_reg *)lp->base; + do { + val = lp->lance.ll->rdp; + } while ((hpregs->status & LE_ACK) == 0); + return val; +} + +static int hplance_open(struct device *dev) +{ + int status; + struct hplance_private *lp = (struct hplance_private *)dev->priv; + struct hplance_reg *hpregs = (struct hplance_reg *)lp->base; + + status = lance_open(dev); /* call generic lance open code */ + if (status) + return status; + /* enable interrupts at board level. */ + writeb(LE_IE, &(hpregs->status)); + + MOD_INC_USE_COUNT; + return 0; +} + +static int hplance_close(struct device *dev) +{ + struct hplance_private *lp = (struct hplance_private *)dev->priv; + struct hplance_reg *hpregs = (struct hplance_reg *)lp->base; + writeb(0,&(hpregs->status)); /* disable interrupts at boardlevel */ + lance_close(dev); + MOD_DEC_USE_COUNT; + return 0; +} + +#ifdef MODULE +int init_module(void) +{ + root_lance_dev = NULL; + return hplance_probe(NULL); +} + +void cleanup_module(void) +{ + /* Walk the chain of devices, unregistering them */ + struct hplance_private *lp; + while (root_hplance_dev) { + lp = root_hplance_dev->next_module; + dio_unconfig_board(lp->scode); + unregister_netdev(root_lance_dev->dev); + kfree(root_lance_dev->dev); + root_lance_dev = lp; + } +} + +#endif /* MODULE */ diff -u --recursive --new-file v2.1.105/linux/drivers/net/hplance.h linux/drivers/net/hplance.h --- v2.1.105/linux/drivers/net/hplance.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/hplance.h Sat Jun 13 13:28:34 1998 @@ -0,0 +1,31 @@ +/* Random defines and structures for the HP Lance driver. + * Copyright (C) 05/1998 Peter Maydell + * Based on the Sun Lance driver and the NetBSD HP Lance driver + */ + +/* Registers */ +struct hplance_reg +{ + u_char pad0; + volatile u_char id; /* DIO register: ID byte */ + u_char pad1; + volatile u_char status; /* DIO register: interrupt enable */ +}; + +/* Control and status bits for the hplance->status register */ +#define LE_IE 0x80 /* interrupt enable */ +#define LE_IR 0x40 /* interrupt requested */ +#define LE_LOCK 0x08 /* lock status register */ +#define LE_ACK 0x04 /* ack of lock */ +#define LE_JAB 0x02 /* loss of tx clock (???) */ +/* We can also extract the IPL from the status register with the standard + * DIO_IPL(hplance) macro, or using dio_scodetoipl() + */ + +/* These are the offsets for the DIO regs (hplance_reg), lance_ioreg, + * memory and NVRAM: + */ +#define HPLANCE_IDOFF 0 /* board baseaddr, struct hplance_reg */ +#define HPLANCE_REGOFF 0x4000 /* struct lance_regs */ +#define HPLANCE_MEMOFF 0x8000 /* struct lance_init_block */ +#define HPLANCE_NVRAMOFF 0xC008 /* etheraddress as one *nibble* per byte */ diff -u --recursive --new-file v2.1.105/linux/drivers/net/loopback.c linux/drivers/net/loopback.c --- v2.1.105/linux/drivers/net/loopback.c Thu Feb 12 20:56:08 1998 +++ linux/drivers/net/loopback.c Thu Jun 11 22:52:33 1998 @@ -52,7 +52,7 @@ #include /* For the statistics structure. */ #include /* For ARPHRD_ETHER */ -#define LOOPBACK_MTU (PAGE_SIZE*7/8) +#define LOOPBACK_MTU (PAGE_SIZE - 172) /* * The higher levels take care of making this non-reentrant (it's diff -u --recursive --new-file v2.1.105/linux/drivers/net/net_init.c linux/drivers/net/net_init.c --- v2.1.105/linux/drivers/net/net_init.c Fri May 8 23:14:48 1998 +++ linux/drivers/net/net_init.c Tue Jun 9 01:21:49 1998 @@ -390,7 +390,7 @@ for (i = 0; i < MAX_ETH_CARDS; ++i) { if (ethdev_index[i] == NULL) { sprintf(dev->name, "eth%d", i); - printk("loading device '%s'...\n", dev->name); +/* printk("loading device '%s'...\n", dev->name);*/ ethdev_index[i] = dev; return i; } diff -u --recursive --new-file v2.1.105/linux/drivers/net/ppp.c linux/drivers/net/ppp.c --- v2.1.105/linux/drivers/net/ppp.c Thu May 7 22:51:50 1998 +++ linux/drivers/net/ppp.c Sat Jun 13 12:30:45 1998 @@ -8,7 +8,9 @@ * Dynamic PPP devices by Jim Freeman . * ppp_tty_receive ``noisy-raise-bug'' fixed by Ove Ewerlid * - * ==FILEVERSION 980501== + * Machine hang caused by NULLing a live wait queue fix. + * + * ==FILEVERSION 980608== * * NOTE TO MAINTAINERS: * If you modify this file at all, please set the number above to the @@ -206,6 +208,7 @@ CHECK_PPP_MAGIC(ppp); \ if (!ppp->inuse) { \ printk (ppp_warning, __LINE__); \ + return; \ } \ } while (0) @@ -415,8 +418,6 @@ ppp->ubuf = NULL; ppp->cbuf = NULL; ppp->slcomp = NULL; - ppp->read_wait = NULL; - ppp->write_wait = NULL; ppp->last_xmit = jiffies - flag_time; ppp->last_recv = jiffies; @@ -1706,7 +1707,6 @@ { struct ppp *ppp = tty2ppp (tty); __u8 c; - int error; ssize_t len, ret; #define GETC(c) \ @@ -1720,41 +1720,40 @@ */ if (!ppp) return -EIO; - - /* if (ppp->magic != PPP_MAGIC) - return -EIO; */ - CHECK_PPP (-ENXIO); /* * Before we attempt to write the frame to the user, ensure that the * user has access to the pages for the total buffer length. */ - error = verify_area (VERIFY_WRITE, buf, nr); - if (error != 0) - return (error); + if (verify_area (VERIFY_WRITE, buf, nr)) + return -EFAULT; + +/* + * Increment the module use count so that the module can't get unloaded + * while we're sleeping below. The problem is that ppp_tty_close() can + * get called (as a result of a hangup from the tty) while we're sleeping. + */ + MOD_INC_USE_COUNT; /* * Acquire the read lock. */ for (;;) { + ret = 0; ppp = tty2ppp (tty); if (!ppp || ppp->magic != PPP_MAGIC || !ppp->inuse || tty != ppp->tty) - return 0; + goto done; if (test_and_set_bit (0, &ppp->ubuf->locked) != 0) { -#if 0 - if (ppp->flags & SC_DEBUG) - printk (KERN_DEBUG - "ppp_tty_read: sleeping(ubuf)\n"); -#endif current->timeout = 0; current->state = TASK_INTERRUPTIBLE; - schedule (); + schedule(); + ret = -EINTR; if (signal_pending(current)) - return -EINTR; + goto done; continue; } @@ -1777,17 +1776,14 @@ */ /* no data */ clear_bit (0, &ppp->ubuf->locked); + ret = -EAGAIN; if (file->f_flags & O_NONBLOCK) - return -EAGAIN; + goto done; current->timeout = 0; -#if 0 - if (ppp->flags & SC_DEBUG) - printk (KERN_DEBUG - "ppp_tty_read: sleeping(read_wait)\n"); -#endif interruptible_sleep_on (&ppp->read_wait); + ret = -EINTR; if (signal_pending(current)) - return -EINTR; + goto done; } /* @@ -1802,7 +1798,7 @@ "ppp: read of %lu bytes too small for %ld " "frame\n", (unsigned long) nr, (long) len + 2); ppp->stats.ppp_ierrors++; - error = -EOVERFLOW; + ret = -EOVERFLOW; goto out; } @@ -1810,35 +1806,32 @@ * Fake the insertion of the ADDRESS and CONTROL information because these * were not saved in the buffer. */ - error = put_user((u_char) PPP_ALLSTATIONS, buf); - if (error) - goto out; - ++buf; - error = put_user((u_char) PPP_UI, buf); - if (error) + ret = -EFAULT; + if (put_user((u_char) PPP_ALLSTATIONS, buf) + || put_user((u_char) PPP_UI, buf+1)) goto out; - ++buf; + buf += 2; /* * Copy the received data from the buffer to the caller's area. */ - ret = len + 2; /* Account for ADDRESS and CONTROL bytes */ + nr = len + 2; /* Account for ADDRESS and CONTROL bytes */ while (len-- > 0) { GETC (c); - error = put_user(c, buf); - if (error) + if (put_user(c, buf)) goto out; ++buf; } - - clear_bit (0, &ppp->ubuf->locked); - return ret; + ret = nr; out: - ppp->ubuf->tail += len; - ppp->ubuf->tail &= ppp->ubuf->size; - clear_bit (0, &ppp->ubuf->locked); - return error; + if (len > 0) + ppp->ubuf->tail = (ppp->ubuf->tail + len) & ppp->ubuf->size; + clear_bit(0, &ppp->ubuf->locked); + +done: + MOD_DEC_USE_COUNT; + return ret; #undef GETC } @@ -2100,6 +2093,14 @@ error = -EFAULT; if (copy_from_user(new_data, data, count)) goto out_free; + +/* + * Increment the module use count so that the module can't get unloaded + * while we're sleeping below. The problem is that ppp_tty_close() can + * get called (as a result of a hangup from the tty) while we're sleeping. + */ + MOD_INC_USE_COUNT; + /* * Lock this PPP unit so we will be the only writer, * sleeping if necessary. @@ -2131,7 +2132,7 @@ current->state = TASK_RUNNING; remove_wait_queue(&ppp->write_wait, &wait); if (error) - goto out_free; + goto out_free_dec; /* * Change the LQR frame @@ -2154,6 +2155,8 @@ } error = count; +out_free_dec: + MOD_DEC_USE_COUNT; out_free: kfree (new_data); out: @@ -2619,6 +2622,7 @@ dev->name); CHECK_PPP (-ENXIO); + MOD_INC_USE_COUNT; return 0; } @@ -2631,6 +2635,7 @@ { struct ppp *ppp = dev2ppp (dev); + MOD_DEC_USE_COUNT; if (ppp2tty (ppp) == NULL) { return -ENXIO; } @@ -3094,6 +3099,8 @@ ppp_last->next = ppp; ppp_last = ppp; ppp->next = 0; + ppp->read_wait = NULL; + ppp->write_wait = NULL; dev = ppp2dev(ppp); dev->next = NULL; diff -u --recursive --new-file v2.1.105/linux/drivers/net/wavelan.c linux/drivers/net/wavelan.c --- v2.1.105/linux/drivers/net/wavelan.c Sun Jun 7 11:16:33 1998 +++ linux/drivers/net/wavelan.c Sat Jun 13 12:01:39 1998 @@ -1,10 +1,10 @@ /* - * Wavelan ISA driver + * WaveLAN ISA driver * * Jean II - HPLB '96 * * Reorganisation and extension of the driver. - * Original copyrigth follow (see also end of this file). + * Original copyright follows (also see the end of this file). * See wavelan.p.h for details. */ @@ -19,7 +19,7 @@ /************************* MISC SUBROUTINES **************************/ /* * Subroutines which won't fit in one of the following category - * (wavelan modem or i82586) + * (WaveLAN modem or i82586) */ /*------------------------------------------------------------------*/ @@ -95,14 +95,14 @@ #undef SC return((char *) NULL); -} /* wv_structuct_check */ +} /* wv_struct_check */ #endif /* STRUCT_CHECK */ /********************* HOST ADAPTER SUBROUTINES *********************/ /* - * Usefull subroutines to manage the wavelan ISA interface + * Useful subroutines to manage the WaveLAN ISA interface * - * One major difference with the Pcmcia hardware (exept the port mapping) + * One major difference with the PCMCIA hardware (except the port mapping) * is that we have to keep the state of the Host Control Register * because of the interrupt enable & bus size flags. */ @@ -166,7 +166,7 @@ /*------------------------------------------------------------------*/ /* - * Set the i/o transfer over the ISA bus to 8 bits mode + * Set the I/O transfer over the ISA bus to 8-bit mode */ static inline void wv_16_off(u_long ioaddr, @@ -178,7 +178,7 @@ /*------------------------------------------------------------------*/ /* - * Set the i/o transfer over the ISA bus to 8 bits mode + * Set the I/O transfer over the ISA bus to 8-bit mode */ static inline void wv_16_on(u_long ioaddr, @@ -190,7 +190,7 @@ /*------------------------------------------------------------------*/ /* - * Disable interrupts on the wavelan hardware + * Disable interrupts on the WaveLAN hardware. */ static inline void wv_ints_off(device * dev) @@ -209,7 +209,7 @@ /*------------------------------------------------------------------*/ /* - * Enable interrupts on the wavelan hardware + * Enable interrupts on the WaveLAN hardware. */ static inline void wv_ints_on(device * dev) @@ -228,7 +228,7 @@ /******************* MODEM MANAGEMENT SUBROUTINES *******************/ /* - * Usefull subroutines to manage the modem of the wavelan + * Useful subroutines to manage the modem of the WaveLAN */ /*------------------------------------------------------------------*/ @@ -259,7 +259,7 @@ /*------------------------------------------------------------------*/ /* - * Write the Paramter Storage Area to the WaveLAN card's memory + * Write the Parameter Storage Area to the WaveLAN card's memory. */ static void psa_write(u_long ioaddr, @@ -294,10 +294,10 @@ /*------------------------------------------------------------------*/ /* * Calculate the PSA CRC (not tested yet) - * As the Wavelan drivers don't use the CRC, I won't use it either... - * Thanks to Valster, Nico for the code + * As the WaveLAN drivers don't use the CRC, I won't use it either. + * Thanks to Nico Valster for the code * NOTE: By specifying a length including the CRC position the - * returned value should be zero. (i.e. a correct checksum in the PSA) + * returned value should be zero. (i.e. a correct checksum in the PSA). */ static u_short psa_crc(u_short * psa, /* The PSA */ @@ -344,7 +344,7 @@ /*------------------------------------------------------------------*/ /* * Routine to write bytes to the Modem Management Controller. - * We start by the end because it is the way it should be ! + * We start at the end because it is the way it should be! */ static inline void mmc_write(u_long ioaddr, @@ -361,8 +361,8 @@ /*------------------------------------------------------------------*/ /* - * Read 1 byte from the MMC. - * Optimised version for 1 byte, avoid using memory... + * Read a byte from the MMC. + * Optimised version for 1 byte, avoid using memory. */ static inline u_char mmc_in(u_long ioaddr, @@ -383,7 +383,7 @@ * The implementation is complicated by a lack of address lines, * which prevents decoding of the low-order bit. * (code has just been moved in the above function) - * We start by the end because it is the way it should be ! + * We start at the end because it is the way it should be! */ static inline void mmc_read(u_long ioaddr, @@ -400,7 +400,7 @@ /*------------------------------------------------------------------*/ /* - * Get the type of encryption available... + * Get the type of encryption available. */ static inline int mmc_encr(u_long ioaddr) /* i/o port of the card */ @@ -416,8 +416,8 @@ /*------------------------------------------------------------------*/ /* - * Wait for the frequency EEprom to complete a command... - * I hope this one will be optimally inlined... + * Wait for the frequency EEPROM to complete a command. + * I hope this one will be optimally inlined. */ static inline void fee_wait(u_long ioaddr, /* i/o port of the card */ @@ -433,7 +433,7 @@ /*------------------------------------------------------------------*/ /* - * Read bytes from the Frequency EEprom (frequency select cards). + * Read bytes from the Frequency EEPROM (frequency select cards). */ static void fee_read(u_long ioaddr, /* i/o port of the card */ @@ -452,21 +452,21 @@ /* Write the read command */ mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_READ); - /* Wait until EEprom is ready (should be quick !) */ + /* Wait until EEPROM is ready (should be quick). */ fee_wait(ioaddr, 10, 100); - /* Read the value */ + /* Read the value. */ *--b = ((mmc_in(ioaddr, mmroff(0, mmr_fee_data_h)) << 8) | mmc_in(ioaddr, mmroff(0, mmr_fee_data_l))); } } -#ifdef WIRELESS_EXT /* If wireless extension exist in the kernel */ +#ifdef WIRELESS_EXT /* if the wireless extension exists in the kernel */ /*------------------------------------------------------------------*/ /* - * Write bytes from the Frequency EEprom (frequency select cards). - * This is a bit complicated, because the frequency eeprom has to + * Write bytes from the Frequency EEPROM (frequency select cards). + * This is a bit complicated, because the frequency EEPROM has to * be unprotected and the write enabled. * Jean II */ @@ -476,7 +476,7 @@ u_short * b, /* data buffer */ int n) /* number of registers */ { - b += n; /* Position at the end of the area */ + b += n; /* Position at the end of the area. */ #ifdef EEPROM_IS_PROTECTED /* disabled */ #ifdef DOESNT_SEEM_TO_WORK /* disabled */ @@ -485,19 +485,19 @@ fee_wait(ioaddr, 10, 100); - /* Read the protected register */ + /* Read the protected register. */ printk("Protected 2 : %02X-%02X\n", mmc_in(ioaddr, mmroff(0, mmr_fee_data_h)), mmc_in(ioaddr, mmroff(0, mmr_fee_data_l))); #endif /* DOESNT_SEEM_TO_WORK */ - /* Enable protected register */ + /* Enable protected register. */ mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_EN); mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PREN); fee_wait(ioaddr, 10, 100); - /* Unprotect area */ + /* Unprotect area. */ mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), o + n); mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRWRITE); #ifdef DOESNT_SEEM_TO_WORK /* disabled */ @@ -508,38 +508,38 @@ fee_wait(ioaddr, 10, 100); #endif /* EEPROM_IS_PROTECTED */ - /* Write enable */ + /* Write enable. */ mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_EN); mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_WREN); fee_wait(ioaddr, 10, 100); - /* Write the EEprom address */ + /* Write the EEPROM address. */ mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), o + n - 1); /* Loop on all buffer */ while(n-- > 0) { - /* Write the value */ + /* Write the value. */ mmc_out(ioaddr, mmwoff(0, mmw_fee_data_h), (*--b) >> 8); mmc_out(ioaddr, mmwoff(0, mmw_fee_data_l), *b & 0xFF); - /* Write the write command */ + /* Write the write command. */ mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_WRITE); - /* Wavelan doc says : wait at least 10 ms for EEBUSY = 0 */ + /* WaveLAN documentation says to wait at least 10 ms for EEBUSY = 0 */ mdelay(10); fee_wait(ioaddr, 10, 100); } - /* Write disable */ + /* Write disable. */ mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_DS); mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_WDS); fee_wait(ioaddr, 10, 100); #ifdef EEPROM_IS_PROTECTED /* disabled */ - /* Reprotect EEprom */ + /* Reprotect EEPROM. */ mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), 0x00); mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRWRITE); @@ -550,13 +550,13 @@ /************************ I82586 SUBROUTINES *************************/ /* - * Usefull subroutines to manage the Ethernet controler + * Useful subroutines to manage the Ethernet controller */ /*------------------------------------------------------------------*/ /* * Read bytes from the on-board RAM. - * Why inlining this function make it fail ??? + * Why does inlining this function make it fail? */ static /*inline*/ void obram_read(u_long ioaddr, @@ -584,7 +584,7 @@ /*------------------------------------------------------------------*/ /* - * Acknowledge the reading of the status issued by the i82586 + * Acknowledge the reading of the status issued by the i82586. */ static void wv_ack(device * dev) @@ -626,7 +626,7 @@ /*------------------------------------------------------------------*/ /* * Set channel attention bit and busy wait until command has - * completed, then acknowledge the command completion. + * completed, then acknowledge completion of the command. */ static inline int wv_synchronous_cmd(device * dev, @@ -675,7 +675,7 @@ /*------------------------------------------------------------------*/ /* * Configuration commands completion interrupt. - * Check if done, and if ok... + * Check if done, and if OK. */ static inline int wv_config_complete(device * dev, @@ -693,7 +693,7 @@ mcs_addr = lp->tx_first_in_use + sizeof(ac_tx_t) + sizeof(ac_nop_t) + sizeof(tbd_t) + sizeof(ac_cfg_t) + sizeof(ac_ias_t); - /* Read the status of the last command (set mc list) */ + /* Read the status of the last command (set mc list). */ obram_read(ioaddr, acoff(mcs_addr, ac_status), (unsigned char *)&status, sizeof(status)); /* If not completed -> exit */ @@ -717,7 +717,7 @@ printk(KERN_INFO "wv_config_complete(): set_MAC_address; status = 0x%x\n", dev->name, str, status); - /* Check config command */ + /* Check config command. */ cfg_addr = ias_addr - sizeof(ac_cfg_t); obram_read(ioaddr, acoff(cfg_addr, ac_status), (unsigned char *)&status, sizeof(status)); if(status & AC_SFLD_OK != 0) @@ -776,7 +776,7 @@ printk("%c", "0123456789abcdefghijk"[lp->tx_n_in_use]); */ - /* Was it the last one ? */ + /* Was it the last one? */ if(lp->tx_n_in_use <= 0) lp->tx_first_in_use = I82586NULL; else @@ -882,12 +882,12 @@ /*------------------------------------------------------------------*/ /* - * Reconfigure the i82586, or at least ask for it... - * Because wv_82586_config use a transmission buffer, we must do it + * Reconfigure the i82586, or at least ask for it. + * Because wv_82586_config uses a transmission buffer, we must do it * when we are sure that there is one left, so we do it now * or in wavelan_packet_xmit() (I can't find any better place, - * wavelan_interrupt is not an option...), so you may experience - * some delay sometime... + * wavelan_interrupt is not an option), so you may experience + * delays sometimes. */ static inline void wv_82586_reconfig(device * dev) @@ -909,8 +909,8 @@ /********************* DEBUG & INFO SUBROUTINES *********************/ /* - * This routines are used in the code to show debug informations. - * Most of the time, it dump the content of hardware structures... + * This routine is used in the code to show information for debugging. + * Most of the time, it dumps the contents of hardware structures. */ #ifdef DEBUG_PSA_SHOW @@ -921,7 +921,7 @@ static void wv_psa_show(psa_t * p) { - printk(KERN_DEBUG "##### wavelan psa contents: #####\n"); + printk(KERN_DEBUG "##### WaveLAN psa contents: #####\n"); printk(KERN_DEBUG "psa_io_base_addr_1: 0x%02X %02X %02X %02X\n", p->psa_io_base_addr_1, p->psa_io_base_addr_2, @@ -1006,7 +1006,7 @@ /*------------------------------------------------------------------*/ /* * Print the formatted status of the Modem Management Controller. - * This function need to be completed... + * This function needs to be completed. */ static void wv_mmc_show(device * dev) @@ -1028,12 +1028,12 @@ mmc_read(ioaddr, 0, (u_char *)&m, sizeof(m)); mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0); -#ifdef WIRELESS_EXT /* If wireless extension exist in the kernel */ +#ifdef WIRELESS_EXT /* if wireless extension exists in the kernel */ /* Don't forget to update statistics */ lp->wstats.discard.nwid += (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l; #endif /* WIRELESS_EXT */ - printk(KERN_DEBUG "##### wavelan modem status registers: #####\n"); + printk(KERN_DEBUG "##### WaveLAN modem status registers: #####\n"); #ifdef DEBUG_SHOW_UNUSED printk(KERN_DEBUG "mmc_unused0[]: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", m.mmr_unused0[0], @@ -1045,7 +1045,7 @@ m.mmr_unused0[6], m.mmr_unused0[7]); #endif /* DEBUG_SHOW_UNUSED */ - printk(KERN_DEBUG "Encryption algorythm: %02X - Status: %02X\n", + printk(KERN_DEBUG "Encryption algorithm: %02X - Status: %02X\n", m.mmr_des_avail, m.mmr_des_status); #ifdef DEBUG_SHOW_UNUSED printk(KERN_DEBUG "mmc_unused1[]: %02X:%02X:%02X:%02X:%02X\n", @@ -1093,7 +1093,7 @@ #ifdef DEBUG_I82586_SHOW /*------------------------------------------------------------------*/ /* - * Print the last block of the i82586 memory + * Print the last block of the i82586 memory. */ static void wv_scb_show(u_long ioaddr) @@ -1102,7 +1102,7 @@ obram_read(ioaddr, OFFSET_SCB, (unsigned char *)&scb, sizeof(scb)); - printk(KERN_DEBUG "##### wavelan system control block: #####\n"); + printk(KERN_DEBUG "##### WaveLAN system control block: #####\n"); printk(KERN_DEBUG "status: "); printk("stat 0x%x[%s%s%s%s] ", @@ -1163,7 +1163,7 @@ { /* net_local *lp = (net_local *) dev->priv; */ - printk(KERN_DEBUG "##### wavelan i82586 receiver unit status: #####\n"); + printk(KERN_DEBUG "##### WaveLAN i82586 receiver unit status: #####\n"); printk(KERN_DEBUG "ru:"); /* * Not implemented yet... @@ -1173,7 +1173,7 @@ /*------------------------------------------------------------------*/ /* - * Display info about one control block of the i82586 memory + * Display info about one control block of the i82586 memory. */ static void wv_cu_show_one(device * dev, @@ -1206,7 +1206,7 @@ /*------------------------------------------------------------------*/ /* - * Print status of the command unit of the i82586 + * Print status of the command unit of the i82586. */ static void wv_cu_show(device * dev) @@ -1215,7 +1215,7 @@ unsigned int i; u_short p; - printk(KERN_DEBUG "##### wavelan i82586 command unit status: #####\n"); + printk(KERN_DEBUG "##### WaveLAN i82586 command unit status: #####\n"); printk(KERN_DEBUG); for(i = 0, p = lp->tx_first_in_use; i < NTXBLOCKS; i++) @@ -1310,8 +1310,8 @@ /*------------------------------------------------------------------*/ /* - * This is the information which is displayed by the driver at startup - * There is a lot of flag to configure it at your will... + * This is the information which is displayed by the driver at startup. + * There are lots of flags for configuring it to your liking. */ static inline void wv_init_info(device * dev) @@ -1341,7 +1341,7 @@ printk("%s%02X", (i == 0) ? " " : ":", dev->dev_addr[i]); printk(", IRQ %d", dev->irq); - /* Print current network id */ + /* Print current network ID. */ if(psa.psa_nwid_select) printk(", nwid 0x%02X-%02X", psa.psa_nwid[0], psa.psa_nwid[1]); else @@ -1353,14 +1353,14 @@ { unsigned short freq; - /* Ask the EEprom to read the frequency from the first area */ + /* Ask the EEPROM to read the frequency from the first area */ fee_read(ioaddr, 0x00 /* 1st area - frequency... */, &freq, 1); /* Print frequency */ printk(", 2.00, %ld", (freq >> 6) + 2400L); - /* Hack !!! */ + /* Hack! */ if(freq & 0x20) printk(".5"); } @@ -1381,7 +1381,7 @@ printk("MCIA"); break; default: - printk("???"); + printk("?"); } printk(", "); switch (psa.psa_subband) @@ -1402,7 +1402,7 @@ printk("2430.5"); break; default: - printk("???"); + printk("?"); } } @@ -1417,7 +1417,7 @@ /********************* IOCTL, STATS & RECONFIG *********************/ /* - * We found here routines that are called by Linux on differents + * We found here routines that are called by Linux on different * occasions after the configuration and not for transmitting data * These may be called when the user use ifconfig, /proc/net/dev * or wireless extensions @@ -1425,7 +1425,7 @@ /*------------------------------------------------------------------*/ /* - * Get the current ethernet statistics. This may be called with the + * Get the current Ethernet statistics. This may be called with the * card open or closed. * Used when the user read /proc/net/dev */ @@ -1461,9 +1461,9 @@ dev->name, dev->flags, dev->mc_count); #endif - /* If we ask for promiscuous mode, - * or all multicast addresses (we don't have that !) - * or too much multicast addresses for the hardware filter */ + /* Are we asking for promiscuous mode, + * or all multicast addresses (we don't have that!) + * or too many multicast addresses for the hardware filter? */ if((dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI) || (dev->mc_count > I82586_MAX_MULTICAST_ADDRESSES)) @@ -1478,12 +1478,12 @@ wv_82586_reconfig(dev); - /* Tell the kernel that we are doing a really bad job... */ + /* Tell the kernel that we are doing a really bad job. */ dev->flags |= IFF_PROMISC; } } else - /* If there is some multicast addresses to send */ + /* Are there multicast addresses to send? */ if(dev->mc_list != (struct dev_mc_list *) NULL) { /* @@ -1522,7 +1522,7 @@ /*------------------------------------------------------------------*/ /* - * This function doesn't exist... + * This function doesn't exist. */ static int wavelan_set_mac_address(device * dev, @@ -1530,16 +1530,16 @@ { struct sockaddr * mac = addr; - /* Copy the address */ + /* Copy the address. */ memcpy(dev->dev_addr, mac->sa_data, WAVELAN_ADDR_SIZE); - /* Reconfig the beast */ + /* Reconfigure the beast. */ wv_82586_reconfig(dev); return 0; } -#ifdef WIRELESS_EXT /* If wireless extension exist in the kernel */ +#ifdef WIRELESS_EXT /* if wireless extension exists in the kernel */ /*------------------------------------------------------------------*/ /* @@ -1558,10 +1558,10 @@ #endif /* Setting by frequency */ - /* Theoritically, you may set any frequency between + /* Theoretically, you may set any frequency between * the two limits with a 0.5 MHz precision. In practice, * I don't want you to have trouble with local - * regulations... */ + * regulations. */ if((frequency->e == 1) && (frequency->m >= (int) 2.412e8) && (frequency->m <= (int) 2.487e8)) { @@ -1569,29 +1569,29 @@ } /* Setting by channel (same as wfreqsel) */ - /* Warning : each channel is 22MHz wide, so some of the channels - * will interfere... */ + /* Warning: each channel is 22 MHz wide, so some of the channels + * will interfere. */ if((frequency->e == 0) && (frequency->m >= 0) && (frequency->m < BAND_NUM)) { - /* frequency in 1/4 of MHz (as read in the offset register) */ + /* frequency in units of 250 kHz (as read in the offset register) */ short bands[] = { 0x30, 0x58, 0x64, 0x7A, 0x80, 0xA8, 0xD0, 0xF0, 0xF8, 0x150 }; - /* Get frequency offset */ + /* Get frequency offset. */ freq = bands[frequency->m] >> 1; } - /* Verify if the frequency is allowed */ + /* Verify that the frequency is allowed. */ if(freq != 0L) { u_short table[10]; /* Authorized frequency table */ - /* Read the frequency table */ + /* Read the frequency table. */ fee_read(ioaddr, 0x71 /* frequency table */, table, 10); #ifdef DEBUG_IOCTL_INFO - printk(KERN_DEBUG "Frequency table :"); + printk(KERN_DEBUG "Frequency table: "); for(i = 0; i < 10; i++) { printk(" %04X", @@ -1600,7 +1600,7 @@ printk("\n"); #endif - /* Look in the table if the frequency is allowed */ + /* Look in the table to see whether the frequency is allowed. */ if(!(table[9 - ((freq - 24) / 16)] & (1 << ((freq - 24) % 16)))) return -EINVAL; /* not allowed */ @@ -1608,7 +1608,7 @@ else return -EINVAL; - /* If we get a usable frequency */ + /* if we get a usable frequency */ if(freq != 0L) { unsigned short area[16]; @@ -1616,7 +1616,7 @@ unsigned short area_verify[16]; unsigned short dac_verify[2]; /* Corresponding gain (in the power adjust value table) - * see AT&T Wavelan Data Manual, REF 407-024689/E, page 3-8 + * see AT&T WaveLAN Data Manual, REF 407-024689/E, page 3-8 * & WCIN062D.DOC, page 6.2.9 */ unsigned short power_limit[] = { 40, 80, 120, 160, 0 }; int power_band = 0; /* Selected band */ @@ -1628,15 +1628,15 @@ (power_limit[++power_band] != 0)) ; - /* Read the first area */ + /* Read the first area. */ fee_read(ioaddr, 0x00, area, 16); - /* Read the DAC */ + /* Read the DAC. */ fee_read(ioaddr, 0x60, dac, 2); - /* Read the new power adjust value */ + /* Read the new power adjust value. */ fee_read(ioaddr, 0x6B - (power_band >> 1), &power_adjust, 1); if(power_band & 0x1) @@ -1645,7 +1645,7 @@ power_adjust &= 0xFF; #ifdef DEBUG_IOCTL_INFO - printk(KERN_DEBUG "Wavelan EEprom Area 1 :"); + printk(KERN_DEBUG "WaveLAN EEPROM Area 1: "); for(i = 0; i < 16; i++) { printk(" %04X", @@ -1653,11 +1653,11 @@ } printk("\n"); - printk(KERN_DEBUG "Wavelan EEprom DAC : %04X %04X\n", + printk(KERN_DEBUG "WaveLAN EEPROM DAC: %04X %04X\n", dac[0], dac[1]); #endif - /* Frequency offset (for info only...) */ + /* Frequency offset (for info only) */ area[0] = ((freq << 5) & 0xFFE0) | (area[0] & 0x1F); /* Receiver Principle main divider coefficient */ @@ -1668,43 +1668,43 @@ area[13] = (freq >> 1) + 2400L; area[12] = ((freq & 0x1) << 4) | (area[2] & 0xFFEF); - /* Others part of the area are flags, bit streams or unused... */ + /* Other parts of the area are flags, bit streams or unused. */ - /* Set the value in the DAC */ + /* Set the value in the DAC. */ dac[1] = ((power_adjust >> 1) & 0x7F) | (dac[1] & 0xFF80); dac[0] = ((power_adjust & 0x1) << 4) | (dac[0] & 0xFFEF); - /* Write the first area */ + /* Write the first area. */ fee_write(ioaddr, 0x00, area, 16); - /* Write the DAC */ + /* Write the DAC. */ fee_write(ioaddr, 0x60, dac, 2); - /* We now should verify here that the EEprom writting was ok */ + /* We now should verify here that the writing of the EEPROM was OK. */ - /* ReRead the first area */ + /* Reread the first area. */ fee_read(ioaddr, 0x00, area_verify, 16); - /* ReRead the DAC */ + /* Reread the DAC. */ fee_read(ioaddr, 0x60, dac_verify, 2); - /* Compare */ + /* Compare. */ if(memcmp(area, area_verify, 16 * 2) || memcmp(dac, dac_verify, 2 * 2)) { #ifdef DEBUG_IOCTL_ERROR - printk(KERN_INFO "Wavelan: wv_set_frequency : unable to write new frequency to EEprom (??)\n"); + printk(KERN_INFO "WaveLAN: wv_set_frequency: unable to write new frequency to EEPROM(?).\n"); #endif return -EOPNOTSUPP; } /* We must download the frequency parameters to the - * synthetisers (from the EEprom - area 1) - * Note : as the EEprom is auto decremented, we set the end + * synthesizers (from the EEPROM - area 1) + * Note: as the EEPROM is automatically decremented, we set the end * if the area... */ mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), 0x0F); mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), @@ -1714,7 +1714,7 @@ fee_wait(ioaddr, 100, 100); /* We must now download the power adjust value (gain) to - * the synthetisers (from the EEprom - area 7 - DAC) */ + * the synthesizers (from the EEPROM - area 7 - DAC) */ mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), 0x61); mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD); @@ -1723,9 +1723,9 @@ fee_wait(ioaddr, 100, 100); #ifdef DEBUG_IOCTL_INFO - /* Verification of what we have done... */ + /* Verification of what we have done */ - printk(KERN_DEBUG "Wavelan EEprom Area 1 :"); + printk(KERN_DEBUG "WaveLAN EEPROM Area 1: "); for(i = 0; i < 16; i++) { printk(" %04X", @@ -1733,7 +1733,7 @@ } printk("\n"); - printk(KERN_DEBUG "Wavelan EEprom DAC : %04X %04X\n", + printk(KERN_DEBUG "WaveLAN EEPROM DAC: %04X %04X\n", dac_verify[0], dac_verify[1]); #endif @@ -1760,7 +1760,7 @@ fee_read(ioaddr, 0x71 /* frequency table */, table, 10); - /* Look all frequencies */ + /* Check all frequencies */ i = 0; for(freq = 0; freq < 150; freq++) /* Look in the table if the frequency is allowed */ @@ -1770,7 +1770,7 @@ list[i].m = (((freq + 24) * 5) + 24000L) * 10000; list[i++].e = 1; - /* Check number */ + /* Check number. */ if(i >= max) return(i); } @@ -1781,9 +1781,9 @@ #ifdef WIRELESS_SPY /*------------------------------------------------------------------*/ /* - * Gather wireless spy statistics : for each packet, compare the source - * address with out list, and if match, get the stats... - * Sorry, but this function really need wireless extensions... + * Gather wireless spy statistics: for each packet, compare the source + * address with our list, and if they match, get the statistics. + * Sorry, but this function really needs the wireless extensions. */ static inline void wl_spy_gather(device * dev, @@ -1793,7 +1793,7 @@ net_local * lp = (net_local *) dev->priv; int i; - /* Look all addresses */ + /* Check all addresses. */ for(i = 0; i < lp->spy_number; i++) /* If match */ if(!memcmp(mac, lp->spy_address[i], WAVELAN_ADDR_SIZE)) @@ -1810,12 +1810,12 @@ #ifdef HISTOGRAM /*------------------------------------------------------------------*/ /* - * This function calculate an histogram on the signal level. + * This function calculates a histogram of the signal level. * As the noise is quite constant, it's like doing it on the SNR. * We have defined a set of interval (lp->his_range), and each time * the level goes in that interval, we increment the count (lp->his_sum). - * With this histogram you may detect if one wavelan is really weak, - * or you may also calculate the mean and standard deviation of the level... + * With this histogram you may detect if one WaveLAN is really weak, + * or you may also calculate the mean and standard deviation of the level. */ static inline void wl_his_gather(device * dev, @@ -1825,25 +1825,25 @@ u_char level = stats[0] & MMR_SIGNAL_LVL; int i; - /* Find the correct interval */ + /* Find the correct interval. */ i = 0; while((i < (lp->his_number - 1)) && (level >= lp->his_range[i++])) ; - /* Increment interval counter */ + /* Increment interval counter. */ (lp->his_sum[i])++; } #endif /* HISTOGRAM */ /*------------------------------------------------------------------*/ /* - * Perform ioctl : config & info stuff + * Perform ioctl: configuration and information * This is here that are treated the wireless extensions (iwconfig) */ static int -wavelan_ioctl(struct device * dev, /* Device on wich the ioctl apply */ - struct ifreq * rq, /* Data passed */ - int cmd) /* Ioctl number */ +wavelan_ioctl(struct device * dev, /* device on which the ioctl is applied */ + struct ifreq * rq, /* data passed */ + int cmd) /* ioctl number */ { u_long ioaddr = dev->base_addr; net_local * lp = (net_local *)dev->priv; /* lp is not unused */ @@ -1870,7 +1870,7 @@ break; case SIOCSIWNWID: - /* Set NWID in wavelan */ + /* Set NWID in WaveLAN. */ if(wrq->u.nwid.on) { /* Set NWID in psa */ @@ -1889,19 +1889,19 @@ } else { - /* Disable nwid in the psa */ + /* Disable NWID in the psa. */ psa.psa_nwid_select = 0x00; psa_write(ioaddr, lp->hacr, (char *)&psa.psa_nwid_select - (char *)&psa, (unsigned char *)&psa.psa_nwid_select, 1); - /* Disable nwid in the mmc (no filtering) */ + /* Disable NWID in the mmc (no filtering). */ mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), MMW_LOOPT_SEL_DIS_NWID); } break; case SIOCGIWNWID: - /* Read the NWID */ + /* Read the NWID. */ psa_read(ioaddr, lp->hacr, (char *)psa.psa_nwid - (char *)&psa, (unsigned char *)psa.psa_nwid, 3); wrq->u.nwid.nwid = (psa.psa_nwid[0] << 8) + psa.psa_nwid[1]; @@ -1909,7 +1909,7 @@ break; case SIOCSIWFREQ: - /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable) */ + /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */ if(!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) & (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) ret = wv_set_frequency(ioaddr, &(wrq->u.freq)); @@ -1918,14 +1918,14 @@ break; case SIOCGIWFREQ: - /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable) - * (does it work for everybody ??? - especially old cards...) */ + /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). + * Does it work for everybody, especially old cards? */ if(!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) & (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) { unsigned short freq; - /* Ask the EEprom to read the frequency from the first area */ + /* Ask the EEPROM to read the frequency from the first area */ fee_read(ioaddr, 0x00 /* 1st area - frequency... */, &freq, 1); wrq->u.freq.m = ((freq >> 5) * 5 + 24000L) * 10000; @@ -1949,7 +1949,7 @@ break; case SIOCSIWSENS: - /* Set the level threshold */ + /* Set the level threshold. */ if(!suser()) return -EPERM; psa.psa_thr_pre_set = wrq->u.sensitivity & 0x3F; @@ -1959,14 +1959,14 @@ break; case SIOCGIWSENS: - /* Read the level threshold */ + /* Read the level threshold. */ psa_read(ioaddr, lp->hacr, (char *)&psa.psa_thr_pre_set - (char *)&psa, (unsigned char *) &psa.psa_thr_pre_set, 1); wrq->u.sensitivity = psa.psa_thr_pre_set & 0x3F; break; case SIOCSIWENCODE: - /* Set encryption key */ + /* Set encryption key. */ if(!mmc_encr(ioaddr)) { ret = -EOPNOTSUPP; @@ -1974,7 +1974,7 @@ } if(wrq->u.encoding.method) - { /* enable encryption */ + { /* Enable encryption. */ int i; long long key = wrq->u.encoding.code; @@ -1994,7 +1994,7 @@ (unsigned char *) &psa.psa_encryption_key, 8); } else - { /* disable encryption */ + { /* Disable encryption. */ psa.psa_encryption_select = 0; psa_write(ioaddr, lp->hacr, (char *) &psa.psa_encryption_select - (char *) &psa, @@ -2005,14 +2005,14 @@ break; case SIOCGIWENCODE: - /* Read the encryption key */ + /* Read the encryption key. */ if(!mmc_encr(ioaddr)) { ret = -EOPNOTSUPP; break; } - /* only super-user can see encryption key */ + /* Only super-user can see encryption key. */ if(!suser()) { ret = -EPERM; @@ -2042,26 +2042,26 @@ break; case SIOCGIWRANGE: - /* Basic checking... */ + /* basic checking */ if(wrq->u.data.pointer != (caddr_t) 0) { struct iw_range range; - /* Verify the user buffer */ + /* Verify the user buffer. */ ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer, sizeof(struct iw_range)); if(ret) break; - /* Set the length (useless : its constant...) */ + /* Set the length (useless: it's constant). */ wrq->u.data.length = sizeof(struct iw_range); - /* Set information in the range struct */ + /* Set information in the range struct. */ range.throughput = 1.6 * 1024 * 1024; /* don't argue on this ! */ range.min_nwid = 0x0000; range.max_nwid = 0xFFFF; - /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable) */ + /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */ if(!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) & (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) { @@ -2077,14 +2077,14 @@ range.max_qual.level = MMR_SIGNAL_LVL; range.max_qual.noise = MMR_SILENCE_LVL; - /* Copy structure to the user buffer */ + /* Copy structure to the user buffer. */ copy_to_user(wrq->u.data.pointer, &range, sizeof(struct iw_range)); } break; case SIOCGIWPRIV: - /* Basic checking... */ + /* Basic checking */ if(wrq->u.data.pointer != (caddr_t) 0) { struct iw_priv_args priv[] = @@ -2102,10 +2102,10 @@ if(ret) break; - /* Set the number of ioctl available */ + /* Set the number of available ioctls. */ wrq->u.data.length = 4; - /* Copy structure to the user buffer */ + /* Copy structure to the user buffer. */ copy_to_user(wrq->u.data.pointer, (u_char *) priv, sizeof(priv)); } @@ -2115,7 +2115,7 @@ case SIOCSIWSPY: /* Set the spy list */ - /* Check the number of addresses */ + /* Check the number of addresses. */ if(wrq->u.data.length > IW_MAX_SPY) { ret = -E2BIG; @@ -2123,33 +2123,33 @@ } lp->spy_number = wrq->u.data.length; - /* If there is some addresses to copy */ + /* Are there are addresses to copy? */ if(lp->spy_number > 0) { struct sockaddr address[IW_MAX_SPY]; int i; - /* Verify where the user has set his addresses */ + /* Verify where the user has set his addresses. */ ret = verify_area(VERIFY_READ, wrq->u.data.pointer, sizeof(struct sockaddr) * lp->spy_number); if(ret) break; - /* Copy addresses to the driver */ + /* Copy addresses to the driver. */ copy_from_user(address, wrq->u.data.pointer, sizeof(struct sockaddr) * lp->spy_number); - /* Copy addresses to the lp structure */ + /* Copy addresses to the lp structure. */ for(i = 0; i < lp->spy_number; i++) { memcpy(lp->spy_address[i], address[i].sa_data, WAVELAN_ADDR_SIZE); } - /* Reset structure... */ + /* Reset structure. */ memset(lp->spy_stat, 0x00, sizeof(iw_qual) * IW_MAX_SPY); #ifdef DEBUG_IOCTL_INFO - printk(KERN_DEBUG "SetSpy - Set of new addresses is :\n"); + printk(KERN_DEBUG "SetSpy - Set of new addresses is: \n"); for(i = 0; i < wrq->u.data.length; i++) printk(KERN_DEBUG "%02X:%02X:%02X:%02X:%02X:%02X \n", lp->spy_address[i][0], @@ -2164,25 +2164,25 @@ break; case SIOCGIWSPY: - /* Get the spy list and spy stats */ + /* Get the spy list and spy stats. */ /* Set the number of addresses */ wrq->u.data.length = lp->spy_number; - /* If the user want to have the addresses back... */ + /* Does the user want to have the addresses back? */ if((lp->spy_number > 0) && (wrq->u.data.pointer != (caddr_t) 0)) { struct sockaddr address[IW_MAX_SPY]; int i; - /* Verify the user buffer */ + /* Verify the user buffer. */ ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer, (sizeof(iw_qual) + sizeof(struct sockaddr)) * IW_MAX_SPY); if(ret) break; - /* Copy addresses from the lp structure */ + /* Copy addresses from the lp structure. */ for(i = 0; i < lp->spy_number; i++) { memcpy(address[i].sa_data, lp->spy_address[i], @@ -2190,16 +2190,16 @@ address[i].sa_family = AF_UNIX; } - /* Copy addresses to the user buffer */ + /* Copy addresses to the user buffer. */ copy_to_user(wrq->u.data.pointer, address, sizeof(struct sockaddr) * lp->spy_number); - /* Copy stats to the user buffer (just after) */ + /* Copy stats to the user buffer (just after). */ copy_to_user(wrq->u.data.pointer + (sizeof(struct sockaddr) * lp->spy_number), lp->spy_stat, sizeof(iw_qual) * lp->spy_number); - /* Reset updated flags */ + /* Reset updated flags. */ for(i = 0; i < lp->spy_number; i++) lp->spy_stat[i].updated = 0x0; } /* if(pointer != NULL) */ @@ -2230,7 +2230,7 @@ if(!suser()) return -EPERM; - /* Check the number of intervals */ + /* Check the number of intervals. */ if(wrq->u.data.length > 16) { ret = -E2BIG; @@ -2238,10 +2238,10 @@ } lp->his_number = wrq->u.data.length; - /* If there is some addresses to copy */ + /* Are there addresses to copy? */ if(lp->his_number > 0) { - /* Verify where the user has set his addresses */ + /* Verify where the user has set his addresses. */ ret = verify_area(VERIFY_READ, wrq->u.data.pointer, sizeof(char) * lp->his_number); if(ret) @@ -2250,25 +2250,25 @@ copy_from_user(lp->his_range, wrq->u.data.pointer, sizeof(char) * lp->his_number); - /* Reset structure... */ + /* Reset structure. */ memset(lp->his_sum, 0x00, sizeof(long) * 16); } break; case SIOCGIPHISTO: - /* Set the number of intervals */ + /* Set the number of intervals. */ wrq->u.data.length = lp->his_number; /* Give back the distribution statistics */ if((lp->his_number > 0) && (wrq->u.data.pointer != (caddr_t) 0)) { - /* Verify the user buffer */ + /* Verify the user buffer. */ ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer, sizeof(long) * 16); if(ret) break; - /* Copy data to the user buffer */ + /* Copy data to the user buffer. */ copy_to_user(wrq->u.data.pointer, lp->his_sum, sizeof(long) * lp->his_number); } /* if(pointer != NULL) */ @@ -2281,7 +2281,7 @@ ret = -EOPNOTSUPP; } - /* ReEnable interrupts & restore flags */ + /* Enable interrupts and restore flags. */ wv_splx(x); #ifdef DEBUG_IOCTL_TRACE @@ -2292,8 +2292,8 @@ /*------------------------------------------------------------------*/ /* - * Get wireless statistics - * Called by /proc/net/wireless... + * Get wireless statistics. + * Called by /proc/net/wireless */ static iw_stats * wavelan_get_wireless_stats(device * dev) @@ -2308,14 +2308,14 @@ printk(KERN_DEBUG "%s: ->wavelan_get_wireless_stats()\n", dev->name); #endif - /* Disable interrupts & save flags */ + /* Disable interrupts and save flags. */ x = wv_splhi(); if(lp == (net_local *) NULL) return (iw_stats *) NULL; wstats = &lp->wstats; - /* Get data from the mmc */ + /* Get data from the mmc. */ mmc_out(ioaddr, mmwoff(0, mmw_freeze), 1); mmc_read(ioaddr, mmroff(0, mmr_dce_status), &m.mmr_dce_status, 1); @@ -2324,7 +2324,7 @@ mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0); - /* Copy data to wireless stuff */ + /* Copy data to wireless stuff. */ wstats->status = m.mmr_dce_status; wstats->qual.qual = m.mmr_sgnl_qual & MMR_SGNL_QUAL; wstats->qual.level = m.mmr_signal_lvl & MMR_SIGNAL_LVL; @@ -2336,7 +2336,7 @@ wstats->discard.code = 0L; wstats->discard.misc = 0L; - /* ReEnable interrupts & restore flags */ + /* Enable interrupts and restore flags. */ wv_splx(x); #ifdef DEBUG_IOCTL_TRACE @@ -2348,22 +2348,22 @@ /************************* PACKET RECEPTION *************************/ /* - * This part deal with receiving the packets. - * The interrupt handler get an interrupt when a packet has been - * successfully received and called this part... + * This part deals with receiving the packets. + * The interrupt handler gets an interrupt when a packet has been + * successfully received and calls this part. */ /*------------------------------------------------------------------*/ /* - * This routine does the actual copy of data (including the ethernet + * This routine does the actual copying of data (including the Ethernet * header structure) from the WaveLAN card to an sk_buff chain that - * will be passed up to the network interface layer. NOTE: We + * will be passed up to the network interface layer. NOTE: we * currently don't handle trailer protocols (neither does the rest of * the network interface), so if that is needed, it will (at least in * part) be added here. The contents of the receive ring buffer are * copied to a message chain that is then passed to the kernel. * - * Note: if any errors occur, the packet is "dropped on the floor" + * Note: if any errors occur, the packet is "dropped on the floor". * (called by wv_packet_rcv()) */ static inline void @@ -2393,7 +2393,7 @@ skb->dev = dev; - /* Copy the packet to the buffer */ + /* Copy the packet to the buffer. */ obram_read(ioaddr, buf_off, skb_put(skb, sksize), sksize); skb->protocol=eth_type_trans(skb, dev); @@ -2401,7 +2401,7 @@ wv_packet_info(skb->mac.raw, sksize, dev->name, "wv_packet_read"); #endif /* DEBUG_RX_INFO */ - /* Statistics gathering & stuff associated. + /* Statistics-gathering and associated stuff. * It seem a bit messy with all the define, but it's really simple... */ #if defined(WIRELESS_SPY) || defined(HISTOGRAM) if( @@ -2413,13 +2413,13 @@ #endif /* HISTOGRAM */ 0) { - u_char stats[3]; /* Signal level, Noise level, Signal quality */ + u_char stats[3]; /* signal level, noise level, signal quality */ - /* read signal level, silence level and signal quality bytes */ - /* Note : in the Pcmcia hardware, these are part of the frame. It seem + /* Read signal level, silence level and signal quality bytes. */ + /* Note: in the PCMCIA hardware, these are part of the frame. It seems * that for the ISA hardware, it's nowhere to be found in the frame, - * so I'm oblige to do this (it has side effect on /proc/net/wireless) - * Any idea ? */ + * so I'm obliged to do this (it has a side effect on /proc/net/wireless). + * Any ideas? */ mmc_out(ioaddr, mmwoff(0, mmw_freeze), 1); mmc_read(ioaddr, mmroff(0, mmr_signal_lvl), stats, 3); mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0); @@ -2440,11 +2440,11 @@ #endif /* defined(WIRELESS_SPY) || defined(HISTOGRAM) */ /* - * Hand the packet to the Network Module + * Hand the packet to the network module. */ netif_rx(skb); - /* Keep stats up to date */ + /* Keep statistics up to date */ lp->stats.rx_packets++; lp->stats.rx_bytes += skb->len; @@ -2470,7 +2470,7 @@ printk(KERN_DEBUG "%s: ->wv_receive()\n", dev->name); #endif - /* Loop on each received packet */ + /* Loop on each received packet. */ for(;;) { fd_t fd; @@ -2479,13 +2479,13 @@ obram_read(ioaddr, lp->rx_head, (unsigned char *) &fd, sizeof(fd)); - /* If the current frame is not complete, we have reach the end... */ + /* If the current frame is not complete, we have reached the end. */ if((fd.fd_status & FD_STATUS_C) != FD_STATUS_C) - break; /* This is how we exit the loop */ + break; /* This is how we exit the loop. */ nreaped++; - /* Check if frame correctly received */ + /* Check whether frame was correctly received. */ if((fd.fd_status & (FD_STATUS_B | FD_STATUS_OK)) != (FD_STATUS_B | FD_STATUS_OK)) { @@ -2508,7 +2508,7 @@ #endif } - /* Check is there was problems in the frame processing */ + /* Were there problems in processing the frame? Let's check. */ if((fd.fd_status & (FD_STATUS_S6 | FD_STATUS_S7 | FD_STATUS_S8 | FD_STATUS_S9 | FD_STATUS_S10 | FD_STATUS_S11)) != 0) @@ -2565,7 +2565,7 @@ } } - /* Check if frame contain a pointer to the data */ + /* Does the frame contain a pointer to the data? Let's check. */ if(fd.fd_rbd_offset == I82586NULL) #ifdef DEBUG_RX_ERROR printk(KERN_INFO "%s: wv_receive(): frame has no data.\n", dev->name); @@ -2618,7 +2618,7 @@ /*********************** PACKET TRANSMISSION ***********************/ /* - * This part deal with sending packet through the wavelan + * This part deals with sending packets through the WaveLAN. * */ @@ -2628,13 +2628,13 @@ * locations on the WaveLAN card and starts the card off on * the transmit. * - * The principle : - * Each block contains a transmit command, a nop command, + * The principle: + * Each block contains a transmit command, a NOP command, * a transmit block descriptor and a buffer. * The CU reads the transmit block which points to the tbd, * reads the tbd and the content of the buffer. * When it has finished with it, it goes to the next command - * which in our case is the nop. The nop points on itself, + * which in our case is the NOP. The NOP points on itself, * so the CU stops here. * When we add the next block, we modify the previous nop * to make it point on the new tx command. @@ -2665,13 +2665,13 @@ printk(KERN_DEBUG "%s: ->wv_packet_write(%d)\n", dev->name, length); #endif - /* Check if we need some padding */ + /* Do we need some padding? */ if(clen < ETH_ZLEN) clen = ETH_ZLEN; x = wv_splhi(); - /* Calculate addresses of next block and previous block */ + /* Calculate addresses of next block and previous block. */ txblock = lp->tx_first_free; txpred = txblock - TXBLOCKZ; if(txpred < OFFSET_CU) @@ -2687,14 +2687,14 @@ lp->tx_n_in_use++; - /* Calculate addresses of the differents part of the block */ + /* Calculate addresses of the different parts of the block. */ tx_addr = txblock; nop_addr = tx_addr + sizeof(tx); tbd_addr = nop_addr + sizeof(nop); buf_addr = tbd_addr + sizeof(tbd); /* - * Transmit command. + * Transmit command */ tx.tx_h.ac_status = 0; obram_write(ioaddr, toff(ac_tx_t, tx_addr, tx_h.ac_status), @@ -2702,7 +2702,7 @@ sizeof(tx.tx_h.ac_status)); /* - * NOP command. + * NOP command */ nop.nop_h.ac_status = 0; obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status), @@ -2714,7 +2714,7 @@ sizeof(nop.nop_h.ac_link)); /* - * Transmit buffer descriptor. + * Transmit buffer descriptor */ tbd.tbd_status = TBD_STATUS_EOF | (TBD_STATUS_ACNT & clen); tbd.tbd_next_bd_offset = I82586NULL; @@ -2723,7 +2723,7 @@ obram_write(ioaddr, tbd_addr, (unsigned char *)&tbd, sizeof(tbd)); /* - * Data. + * Data */ obram_write(ioaddr, buf_addr, buf, clen); @@ -2741,13 +2741,13 @@ (unsigned char *) &nop.nop_h.ac_link, sizeof(nop.nop_h.ac_link)); - /* Keep stats up to date */ + /* Keep stats up to date. */ lp->stats.tx_bytes += length; /* If watchdog not already active, activate it... */ if(lp->watchdog.prev == (timer_list *) NULL) { - /* set timer to expire in WATCHDOG_JIFFIES */ + /* Set timer to expire in WATCHDOG_JIFFIES. */ lp->watchdog.expires = jiffies + WATCHDOG_JIFFIES; add_timer(&lp->watchdog); } @@ -2774,7 +2774,7 @@ * This routine is called when we want to send a packet (NET3 callback) * In this routine, we check if the hardware is ready to accept * the packet. We also prevent reentrance. Then, we call the function - * to send the packet... + * to send the packet. */ static int wavelan_packet_xmit(struct sk_buff * skb, @@ -2788,9 +2788,9 @@ #endif /* This flag indicate that the hardware can't perform a transmission. - * Theoritically, NET3 check it before sending a packet to the driver, - * but in fact it never do that and pool continuously. - * As the watchdog will abort too long transmissions, we are quite safe... + * Theoretically, NET3 checks it before sending a packet to the driver, + * but in fact it never does that and pools continuously. + * As the watchdog will abort overly long transmissions, we are quite safe. */ if(dev->tbusy) return 1; @@ -2805,7 +2805,9 @@ #endif else { - /* If somebody has asked to reconfigure the controler, we can do it now */ + /* If somebody has asked to reconfigure the controller, + * we can do it now. + */ if(lp->reconfig_82586) { wv_82586_config(dev); @@ -2829,12 +2831,12 @@ return 0; } -/********************** HARDWARE CONFIGURATION **********************/ +/*********************** HARDWARE CONFIGURATION ***********************/ /* - * This part do the real job of starting and configuring the hardware. + * This part does the real job of starting and configuring the hardware. */ -/*------------------------------------------------------------------*/ +/*--------------------------------------------------------------------*/ /* * Routine to initialize the Modem Management Controller. * (called by wv_hw_reset()) @@ -2852,7 +2854,7 @@ printk(KERN_DEBUG "%s: ->wv_mmc_init()\n", dev->name); #endif - /* Read the parameter storage area */ + /* Read the parameter storage area. */ psa_read(ioaddr, lp->hacr, 0, (unsigned char *) &psa, sizeof(psa)); #ifdef USE_PSA_CONFIG @@ -2864,11 +2866,11 @@ /* Is the PSA is not configured */ if(!configured) { - /* User will be able to configure NWID after (with iwconfig) */ + /* User will be able to configure NWID later (with iwconfig). */ psa.psa_nwid[0] = 0; psa.psa_nwid[1] = 0; - /* As NWID is not set : no NWID checking */ + /* no NWID checking since NWID is not set */ psa.psa_nwid_select = 0; /* Disable encryption */ @@ -2901,10 +2903,10 @@ #endif } - /* Zero the mmc structure */ + /* Zero the mmc structure. */ memset(&m, 0x00, sizeof(m)); - /* Copy PSA info to the mmc */ + /* Copy PSA info to the mmc. */ m.mmw_netw_id_l = psa.psa_nwid[1]; m.mmw_netw_id_h = psa.psa_nwid[0]; @@ -2924,7 +2926,7 @@ m.mmw_thr_pre_set = psa.psa_thr_pre_set & 0x3F; m.mmw_quality_thr = psa.psa_quality_thr & 0x0F; - /* Missing : encryption stuff... */ + /* Encryption stuff is missing. */ /* * Set default modem control parameters. @@ -2942,58 +2944,58 @@ m.mmw_decay_prm = 0; m.mmw_decay_updat_prm = 0; - /* Write all info to mmc */ + /* Write all info to MMC. */ mmc_write(ioaddr, 0, (u_char *)&m, sizeof(m)); - /* The following code start the modem of the 2.00 frequency + /* The following code starts the modem of the 2.00 frequency * selectable cards at power on. It's not strictly needed for the - * following boots... + * following boots. * The original patch was by Joe Finney for the PCMCIA driver, but - * I've cleaned it a bit and add documentation. + * I've cleaned it up a bit and added documentation. * Thanks to Loeke Brederveld from Lucent for the info. */ /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable) - * (does it work for everybody ??? - especially old cards...) */ - /* Note : WFREQSEL verify that it is able to read from EEprom - * a sensible frequency (address 0x00) + that MMR_FEE_STATUS_ID - * is 0xA (Xilinx version) or 0xB (Ariadne version). - * My test is more crude but do work... */ + * Does it work for everybody, especially old cards? */ + /* Note: WFREQSEL verifies that it is able to read a sensible + * frequency from from EEPROM (address 0x00) and that + * MMR_FEE_STATUS_ID is 0xA (Xilinx version) or 0xB (Ariadne version). + * My test is more crude but does work. */ if(!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) & (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) { /* We must download the frequency parameters to the - * synthetisers (from the EEprom - area 1) - * Note : as the EEprom is auto decremented, we set the end + * synthesizers (from the EEPROM - area 1) + * Note: as the EEPROM is automatically decremented, we set the end * if the area... */ m.mmw_fee_addr = 0x0F; m.mmw_fee_ctrl = MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD; mmc_write(ioaddr, (char *)&m.mmw_fee_ctrl - (char *)&m, (unsigned char *)&m.mmw_fee_ctrl, 2); - /* Wait until the download is finished */ + /* Wait until the download is finished. */ fee_wait(ioaddr, 100, 100); #ifdef DEBUG_CONFIG_INFO - /* The frequency was in the last word downloaded... */ + /* The frequency was in the last word downloaded. */ mmc_read(ioaddr, (char *)&m.mmw_fee_data_l - (char *)&m, (unsigned char *)&m.mmw_fee_data_l, 2); - /* Print some info for the user */ - printk(KERN_DEBUG "%s: Wavelan 2.00 recognised (frequency select) : Current frequency = %ld\n", + /* Print some info for the user. */ + printk(KERN_DEBUG "%s: WaveLAN 2.00 recognised (frequency select). Current frequency = %ld\n", dev->name, ((m.mmw_fee_data_h << 4) | (m.mmw_fee_data_l >> 4)) * 5 / 2 + 24000L); #endif /* We must now download the power adjust value (gain) to - * the synthetisers (from the EEprom - area 7 - DAC) */ + * the synthesizers (from the EEPROM - area 7 - DAC). */ m.mmw_fee_addr = 0x61; m.mmw_fee_ctrl = MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD; mmc_write(ioaddr, (char *)&m.mmw_fee_ctrl - (char *)&m, (unsigned char *)&m.mmw_fee_ctrl, 2); - /* Wait until the download is finished */ + /* Wait until the download is finished. */ } /* if 2.00 card */ #ifdef DEBUG_CONFIG_TRACE @@ -3091,13 +3093,13 @@ * Start the command unit executing the NOP * self-loop of the first transmit block. * - * Here, we create the list of send buffer used to transmit packets + * Here we create the list of send buffers used to transmit packets * between the PC and the command unit. For each buffer, we create a * buffer descriptor (pointing on the buffer), a transmit command - * (pointing to the buffer descriptor) and a nop command. - * The transmit command is linked to the nop, and the nop to itself. - * When we will have finish to execute the transmit command, we will - * then loop on the nop. By releasing the nop link to a new command, + * (pointing to the buffer descriptor) and a NOP command. + * The transmit command is linked to the NOP, and the NOP to itself. + * When we will have finished executing the transmit command, we will + * then loop on the NOP. By releasing the NOP link to a new command, * we may send another buffer. * * (called by wv_hw_reset()) @@ -3194,12 +3196,13 @@ /*------------------------------------------------------------------*/ /* - * This routine does a standard config of the WaveLAN controler (i82586). + * This routine does a standard configuration of the WaveLAN + * controller (i82586). * - * It initialise the scp, iscp and scb structure - * The two first are only pointer to the next. + * It initialises the scp, iscp and scb structure + * The first two are just pointers to the next. * The last one is used for basic configuration and for basic - * communication (interrupt status) + * communication (interrupt status). * * (called by wv_hw_reset()) */ @@ -3240,7 +3243,7 @@ iscp.iscp_offset = OFFSET_SCB; obram_write(ioaddr, OFFSET_ISCP, (unsigned char *)&iscp, sizeof(iscp)); - /* Our first command is to reset the i82586 */ + /* Our first command is to reset the i82586. */ memset(&scb, 0x00, sizeof(scb)); scb.scb_command = SCB_CMD_RESET; scb.scb_cbl_offset = OFFSET_CU; @@ -3249,7 +3252,7 @@ set_chan_attn(ioaddr, lp->hacr); - /* Wait for command to finish */ + /* Wait for command to finish. */ for(i = 1000; i > 0; i--) { obram_read(ioaddr, OFFSET_ISCP, (unsigned char *) &iscp, sizeof(iscp)); @@ -3269,7 +3272,7 @@ return -1; } - /* Check command completion */ + /* Check command completion. */ for(i = 15; i > 0; i--) { obram_read(ioaddr, OFFSET_SCB, (unsigned char *) &scb, sizeof(scb)); @@ -3291,7 +3294,7 @@ wv_ack(dev); - /* Set the action command header */ + /* Set the action command header. */ memset(&cb, 0x00, sizeof(cb)); cb.ac_command = AC_CFLD_EL | (AC_CFLD_CMD & acmd_diagnose); cb.ac_link = OFFSET_CU; @@ -3322,14 +3325,15 @@ /*------------------------------------------------------------------*/ /* - * This routine does a standard config of the WaveLAN controler (i82586). + * This routine does a standard configuration of the WaveLAN + * controller (i82586). * * This routine is a violent hack. We use the first free transmit block * to make our configuration. In the buffer area, we create the three - * configure command (linked). We make the previous nop point to the - * beggining of the buffer instead of the tx command. After, we go as - * usual to the nop command... - * Note that only the last command (mc_set) will generate an interrupt... + * configuration commands (linked). We make the previous NOP point to + * the beginning of the buffer instead of the tx command. After, we go + * as usual to the NOP command. + * Note that only the last command (mc_set) will generate an interrupt. * * (called by wv_hw_reset(), wv_82586_reconfig()) */ @@ -3360,7 +3364,7 @@ x = wv_splhi(); - /* Calculate addresses of next block and previous block */ + /* Calculate addresses of next block and previous block. */ txblock = lp->tx_first_free; txpred = txblock - TXBLOCKZ; if(txpred < OFFSET_CU) @@ -3371,16 +3375,16 @@ lp->tx_n_in_use++; - /* Calculate addresses of the differents part of the block */ + /* Calculate addresses of the different parts of the block. */ tx_addr = txblock; nop_addr = tx_addr + sizeof(tx); tbd_addr = nop_addr + sizeof(nop); - cfg_addr = tbd_addr + sizeof(tbd_t); /* beggining of the buffer */ + cfg_addr = tbd_addr + sizeof(tbd_t); /* beginning of the buffer */ ias_addr = cfg_addr + sizeof(cfg); mcs_addr = ias_addr + sizeof(ias); /* - * Transmit command. + * Transmit command */ tx.tx_h.ac_status = 0xFFFF; /* Fake completion value */ obram_write(ioaddr, toff(ac_tx_t, tx_addr, tx_h.ac_status), @@ -3388,7 +3392,7 @@ sizeof(tx.tx_h.ac_status)); /* - * NOP command. + * NOP command */ nop.nop_h.ac_status = 0; obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status), @@ -3399,23 +3403,23 @@ (unsigned char *) &nop.nop_h.ac_link, sizeof(nop.nop_h.ac_link)); - /* Create a configure action */ + /* Create a configure action. */ memset(&cfg, 0x00, sizeof(cfg)); #if 0 /* - * The default board configuration. + * The default board configuration */ cfg.fifolim_bytecnt = 0x080c; cfg.addrlen_mode = 0x2600; cfg.linprio_interframe = 0x7820; /* IFS=120, ACS=2 */ cfg.slot_time = 0xf00c; /* slottime=12 */ - cfg.hardware = 0x0008; /* tx even w/o CD */ + cfg.hardware = 0x0008; /* tx even without CD */ cfg.min_frame_len = 0x0040; #endif /* 0 */ /* - * For Linux we invert AC_CFG_ALOC(..) so as to conform + * For Linux we invert AC_CFG_ALOC() so as to conform * to the way that net packets reach us from above. * (See also ac_tx_t.) */ @@ -3456,21 +3460,21 @@ cfg.cfg_h.ac_link = ias_addr; obram_write(ioaddr, cfg_addr, (unsigned char *)&cfg, sizeof(cfg)); - /* Setup the MAC address */ + /* Set up the MAC address */ memset(&ias, 0x00, sizeof(ias)); ias.ias_h.ac_command = (AC_CFLD_CMD & acmd_ia_setup); ias.ias_h.ac_link = mcs_addr; memcpy(&ias.ias_addr[0], (unsigned char *)&dev->dev_addr[0], sizeof(ias.ias_addr)); obram_write(ioaddr, ias_addr, (unsigned char *)&ias, sizeof(ias)); - /* Initialize adapter's ethernet multicast addresses */ + /* Initialize adapter's Ethernet multicast addresses */ memset(&mcs, 0x00, sizeof(mcs)); mcs.mcs_h.ac_command = AC_CFLD_I | (AC_CFLD_CMD & acmd_mc_setup); mcs.mcs_h.ac_link = nop_addr; mcs.mcs_cnt = WAVELAN_ADDR_SIZE * lp->mc_count; obram_write(ioaddr, mcs_addr, (unsigned char *)&mcs, sizeof(mcs)); - /* If any address to set */ + /* Any address to set? */ if(lp->mc_count) { for(dmi=dev->mc_list; dmi; dmi=dmi->next) @@ -3526,8 +3530,8 @@ /*------------------------------------------------------------------*/ /* - * This routine stop gracefully the WaveLAN controler (i82586). - * (called by wavelan_close()) + * This routine, called by wavelan_close(), gracefully stops the + * WaveLAN controller (i82586). */ static inline void wv_82586_stop(device * dev) @@ -3540,7 +3544,7 @@ printk(KERN_DEBUG "%s: ->wv_82586_stop()\n", dev->name); #endif - /* Suspend both command unit and receive unit */ + /* Suspend both command unit and receive unit. */ scb_cmd = (SCB_CMD_CUC & SCB_CMD_CUC_SUS) | (SCB_CMD_RUC & SCB_CMD_RUC_SUS); obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&scb_cmd, sizeof(scb_cmd)); @@ -3556,7 +3560,7 @@ /*------------------------------------------------------------------*/ /* - * Totally reset the wavelan and restart it. + * Totally reset the WaveLAN and restart it. * Performs the following actions: * 1. A power reset (reset DMA) * 2. Initialize the radio modem (using wv_mmc_init) @@ -3575,11 +3579,11 @@ (unsigned int)dev); #endif - /* If watchdog was activated, kill it ! */ + /* If watchdog was activated, kill it! */ if(lp->watchdog.prev != (timer_list *) NULL) del_timer(&lp->watchdog); - /* Increase the number of resets done */ + /* Increase the number of resets done. */ lp->nresets++; wv_hacr_reset(ioaddr); @@ -3589,7 +3593,7 @@ (wv_82586_start(dev) < 0)) return -1; - /* Enable the card to send interrupts */ + /* Enable the card to send interrupts. */ wv_ints_on(dev); /* Start card functions */ @@ -3597,7 +3601,7 @@ (wv_cu_start(dev) < 0)) return -1; - /* Finish configuration */ + /* Finish configuration. */ wv_82586_config(dev); #ifdef DEBUG_CONFIG_TRACE @@ -3608,8 +3612,8 @@ /*------------------------------------------------------------------*/ /* - * Check if there is a wavelan at the specific base address. - * As a side effect, it read the MAC address. + * Check if there is a WaveLAN at the specific base address. + * As a side effect, this reads the MAC address. * (called in wavelan_probe() and init_module()) */ static int @@ -3618,22 +3622,22 @@ { int i; /* Loop counter */ - /* Check if the base address if available */ + /* Check if the base address if available. */ if(check_region(ioaddr, sizeof(ha_t))) - return EADDRINUSE; /* ioaddr already used... */ + return EADDRINUSE; /* ioaddr already used */ /* Reset host interface */ wv_hacr_reset(ioaddr); - /* Read the MAC address from the parameter storage area */ + /* Read the MAC address from the parameter storage area. */ psa_read(ioaddr, HACR_DEFAULT, psaoff(0, psa_univ_mac_addr), mac, 6); /* - * Check the first three octets of the addr for the manufacturer's code. - * Note: If you can't find your wavelan card, you've got a - * non-NCR/AT&T/Lucent ISA cards, see wavelan.p.h for detail on - * how to configure your card... + * Check the first three octets of the address for the manufacturer's code. + * Note: if this can't find your WaveLAN card, you've got a + * non-NCR/AT&T/Lucent ISA card. See wavelan.p.h for detail on + * how to configure your card. */ for(i = 0; i < (sizeof(MAC_ADDRESSES) / sizeof(char) / 3); i++) if((mac[0] == MAC_ADDRESSES[i][0]) && @@ -3642,7 +3646,7 @@ return 0; #ifdef DEBUG_CONFIG_INFO - printk(KERN_WARNING "Wavelan (0x%3X) : Your MAC address might be : %02X:%02X:%02X...\n", + printk(KERN_WARNING "WaveLAN (0x%3X): your MAC address might be %02X:%02X:%02X.\n", ioaddr, mac[0], mac[1], mac[2]); #endif return ENODEV; @@ -3675,7 +3679,7 @@ lp = (net_local *) dev->priv; ioaddr = dev->base_addr; - /* Prevent reentrance. What should we do here ? */ + /* Prevent reentrance. What should we do here? */ #ifdef DEBUG_INTERRUPT_ERROR if(dev->interrupt) printk(KERN_INFO "%s: wavelan_interrupt(): Re-entering the interrupt handler.\n", @@ -3708,7 +3712,7 @@ return; } - /* Read interrupt data */ + /* Read interrupt data. */ obram_read(ioaddr, scboff(OFFSET_SCB, scb_status), (unsigned char *) &status, sizeof(status)); @@ -3755,7 +3759,7 @@ wv_receive(dev); } - /* Check the state of the command unit */ + /* Check the state of the command unit. */ if(((status & SCB_ST_CNA) == SCB_ST_CNA) || (((status & SCB_ST_CUS) != SCB_ST_CUS_ACTV) && dev->start)) { @@ -3766,7 +3770,7 @@ wv_hw_reset(dev); } - /* Check the state of the command unit */ + /* Check the state of the command unit. */ if(((status & SCB_ST_RNR) == SCB_ST_RNR) || (((status & SCB_ST_RUS) != SCB_ST_RUS_RDY) && dev->start)) { @@ -3786,14 +3790,14 @@ /*------------------------------------------------------------------*/ /* - * Watchdog : when we start a transmission, we set a timer in the - * kernel. If the transmission complete, this timer is disabled. If - * it expire, it try to unlock the hardware. + * Watchdog: when we start a transmission, we set a timer in the + * kernel. If the transmission completes, this timer is disabled. If + * the timer expires, we try to unlock the hardware. * - * Note : this watchdog doesn't work on the same principle as the - * watchdog in the previous version of the ISA driver. I make it this + * Note: this watchdog doesn't work on the same principle as the + * watchdog in the previous version of the ISA driver. I made it this * way because the overhead of add_timer() and del_timer() is nothing - * and that it avoid calling the watchdog, saving some CPU... + * and because it avoids calling the watchdog, saving some CPU. */ static void wavelan_watchdog(u_long a) @@ -3860,7 +3864,7 @@ wv_hw_reset(dev); } else - /* Re-set watchodog for next transmission */ + /* Reset watchdog for next transmission. */ if(lp->tx_n_in_use > 0) { /* set timer to expire in WATCHDOG_JIFFIES */ @@ -3877,15 +3881,15 @@ /********************* CONFIGURATION CALLBACKS *********************/ /* - * Here are the functions called by the linux networking (NET3) for - * initialization, configuration and deinstallations of the Wavelan - * ISA Hardware. + * Here are the functions called by the Linux networking code (NET3) + * for initialization, configuration and deinstallations of the + * WaveLAN ISA hardware. */ /*------------------------------------------------------------------*/ /* * Configure and start up the WaveLAN PCMCIA adaptor. - * Called by NET3 when it "open" the device. + * Called by NET3 when it "opens" the device. */ static int wavelan_open(device * dev) @@ -3901,7 +3905,7 @@ if(dev->irq == 0) { #ifdef DEBUG_CONFIG_ERRORS - printk(KERN_WARNING "%s: wavelan_open(): no irq\n", dev->name); + printk(KERN_WARNING "%s: wavelan_open(): no IRQ\n", dev->name); #endif return -ENXIO; } @@ -3909,7 +3913,7 @@ if(request_irq(dev->irq, &wavelan_interrupt, 0, "WaveLAN", dev) != 0) { #ifdef DEBUG_CONFIG_ERRORS - printk(KERN_WARNING "%s: wavelan_open(): invalid irq\n", dev->name); + printk(KERN_WARNING "%s: wavelan_open(): invalid IRQ\n", dev->name); #endif return -EAGAIN; } @@ -3941,8 +3945,8 @@ /*------------------------------------------------------------------*/ /* - * Shutdown the WaveLAN ISA card. - * Called by NET3 when it "close" the device. + * Shut down the WaveLAN ISA card. + * Called by NET3 when it "closes" the device. */ static int wavelan_close(device * dev) @@ -3954,14 +3958,14 @@ (unsigned int) dev); #endif - /* Not do the job twice... */ + /* Don't do the job twice. */ if(dev->start == 0) return 0; dev->tbusy = 1; dev->start = 0; - /* If watchdog was activated, kill it ! */ + /* If watchdog was activated, kill it! */ if(lp->watchdog.prev != (timer_list *) NULL) del_timer(&lp->watchdog); @@ -3982,9 +3986,9 @@ /*------------------------------------------------------------------*/ /* - * Probe an i/o address, and if the wavelan is there configure the + * Probe an I/O address, and if the WaveLAN is there configure the * device structure - * (called by wavelan_probe() & via init_module()) + * (called by wavelan_probe() and via init_module()). */ __initfunc(static int wavelan_config(device * dev)) @@ -3999,7 +4003,7 @@ (unsigned int)dev, ioaddr); #endif - /* Check irq arg on command line */ + /* Check IRQ argument on command line. */ if(dev->irq != 0) { irq_mask = wv_irq_to_psa(dev->irq); @@ -4007,7 +4011,7 @@ if(irq_mask == 0) { #ifdef DEBUG_CONFIG_ERROR - printk(KERN_WARNING "%s: wavelan_config(): invalid irq %d -- ignored.\n", + printk(KERN_WARNING "%s: wavelan_config(): invalid IRQ %d ignored.\n", dev->name, dev->irq); #endif dev->irq = 0; @@ -4015,7 +4019,7 @@ else { #ifdef DEBUG_CONFIG_INFO - printk(KERN_DEBUG "%s: wavelan_config(): changing irq to %d\n", + printk(KERN_DEBUG "%s: wavelan_config(): changing IRQ to %d\n", dev->name, dev->irq); #endif psa_write(ioaddr, HACR_DEFAULT, @@ -4049,9 +4053,9 @@ memset(dev->priv, 0x00, sizeof(net_local)); lp = (net_local *)dev->priv; - /* Back link to the device structure */ + /* Back link to the device structure. */ lp->dev = dev; - /* Add the device at the beggining of the linked list */ + /* Add the device at the beginning of the linked list. */ lp->next = wavelan_list; wavelan_list = lp; @@ -4064,7 +4068,7 @@ /* * Fill in the fields of the device structure - * with ethernet-generic values. + * with generic Ethernet values. */ ether_setup(dev); @@ -4075,14 +4079,14 @@ dev->set_multicast_list = &wavelan_set_multicast_list; dev->set_mac_address = &wavelan_set_mac_address; -#ifdef WIRELESS_EXT /* If wireless extension exist in the kernel */ +#ifdef WIRELESS_EXT /* if wireless extension exists in the kernel */ dev->do_ioctl = wavelan_ioctl; dev->get_wireless_stats = wavelan_get_wireless_stats; #endif dev->mtu = WAVELAN_MTU; - /* Display nice info */ + /* Display nice information. */ wv_init_info(dev); #ifdef DEBUG_CALLBACK_TRACE @@ -4093,18 +4097,17 @@ /*------------------------------------------------------------------*/ /* - * Check for a network adaptor of this type. - * Return '0' iff one exists. - * (There seem to be different interpretations of + * Check for a network adaptor of this type. Return '0' iff one + * exists. There seem to be different interpretations of * the initial value of dev->base_addr. - * We follow the example in drivers/net/ne.c.) + * We follow the example in drivers/net/ne.c. * (called in "Space.c") */ __initfunc(int wavelan_probe(device * dev)) { short base_addr; - mac_addr mac; /* Mac address (check wavelan existence) */ + mac_addr mac; /* MAC address (check existence of WaveLAN) */ int i; int r; @@ -4122,7 +4125,7 @@ } #endif /* STRUCT_CHECK */ - /* Check the value of the command line parameter for base address */ + /* Check the value of the command line parameter for base address. */ base_addr = dev->base_addr; /* Don't probe at all. */ @@ -4138,10 +4141,10 @@ /* Check a single specified location. */ if(base_addr > 0x100) { - /* Check if the is something at this base address */ + /* Check if there is something at this base address */ if((r = wv_check_ioaddr(base_addr, mac)) == 0) { - memcpy(dev->dev_addr, mac, 6); /* Copy mac address */ + memcpy(dev->dev_addr, mac, 6); /* Copy MAC address. */ r = wavelan_config(dev); } @@ -4157,14 +4160,14 @@ return r; } - /* Scan all possible address of the wavelan hardware */ + /* Scan all possible addresses of the WaveLAN hardware. */ for(i = 0; i < NELS(iobase); i++) { - /* Check if the is something at this base address */ + /* Check whether there is something at this base address. */ if(wv_check_ioaddr(iobase[i], mac) == 0) { - dev->base_addr = iobase[i]; /* Copy base address */ - memcpy(dev->dev_addr, mac, 6); /* Copy mac address */ + dev->base_addr = iobase[i]; /* Copy base address. */ + memcpy(dev->dev_addr, mac, 6); /* Copy MAC address. */ if(wavelan_config(dev) == 0) { #ifdef DEBUG_CALLBACK_TRACE @@ -4175,7 +4178,7 @@ } } - /* We may have touch base_addr : another driver may not like it... */ + /* We may have touched base_addr. Another driver may not like it. */ dev->base_addr = base_addr; #ifdef DEBUG_CONFIG_INFO @@ -4188,19 +4191,19 @@ /****************************** MODULE ******************************/ /* - * Module entry point : insertion & removal + * Module entry point: insertion and removal */ #ifdef MODULE /*------------------------------------------------------------------*/ /* - * Insertion of the module... - * I'm now quite proud of the multi-device support... + * Insertion of the module + * I'm now quite proud of the multi-device support. */ int init_module(void) { - mac_addr mac; /* Mac address (check wavelan existence) */ + mac_addr mac; /* MAC address (check WaveLAN existence) */ int ret = 0; int i; @@ -4212,48 +4215,48 @@ if(io[0] == 0) { #ifdef DEBUG_CONFIG_ERRORS - printk(KERN_WARNING "wavelan init_module(): doing device probing (bad !)\n"); + printk(KERN_WARNING "WaveLAN init_module(): doing device probing (bad !)\n"); printk(KERN_WARNING "Specify base addresses while loading module to correct the problem\n"); #endif - /* Copy the basic set of address to be probed */ + /* Copy the basic set of address to be probed. */ for(i = 0; i < NELS(iobase); i++) io[i] = iobase[i]; } - /* Loop on all possible base addresses */ + /* Loop on all possible base addresses. */ i = -1; while((io[++i] != 0) && (i < NELS(io))) { - /* Check if the is something at this base address */ + /* Check if there is something at this base address. */ if(wv_check_ioaddr(io[i], mac) == 0) { device * dev; - /* Create device and set basics args */ + /* Create device and set basic arguments. */ dev = kmalloc(sizeof(struct device), GFP_KERNEL); memset(dev, 0x00, sizeof(struct device)); dev->name = name[i]; dev->base_addr = io[i]; dev->irq = irq[i]; dev->init = &wavelan_config; - memcpy(dev->dev_addr, mac, 6); /* Copy mac address */ + memcpy(dev->dev_addr, mac, 6); /* Copy MAC address. */ - /* Try to create the device */ + /* Try to create the device. */ if(register_netdev(dev) != 0) { - /* DeAllocate everything */ - /* Note : if dev->priv is mallocated, there is no way to fail */ + /* Deallocate everything. */ + /* Note: if dev->priv is mallocated, there is no way to fail. */ kfree_s(dev, sizeof(struct device)); ret = -EIO; } - } /* If there is something at the address */ - } /* Loop on all addresses */ + } /* if there is something at the address */ + } /* Loop on all addresses. */ #ifdef DEBUG_CONFIG_ERRORS if(wavelan_list == (net_local *) NULL) - printk(KERN_WARNING "wavelan init_module(): No device found\n"); + printk(KERN_WARNING "WaveLAN init_module(): no device found\n"); #endif #ifdef DEBUG_MODULE_TRACE @@ -4273,7 +4276,7 @@ printk(KERN_DEBUG "-> cleanup_module()\n"); #endif - /* Loop on all devices and release them */ + /* Loop on all devices and release them. */ while(wavelan_list != (net_local *) NULL) { device * dev = wavelan_list->dev; @@ -4283,16 +4286,16 @@ dev->name, (unsigned int) dev); #endif - /* Release the ioport-region. */ + /* Release the ioport region. */ release_region(dev->base_addr, sizeof(ha_t)); - /* Remove definitely the device */ + /* Definitely remove the device. */ unregister_netdev(dev); - /* Unlink the device */ + /* Unlink the device. */ wavelan_list = wavelan_list->next; - /* Free pieces */ + /* Free pieces. */ kfree_s(dev->priv, sizeof(struct net_local)); kfree_s(dev, sizeof(struct device)); } diff -u --recursive --new-file v2.1.105/linux/drivers/scsi/Config.in linux/drivers/scsi/Config.in --- v2.1.105/linux/drivers/scsi/Config.in Tue Apr 14 14:29:21 1998 +++ linux/drivers/scsi/Config.in Sat Jun 13 12:59:15 1998 @@ -131,4 +131,7 @@ fi dep_tristate '53C94 (Power Mac external SCSI) support' CONFIG_SCSI_MAC53C94 $CONFIG_SCSI fi +if [ "$CONFIG_ARCH_ACORN" = "y" ]; then + source drivers/acorn/scsi/Config.in +fi endmenu diff -u --recursive --new-file v2.1.105/linux/drivers/scsi/NCR53C9x.c linux/drivers/scsi/NCR53C9x.c --- v2.1.105/linux/drivers/scsi/NCR53C9x.c Sun Jun 7 11:16:33 1998 +++ linux/drivers/scsi/NCR53C9x.c Sat Jun 13 13:28:34 1998 @@ -395,12 +395,6 @@ esp_cmd(esp, eregs, ESP_CMD_NULL | ESP_CMD_DMA); esp_cmd(esp, eregs, ESP_CMD_NULL | ESP_CMD_DMA); - /* Reload the configuration registers */ - eregs->esp_cfact = esp->cfact; - eregs->esp_stp = 0; - eregs->esp_soff = 0; - eregs->esp_timeo = esp->neg_defp; - /* This is the only point at which it is reliable to read * the ID-code for a fast ESP chip variant. */ @@ -417,7 +411,10 @@ } #endif if(family_code == 0x02) - esp->erev = fas236; + if ((version & 7) == 2) + esp->erev = fas216; + else + esp->erev = fas236; else if(family_code == 0x0a) esp->erev = fashme; /* Version is usually '5'. */ else @@ -425,13 +422,20 @@ printk("esp%d: FAST chip is %s (family=%d, version=%d)\n", esp->esp_id, (esp->erev == fas236) ? "fas236" : - ((esp->erev == fas100a) ? "fas100a" : - "fasHME"), family_code, (version & 7)); + ((esp->erev == fas216) ? "fas216" : + (((esp->erev == fas100a) ? "fas100a" : + "fasHME"))), family_code, (version & 7)); esp->min_period = ((4 * esp->ccycle) / 1000); } else { esp->min_period = ((5 * esp->ccycle) / 1000); } + + /* Reload the configuration registers */ + eregs->esp_cfact = esp->cfact; + eregs->esp_stp = 0; + eregs->esp_soff = 0; + eregs->esp_timeo = esp->neg_defp; esp->max_period = (esp->max_period + 3)>>2; esp->min_period = (esp->min_period + 3)>>2; @@ -451,6 +455,7 @@ case fashme: esp->config2 |= (ESP_CONFIG2_HME32 | ESP_CONFIG2_HMEFENAB); /* fallthrough... */ + case fas216: case fas236: /* Fast 236 or HME */ eregs->esp_cfg2 = esp->config2; @@ -630,6 +635,9 @@ esp->neg_defp = ESP_NEG_DEFP(fmhz, ccf); esp->sync_defp = SYNC_DEFP_SLOW; + printk("SCSI ID %d Clock %d MHz CCF=%d Time-Out %d ", + esp->scsi_id, (esp->cfreq / 1000000), + esp->ccf, (int) esp->neg_defp); /* Fill in ehost data */ esp->ehost->base = (unsigned char *) eregs; @@ -707,10 +715,6 @@ esp_bootup_reset(esp, eregs); esps_in_use++; - - printk("SCSI ID %d Clock %d MHz CCF=%d Time-Out %d ", - esp->scsi_id, (esp->cfreq / 1000000), - esp->ccf, (int) esp->neg_defp); } /* The info function will return whatever useful @@ -724,17 +728,19 @@ esp = (struct NCR_ESP *) host->hostdata; switch(esp->erev) { case esp100: - return "Sparc ESP100 (NCR53C90)"; + return "ESP100 (NCR53C90)"; case esp100a: - return "Sparc ESP100A (NCR53C90A)"; + return "ESP100A (NCR53C90A)"; case esp236: - return "Sparc ESP236"; + return "ESP236"; + case fas216: + return "ESP216-FAST"; case fas236: - return "Sparc ESP236-FAST"; + return "ESP236-FAST"; case fashme: - return "Sparc ESP366-HME"; + return "ESP366-HME"; case fas100a: - return "Sparc ESP100A-FAST"; + return "ESP100A-FAST"; default: panic("Bogon ESP revision"); }; @@ -807,6 +813,9 @@ case esp236: copy_info(&info, "ESP236\n"); break; + case fas216: + copy_info(&info, "FAS216\n"); + break; case fas236: copy_info(&info, "FAS236\n"); break; @@ -1252,20 +1261,11 @@ SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->request_buffer; SCpnt->SCp.buffers_residual = 0; -#ifdef CONFIG_SCSI_SUNESP - /* Sneaky. */ - SCpnt->SCp.have_data_in = mmu_get_scsi_one((char *)SCpnt->SCp.buffer, - SCpnt->SCp.this_residual, - ((struct linux_sbus_device*) (esp->edev))->my_bus); - /* XXX The casts are extremely gross, but with 64-bit kernel - * XXX and 32-bit SBUS what am I to do? -DaveM - */ - SCpnt->SCp.ptr = (char *)((unsigned long)SCpnt->SCp.have_data_in); -#else - SCpnt->SCp.have_data_in = (int) SCpnt->SCp.ptr = - (char *) VTOP((unsigned long) SCpnt->request_buffer); -#endif - + if (esp->dma_mmu_get_scsi_one) + esp->dma_mmu_get_scsi_one (esp, SCpnt); + else + SCpnt->SCp.have_data_in = (int) SCpnt->SCp.ptr = + (char *) virt_to_phys(SCpnt->request_buffer); } else { ESPQUEUE(("use_sg ")); #ifdef DEBUG_ESP_SG @@ -1275,16 +1275,11 @@ SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->buffer; SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1; SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length; -#ifdef CONFIG_SCSI_SUNESP - mmu_get_scsi_sgl((struct mmu_sglist *) SCpnt->SCp.buffer, - SCpnt->SCp.buffers_residual, - ((struct linux_sbus_device *) (esp->edev))->my_bus); - /* XXX Again these casts are sick... -DaveM */ - SCpnt->SCp.ptr=(char *)((unsigned long)SCpnt->SCp.buffer->dvma_address); -#else - SCpnt->SCp.ptr = - (char *) VTOP((unsigned long) SCpnt->SCp.buffer->address); -#endif + if (esp->dma_mmu_get_scsi_sgl) + esp->dma_mmu_get_scsi_sgl (esp, SCpnt); + else + SCpnt->SCp.ptr = + (char *) virt_to_phys(SCpnt->SCp.buffer->address); } SCpnt->SCp.Status = CHECK_CONDITION; SCpnt->SCp.Message = 0xff; @@ -1481,21 +1476,14 @@ /* Free dvma entry. */ if(!done_SC->use_sg) { -#ifdef CONFIG_SCSI_SUNESP - /* Sneaky. */ - mmu_release_scsi_one(done_SC->SCp.have_data_in, - done_SC->request_bufflen, - ((struct linux_sbus_device *) (esp->edev))->my_bus); -#endif + if (esp->dma_mmu_release_scsi_one) + esp->dma_mmu_release_scsi_one (esp, done_SC); } else { #ifdef DEBUG_ESP_SG printk("esp%d: unmapping sg ", esp->esp_id); #endif -#ifdef CONFIG_SCSI_SUNESP - mmu_release_scsi_sgl((struct mmu_sglist *) done_SC->buffer, - done_SC->use_sg - 1, - ((struct linux_sbus_device *) (esp->edev))->my_bus); -#endif + if (esp->dma_mmu_release_scsi_sgl) + esp->dma_mmu_release_scsi_sgl (esp, done_SC); #ifdef DEBUG_ESP_SG printk("done.\n"); #endif @@ -1861,16 +1849,15 @@ return do_work_bus; } -static inline void advance_sg(Scsi_Cmnd *sp) +static inline void advance_sg(struct NCR_ESP *esp, Scsi_Cmnd *sp) { ++sp->SCp.buffer; --sp->SCp.buffers_residual; sp->SCp.this_residual = sp->SCp.buffer->length; -#ifdef CONFIG_SCSI_SUNESP - sp->SCp.ptr = (char *)((unsigned long)sp->SCp.buffer->dvma_address); -#else - sp->SCp.ptr = (char *)VTOP((unsigned long) sp->SCp.buffer->address); -#endif + if (esp->dma_advance_sg) + esp->dma_advance_sg (sp); + else + sp->SCp.ptr = (char *)virt_to_phys(sp->SCp.buffer->address); } /* Please note that the way I've coded these routines is that I _always_ @@ -2067,7 +2054,7 @@ * figure this out. */ if(SCptr->use_sg && !SCptr->SCp.this_residual) - advance_sg(SCptr); + advance_sg(esp, SCptr); if(sreg_datainp(esp->sreg) || sreg_dataoutp(esp->sreg)) { ESPDATA(("to more data\n")); return esp_do_data(esp, eregs); @@ -2922,6 +2909,7 @@ tmp = esp->ccycle / 1000; regval = (((period << 2) + tmp - 1) / tmp); if(regval && ((esp->erev == fas100a || + esp->erev == fas216 || esp->erev == fas236 || esp->erev == fashme))) { if(period >= 50) @@ -2934,7 +2922,7 @@ SDptr->sync_min_period = (regval & 0x1f); SDptr->sync_max_offset = (offset | esp->radelay); - if((esp->erev == fas100a || esp->erev == fas236 || esp->erev == fashme)) { + if((esp->erev == fas100a || esp->erev == fas216 || esp->erev == fas236 || esp->erev == fashme)) { if((esp->erev == fas100a) || (esp->erev == fashme)) bit = ESP_CONFIG3_FAST; else @@ -2963,7 +2951,7 @@ SDptr->sync_min_period = 0; eregs->esp_soff = 0; eregs->esp_stp = 0; - if((esp->erev == fas100a || esp->erev == fas236 || esp->erev == fashme)) { + if((esp->erev == fas100a || esp->erev == fas216 || esp->erev == fas236 || esp->erev == fashme)) { if((esp->erev == fas100a) || (esp->erev == fashme)) bit = ESP_CONFIG3_FAST; else @@ -3595,17 +3583,13 @@ if(esp->current_SC) { Scsi_Cmnd *SCptr = esp->current_SC; -#ifdef CONFIG_SCSI_SUNESP - if(!SCptr->use_sg) - mmu_release_scsi_one(SCptr->SCp.have_data_in, - SCptr->request_bufflen, - ((struct linux_sbus_device *) (esp->edev))->my_bus); - else - mmu_release_scsi_sgl((struct mmu_sglist *) - SCptr->buffer, - SCptr->use_sg - 1, - ((struct linux_sbus_device *) (esp->edev))->my_bus); -#endif + if(!SCptr->use_sg) { + if (esp->dma_mmu_release_scsi_one) + esp->dma_mmu_release_scsi_one (esp, SCptr); + } else { + if (esp->dma_mmu_release_scsi_sgl) + esp->dma_mmu_release_scsi_sgl (esp, SCptr); + } SCptr->result = (DID_RESET << 16); SCptr->scsi_done(SCptr); @@ -3614,17 +3598,13 @@ if(esp->disconnected_SC) { Scsi_Cmnd *SCptr; while((SCptr = remove_first_SC(&esp->disconnected_SC))) { - if(!SCptr->use_sg) -#ifdef CONFIG_SCSI_SUNESP - mmu_release_scsi_one(SCptr->SCp.have_data_in, - SCptr->request_bufflen, - ((struct linux_sbus_device *) (esp->edev))->my_bus); - else - mmu_release_scsi_sgl((struct mmu_sglist *) - SCptr->buffer, - SCptr->use_sg - 1, - ((struct linux_sbus_device *) (esp->edev))->my_bus); -#endif + if(!SCptr->use_sg) { + if (esp->dma_mmu_release_scsi_one) + esp->dma_mmu_release_scsi_one (esp, SCptr); + } else { + if (esp->dma_mmu_release_scsi_sgl) + esp->dma_mmu_release_scsi_sgl (esp, SCptr); + } SCptr->result = (DID_RESET << 16); SCptr->scsi_done(SCptr); @@ -3671,7 +3651,9 @@ repeat: again = 0; for_each_esp(esp) { +#ifndef __mips__ if(((esp)->irq & 0xf) == irq) { +#endif if(esp->dma_irq_p(esp)) { again = 1; @@ -3683,7 +3665,9 @@ esp->dma_ints_on(esp); } +#ifndef __mips__ } +#endif } if(again) goto repeat; diff -u --recursive --new-file v2.1.105/linux/drivers/scsi/NCR53C9x.h linux/drivers/scsi/NCR53C9x.h --- v2.1.105/linux/drivers/scsi/NCR53C9x.h Thu Mar 26 15:57:03 1998 +++ linux/drivers/scsi/NCR53C9x.h Sat Jun 13 13:28:34 1998 @@ -107,6 +107,15 @@ (printk ("Internal ESP driver error in file %s, line %d\n", \ __FILE__, __LINE__)) +/* + * padding for register structure + */ +#ifdef CONFIG_JAZZ_ESP +#define EREGS_PAD(n) +#else +#define EREGS_PAD(n) unchar n[3]; +#endif + /* The ESP SCSI controllers have their register sets in three * "classes": * @@ -124,44 +133,45 @@ struct ESP_regs { /* Access Description Offset */ volatile unchar esp_tclow; /* rw Low bits of the transfer count 0x00 */ - unchar tlpad1[3]; + EREGS_PAD(tlpad1); volatile unchar esp_tcmed; /* rw Mid bits of the transfer count 0x04 */ - unchar fdpad[3]; + EREGS_PAD(fdpad); volatile unchar esp_fdata; /* rw FIFO data bits 0x08 */ - unchar cbpad[3]; + EREGS_PAD(cbpad); volatile unchar esp_cmd; /* rw SCSI command bits 0x0c */ - unchar stpad[3]; + EREGS_PAD(stpad); volatile unchar esp_status; /* ro ESP status register 0x10 */ #define esp_busid esp_status /* wo Bus ID for select/reselect 0x10 */ - unchar irqpd[3]; + EREGS_PAD(irqpd); volatile unchar esp_intrpt; /* ro Kind of interrupt 0x14 */ #define esp_timeo esp_intrpt /* wo Timeout value for select/resel 0x14 */ - unchar sspad[3]; + EREGS_PAD(sspad); volatile unchar esp_sstep; /* ro Sequence step register 0x18 */ #define esp_stp esp_sstep /* wo Transfer period per sync 0x18 */ - unchar ffpad[3]; + EREGS_PAD(ffpad); volatile unchar esp_fflags; /* ro Bits of current FIFO info 0x1c */ #define esp_soff esp_fflags /* wo Sync offset 0x1c */ - unchar cf1pd[3]; + EREGS_PAD(cf1pd); volatile unchar esp_cfg1; /* rw First configuration register 0x20 */ - unchar cfpad[3]; + EREGS_PAD(cfpad); volatile unchar esp_cfact; /* wo Clock conversion factor 0x24 */ #define esp_status2 esp_cfact /* ro HME status2 register 0x24 */ - unchar ctpad[3]; + EREGS_PAD(ctpad); volatile unchar esp_ctest; /* wo Chip test register 0x28 */ - unchar cf2pd[3]; + EREGS_PAD(cf2pd); volatile unchar esp_cfg2; /* rw Second configuration register 0x2c */ - unchar cf3pd[3]; + EREGS_PAD(cf3pd); /* The following is only found on the 53C9X series SCSI chips */ volatile unchar esp_cfg3; /* rw Third configuration register 0x30 */ - unchar thpd[7]; - + EREGS_PAD(holep); + volatile unchar esp_hole; /* hole in register map 0x34 */ + EREGS_PAD(thpd); /* The following is found on all chips except the NCR53C90 (ESP100) */ volatile unchar esp_tchi; /* rw High bits of transfer count 0x38 */ #define esp_uid esp_tchi /* ro Unique ID code 0x38 */ #define fas_rlo esp_tchi /* rw HME extended counter 0x38 */ - unchar fgpad[3]; + EREGS_PAD(fgpad); volatile unchar esp_fgrnd; /* rw Data base for fifo 0x3c */ #define fas_rhi esp_fgrnd /* rw HME extended counter 0x3c */ }; @@ -175,7 +185,8 @@ fas100a = 0x04, fast = 0x05, fashme = 0x06, - espunknown = 0x07 + fas216 = 0x07, + espunknown = 0x08 }; /* We get one of these for each ESP probed. */ @@ -303,6 +314,13 @@ void (*dma_led_on)(struct NCR_ESP *); void (*dma_poll)(struct NCR_ESP *, unsigned char *); void (*dma_reset)(struct NCR_ESP *); + + /* Optional virtual DMA functions */ + void (*dma_mmu_get_scsi_one)(struct NCR_ESP *, Scsi_Cmnd *); + void (*dma_mmu_get_scsi_sgl)(struct NCR_ESP *, Scsi_Cmnd *); + void (*dma_mmu_release_scsi_one)(struct NCR_ESP *, Scsi_Cmnd *); + void (*dma_mmu_release_scsi_sgl)(struct NCR_ESP *, Scsi_Cmnd *); + void (*dma_advance_sg)(Scsi_Cmnd *); }; /* Bitfield meanings for the above registers. */ diff -u --recursive --new-file v2.1.105/linux/drivers/scsi/aha1542.c linux/drivers/scsi/aha1542.c --- v2.1.105/linux/drivers/scsi/aha1542.c Tue Jun 9 11:57:30 1998 +++ linux/drivers/scsi/aha1542.c Tue Jun 9 01:21:50 1998 @@ -223,7 +223,7 @@ /* Similar to aha1542_in, except that we wait a very short period of time. We use this if we know the board is alive and awake, but we are not sure - if the board will respond the command we are about to send or not */ + if the board will respond to the command we are about to send or not */ static int aha1542_in1(unsigned int base, unchar *cmdp, int len) { unsigned long flags; diff -u --recursive --new-file v2.1.105/linux/drivers/scsi/blz1230.c linux/drivers/scsi/blz1230.c --- v2.1.105/linux/drivers/scsi/blz1230.c Fri May 8 23:14:49 1998 +++ linux/drivers/scsi/blz1230.c Sat Jun 13 13:23:01 1998 @@ -130,6 +130,7 @@ esp->eregs = eregs; /* Set the command buffer */ + esp->esp_command = (volatile unsigned char*) cmd_buffer; esp->esp_command_dvma = VTOP((unsigned long) cmd_buffer); esp->irq = IRQ_AMIGA_PORTS; diff -u --recursive --new-file v2.1.105/linux/drivers/scsi/blz1230.h linux/drivers/scsi/blz1230.h --- v2.1.105/linux/drivers/scsi/blz1230.h Fri May 8 23:14:49 1998 +++ linux/drivers/scsi/blz1230.h Sat Jun 13 13:49:32 1998 @@ -56,27 +56,17 @@ extern int esp_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout); -#define SCSI_BLZ1230 { \ -/* struct SHT *next */ NULL, \ -/* long *usage_count */ NULL, \ -/* struct proc_dir_entry *proc_dir */ &proc_scsi_esp, \ -/* int (*proc_info)(char *, char **, off_t, int, int, int) */ &esp_proc_info, \ -/* const char *name */ "Blizzard1230 SCSI IV", \ -/* int detect(struct SHT *) */ blz1230_esp_detect, \ -/* int release(struct Scsi_Host *) */ NULL, \ -/* const char *info(struct Scsi_Host *) */ esp_info, \ -/* int command(Scsi_Cmnd *) */ esp_command, \ -/* int queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)) */ esp_queue, \ -/* int abort(Scsi_Cmnd *) */ esp_abort, \ -/* int reset(Scsi_Cmnd *) */ esp_reset, \ -/* int slave_attach(int, int) */ NULL, \ -/* int bios_param(Disk *, kdev_t, int[]) */ NULL, \ -/* int can_queue */ 7, \ -/* int this_id */ 7, \ -/* short unsigned int sg_tablesize */ SG_ALL, \ -/* short cmd_per_lun */ 1, \ -/* unsigned char present */ 0, \ -/* unsigned unchecked_isa_dma:1 */ 0, \ -/* unsigned use_clustering:1 */ DISABLE_CLUSTERING, } +#define SCSI_BLZ1230 { proc_dir: &proc_scsi_esp, \ + name: "Blizzard1230 SCSI IV", \ + detect: blz1230_esp_detect, \ + release: NULL, \ + queuecommand: esp_queue, \ + abort: esp_abort, \ + reset: esp_reset, \ + can_queue: 7, \ + this_id: 7, \ + sg_tablesize: SG_ALL, \ + cmd_per_lun: 1, \ + use_clustering: DISABLE_CLUSTERING } #endif /* BLZ1230_H */ diff -u --recursive --new-file v2.1.105/linux/drivers/scsi/blz2060.c linux/drivers/scsi/blz2060.c --- v2.1.105/linux/drivers/scsi/blz2060.c Fri May 8 23:14:49 1998 +++ linux/drivers/scsi/blz2060.c Sat Jun 13 13:23:01 1998 @@ -106,6 +106,7 @@ esp->eregs = (struct ESP_regs *)(address + BLZ2060_ESP_ADDR); /* Set the command buffer */ + esp->esp_command = (volatile unsigned char*) cmd_buffer; esp->esp_command_dvma = VTOP((unsigned long) cmd_buffer); esp->irq = IRQ_AMIGA_PORTS; diff -u --recursive --new-file v2.1.105/linux/drivers/scsi/blz2060.h linux/drivers/scsi/blz2060.h --- v2.1.105/linux/drivers/scsi/blz2060.h Fri May 8 23:14:49 1998 +++ linux/drivers/scsi/blz2060.h Sat Jun 13 13:49:32 1998 @@ -52,27 +52,17 @@ extern int esp_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout); -#define SCSI_BLZ2060 { \ -/* struct SHT *next */ NULL, \ -/* long *usage_count */ NULL, \ -/* struct proc_dir_entry *proc_dir */ &proc_scsi_esp, \ -/* int (*proc_info)(char *, char **, off_t, int, int, int) */ &esp_proc_info, \ -/* const char *name */ "Blizzard2060 SCSI", \ -/* int detect(struct SHT *) */ blz2060_esp_detect, \ -/* int release(struct Scsi_Host *) */ NULL, \ -/* const char *info(struct Scsi_Host *) */ esp_info, \ -/* int command(Scsi_Cmnd *) */ esp_command, \ -/* int queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)) */ esp_queue, \ -/* int abort(Scsi_Cmnd *) */ esp_abort, \ -/* int reset(Scsi_Cmnd *) */ esp_reset, \ -/* int slave_attach(int, int) */ NULL, \ -/* int bios_param(Disk *, kdev_t, int[]) */ NULL, \ -/* int can_queue */ 7, \ -/* int this_id */ 7, \ -/* short unsigned int sg_tablesize */ SG_ALL, \ -/* short cmd_per_lun */ 1, \ -/* unsigned char present */ 0, \ -/* unsigned unchecked_isa_dma:1 */ 0, \ -/* unsigned use_clustering:1 */ DISABLE_CLUSTERING, } +#define SCSI_BLZ2060 { proc_dir: &proc_scsi_esp, \ + name: "Blizzard2060 SCSI", \ + detect: blz2060_esp_detect, \ + release: NULL, \ + queuecommand: esp_queue, \ + abort: esp_abort, \ + reset: esp_reset, \ + can_queue: 7, \ + this_id: 7, \ + sg_tablesize: SG_ALL, \ + cmd_per_lun: 1, \ + use_clustering: DISABLE_CLUSTERING } #endif /* BLZ2060_H */ diff -u --recursive --new-file v2.1.105/linux/drivers/scsi/cyberstorm.c linux/drivers/scsi/cyberstorm.c --- v2.1.105/linux/drivers/scsi/cyberstorm.c Fri May 8 23:14:49 1998 +++ linux/drivers/scsi/cyberstorm.c Sat Jun 13 13:23:01 1998 @@ -126,6 +126,7 @@ esp->eregs = (struct ESP_regs *)(address + CYBER_ESP_ADDR); /* Set the command buffer */ + esp->esp_command = (volatile unsigned char*) cmd_buffer; esp->esp_command_dvma = VTOP((unsigned long) cmd_buffer); esp->irq = IRQ_AMIGA_PORTS; diff -u --recursive --new-file v2.1.105/linux/drivers/scsi/cyberstorm.h linux/drivers/scsi/cyberstorm.h --- v2.1.105/linux/drivers/scsi/cyberstorm.h Fri May 8 23:14:49 1998 +++ linux/drivers/scsi/cyberstorm.h Sat Jun 13 13:49:32 1998 @@ -55,28 +55,18 @@ int hostno, int inout); -#define SCSI_CYBERSTORM { \ -/* struct SHT *next */ NULL, \ -/* long *usage_count */ NULL, \ -/* struct proc_dir_entry *proc_dir */ &proc_scsi_esp, \ -/* int (*proc_info)(char *, char **, off_t, int, int, int) */ &esp_proc_info, \ -/* const char *name */ "CyberStorm SCSI", \ -/* int detect(struct SHT *) */ cyber_esp_detect, \ -/* int release(struct Scsi_Host *) */ NULL, \ -/* const char *info(struct Scsi_Host *) */ esp_info, \ -/* int command(Scsi_Cmnd *) */ esp_command, \ -/* int queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)) */ esp_queue, \ -/* int abort(Scsi_Cmnd *) */ esp_abort, \ -/* int reset(Scsi_Cmnd *) */ esp_reset, \ -/* int slave_attach(int, int) */ NULL, \ -/* int bios_param(Disk *, kdev_t, int[]) */ NULL, \ -/* int can_queue */ 7, \ -/* int this_id */ 7, \ -/* short unsigned int sg_tablesize */ SG_ALL, \ -/* short cmd_per_lun */ 1, \ -/* unsigned char present */ 0, \ -/* unsigned unchecked_isa_dma:1 */ 0, \ -/* unsigned use_clustering:1 */ DISABLE_CLUSTERING, } +#define SCSI_CYBERSTORM { proc_dir: &proc_scsi_esp, \ + name: "CyberStorm SCSI", \ + detect: cyber_esp_detect, \ + release: NULL, \ + queuecommand: esp_queue, \ + abort: esp_abort, \ + reset: esp_reset, \ + can_queue: 7, \ + this_id: 7, \ + sg_tablesize: SG_ALL, \ + cmd_per_lun: 1, \ + use_clustering: DISABLE_CLUSTERING } #endif /* CYBER_ESP_H */ diff -u --recursive --new-file v2.1.105/linux/drivers/scsi/cyberstormII.c linux/drivers/scsi/cyberstormII.c --- v2.1.105/linux/drivers/scsi/cyberstormII.c Fri May 8 23:14:49 1998 +++ linux/drivers/scsi/cyberstormII.c Sat Jun 13 13:23:01 1998 @@ -117,6 +117,7 @@ esp->eregs = eregs; /* Set the command buffer */ + esp->esp_command = (volatile unsigned char*) cmd_buffer; esp->esp_command_dvma = VTOP((unsigned long) cmd_buffer); esp->irq = IRQ_AMIGA_PORTS; diff -u --recursive --new-file v2.1.105/linux/drivers/scsi/cyberstormII.h linux/drivers/scsi/cyberstormII.h --- v2.1.105/linux/drivers/scsi/cyberstormII.h Fri May 8 23:14:49 1998 +++ linux/drivers/scsi/cyberstormII.h Sat Jun 13 13:49:32 1998 @@ -42,28 +42,18 @@ extern int esp_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout); -#define SCSI_CYBERSTORMII { \ -/* struct SHT *next */ NULL, \ -/* long *usage_count */ NULL, \ -/* struct proc_dir_entry *proc_dir */ &proc_scsi_esp, \ -/* int (*proc_info)(char *, char **, off_t, int, int, int) */ &esp_proc_info, \ -/* const char *name */ "CyberStorm Mk II SCSI", \ -/* int detect(struct SHT *) */ cyberII_esp_detect, \ -/* int release(struct Scsi_Host *) */ NULL, \ -/* const char *info(struct Scsi_Host *) */ esp_info, \ -/* int command(Scsi_Cmnd *) */ esp_command, \ -/* int queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)) */ esp_queue, \ -/* int abort(Scsi_Cmnd *) */ esp_abort, \ -/* int reset(Scsi_Cmnd *) */ esp_reset, \ -/* int slave_attach(int, int) */ NULL, \ -/* int bios_param(Disk *, kdev_t, int[]) */ NULL, \ -/* int can_queue */ 7, \ -/* int this_id */ 7, \ -/* short unsigned int sg_tablesize */ SG_ALL, \ -/* short cmd_per_lun */ 1, \ -/* unsigned char present */ 0, \ -/* unsigned unchecked_isa_dma:1 */ 0, \ -/* unsigned use_clustering:1 */ DISABLE_CLUSTERING, } +#define SCSI_CYBERSTORMII { proc_dir: &proc_scsi_esp, \ + name: "CyberStorm Mk II SCSI", \ + detect: cyberII_esp_detect, \ + release: NULL, \ + queuecommand: esp_queue, \ + abort: esp_abort, \ + reset: esp_reset, \ + can_queue: 7, \ + this_id: 7, \ + sg_tablesize: SG_ALL, \ + cmd_per_lun: 1, \ + use_clustering: DISABLE_CLUSTERING } #endif /* CYBERII_ESP_H */ diff -u --recursive --new-file v2.1.105/linux/drivers/scsi/fastlane.c linux/drivers/scsi/fastlane.c --- v2.1.105/linux/drivers/scsi/fastlane.c Fri May 8 23:14:49 1998 +++ linux/drivers/scsi/fastlane.c Sat Jun 13 13:23:01 1998 @@ -5,8 +5,8 @@ * This driver is based on the CyberStorm driver, hence the occasional * reference to CyberStorm. * - * Betatesting & crucial adjustments by Patrik Rak - * (prak3264@ss1000.ms.mff.cuni.cz) + * Betatesting & crucial adjustments by + * Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz) * */ @@ -43,8 +43,11 @@ #include +/* Such day has just come... */ +#if 0 /* Let this defined unless you really need to enable DMA IRQ one day */ #define NODMAIRQ +#endif static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count); static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp); @@ -55,6 +58,7 @@ static void dma_ints_off(struct NCR_ESP *esp); static void dma_ints_on(struct NCR_ESP *esp); static int dma_irq_p(struct NCR_ESP *esp); +static void dma_irq_exit(struct NCR_ESP *esp); static void dma_led_off(struct NCR_ESP *esp); static void dma_led_on(struct NCR_ESP *esp); static int dma_ports_p(struct NCR_ESP *esp); @@ -113,7 +117,7 @@ esp->dma_drain = 0; esp->dma_invalidate = 0; esp->dma_irq_entry = 0; - esp->dma_irq_exit = 0; + esp->dma_irq_exit = &dma_irq_exit; esp->dma_led_on = &dma_led_on; esp->dma_led_off = &dma_led_off; esp->dma_poll = 0; @@ -158,6 +162,7 @@ esp->edev = (void *) address; /* Set the command buffer */ + esp->esp_command = (volatile unsigned char*) cmd_buffer; esp->esp_command_dvma = VTOP((unsigned long) cmd_buffer); esp->irq = IRQ_AMIGA_PORTS; @@ -278,39 +283,34 @@ enable_irq(esp->irq); } +static void dma_irq_exit(struct NCR_ESP *esp) +{ + struct fastlane_dma_registers *dregs = + (struct fastlane_dma_registers *) (esp->dregs); + + dregs->ctrl_reg = ctrl_data & ~(FASTLANE_DMA_EDI|FASTLANE_DMA_ESI); + nop(); + dregs->ctrl_reg = ctrl_data; +} + static int dma_irq_p(struct NCR_ESP *esp) { struct fastlane_dma_registers *dregs = (struct fastlane_dma_registers *) (esp->dregs); -#if 0 unsigned char dma_status; - int r = 0; dma_status = dregs->cond_reg; if(dma_status & FASTLANE_DMA_IACT) return 0; /* not our IRQ */ - /* Return 1 if ESP requested IRQ */ - if( + /* Return non-zero if ESP requested IRQ */ + return ( #ifndef NODMAIRQ (dma_status & FASTLANE_DMA_CREQ) && #endif (!(dma_status & FASTLANE_DMA_MINT)) && - ((((struct ESP_regs *) (esp->eregs))->esp_status) & ESP_STAT_INTR)) - r = 1; - - dregs->ctrl_reg = (ctrl_data & ~(FASTLANE_DMA_EDI|FASTLANE_DMA_ESI) ); - dregs->ctrl_reg = ctrl_data; - - return r; -#else - int r; - r = (((struct ESP_regs *) (esp->eregs))->esp_status) & ESP_STAT_INTR; - dregs->ctrl_reg = ctrl_data & ~(FASTLANE_DMA_EDI|FASTLANE_DMA_ESI); - dregs->ctrl_reg = ctrl_data; - return r; -#endif + ((((struct ESP_regs *) (esp->eregs))->esp_status) & ESP_STAT_INTR)); } static void dma_led_off(struct NCR_ESP *esp) diff -u --recursive --new-file v2.1.105/linux/drivers/scsi/fastlane.h linux/drivers/scsi/fastlane.h --- v2.1.105/linux/drivers/scsi/fastlane.h Fri May 8 23:14:49 1998 +++ linux/drivers/scsi/fastlane.h Sat Jun 13 13:49:32 1998 @@ -47,27 +47,17 @@ extern int esp_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout); -#define SCSI_FASTLANE { \ -/* struct SHT *next */ NULL, \ -/* long *usage_count */ NULL, \ -/* struct proc_dir_entry *proc_dir */ &proc_scsi_esp, \ -/* int (*proc_info)(char *, char **, off_t, int, int, int) */ &esp_proc_info, \ -/* const char *name */ "Fastlane SCSI", \ -/* int detect(struct SHT *) */ fastlane_esp_detect, \ -/* int release(struct Scsi_Host *) */ NULL, \ -/* const char *info(struct Scsi_Host *) */ esp_info, \ -/* int command(Scsi_Cmnd *) */ esp_command, \ -/* int queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)) */ esp_queue, \ -/* int abort(Scsi_Cmnd *) */ esp_abort, \ -/* int reset(Scsi_Cmnd *) */ esp_reset, \ -/* int slave_attach(int, int) */ NULL, \ -/* int bios_param(Disk *, kdev_t, int[]) */ NULL, \ -/* int can_queue */ 7, \ -/* int this_id */ 7, \ -/* short unsigned int sg_tablesize */ SG_ALL, \ -/* short cmd_per_lun */ 1, \ -/* unsigned char present */ 0, \ -/* unsigned unchecked_isa_dma:1 */ 0, \ -/* unsigned use_clustering:1 */ DISABLE_CLUSTERING, } +#define SCSI_FASTLANE { proc_dir: &proc_scsi_esp, \ + name: "Fastlane SCSI", \ + detect: fastlane_esp_detect, \ + release: NULL, \ + queuecommand: esp_queue, \ + abort: esp_abort, \ + reset: esp_reset, \ + can_queue: 7, \ + this_id: 7, \ + sg_tablesize: SG_ALL, \ + cmd_per_lun: 1, \ + use_clustering: DISABLE_CLUSTERING } #endif /* FASTLANE_H */ diff -u --recursive --new-file v2.1.105/linux/drivers/scsi/hosts.c linux/drivers/scsi/hosts.c --- v2.1.105/linux/drivers/scsi/hosts.c Sun Jun 7 11:16:34 1998 +++ linux/drivers/scsi/hosts.c Sat Jun 13 12:59:15 1998 @@ -237,6 +237,29 @@ #include "scsi_debug.h" #endif +#ifdef CONFIG_SCSI_ACORNSCSI_3 +#include "../acorn/scsi/acornscsi.h" +#endif + +#ifdef CONFIG_SCSI_CUMANA_1 +#include "../acorn/scsi/cumana_1.h" +#endif + +#ifdef CONFIG_SCSI_CUMANA_2 +#include "../acorn/scsi/cumana_2.h" +#endif + +#ifdef CONFIG_SCSI_ECOSCSI +#include "../acorn/scsi/ecoscsi.h" +#endif + +#ifdef CONFIG_SCSI_OAK1 +#include "../acorn/scsi/oak.h" +#endif + +#ifdef CONFIG_SCSI_POWERTECSCSI +#include "../acorn/scsi/powertec.h" +#endif /* static const char RCSid[] = "$Header: /vger/u4/cvs/linux/drivers/scsi/hosts.c,v 1.20 1996/12/12 19:18:32 davem Exp $"; @@ -423,6 +446,26 @@ #endif #ifdef CONFIG_SCSI_PLUTO PLUTO, +#endif +#ifdef CONFIG_ARCH_ACORN +#ifdef CONFIG_SCSI_ACORNSCSI_3 + ACORNSCSI_3, +#endif +#ifdef CONFIG_SCSI_CUMANA_1 + CUMANA_NCR5380, +#endif +#ifdef CONFIG_SCSI_CUMANA_2 + CUMANA_FAS216, +#endif +#ifdef CONFIG_SCSI_ECOSCSI + ECOSCSI_NCR5380, +#endif +#ifdef CONFIG_SCSI_OAK1 + OAK_NCR5380, +#endif +#ifdef CONFIG_SCSI_POWERTECSCSI + POWERTECSCSI, +#endif #endif #ifdef CONFIG_SCSI_DEBUG SCSI_DEBUG, diff -u --recursive --new-file v2.1.105/linux/drivers/scsi/ncr53c8xx.c linux/drivers/scsi/ncr53c8xx.c --- v2.1.105/linux/drivers/scsi/ncr53c8xx.c Sun Jun 7 11:16:34 1998 +++ linux/drivers/scsi/ncr53c8xx.c Tue Jun 9 01:21:50 1998 @@ -369,8 +369,8 @@ static void DELAY(long us) { - if (us/1000) mdelay(us/1000); - if (us%1000) udelay(us%1000); + for (;us>1000;us-=1000) udelay(1000); + if (us) udelay(us); } /* diff -u --recursive --new-file v2.1.105/linux/drivers/scsi/scsi_obsolete.c linux/drivers/scsi/scsi_obsolete.c --- v2.1.105/linux/drivers/scsi/scsi_obsolete.c Thu May 14 19:47:41 1998 +++ linux/drivers/scsi/scsi_obsolete.c Sat Jun 13 13:25:12 1998 @@ -79,7 +79,7 @@ static int scsi_reset (Scsi_Cmnd *, unsigned int); extern void scsi_old_done (Scsi_Cmnd *SCpnt); -static int update_timeout (Scsi_Cmnd *, int); +int update_timeout (Scsi_Cmnd *, int); extern void scsi_old_times_out (Scsi_Cmnd * SCpnt); extern void internal_cmnd (Scsi_Cmnd * SCpnt); @@ -1058,7 +1058,7 @@ * set the timer, we want to take this value into account. */ -static int update_timeout(Scsi_Cmnd * SCset, int timeout) +int update_timeout(Scsi_Cmnd * SCset, int timeout) { int rtn; diff -u --recursive --new-file v2.1.105/linux/drivers/scsi/scsi_proc.c linux/drivers/scsi/scsi_proc.c --- v2.1.105/linux/drivers/scsi/scsi_proc.c Mon Feb 23 18:12:07 1998 +++ linux/drivers/scsi/scsi_proc.c Sat Jun 13 12:10:31 1998 @@ -184,9 +184,9 @@ if (!buf || !cmdList) /* bad input ? */ return(NULL); - if ((handle = (parseHandle*) kmalloc(sizeof(parseHandle), 1)) == 0) + if ((handle = (parseHandle*) kmalloc(sizeof(parseHandle), GFP_KERNEL)) == 0) return(NULL); /* out of memory */ - if ((handle->cmdPos = (char**) kmalloc(sizeof(int), cmdNum)) == 0) { + if ((handle->cmdPos = (char**) kmalloc(sizeof(int) * cmdNum, GFP_KERNEL)) == 0) { kfree(handle); return(NULL); /* out of memory */ } diff -u --recursive --new-file v2.1.105/linux/drivers/scsi/sr_ioctl.c linux/drivers/scsi/sr_ioctl.c --- v2.1.105/linux/drivers/scsi/sr_ioctl.c Thu May 14 19:47:41 1998 +++ linux/drivers/scsi/sr_ioctl.c Fri Jun 12 22:31:48 1998 @@ -93,7 +93,14 @@ printk(KERN_INFO "sr%d: CDROM not ready yet.\n", target); if (retries++ < 10) { /* sleep 2 sec and try again */ + /* + * The spinlock is silly - we should really lock more of this + * function, but the minimal locking required to not lock up + * is around this - scsi_sleep() assumes we hold the spinlock. + */ + spin_lock_irqsave(&io_request_lock, flags); scsi_sleep(2*HZ); + spin_unlock_irqrestore(&io_request_lock, flags); goto retry; } else { /* 20 secs are enouth? */ diff -u --recursive --new-file v2.1.105/linux/drivers/sound/Config.in linux/drivers/sound/Config.in --- v2.1.105/linux/drivers/sound/Config.in Tue Jun 9 11:57:30 1998 +++ linux/drivers/sound/Config.in Sat Jun 13 10:23:52 1998 @@ -137,6 +137,19 @@ string ' Full pathname of OSWF.MOT firmware file' CONFIG_MAUI_BOOT_FILE fi fi + + if [ "$CONFIG_SOUND" = "m" ]; then + dep_tristate 'Support for Turtle Beach MultiSound Classic, Tahiti, Monterey' CONFIG_SOUND_MSNDCLAS $CONFIG_SOUND + if [ "$CONFIG_SOUND_MSNDCLAS" = "m" ]; then + string ' Full pathname of MSNDINIT.BIN firmware file' CONFIG_MSNDCLAS_INIT_FILE + string ' Full pathname of MSNDPERM.BIN firmware file' CONFIG_MSNDCLAS_PERM_FILE + fi + dep_tristate 'Support for Turtle Beach MultiSound Pinnacle, Fiji' CONFIG_SOUND_MSNDPIN $CONFIG_SOUND + if [ "$CONFIG_SOUND_MSNDPIN" = "m" ]; then + string ' Full pathname of PNDSPINI.BIN firmware file' CONFIG_MSNDPIN_INIT_FILE + string ' Full pathname of PNDSPERM.BIN firmware file' CONFIG_MSNDPIN_PERM_FILE + fi + fi dep_tristate 'Support for Aztech Sound Galaxy (non-PnP) cards' CONFIG_SOUND_SGALAXY $CONFIG_SOUND_OSS if [ "$CONFIG_SOUND_SGALAXY" = "y" ]; then diff -u --recursive --new-file v2.1.105/linux/drivers/sound/Makefile linux/drivers/sound/Makefile --- v2.1.105/linux/drivers/sound/Makefile Tue Jun 9 11:57:30 1998 +++ linux/drivers/sound/Makefile Sat Jun 13 10:23:52 1998 @@ -23,8 +23,9 @@ # This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'. export-objs := ad1848.o audio_syms.o midi_syms.o mpu401.o \ - opl3.o sb_card.o sequencer_syms.o sound_core.o \ - sound_firmware.o sound_syms.o uart401.o + msnd.o opl3.o sb_card.o sequencer_syms.o \ + sound_core.o sound_firmware.o sound_syms.o \ + uart401.o @@ -53,6 +54,8 @@ obj-$(CONFIG_SOUND_MAD16) += mad16.o ad1848.o sb.o uart401.o obj-$(CONFIG_SOUND_MAUI) += maui.o mpu401.o obj-$(CONFIG_SOUND_MPU401) += mpu401.o +obj-$(CONFIG_SOUND_MSNDCLAS) += msnd.o msnd_classic.o +obj-$(CONFIG_SOUND_MSNDPIN) += msnd.o msnd_pinnacle.o obj-$(CONFIG_SOUND_MSS) += ad1848.o obj-$(CONFIG_SOUND_OPL3SA1) += opl3sa.o ad1848.o uart401.o obj-$(CONFIG_SOUND_PAS) += pas2.o sb.o uart401.o diff -u --recursive --new-file v2.1.105/linux/drivers/sound/dmasound.c linux/drivers/sound/dmasound.c --- v2.1.105/linux/drivers/sound/dmasound.c Wed Apr 8 19:36:27 1998 +++ linux/drivers/sound/dmasound.c Sat Jun 13 13:23:01 1998 @@ -4,6 +4,7 @@ /* OSS/Free compatible Atari TT/Falcon and Amiga DMA sound driver for Linux/m68k +Extended to support Power Macintosh for Linux/ppc by Paul Mackerras (c) 1995 by Michael Schlueter & Michael Marte @@ -85,7 +86,9 @@ #include #include +#ifdef __mc68000__ #include +#endif #include #include #include @@ -100,10 +103,23 @@ #include #include #endif /* CONFIG_AMIGA */ +#ifdef CONFIG_PMAC +#include +#include +#include +#ifdef CONFIG_PMAC_PBOOK +#include +#include +#endif /* CONFIG_PMAC_PBOOK */ +#include "awacs_defs.h" +#include +#include +#endif /* CONFIG_PMAC */ #include "dmasound.h" #include +#define HAS_8BIT_TABLES #ifdef MODULE static int chrdev_registered = 0; @@ -143,6 +159,90 @@ #endif /* CONFIG_AMIGA */ +#ifdef CONFIG_PMAC +/* + * Interrupt numbers and addresses, obtained from the device tree. + */ +static int awacs_irq, awacs_tx_irq, awacs_rx_irq; +static volatile struct awacs_regs *awacs; +static volatile struct dbdma_regs *awacs_txdma, *awacs_rxdma; +static int awacs_rate_index; + +/* + * Space for the DBDMA command blocks. + */ +static void *awacs_tx_cmd_space; +static volatile struct dbdma_cmd *awacs_tx_cmds; + +/* + * Cached values of AWACS registers (we can't read them). + */ +int awacs_reg[5]; + +#define HAS_16BIT_TABLES +#undef HAS_8BIT_TABLES + +/* + * Stuff for outputting a beep. The values range from -327 to +327 + * so we can multiply by an amplitude in the range 0..100 to get a + * signed short value to put in the output buffer. + */ +static short beep_wform[256] = { + 0, 40, 79, 117, 153, 187, 218, 245, + 269, 288, 304, 316, 323, 327, 327, 324, + 318, 310, 299, 288, 275, 262, 249, 236, + 224, 213, 204, 196, 190, 186, 183, 182, + 182, 183, 186, 189, 192, 196, 200, 203, + 206, 208, 209, 209, 209, 207, 204, 201, + 197, 193, 188, 183, 179, 174, 170, 166, + 163, 161, 160, 159, 159, 160, 161, 162, + 164, 166, 168, 169, 171, 171, 171, 170, + 169, 167, 163, 159, 155, 150, 144, 139, + 133, 128, 122, 117, 113, 110, 107, 105, + 103, 103, 103, 103, 104, 104, 105, 105, + 105, 103, 101, 97, 92, 86, 78, 68, + 58, 45, 32, 18, 3, -11, -26, -41, + -55, -68, -79, -88, -95, -100, -102, -102, + -99, -93, -85, -75, -62, -48, -33, -16, + 0, 16, 33, 48, 62, 75, 85, 93, + 99, 102, 102, 100, 95, 88, 79, 68, + 55, 41, 26, 11, -3, -18, -32, -45, + -58, -68, -78, -86, -92, -97, -101, -103, + -105, -105, -105, -104, -104, -103, -103, -103, + -103, -105, -107, -110, -113, -117, -122, -128, + -133, -139, -144, -150, -155, -159, -163, -167, + -169, -170, -171, -171, -171, -169, -168, -166, + -164, -162, -161, -160, -159, -159, -160, -161, + -163, -166, -170, -174, -179, -183, -188, -193, + -197, -201, -204, -207, -209, -209, -209, -208, + -206, -203, -200, -196, -192, -189, -186, -183, + -182, -182, -183, -186, -190, -196, -204, -213, + -224, -236, -249, -262, -275, -288, -299, -310, + -318, -324, -327, -327, -323, -316, -304, -288, + -269, -245, -218, -187, -153, -117, -79, -40, +}; + +#define BEEP_SPEED 2 /* 22050 Hz sample rate */ +#define BEEP_BUFLEN 512 +#define BEEP_VOLUME 15 /* 0 - 100 */ + +static int beep_volume = BEEP_VOLUME; +static int beep_playing = 0; +static short *beep_buf; +static volatile struct dbdma_cmd *beep_dbdma_cmd; +static void (*orig_mksound)(unsigned int, unsigned int); + +#ifdef CONFIG_PMAC_PBOOK +/* + * Stuff for restoring after a sleep. + */ +static int awacs_sleep_notify(struct notifier_block *, unsigned long, void *); +struct notifier_block awacs_sleep_notifier = { + awacs_sleep_notify +}; +#endif /* CONFIG_PMAC_PBOOK */ + +#endif /* CONFIG_PMAC */ /*** Some declarations *******************************************************/ @@ -150,6 +250,7 @@ #define DMASND_TT 1 #define DMASND_FALCON 2 #define DMASND_AMIGA 3 +#define DMASND_AWACS 4 #define MAX_CATCH_RADIUS 10 #define MIN_BUFFERS 4 @@ -165,164 +266,164 @@ #define le2be16dbl(x) (((x)<<8 & 0xff00ff00) | ((x)>>8 & 0x00ff00ff)) #define IOCTL_IN(arg, ret) \ - do { int error = get_user(ret, (int *)(arg)); \ - if (error) return error; \ - } while (0) + do { int error = get_user(ret, (int *)(arg)); \ + if (error) return error; \ + } while (0) #define IOCTL_OUT(arg, ret) ioctl_return((int *)(arg), ret) /*** Some low level helpers **************************************************/ - +#ifdef HAS_8BIT_TABLES /* 8 bit mu-law */ static char ulaw2dma8[] = { - -126, -122, -118, -114, -110, -106, -102, -98, - -94, -90, -86, -82, -78, -74, -70, -66, - -63, -61, -59, -57, -55, -53, -51, -49, - -47, -45, -43, -41, -39, -37, -35, -33, - -31, -30, -29, -28, -27, -26, -25, -24, - -23, -22, -21, -20, -19, -18, -17, -16, - -16, -15, -15, -14, -14, -13, -13, -12, - -12, -11, -11, -10, -10, -9, -9, -8, - -8, -8, -7, -7, -7, -7, -6, -6, - -6, -6, -5, -5, -5, -5, -4, -4, - -4, -4, -4, -4, -3, -3, -3, -3, - -3, -3, -3, -3, -2, -2, -2, -2, - -2, -2, -2, -2, -2, -2, -2, -2, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 0, - 125, 121, 117, 113, 109, 105, 101, 97, - 93, 89, 85, 81, 77, 73, 69, 65, - 62, 60, 58, 56, 54, 52, 50, 48, - 46, 44, 42, 40, 38, 36, 34, 32, - 30, 29, 28, 27, 26, 25, 24, 23, - 22, 21, 20, 19, 18, 17, 16, 15, - 15, 14, 14, 13, 13, 12, 12, 11, - 11, 10, 10, 9, 9, 8, 8, 7, - 7, 7, 6, 6, 6, 6, 5, 5, - 5, 5, 4, 4, 4, 4, 3, 3, - 3, 3, 3, 3, 2, 2, 2, 2, - 2, 2, 2, 2, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 + -126, -122, -118, -114, -110, -106, -102, -98, + -94, -90, -86, -82, -78, -74, -70, -66, + -63, -61, -59, -57, -55, -53, -51, -49, + -47, -45, -43, -41, -39, -37, -35, -33, + -31, -30, -29, -28, -27, -26, -25, -24, + -23, -22, -21, -20, -19, -18, -17, -16, + -16, -15, -15, -14, -14, -13, -13, -12, + -12, -11, -11, -10, -10, -9, -9, -8, + -8, -8, -7, -7, -7, -7, -6, -6, + -6, -6, -5, -5, -5, -5, -4, -4, + -4, -4, -4, -4, -3, -3, -3, -3, + -3, -3, -3, -3, -2, -2, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -2, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 0, + 125, 121, 117, 113, 109, 105, 101, 97, + 93, 89, 85, 81, 77, 73, 69, 65, + 62, 60, 58, 56, 54, 52, 50, 48, + 46, 44, 42, 40, 38, 36, 34, 32, + 30, 29, 28, 27, 26, 25, 24, 23, + 22, 21, 20, 19, 18, 17, 16, 15, + 15, 14, 14, 13, 13, 12, 12, 11, + 11, 10, 10, 9, 9, 8, 8, 7, + 7, 7, 6, 6, 6, 6, 5, 5, + 5, 5, 4, 4, 4, 4, 3, 3, + 3, 3, 3, 3, 2, 2, 2, 2, + 2, 2, 2, 2, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }; /* 8 bit A-law */ static char alaw2dma8[] = { - -22, -21, -24, -23, -18, -17, -20, -19, - -30, -29, -32, -31, -26, -25, -28, -27, - -11, -11, -12, -12, -9, -9, -10, -10, - -15, -15, -16, -16, -13, -13, -14, -14, - -86, -82, -94, -90, -70, -66, -78, -74, - -118, -114, -126, -122, -102, -98, -110, -106, - -43, -41, -47, -45, -35, -33, -39, -37, - -59, -57, -63, -61, -51, -49, -55, -53, - -2, -2, -2, -2, -2, -2, -2, -2, - -2, -2, -2, -2, -2, -2, -2, -2, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -6, -6, -6, -6, -5, -5, -5, -5, - -8, -8, -8, -8, -7, -7, -7, -7, - -3, -3, -3, -3, -3, -3, -3, -3, - -4, -4, -4, -4, -4, -4, -4, -4, - 21, 20, 23, 22, 17, 16, 19, 18, - 29, 28, 31, 30, 25, 24, 27, 26, - 10, 10, 11, 11, 8, 8, 9, 9, - 14, 14, 15, 15, 12, 12, 13, 13, - 86, 82, 94, 90, 70, 66, 78, 74, - 118, 114, 126, 122, 102, 98, 110, 106, - 43, 41, 47, 45, 35, 33, 39, 37, - 59, 57, 63, 61, 51, 49, 55, 53, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 5, 5, 5, 5, 4, 4, 4, 4, - 7, 7, 7, 7, 6, 6, 6, 6, - 2, 2, 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 3 + -22, -21, -24, -23, -18, -17, -20, -19, + -30, -29, -32, -31, -26, -25, -28, -27, + -11, -11, -12, -12, -9, -9, -10, -10, + -15, -15, -16, -16, -13, -13, -14, -14, + -86, -82, -94, -90, -70, -66, -78, -74, + -118, -114, -126, -122, -102, -98, -110, -106, + -43, -41, -47, -45, -35, -33, -39, -37, + -59, -57, -63, -61, -51, -49, -55, -53, + -2, -2, -2, -2, -2, -2, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -2, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -6, -6, -6, -6, -5, -5, -5, -5, + -8, -8, -8, -8, -7, -7, -7, -7, + -3, -3, -3, -3, -3, -3, -3, -3, + -4, -4, -4, -4, -4, -4, -4, -4, + 21, 20, 23, 22, 17, 16, 19, 18, + 29, 28, 31, 30, 25, 24, 27, 26, + 10, 10, 11, 11, 8, 8, 9, 9, + 14, 14, 15, 15, 12, 12, 13, 13, + 86, 82, 94, 90, 70, 66, 78, 74, + 118, 114, 126, 122, 102, 98, 110, 106, + 43, 41, 47, 45, 35, 33, 39, 37, + 59, 57, 63, 61, 51, 49, 55, 53, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 4, 4, 4, 4, + 7, 7, 7, 7, 6, 6, 6, 6, + 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3 }; - +#endif /* HAS_8BIT_TABLES */ #ifdef HAS_16BIT_TABLES /* 16 bit mu-law */ -static char ulaw2dma16[] = { - -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956, - -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764, - -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412, - -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316, - -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140, - -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092, - -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004, - -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980, - -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436, - -1372, -1308, -1244, -1180, -1116, -1052, -988, -924, - -876, -844, -812, -780, -748, -716, -684, -652, - -620, -588, -556, -524, -492, -460, -428, -396, - -372, -356, -340, -324, -308, -292, -276, -260, - -244, -228, -212, -196, -180, -164, -148, -132, - -120, -112, -104, -96, -88, -80, -72, -64, - -56, -48, -40, -32, -24, -16, -8, 0, - 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956, - 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764, - 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412, - 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316, - 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140, - 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092, - 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004, - 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980, - 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436, - 1372, 1308, 1244, 1180, 1116, 1052, 988, 924, - 876, 844, 812, 780, 748, 716, 684, 652, - 620, 588, 556, 524, 492, 460, 428, 396, - 372, 356, 340, 324, 308, 292, 276, 260, - 244, 228, 212, 196, 180, 164, 148, 132, - 120, 112, 104, 96, 88, 80, 72, 64, - 56, 48, 40, 32, 24, 16, 8, 0, +static short ulaw2dma16[] = { + -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956, + -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764, + -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412, + -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316, + -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140, + -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092, + -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004, + -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980, + -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436, + -1372, -1308, -1244, -1180, -1116, -1052, -988, -924, + -876, -844, -812, -780, -748, -716, -684, -652, + -620, -588, -556, -524, -492, -460, -428, -396, + -372, -356, -340, -324, -308, -292, -276, -260, + -244, -228, -212, -196, -180, -164, -148, -132, + -120, -112, -104, -96, -88, -80, -72, -64, + -56, -48, -40, -32, -24, -16, -8, 0, + 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956, + 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764, + 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412, + 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316, + 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140, + 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092, + 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004, + 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980, + 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436, + 1372, 1308, 1244, 1180, 1116, 1052, 988, 924, + 876, 844, 812, 780, 748, 716, 684, 652, + 620, 588, 556, 524, 492, 460, 428, 396, + 372, 356, 340, 324, 308, 292, 276, 260, + 244, 228, 212, 196, 180, 164, 148, 132, + 120, 112, 104, 96, 88, 80, 72, 64, + 56, 48, 40, 32, 24, 16, 8, 0, }; /* 16 bit A-law */ -static char alaw2dma16[] = { - -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736, - -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, - -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368, - -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392, - -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944, - -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136, - -11008, -10496, -12032, -11520, -8960, -8448, -9984, -9472, - -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568, - -344, -328, -376, -360, -280, -264, -312, -296, - -472, -456, -504, -488, -408, -392, -440, -424, - -88, -72, -120, -104, -24, -8, -56, -40, - -216, -200, -248, -232, -152, -136, -184, -168, - -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184, - -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, - -688, -656, -752, -720, -560, -528, -624, -592, - -944, -912, -1008, -976, -816, -784, -880, -848, - 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736, - 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, - 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368, - 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, - 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944, - 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, - 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472, - 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, - 344, 328, 376, 360, 280, 264, 312, 296, - 472, 456, 504, 488, 408, 392, 440, 424, - 88, 72, 120, 104, 24, 8, 56, 40, - 216, 200, 248, 232, 152, 136, 184, 168, - 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184, - 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, - 688, 656, 752, 720, 560, 528, 624, 592, - 944, 912, 1008, 976, 816, 784, 880, 848, +static short alaw2dma16[] = { + -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736, + -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, + -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368, + -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392, + -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944, + -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136, + -11008, -10496, -12032, -11520, -8960, -8448, -9984, -9472, + -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568, + -344, -328, -376, -360, -280, -264, -312, -296, + -472, -456, -504, -488, -408, -392, -440, -424, + -88, -72, -120, -104, -24, -8, -56, -40, + -216, -200, -248, -232, -152, -136, -184, -168, + -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184, + -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, + -688, -656, -752, -720, -560, -528, -624, -592, + -944, -912, -1008, -976, -816, -784, -880, -848, + 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736, + 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, + 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368, + 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, + 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944, + 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, + 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472, + 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, + 344, 328, 376, 360, 280, 264, 312, 296, + 472, 456, 504, 488, 408, 392, 440, 424, + 88, 72, 120, 104, 24, 8, 56, 40, + 216, 200, 248, 232, 152, 136, 184, 168, + 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184, + 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, + 688, 656, 752, 720, 560, 528, 624, 592, + 944, 912, 1008, 976, 816, 784, 880, 848, }; #endif /* HAS_16BIT_TABLES */ @@ -332,75 +433,75 @@ /* 14 bit mu-law (LSB) */ static char alaw2dma14l[] = { - 33, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 33, 33, 33, 33, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 49, 17, 49, 17, 49, 17, 49, 17, - 49, 17, 49, 17, 49, 17, 49, 17, - 41, 57, 9, 25, 41, 57, 9, 25, - 41, 57, 9, 25, 41, 57, 9, 25, - 37, 45, 53, 61, 5, 13, 21, 29, - 37, 45, 53, 61, 5, 13, 21, 29, - 35, 39, 43, 47, 51, 55, 59, 63, - 3, 7, 11, 15, 19, 23, 27, 31, - 34, 36, 38, 40, 42, 44, 46, 48, - 50, 52, 54, 56, 58, 60, 62, 0, - 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31, - 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, - 15, 47, 15, 47, 15, 47, 15, 47, - 15, 47, 15, 47, 15, 47, 15, 47, - 23, 7, 55, 39, 23, 7, 55, 39, - 23, 7, 55, 39, 23, 7, 55, 39, - 27, 19, 11, 3, 59, 51, 43, 35, - 27, 19, 11, 3, 59, 51, 43, 35, - 29, 25, 21, 17, 13, 9, 5, 1, - 61, 57, 53, 49, 45, 41, 37, 33, - 30, 28, 26, 24, 22, 20, 18, 16, - 14, 12, 10, 8, 6, 4, 2, 0 + 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 49, 17, 49, 17, 49, 17, 49, 17, + 49, 17, 49, 17, 49, 17, 49, 17, + 41, 57, 9, 25, 41, 57, 9, 25, + 41, 57, 9, 25, 41, 57, 9, 25, + 37, 45, 53, 61, 5, 13, 21, 29, + 37, 45, 53, 61, 5, 13, 21, 29, + 35, 39, 43, 47, 51, 55, 59, 63, + 3, 7, 11, 15, 19, 23, 27, 31, + 34, 36, 38, 40, 42, 44, 46, 48, + 50, 52, 54, 56, 58, 60, 62, 0, + 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, + 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, + 15, 47, 15, 47, 15, 47, 15, 47, + 15, 47, 15, 47, 15, 47, 15, 47, + 23, 7, 55, 39, 23, 7, 55, 39, + 23, 7, 55, 39, 23, 7, 55, 39, + 27, 19, 11, 3, 59, 51, 43, 35, + 27, 19, 11, 3, 59, 51, 43, 35, + 29, 25, 21, 17, 13, 9, 5, 1, + 61, 57, 53, 49, 45, 41, 37, 33, + 30, 28, 26, 24, 22, 20, 18, 16, + 14, 12, 10, 8, 6, 4, 2, 0 }; /* 14 bit A-law (LSB) */ static char alaw2dma14l[] = { - 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, - 16, 48, 16, 48, 16, 48, 16, 48, - 16, 48, 16, 48, 16, 48, 16, 48, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 42, 46, 34, 38, 58, 62, 50, 54, - 10, 14, 2, 6, 26, 30, 18, 22, - 42, 46, 34, 38, 58, 62, 50, 54, - 10, 14, 2, 6, 26, 30, 18, 22, - 40, 56, 8, 24, 40, 56, 8, 24, - 40, 56, 8, 24, 40, 56, 8, 24, - 20, 28, 4, 12, 52, 60, 36, 44, - 20, 28, 4, 12, 52, 60, 36, 44, - 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, - 48, 16, 48, 16, 48, 16, 48, 16, - 48, 16, 48, 16, 48, 16, 48, 16, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 22, 18, 30, 26, 6, 2, 14, 10, - 54, 50, 62, 58, 38, 34, 46, 42, - 22, 18, 30, 26, 6, 2, 14, 10, - 54, 50, 62, 58, 38, 34, 46, 42, - 24, 8, 56, 40, 24, 8, 56, 40, - 24, 8, 56, 40, 24, 8, 56, 40, - 44, 36, 60, 52, 12, 4, 28, 20, - 44, 36, 60, 52, 12, 4, 28, 20 + 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, + 16, 48, 16, 48, 16, 48, 16, 48, + 16, 48, 16, 48, 16, 48, 16, 48, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 42, 46, 34, 38, 58, 62, 50, 54, + 10, 14, 2, 6, 26, 30, 18, 22, + 42, 46, 34, 38, 58, 62, 50, 54, + 10, 14, 2, 6, 26, 30, 18, 22, + 40, 56, 8, 24, 40, 56, 8, 24, + 40, 56, 8, 24, 40, 56, 8, 24, + 20, 28, 4, 12, 52, 60, 36, 44, + 20, 28, 4, 12, 52, 60, 36, 44, + 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, + 48, 16, 48, 16, 48, 16, 48, 16, + 48, 16, 48, 16, 48, 16, 48, 16, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 22, 18, 30, 26, 6, 2, 14, 10, + 54, 50, 62, 58, 38, 34, 46, 42, + 22, 18, 30, 26, 6, 2, 14, 10, + 54, 50, 62, 58, 38, 34, 46, 42, + 24, 8, 56, 40, 24, 8, 56, 40, + 24, 8, 56, 40, 24, 8, 56, 40, + 44, 36, 60, 52, 12, 4, 28, 20, + 44, 36, 60, 52, 12, 4, 28, 20 }; #endif /* HAS_14BIT_TABLES */ @@ -456,26 +557,48 @@ u_char frame[], long *frameUsed, long frameLeft); #endif /* CONFIG_AMIGA */ +#ifdef CONFIG_PMAC +static long pmac_ct_law(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft); +static long pmac_ct_s8(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft); +static long pmac_ct_u8(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft); +static long pmac_ct_s16(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft); +static long pmac_ct_u16(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft); +static long pmac_ctx_law(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft); +static long pmac_ctx_s8(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft); +static long pmac_ctx_u8(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft); +static long pmac_ctx_s16(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft); +static long pmac_ctx_u16(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft); +#endif /* CONFIG_PMAC */ /*** Machine definitions *****************************************************/ typedef struct { - int type; - void *(*dma_alloc)(unsigned int, int); - void (*dma_free)(void *, unsigned int); - int (*irqinit)(void); + int type; + void *(*dma_alloc)(unsigned int, int); + void (*dma_free)(void *, unsigned int); + int (*irqinit)(void); #ifdef MODULE - void (*irqcleanup)(void); + void (*irqcleanup)(void); #endif /* MODULE */ - void (*init)(void); - void (*silence)(void); - int (*setFormat)(int); - int (*setVolume)(int); - int (*setBass)(int); - int (*setTreble)(int); - int (*setGain)(int); - void (*play)(void); + void (*init)(void); + void (*silence)(void); + int (*setFormat)(int); + int (*setVolume)(int); + int (*setBass)(int); + int (*setTreble)(int); + int (*setGain)(int); + void (*play)(void); } MACHINE; @@ -483,38 +606,38 @@ typedef struct { - int format; /* AFMT_* */ - int stereo; /* 0 = mono, 1 = stereo */ - int size; /* 8/16 bit*/ - int speed; /* speed */ + int format; /* AFMT_* */ + int stereo; /* 0 = mono, 1 = stereo */ + int size; /* 8/16 bit*/ + int speed; /* speed */ } SETTINGS; typedef struct { - long (*ct_ulaw)(const u_char *, unsigned long, u_char *, long *, long); - long (*ct_alaw)(const u_char *, unsigned long, u_char *, long *, long); - long (*ct_s8)(const u_char *, unsigned long, u_char *, long *, long); - long (*ct_u8)(const u_char *, unsigned long, u_char *, long *, long); - long (*ct_s16be)(const u_char *, unsigned long, u_char *, long *, long); - long (*ct_u16be)(const u_char *, unsigned long, u_char *, long *, long); - long (*ct_s16le)(const u_char *, unsigned long, u_char *, long *, long); - long (*ct_u16le)(const u_char *, unsigned long, u_char *, long *, long); + long (*ct_ulaw)(const u_char *, unsigned long, u_char *, long *, long); + long (*ct_alaw)(const u_char *, unsigned long, u_char *, long *, long); + long (*ct_s8)(const u_char *, unsigned long, u_char *, long *, long); + long (*ct_u8)(const u_char *, unsigned long, u_char *, long *, long); + long (*ct_s16be)(const u_char *, unsigned long, u_char *, long *, long); + long (*ct_u16be)(const u_char *, unsigned long, u_char *, long *, long); + long (*ct_s16le)(const u_char *, unsigned long, u_char *, long *, long); + long (*ct_u16le)(const u_char *, unsigned long, u_char *, long *, long); } TRANS; struct sound_settings { - MACHINE mach; /* machine dependent things */ - SETTINGS hard; /* hardware settings */ - SETTINGS soft; /* software settings */ - SETTINGS dsp; /* /dev/dsp default settings */ - TRANS *trans; /* supported translations */ - int volume_left; /* volume (range is machine dependent) */ - int volume_right; - int bass; /* tone (range is machine dependent) */ - int treble; - int gain; - int minDev; /* minor device number currently open */ -#ifdef CONFIG_ATARI - int bal; /* balance factor for expanding (not volume!) */ - u_long data; /* data for expanding */ + MACHINE mach; /* machine dependent things */ + SETTINGS hard; /* hardware settings */ + SETTINGS soft; /* software settings */ + SETTINGS dsp; /* /dev/dsp default settings */ + TRANS *trans; /* supported translations */ + int volume_left; /* volume (range is machine dependent) */ + int volume_right; + int bass; /* tone (range is machine dependent) */ + int treble; + int gain; + int minDev; /* minor device number currently open */ +#if defined(CONFIG_ATARI) || defined(CONFIG_PMAC) + int bal; /* balance factor for expanding (not volume!) */ + u_long data; /* data for expanding */ #endif /* CONFIG_ATARI */ }; @@ -561,6 +684,26 @@ static void ami_sq_interrupt(int irq, void *dummy, struct pt_regs *fp); #endif /* CONFIG_AMIGA */ +#ifdef CONFIG_PMAC +static void *PMacAlloc(unsigned int size, int flags); +static void PMacFree(void *ptr, unsigned int size); +static int PMacIrqInit(void); +#ifdef MODULE +static void PMacIrqCleanup(void); +#endif /* MODULE */ +static void PMacSilence(void); +static void PMacInit(void); +static void PMacPlay(void); +static int PMacSetFormat(int format); +static int PMacSetVolume(int volume); +static void pmac_awacs_tx_intr(int irq, void *devid, struct pt_regs *regs); +static void pmac_awacs_intr(int irq, void *devid, struct pt_regs *regs); +static void awacs_write(int val); +static int awacs_get_volume(int reg, int lshift); +static int awacs_volume_setter(int volume, int n, int mute, int lshift); +static void awacs_mksound(unsigned int hz, unsigned int ticks); +static void awacs_nosound(unsigned long xx); +#endif /* CONFIG_PMAC */ /*** Mid level stuff *********************************************************/ @@ -574,7 +717,9 @@ #ifdef CONFIG_ATARI static int sound_set_bass(int bass); #endif /* CONFIG_ATARI */ +#if defined(CONFIG_ATARI) || defined(CONFIG_AMIGA) static int sound_set_treble(int treble); +#endif /* CONFIG_ATARI || CONFIG_AMIGA */ static long sound_copy_translate(const u_char *userPtr, unsigned long userCount, u_char frame[], long *frameUsed, @@ -603,29 +748,30 @@ */ struct sound_queue { - int max_count, block_size; - char **buffers; - - /* it shouldn't be necessary to declare any of these volatile */ - int front, rear, count; - int rear_size; - /* - * The use of the playing field depends on the hardware - * - * Atari: The number of frames that are loaded/playing - * - * Amiga: Bit 0 is set: a frame is loaded - * Bit 1 is set: a frame is playing - */ - int playing; - struct wait_queue *write_queue, *open_queue, *sync_queue; - int open_mode; - int busy, syncing; + int max_count, block_size; + char **buffers; + int max_active; + + /* it shouldn't be necessary to declare any of these volatile */ + int front, rear, count; + int rear_size; + /* + * The use of the playing field depends on the hardware + * + * Atari, PMac: The number of frames that are loaded/playing + * + * Amiga: Bit 0 is set: a frame is loaded + * Bit 1 is set: a frame is playing + */ + int playing; + struct wait_queue *write_queue, *open_queue, *sync_queue; + int open_mode; + int busy, syncing; #ifdef CONFIG_ATARI - int ignore_int; /* ++TeSche: used for Falcon */ + int ignore_int; /* ++TeSche: used for Falcon */ #endif /* CONFIG_ATARI */ #ifdef CONFIG_AMIGA - int block_size_half, block_size_quarter; + int block_size_half, block_size_quarter; #endif /* CONFIG_AMIGA */ }; @@ -648,6 +794,7 @@ static void sq_reset(void); static int sq_sync(void); static int sq_release(void); +static void init_settings(void); /* @@ -655,9 +802,9 @@ */ struct sound_state { - int busy; - char buf[512]; - int len, ptr; + int busy; + char buf[512]; + int len, ptr; }; static struct sound_state state; @@ -681,10 +828,10 @@ loff_t *ppos); static inline int ioctl_return(int *addr, int value) { - if (value < 0) - return(value); + if (value < 0) + return(value); - return put_user(value, addr); + return put_user(value, addr)? -EFAULT: 0; } static int unknown_minor_dev(char *fname, int dev); static int sound_ioctl(struct inode *inode, struct file *file, u_int cmd, @@ -730,554 +877,581 @@ static long ata_ct_law(const u_char *userPtr, unsigned long userCount, u_char frame[], long *frameUsed, long frameLeft) { - char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8; - long count, used; - u_char *p = &frame[*frameUsed]; - - count = min(userCount, frameLeft); - if (sound.soft.stereo) - count &= ~1; - used = count; - while (count > 0) { - u_char data; - get_user(data, userPtr++); - *p++ = table[data]; - count--; - } - *frameUsed += used; - return(used); + char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8; + long count, used; + u_char *p = &frame[*frameUsed]; + + count = min(userCount, frameLeft); + if (sound.soft.stereo) + count &= ~1; + used = count; + while (count > 0) { + u_char data; + if (get_user(data, userPtr++)) + return -EFAULT; + *p++ = table[data]; + count--; + } + *frameUsed += used; + return(used); } static long ata_ct_s8(const u_char *userPtr, unsigned long userCount, u_char frame[], long *frameUsed, long frameLeft) { - long count, used; - void *p = &frame[*frameUsed]; + long count, used; + void *p = &frame[*frameUsed]; - count = min(userCount, frameLeft); - if (sound.soft.stereo) - count &= ~1; - used = count; - copy_from_user(p, userPtr, count); - *frameUsed += used; - return(used); + count = min(userCount, frameLeft); + if (sound.soft.stereo) + count &= ~1; + used = count; + if (copy_from_user(p, userPtr, count)) + return -EFAULT; + *frameUsed += used; + return(used); } static long ata_ct_u8(const u_char *userPtr, unsigned long userCount, u_char frame[], long *frameUsed, long frameLeft) { - long count, used; + long count, used; - if (!sound.soft.stereo) { - u_char *p = &frame[*frameUsed]; - count = min(userCount, frameLeft); - used = count; - while (count > 0) { - u_char data; - get_user(data, userPtr++); - *p++ = data ^ 0x80; - count--; - } - } else { - u_short *p = (u_short *)&frame[*frameUsed]; - count = min(userCount, frameLeft)>>1; - used = count*2; - while (count > 0) { - u_short data; - get_user(data, ((u_short *)userPtr)++); - *p++ = data ^ 0x8080; - count--; - } - } - *frameUsed += used; - return(used); + if (!sound.soft.stereo) { + u_char *p = &frame[*frameUsed]; + count = min(userCount, frameLeft); + used = count; + while (count > 0) { + u_char data; + if (get_user(data, userPtr++)) + return -EFAULT; + *p++ = data ^ 0x80; + count--; + } + } else { + u_short *p = (u_short *)&frame[*frameUsed]; + count = min(userCount, frameLeft)>>1; + used = count*2; + while (count > 0) { + u_short data; + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + *p++ = data ^ 0x8080; + count--; + } + } + *frameUsed += used; + return(used); } static long ata_ct_s16be(const u_char *userPtr, unsigned long userCount, u_char frame[], long *frameUsed, long frameLeft) { - long count, used; - u_long data; + long count, used; + u_long data; - if (!sound.soft.stereo) { - u_short *p = (u_short *)&frame[*frameUsed]; - count = min(userCount, frameLeft)>>1; - used = count*2; - while (count > 0) { - get_user(data, ((u_short *)userPtr)++); - *p++ = data; - *p++ = data; - count--; - } - *frameUsed += used*2; - } else { - void *p = (u_short *)&frame[*frameUsed]; - count = min(userCount, frameLeft) & ~3; - used = count; - copy_from_user(p, userPtr, count); - *frameUsed += used; - } - return(used); + if (!sound.soft.stereo) { + u_short *p = (u_short *)&frame[*frameUsed]; + count = min(userCount, frameLeft)>>1; + used = count*2; + while (count > 0) { + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + *p++ = data; + *p++ = data; + count--; + } + *frameUsed += used*2; + } else { + void *p = (u_short *)&frame[*frameUsed]; + count = min(userCount, frameLeft) & ~3; + used = count; + if (copy_from_user(p, userPtr, count)) + return -EFAULT; + *frameUsed += used; + } + return(used); } static long ata_ct_u16be(const u_char *userPtr, unsigned long userCount, u_char frame[], long *frameUsed, long frameLeft) { - long count, used; - u_long data; + long count, used; + u_long data; - if (!sound.soft.stereo) { - u_short *p = (u_short *)&frame[*frameUsed]; - count = min(userCount, frameLeft)>>1; - used = count*2; - while (count > 0) { - get_user(data, ((u_short *)userPtr)++); - data ^= 0x8000; - *p++ = data; - *p++ = data; - count--; - } - *frameUsed += used*2; - } else { - u_long *p = (u_long *)&frame[*frameUsed]; - count = min(userCount, frameLeft)>>2; - used = count*4; - while (count > 0) { - get_user(data, ((u_int *)userPtr)++); - *p++ = data ^ 0x80008000; - count--; + if (!sound.soft.stereo) { + u_short *p = (u_short *)&frame[*frameUsed]; + count = min(userCount, frameLeft)>>1; + used = count*2; + while (count > 0) { + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + data ^= 0x8000; + *p++ = data; + *p++ = data; + count--; + } + *frameUsed += used*2; + } else { + u_long *p = (u_long *)&frame[*frameUsed]; + count = min(userCount, frameLeft)>>2; + used = count*4; + while (count > 0) { + if (get_user(data, ((u_int *)userPtr)++)) + return -EFAULT; + *p++ = data ^ 0x80008000; + count--; + } + *frameUsed += used; } - *frameUsed += used; - } - return(used); + return(used); } static long ata_ct_s16le(const u_char *userPtr, unsigned long userCount, u_char frame[], long *frameUsed, long frameLeft) { - long count, used; - u_long data; + long count, used; + u_long data; - count = frameLeft; - if (!sound.soft.stereo) { - u_short *p = (u_short *)&frame[*frameUsed]; - count = min(userCount, frameLeft)>>1; - used = count*2; - while (count > 0) { - get_user(data, ((u_short *)userPtr)++); - data = le2be16(data); - *p++ = data; - *p++ = data; - count--; - } - *frameUsed += used*2; - } else { - u_long *p = (u_long *)&frame[*frameUsed]; - count = min(userCount, frameLeft)>>2; - used = count*4; - while (count > 0) { - get_user(data, ((u_int *)userPtr)++); - data = le2be16dbl(data); - *p++ = data; - count--; + count = frameLeft; + if (!sound.soft.stereo) { + u_short *p = (u_short *)&frame[*frameUsed]; + count = min(userCount, frameLeft)>>1; + used = count*2; + while (count > 0) { + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + data = le2be16(data); + *p++ = data; + *p++ = data; + count--; + } + *frameUsed += used*2; + } else { + u_long *p = (u_long *)&frame[*frameUsed]; + count = min(userCount, frameLeft)>>2; + used = count*4; + while (count > 0) { + if (get_user(data, ((u_int *)userPtr)++)) + return -EFAULT; + data = le2be16dbl(data); + *p++ = data; + count--; + } + *frameUsed += used; } - *frameUsed += used; - } - return(used); + return(used); } static long ata_ct_u16le(const u_char *userPtr, unsigned long userCount, u_char frame[], long *frameUsed, long frameLeft) { - long count, used; - u_long data; + long count, used; + u_long data; - count = frameLeft; - if (!sound.soft.stereo) { - u_short *p = (u_short *)&frame[*frameUsed]; - count = min(userCount, frameLeft)>>1; - used = count*2; - while (count > 0) { - get_user(data, ((u_short *)userPtr)++); - data = le2be16(data) ^ 0x8000; - *p++ = data; - *p++ = data; - } - *frameUsed += used*2; - } else { - u_long *p = (u_long *)&frame[*frameUsed]; - count = min(userCount, frameLeft)>>2; - used = count; - while (count > 0) { - get_user(data, ((u_int *)userPtr)++); - data = le2be16dbl(data) ^ 0x80008000; - *p++ = data; - count--; + count = frameLeft; + if (!sound.soft.stereo) { + u_short *p = (u_short *)&frame[*frameUsed]; + count = min(userCount, frameLeft)>>1; + used = count*2; + while (count > 0) { + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + data = le2be16(data) ^ 0x8000; + *p++ = data; + *p++ = data; + } + *frameUsed += used*2; + } else { + u_long *p = (u_long *)&frame[*frameUsed]; + count = min(userCount, frameLeft)>>2; + used = count; + while (count > 0) { + if (get_user(data, ((u_int *)userPtr)++)) + return -EFAULT; + data = le2be16dbl(data) ^ 0x80008000; + *p++ = data; + count--; + } + *frameUsed += used; } - *frameUsed += used; - } - return(used); + return(used); } static long ata_ctx_law(const u_char *userPtr, unsigned long userCount, u_char frame[], long *frameUsed, long frameLeft) { - char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8; - /* this should help gcc to stuff everything into registers */ - u_long data = sound.data; - long bal = sound.bal; - long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - long used, usedf; - - used = userCount; - usedf = frameLeft; - if (!sound.soft.stereo) { - u_char *p = &frame[*frameUsed]; - while (frameLeft) { - u_char c; - if (bal < 0) { - if (!userCount) - break; - get_user(c, userPtr++); - data = table[c]; - userCount--; - bal += hSpeed; - } - *p++ = data; - frameLeft--; - bal -= sSpeed; - } - } else { - u_short *p = (u_short *)&frame[*frameUsed]; - while (frameLeft >= 2) { - u_char c; - if (bal < 0) { - if (userCount < 2) - break; - get_user(c, userPtr++); - data = table[c] << 8; - get_user(c, userPtr++); - data |= table[c]; - userCount -= 2; - bal += hSpeed; - } - *p++ = data; - frameLeft -= 2; - bal -= sSpeed; - } - } - sound.bal = bal; - sound.data = data; - used -= userCount; - *frameUsed += usedf-frameLeft; - return(used); + char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8; + /* this should help gcc to stuff everything into registers */ + u_long data = sound.data; + long bal = sound.bal; + long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; + long used, usedf; + + used = userCount; + usedf = frameLeft; + if (!sound.soft.stereo) { + u_char *p = &frame[*frameUsed]; + while (frameLeft) { + u_char c; + if (bal < 0) { + if (!userCount) + break; + if (get_user(c, userPtr++)) + return -EFAULT; + data = table[c]; + userCount--; + bal += hSpeed; + } + *p++ = data; + frameLeft--; + bal -= sSpeed; + } + } else { + u_short *p = (u_short *)&frame[*frameUsed]; + while (frameLeft >= 2) { + u_char c; + if (bal < 0) { + if (userCount < 2) + break; + if (get_user(c, userPtr++)) + return -EFAULT; + data = table[c] << 8; + if (get_user(c, userPtr++)) + return -EFAULT; + data |= table[c]; + userCount -= 2; + bal += hSpeed; + } + *p++ = data; + frameLeft -= 2; + bal -= sSpeed; + } + } + sound.bal = bal; + sound.data = data; + used -= userCount; + *frameUsed += usedf-frameLeft; + return(used); } static long ata_ctx_s8(const u_char *userPtr, unsigned long userCount, u_char frame[], long *frameUsed, long frameLeft) { - /* this should help gcc to stuff everything into registers */ - u_long data = sound.data; - long bal = sound.bal; - long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - long used, usedf; - - used = userCount; - usedf = frameLeft; - if (!sound.soft.stereo) { - u_char *p = &frame[*frameUsed]; - while (frameLeft) { - if (bal < 0) { - if (!userCount) - break; - get_user(data, userPtr++); - userCount--; - bal += hSpeed; - } - *p++ = data; - frameLeft--; - bal -= sSpeed; - } - } else { - u_short *p = (u_short *)&frame[*frameUsed]; - while (frameLeft >= 2) { - if (bal < 0) { - if (userCount < 2) - break; - get_user(data, ((u_short *)userPtr)++); - userCount -= 2; - bal += hSpeed; - } - *p++ = data; - frameLeft -= 2; - bal -= sSpeed; - } - } - sound.bal = bal; - sound.data = data; - used -= userCount; - *frameUsed += usedf-frameLeft; - return(used); + /* this should help gcc to stuff everything into registers */ + u_long data = sound.data; + long bal = sound.bal; + long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; + long used, usedf; + + used = userCount; + usedf = frameLeft; + if (!sound.soft.stereo) { + u_char *p = &frame[*frameUsed]; + while (frameLeft) { + if (bal < 0) { + if (!userCount) + break; + if (get_user(data, userPtr++)) + return -EFAULT; + userCount--; + bal += hSpeed; + } + *p++ = data; + frameLeft--; + bal -= sSpeed; + } + } else { + u_short *p = (u_short *)&frame[*frameUsed]; + while (frameLeft >= 2) { + if (bal < 0) { + if (userCount < 2) + break; + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + userCount -= 2; + bal += hSpeed; + } + *p++ = data; + frameLeft -= 2; + bal -= sSpeed; + } + } + sound.bal = bal; + sound.data = data; + used -= userCount; + *frameUsed += usedf-frameLeft; + return(used); } static long ata_ctx_u8(const u_char *userPtr, unsigned long userCount, u_char frame[], long *frameUsed, long frameLeft) { - /* this should help gcc to stuff everything into registers */ - u_long data = sound.data; - long bal = sound.bal; - long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - long used, usedf; - - used = userCount; - usedf = frameLeft; - if (!sound.soft.stereo) { - u_char *p = &frame[*frameUsed]; - while (frameLeft) { - if (bal < 0) { - if (!userCount) - break; - get_user(data, userPtr++); - data ^= 0x80; - userCount--; - bal += hSpeed; - } - *p++ = data; - frameLeft--; - bal -= sSpeed; - } - } else { - u_short *p = (u_short *)&frame[*frameUsed]; - while (frameLeft >= 2) { - if (bal < 0) { - if (userCount < 2) - break; - get_user(data, ((u_short *)userPtr)++); - data ^= 0x8080; - userCount -= 2; - bal += hSpeed; - } - *p++ = data; - frameLeft -= 2; - bal -= sSpeed; - } - } - sound.bal = bal; - sound.data = data; - used -= userCount; - *frameUsed += usedf-frameLeft; - return(used); + /* this should help gcc to stuff everything into registers */ + u_long data = sound.data; + long bal = sound.bal; + long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; + long used, usedf; + + used = userCount; + usedf = frameLeft; + if (!sound.soft.stereo) { + u_char *p = &frame[*frameUsed]; + while (frameLeft) { + if (bal < 0) { + if (!userCount) + break; + if (get_user(data, userPtr++)) + return -EFAULT; + data ^= 0x80; + userCount--; + bal += hSpeed; + } + *p++ = data; + frameLeft--; + bal -= sSpeed; + } + } else { + u_short *p = (u_short *)&frame[*frameUsed]; + while (frameLeft >= 2) { + if (bal < 0) { + if (userCount < 2) + break; + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + data ^= 0x8080; + userCount -= 2; + bal += hSpeed; + } + *p++ = data; + frameLeft -= 2; + bal -= sSpeed; + } + } + sound.bal = bal; + sound.data = data; + used -= userCount; + *frameUsed += usedf-frameLeft; + return(used); } static long ata_ctx_s16be(const u_char *userPtr, unsigned long userCount, u_char frame[], long *frameUsed, long frameLeft) { - /* this should help gcc to stuff everything into registers */ - u_long data = sound.data; - long bal = sound.bal; - long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - long used, usedf; - - used = userCount; - usedf = frameLeft; - if (!sound.soft.stereo) { - u_short *p = (u_short *)&frame[*frameUsed]; - while (frameLeft >= 4) { - if (bal < 0) { - if (userCount < 2) - break; - get_user(data, ((u_short *)userPtr)++); - userCount -= 2; - bal += hSpeed; - } - *p++ = data; - *p++ = data; - frameLeft -= 4; - bal -= sSpeed; - } - } else { - u_long *p = (u_long *)&frame[*frameUsed]; - while (frameLeft >= 4) { - if (bal < 0) { - if (userCount < 4) - break; - get_user(data, ((u_int *)userPtr)++); - userCount -= 4; - bal += hSpeed; - } - *p++ = data; - frameLeft -= 4; - bal -= sSpeed; - } - } - sound.bal = bal; - sound.data = data; - used -= userCount; - *frameUsed += usedf-frameLeft; - return(used); + /* this should help gcc to stuff everything into registers */ + u_long data = sound.data; + long bal = sound.bal; + long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; + long used, usedf; + + used = userCount; + usedf = frameLeft; + if (!sound.soft.stereo) { + u_short *p = (u_short *)&frame[*frameUsed]; + while (frameLeft >= 4) { + if (bal < 0) { + if (userCount < 2) + break; + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + userCount -= 2; + bal += hSpeed; + } + *p++ = data; + *p++ = data; + frameLeft -= 4; + bal -= sSpeed; + } + } else { + u_long *p = (u_long *)&frame[*frameUsed]; + while (frameLeft >= 4) { + if (bal < 0) { + if (userCount < 4) + break; + if (get_user(data, ((u_int *)userPtr)++)) + return -EFAULT; + userCount -= 4; + bal += hSpeed; + } + *p++ = data; + frameLeft -= 4; + bal -= sSpeed; + } + } + sound.bal = bal; + sound.data = data; + used -= userCount; + *frameUsed += usedf-frameLeft; + return(used); } static long ata_ctx_u16be(const u_char *userPtr, unsigned long userCount, u_char frame[], long *frameUsed, long frameLeft) { - /* this should help gcc to stuff everything into registers */ - u_long data = sound.data; - long bal = sound.bal; - long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - long used, usedf; - - used = userCount; - usedf = frameLeft; - if (!sound.soft.stereo) { - u_short *p = (u_short *)&frame[*frameUsed]; - while (frameLeft >= 4) { - if (bal < 0) { - if (userCount < 2) - break; - get_user(data, ((u_short *)userPtr)++); - data ^= 0x8000; - userCount -= 2; - bal += hSpeed; - } - *p++ = data; - *p++ = data; - frameLeft -= 4; - bal -= sSpeed; - } - } else { - u_long *p = (u_long *)&frame[*frameUsed]; - while (frameLeft >= 4) { - if (bal < 0) { - if (userCount < 4) - break; - get_user(data, ((u_int *)userPtr)++); - data ^= 0x80008000; - userCount -= 4; - bal += hSpeed; - } - *p++ = data; - frameLeft -= 4; - bal -= sSpeed; - } - } - sound.bal = bal; - sound.data = data; - used -= userCount; - *frameUsed += usedf-frameLeft; - return(used); + /* this should help gcc to stuff everything into registers */ + u_long data = sound.data; + long bal = sound.bal; + long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; + long used, usedf; + + used = userCount; + usedf = frameLeft; + if (!sound.soft.stereo) { + u_short *p = (u_short *)&frame[*frameUsed]; + while (frameLeft >= 4) { + if (bal < 0) { + if (userCount < 2) + break; + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + data ^= 0x8000; + userCount -= 2; + bal += hSpeed; + } + *p++ = data; + *p++ = data; + frameLeft -= 4; + bal -= sSpeed; + } + } else { + u_long *p = (u_long *)&frame[*frameUsed]; + while (frameLeft >= 4) { + if (bal < 0) { + if (userCount < 4) + break; + if (get_user(data, ((u_int *)userPtr)++)) + return -EFAULT; + data ^= 0x80008000; + userCount -= 4; + bal += hSpeed; + } + *p++ = data; + frameLeft -= 4; + bal -= sSpeed; + } + } + sound.bal = bal; + sound.data = data; + used -= userCount; + *frameUsed += usedf-frameLeft; + return(used); } static long ata_ctx_s16le(const u_char *userPtr, unsigned long userCount, u_char frame[], long *frameUsed, long frameLeft) { - /* this should help gcc to stuff everything into registers */ - u_long data = sound.data; - long bal = sound.bal; - long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - long used, usedf; - - used = userCount; - usedf = frameLeft; - if (!sound.soft.stereo) { - u_short *p = (u_short *)&frame[*frameUsed]; - while (frameLeft >= 4) { - if (bal < 0) { - if (userCount < 2) - break; - get_user(data, ((u_short *)userPtr)++); - data = le2be16(data); - userCount -= 2; - bal += hSpeed; - } - *p++ = data; - *p++ = data; - frameLeft -= 4; - bal -= sSpeed; - } - } else { - u_long *p = (u_long *)&frame[*frameUsed]; - while (frameLeft >= 4) { - if (bal < 0) { - if (userCount < 4) - break; - get_user(data, ((u_int *)userPtr)++); - data = le2be16dbl(data); - userCount -= 4; - bal += hSpeed; - } - *p++ = data; - frameLeft -= 4; - bal -= sSpeed; - } - } - sound.bal = bal; - sound.data = data; - used -= userCount; - *frameUsed += usedf-frameLeft; - return(used); + /* this should help gcc to stuff everything into registers */ + u_long data = sound.data; + long bal = sound.bal; + long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; + long used, usedf; + + used = userCount; + usedf = frameLeft; + if (!sound.soft.stereo) { + u_short *p = (u_short *)&frame[*frameUsed]; + while (frameLeft >= 4) { + if (bal < 0) { + if (userCount < 2) + break; + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + data = le2be16(data); + userCount -= 2; + bal += hSpeed; + } + *p++ = data; + *p++ = data; + frameLeft -= 4; + bal -= sSpeed; + } + } else { + u_long *p = (u_long *)&frame[*frameUsed]; + while (frameLeft >= 4) { + if (bal < 0) { + if (userCount < 4) + break; + if (get_user(data, ((u_int *)userPtr)++)) + return -EFAULT; + data = le2be16dbl(data); + userCount -= 4; + bal += hSpeed; + } + *p++ = data; + frameLeft -= 4; + bal -= sSpeed; + } + } + sound.bal = bal; + sound.data = data; + used -= userCount; + *frameUsed += usedf-frameLeft; + return(used); } static long ata_ctx_u16le(const u_char *userPtr, unsigned long userCount, u_char frame[], long *frameUsed, long frameLeft) { - /* this should help gcc to stuff everything into registers */ - u_long data = sound.data; - long bal = sound.bal; - long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - long used, usedf; - - used = userCount; - usedf = frameLeft; - if (!sound.soft.stereo) { - u_short *p = (u_short *)&frame[*frameUsed]; - while (frameLeft >= 4) { - if (bal < 0) { - if (userCount < 2) - break; - get_user(data, ((u_short *)userPtr)++); - data = le2be16(data) ^ 0x8000; - userCount -= 2; - bal += hSpeed; - } - *p++ = data; - *p++ = data; - frameLeft -= 4; - bal -= sSpeed; - } - } else { - u_long *p = (u_long *)&frame[*frameUsed]; - while (frameLeft >= 4) { - if (bal < 0) { - if (userCount < 4) - break; - get_user(data, ((u_int *)userPtr)++); - data = le2be16dbl(data) ^ 0x80008000; - userCount -= 4; - bal += hSpeed; - } - *p++ = data; - frameLeft -= 4; - bal -= sSpeed; - } - } - sound.bal = bal; - sound.data = data; - used -= userCount; - *frameUsed += usedf-frameLeft; - return(used); + /* this should help gcc to stuff everything into registers */ + u_long data = sound.data; + long bal = sound.bal; + long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; + long used, usedf; + + used = userCount; + usedf = frameLeft; + if (!sound.soft.stereo) { + u_short *p = (u_short *)&frame[*frameUsed]; + while (frameLeft >= 4) { + if (bal < 0) { + if (userCount < 2) + break; + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + data = le2be16(data) ^ 0x8000; + userCount -= 2; + bal += hSpeed; + } + *p++ = data; + *p++ = data; + frameLeft -= 4; + bal -= sSpeed; + } + } else { + u_long *p = (u_long *)&frame[*frameUsed]; + while (frameLeft >= 4) { + if (bal < 0) { + if (userCount < 4) + break; + if (get_user(data, ((u_int *)userPtr)++)) + return -EFAULT; + data = le2be16dbl(data) ^ 0x80008000; + userCount -= 4; + bal += hSpeed; + } + *p++ = data; + frameLeft -= 4; + bal -= sSpeed; + } + } + sound.bal = bal; + sound.data = data; + used -= userCount; + *frameUsed += usedf-frameLeft; + return(used); } #endif /* CONFIG_ATARI */ @@ -1286,291 +1460,698 @@ static long ami_ct_law(const u_char *userPtr, unsigned long userCount, u_char frame[], long *frameUsed, long frameLeft) { - char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8; - long count, used; + char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8; + long count, used; - if (!sound.soft.stereo) { - u_char *p = &frame[*frameUsed]; - count = min(userCount, frameLeft) & ~1; - used = count; - while (count > 0) { - u_char data; - get_user(data, userPtr++); - *p++ = table[data]; - count--; - } - } else { - u_char *left = &frame[*frameUsed>>1]; - u_char *right = left+sq.block_size_half; - count = min(userCount, frameLeft)>>1 & ~1; - used = count*2; - while (count > 0) { - u_char data; - get_user(data, userPtr++); - *left++ = table[data]; - get_user(data, userPtr++); - *right++ = table[data]; - count--; - } - } - *frameUsed += used; - return(used); + if (!sound.soft.stereo) { + u_char *p = &frame[*frameUsed]; + count = min(userCount, frameLeft) & ~1; + used = count; + while (count > 0) { + u_char data; + if (get_user(data, userPtr++)) + return -EFAULT; + *p++ = table[data]; + count--; + } + } else { + u_char *left = &frame[*frameUsed>>1]; + u_char *right = left+sq.block_size_half; + count = min(userCount, frameLeft)>>1 & ~1; + used = count*2; + while (count > 0) { + u_char data; + if (get_user(data, userPtr++)) + return -EFAULT; + *left++ = table[data]; + if (get_user(data, userPtr++)) + return -EFAULT; + *right++ = table[data]; + count--; + } + } + *frameUsed += used; + return(used); } static long ami_ct_s8(const u_char *userPtr, unsigned long userCount, u_char frame[], long *frameUsed, long frameLeft) { - long count, used; + long count, used; - if (!sound.soft.stereo) { - void *p = &frame[*frameUsed]; - count = min(userCount, frameLeft) & ~1; - used = count; - copy_from_user(p, userPtr, count); - } else { - u_char *left = &frame[*frameUsed>>1]; - u_char *right = left+sq.block_size_half; - count = min(userCount, frameLeft)>>1 & ~1; - used = count*2; - while (count > 0) { - get_user(*left++, userPtr++); - get_user(*right++, userPtr++); - count--; - } - } - *frameUsed += used; - return(used); + if (!sound.soft.stereo) { + void *p = &frame[*frameUsed]; + count = min(userCount, frameLeft) & ~1; + used = count; + if (copy_from_user(p, userPtr, count)) + return -EFAULT; + } else { + u_char *left = &frame[*frameUsed>>1]; + u_char *right = left+sq.block_size_half; + count = min(userCount, frameLeft)>>1 & ~1; + used = count*2; + while (count > 0) { + if (get_user(*left++, userPtr++) + || get_user(*right++, userPtr++)) + return -EFAULT; + count--; + } + } + *frameUsed += used; + return(used); } static long ami_ct_u8(const u_char *userPtr, unsigned long userCount, u_char frame[], long *frameUsed, long frameLeft) { - long count, used; + long count, used; - if (!sound.soft.stereo) { - char *p = &frame[*frameUsed]; - count = min(userCount, frameLeft) & ~1; - used = count; - while (count > 0) { - u_char data; - get_user(data, userPtr++); - *p++ = data ^ 0x80; - count--; - } - } else { - u_char *left = &frame[*frameUsed>>1]; - u_char *right = left+sq.block_size_half; - count = min(userCount, frameLeft)>>1 & ~1; - used = count*2; - while (count > 0) { - u_char data; - get_user(data, userPtr++); - *left++ = data ^ 0x80; - get_user(data, userPtr++); - *right++ = data ^ 0x80; - count--; - } - } - *frameUsed += used; - return(used); + if (!sound.soft.stereo) { + char *p = &frame[*frameUsed]; + count = min(userCount, frameLeft) & ~1; + used = count; + while (count > 0) { + u_char data; + if (get_user(data, userPtr++)) + return -EFAULT; + *p++ = data ^ 0x80; + count--; + } + } else { + u_char *left = &frame[*frameUsed>>1]; + u_char *right = left+sq.block_size_half; + count = min(userCount, frameLeft)>>1 & ~1; + used = count*2; + while (count > 0) { + u_char data; + if (get_user(data, userPtr++)) + return -EFAULT; + *left++ = data ^ 0x80; + if (get_user(data, userPtr++)) + return -EFAULT; + *right++ = data ^ 0x80; + count--; + } + } + *frameUsed += used; + return(used); } static long ami_ct_s16be(const u_char *userPtr, unsigned long userCount, u_char frame[], long *frameUsed, long frameLeft) { - long count, used; - u_long data; + long count, used; + u_long data; - if (!sound.soft.stereo) { - u_char *high = &frame[*frameUsed>>1]; - u_char *low = high+sq.block_size_half; - count = min(userCount, frameLeft)>>1 & ~1; - used = count*2; - while (count > 0) { - get_user(data, ((u_short *)userPtr)++); - *high++ = data>>8; - *low++ = (data>>2) & 0x3f; - count--; - } - } else { - u_char *lefth = &frame[*frameUsed>>2]; - u_char *leftl = lefth+sq.block_size_quarter; - u_char *righth = lefth+sq.block_size_half; - u_char *rightl = righth+sq.block_size_quarter; - count = min(userCount, frameLeft)>>2 & ~1; - used = count*4; - while (count > 0) { - get_user(data, ((u_short *)userPtr)++); - *lefth++ = data>>8; - *leftl++ = (data>>2) & 0x3f; - get_user(data, ((u_short *)userPtr)++); - *righth++ = data>>8; - *rightl++ = (data>>2) & 0x3f; - count--; - } - } - *frameUsed += used; - return(used); + if (!sound.soft.stereo) { + u_char *high = &frame[*frameUsed>>1]; + u_char *low = high+sq.block_size_half; + count = min(userCount, frameLeft)>>1 & ~1; + used = count*2; + while (count > 0) { + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + *high++ = data>>8; + *low++ = (data>>2) & 0x3f; + count--; + } + } else { + u_char *lefth = &frame[*frameUsed>>2]; + u_char *leftl = lefth+sq.block_size_quarter; + u_char *righth = lefth+sq.block_size_half; + u_char *rightl = righth+sq.block_size_quarter; + count = min(userCount, frameLeft)>>2 & ~1; + used = count*4; + while (count > 0) { + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + *lefth++ = data>>8; + *leftl++ = (data>>2) & 0x3f; + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + *righth++ = data>>8; + *rightl++ = (data>>2) & 0x3f; + count--; + } + } + *frameUsed += used; + return(used); } static long ami_ct_u16be(const u_char *userPtr, unsigned long userCount, u_char frame[], long *frameUsed, long frameLeft) { - long count, used; - u_long data; + long count, used; + u_long data; - if (!sound.soft.stereo) { - u_char *high = &frame[*frameUsed>>1]; - u_char *low = high+sq.block_size_half; - count = min(userCount, frameLeft)>>1 & ~1; - used = count*2; - while (count > 0) { - get_user(data, ((u_short *)userPtr)++); - data ^= 0x8000; - *high++ = data>>8; - *low++ = (data>>2) & 0x3f; - count--; - } - } else { - u_char *lefth = &frame[*frameUsed>>2]; - u_char *leftl = lefth+sq.block_size_quarter; - u_char *righth = lefth+sq.block_size_half; - u_char *rightl = righth+sq.block_size_quarter; - count = min(userCount, frameLeft)>>2 & ~1; - used = count*4; - while (count > 0) { - get_user(data, ((u_short *)userPtr)++); - data ^= 0x8000; - *lefth++ = data>>8; - *leftl++ = (data>>2) & 0x3f; - get_user(data, ((u_short *)userPtr)++); - data ^= 0x8000; - *righth++ = data>>8; - *rightl++ = (data>>2) & 0x3f; - count--; - } - } - *frameUsed += used; - return(used); + if (!sound.soft.stereo) { + u_char *high = &frame[*frameUsed>>1]; + u_char *low = high+sq.block_size_half; + count = min(userCount, frameLeft)>>1 & ~1; + used = count*2; + while (count > 0) { + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + data ^= 0x8000; + *high++ = data>>8; + *low++ = (data>>2) & 0x3f; + count--; + } + } else { + u_char *lefth = &frame[*frameUsed>>2]; + u_char *leftl = lefth+sq.block_size_quarter; + u_char *righth = lefth+sq.block_size_half; + u_char *rightl = righth+sq.block_size_quarter; + count = min(userCount, frameLeft)>>2 & ~1; + used = count*4; + while (count > 0) { + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + data ^= 0x8000; + *lefth++ = data>>8; + *leftl++ = (data>>2) & 0x3f; + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + data ^= 0x8000; + *righth++ = data>>8; + *rightl++ = (data>>2) & 0x3f; + count--; + } + } + *frameUsed += used; + return(used); } static long ami_ct_s16le(const u_char *userPtr, unsigned long userCount, u_char frame[], long *frameUsed, long frameLeft) { - long count, used; - u_long data; + long count, used; + u_long data; - if (!sound.soft.stereo) { - u_char *high = &frame[*frameUsed>>1]; - u_char *low = high+sq.block_size_half; - count = min(userCount, frameLeft)>>1 & ~1; - used = count*2; - while (count > 0) { - get_user(data, ((u_short *)userPtr)++); - data = le2be16(data); - *high++ = data>>8; - *low++ = (data>>2) & 0x3f; - count--; - } - } else { - u_char *lefth = &frame[*frameUsed>>2]; - u_char *leftl = lefth+sq.block_size_quarter; - u_char *righth = lefth+sq.block_size_half; - u_char *rightl = righth+sq.block_size_quarter; - count = min(userCount, frameLeft)>>2 & ~1; - used = count*4; - while (count > 0) { - get_user(data, ((u_short *)userPtr)++); - data = le2be16(data); - *lefth++ = data>>8; - *leftl++ = (data>>2) & 0x3f; - get_user(data, ((u_short *)userPtr)++); - data = le2be16(data); - *righth++ = data>>8; - *rightl++ = (data>>2) & 0x3f; - count--; - } - } - *frameUsed += used; - return(used); + if (!sound.soft.stereo) { + u_char *high = &frame[*frameUsed>>1]; + u_char *low = high+sq.block_size_half; + count = min(userCount, frameLeft)>>1 & ~1; + used = count*2; + while (count > 0) { + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + data = le2be16(data); + *high++ = data>>8; + *low++ = (data>>2) & 0x3f; + count--; + } + } else { + u_char *lefth = &frame[*frameUsed>>2]; + u_char *leftl = lefth+sq.block_size_quarter; + u_char *righth = lefth+sq.block_size_half; + u_char *rightl = righth+sq.block_size_quarter; + count = min(userCount, frameLeft)>>2 & ~1; + used = count*4; + while (count > 0) { + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + data = le2be16(data); + *lefth++ = data>>8; + *leftl++ = (data>>2) & 0x3f; + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + data = le2be16(data); + *righth++ = data>>8; + *rightl++ = (data>>2) & 0x3f; + count--; + } + } + *frameUsed += used; + return(used); } static long ami_ct_u16le(const u_char *userPtr, unsigned long userCount, u_char frame[], long *frameUsed, long frameLeft) { - long count, used; - u_long data; + long count, used; + u_long data; + + if (!sound.soft.stereo) { + u_char *high = &frame[*frameUsed>>1]; + u_char *low = high+sq.block_size_half; + count = min(userCount, frameLeft)>>1 & ~1; + used = count*2; + while (count > 0) { + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + data = le2be16(data) ^ 0x8000; + *high++ = data>>8; + *low++ = (data>>2) & 0x3f; + count--; + } + } else { + u_char *lefth = &frame[*frameUsed>>2]; + u_char *leftl = lefth+sq.block_size_quarter; + u_char *righth = lefth+sq.block_size_half; + u_char *rightl = righth+sq.block_size_quarter; + count = min(userCount, frameLeft)>>2 & ~1; + used = count*4; + while (count > 0) { + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + data = le2be16(data) ^ 0x8000; + *lefth++ = data>>8; + *leftl++ = (data>>2) & 0x3f; + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + data = le2be16(data) ^ 0x8000; + *righth++ = data>>8; + *rightl++ = (data>>2) & 0x3f; + count--; + } + } + *frameUsed += used; + return(used); +} +#endif /* CONFIG_AMIGA */ + +#ifdef CONFIG_PMAC +static long pmac_ct_law(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft) +{ + short *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma16: alaw2dma16; + long count, used; + short *p = (short *) &frame[*frameUsed]; + int val, stereo = sound.soft.stereo; + + frameLeft >>= 2; + if (stereo) + userCount >>= 1; + used = count = min(userCount, frameLeft); + while (count > 0) { + u_char data; + if (get_user(data, userPtr++)) + return -EFAULT; + val = table[data]; + *p++ = val; + if (stereo) { + if (get_user(data, userPtr++)) + return -EFAULT; + val = table[data]; + } + *p++ = val; + count--; + } + *frameUsed += used * 4; + return stereo? used * 2: used; +} + + +static long pmac_ct_s8(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft) +{ + long count, used; + short *p = (short *) &frame[*frameUsed]; + int val, stereo = sound.soft.stereo; + + frameLeft >>= 2; + if (stereo) + userCount >>= 1; + used = count = min(userCount, frameLeft); + while (count > 0) { + u_char data; + if (get_user(data, userPtr++)) + return -EFAULT; + val = data << 8; + *p++ = val; + if (stereo) { + if (get_user(data, userPtr++)) + return -EFAULT; + val = data << 8; + } + *p++ = val; + count--; + } + *frameUsed += used * 4; + return stereo? used * 2: used; +} + - if (!sound.soft.stereo) { - u_char *high = &frame[*frameUsed>>1]; - u_char *low = high+sq.block_size_half; - count = min(userCount, frameLeft)>>1 & ~1; - used = count*2; +static long pmac_ct_u8(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft) +{ + long count, used; + short *p = (short *) &frame[*frameUsed]; + int val, stereo = sound.soft.stereo; + + frameLeft >>= 2; + if (stereo) + userCount >>= 1; + used = count = min(userCount, frameLeft); while (count > 0) { - get_user(data, ((u_short *)userPtr)++); - data = le2be16(data) ^ 0x8000; - *high++ = data>>8; - *low++ = (data>>2) & 0x3f; - count--; - } - } else { - u_char *lefth = &frame[*frameUsed>>2]; - u_char *leftl = lefth+sq.block_size_quarter; - u_char *righth = lefth+sq.block_size_half; - u_char *rightl = righth+sq.block_size_quarter; - count = min(userCount, frameLeft)>>2 & ~1; - used = count*4; + u_char data; + if (get_user(data, userPtr++)) + return -EFAULT; + val = (data ^ 0x80) << 8; + *p++ = val; + if (stereo) { + if (get_user(data, userPtr++)) + return -EFAULT; + val = (data ^ 0x80) << 8; + } + *p++ = val; + count--; + } + *frameUsed += used * 4; + return stereo? used * 2: used; +} + + +static long pmac_ct_s16(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft) +{ + long count, used; + int stereo = sound.soft.stereo; + short *fp = (short *) &frame[*frameUsed]; + + frameLeft >>= 2; + userCount >>= (stereo? 2: 1); + used = count = min(userCount, frameLeft); + if (!stereo) { + short *up = (short *) userPtr; + while (count > 0) { + short data; + if (get_user(data, up++)) + return -EFAULT; + *fp++ = data; + *fp++ = data; + count--; + } + } else { + if (copy_from_user(fp, userPtr, count * 4)) + return -EFAULT; + } + *frameUsed += used * 4; + return stereo? used * 4: used * 2; +} + +static long pmac_ct_u16(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft) +{ + long count, used; + int mask = (sound.soft.format == AFMT_U16_LE? 0x0080: 0x8000); + int stereo = sound.soft.stereo; + short *fp = (short *) &frame[*frameUsed]; + short *up = (short *) userPtr; + + frameLeft >>= 2; + userCount >>= (stereo? 2: 1); + used = count = min(userCount, frameLeft); while (count > 0) { - get_user(data, ((u_short *)userPtr)++); - data = le2be16(data) ^ 0x8000; - *lefth++ = data>>8; - *leftl++ = (data>>2) & 0x3f; - get_user(data, ((u_short *)userPtr)++); - data = le2be16(data) ^ 0x8000; - *righth++ = data>>8; - *rightl++ = (data>>2) & 0x3f; - count--; - } - } - *frameUsed += used; - return(used); + int data; + if (get_user(data, up++)) + return -EFAULT; + data ^= mask; + *fp++ = data; + if (stereo) { + if (get_user(data, up++)) + return -EFAULT; + data ^= mask; + } + *fp++ = data; + count--; + } + *frameUsed += used * 4; + return stereo? used * 4: used * 2; +} + + +static long pmac_ctx_law(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft) +{ + unsigned short *table = (unsigned short *) + (sound.soft.format == AFMT_MU_LAW ? ulaw2dma16: alaw2dma16); + unsigned int data = sound.data; + unsigned int *p = (unsigned int *) &frame[*frameUsed]; + int bal = sound.bal; + int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; + int utotal, ftotal; + int stereo = sound.soft.stereo; + + frameLeft >>= 2; + if (stereo) + userCount >>= 1; + ftotal = frameLeft; + utotal = userCount; + while (frameLeft) { + u_char c; + if (bal < 0) { + if (userCount == 0) + break; + if (get_user(c, userPtr++)) + return -EFAULT; + data = table[c]; + if (stereo) { + if (get_user(c, userPtr++)) + return -EFAULT; + data = (data << 16) + table[c]; + } else + data = (data << 16) + data; + userCount--; + bal += hSpeed; + } + *p++ = data; + frameLeft--; + bal -= sSpeed; + } + sound.bal = bal; + sound.data = data; + *frameUsed += (ftotal - frameLeft) * 4; + utotal -= userCount; + return stereo? utotal * 2: utotal; +} + + +static long pmac_ctx_s8(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft) +{ + unsigned int *p = (unsigned int *) &frame[*frameUsed]; + unsigned int data = sound.data; + int bal = sound.bal; + int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; + int stereo = sound.soft.stereo; + int utotal, ftotal; + + frameLeft >>= 2; + if (stereo) + userCount >>= 1; + ftotal = frameLeft; + utotal = userCount; + while (frameLeft) { + u_char c; + if (bal < 0) { + if (userCount == 0) + break; + if (get_user(c, userPtr++)) + return -EFAULT; + data = c << 8; + if (stereo) { + if (get_user(c, userPtr++)) + return -EFAULT; + data = (data << 16) + (c << 8); + } else + data = (data << 16) + data; + userCount--; + bal += hSpeed; + } + *p++ = data; + frameLeft--; + bal -= sSpeed; + } + sound.bal = bal; + sound.data = data; + *frameUsed += (ftotal - frameLeft) * 4; + utotal -= userCount; + return stereo? utotal * 2: utotal; +} + + +static long pmac_ctx_u8(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft) +{ + unsigned int *p = (unsigned int *) &frame[*frameUsed]; + unsigned int data = sound.data; + int bal = sound.bal; + int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; + int stereo = sound.soft.stereo; + int utotal, ftotal; + + frameLeft >>= 2; + if (stereo) + userCount >>= 1; + ftotal = frameLeft; + utotal = userCount; + while (frameLeft) { + u_char c; + if (bal < 0) { + if (userCount == 0) + break; + if (get_user(c, userPtr++)) + return -EFAULT; + data = (c ^ 0x80) << 8; + if (stereo) { + if (get_user(c, userPtr++)) + return -EFAULT; + data = (data << 16) + ((c ^ 0x80) << 8); + } else + data = (data << 16) + data; + userCount--; + bal += hSpeed; + } + *p++ = data; + frameLeft--; + bal -= sSpeed; + } + sound.bal = bal; + sound.data = data; + *frameUsed += (ftotal - frameLeft) * 4; + utotal -= userCount; + return stereo? utotal * 2: utotal; +} + + +static long pmac_ctx_s16(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft) +{ + unsigned int *p = (unsigned int *) &frame[*frameUsed]; + unsigned int data = sound.data; + unsigned short *up = (unsigned short *) userPtr; + int bal = sound.bal; + int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; + int stereo = sound.soft.stereo; + int utotal, ftotal; + + frameLeft >>= 2; + if (stereo) + userCount >>= 1; + ftotal = frameLeft; + utotal = userCount; + while (frameLeft) { + unsigned short c; + if (bal < 0) { + if (userCount == 0) + break; + if (get_user(data, up++)) + return -EFAULT; + if (stereo) { + if (get_user(c, up++)) + return -EFAULT; + data = (data << 16) + c; + } else + data = (data << 16) + data; + userCount--; + bal += hSpeed; + } + *p++ = data; + frameLeft--; + bal -= sSpeed; + } + sound.bal = bal; + sound.data = data; + *frameUsed += (ftotal - frameLeft) * 4; + utotal -= userCount; + return stereo? utotal * 4: utotal * 2; +} + + +static long pmac_ctx_u16(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft) +{ + int mask = (sound.soft.format == AFMT_U16_LE? 0x0080: 0x8000); + unsigned int *p = (unsigned int *) &frame[*frameUsed]; + unsigned int data = sound.data; + unsigned short *up = (unsigned short *) userPtr; + int bal = sound.bal; + int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; + int stereo = sound.soft.stereo; + int utotal, ftotal; + + frameLeft >>= 2; + if (stereo) + userCount >>= 1; + ftotal = frameLeft; + utotal = userCount; + while (frameLeft) { + unsigned short c; + if (bal < 0) { + if (userCount == 0) + break; + if (get_user(data, up++)) + return -EFAULT; + data ^= mask; + if (stereo) { + if (get_user(c, up++)) + return -EFAULT; + data = (data << 16) + (c ^ mask); + } else + data = (data << 16) + data; + userCount--; + bal += hSpeed; + } + *p++ = data; + frameLeft--; + bal -= sSpeed; + } + sound.bal = bal; + sound.data = data; + *frameUsed += (ftotal - frameLeft) * 4; + utotal -= userCount; + return stereo? utotal * 4: utotal * 2; } -#endif /* CONFIG_AMIGA */ + +#endif /* CONFIG_PMAC */ #ifdef CONFIG_ATARI static TRANS transTTNormal = { - ata_ct_law, ata_ct_law, ata_ct_s8, ata_ct_u8, NULL, NULL, NULL, NULL + ata_ct_law, ata_ct_law, ata_ct_s8, ata_ct_u8, NULL, NULL, NULL, NULL }; static TRANS transTTExpanding = { - ata_ctx_law, ata_ctx_law, ata_ctx_s8, ata_ctx_u8, NULL, NULL, NULL, NULL + ata_ctx_law, ata_ctx_law, ata_ctx_s8, ata_ctx_u8, NULL, NULL, NULL, NULL }; static TRANS transFalconNormal = { - ata_ct_law, ata_ct_law, ata_ct_s8, ata_ct_u8, ata_ct_s16be, ata_ct_u16be, - ata_ct_s16le, ata_ct_u16le + ata_ct_law, ata_ct_law, ata_ct_s8, ata_ct_u8, + ata_ct_s16be, ata_ct_u16be, ata_ct_s16le, ata_ct_u16le }; static TRANS transFalconExpanding = { - ata_ctx_law, ata_ctx_law, ata_ctx_s8, ata_ctx_u8, ata_ctx_s16be, - ata_ctx_u16be, ata_ctx_s16le, ata_ctx_u16le + ata_ctx_law, ata_ctx_law, ata_ctx_s8, ata_ctx_u8, + ata_ctx_s16be, ata_ctx_u16be, ata_ctx_s16le, ata_ctx_u16le }; #endif /* CONFIG_ATARI */ #ifdef CONFIG_AMIGA static TRANS transAmiga = { - ami_ct_law, ami_ct_law, ami_ct_s8, ami_ct_u8, ami_ct_s16be, ami_ct_u16be, - ami_ct_s16le, ami_ct_u16le + ami_ct_law, ami_ct_law, ami_ct_s8, ami_ct_u8, + ami_ct_s16be, ami_ct_u16be, ami_ct_s16le, ami_ct_u16le }; #endif /* CONFIG_AMIGA */ +#ifdef CONFIG_PMAC +static TRANS transAwacsNormal = { + pmac_ct_law, pmac_ct_law, pmac_ct_s8, pmac_ct_u8, + pmac_ct_s16, pmac_ct_u16, pmac_ct_s16, pmac_ct_u16 +}; + +static TRANS transAwacsExpand = { + pmac_ctx_law, pmac_ctx_law, pmac_ctx_s8, pmac_ctx_u8, + pmac_ctx_s16, pmac_ctx_u16, pmac_ctx_s16, pmac_ctx_u16 +}; +#endif /* CONFIG_PMAC */ /*** Low level stuff *********************************************************/ @@ -1583,40 +2164,40 @@ static void *AtaAlloc(unsigned int size, int flags) { - return( atari_stram_alloc( size, NULL, "dmasound" )); + return( atari_stram_alloc( size, NULL, "dmasound" )); } static void AtaFree(void *obj, unsigned int size) { - atari_stram_free( obj ); + atari_stram_free( obj ); } static int AtaIrqInit(void) { - /* Set up timer A. Timer A - will receive a signal upon end of playing from the sound - hardware. Furthermore Timer A is able to count events - and will cause an interrupt after a programmed number - of events. So all we need to keep the music playing is - to provide the sound hardware with new data upon - an interrupt from timer A. */ - mfp.tim_ct_a = 0; /* ++roman: Stop timer before programming! */ - mfp.tim_dt_a = 1; /* Cause interrupt after first event. */ - mfp.tim_ct_a = 8; /* Turn on event counting. */ - /* Register interrupt handler. */ - request_irq(IRQ_MFP_TIMA, ata_sq_interrupt, IRQ_TYPE_SLOW, - "DMA sound", ata_sq_interrupt); - mfp.int_en_a |= 0x20; /* Turn interrupt on. */ - mfp.int_mk_a |= 0x20; - return(1); + /* Set up timer A. Timer A + will receive a signal upon end of playing from the sound + hardware. Furthermore Timer A is able to count events + and will cause an interrupt after a programmed number + of events. So all we need to keep the music playing is + to provide the sound hardware with new data upon + an interrupt from timer A. */ + mfp.tim_ct_a = 0; /* ++roman: Stop timer before programming! */ + mfp.tim_dt_a = 1; /* Cause interrupt after first event. */ + mfp.tim_ct_a = 8; /* Turn on event counting. */ + /* Register interrupt handler. */ + request_irq(IRQ_MFP_TIMA, ata_sq_interrupt, IRQ_TYPE_SLOW, + "DMA sound", ata_sq_interrupt); + mfp.int_en_a |= 0x20; /* Turn interrupt on. */ + mfp.int_mk_a |= 0x20; + return(1); } #ifdef MODULE static void AtaIrqCleanUp(void) { - mfp.tim_ct_a = 0; /* stop timer */ - mfp.int_en_a &= ~0x20; /* turn interrupt off */ - free_irq(IRQ_MFP_TIMA, ata_sq_interrupt); + mfp.tim_ct_a = 0; /* stop timer */ + mfp.int_en_a &= ~0x20; /* turn interrupt off */ + free_irq(IRQ_MFP_TIMA, ata_sq_interrupt); } #endif /* MODULE */ @@ -1628,17 +2209,17 @@ static int AtaSetBass(int bass) { - sound.bass = TONE_VOXWARE_TO_DB(bass); - atari_microwire_cmd(MW_LM1992_BASS(sound.bass)); - return(TONE_DB_TO_VOXWARE(sound.bass)); + sound.bass = TONE_VOXWARE_TO_DB(bass); + atari_microwire_cmd(MW_LM1992_BASS(sound.bass)); + return(TONE_DB_TO_VOXWARE(sound.bass)); } static int AtaSetTreble(int treble) { - sound.treble = TONE_VOXWARE_TO_DB(treble); - atari_microwire_cmd(MW_LM1992_TREBLE(sound.treble)); - return(TONE_DB_TO_VOXWARE(sound.treble)); + sound.treble = TONE_VOXWARE_TO_DB(treble); + atari_microwire_cmd(MW_LM1992_TREBLE(sound.treble)); + return(TONE_DB_TO_VOXWARE(sound.treble)); } @@ -1650,86 +2231,86 @@ static void TTSilence(void) { - tt_dmasnd.ctrl = DMASND_CTRL_OFF; - atari_microwire_cmd(MW_LM1992_PSG_HIGH); /* mix in PSG signal 1:1 */ + tt_dmasnd.ctrl = DMASND_CTRL_OFF; + atari_microwire_cmd(MW_LM1992_PSG_HIGH); /* mix in PSG signal 1:1 */ } static void TTInit(void) { - int mode, i, idx; - const int freq[4] = {50066, 25033, 12517, 6258}; + int mode, i, idx; + const int freq[4] = {50066, 25033, 12517, 6258}; - /* search a frequency that fits into the allowed error range */ + /* search a frequency that fits into the allowed error range */ - idx = -1; - for (i = 0; i < arraysize(freq); i++) - /* this isn't as much useful for a TT than for a Falcon, but - * then it doesn't hurt very much to implement it for a TT too. - */ - if ((100 * abs(sound.soft.speed - freq[i]) / freq[i]) < catchRadius) - idx = i; - if (idx > -1) { - sound.soft.speed = freq[idx]; - sound.trans = &transTTNormal; - } else - sound.trans = &transTTExpanding; - - TTSilence(); - sound.hard = sound.soft; - - if (sound.hard.speed > 50066) { - /* we would need to squeeze the sound, but we won't do that */ - sound.hard.speed = 50066; - mode = DMASND_MODE_50KHZ; - sound.trans = &transTTNormal; - } else if (sound.hard.speed > 25033) { - sound.hard.speed = 50066; - mode = DMASND_MODE_50KHZ; - } else if (sound.hard.speed > 12517) { - sound.hard.speed = 25033; - mode = DMASND_MODE_25KHZ; - } else if (sound.hard.speed > 6258) { - sound.hard.speed = 12517; - mode = DMASND_MODE_12KHZ; - } else { - sound.hard.speed = 6258; - mode = DMASND_MODE_6KHZ; - } - - tt_dmasnd.mode = (sound.hard.stereo ? - DMASND_MODE_STEREO : DMASND_MODE_MONO) | - DMASND_MODE_8BIT | mode; + idx = -1; + for (i = 0; i < arraysize(freq); i++) + /* this isn't as much useful for a TT than for a Falcon, but + * then it doesn't hurt very much to implement it for a TT too. + */ + if ((100 * abs(sound.soft.speed - freq[i]) / freq[i]) < catchRadius) + idx = i; + if (idx > -1) { + sound.soft.speed = freq[idx]; + sound.trans = &transTTNormal; + } else + sound.trans = &transTTExpanding; + + TTSilence(); + sound.hard = sound.soft; + + if (sound.hard.speed > 50066) { + /* we would need to squeeze the sound, but we won't do that */ + sound.hard.speed = 50066; + mode = DMASND_MODE_50KHZ; + sound.trans = &transTTNormal; + } else if (sound.hard.speed > 25033) { + sound.hard.speed = 50066; + mode = DMASND_MODE_50KHZ; + } else if (sound.hard.speed > 12517) { + sound.hard.speed = 25033; + mode = DMASND_MODE_25KHZ; + } else if (sound.hard.speed > 6258) { + sound.hard.speed = 12517; + mode = DMASND_MODE_12KHZ; + } else { + sound.hard.speed = 6258; + mode = DMASND_MODE_6KHZ; + } + + tt_dmasnd.mode = (sound.hard.stereo ? + DMASND_MODE_STEREO : DMASND_MODE_MONO) | + DMASND_MODE_8BIT | mode; - sound.bal = -sound.soft.speed; + sound.bal = -sound.soft.speed; } static int TTSetFormat(int format) { - /* TT sound DMA supports only 8bit modes */ + /* TT sound DMA supports only 8bit modes */ - switch (format) { + switch (format) { case AFMT_QUERY: - return(sound.soft.format); + return(sound.soft.format); case AFMT_MU_LAW: case AFMT_A_LAW: case AFMT_S8: case AFMT_U8: - break; + break; default: - format = AFMT_S8; - } + format = AFMT_S8; + } - sound.soft.format = format; - sound.soft.size = 8; - if (sound.minDev == SND_DEV_DSP) { - sound.dsp.format = format; - sound.dsp.size = 8; - } - TTInit(); + sound.soft.format = format; + sound.soft.size = 8; + if (sound.minDev == SND_DEV_DSP) { + sound.dsp.format = format; + sound.dsp.size = 8; + } + TTInit(); - return(format); + return(format); } @@ -1740,12 +2321,12 @@ static int TTSetVolume(int volume) { - sound.volume_left = VOLUME_VOXWARE_TO_DB(volume & 0xff); - atari_microwire_cmd(MW_LM1992_BALLEFT(sound.volume_left)); - sound.volume_right = VOLUME_VOXWARE_TO_DB((volume & 0xff00) >> 8); - atari_microwire_cmd(MW_LM1992_BALRIGHT(sound.volume_right)); - return(VOLUME_DB_TO_VOXWARE(sound.volume_left) | - (VOLUME_DB_TO_VOXWARE(sound.volume_right) << 8)); + sound.volume_left = VOLUME_VOXWARE_TO_DB(volume & 0xff); + atari_microwire_cmd(MW_LM1992_BALLEFT(sound.volume_left)); + sound.volume_right = VOLUME_VOXWARE_TO_DB((volume & 0xff00) >> 8); + atari_microwire_cmd(MW_LM1992_BALRIGHT(sound.volume_right)); + return(VOLUME_DB_TO_VOXWARE(sound.volume_left) | + (VOLUME_DB_TO_VOXWARE(sound.volume_right) << 8)); } @@ -1755,9 +2336,9 @@ static int TTSetGain(int gain) { - sound.gain = GAIN_VOXWARE_TO_DB(gain); - atari_microwire_cmd(MW_LM1992_VOLUME(sound.gain)); - return GAIN_DB_TO_VOXWARE(sound.gain); + sound.gain = GAIN_VOXWARE_TO_DB(gain); + atari_microwire_cmd(MW_LM1992_VOLUME(sound.gain)); + return GAIN_DB_TO_VOXWARE(sound.gain); } @@ -1769,133 +2350,133 @@ static void FalconSilence(void) { - /* stop playback, set sample rate 50kHz for PSG sound */ - tt_dmasnd.ctrl = DMASND_CTRL_OFF; - tt_dmasnd.mode = DMASND_MODE_50KHZ | DMASND_MODE_STEREO | DMASND_MODE_8BIT; - tt_dmasnd.int_div = 0; /* STE compatible divider */ - tt_dmasnd.int_ctrl = 0x0; - tt_dmasnd.cbar_src = 0x0000; /* no matrix inputs */ - tt_dmasnd.cbar_dst = 0x0000; /* no matrix outputs */ - tt_dmasnd.dac_src = 1; /* connect ADC to DAC, disconnect matrix */ - tt_dmasnd.adc_src = 3; /* ADC Input = PSG */ + /* stop playback, set sample rate 50kHz for PSG sound */ + tt_dmasnd.ctrl = DMASND_CTRL_OFF; + tt_dmasnd.mode = DMASND_MODE_50KHZ | DMASND_MODE_STEREO | DMASND_MODE_8BIT; + tt_dmasnd.int_div = 0; /* STE compatible divider */ + tt_dmasnd.int_ctrl = 0x0; + tt_dmasnd.cbar_src = 0x0000; /* no matrix inputs */ + tt_dmasnd.cbar_dst = 0x0000; /* no matrix outputs */ + tt_dmasnd.dac_src = 1; /* connect ADC to DAC, disconnect matrix */ + tt_dmasnd.adc_src = 3; /* ADC Input = PSG */ } static void FalconInit(void) { - int divider, i, idx; - const int freq[8] = {49170, 32780, 24585, 19668, 16390, 12292, 9834, 8195}; + int divider, i, idx; + const int freq[8] = {49170, 32780, 24585, 19668, 16390, 12292, 9834, 8195}; - /* search a frequency that fits into the allowed error range */ + /* search a frequency that fits into the allowed error range */ - idx = -1; - for (i = 0; i < arraysize(freq); i++) - /* if we will tolerate 3% error 8000Hz->8195Hz (2.38%) would - * be playable without expanding, but that now a kernel runtime - * option - */ - if ((100 * abs(sound.soft.speed - freq[i]) / freq[i]) < catchRadius) - idx = i; - if (idx > -1) { - sound.soft.speed = freq[idx]; - sound.trans = &transFalconNormal; - } else - sound.trans = &transFalconExpanding; - - FalconSilence(); - sound.hard = sound.soft; + idx = -1; + for (i = 0; i < arraysize(freq); i++) + /* if we will tolerate 3% error 8000Hz->8195Hz (2.38%) would + * be playable without expanding, but that now a kernel runtime + * option + */ + if ((100 * abs(sound.soft.speed - freq[i]) / freq[i]) < catchRadius) + idx = i; + if (idx > -1) { + sound.soft.speed = freq[idx]; + sound.trans = &transFalconNormal; + } else + sound.trans = &transFalconExpanding; - if (sound.hard.size == 16) { - /* the Falcon can play 16bit samples only in stereo */ - sound.hard.stereo = 1; - } + FalconSilence(); + sound.hard = sound.soft; - if (sound.hard.speed > 49170) { - /* we would need to squeeze the sound, but we won't do that */ - sound.hard.speed = 49170; - divider = 1; - sound.trans = &transFalconNormal; - } else if (sound.hard.speed > 32780) { - sound.hard.speed = 49170; - divider = 1; - } else if (sound.hard.speed > 24585) { - sound.hard.speed = 32780; - divider = 2; - } else if (sound.hard.speed > 19668) { - sound.hard.speed = 24585; - divider = 3; - } else if (sound.hard.speed > 16390) { - sound.hard.speed = 19668; - divider = 4; - } else if (sound.hard.speed > 12292) { - sound.hard.speed = 16390; - divider = 5; - } else if (sound.hard.speed > 9834) { - sound.hard.speed = 12292; - divider = 7; - } else if (sound.hard.speed > 8195) { - sound.hard.speed = 9834; - divider = 9; - } else { - sound.hard.speed = 8195; - divider = 11; - } - tt_dmasnd.int_div = divider; - - /* Setup Falcon sound DMA for playback */ - tt_dmasnd.int_ctrl = 0x4; /* Timer A int at play end */ - tt_dmasnd.track_select = 0x0; /* play 1 track, track 1 */ - tt_dmasnd.cbar_src = 0x0001; /* DMA(25MHz) --> DAC */ - tt_dmasnd.cbar_dst = 0x0000; - tt_dmasnd.rec_track_select = 0; - tt_dmasnd.dac_src = 2; /* connect matrix to DAC */ - tt_dmasnd.adc_src = 0; /* ADC Input = Mic */ - - tt_dmasnd.mode = (sound.hard.stereo ? - DMASND_MODE_STEREO : DMASND_MODE_MONO) | - ((sound.hard.size == 8) ? - DMASND_MODE_8BIT : DMASND_MODE_16BIT) | - DMASND_MODE_6KHZ; + if (sound.hard.size == 16) { + /* the Falcon can play 16bit samples only in stereo */ + sound.hard.stereo = 1; + } + + if (sound.hard.speed > 49170) { + /* we would need to squeeze the sound, but we won't do that */ + sound.hard.speed = 49170; + divider = 1; + sound.trans = &transFalconNormal; + } else if (sound.hard.speed > 32780) { + sound.hard.speed = 49170; + divider = 1; + } else if (sound.hard.speed > 24585) { + sound.hard.speed = 32780; + divider = 2; + } else if (sound.hard.speed > 19668) { + sound.hard.speed = 24585; + divider = 3; + } else if (sound.hard.speed > 16390) { + sound.hard.speed = 19668; + divider = 4; + } else if (sound.hard.speed > 12292) { + sound.hard.speed = 16390; + divider = 5; + } else if (sound.hard.speed > 9834) { + sound.hard.speed = 12292; + divider = 7; + } else if (sound.hard.speed > 8195) { + sound.hard.speed = 9834; + divider = 9; + } else { + sound.hard.speed = 8195; + divider = 11; + } + tt_dmasnd.int_div = divider; + + /* Setup Falcon sound DMA for playback */ + tt_dmasnd.int_ctrl = 0x4; /* Timer A int at play end */ + tt_dmasnd.track_select = 0x0; /* play 1 track, track 1 */ + tt_dmasnd.cbar_src = 0x0001; /* DMA(25MHz) --> DAC */ + tt_dmasnd.cbar_dst = 0x0000; + tt_dmasnd.rec_track_select = 0; + tt_dmasnd.dac_src = 2; /* connect matrix to DAC */ + tt_dmasnd.adc_src = 0; /* ADC Input = Mic */ + + tt_dmasnd.mode = (sound.hard.stereo ? + DMASND_MODE_STEREO : DMASND_MODE_MONO) | + ((sound.hard.size == 8) ? + DMASND_MODE_8BIT : DMASND_MODE_16BIT) | + DMASND_MODE_6KHZ; - sound.bal = -sound.soft.speed; + sound.bal = -sound.soft.speed; } static int FalconSetFormat(int format) { - int size; - /* Falcon sound DMA supports 8bit and 16bit modes */ + int size; + /* Falcon sound DMA supports 8bit and 16bit modes */ - switch (format) { + switch (format) { case AFMT_QUERY: - return(sound.soft.format); + return(sound.soft.format); case AFMT_MU_LAW: case AFMT_A_LAW: case AFMT_U8: case AFMT_S8: - size = 8; - break; + size = 8; + break; case AFMT_S16_BE: case AFMT_U16_BE: case AFMT_S16_LE: case AFMT_U16_LE: - size = 16; - break; + size = 16; + break; default: /* :-) */ - size = 8; - format = AFMT_S8; - } - - sound.soft.format = format; - sound.soft.size = size; - if (sound.minDev == SND_DEV_DSP) { - sound.dsp.format = format; - sound.dsp.size = sound.soft.size; - } + size = 8; + format = AFMT_S8; + } + + sound.soft.format = format; + sound.soft.size = size; + if (sound.minDev == SND_DEV_DSP) { + sound.dsp.format = format; + sound.dsp.size = sound.soft.size; + } - FalconInit(); + FalconInit(); - return(format); + return(format); } @@ -1909,164 +2490,164 @@ static int FalconSetVolume(int volume) { - sound.volume_left = VOLUME_VOXWARE_TO_ATT(volume & 0xff); - sound.volume_right = VOLUME_VOXWARE_TO_ATT((volume & 0xff00) >> 8); - tt_dmasnd.output_atten = sound.volume_left << 8 | sound.volume_right << 4; - return(VOLUME_ATT_TO_VOXWARE(sound.volume_left) | - VOLUME_ATT_TO_VOXWARE(sound.volume_right) << 8); + sound.volume_left = VOLUME_VOXWARE_TO_ATT(volume & 0xff); + sound.volume_right = VOLUME_VOXWARE_TO_ATT((volume & 0xff00) >> 8); + tt_dmasnd.output_atten = sound.volume_left << 8 | sound.volume_right << 4; + return(VOLUME_ATT_TO_VOXWARE(sound.volume_left) | + VOLUME_ATT_TO_VOXWARE(sound.volume_right) << 8); } static void ata_sq_play_next_frame(int index) { - char *start, *end; + char *start, *end; - /* used by AtaPlay() if all doubts whether there really is something - * to be played are already wiped out. - */ - start = sq_block_address(sq.front); - end = start+((sq.count == index) ? sq.rear_size : sq.block_size); - /* end might not be a legal virtual address. */ - DMASNDSetEnd(VTOP(end - 1) + 1); - DMASNDSetBase(VTOP(start)); + /* used by AtaPlay() if all doubts whether there really is something + * to be played are already wiped out. + */ + start = sq_block_address(sq.front); + end = start+((sq.count == index) ? sq.rear_size : sq.block_size); + /* end might not be a legal virtual address. */ + DMASNDSetEnd(VTOP(end - 1) + 1); + DMASNDSetBase(VTOP(start)); /* Since only an even number of samples per frame can - be played, we might lose one byte here. (TO DO) */ - sq.front = (sq.front+1) % sq.max_count; - sq.playing++; - tt_dmasnd.ctrl = DMASND_CTRL_ON | DMASND_CTRL_REPEAT; + be played, we might lose one byte here. (TO DO) */ + sq.front = (sq.front+1) % sq.max_count; + sq.playing++; + tt_dmasnd.ctrl = DMASND_CTRL_ON | DMASND_CTRL_REPEAT; } static void AtaPlay(void) { - /* ++TeSche: Note that sq.playing is no longer just a flag but holds - * the number of frames the DMA is currently programmed for instead, - * may be 0, 1 (currently being played) or 2 (pre-programmed). - * - * Changes done to sq.count and sq.playing are a bit more subtle again - * so now I must admit I also prefer disabling the irq here rather - * than considering all possible situations. But the point is that - * disabling the irq doesn't have any bad influence on this version of - * the driver as we benefit from having pre-programmed the DMA - * wherever possible: There's no need to reload the DMA at the exact - * time of an interrupt but only at some time while the pre-programmed - * frame is playing! - */ - atari_disable_irq(IRQ_MFP_TIMA); + /* ++TeSche: Note that sq.playing is no longer just a flag but holds + * the number of frames the DMA is currently programmed for instead, + * may be 0, 1 (currently being played) or 2 (pre-programmed). + * + * Changes done to sq.count and sq.playing are a bit more subtle again + * so now I must admit I also prefer disabling the irq here rather + * than considering all possible situations. But the point is that + * disabling the irq doesn't have any bad influence on this version of + * the driver as we benefit from having pre-programmed the DMA + * wherever possible: There's no need to reload the DMA at the exact + * time of an interrupt but only at some time while the pre-programmed + * frame is playing! + */ + atari_disable_irq(IRQ_MFP_TIMA); - if (sq.playing == 2 || /* DMA is 'full' */ - sq.count <= 0) { /* nothing to do */ - atari_enable_irq(IRQ_MFP_TIMA); - return; - } + if (sq.playing == 2 || /* DMA is 'full' */ + sq.count <= 0) { /* nothing to do */ + atari_enable_irq(IRQ_MFP_TIMA); + return; + } - if (sq.playing == 0) { - /* looks like there's nothing 'in' the DMA yet, so try - * to put two frames into it (at least one is available). - */ - if (sq.count == 1 && sq.rear_size < sq.block_size && !sq.syncing) { - /* hmmm, the only existing frame is not - * yet filled and we're not syncing? - */ - atari_enable_irq(IRQ_MFP_TIMA); - return; - } - ata_sq_play_next_frame(1); - if (sq.count == 1) { - /* no more frames */ - atari_enable_irq(IRQ_MFP_TIMA); - return; - } - if (sq.count == 2 && sq.rear_size < sq.block_size && !sq.syncing) { - /* hmmm, there were two frames, but the second - * one is not yet filled and we're not syncing? - */ - atari_enable_irq(IRQ_MFP_TIMA); - return; - } - ata_sq_play_next_frame(2); - } else { - /* there's already a frame being played so we may only stuff - * one new into the DMA, but even if this may be the last - * frame existing the previous one is still on sq.count. - */ - if (sq.count == 2 && sq.rear_size < sq.block_size && !sq.syncing) { - /* hmmm, the only existing frame is not - * yet filled and we're not syncing? - */ - atari_enable_irq(IRQ_MFP_TIMA); - return; - } - ata_sq_play_next_frame(2); - } - atari_enable_irq(IRQ_MFP_TIMA); + if (sq.playing == 0) { + /* looks like there's nothing 'in' the DMA yet, so try + * to put two frames into it (at least one is available). + */ + if (sq.count == 1 && sq.rear_size < sq.block_size && !sq.syncing) { + /* hmmm, the only existing frame is not + * yet filled and we're not syncing? + */ + atari_enable_irq(IRQ_MFP_TIMA); + return; + } + ata_sq_play_next_frame(1); + if (sq.count == 1) { + /* no more frames */ + atari_enable_irq(IRQ_MFP_TIMA); + return; + } + if (sq.count == 2 && sq.rear_size < sq.block_size && !sq.syncing) { + /* hmmm, there were two frames, but the second + * one is not yet filled and we're not syncing? + */ + atari_enable_irq(IRQ_MFP_TIMA); + return; + } + ata_sq_play_next_frame(2); + } else { + /* there's already a frame being played so we may only stuff + * one new into the DMA, but even if this may be the last + * frame existing the previous one is still on sq.count. + */ + if (sq.count == 2 && sq.rear_size < sq.block_size && !sq.syncing) { + /* hmmm, the only existing frame is not + * yet filled and we're not syncing? + */ + atari_enable_irq(IRQ_MFP_TIMA); + return; + } + ata_sq_play_next_frame(2); + } + atari_enable_irq(IRQ_MFP_TIMA); } static void ata_sq_interrupt(int irq, void *dummy, struct pt_regs *fp) { #if 0 - /* ++TeSche: if you should want to test this... */ - static int cnt = 0; - if (sq.playing == 2) - if (++cnt == 10) { - /* simulate losing an interrupt */ - cnt = 0; - return; - } + /* ++TeSche: if you should want to test this... */ + static int cnt = 0; + if (sq.playing == 2) + if (++cnt == 10) { + /* simulate losing an interrupt */ + cnt = 0; + return; + } #endif - if (sq.ignore_int && (sound.mach.type == DMASND_FALCON)) { - /* ++TeSche: Falcon only: ignore first irq because it comes - * immediately after starting a frame. after that, irqs come - * (almost) like on the TT. - */ - sq.ignore_int = 0; - return; - } + if (sq.ignore_int && (sound.mach.type == DMASND_FALCON)) { + /* ++TeSche: Falcon only: ignore first irq because it comes + * immediately after starting a frame. after that, irqs come + * (almost) like on the TT. + */ + sq.ignore_int = 0; + return; + } - if (!sq.playing) { - /* playing was interrupted and sq_reset() has already cleared - * the sq variables, so better don't do anything here. - */ - WAKE_UP(sq.sync_queue); - return; - } + if (!sq.playing) { + /* playing was interrupted and sq_reset() has already cleared + * the sq variables, so better don't do anything here. + */ + WAKE_UP(sq.sync_queue); + return; + } - /* Probably ;) one frame is finished. Well, in fact it may be that a - * pre-programmed one is also finished because there has been a long - * delay in interrupt delivery and we've completely lost one, but - * there's no way to detect such a situation. In such a case the last - * frame will be played more than once and the situation will recover - * as soon as the irq gets through. - */ - sq.count--; - sq.playing--; + /* Probably ;) one frame is finished. Well, in fact it may be that a + * pre-programmed one is also finished because there has been a long + * delay in interrupt delivery and we've completely lost one, but + * there's no way to detect such a situation. In such a case the last + * frame will be played more than once and the situation will recover + * as soon as the irq gets through. + */ + sq.count--; + sq.playing--; - if (!sq.playing) { - tt_dmasnd.ctrl = DMASND_CTRL_OFF; - sq.ignore_int = 1; - } + if (!sq.playing) { + tt_dmasnd.ctrl = DMASND_CTRL_OFF; + sq.ignore_int = 1; + } - WAKE_UP(sq.write_queue); + WAKE_UP(sq.write_queue); /* At least one block of the queue is free now - so wake up a writing process blocked because - of a full queue. */ + so wake up a writing process blocked because + of a full queue. */ - if ((sq.playing != 1) || (sq.count != 1)) - /* We must be a bit carefully here: sq.count indicates the - * number of buffers used and not the number of frames to - * be played. If sq.count==1 and sq.playing==1 that means - * the only remaining frame was already programmed earlier - * (and is currently running) so we mustn't call AtaPlay() - * here, otherwise we'll play one frame too much. - */ - AtaPlay(); + if ((sq.playing != 1) || (sq.count != 1)) + /* We must be a bit carefully here: sq.count indicates the + * number of buffers used and not the number of frames to + * be played. If sq.count==1 and sq.playing==1 that means + * the only remaining frame was already programmed earlier + * (and is currently running) so we mustn't call AtaPlay() + * here, otherwise we'll play one frame too much. + */ + AtaPlay(); - if (!sq.playing) WAKE_UP(sq.sync_queue); + if (!sq.playing) WAKE_UP(sq.sync_queue); /* We are not playing after AtaPlay(), so there - is nothing to play any more. Wake up a process - waiting for audio output to drain. */ + is nothing to play any more. Wake up a process + waiting for audio output to drain. */ } #endif /* CONFIG_ATARI */ @@ -2080,107 +2661,107 @@ static void *AmiAlloc(unsigned int size, int flags) { - return(amiga_chip_alloc((long)size)); + return(amiga_chip_alloc((long)size)); } static void AmiFree(void *obj, unsigned int size) { - amiga_chip_free (obj); + amiga_chip_free (obj); } static int AmiIrqInit(void) { - /* turn off DMA for audio channels */ - custom.dmacon = AMI_AUDIO_OFF; + /* turn off DMA for audio channels */ + custom.dmacon = AMI_AUDIO_OFF; - /* Register interrupt handler. */ - if (request_irq(IRQ_AMIGA_AUD0, ami_sq_interrupt, 0, - "DMA sound", ami_sq_interrupt)) - return(0); - return(1); + /* Register interrupt handler. */ + if (request_irq(IRQ_AMIGA_AUD0, ami_sq_interrupt, 0, + "DMA sound", ami_sq_interrupt)) + return(0); + return(1); } #ifdef MODULE static void AmiIrqCleanUp(void) { - /* turn off DMA for audio channels */ - custom.dmacon = AMI_AUDIO_OFF; - /* release the interrupt */ - free_irq(IRQ_AMIGA_AUD0, ami_sq_interrupt); + /* turn off DMA for audio channels */ + custom.dmacon = AMI_AUDIO_OFF; + /* release the interrupt */ + free_irq(IRQ_AMIGA_AUD0, ami_sq_interrupt); } #endif /* MODULE */ static void AmiSilence(void) { - /* turn off DMA for audio channels */ - custom.dmacon = AMI_AUDIO_OFF; + /* turn off DMA for audio channels */ + custom.dmacon = AMI_AUDIO_OFF; } static void AmiInit(void) { - int period, i; + int period, i; - AmiSilence(); + AmiSilence(); - if (sound.soft.speed) - period = amiga_colorclock/sound.soft.speed-1; - else - period = amiga_audio_min_period; - sound.hard = sound.soft; - sound.trans = &transAmiga; - - if (period < amiga_audio_min_period) { - /* we would need to squeeze the sound, but we won't do that */ - period = amiga_audio_min_period; - } else if (period > 65535) { - period = 65535; - } - sound.hard.speed = amiga_colorclock/(period+1); - - for (i = 0; i < 4; i++) - custom.aud[i].audper = period; - amiga_audio_period = period; + if (sound.soft.speed) + period = amiga_colorclock/sound.soft.speed-1; + else + period = amiga_audio_min_period; + sound.hard = sound.soft; + sound.trans = &transAmiga; + + if (period < amiga_audio_min_period) { + /* we would need to squeeze the sound, but we won't do that */ + period = amiga_audio_min_period; + } else if (period > 65535) { + period = 65535; + } + sound.hard.speed = amiga_colorclock/(period+1); + + for (i = 0; i < 4; i++) + custom.aud[i].audper = period; + amiga_audio_period = period; - AmiSetTreble(50); /* recommended for newer amiga models */ + AmiSetTreble(50); /* recommended for newer amiga models */ } static int AmiSetFormat(int format) { - int size; + int size; - /* Amiga sound DMA supports 8bit and 16bit (pseudo 14 bit) modes */ + /* Amiga sound DMA supports 8bit and 16bit (pseudo 14 bit) modes */ - switch (format) { + switch (format) { case AFMT_QUERY: - return(sound.soft.format); + return(sound.soft.format); case AFMT_MU_LAW: case AFMT_A_LAW: case AFMT_U8: case AFMT_S8: - size = 8; - break; + size = 8; + break; case AFMT_S16_BE: case AFMT_U16_BE: case AFMT_S16_LE: case AFMT_U16_LE: - size = 16; - break; + size = 16; + break; default: /* :-) */ - size = 8; - format = AFMT_S8; - } - - sound.soft.format = format; - sound.soft.size = size; - if (sound.minDev == SND_DEV_DSP) { - sound.dsp.format = format; - sound.dsp.size = sound.soft.size; - } - AmiInit(); + size = 8; + format = AFMT_S8; + } + + sound.soft.format = format; + sound.soft.size = size; + if (sound.minDev == SND_DEV_DSP) { + sound.dsp.format = format; + sound.dsp.size = sound.soft.size; + } + AmiInit(); - return(format); + return(format); } @@ -2190,22 +2771,22 @@ static int AmiSetVolume(int volume) { - sound.volume_left = VOLUME_VOXWARE_TO_AMI(volume & 0xff); - custom.aud[0].audvol = sound.volume_left; - sound.volume_right = VOLUME_VOXWARE_TO_AMI((volume & 0xff00) >> 8); - custom.aud[1].audvol = sound.volume_right; - return(VOLUME_AMI_TO_VOXWARE(sound.volume_left) | - (VOLUME_AMI_TO_VOXWARE(sound.volume_right) << 8)); + sound.volume_left = VOLUME_VOXWARE_TO_AMI(volume & 0xff); + custom.aud[0].audvol = sound.volume_left; + sound.volume_right = VOLUME_VOXWARE_TO_AMI((volume & 0xff00) >> 8); + custom.aud[1].audvol = sound.volume_right; + return(VOLUME_AMI_TO_VOXWARE(sound.volume_left) | + (VOLUME_AMI_TO_VOXWARE(sound.volume_right) << 8)); } static int AmiSetTreble(int treble) { - sound.treble = treble; - if (treble < 50) - ciaa.pra &= ~0x02; - else - ciaa.pra |= 0x02; - return(treble); + sound.treble = treble; + if (treble < 50) + ciaa.pra &= ~0x02; + else + ciaa.pra |= 0x02; + return(treble); } @@ -2216,164 +2797,550 @@ static void ami_sq_play_next_frame(int index) { - u_char *start, *ch0, *ch1, *ch2, *ch3; - u_long size; + u_char *start, *ch0, *ch1, *ch2, *ch3; + u_long size; - /* used by AmiPlay() if all doubts whether there really is something - * to be played are already wiped out. - */ - start = sq_block_address(sq.front); - size = (sq.count == index ? sq.rear_size : sq.block_size)>>1; - - if (sound.hard.stereo) { - ch0 = start; - ch1 = start+sq.block_size_half; - size >>= 1; - } else { - ch0 = start; - ch1 = start; - } - if (sound.hard.size == 8) { - custom.aud[0].audlc = (u_short *)ZTWO_PADDR(ch0); - custom.aud[0].audlen = size; - custom.aud[1].audlc = (u_short *)ZTWO_PADDR(ch1); - custom.aud[1].audlen = size; - custom.dmacon = AMI_AUDIO_8; - } else { - size >>= 1; - custom.aud[0].audlc = (u_short *)ZTWO_PADDR(ch0); - custom.aud[0].audlen = size; - custom.aud[1].audlc = (u_short *)ZTWO_PADDR(ch1); - custom.aud[1].audlen = size; - if (sound.volume_left == 64 && sound.volume_right == 64) { - /* We can play pseudo 14-bit only with the maximum volume */ - ch3 = ch0+sq.block_size_quarter; - ch2 = ch1+sq.block_size_quarter; - custom.aud[2].audvol = 1; /* we are being affected by the beeps */ - custom.aud[3].audvol = 1; /* restoring volume here helps a bit */ - custom.aud[2].audlc = (u_short *)ZTWO_PADDR(ch2); - custom.aud[2].audlen = size; - custom.aud[3].audlc = (u_short *)ZTWO_PADDR(ch3); - custom.aud[3].audlen = size; - custom.dmacon = AMI_AUDIO_14; - } else - custom.dmacon = AMI_AUDIO_8; - } - sq.front = (sq.front+1) % sq.max_count; - sq.playing |= AMI_PLAY_LOADED; + /* used by AmiPlay() if all doubts whether there really is something + * to be played are already wiped out. + */ + start = sq_block_address(sq.front); + size = (sq.count == index ? sq.rear_size : sq.block_size)>>1; + + if (sound.hard.stereo) { + ch0 = start; + ch1 = start+sq.block_size_half; + size >>= 1; + } else { + ch0 = start; + ch1 = start; + } + if (sound.hard.size == 8) { + custom.aud[0].audlc = (u_short *)ZTWO_PADDR(ch0); + custom.aud[0].audlen = size; + custom.aud[1].audlc = (u_short *)ZTWO_PADDR(ch1); + custom.aud[1].audlen = size; + custom.dmacon = AMI_AUDIO_8; + } else { + size >>= 1; + custom.aud[0].audlc = (u_short *)ZTWO_PADDR(ch0); + custom.aud[0].audlen = size; + custom.aud[1].audlc = (u_short *)ZTWO_PADDR(ch1); + custom.aud[1].audlen = size; + if (sound.volume_left == 64 && sound.volume_right == 64) { + /* We can play pseudo 14-bit only with the maximum volume */ + ch3 = ch0+sq.block_size_quarter; + ch2 = ch1+sq.block_size_quarter; + custom.aud[2].audvol = 1; /* we are being affected by the beeps */ + custom.aud[3].audvol = 1; /* restoring volume here helps a bit */ + custom.aud[2].audlc = (u_short *)ZTWO_PADDR(ch2); + custom.aud[2].audlen = size; + custom.aud[3].audlc = (u_short *)ZTWO_PADDR(ch3); + custom.aud[3].audlen = size; + custom.dmacon = AMI_AUDIO_14; + } else + custom.dmacon = AMI_AUDIO_8; + } + sq.front = (sq.front+1) % sq.max_count; + sq.playing |= AMI_PLAY_LOADED; } static void AmiPlay(void) { - int minframes = 1; + int minframes = 1; - custom.intena = IF_AUD0; + custom.intena = IF_AUD0; - if (sq.playing & AMI_PLAY_LOADED) { - /* There's already a frame loaded */ - custom.intena = IF_SETCLR | IF_AUD0; - return; - } + if (sq.playing & AMI_PLAY_LOADED) { + /* There's already a frame loaded */ + custom.intena = IF_SETCLR | IF_AUD0; + return; + } - if (sq.playing & AMI_PLAY_PLAYING) - /* Increase threshold: frame 1 is already being played */ - minframes = 2; + if (sq.playing & AMI_PLAY_PLAYING) + /* Increase threshold: frame 1 is already being played */ + minframes = 2; - if (sq.count < minframes) { - /* Nothing to do */ - custom.intena = IF_SETCLR | IF_AUD0; - return; - } + if (sq.count < minframes) { + /* Nothing to do */ + custom.intena = IF_SETCLR | IF_AUD0; + return; + } - if (sq.count <= minframes && sq.rear_size < sq.block_size && !sq.syncing) { - /* hmmm, the only existing frame is not - * yet filled and we're not syncing? - */ - custom.intena = IF_SETCLR | IF_AUD0; - return; - } + if (sq.count <= minframes && sq.rear_size < sq.block_size && !sq.syncing) { + /* hmmm, the only existing frame is not + * yet filled and we're not syncing? + */ + custom.intena = IF_SETCLR | IF_AUD0; + return; + } - ami_sq_play_next_frame(minframes); + ami_sq_play_next_frame(minframes); - custom.intena = IF_SETCLR | IF_AUD0; + custom.intena = IF_SETCLR | IF_AUD0; } static void ami_sq_interrupt(int irq, void *dummy, struct pt_regs *fp) { - int minframes = 1; + int minframes = 1; - if (!sq.playing) { - /* Playing was interrupted and sq_reset() has already cleared - * the sq variables, so better don't do anything here. - */ - WAKE_UP(sq.sync_queue); - return; - } + if (!sq.playing) { + /* Playing was interrupted and sq_reset() has already cleared + * the sq variables, so better don't do anything here. + */ + WAKE_UP(sq.sync_queue); + return; + } - if (sq.playing & AMI_PLAY_PLAYING) { - /* We've just finished a frame */ - sq.count--; - WAKE_UP(sq.write_queue); - } + if (sq.playing & AMI_PLAY_PLAYING) { + /* We've just finished a frame */ + sq.count--; + WAKE_UP(sq.write_queue); + } - if (sq.playing & AMI_PLAY_LOADED) - /* Increase threshold: frame 1 is already being played */ - minframes = 2; + if (sq.playing & AMI_PLAY_LOADED) + /* Increase threshold: frame 1 is already being played */ + minframes = 2; - /* Shift the flags */ - sq.playing = (sq.playing<<1) & AMI_PLAY_MASK; + /* Shift the flags */ + sq.playing = (sq.playing<<1) & AMI_PLAY_MASK; - if (!sq.playing) - /* No frame is playing, disable audio DMA */ - custom.dmacon = AMI_AUDIO_OFF; + if (!sq.playing) + /* No frame is playing, disable audio DMA */ + custom.dmacon = AMI_AUDIO_OFF; + + if (sq.count >= minframes) + /* Try to play the next frame */ + AmiPlay(); - if (sq.count >= minframes) - /* Try to play the next frame */ - AmiPlay(); - - if (!sq.playing) - /* Nothing to play anymore. - Wake up a process waiting for audio output to drain. */ - WAKE_UP(sq.sync_queue); + if (!sq.playing) + /* Nothing to play anymore. + Wake up a process waiting for audio output to drain. */ + WAKE_UP(sq.sync_queue); } #endif /* CONFIG_AMIGA */ +#ifdef CONFIG_PMAC + +/* + * PCI PowerMac, with AWACS and DBDMA. + */ + +static void *PMacAlloc(unsigned int size, int flags) +{ + return kmalloc(size, flags); +} + +static void PMacFree(void *ptr, unsigned int size) +{ + kfree(ptr); +} + +static int PMacIrqInit(void) +{ + if (request_irq(awacs_irq, pmac_awacs_intr, 0, "AWACS", 0) + || request_irq(awacs_tx_irq, pmac_awacs_tx_intr, 0, "AWACS out", 0)) + return 0; + return 1; +} + +#ifdef MODULE +static void PMacIrqCleanup(void) +{ + /* turn off output dma */ + out_le32(&awacs_txdma->control, RUN<<16); + /* disable interrupts from awacs interface */ + out_le32(&awacs->control, in_le32(&awacs->control) & 0xfff); + free_irq(awacs_irq, pmac_awacs_intr); + free_irq(awacs_tx_irq, pmac_awacs_tx_intr); + kfree(awacs_tx_cmd_space); + if (beep_buf) + kfree(beep_buf); + kd_mksound = orig_mksound; +} +#endif /* MODULE */ + +static void PMacSilence(void) +{ + /* turn off output dma */ + out_le32(&awacs_txdma->control, RUN<<16); +} + +static int awacs_freqs[8] = { + 44100, 29400, 22050, 17640, 14700, 11025, 8820, 7350 +}; + +static void PMacInit(void) +{ + int i, tolerance; + + switch (sound.soft.format) { + case AFMT_S16_LE: + case AFMT_U16_LE: + sound.hard.format = AFMT_S16_LE; + break; + default: + sound.hard.format = AFMT_S16_BE; + break; + } + sound.hard.stereo = 1; + sound.hard.size = 16; + + /* + * If we have a sample rate which is within catchRadius percent + * of the requested value, we don't have to expand the samples. + * Otherwise choose the next higher rate. + */ + i = 8; + do { + tolerance = catchRadius * awacs_freqs[--i] / 100; + } while (sound.soft.speed > awacs_freqs[i] + tolerance && i > 0); + if (sound.soft.speed >= awacs_freqs[i] - tolerance) + sound.trans = &transAwacsNormal; + else + sound.trans = &transAwacsExpand; + sound.hard.speed = awacs_freqs[i]; + awacs_rate_index = i; + + PMacSilence(); + out_le32(&awacs->control, MASK_IEPC | MASK_IEE | (i << 8) | 0x11); + awacs_reg[1] = (awacs_reg[1] & ~MASK_SAMPLERATE) | (i << 3); + awacs_write(awacs_reg[1] | MASK_ADDR1); + out_le32(&awacs->byteswap, sound.hard.format != AFMT_S16_BE); + + sound.bal = -sound.soft.speed; +} + +static int PMacSetFormat(int format) +{ + int size; + + switch (format) { + case AFMT_QUERY: + return sound.soft.format; + case AFMT_MU_LAW: + case AFMT_A_LAW: + case AFMT_U8: + case AFMT_S8: + size = 8; + break; + case AFMT_S16_BE: + case AFMT_U16_BE: + case AFMT_S16_LE: + case AFMT_U16_LE: + size = 16; + break; + default: /* :-) */ + printk(KERN_ERR "dmasound: unknown format 0x%x, using AFMT_U8\n", + format); + size = 8; + format = AFMT_U8; + } + + sound.soft.format = format; + sound.soft.size = size; + if (sound.minDev == SND_DEV_DSP) { + sound.dsp.format = format; + sound.dsp.size = size; + } + + PMacInit(); + + return format; +} + +#define AWACS_VOLUME_TO_MASK(x) (15 - ((((x) - 1) * 15) / 99)) +#define AWACS_MASK_TO_VOLUME(y) (100 - ((y) * 99 / 15)) + +static int awacs_get_volume(int reg, int lshift) +{ + int volume; + + volume = AWACS_MASK_TO_VOLUME((reg >> lshift) & 0xf); + volume |= AWACS_MASK_TO_VOLUME(reg & 0xf) << 8; + return volume; +} + +static int awacs_volume_setter(int volume, int n, int mute, int lshift) +{ + int r1, rn; + + if (mute && volume == 0) { + r1 = awacs_reg[1] | mute; + } else { + r1 = awacs_reg[1] & ~mute; + rn = awacs_reg[n] & ~(0xf | (0xf << lshift)); + rn |= ((AWACS_VOLUME_TO_MASK(volume & 0xff) & 0xf) << lshift); + rn |= AWACS_VOLUME_TO_MASK((volume >> 8) & 0xff) & 0xf; + awacs_reg[n] = rn; + awacs_write((n << 12) | rn); + volume = awacs_get_volume(rn, lshift); + } + if (r1 != awacs_reg[1]) { + awacs_reg[1] = r1; + awacs_write(r1 | MASK_ADDR1); + } + return volume; +} + +static int PMacSetVolume(int volume) +{ + return awacs_volume_setter(volume, 2, MASK_AMUTE, 6); +} + +static void PMacPlay(void) +{ + volatile struct dbdma_cmd *cp; + int i, count; + unsigned long flags; + + save_flags(flags); cli(); + if (beep_playing) { + /* sound takes precedence over beeps */ + out_le32(&awacs_txdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16); + out_le32(&awacs->control, + (in_le32(&awacs->control) & ~0x1f00) + || (awacs_rate_index << 8)); + out_le32(&awacs->byteswap, sound.hard.format != AFMT_S16_BE); + beep_playing = 0; + } + i = sq.front + sq.playing; + if (i >= sq.max_count) + i -= sq.max_count; + while (sq.playing < 2 && sq.playing < sq.count) { + count = (sq.count == sq.playing + 1)? sq.rear_size: sq.block_size; + if (count < sq.block_size && !sq.syncing) + /* last block not yet filled, and we're not syncing. */ + break; + cp = &awacs_tx_cmds[i]; + st_le16(&cp->req_count, count); + st_le16(&cp->xfer_status, 0); + if (++i >= sq.max_count) + i = 0; + out_le16(&awacs_tx_cmds[i].command, DBDMA_STOP); + out_le16(&cp->command, OUTPUT_MORE + INTR_ALWAYS); + if (sq.playing == 0) + out_le32(&awacs_txdma->cmdptr, virt_to_bus(cp)); + out_le32(&awacs_txdma->control, ((RUN|WAKE) << 16) + (RUN|WAKE)); + ++sq.playing; + } + restore_flags(flags); +} + +static void +pmac_awacs_tx_intr(int irq, void *devid, struct pt_regs *regs) +{ + int i = sq.front; + int stat; + volatile struct dbdma_cmd *cp; + + while (sq.playing > 0) { + cp = &awacs_tx_cmds[i]; + stat = ld_le16(&cp->xfer_status); + if ((stat & ACTIVE) == 0) + break; /* this frame is still going */ + --sq.count; + --sq.playing; + if (++i >= sq.max_count) + i = 0; + } + if (i != sq.front) + WAKE_UP(sq.write_queue); + sq.front = i; + + PMacPlay(); + + if (!sq.playing) + WAKE_UP(sq.sync_queue); +} + +static void +pmac_awacs_intr(int irq, void *devid, struct pt_regs *regs) +{ + int ctrl = in_le32(&awacs->control); + + if (ctrl & MASK_PORTCHG) { + /* do something when headphone is plugged/unplugged? */ + } + if (ctrl & MASK_CNTLERR) { + printk(KERN_ERR "AWACS: error, status = %x\n", + in_le32(&awacs->codec_stat)); + } + /* Writing 1s to the CNTLERR and PORTCHG bits clears them... */ + out_le32(&awacs->control, ctrl); +} + +static void +awacs_write(int val) +{ + while (in_le32(&awacs->codec_ctrl) & MASK_NEWECMD) + ; /* XXX should have timeout */ + out_le32(&awacs->codec_ctrl, val); +} + +static void awacs_nosound(unsigned long xx) +{ + unsigned long flags; + + save_flags(flags); cli(); + if (beep_playing) { + st_le16(&beep_dbdma_cmd->command, DBDMA_STOP); + beep_playing = 0; + } + restore_flags(flags); +} + +static struct timer_list beep_timer = { + NULL, NULL, 0, 0, awacs_nosound +}; + +static void awacs_mksound(unsigned int hz, unsigned int ticks) +{ + unsigned long flags; + int srate = awacs_freqs[BEEP_SPEED]; + int period, ncycles, nsamples; + int i, j, f; + short *p; + static int beep_hz_cache; + static int beep_nsamples_cache; + static int beep_volume_cache; + + if (hz <= srate / BEEP_BUFLEN || hz > srate / 2) { +#if 1 + /* this is a hack for broken X server code */ + hz = 750; + ticks = 12; +#else + /* cancel beep currently playing */ + awacs_nosound(0); + return; +#endif + } + save_flags(flags); cli(); + del_timer(&beep_timer); + if (ticks) { + beep_timer.expires = jiffies + ticks; + add_timer(&beep_timer); + } + if (beep_playing || sq.playing || beep_buf == NULL) { + restore_flags(flags); + return; /* too hard, sorry :-( */ + } + beep_playing = 1; + st_le16(&beep_dbdma_cmd->command, OUTPUT_MORE + BR_ALWAYS); + restore_flags(flags); + + if (hz == beep_hz_cache && beep_volume == beep_volume_cache) { + nsamples = beep_nsamples_cache; + } else { + period = srate * 256 / hz; /* fixed point */ + ncycles = BEEP_BUFLEN * 256 / period; + nsamples = (period * ncycles) >> 8; + f = ncycles * 65536 / nsamples; + j = 0; + p = beep_buf; + for (i = 0; i < nsamples; ++i, p += 2) { + p[0] = p[1] = beep_wform[j >> 8] * beep_volume; + j = (j + f) & 0xffff; + } + beep_hz_cache = hz; + beep_volume_cache = beep_volume; + beep_nsamples_cache = nsamples; + } + + st_le16(&beep_dbdma_cmd->req_count, nsamples*4); + st_le16(&beep_dbdma_cmd->xfer_status, 0); + st_le32(&beep_dbdma_cmd->cmd_dep, virt_to_bus(beep_dbdma_cmd)); + st_le32(&beep_dbdma_cmd->phy_addr, virt_to_bus(beep_buf)); + + save_flags(flags); cli(); + if (beep_playing) { /* i.e. haven't been terminated already */ + out_le32(&awacs_txdma->control, (RUN|WAKE|FLUSH|PAUSE) << 16); + out_le32(&awacs->control, + (in_le32(&awacs->control) & ~0x1f00) + | (BEEP_SPEED << 8)); + out_le32(&awacs->byteswap, 0); + out_le32(&awacs_txdma->cmdptr, virt_to_bus(beep_dbdma_cmd)); + out_le32(&awacs_txdma->control, RUN | (RUN << 16)); + } + restore_flags(flags); +} + +#ifdef CONFIG_PMAC_PBOOK +/* + * Save state when going to sleep, restore it afterwards. + */ +static int awacs_sleep_notify(struct notifier_block *this, + unsigned long code, void *x) +{ + switch (code) { + case PBOOK_SLEEP: + /* XXX we should stop any dma in progress when going to sleep + and restart it when we wake. */ + PMacSilence(); + break; + case PBOOK_WAKE: + out_le32(&awacs->control, MASK_IEPC | MASK_IEE | + (awacs_rate_index << 8) | 0x11); + awacs_write(awacs_reg[0] | MASK_ADDR0); + awacs_write(awacs_reg[1] | MASK_ADDR1); + awacs_write(awacs_reg[2] | MASK_ADDR2); + awacs_write(awacs_reg[4] | MASK_ADDR4); + out_le32(&awacs->byteswap, sound.hard.format != AFMT_S16_BE); + } + return NOTIFY_DONE; +} +#endif /* CONFIG_PMAC_PBOOK */ + +#endif /* CONFIG_PMAC */ /*** Machine definitions *****************************************************/ #ifdef CONFIG_ATARI static MACHINE machTT = { - DMASND_TT, AtaAlloc, AtaFree, AtaIrqInit, + DMASND_TT, AtaAlloc, AtaFree, AtaIrqInit, #ifdef MODULE - AtaIrqCleanUp, + AtaIrqCleanUp, #endif /* MODULE */ - TTInit, TTSilence, TTSetFormat, TTSetVolume, AtaSetBass, AtaSetTreble, - TTSetGain, - AtaPlay + TTInit, TTSilence, TTSetFormat, TTSetVolume, + AtaSetBass, AtaSetTreble, TTSetGain, + AtaPlay }; static MACHINE machFalcon = { - DMASND_FALCON, AtaAlloc, AtaFree, AtaIrqInit, + DMASND_FALCON, AtaAlloc, AtaFree, AtaIrqInit, #ifdef MODULE - AtaIrqCleanUp, + AtaIrqCleanUp, #endif /* MODULE */ - FalconInit, FalconSilence, FalconSetFormat, FalconSetVolume, AtaSetBass, - AtaSetTreble, NULL, AtaPlay + FalconInit, FalconSilence, FalconSetFormat, FalconSetVolume, + AtaSetBass, AtaSetTreble, NULL, + AtaPlay }; #endif /* CONFIG_ATARI */ #ifdef CONFIG_AMIGA static MACHINE machAmiga = { - DMASND_AMIGA, AmiAlloc, AmiFree, AmiIrqInit, + DMASND_AMIGA, AmiAlloc, AmiFree, AmiIrqInit, +#ifdef MODULE + AmiIrqCleanUp, +#endif /* MODULE */ + AmiInit, AmiSilence, AmiSetFormat, AmiSetVolume, + NULL, AmiSetTreble, NULL, + AmiPlay +}; +#endif /* CONFIG_AMIGA */ + +#ifdef CONFIG_PMAC +static MACHINE machPMac = { + DMASND_AWACS, PMacAlloc, PMacFree, PMacIrqInit, #ifdef MODULE - AmiIrqCleanUp, + PMacIrqCleanup, #endif /* MODULE */ - AmiInit, AmiSilence, AmiSetFormat, AmiSetVolume, NULL, AmiSetTreble, - NULL, - AmiPlay + PMacInit, PMacSilence, PMacSetFormat, PMacSetVolume, + NULL, NULL, NULL, /* bass, treble, gain */ + PMacPlay }; #endif /* CONFIG_AMIGA */ @@ -2383,78 +3350,79 @@ static void sound_silence(void) { - /* update hardware settings one more */ - (*sound.mach.init)(); + /* update hardware settings one more */ + (*sound.mach.init)(); - (*sound.mach.silence)(); + (*sound.mach.silence)(); } static void sound_init(void) { - (*sound.mach.init)(); + (*sound.mach.init)(); } static int sound_set_format(int format) { - return(*sound.mach.setFormat)(format); + return(*sound.mach.setFormat)(format); } static int sound_set_speed(int speed) { - if (speed < 0) - return(sound.soft.speed); + if (speed < 0) + return(sound.soft.speed); - sound.soft.speed = speed; - (*sound.mach.init)(); - if (sound.minDev == SND_DEV_DSP) - sound.dsp.speed = sound.soft.speed; + sound.soft.speed = speed; + (*sound.mach.init)(); + if (sound.minDev == SND_DEV_DSP) + sound.dsp.speed = sound.soft.speed; - return(sound.soft.speed); + return(sound.soft.speed); } static int sound_set_stereo(int stereo) { - if (stereo < 0) - return(sound.soft.stereo); + if (stereo < 0) + return(sound.soft.stereo); - stereo = !!stereo; /* should be 0 or 1 now */ + stereo = !!stereo; /* should be 0 or 1 now */ - sound.soft.stereo = stereo; - if (sound.minDev == SND_DEV_DSP) - sound.dsp.stereo = stereo; - (*sound.mach.init)(); + sound.soft.stereo = stereo; + if (sound.minDev == SND_DEV_DSP) + sound.dsp.stereo = stereo; + (*sound.mach.init)(); - return(stereo); + return(stereo); } static int sound_set_volume(int volume) { - return(*sound.mach.setVolume)(volume); + return(*sound.mach.setVolume)(volume); } #ifdef CONFIG_ATARI static int sound_set_bass(int bass) { - return(sound.mach.setBass ? (*sound.mach.setBass)(bass) : 50); + return(sound.mach.setBass ? (*sound.mach.setBass)(bass) : 50); } static int sound_set_gain(int gain) { - return sound.mach.setGain ? sound.mach.setGain(gain) : 100; + return sound.mach.setGain ? sound.mach.setGain(gain) : 100; } #endif /* CONFIG_ATARI */ - +#if defined(CONFIG_ATARI) || defined(CONFIG_AMIGA) static int sound_set_treble(int treble) { - return(sound.mach.setTreble ? (*sound.mach.setTreble)(treble) : 50); + return(sound.mach.setTreble ? (*sound.mach.setTreble)(treble) : 50); } +#endif /* CONFIG_ATARI || CONFIG_AMIGA */ static long sound_copy_translate(const u_char *userPtr, @@ -2462,38 +3430,38 @@ u_char frame[], long *frameUsed, long frameLeft) { - long (*ct_func)(const u_char *, unsigned long, u_char *, long *, long) = NULL; + long (*ct_func)(const u_char *, unsigned long, u_char *, long *, long) = NULL; - switch (sound.soft.format) { + switch (sound.soft.format) { case AFMT_MU_LAW: - ct_func = sound.trans->ct_ulaw; - break; + ct_func = sound.trans->ct_ulaw; + break; case AFMT_A_LAW: - ct_func = sound.trans->ct_alaw; - break; + ct_func = sound.trans->ct_alaw; + break; case AFMT_S8: - ct_func = sound.trans->ct_s8; - break; + ct_func = sound.trans->ct_s8; + break; case AFMT_U8: - ct_func = sound.trans->ct_u8; - break; + ct_func = sound.trans->ct_u8; + break; case AFMT_S16_BE: - ct_func = sound.trans->ct_s16be; - break; + ct_func = sound.trans->ct_s16be; + break; case AFMT_U16_BE: - ct_func = sound.trans->ct_u16be; - break; + ct_func = sound.trans->ct_u16be; + break; case AFMT_S16_LE: - ct_func = sound.trans->ct_s16le; - break; + ct_func = sound.trans->ct_s16le; + break; case AFMT_U16_LE: - ct_func = sound.trans->ct_u16le; - break; - } - if (ct_func) - return(ct_func(userPtr, userCount, frame, frameUsed, frameLeft)); - else - return(0); + ct_func = sound.trans->ct_u16le; + break; + } + if (ct_func) + return(ct_func(userPtr, userCount, frame, frameUsed, frameLeft)); + else + return(0); } @@ -2509,201 +3477,308 @@ static void mixer_init(void) { - mixer.busy = 0; - sound.treble = 0; - sound.bass = 0; - switch (sound.mach.type) { + mixer.busy = 0; + sound.treble = 0; + sound.bass = 0; + switch (sound.mach.type) { #ifdef CONFIG_ATARI case DMASND_TT: - atari_microwire_cmd(MW_LM1992_VOLUME(0)); - sound.volume_left = 0; - atari_microwire_cmd(MW_LM1992_BALLEFT(0)); - sound.volume_right = 0; - atari_microwire_cmd(MW_LM1992_BALRIGHT(0)); - atari_microwire_cmd(MW_LM1992_TREBLE(0)); - atari_microwire_cmd(MW_LM1992_BASS(0)); - break; + atari_microwire_cmd(MW_LM1992_VOLUME(0)); + sound.volume_left = 0; + atari_microwire_cmd(MW_LM1992_BALLEFT(0)); + sound.volume_right = 0; + atari_microwire_cmd(MW_LM1992_BALRIGHT(0)); + atari_microwire_cmd(MW_LM1992_TREBLE(0)); + atari_microwire_cmd(MW_LM1992_BASS(0)); + break; case DMASND_FALCON: - sound.volume_left = (tt_dmasnd.output_atten & 0xf00) >> 8; - sound.volume_right = (tt_dmasnd.output_atten & 0xf0) >> 4; - break; + sound.volume_left = (tt_dmasnd.output_atten & 0xf00) >> 8; + sound.volume_right = (tt_dmasnd.output_atten & 0xf0) >> 4; + break; #endif /* CONFIG_ATARI */ #ifdef CONFIG_AMIGA case DMASND_AMIGA: - sound.volume_left = 64; - sound.volume_right = 64; - custom.aud[0].audvol = sound.volume_left; - custom.aud[3].audvol = 1; /* For pseudo 14bit */ - custom.aud[1].audvol = sound.volume_right; - custom.aud[2].audvol = 1; /* For pseudo 14bit */ - sound.treble = 50; - break; + sound.volume_left = 64; + sound.volume_right = 64; + custom.aud[0].audvol = sound.volume_left; + custom.aud[3].audvol = 1; /* For pseudo 14bit */ + custom.aud[1].audvol = sound.volume_right; + custom.aud[2].audvol = 1; /* For pseudo 14bit */ + sound.treble = 50; + break; #endif /* CONFIG_AMIGA */ - } + } } static int mixer_open(int open_mode) { - if (mixer.busy) - return(-EBUSY); - mixer.busy = 1; - return(0); + mixer.busy = 1; + return(0); } static int mixer_release(void) { - mixer.busy = 0; - return(0); + mixer.busy = 0; + return(0); } static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg) { - int data; - switch (sound.mach.type) { + int data; + switch (sound.mach.type) { #ifdef CONFIG_ATARI case DMASND_FALCON: - switch (cmd) { + switch (cmd) { case SOUND_MIXER_READ_DEVMASK: - return(IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC | SOUND_MASK_SPEAKER)); + return(IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC | SOUND_MASK_SPEAKER)); case SOUND_MIXER_READ_RECMASK: - return(IOCTL_OUT(arg, SOUND_MASK_MIC)); + return(IOCTL_OUT(arg, SOUND_MASK_MIC)); case SOUND_MIXER_READ_STEREODEVS: - return(IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC)); + return(IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC)); case SOUND_MIXER_READ_CAPS: - return(IOCTL_OUT(arg, SOUND_CAP_EXCL_INPUT)); + return(IOCTL_OUT(arg, SOUND_CAP_EXCL_INPUT)); case SOUND_MIXER_READ_VOLUME: - return(IOCTL_OUT(arg, - VOLUME_ATT_TO_VOXWARE(sound.volume_left) | - VOLUME_ATT_TO_VOXWARE(sound.volume_right) << 8)); + return(IOCTL_OUT(arg, + VOLUME_ATT_TO_VOXWARE(sound.volume_left) | + VOLUME_ATT_TO_VOXWARE(sound.volume_right) << 8)); case SOUND_MIXER_WRITE_MIC: - IOCTL_IN(arg, data); - tt_dmasnd.input_gain = - RECLEVEL_VOXWARE_TO_GAIN(data & 0xff) << 4 | - RECLEVEL_VOXWARE_TO_GAIN(data >> 8 & 0xff); - /* fall thru, return set value */ + IOCTL_IN(arg, data); + tt_dmasnd.input_gain = + RECLEVEL_VOXWARE_TO_GAIN(data & 0xff) << 4 | + RECLEVEL_VOXWARE_TO_GAIN(data >> 8 & 0xff); + /* fall thru, return set value */ case SOUND_MIXER_READ_MIC: - return(IOCTL_OUT(arg, - RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain >> 4 & 0xf) | - RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain & 0xf) << 8)); + return(IOCTL_OUT(arg, + RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain >> 4 & 0xf) | + RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain & 0xf) << 8)); case SOUND_MIXER_READ_SPEAKER: - { - int porta; - cli(); - sound_ym.rd_data_reg_sel = 14; - porta = sound_ym.rd_data_reg_sel; - sti(); - return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100)); - } + { + int porta; + cli(); + sound_ym.rd_data_reg_sel = 14; + porta = sound_ym.rd_data_reg_sel; + sti(); + return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100)); + } case SOUND_MIXER_WRITE_VOLUME: - IOCTL_IN(arg, data); - return(IOCTL_OUT(arg, sound_set_volume(data))); - case SOUND_MIXER_WRITE_SPEAKER: - { - int porta; IOCTL_IN(arg, data); - cli(); - sound_ym.rd_data_reg_sel = 14; - porta = (sound_ym.rd_data_reg_sel & ~0x40) | - (data < 50 ? 0x40 : 0); - sound_ym.wd_data = porta; - sti(); - return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100)); - } - } - break; + return(IOCTL_OUT(arg, sound_set_volume(data))); + case SOUND_MIXER_WRITE_SPEAKER: + { + int porta; + IOCTL_IN(arg, data); + cli(); + sound_ym.rd_data_reg_sel = 14; + porta = (sound_ym.rd_data_reg_sel & ~0x40) | + (data < 50 ? 0x40 : 0); + sound_ym.wd_data = porta; + sti(); + return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100)); + } + } + break; case DMASND_TT: - switch (cmd) { + switch (cmd) { case SOUND_MIXER_READ_DEVMASK: - return(IOCTL_OUT(arg, - SOUND_MASK_VOLUME | SOUND_MASK_TREBLE | SOUND_MASK_BASS | - (MACH_IS_TT ? SOUND_MASK_SPEAKER : 0))); + return(IOCTL_OUT(arg, + SOUND_MASK_VOLUME | SOUND_MASK_TREBLE | SOUND_MASK_BASS | + (MACH_IS_TT ? SOUND_MASK_SPEAKER : 0))); case SOUND_MIXER_READ_RECMASK: - return(IOCTL_OUT(arg, 0)); + return(IOCTL_OUT(arg, 0)); case SOUND_MIXER_READ_STEREODEVS: - return(IOCTL_OUT(arg, SOUND_MASK_VOLUME)); + return(IOCTL_OUT(arg, SOUND_MASK_VOLUME)); case SOUND_MIXER_READ_VOLUME: - return(IOCTL_OUT(arg, - VOLUME_DB_TO_VOXWARE(sound.volume_left) | - (VOLUME_DB_TO_VOXWARE(sound.volume_right) << 8))); + return(IOCTL_OUT(arg, + VOLUME_DB_TO_VOXWARE(sound.volume_left) | + (VOLUME_DB_TO_VOXWARE(sound.volume_right) << 8))); case SOUND_MIXER_READ_BASS: - return(IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(sound.bass))); + return(IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(sound.bass))); case SOUND_MIXER_READ_TREBLE: - return(IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(sound.treble))); + return(IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(sound.treble))); case SOUND_MIXER_READ_OGAIN: - return(IOCTL_OUT(arg, GAIN_DB_TO_VOXWARE(sound.gain))); + return(IOCTL_OUT(arg, GAIN_DB_TO_VOXWARE(sound.gain))); case SOUND_MIXER_READ_SPEAKER: - { - int porta; - if (MACH_IS_TT) { - cli(); - sound_ym.rd_data_reg_sel = 14; - porta = sound_ym.rd_data_reg_sel; - sti(); - return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100)); - } else - return(-EINVAL); - } + { + int porta; + if (MACH_IS_TT) { + cli(); + sound_ym.rd_data_reg_sel = 14; + porta = sound_ym.rd_data_reg_sel; + sti(); + return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100)); + } else + return(-EINVAL); + } case SOUND_MIXER_WRITE_VOLUME: - IOCTL_IN(arg, data); - return(IOCTL_OUT(arg, sound_set_volume(data))); + IOCTL_IN(arg, data); + return(IOCTL_OUT(arg, sound_set_volume(data))); case SOUND_MIXER_WRITE_BASS: - IOCTL_IN(arg, data); - return(IOCTL_OUT(arg, sound_set_bass(data))); + IOCTL_IN(arg, data); + return(IOCTL_OUT(arg, sound_set_bass(data))); case SOUND_MIXER_WRITE_TREBLE: - IOCTL_IN(arg, data); - return(IOCTL_OUT(arg, sound_set_treble(data))); + IOCTL_IN(arg, data); + return(IOCTL_OUT(arg, sound_set_treble(data))); case SOUND_MIXER_WRITE_OGAIN: - IOCTL_IN(arg, data); - return(IOCTL_OUT(arg, sound_set_gain(data))); - case SOUND_MIXER_WRITE_SPEAKER: - if (MACH_IS_TT) { - int porta; IOCTL_IN(arg, data); - cli(); - sound_ym.rd_data_reg_sel = 14; - porta = (sound_ym.rd_data_reg_sel & ~0x40) | - (data < 50 ? 0x40 : 0); - sound_ym.wd_data = porta; - sti(); - return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100)); - } else - return(-EINVAL); - } - break; + return(IOCTL_OUT(arg, sound_set_gain(data))); + case SOUND_MIXER_WRITE_SPEAKER: + if (MACH_IS_TT) { + int porta; + IOCTL_IN(arg, data); + cli(); + sound_ym.rd_data_reg_sel = 14; + porta = (sound_ym.rd_data_reg_sel & ~0x40) | + (data < 50 ? 0x40 : 0); + sound_ym.wd_data = porta; + sti(); + return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100)); + } else + return(-EINVAL); + } + break; #endif /* CONFIG_ATARI */ #ifdef CONFIG_AMIGA case DMASND_AMIGA: - switch (cmd) { + switch (cmd) { case SOUND_MIXER_READ_DEVMASK: - return(IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_TREBLE)); + return(IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_TREBLE)); case SOUND_MIXER_READ_RECMASK: - return(IOCTL_OUT(arg, 0)); + return(IOCTL_OUT(arg, 0)); case SOUND_MIXER_READ_STEREODEVS: - return(IOCTL_OUT(arg, SOUND_MASK_VOLUME)); + return(IOCTL_OUT(arg, SOUND_MASK_VOLUME)); case SOUND_MIXER_READ_VOLUME: - return(IOCTL_OUT(arg, - VOLUME_AMI_TO_VOXWARE(sound.volume_left) | - VOLUME_AMI_TO_VOXWARE(sound.volume_right) << 8)); + return(IOCTL_OUT(arg, + VOLUME_AMI_TO_VOXWARE(sound.volume_left) | + VOLUME_AMI_TO_VOXWARE(sound.volume_right) << 8)); case SOUND_MIXER_WRITE_VOLUME: - IOCTL_IN(arg, data); - return(IOCTL_OUT(arg, sound_set_volume(data))); + IOCTL_IN(arg, data); + return(IOCTL_OUT(arg, sound_set_volume(data))); case SOUND_MIXER_READ_TREBLE: - return(IOCTL_OUT(arg, sound.treble)); + return(IOCTL_OUT(arg, sound.treble)); case SOUND_MIXER_WRITE_TREBLE: - IOCTL_IN(arg, data); - return(IOCTL_OUT(arg, sound_set_treble(data))); - } - break; + IOCTL_IN(arg, data); + return(IOCTL_OUT(arg, sound_set_treble(data))); + } + break; #endif /* CONFIG_AMIGA */ - } - return(-EINVAL); +#ifdef CONFIG_PMAC + case DMASND_AWACS: + switch (cmd) { + case SOUND_MIXER_READ_DEVMASK: + data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER + | SOUND_MASK_LINE | SOUND_MASK_MIC + | SOUND_MASK_CD | SOUND_MASK_RECLEV + | SOUND_MASK_ALTPCM; + return IOCTL_OUT(arg, data); + case SOUND_MIXER_READ_RECMASK: + data = SOUND_MASK_LINE | SOUND_MASK_MIC + | SOUND_MASK_CD; + return IOCTL_OUT(arg, data); + case SOUND_MIXER_READ_RECSRC: + data = 0; + if (awacs_reg[0] & MASK_MUX_AUDIN) + data |= SOUND_MASK_LINE; + if (awacs_reg[0] & MASK_MUX_MIC) + data |= SOUND_MASK_MIC; + if (awacs_reg[0] & MASK_MUX_CD) + data |= SOUND_MASK_CD; + return IOCTL_OUT(arg, data); + case SOUND_MIXER_WRITE_RECSRC: + IOCTL_IN(arg, data); + data &= (SOUND_MASK_LINE + | SOUND_MASK_MIC | SOUND_MASK_CD); + awacs_reg[0] &= ~(MASK_MUX_CD | MASK_MUX_MIC + | MASK_MUX_AUDIN); + if (data & SOUND_MASK_LINE) + awacs_reg[0] |= MASK_MUX_AUDIN; + if (data & SOUND_MASK_MIC) + awacs_reg[0] |= MASK_MUX_MIC; + if (data & SOUND_MASK_CD) + awacs_reg[0] |= MASK_MUX_CD; + awacs_write(awacs_reg[0] | MASK_ADDR0); + return IOCTL_OUT(arg, data); + case SOUND_MIXER_READ_STEREODEVS: + data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER + | SOUND_MASK_RECLEV; + return IOCTL_OUT(arg, data); + case SOUND_MIXER_READ_CAPS: + return IOCTL_OUT(arg, 0); + case SOUND_MIXER_READ_VOLUME: + data = (awacs_reg[1] & MASK_AMUTE)? 0: + awacs_get_volume(awacs_reg[2], 6); + return IOCTL_OUT(arg, data); + case SOUND_MIXER_WRITE_VOLUME: + IOCTL_IN(arg, data); + return IOCTL_OUT(arg, sound_set_volume(data)); + case SOUND_MIXER_READ_SPEAKER: + data = (awacs_reg[1] & MASK_CMUTE)? 0: + awacs_get_volume(awacs_reg[4], 6); + return IOCTL_OUT(arg, data); + case SOUND_MIXER_WRITE_SPEAKER: + IOCTL_IN(arg, data); + data = awacs_volume_setter(data, 4, MASK_CMUTE, 6); + return IOCTL_OUT(arg, data); + case SOUND_MIXER_WRITE_ALTPCM: /* really bell volume */ + IOCTL_IN(arg, data); + beep_volume = data & 0xff; + /* fall through */ + case SOUND_MIXER_READ_ALTPCM: + return IOCTL_OUT(arg, beep_volume); + case SOUND_MIXER_WRITE_LINE: + IOCTL_IN(arg, data); + awacs_reg[0] &= ~MASK_MUX_AUDIN; + if ((data & 0xff) >= 50) + awacs_reg[0] |= MASK_MUX_AUDIN; + awacs_write(MASK_ADDR0 | awacs_reg[0]); + /* fall through */ + case SOUND_MIXER_READ_LINE: + data = (awacs_reg[0] & MASK_MUX_AUDIN)? 100: 0; + return IOCTL_OUT(arg, data); + case SOUND_MIXER_WRITE_MIC: + IOCTL_IN(arg, data); + data &= 0xff; + awacs_reg[0] &= ~(MASK_MUX_MIC | MASK_GAINLINE); + if (data >= 25) { + awacs_reg[0] |= MASK_MUX_MIC; + if (data >= 75) + awacs_reg[0] |= MASK_GAINLINE; + } + awacs_write(MASK_ADDR0 | awacs_reg[0]); + /* fall through */ + case SOUND_MIXER_READ_MIC: + data = (awacs_reg[0] & MASK_MUX_MIC)? + (awacs_reg[0] & MASK_GAINLINE? 100: 50): 0; + return IOCTL_OUT(arg, data); + case SOUND_MIXER_WRITE_CD: + IOCTL_IN(arg, data); + awacs_reg[0] &= ~MASK_MUX_CD; + if ((data & 0xff) >= 50) + awacs_reg[0] |= MASK_MUX_CD; + awacs_write(MASK_ADDR0 | awacs_reg[0]); + /* fall through */ + case SOUND_MIXER_READ_CD: + data = (awacs_reg[0] & MASK_MUX_CD)? 100: 0; + return IOCTL_OUT(arg, data); + case SOUND_MIXER_WRITE_RECLEV: + IOCTL_IN(arg, data); + data = awacs_volume_setter(data, 0, 0, 4); + return IOCTL_OUT(arg, data); + case SOUND_MIXER_READ_RECLEV: + data = awacs_get_volume(awacs_reg[0], 4); + return IOCTL_OUT(arg, data); + } + break; +#endif + } + + return(-EINVAL); } @@ -2715,62 +3790,88 @@ static void sq_init(int numBufs, int bufSize, char **buffers) { - sq.max_count = numBufs; - sq.block_size = bufSize; - sq.buffers = buffers; - - sq.front = sq.count = 0; - sq.rear = -1; - sq.write_queue = sq.open_queue = sq.sync_queue = 0; - sq.busy = 0; - sq.syncing = 0; +#ifdef CONFIG_PMAC + int i; + volatile struct dbdma_cmd *cp; +#endif /* CONFIG_PMAC */ + + sq.max_count = numBufs; + sq.max_active = numBufs; + sq.block_size = bufSize; + sq.buffers = buffers; + + sq.front = sq.count = 0; + sq.rear = -1; + sq.write_queue = sq.open_queue = sq.sync_queue = 0; + sq.busy = 0; + sq.syncing = 0; - sq.playing = 0; + sq.playing = 0; #ifdef CONFIG_ATARI - sq.ignore_int = 0; + sq.ignore_int = 0; #endif /* CONFIG_ATARI */ #ifdef CONFIG_AMIGA - sq.block_size_half = sq.block_size>>1; - sq.block_size_quarter = sq.block_size_half>>1; + sq.block_size_half = sq.block_size>>1; + sq.block_size_quarter = sq.block_size_half>>1; #endif /* CONFIG_AMIGA */ +#ifdef CONFIG_PMAC + cp = awacs_tx_cmds; + memset((void *) cp, 0, (numBufs + 1) * sizeof(struct dbdma_cmd)); + for (i = 0; i < numBufs; ++i, ++cp) { + st_le32(&cp->phy_addr, virt_to_bus(buffers[i])); + } + st_le16(&cp->command, DBDMA_NOP + BR_ALWAYS); + st_le32(&cp->cmd_dep, virt_to_bus(awacs_tx_cmds)); + out_le32(&awacs_txdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16); + out_le32(&awacs_txdma->cmdptr, virt_to_bus(awacs_tx_cmds)); +#endif /* CONFIG_PMAC */ +} + +static void +init_settings(void) +{ + /* whatever you like as startup mode for /dev/dsp, + * (/dev/audio hasn't got a startup mode). note that + * once changed a new open() will *not* restore these! + */ + sound.dsp.format = AFMT_U8; + sound.dsp.stereo = 0; + sound.dsp.size = 8; - sound_silence(); - - /* whatever you like as startup mode for /dev/dsp, - * (/dev/audio hasn't got a startup mode). note that - * once changed a new open() will *not* restore these! - */ - sound.dsp.format = AFMT_S8; - sound.dsp.stereo = 0; - sound.dsp.size = 8; - - /* set minimum rate possible without expanding */ - switch (sound.mach.type) { + /* set minimum rate possible without expanding */ + switch (sound.mach.type) { #ifdef CONFIG_ATARI case DMASND_TT: - sound.dsp.speed = 6258; - break; + sound.dsp.speed = 6258; + break; case DMASND_FALCON: - sound.dsp.speed = 8195; - break; + sound.dsp.speed = 8195; + break; #endif /* CONFIG_ATARI */ #ifdef CONFIG_AMIGA case DMASND_AMIGA: - sound.dsp.speed = 8000; - break; + sound.dsp.speed = 8000; + break; #endif /* CONFIG_AMIGA */ - } +#ifdef CONFIG_PMAC + case DMASND_AWACS: + sound.dsp.speed = 8000; + break; +#endif /* CONFIG_PMAC */ + } + + /* before the first open to /dev/dsp this wouldn't be set */ + sound.soft = sound.dsp; + sound.hard = sound.dsp; - /* before the first open to /dev/dsp this wouldn't be set */ - sound.soft = sound.dsp; - sound.hard = sound.dsp; + sound_silence(); } static void sq_play(void) { - (*sound.mach.play)(); + (*sound.mach.play)(); } @@ -2778,133 +3879,139 @@ static long sq_write(const char *src, unsigned long uLeft) { - long uWritten = 0; - u_char *dest; - long uUsed, bUsed, bLeft; - - /* ++TeSche: Is something like this necessary? - * Hey, that's an honest question! Or does any other part of the - * filesystem already checks this situation? I really don't know. - */ - if (uLeft == 0) - return(0); + long uWritten = 0; + u_char *dest; + long uUsed, bUsed, bLeft; + + /* ++TeSche: Is something like this necessary? + * Hey, that's an honest question! Or does any other part of the + * filesystem already checks this situation? I really don't know. + */ + if (uLeft == 0) + return(0); - /* The interrupt doesn't start to play the last, incomplete frame. - * Thus we can append to it without disabling the interrupts! (Note - * also that sq.rear isn't affected by the interrupt.) - */ - - if (sq.count > 0 && (bLeft = sq.block_size-sq.rear_size) > 0) { - dest = sq_block_address(sq.rear); - bUsed = sq.rear_size; - uUsed = sound_copy_translate(src, uLeft, dest, &bUsed, bLeft); - src += uUsed; - uWritten += uUsed; - uLeft -= uUsed; - sq.rear_size = bUsed; - } - - do { - while (sq.count == sq.max_count) { - sq_play(); - if (NON_BLOCKING(sq.open_mode)) - return(uWritten > 0 ? uWritten : -EAGAIN); - SLEEP(sq.write_queue, ONE_SECOND); - if (SIGNAL_RECEIVED) - return(uWritten > 0 ? uWritten : -EINTR); - } - - /* Here, we can avoid disabling the interrupt by first - * copying and translating the data, and then updating - * the sq variables. Until this is done, the interrupt - * won't see the new frame and we can work on it - * undisturbed. + /* The interrupt doesn't start to play the last, incomplete frame. + * Thus we can append to it without disabling the interrupts! (Note + * also that sq.rear isn't affected by the interrupt.) */ - dest = sq_block_address((sq.rear+1) % sq.max_count); - bUsed = 0; - bLeft = sq.block_size; - uUsed = sound_copy_translate(src, uLeft, dest, &bUsed, bLeft); - src += uUsed; - uWritten += uUsed; - uLeft -= uUsed; - if (bUsed) { - sq.rear = (sq.rear+1) % sq.max_count; - sq.rear_size = bUsed; - sq.count++; - } - } while (bUsed); /* uUsed may have been 0 */ + if (sq.count > 0 && (bLeft = sq.block_size-sq.rear_size) > 0) { + dest = sq_block_address(sq.rear); + bUsed = sq.rear_size; + uUsed = sound_copy_translate(src, uLeft, dest, &bUsed, bLeft); + if (uUsed <= 0) + return uUsed; + src += uUsed; + uWritten += uUsed; + uLeft -= uUsed; + sq.rear_size = bUsed; + } + + do { + while (sq.count == sq.max_active) { + sq_play(); + if (NON_BLOCKING(sq.open_mode)) + return(uWritten > 0 ? uWritten : -EAGAIN); + SLEEP(sq.write_queue, ONE_SECOND); + if (SIGNAL_RECEIVED) + return(uWritten > 0 ? uWritten : -EINTR); + } - sq_play(); + /* Here, we can avoid disabling the interrupt by first + * copying and translating the data, and then updating + * the sq variables. Until this is done, the interrupt + * won't see the new frame and we can work on it + * undisturbed. + */ + + dest = sq_block_address((sq.rear+1) % sq.max_count); + bUsed = 0; + bLeft = sq.block_size; + uUsed = sound_copy_translate(src, uLeft, dest, &bUsed, bLeft); + if (uUsed <= 0) + break; + src += uUsed; + uWritten += uUsed; + uLeft -= uUsed; + if (bUsed) { + sq.rear = (sq.rear+1) % sq.max_count; + sq.rear_size = bUsed; + sq.count++; + } + } while (bUsed); /* uUsed may have been 0 */ - return(uWritten); + sq_play(); + + return(uUsed < 0? uUsed: uWritten); } static int sq_open(int open_mode) { - if (sq.busy) { - if (NON_BLOCKING(open_mode)) - return(-EBUSY); - while (sq.busy) { - SLEEP(sq.open_queue, ONE_SECOND); - if (SIGNAL_RECEIVED) - return(-EINTR); - } - } - sq.open_mode = open_mode; - sq.busy = 1; + if (sq.busy) { + if (NON_BLOCKING(open_mode)) + return(-EBUSY); + while (sq.busy) { + SLEEP(sq.open_queue, ONE_SECOND); + if (SIGNAL_RECEIVED) + return(-EINTR); + } + } + sq_init(numBufs, bufSize << 10, sound_buffers); + sq.open_mode = open_mode; + sq.busy = 1; #ifdef CONFIG_ATARI - sq.ignore_int = 1; + sq.ignore_int = 1; #endif /* CONFIG_ATARI */ - return(0); + return(0); } static void sq_reset(void) { - sound_silence(); - sq.playing = 0; - sq.count = 0; - sq.front = (sq.rear+1) % sq.max_count; + sound_silence(); + sq.playing = 0; + sq.count = 0; + sq.front = (sq.rear+1) % sq.max_count; } static int sq_sync(void) { - int rc = 0; + int rc = 0; - sq.syncing = 1; - sq_play(); /* there may be an incomplete frame waiting */ + sq.syncing = 1; + sq_play(); /* there may be an incomplete frame waiting */ - while (sq.playing) { - SLEEP(sq.sync_queue, ONE_SECOND); - if (SIGNAL_RECEIVED) { - /* While waiting for audio output to drain, an interrupt occurred. - Stop audio output immediately and clear the queue. */ - sq_reset(); - rc = -EINTR; - break; + while (sq.playing) { + SLEEP(sq.sync_queue, ONE_SECOND); + if (SIGNAL_RECEIVED) { + /* While waiting for audio output to drain, an + * interrupt occurred. Stop audio output immediately + * and clear the queue. */ + sq_reset(); + rc = -EINTR; + break; + } } - } - sq.syncing = 0; - return(rc); + sq.syncing = 0; + return(rc); } static int sq_release(void) { - int rc = 0; - if (sq.busy) { - rc = sq_sync(); - sq.busy = 0; - WAKE_UP(sq.open_queue); - /* Wake up a process waiting for the queue being released. - Note: There may be several processes waiting for a call to open() - returning. */ - } - return(rc); + int rc = 0; + if (sq.busy) { + rc = sq_sync(); + sq.busy = 0; + WAKE_UP(sq.open_queue); + /* Wake up a process waiting for the queue being released. + * Note: There may be several processes waiting for a call + * to open() returning. */ + } + return(rc); } @@ -2916,7 +4023,7 @@ static void state_init(void) { - state.busy = 0; + state.busy = 0; } @@ -2924,118 +4031,125 @@ static int state_open(int open_mode) { - char *buffer = state.buf, *mach = ""; - int len = 0; + char *buffer = state.buf, *mach = ""; + int len = 0; - if (state.busy) - return(-EBUSY); + if (state.busy) + return(-EBUSY); - state.ptr = 0; - state.busy = 1; + state.ptr = 0; + state.busy = 1; - switch (sound.mach.type) { + switch (sound.mach.type) { #ifdef CONFIG_ATARI case DMASND_TT: case DMASND_FALCON: - mach = "Atari "; - break; + mach = "Atari "; + break; #endif /* CONFIG_ATARI */ #ifdef CONFIG_AMIGA case DMASND_AMIGA: - mach = "Amiga "; - break; + mach = "Amiga "; + break; #endif /* CONFIG_AMIGA */ - } - len += sprintf(buffer+len, "%sDMA sound driver:\n", mach); +#ifdef CONFIG_PMAC + case DMASND_AWACS: + mach = "PowerMac "; + break; +#endif /* CONFIG_PMAC */ + } + len += sprintf(buffer+len, "%sDMA sound driver:\n", mach); - len += sprintf(buffer+len, "\tsound.format = 0x%x", sound.soft.format); - switch (sound.soft.format) { + len += sprintf(buffer+len, "\tsound.format = 0x%x", sound.soft.format); + switch (sound.soft.format) { case AFMT_MU_LAW: - len += sprintf(buffer+len, " (mu-law)"); - break; + len += sprintf(buffer+len, " (mu-law)"); + break; case AFMT_A_LAW: - len += sprintf(buffer+len, " (A-law)"); - break; + len += sprintf(buffer+len, " (A-law)"); + break; case AFMT_U8: - len += sprintf(buffer+len, " (unsigned 8 bit)"); - break; + len += sprintf(buffer+len, " (unsigned 8 bit)"); + break; case AFMT_S8: - len += sprintf(buffer+len, " (signed 8 bit)"); - break; + len += sprintf(buffer+len, " (signed 8 bit)"); + break; case AFMT_S16_BE: - len += sprintf(buffer+len, " (signed 16 bit big)"); - break; + len += sprintf(buffer+len, " (signed 16 bit big)"); + break; case AFMT_U16_BE: - len += sprintf(buffer+len, " (unsigned 16 bit big)"); - break; + len += sprintf(buffer+len, " (unsigned 16 bit big)"); + break; case AFMT_S16_LE: - len += sprintf(buffer+len, " (signed 16 bit little)"); - break; + len += sprintf(buffer+len, " (signed 16 bit little)"); + break; case AFMT_U16_LE: - len += sprintf(buffer+len, " (unsigned 16 bit little)"); - break; - } - len += sprintf(buffer+len, "\n"); - len += sprintf(buffer+len, "\tsound.speed = %dHz (phys. %dHz)\n", - sound.soft.speed, sound.hard.speed); - len += sprintf(buffer+len, "\tsound.stereo = 0x%x (%s)\n", - sound.soft.stereo, sound.soft.stereo ? "stereo" : "mono"); - switch (sound.mach.type) { + len += sprintf(buffer+len, " (unsigned 16 bit little)"); + break; + } + len += sprintf(buffer+len, "\n"); + len += sprintf(buffer+len, "\tsound.speed = %dHz (phys. %dHz)\n", + sound.soft.speed, sound.hard.speed); + len += sprintf(buffer+len, "\tsound.stereo = 0x%x (%s)\n", + sound.soft.stereo, sound.soft.stereo ? "stereo" : "mono"); + switch (sound.mach.type) { #ifdef CONFIG_ATARI case DMASND_TT: - len += sprintf(buffer+len, "\tsound.volume_left = %ddB [-40...0]\n", - sound.volume_left); - len += sprintf(buffer+len, "\tsound.volume_right = %ddB [-40...0]\n", - sound.volume_right); - len += sprintf(buffer+len, "\tsound.bass = %ddB [-12...+12]\n", - sound.bass); - len += sprintf(buffer+len, "\tsound.treble = %ddB [-12...+12]\n", - sound.treble); - break; + len += sprintf(buffer+len, "\tsound.volume_left = %ddB [-40...0]\n", + sound.volume_left); + len += sprintf(buffer+len, "\tsound.volume_right = %ddB [-40...0]\n", + sound.volume_right); + len += sprintf(buffer+len, "\tsound.bass = %ddB [-12...+12]\n", + sound.bass); + len += sprintf(buffer+len, "\tsound.treble = %ddB [-12...+12]\n", + sound.treble); + break; case DMASND_FALCON: - len += sprintf(buffer+len, "\tsound.volume_left = %ddB [-22.5...0]\n", - sound.volume_left); - len += sprintf(buffer+len, "\tsound.volume_right = %ddB [-22.5...0]\n", - sound.volume_right); - break; + len += sprintf(buffer+len, "\tsound.volume_left = %ddB [-22.5...0]\n", + sound.volume_left); + len += sprintf(buffer+len, "\tsound.volume_right = %ddB [-22.5...0]\n", + sound.volume_right); + break; #endif /* CONFIG_ATARI */ #ifdef CONFIG_AMIGA case DMASND_AMIGA: - len += sprintf(buffer+len, "\tsound.volume_left = %d [0...64]\n", - sound.volume_left); - len += sprintf(buffer+len, "\tsound.volume_right = %d [0...64]\n", - sound.volume_right); - break; + len += sprintf(buffer+len, "\tsound.volume_left = %d [0...64]\n", + sound.volume_left); + len += sprintf(buffer+len, "\tsound.volume_right = %d [0...64]\n", + sound.volume_right); + break; #endif /* CONFIG_AMIGA */ - } - len += sprintf(buffer+len, "\tsq.block_size = %d sq.max_count = %d\n", - sq.block_size, sq.max_count); - len += sprintf(buffer+len, "\tsq.count = %d sq.rear_size = %d\n", sq.count, - sq.rear_size); - len += sprintf(buffer+len, "\tsq.playing = %d sq.syncing = %d\n", - sq.playing, sq.syncing); - state.len = len; - return(0); + } + len += sprintf(buffer+len, "\tsq.block_size = %d sq.max_count = %d" + " sq.max_active = %d\n", + sq.block_size, sq.max_count, sq.max_active); + len += sprintf(buffer+len, "\tsq.count = %d sq.rear_size = %d\n", sq.count, + sq.rear_size); + len += sprintf(buffer+len, "\tsq.playing = %d sq.syncing = %d\n", + sq.playing, sq.syncing); + state.len = len; + return(0); } static int state_release(void) { - state.busy = 0; - return(0); + state.busy = 0; + return(0); } static long state_read(char *dest, unsigned long count) { - int n = state.len-state.ptr; - if (n > count) - n = count; - if (n <= 0) - return(0); - copy_to_user(dest, &state.buf[state.ptr], n); - state.ptr += n; - return(n); + int n = state.len-state.ptr; + if (n > count) + n = count; + if (n <= 0) + return(0); + if (copy_to_user(dest, &state.buf[state.ptr], n)) + return -EFAULT; + state.ptr += n; + return(n); } @@ -3045,230 +4159,252 @@ static int sound_open(struct inode *inode, struct file *file) { - int dev = MINOR(inode->i_rdev) & 0x0f; - int rc = 0; + int dev = MINOR(inode->i_rdev) & 0x0f; + int rc = 0; - switch (dev) { + switch (dev) { case SND_DEV_STATUS: - rc = state_open(file->f_flags); - break; + rc = state_open(file->f_flags); + break; case SND_DEV_CTL: - rc = mixer_open(file->f_flags); - break; + rc = mixer_open(file->f_flags); + break; case SND_DEV_DSP: case SND_DEV_AUDIO: - rc = sq_open(file->f_flags); - if (rc == 0) { - sound.minDev = dev; - sound.soft = sound.dsp; - sound.hard = sound.dsp; - sound_init(); - if (dev == SND_DEV_AUDIO) { - sound_set_speed(8000); - sound_set_stereo(0); - sound_set_format(AFMT_MU_LAW); + rc = sq_open(file->f_flags); + if (rc == 0) { + sound.minDev = dev; + sound.soft = sound.dsp; + sound.hard = sound.dsp; + sound_init(); + if (dev == SND_DEV_AUDIO) { + sound_set_speed(8000); + sound_set_stereo(0); + sound_set_format(AFMT_MU_LAW); + } } - } - break; + break; default: - rc = -ENXIO; - } + rc = -ENXIO; + } #ifdef MODULE - if (rc >= 0) - MOD_INC_USE_COUNT; + if (rc >= 0) + MOD_INC_USE_COUNT; #endif - return(rc); + return(rc); } static int sound_fsync(struct file *filp, struct dentry *dentry) { - int dev = MINOR(dentry->d_inode->i_rdev) & 0x0f; + int dev = MINOR(dentry->d_inode->i_rdev) & 0x0f; - switch (dev) { + switch (dev) { case SND_DEV_STATUS: case SND_DEV_CTL: - return(0); + return(0); case SND_DEV_DSP: case SND_DEV_AUDIO: - return(sq_sync()); + return(sq_sync()); default: - return(unknown_minor_dev("sound_fsync", dev)); - } + return(unknown_minor_dev("sound_fsync", dev)); + } } static int sound_release(struct inode *inode, struct file *file) { - int dev = MINOR(inode->i_rdev); + int dev = MINOR(inode->i_rdev); - switch (dev & 0x0f) { + switch (dev & 0x0f) { case SND_DEV_STATUS: - state_release(); - break; + state_release(); + break; case SND_DEV_CTL: - mixer_release(); - break; + mixer_release(); + break; case SND_DEV_DSP: case SND_DEV_AUDIO: - sq_release(); - sound.soft = sound.dsp; - sound.hard = sound.dsp; - sound_silence(); - break; + sq_release(); + sound.soft = sound.dsp; + sound.hard = sound.dsp; + sound_silence(); + break; default: - return unknown_minor_dev("sound_release", dev); - } + return unknown_minor_dev("sound_release", dev); + } #ifdef MODULE - MOD_DEC_USE_COUNT; + MOD_DEC_USE_COUNT; #endif - return 0; + return 0; } static long long sound_lseek(struct file *file, long long offset, int orig) { - return -ESPIPE; + return -ESPIPE; } static ssize_t sound_read(struct file *file, char *buf, size_t count, loff_t *ppos) { - struct inode *inode = file->f_dentry->d_inode; - int dev = MINOR(inode->i_rdev); + struct inode *inode = file->f_dentry->d_inode; + int dev = MINOR(inode->i_rdev); - switch (dev & 0x0f) { + switch (dev & 0x0f) { case SND_DEV_STATUS: - return(state_read(buf, count)); + return(state_read(buf, count)); case SND_DEV_CTL: case SND_DEV_DSP: case SND_DEV_AUDIO: - return(-EPERM); + return(-EPERM); default: - return(unknown_minor_dev("sound_read", dev)); - } + return(unknown_minor_dev("sound_read", dev)); + } } static ssize_t sound_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { - struct inode *inode = file->f_dentry->d_inode; - int dev = MINOR(inode->i_rdev); + struct inode *inode = file->f_dentry->d_inode; + int dev = MINOR(inode->i_rdev); - switch (dev & 0x0f) { + switch (dev & 0x0f) { case SND_DEV_STATUS: case SND_DEV_CTL: - return(-EPERM); + return(-EPERM); case SND_DEV_DSP: case SND_DEV_AUDIO: - return(sq_write(buf, count)); + return(sq_write(buf, count)); default: - return(unknown_minor_dev("sound_write", dev)); - } + return(unknown_minor_dev("sound_write", dev)); + } } static int unknown_minor_dev(char *fname, int dev) { - /* printk("%s: Unknown minor device %d\n", fname, dev); */ - return(-ENXIO); + /* printk("%s: Unknown minor device %d\n", fname, dev); */ + return(-ENXIO); } static int sound_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg) { - int dev = MINOR(inode->i_rdev); - u_long fmt; - int data; + int dev = MINOR(inode->i_rdev); + u_long fmt; + int data; + int size, nbufs; - switch (dev & 0x0f) { + switch (dev & 0x0f) { case SND_DEV_STATUS: - return(-EPERM); + return(-EPERM); case SND_DEV_CTL: - return(mixer_ioctl(inode, file, cmd, arg)); + return(mixer_ioctl(inode, file, cmd, arg)); case SND_DEV_AUDIO: case SND_DEV_DSP: - switch (cmd) { + switch (cmd) { case SNDCTL_DSP_RESET: - sq_reset(); - return(0); + sq_reset(); + return(0); case SNDCTL_DSP_POST: case SNDCTL_DSP_SYNC: - return(sound_fsync(file, file->f_dentry)); + return(sound_fsync(file, file->f_dentry)); - /* ++TeSche: before changing any of these it's probably wise to - * wait until sound playing has settled down - */ + /* ++TeSche: before changing any of these it's + * probably wise to wait until sound playing has + * settled down. */ case SNDCTL_DSP_SPEED: - sound_fsync(file, file->f_dentry); - IOCTL_IN(arg, data); - return(IOCTL_OUT(arg, sound_set_speed(data))); + sound_fsync(file, file->f_dentry); + IOCTL_IN(arg, data); + return(IOCTL_OUT(arg, sound_set_speed(data))); case SNDCTL_DSP_STEREO: - sound_fsync(file, file->f_dentry); - IOCTL_IN(arg, data); - return(IOCTL_OUT(arg, sound_set_stereo(data))); + sound_fsync(file, file->f_dentry); + IOCTL_IN(arg, data); + return(IOCTL_OUT(arg, sound_set_stereo(data))); case SOUND_PCM_WRITE_CHANNELS: - sound_fsync(file, file->f_dentry); - IOCTL_IN(arg, data); - return(IOCTL_OUT(arg, sound_set_stereo(data-1)+1)); + sound_fsync(file, file->f_dentry); + IOCTL_IN(arg, data); + return(IOCTL_OUT(arg, sound_set_stereo(data-1)+1)); case SNDCTL_DSP_SETFMT: - sound_fsync(file, file->f_dentry); - IOCTL_IN(arg, data); - return(IOCTL_OUT(arg, sound_set_format(data))); + sound_fsync(file, file->f_dentry); + IOCTL_IN(arg, data); + return(IOCTL_OUT(arg, sound_set_format(data))); case SNDCTL_DSP_GETFMTS: - fmt = 0; - if (sound.trans) { - if (sound.trans->ct_ulaw) - fmt |= AFMT_MU_LAW; - if (sound.trans->ct_alaw) - fmt |= AFMT_A_LAW; - if (sound.trans->ct_s8) - fmt |= AFMT_S8; - if (sound.trans->ct_u8) - fmt |= AFMT_U8; - if (sound.trans->ct_s16be) - fmt |= AFMT_S16_BE; - if (sound.trans->ct_u16be) - fmt |= AFMT_U16_BE; - if (sound.trans->ct_s16le) - fmt |= AFMT_S16_LE; - if (sound.trans->ct_u16le) - fmt |= AFMT_U16_LE; - } - return(IOCTL_OUT(arg, fmt)); + fmt = 0; + if (sound.trans) { + if (sound.trans->ct_ulaw) + fmt |= AFMT_MU_LAW; + if (sound.trans->ct_alaw) + fmt |= AFMT_A_LAW; + if (sound.trans->ct_s8) + fmt |= AFMT_S8; + if (sound.trans->ct_u8) + fmt |= AFMT_U8; + if (sound.trans->ct_s16be) + fmt |= AFMT_S16_BE; + if (sound.trans->ct_u16be) + fmt |= AFMT_U16_BE; + if (sound.trans->ct_s16le) + fmt |= AFMT_S16_LE; + if (sound.trans->ct_u16le) + fmt |= AFMT_U16_LE; + } + return(IOCTL_OUT(arg, fmt)); case SNDCTL_DSP_GETBLKSIZE: - return(IOCTL_OUT(arg, 10240)); + size = sq.block_size + * sound.soft.size * (sound.soft.stereo + 1) + / (sound.hard.size * (sound.hard.stereo + 1)); + return(IOCTL_OUT(arg, size)); case SNDCTL_DSP_SUBDIVIDE: + break; case SNDCTL_DSP_SETFRAGMENT: - break; + if (sq.count || sq.playing || sq.syncing) + return -EINVAL; + IOCTL_IN(arg, size); + nbufs = size >> 16; + if (nbufs < 2 || nbufs > numBufs) + nbufs = numBufs; + size &= 0xffff; + if (size >= 8 && size <= 30) { + size = 1 << size; + size *= sound.hard.size * (sound.hard.stereo + 1); + size /= sound.soft.size * (sound.soft.stereo + 1); + if (size > (bufSize << 10)) + size = bufSize << 10; + } else + size = bufSize << 10; + sq_init(numBufs, size, sound_buffers); + sq.max_active = nbufs; + break; default: - return(mixer_ioctl(inode, file, cmd, arg)); - } - break; + return(mixer_ioctl(inode, file, cmd, arg)); + } + break; default: - return(unknown_minor_dev("sound_ioctl", dev)); - } - return(-EINVAL); + return(unknown_minor_dev("sound_ioctl", dev)); + } + return(-EINVAL); } static struct file_operations sound_fops = { - sound_lseek, - sound_read, - sound_write, - NULL, - NULL, /* select */ - sound_ioctl, - NULL, - sound_open, - sound_release, - sound_fsync + sound_lseek, + sound_read, + sound_write, + NULL, + NULL, /* select */ + sound_ioctl, + NULL, + sound_open, + sound_release, + sound_fsync }; @@ -3278,87 +4414,142 @@ void soundcard_init(void) { - int has_sound = 0; - int i; + int has_sound = 0; + int i; - switch (m68k_machtype) { +#ifdef __mc68000__ + switch (m68k_machtype) { #ifdef CONFIG_ATARI case MACH_ATARI: - if (ATARIHW_PRESENT(PCM_8BIT)) { - if (ATARIHW_PRESENT(CODEC)) - sound.mach = machFalcon; - else if (ATARIHW_PRESENT(MICROWIRE)) - sound.mach = machTT; - else - break; - if ((mfp.int_en_a & mfp.int_mk_a & 0x20) == 0) - has_sound = 1; - else - printk("DMA sound driver: Timer A interrupt already in use\n"); - } - break; + if (ATARIHW_PRESENT(PCM_8BIT)) { + if (ATARIHW_PRESENT(CODEC)) + sound.mach = machFalcon; + else if (ATARIHW_PRESENT(MICROWIRE)) + sound.mach = machTT; + else + break; + if ((mfp.int_en_a & mfp.int_mk_a & 0x20) == 0) + has_sound = 1; + else + printk("DMA sound driver: Timer A interrupt already in use\n"); + } + break; #endif /* CONFIG_ATARI */ #ifdef CONFIG_AMIGA case MACH_AMIGA: - if (AMIGAHW_PRESENT(AMI_AUDIO)) { - sound.mach = machAmiga; - has_sound = 1; - } - break; + if (AMIGAHW_PRESENT(AMI_AUDIO)) { + sound.mach = machAmiga; + has_sound = 1; + } + break; #endif /* CONFIG_AMIGA */ - } - if (!has_sound) - return; + } +#endif /* __mc68000__ */ - /* Set up sound queue, /dev/audio and /dev/dsp. */ - sound_buffers = kmalloc (numBufs * sizeof(char *), GFP_KERNEL); - if (!sound_buffers) { -out_of_memory: - printk("DMA sound driver: Not enough buffer memory, driver disabled!\n"); - return; - } - for (i = 0; i < numBufs; i++) { - sound_buffers[i] = sound.mach.dma_alloc (bufSize << 10, GFP_KERNEL); - if (!sound_buffers[i]) { - while (i--) - sound.mach.dma_free (sound_buffers[i], bufSize << 10); - kfree (sound_buffers); - sound_buffers = 0; - goto out_of_memory; - } - } +#ifdef CONFIG_PMAC + struct device_node *np; + + np = find_devices("awacs"); + if (np != NULL && np->n_addrs >= 3 && np->n_intrs >= 3) { + int vol; + sound.mach = machPMac; + has_sound = 1; + awacs = (volatile struct awacs_regs *) + ioremap(np->addrs[0].address, 0x80); + awacs_txdma = (volatile struct dbdma_regs *) + ioremap(np->addrs[1].address, 0x100); + awacs_rxdma = (volatile struct dbdma_regs *) + ioremap(np->addrs[2].address, 0x100); + awacs_irq = np->intrs[0].line; + awacs_tx_irq = np->intrs[1].line; + awacs_rx_irq = np->intrs[2].line; + awacs_tx_cmd_space = kmalloc((numBufs + 4) * sizeof(struct dbdma_cmd), + GFP_KERNEL); + if (awacs_tx_cmd_space == NULL) + goto out_of_memory; + awacs_tx_cmds = (volatile struct dbdma_cmd *) + DBDMA_ALIGN(awacs_tx_cmd_space); + awacs_reg[0] = MASK_MUX_CD; + awacs_reg[1] = MASK_LOOPTHRU | MASK_PAROUT; + /* get default volume from nvram */ + vol = (~nvram_read_byte(0x1308) & 7) << 1; + awacs_reg[2] = vol + (vol << 6); + awacs_reg[4] = vol + (vol << 6); + awacs_write(awacs_reg[0] + MASK_ADDR0); + awacs_write(awacs_reg[1] + MASK_ADDR1); + awacs_write(awacs_reg[2] + MASK_ADDR2); + awacs_write(awacs_reg[4] + MASK_ADDR4); + + /* Initialize beep stuff */ + beep_dbdma_cmd = awacs_tx_cmds + (numBufs + 1); + orig_mksound = kd_mksound; + kd_mksound = awacs_mksound; + beep_buf = (short *) kmalloc(BEEP_BUFLEN * 2, GFP_KERNEL); + if (beep_buf == NULL) + printk(KERN_WARNING "dmasound: no memory for " + "beep buffer\n"); +#ifdef CONFIG_PMAC_PBOOK + notifier_chain_register(&sleep_notifier_list, + &awacs_sleep_notifier); +#endif /* CONFIG_PMAC_PBOOK */ + } +#endif /* CONFIG_PMAC */ + + if (!has_sound) + return; + + /* Set up sound queue, /dev/audio and /dev/dsp. */ + sound_buffers = kmalloc (numBufs * sizeof(char *), GFP_KERNEL); + if (!sound_buffers) { + out_of_memory: + printk("DMA sound driver: Not enough buffer memory, driver disabled!\n"); + return; + } + for (i = 0; i < numBufs; i++) { + sound_buffers[i] = sound.mach.dma_alloc (bufSize << 10, GFP_KERNEL); + if (!sound_buffers[i]) { + while (i--) + sound.mach.dma_free (sound_buffers[i], bufSize << 10); + kfree (sound_buffers); + sound_buffers = 0; + goto out_of_memory; + } + } #ifndef MODULE - /* Register driver with the VFS. */ - register_chrdev(SOUND_MAJOR, "sound", &sound_fops); + /* Register driver with the VFS. */ + register_chrdev(SOUND_MAJOR, "sound", &sound_fops); #endif - sq_init(numBufs, bufSize << 10, sound_buffers); + sq_init(numBufs, bufSize << 10, sound_buffers); - /* Set up /dev/sndstat. */ - state_init(); + /* Set default settings. */ + init_settings(); - /* Set up /dev/mixer. */ - mixer_init(); + /* Set up /dev/sndstat. */ + state_init(); - if (!sound.mach.irqinit()) { - printk("DMA sound driver: Interrupt initialization failed\n"); - return; - } + /* Set up /dev/mixer. */ + mixer_init(); + + if (!sound.mach.irqinit()) { + printk("DMA sound driver: Interrupt initialization failed\n"); + return; + } #ifdef MODULE - irq_installed = 1; + irq_installed = 1; #endif - printk("DMA sound driver installed, using %d buffers of %dk.\n", numBufs, - bufSize); + printk("DMA sound driver installed, using %d buffers of %dk.\n", numBufs, + bufSize); - return; + return; } void sound_setup(char *str, int *ints) { - /* ++Martin: stub, could possibly be merged with soundcard.c et al later */ + /* ++Martin: stub, could possibly be merged with soundcard.c et al later */ } @@ -3366,30 +4557,30 @@ void dmasound_setup(char *str, int *ints) { - /* check the bootstrap parameter for "dmasound=" */ + /* check the bootstrap parameter for "dmasound=" */ - switch (ints[0]) { + switch (ints[0]) { case 3: - if ((ints[3] < 0) || (ints[3] > MAX_CATCH_RADIUS)) - printk("dmasound_setup: illegal catch radius, using default = %d\n", catchRadius); - else - catchRadius = ints[3]; - /* fall through */ + if ((ints[3] < 0) || (ints[3] > MAX_CATCH_RADIUS)) + printk("dmasound_setup: illegal catch radius, using default = %d\n", catchRadius); + else + catchRadius = ints[3]; + /* fall through */ case 2: - if (ints[1] < MIN_BUFFERS) - printk("dmasound_setup: illegal number of buffers, using default = %d\n", numBufs); - else - numBufs = ints[1]; - if (ints[2] < MIN_BUFSIZE || ints[2] > MAX_BUFSIZE) - printk("dmasound_setup: illegal buffer size, using default = %d\n", bufSize); - else - bufSize = ints[2]; - break; + if (ints[1] < MIN_BUFFERS) + printk("dmasound_setup: illegal number of buffers, using default = %d\n", numBufs); + else + numBufs = ints[1]; + if (ints[2] < MIN_BUFSIZE || ints[2] > MAX_BUFSIZE) + printk("dmasound_setup: illegal buffer size, using default = %d\n", bufSize); + else + bufSize = ints[2]; + break; case 0: - break; + break; default: - printk("dmasound_setup: illegal number of arguments\n"); - } + printk("dmasound_setup: illegal number of arguments\n"); + } } @@ -3399,48 +4590,48 @@ int init_module(void) { - int err, i = 0; - int ints[MAXARGS+1]; + int err, i = 0; + int ints[MAXARGS+1]; + + while (i < MAXARGS && dmasound[i]) + ints[i + 1] = dmasound[i++]; + ints[0] = i; - while (i < MAXARGS && dmasound[i]) - ints[i + 1] = dmasound[i++]; - ints[0] = i; - - if (i) - dmasound_setup("dmasound=", ints); - - err = register_chrdev(SOUND_MAJOR, "sound", &sound_fops); - if (err) { - printk("dmasound: driver already loaded/included in kernel\n"); - return err; - } - chrdev_registered = 1; - soundcard_init(); + if (i) + dmasound_setup("dmasound=", ints); + + err = register_chrdev(SOUND_MAJOR, "sound", &sound_fops); + if (err) { + printk("dmasound: driver already loaded/included in kernel\n"); + return err; + } + chrdev_registered = 1; + soundcard_init(); - return 0; + return 0; } void cleanup_module(void) { - int i; + int i; - if (MOD_IN_USE) - return; + if (MOD_IN_USE) + return; - if (chrdev_registered) - unregister_chrdev(SOUND_MAJOR, "sound"); + if (chrdev_registered) + unregister_chrdev(SOUND_MAJOR, "sound"); - if (irq_installed) { - sound_silence(); - sound.mach.irqcleanup(); - } + if (irq_installed) { + sound_silence(); + sound.mach.irqcleanup(); + } - if (sound_buffers) { - for (i = 0; i < numBufs; i++) - sound.mach.dma_free(sound_buffers[i], bufSize << 10); - kfree(sound_buffers); - } + if (sound_buffers) { + for (i = 0; i < numBufs; i++) + sound.mach.dma_free(sound_buffers[i], bufSize << 10); + kfree(sound_buffers); + } } #endif /* MODULE */ diff -u --recursive --new-file v2.1.105/linux/drivers/sound/gus_wave.c linux/drivers/sound/gus_wave.c --- v2.1.105/linux/drivers/sound/gus_wave.c Sun Jun 7 11:16:35 1998 +++ linux/drivers/sound/gus_wave.c Sat Jun 13 10:23:52 1998 @@ -3128,30 +3128,24 @@ if ((gus_mem_size > 0) & !gus_no_wave_dma) { - if ((dev = sound_alloc_audiodev()) != -1) + hw_config->slots[4] = -1; + if ((gus_devnum = sound_install_audiodrv(AUDIO_DRIVER_VERSION, + "Ultrasound", + &gus_audio_driver, + sizeof(struct audio_driver), + NEEDS_RESTART | + ((!iw_mode && dma2 != dma && dma2 != -1) ? + DMA_DUPLEX : 0), + AFMT_U8 | AFMT_S16_LE, + NULL, dma, dma2)) < 0) { - hw_config->slots[4] = dev; - if ((gus_devnum = sound_install_audiodrv(AUDIO_DRIVER_VERSION, - "Ultrasound", - &gus_audio_driver, - sizeof(struct audio_driver), - NEEDS_RESTART | - ((!iw_mode && dma2 != dma && dma2 != -1) ? - DMA_DUPLEX : 0), - AFMT_U8 | AFMT_S16_LE, - NULL, - dma, - dma2)) < 0) - { - return; - } + return; + } - audio_devs[gus_devnum]->min_fragment = 9; /* 512k */ - audio_devs[gus_devnum]->max_fragment = 11; /* 8k (must match size of bounce_buf */ - audio_devs[gus_devnum]->mixer_dev = -1; /* Next mixer# */ - audio_devs[gus_devnum]->flags |= DMA_HARDSTOP; - } else - printk(KERN_WARNING "GUS: Too many audio devices available\n"); + audio_devs[gus_devnum]->min_fragment = 9; /* 512k */ + audio_devs[gus_devnum]->max_fragment = 11; /* 8k (must match size of bounce_buf */ + audio_devs[gus_devnum]->mixer_dev = -1; /* Next mixer# */ + audio_devs[gus_devnum]->flags |= DMA_HARDSTOP; } /* diff -u --recursive --new-file v2.1.105/linux/drivers/sound/msnd.c linux/drivers/sound/msnd.c --- v2.1.105/linux/drivers/sound/msnd.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/sound/msnd.c Sat Jun 13 10:23:52 1998 @@ -0,0 +1,382 @@ +/********************************************************************* + * + * msnd.c - Driver Base + * + * Turtle Beach MultiSound Soundcard Driver for Linux + * + * Copyright (C) 1998 Andrew Veliath + * + * 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. + * + * $Id: msnd.c,v 1.2 1998/06/09 20:37:39 andrewtv Exp $ + * + ********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "msnd.h" + +#define LOGNAME "msnd" + +#define MSND_MAX_DEVS 4 + +static multisound_dev_t *devs[MSND_MAX_DEVS]; +static int num_devs; + +int msnd_register(multisound_dev_t *dev) +{ + int i; + + for (i = 0; i < MSND_MAX_DEVS; ++i) + if (devs[i] == NULL) + break; + + if (i == MSND_MAX_DEVS) + return -ENOMEM; + + devs[i] = dev; + ++num_devs; + + MOD_INC_USE_COUNT; + + return 0; +} + +void msnd_unregister(multisound_dev_t *dev) +{ + int i; + + for (i = 0; i < MSND_MAX_DEVS; ++i) + if (devs[i] == dev) + break; + + if (i == MSND_MAX_DEVS) { + printk(KERN_WARNING LOGNAME ": Unregistering unknown device\n"); + return; + } + + devs[i] = NULL; + --num_devs; + + MOD_DEC_USE_COUNT; +} + +int msnd_get_num_devs(void) +{ + return num_devs; +} + +multisound_dev_t *msnd_get_dev(int j) +{ + int i; + + for (i = 0; i < MSND_MAX_DEVS && j; ++i) + if (devs[i] != NULL) + --j; + + if (i == MSND_MAX_DEVS || j != 0) + return NULL; + + return devs[i]; +} + +void msnd_fifo_init(msnd_fifo *f) +{ + f->data = NULL; +} + +void msnd_fifo_free(msnd_fifo *f) +{ + if (f->data) { + vfree(f->data); + f->data = NULL; + } +} + +int msnd_fifo_alloc(msnd_fifo *f, size_t n) +{ + msnd_fifo_free(f); + f->data = (char *)vmalloc(n); + f->n = n; + f->tail = 0; + f->head = 0; + f->len = 0; + + if (!f->data) + return -ENOMEM; + + return 0; +} + +void msnd_fifo_make_empty(msnd_fifo *f) +{ + f->len = f->tail = f->head = 0; +} + +int msnd_fifo_write(msnd_fifo *f, const char *buf, size_t len, int user) +{ + int count = 0; + + if (f->len == f->n) + return 0; + + while ((count < len) && (f->len != f->n)) { + + int nwritten; + + if (f->head <= f->tail) { + nwritten = len - count; + if (nwritten > f->n - f->tail) + nwritten = f->n - f->tail; + } + else { + nwritten = f->head - f->tail; + if (nwritten > len - count) + nwritten = len - count; + } + + if (user) { + if (copy_from_user(f->data + f->tail, buf, nwritten)) + return -EFAULT; + } else + memcpy(f->data + f->tail, buf, nwritten); + + count += nwritten; + buf += nwritten; + f->len += nwritten; + f->tail += nwritten; + f->tail %= f->n; + } + + return count; +} + +int msnd_fifo_read(msnd_fifo *f, char *buf, size_t len, int user) +{ + int count = 0; + + if (f->len == 0) + return f->len; + + while ((count < len) && (f->len > 0)) { + + int nread; + + if (f->tail <= f->head) { + nread = len - count; + if (nread > f->n - f->head) + nread = f->n - f->head; + } + else { + nread = f->tail - f->head; + if (nread > len - count) + nread = len - count; + } + + if (user) { + if (copy_to_user(buf, f->data + f->head, nread)) + return -EFAULT; + } else + memcpy(buf, f->data + f->head, nread); + + count += nread; + buf += nread; + f->len -= nread; + f->head += nread; + f->head %= f->n; + } + + return count; +} + +int msnd_wait_TXDE(multisound_dev_t *dev) +{ + register unsigned int io = dev->io; + register int timeout = 5000; + + while(timeout-- > 0) + if (inb(io + HP_ISR) & HPISR_TXDE) + return 0; + + return -EIO; +} + +int msnd_wait_HC0(multisound_dev_t *dev) +{ + register unsigned int io = dev->io; + register int timeout = 25000; + + while(timeout-- > 0) + if (!(inb(io + HP_CVR) & HPCVR_HC)) + return 0; + + return -EIO; +} + +int msnd_send_dsp_cmd(multisound_dev_t *dev, BYTE cmd) +{ + unsigned long flags; + + spin_lock_irqsave(&dev->lock, flags); + if (msnd_wait_HC0(dev) == 0) { + + outb(cmd, dev->io + HP_CVR); + spin_unlock_irqrestore(&dev->lock, flags); + return 0; + } + spin_unlock_irqrestore(&dev->lock, flags); + + printk(KERN_WARNING LOGNAME ": Send DSP command timeout\n"); + + return -EIO; +} + +int msnd_send_word(multisound_dev_t *dev, unsigned char high, + unsigned char mid, unsigned char low) +{ + register unsigned int io = dev->io; + + if (msnd_wait_TXDE(dev) == 0) { + + outb(high, io + HP_TXH); + outb(mid, io + HP_TXM); + outb(low, io + HP_TXL); + return 0; + } + + printk(KERN_WARNING LOGNAME ": Send host word timeout\n"); + + return -EIO; +} + +int msnd_upload_host(multisound_dev_t *dev, char *bin, int len) +{ + int i; + + if (len % 3 != 0) { + + printk(KERN_WARNING LOGNAME ": Upload host data not multiple of 3!\n"); + return -EINVAL; + } + + for (i = 0; i < len; i += 3) + if (msnd_send_word(dev, bin[i], bin[i + 1], bin[i + 2]) != 0) + return -EIO; + + inb(dev->io + HP_RXL); + inb(dev->io + HP_CVR); + + return 0; +} + +int msnd_enable_irq(multisound_dev_t *dev) +{ + printk(KERN_INFO LOGNAME ": enable_irq: count %d\n", dev->irq_ref); + + if (dev->irq_ref++ != 0) + return 0; + + printk(KERN_DEBUG LOGNAME ": Enabling IRQ\n"); + + if (msnd_wait_TXDE(dev) == 0) { + + unsigned long flags; + + spin_lock_irqsave(&dev->lock, flags); + + outb(inb(dev->io + HP_ICR) | HPICR_TREQ, dev->io + HP_ICR); + + if (dev->type == msndClassic) + outb(dev->irqid, dev->io + HP_IRQM); + + outb(inb(dev->io + HP_ICR) & ~HPICR_TREQ, dev->io + HP_ICR); + outb(inb(dev->io + HP_ICR) | HPICR_RREQ, dev->io + HP_ICR); + + spin_unlock_irqrestore(&dev->lock, flags); + + return 0; + } + + return -EIO; +} + +int msnd_disable_irq(multisound_dev_t *dev) +{ + unsigned long flags; + + printk(KERN_DEBUG LOGNAME ": disable_irq: count %d\n", dev->irq_ref); + + if (--dev->irq_ref > 0) + return 0; + + if (dev->irq_ref < 0) + dev->irq_ref = 0; + + printk(KERN_DEBUG LOGNAME ": Disabling IRQ\n"); + + spin_lock_irqsave(&dev->lock, flags); + outb(inb(dev->io + HP_ICR) & ~HPICR_RREQ, dev->io + HP_ICR); + + if (dev->type == msndClassic) + outb(HPIRQ_NONE, dev->io + HP_IRQM); + + spin_unlock_irqrestore(&dev->lock, flags); + + return 0; +} + +EXPORT_SYMBOL(msnd_register); +EXPORT_SYMBOL(msnd_unregister); +EXPORT_SYMBOL(msnd_get_num_devs); +EXPORT_SYMBOL(msnd_get_dev); + +EXPORT_SYMBOL(msnd_fifo_init); +EXPORT_SYMBOL(msnd_fifo_free); +EXPORT_SYMBOL(msnd_fifo_alloc); +EXPORT_SYMBOL(msnd_fifo_make_empty); +EXPORT_SYMBOL(msnd_fifo_write); +EXPORT_SYMBOL(msnd_fifo_read); + +EXPORT_SYMBOL(msnd_wait_TXDE); +EXPORT_SYMBOL(msnd_wait_HC0); +EXPORT_SYMBOL(msnd_send_dsp_cmd); +EXPORT_SYMBOL(msnd_send_word); +EXPORT_SYMBOL(msnd_upload_host); + +EXPORT_SYMBOL(msnd_enable_irq); +EXPORT_SYMBOL(msnd_disable_irq); + +#ifdef MODULE +MODULE_AUTHOR ("Andrew Veliath "); +MODULE_DESCRIPTION ("Turtle Beach MultiSound Driver Base"); + +int init_module(void) +{ + return 0; +} + +void cleanup_module(void) +{ +} +#endif diff -u --recursive --new-file v2.1.105/linux/drivers/sound/msnd.h linux/drivers/sound/msnd.h --- v2.1.105/linux/drivers/sound/msnd.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/sound/msnd.h Sat Jun 13 10:23:52 1998 @@ -0,0 +1,259 @@ +/********************************************************************* + * + * msnd.h + * + * Turtle Beach MultiSound Soundcard Driver for Linux + * + * Some parts of this header file were derived from the Turtle Beach + * MultiSound Driver Development Kit. + * + * Copyright (C) 1998 Andrew Veliath + * Copyright (C) 1993 Turtle Beach Systems, Inc. + * + * 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. + * + * $Id: msnd.h,v 1.3 1998/06/09 20:39:34 andrewtv Exp $ + * + ********************************************************************/ +#ifndef __MSND_H +#define __MSND_H + +#define VERSION "0.6" + +#define DEFSAMPLERATE 44100 +#define DEFSAMPLESIZE 16 +#define DEFCHANNELS 2 + +#define DEFFIFOSIZE 64 + +#define SNDCARD_MSND 38 + +#define SRAM_BANK_SIZE 0x8000 +#define SRAM_CNTL_START 0x7F00 + +#define DSP_BASE_ADDR 0x4000 +#define DSP_BANK_BASE 0x4000 + +#define HP_ICR 0x00 +#define HP_CVR 0x01 +#define HP_ISR 0x02 +#define HP_IVR 0x03 +#define HP_NU 0x04 +#define HP_INFO 0x04 +#define HP_TXH 0x05 +#define HP_RXH 0x05 +#define HP_TXM 0x06 +#define HP_RXM 0x06 +#define HP_TXL 0x07 +#define HP_RXL 0x07 + +#define HP_ICR_DEF 0x00 +#define HP_CVR_DEF 0x12 +#define HP_ISR_DEF 0x06 +#define HP_IVR_DEF 0x0f +#define HP_NU_DEF 0x00 + +#define HP_IRQM 0x09 + +#define HPR_BLRC 0x08 +#define HPR_SPR1 0x09 +#define HPR_SPR2 0x0A +#define HPR_TCL0 0x0B +#define HPR_TCL1 0x0C +#define HPR_TCL2 0x0D +#define HPR_TCL3 0x0E +#define HPR_TCL4 0x0F + +#define HPICR_INIT 0x80 +#define HPICR_HM1 0x40 +#define HPICR_HM0 0x20 +#define HPICR_HF1 0x10 +#define HPICR_HF0 0x08 +#define HPICR_TREQ 0x02 +#define HPICR_RREQ 0x01 + +#define HPCVR_HC 0x80 + +#define HPISR_HREQ 0x80 +#define HPISR_DMA 0x40 +#define HPISR_HF3 0x10 +#define HPISR_HF2 0x08 +#define HPISR_TRDY 0x04 +#define HPISR_TXDE 0x02 +#define HPISR_RXDF 0x01 + +#define HPIO_290 0 +#define HPIO_260 1 +#define HPIO_250 2 +#define HPIO_240 3 +#define HPIO_230 4 +#define HPIO_220 5 +#define HPIO_210 6 +#define HPIO_3E0 7 + +#define HPMEM_NONE 0 +#define HPMEM_B000 1 +#define HPMEM_C800 2 +#define HPMEM_D000 3 +#define HPMEM_D400 4 +#define HPMEM_D800 5 +#define HPMEM_E000 6 +#define HPMEM_E800 7 + +#define HPIRQ_NONE 0 +#define HPIRQ_5 1 +#define HPIRQ_7 2 +#define HPIRQ_9 3 +#define HPIRQ_10 4 +#define HPIRQ_11 5 +#define HPIRQ_12 6 +#define HPIRQ_15 7 + +#define HIMT_PLAY_DONE 0x00 +#define HIMT_RECORD_DONE 0x01 +#define HIMT_MIDI_EOS 0x02 +#define HIMT_MIDI_OUT 0x03 + +#define HIMT_MIDI_IN_UCHAR 0x0E +#define HIMT_DSP 0x0F + +#define HIWORD(l) ((WORD)((((DWORD)(l)) >> 16) & 0xFFFF )) +#define LOWORD(l) ((WORD)(DWORD)(l)) +#define HIBYTE(w) ((BYTE)(((WORD)(w) >> 8 ) & 0xFF )) +#define LOBYTE(w) ((BYTE)(w)) +#define MAKELONG(low,hi) ((long)(((WORD)(low))|(((DWORD)((WORD)(hi)))<<16))) +#define MAKEWORD(low,hi) ((WORD)(((BYTE)(low))|(((WORD)((BYTE)(hi)))<<8))) + +#define PCTODSP_OFFSET(w) (USHORT)((w)/2) +#define PCTODSP_BASED(w) (USHORT)(((w)/2) + DSP_BASE_ADDR) + +#ifdef SLOWIO +# define outb outb_p +# define inb inb_p +#endif + +typedef unsigned char BYTE; +typedef unsigned short USHORT; +typedef unsigned short WORD; +typedef unsigned int DWORD; +typedef +struct DAQueueDataStruct * LPDAQD; + +#define GCC_PACKED __attribute__ ((packed)) + +struct JobQueueStruct { + WORD wStart; + WORD wSize; + WORD wHead; + WORD wTail; +} GCC_PACKED; + +struct DAQueueDataStruct { + WORD wStart; + WORD wSize; + WORD wFormat; + WORD wSampleSize; + WORD wChannels; + WORD wSampleRate; + WORD wIntMsg; + WORD wFlags; +} GCC_PACKED; + +typedef struct { + size_t n, len; + char *data; + int head, tail; +} msnd_fifo; + +typedef struct multisound_dev { + + char *name; + int dsp_minor, mixer_minor; + + /* Hardware resources */ + unsigned int io, numio; + int memid, irqid; + int irq, irq_ref; + unsigned char info; + char *base; + spinlock_t lock; + + /* MultiSound DDK variables */ + enum { msndClassic, msndPinnacle } type; + struct SMA0_CommonData *SMA; /* diff. structure for classic vs. pinnacle */ + struct DAQueueDataStruct *CurDAQD; + struct DAQueueDataStruct *CurDARQD; + WORD *pwDSPQData , *pwMIDQData , *pwMODQData; + struct JobQueueStruct *DAPQ , *DARQ , *MODQ , *MIDQ , *DSPQ; + + /* State variables */ + mode_t mode; + unsigned long flags; +#define F_BANKONE 0 +#define F_INTERRUPT 1 +#define F_WRITING 2 +#define F_WRITEBLOCK 3 +#define F_READING 4 +#define F_READBLOCK 5 +#define F_AUDIO_INUSE 6 +#define F_EXT_MIDI_INUSE 7 +#define F_INT_MIDI_INUSE 8 + struct wait_queue *writeblock, *readblock; + unsigned long recsrc; + int left_levels[16]; + int right_levels[16]; + int calibrate_signal; + int sample_size; + int sample_rate; + int channels; + void (*inc_ref)(void); + void (*dec_ref)(void); + + /* Digital audio FIFOs */ + int fifosize; + msnd_fifo DAPF, DARF; + int lastbank; + + /* MIDI in callback */ + void (*midi_in_interrupt)(struct multisound_dev *); + +} multisound_dev_t; + +#ifndef mdelay +# define mdelay(a) udelay((a) * 1000) +#endif + +int msnd_register(multisound_dev_t *dev); +void msnd_unregister(multisound_dev_t *dev); +int msnd_get_num_devs(void); +multisound_dev_t * msnd_get_dev(int i); + +void msnd_fifo_init(msnd_fifo *f); +void msnd_fifo_free(msnd_fifo *f); +int msnd_fifo_alloc(msnd_fifo *f, size_t n); +void msnd_fifo_make_empty(msnd_fifo *f); +int msnd_fifo_write(msnd_fifo *f, const char *buf, size_t len, int user); +int msnd_fifo_read(msnd_fifo *f, char *buf, size_t len, int user); + +int msnd_wait_TXDE(multisound_dev_t *dev); +int msnd_wait_HC0(multisound_dev_t *dev); +int msnd_send_dsp_cmd(multisound_dev_t *dev, BYTE cmd); +int msnd_send_word(multisound_dev_t *dev, unsigned char high, + unsigned char mid, unsigned char low); +int msnd_upload_host(multisound_dev_t *dev, char *bin, int len); +int msnd_enable_irq(multisound_dev_t *dev); +int msnd_disable_irq(multisound_dev_t *dev); + +#endif /* __MSND_H */ diff -u --recursive --new-file v2.1.105/linux/drivers/sound/msnd_classic.c linux/drivers/sound/msnd_classic.c --- v2.1.105/linux/drivers/sound/msnd_classic.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/sound/msnd_classic.c Sat Jun 13 10:23:52 1998 @@ -0,0 +1,1306 @@ +/********************************************************************* + * + * msnd_classic.c - Support for Turtle Beach Classic/Monterey/Tahiti + * + * Turtle Beach MultiSound Soundcard Driver for Linux + * + * Copyright (C) 1998 Andrew Veliath + * + * 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. + * + * $Id: msnd_classic.c,v 1.2 1998/06/09 20:37:39 andrewtv Exp $ + * + ********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include "sound_config.h" +#include "sound_firmware.h" +#define SLOWIO +#include "msnd.h" +#include "msnd_classic.h" + +#define LOGNAME "msnd_classic" +#define DEVNAME dev.name +#define MIXERMINOR dev.mixer_minor +#define DSPMINOR dev.dsp_minor + +multisound_dev_t dev; + +#ifndef HAVE_DSPCODEH +static char *dspini, *permini; +static int sizeof_dspini, sizeof_permini; +#endif + +static void reset_play_queue(void) +{ + int n; + LPDAQD lpDAQ; + + msnd_fifo_make_empty(&dev.DAPF); + dev.DAPQ->wHead = 0; + dev.DAPQ->wTail = PCTODSP_OFFSET(2 * DAPQ_STRUCT_SIZE); + dev.CurDAQD = (LPDAQD)(dev.base + 1 * DAPQ_DATA_BUFF); + outb(HPBLKSEL_0, dev.io + HP_BLKS); + memset_io(dev.base, 0, DAP_BUFF_SIZE * 3); + + for (n = 0, lpDAQ = dev.CurDAQD; n < 3; ++n, ++lpDAQ) { + + writew(PCTODSP_BASED((DWORD)(DAP_BUFF_SIZE * n)), &lpDAQ->wStart); + writew(DAP_BUFF_SIZE, &lpDAQ->wSize); + writew(1, &lpDAQ->wFormat); + writew(dev.sample_size, &lpDAQ->wSampleSize); + writew(dev.channels, &lpDAQ->wChannels); + writew(dev.sample_rate, &lpDAQ->wSampleRate); + writew(HIMT_PLAY_DONE * 0x100 + n, &lpDAQ->wIntMsg); + writew(n + 1, &lpDAQ->wFlags); + + } + + dev.lastbank = -1; +} + +static void reset_record_queue(void) +{ + int n; + LPDAQD lpDAQ; + + msnd_fifo_make_empty(&dev.DARF); + dev.DARQ->wHead = 0; + dev.DARQ->wTail = PCTODSP_OFFSET(2 * DARQ_STRUCT_SIZE); + dev.CurDARQD = (LPDAQD)(dev.base + 1 * DARQ_DATA_BUFF); + outb(HPBLKSEL_1, dev.io + HP_BLKS); + memset_io(dev.base, 0, DAR_BUFF_SIZE * 3); + outb(HPBLKSEL_0, dev.io + HP_BLKS); + + for (n = 0, lpDAQ = dev.CurDARQD; n < 3; ++n, ++lpDAQ) { + + writew(PCTODSP_BASED((DWORD)(DAR_BUFF_SIZE * n)) + 0x4000, &lpDAQ->wStart); + writew(DAR_BUFF_SIZE, &lpDAQ->wSize); + writew(1, &lpDAQ->wFormat); + writew(dev.sample_size, &lpDAQ->wSampleSize); + writew(dev.channels, &lpDAQ->wChannels); + writew(dev.sample_rate, &lpDAQ->wSampleRate); + writew(HIMT_RECORD_DONE * 0x100 + n, &lpDAQ->wIntMsg); + writew(n + 1, &lpDAQ->wFlags); + + } +} + +static void reset_queues(void) +{ + dev.DSPQ->wHead = dev.DSPQ->wTail = 0; + reset_play_queue(); + reset_record_queue(); +} + +static int dsp_ioctl(unsigned int cmd, unsigned long arg) +{ + int val, i, data; + LPDAQD lpDAQ, lpDARQ; + + lpDAQ = (LPDAQD)(dev.base + DAPQ_DATA_BUFF); + lpDARQ = (LPDAQD)(dev.base + DARQ_DATA_BUFF); + + switch (cmd) { + case SNDCTL_DSP_SUBDIVIDE: + case SNDCTL_DSP_SETFRAGMENT: + case SNDCTL_DSP_SETDUPLEX: + return 0; + + case SNDCTL_DSP_GETIPTR: + case SNDCTL_DSP_GETOPTR: + case SNDCTL_DSP_MAPINBUF: + case SNDCTL_DSP_MAPOUTBUF: + return -EINVAL; + + case SNDCTL_DSP_SYNC: + case SNDCTL_DSP_RESET: + + reset_play_queue(); + reset_record_queue(); + + return 0; + + case SNDCTL_DSP_GETBLKSIZE: + + if (put_user(dev.fifosize / 4, (int *)arg)) + return -EFAULT; + + return 0; + + case SNDCTL_DSP_NONBLOCK: + + dev.mode |= O_NONBLOCK; + + return 0; + + case SNDCTL_DSP_GETCAPS: + + val = DSP_CAP_DUPLEX | DSP_CAP_BATCH; + if (put_user(val, (int *)arg)) + return -EFAULT; + + return 0; + + case SNDCTL_DSP_SAMPLESIZE: + + if (get_user(val, (int *)arg)) + return -EFAULT; + + switch (val) { + case 16: + case 8: + data = val; + break; + default: + data = DEFSAMPLESIZE; + break; + } + + for (i = 0; i < 3; ++i, ++lpDAQ, ++lpDARQ) { + + lpDAQ->wSampleSize = data; + lpDARQ->wSampleSize = data; + } + + dev.sample_size = data; + + if (put_user(data, (int *)arg)) + return -EFAULT; + + return 0; + + case SNDCTL_DSP_SPEED: + + if (get_user(val, (int *)arg)) + return -EFAULT; + + if (val < 8000) + val = 8000; + + if (val > 48000) + val = 48000; + + data = val; + + for (i = 0; i < 3; ++i, ++lpDAQ, ++lpDARQ) { + + lpDAQ->wSampleRate = data; + lpDARQ->wSampleRate = data; + } + + dev.sample_rate = data; + + if (put_user(data, (int *)arg)) + return -EFAULT; + + return 0; + + case SNDCTL_DSP_CHANNELS: + + if (get_user(val, (int *)arg)) + return -EFAULT; + + switch (val) { + case 1: + case 2: + data = val; + break; + default: + val = data = 2; + break; + } + + for (i = 0; i < 3; ++i, ++lpDAQ, ++lpDARQ) { + + lpDAQ->wChannels = data; + lpDARQ->wChannels = data; + } + + dev.channels = data; + + if (put_user(val, (int *)arg)) + return -EFAULT; + + return 0; + + case SNDCTL_DSP_STEREO: + + if (get_user(val, (int *)arg)) + return -EFAULT; + + switch (val) { + case 0: + data = 1; + break; + default: + val = 1; + case 1: + data = 2; + break; + } + + for (i = 0; i < 3; ++i, ++lpDAQ, ++lpDARQ) { + + lpDAQ->wChannels = data; + lpDARQ->wChannels = data; + } + + dev.channels = data; + + if (put_user(val, (int *)arg)) + return -EFAULT; + + return 0; + } + + return -EINVAL; +} + +static int mixer_get(int d) +{ + if (d > 31) + return -EINVAL; + + switch (d) { + case SOUND_MIXER_VOLUME: + case SOUND_MIXER_SYNTH: + case SOUND_MIXER_PCM: + case SOUND_MIXER_LINE: + case SOUND_MIXER_MIC: + case SOUND_MIXER_IMIX: + case SOUND_MIXER_LINE1: + return (dev.left_levels[d] >> 8) * 100 / 0xff | + (((dev.right_levels[d] >> 8) * 100 / 0xff) << 8); + default: + return 0; + } +} + +#define update_vol(a,b,s) \ + writew(dev.left_levels[a] * readw(&dev.SMA->wCurrMastVolLeft) / 0xffff / s, \ + &dev.SMA->b##Left); \ + writew(dev.right_levels[a] * readw(&dev.SMA->wCurrMastVolRight) / 0xffff / s, \ + &dev.SMA->b##Right); + +static int mixer_set(int d, int value) +{ + int left = value & 0x000000ff; + int right = (value & 0x0000ff00) >> 8; + int bLeft, bRight; + int wLeft, wRight; + + if (d > 31) + return -EINVAL; + + bLeft = left * 0xff / 100; + wLeft = left * 0xffff / 100; + + bRight = right * 0xff / 100; + wRight = right * 0xffff / 100; + + dev.left_levels[d] = wLeft; + dev.right_levels[d] = wRight; + + switch (d) { + case SOUND_MIXER_VOLUME: /* master volume */ + writew(wLeft / 2, &dev.SMA->wCurrMastVolLeft); + writew(wRight / 2, &dev.SMA->wCurrMastVolRight); + break; + + /* pot controls */ + case SOUND_MIXER_LINE: /* aux pot control */ + writeb(bLeft, &dev.SMA->bInPotPosLeft); + writeb(bRight, &dev.SMA->bInPotPosRight); + if (msnd_send_word(&dev, 0, 0, HDEXAR_IN_SET_POTS) == 0) + msnd_send_dsp_cmd(&dev, HDEX_AUX_REQ); + break; + + case SOUND_MIXER_LINE1: /* line pot control */ + writeb(bLeft, &dev.SMA->bAuxPotPosLeft); + writeb(bRight, &dev.SMA->bAuxPotPosRight); + if (msnd_send_word(&dev, 0, 0, HDEXAR_AUX_SET_POTS) == 0) + msnd_send_dsp_cmd(&dev, HDEX_AUX_REQ); + break; + + /* digital controls */ + case SOUND_MIXER_SYNTH: /* synth vol (dsp mix) */ + case SOUND_MIXER_PCM: /* pcm vol (dsp mix) */ + case SOUND_MIXER_IMIX: /* input monitor (dsp mix) */ + break; + + default: + return 0; + } + + /* update digital controls for master volume */ + update_vol(SOUND_MIXER_PCM, wCurrPlayVol, 1); + update_vol(SOUND_MIXER_IMIX, wCurrInVol, 1); + + return mixer_get(d); +} + +static unsigned long set_recsrc(unsigned long recsrc) +{ +#ifdef HAVE_NORECSRC + if (recsrc == 0) + dev.recsrc = 0; + else +#endif + dev.recsrc ^= recsrc; + + return dev.recsrc; +} + +static int mixer_ioctl(unsigned int cmd, unsigned long arg) +{ + int val = 0; + + if (((cmd >> 8) & 0xff) == 'M') { + + if (_SIOC_DIR(cmd) & _SIOC_WRITE) { + + switch (cmd & 0xff) { + case SOUND_MIXER_RECSRC: + if (get_user(val, (int *)arg)) + return -EFAULT; + val = set_recsrc(val); + break; + + default: + if (get_user(val, (int *)arg)) + return -EFAULT; + val = mixer_set(cmd & 0xff, val); + break; + } + + return put_user(val, (int *)arg); + } + else { + switch (cmd & 0xff) { + case SOUND_MIXER_RECSRC: + val = dev.recsrc; + break; + + case SOUND_MIXER_DEVMASK: + case SOUND_MIXER_STEREODEVS: + val = SOUND_MASK_VOLUME | + SOUND_MASK_PCM | + SOUND_MASK_LINE | + SOUND_MASK_IMIX | + SOUND_MASK_LINE1; + break; + + case SOUND_MIXER_RECMASK: + val = 0; + break; + + case SOUND_MIXER_CAPS: + val = SOUND_CAP_EXCL_INPUT; + break; + + default: + if ((val = mixer_get(cmd & 0xff)) < 0) + return -EINVAL; + break; + } + } + + return put_user(val, (int *)arg); + } + + return -EINVAL; +} + +static int dev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + int minor = MINOR(inode->i_rdev); + + if (minor == DSPMINOR) + return dsp_ioctl(cmd, arg); + else if (minor == MIXERMINOR) + return mixer_ioctl(cmd, arg); + + return -EINVAL; +} + +static void dsp_halt(void) +{ + mdelay(1); + if (test_and_clear_bit(F_READING, &dev.flags)) { + + msnd_send_dsp_cmd(&dev, HDEX_RECORD_STOP); + msnd_disable_irq(&dev); + + } + mdelay(1); + if (test_and_clear_bit(F_WRITING, &dev.flags)) { + + msnd_send_dsp_cmd(&dev, HDEX_PLAY_STOP); + msnd_disable_irq(&dev); + + } + mdelay(1); + reset_queues(); +} + +static int dsp_open(struct file *file) +{ + dev.mode = file->f_mode; + set_bit(F_AUDIO_INUSE, &dev.flags); + reset_queues(); + return 0; +} + +static int dsp_close(void) +{ + dsp_halt(); + clear_bit(F_AUDIO_INUSE, &dev.flags); + return 0; +} + +static int dev_open(struct inode *inode, struct file *file) +{ + int minor = MINOR(inode->i_rdev); + int err = 0; + + if (minor == DSPMINOR) { + + if (test_bit(F_AUDIO_INUSE, &dev.flags)) + return -EBUSY; + + err = dsp_open(file); + } + else if (minor == MIXERMINOR) { + /* nothing */ + } else + err = -EINVAL; + + if (err >= 0) + MOD_INC_USE_COUNT; + + return err; +} + +static int dev_close(struct inode *inode, struct file *file) +{ + int minor = MINOR(inode->i_rdev); + int err = 0; + + if (minor == DSPMINOR) { + err = dsp_close(); + } + else if (minor == MIXERMINOR) { + /* nothing */ + } else + err = -EINVAL; + + if (err >= 0) + MOD_DEC_USE_COUNT; + + return err; +} + +static int DAPF_to_bank(int bank) +{ + return msnd_fifo_read(&dev.DAPF, dev.base + bank * DAP_BUFF_SIZE, DAP_BUFF_SIZE, 0); +} + +static int bank_to_DARF(int bank) +{ + return msnd_fifo_write(&dev.DARF, dev.base + bank * DAR_BUFF_SIZE, DAR_BUFF_SIZE, 0); +} + +static int dsp_read(char *buf, size_t len) +{ + int err = 0; + int count = len; + + while (count > 0) { + + int n; + + if ((n = msnd_fifo_read(&dev.DARF, buf, count, 1)) < 0) { + + printk(KERN_WARNING LOGNAME ": FIFO read error\n"); + return n; + } + + buf += n; + count -= n; + + if (!test_and_set_bit(F_READING, &dev.flags) && (dev.mode & FMODE_READ)) { + + reset_record_queue(); + msnd_enable_irq(&dev); + msnd_send_dsp_cmd(&dev, HDEX_RECORD_START); + + } + + if (dev.mode & O_NONBLOCK) + return count == len ? -EAGAIN : len - count; + + if (count > 0) { + + set_bit(F_READBLOCK, &dev.flags); + interruptible_sleep_on(&dev.readblock); + clear_bit(F_READBLOCK, &dev.flags); + + if (signal_pending(current)) + err = -EINTR; + + } + + if (err != 0) + return err; + } + + return len - count; +} + +static int dsp_write(const char *buf, size_t len) +{ + int err = 0; + int count = len; + + while (count > 0) { + + int n; + + if ((n = msnd_fifo_write(&dev.DAPF, buf, count, 1)) < 0) { + + printk(KERN_WARNING LOGNAME ": FIFO write error\n"); + return n; + } + + buf += n; + count -= n; + + if (!test_and_set_bit(F_WRITING, &dev.flags) && (dev.mode & FMODE_WRITE)) { + + reset_play_queue(); + msnd_enable_irq(&dev); + msnd_send_dsp_cmd(&dev, HDEX_PLAY_START); + + } + + if (dev.mode & O_NONBLOCK) + return count == len ? -EAGAIN : len - count; + + if (count > 0) { + + set_bit(F_WRITEBLOCK, &dev.flags); + interruptible_sleep_on(&dev.writeblock); + clear_bit(F_WRITEBLOCK, &dev.flags); + + if (signal_pending(current)) + err = -EINTR; + + } + + if (err != 0) + return err; + } + + return len - count; +} + +static ssize_t dev_read(struct file *file, char *buf, size_t count, loff_t *off) +{ + int minor = MINOR(file->f_dentry->d_inode->i_rdev); + + if (minor == DSPMINOR) { + + return dsp_read(buf, count); + + } else + return -EINVAL; +} + +static ssize_t dev_write(struct file *file, const char *buf, size_t count, loff_t *off) +{ + int minor = MINOR(file->f_dentry->d_inode->i_rdev); + + if (minor == DSPMINOR) { + + return dsp_write(buf, count); + + } else + return -EINVAL; +} + +static void eval_dsp_msg(WORD wMessage) +{ + switch (HIBYTE(wMessage)) { + case HIMT_PLAY_DONE: + + if (dev.lastbank == LOBYTE(wMessage)) + break; + + dev.lastbank = LOBYTE(wMessage); + + dev.CurDAQD->wSize = DAP_BUFF_SIZE; + + if ((dev.DAPQ->wTail += PCTODSP_OFFSET(DAPQ_STRUCT_SIZE)) > dev.DAPQ->wSize) + dev.DAPQ->wTail = 0; + + if (++dev.CurDAQD > (LPDAQD)(dev.base + DAPQ_DATA_BUFF + 2 * DAPQ_STRUCT_SIZE)) + dev.CurDAQD = (LPDAQD)(dev.base + DAPQ_DATA_BUFF); + + if (dev.lastbank < 3) { + + if (DAPF_to_bank(dev.lastbank) > 0) { + + mdelay(1); + msnd_send_dsp_cmd(&dev, HDEX_PLAY_START); + + } + else if (!test_bit(F_WRITEBLOCK, &dev.flags)) { + + memset_io(dev.base, 0, DAP_BUFF_SIZE * 3); + clear_bit(F_WRITING, &dev.flags); + msnd_disable_irq(&dev); + + } + } + + if (test_bit(F_WRITEBLOCK, &dev.flags)) + wake_up_interruptible(&dev.writeblock); + + break; + + case HIMT_RECORD_DONE: { + + WORD wTemp; + + wTemp = dev.DARQ->wTail + (DARQ_STRUCT_SIZE / 2); + + if (wTemp > dev.DARQ->wSize) + wTemp = 0; + + while (wTemp == dev.DARQ->wHead); + + dev.DARQ->wTail = wTemp; + + outb(HPBLKSEL_1, dev.io + HP_BLKS); + if (bank_to_DARF(LOBYTE(wMessage)) == 0 && + !test_bit(F_READBLOCK, &dev.flags)) { + + memset_io(dev.base, 0, DAR_BUFF_SIZE * 3); + clear_bit(F_READING, &dev.flags); + msnd_disable_irq(&dev); + + } + outb(HPBLKSEL_0, dev.io + HP_BLKS); + + if (test_bit(F_READBLOCK, &dev.flags)) + wake_up_interruptible(&dev.readblock); + + } break; + + case HIMT_DSP: + switch (LOBYTE(wMessage)) { + case HIDSP_INT_PLAY_UNDER: + printk(KERN_INFO LOGNAME ": Write underflow\n"); + reset_play_queue(); + break; + + case HIDSP_INT_RECORD_OVER: + printk(KERN_INFO LOGNAME ": Read overflow\n"); + reset_record_queue(); + break; + + default: + printk(KERN_INFO LOGNAME ": DSP message %u\n", LOBYTE(wMessage)); + break; + } + break; + + case HIMT_MIDI_IN_UCHAR: + if (dev.midi_in_interrupt) + (*dev.midi_in_interrupt)(&dev); + break; + + default: + break; + } +} + +static void intr(int irq, void *dev_id, struct pt_regs *regs) +{ + if (test_bit(F_INTERRUPT, &dev.flags) || + ((multisound_dev_t *)dev_id != &dev)) + return; + + set_bit(F_INTERRUPT, &dev.flags); + + if (test_bit(F_BANKONE, &dev.flags)) + outb(HPBLKSEL_0, dev.io + HP_BLKS); + + inb(dev.io + HP_RXL); + + while (dev.DSPQ->wTail != dev.DSPQ->wHead) { + + eval_dsp_msg(*(dev.pwDSPQData + dev.DSPQ->wHead)); + + if (++dev.DSPQ->wHead > dev.DSPQ->wSize) + dev.DSPQ->wHead = 0; + } + + if (test_bit(F_BANKONE, &dev.flags)) + outb(HPBLKSEL_1, dev.io + HP_BLKS); + + clear_bit(F_INTERRUPT, &dev.flags); +} + +static struct file_operations dev_fileops = { + NULL, + dev_read, + dev_write, + NULL, + NULL, + dev_ioctl, + NULL, + dev_open, + dev_close, +}; + +__initfunc(static int reset_dsp(void)) +{ + int timeout = 20000; + + outb(HPDSPRESET_ON, dev.io + HP_DSPR); + + mdelay(1); + + dev.info = inb(dev.io + HP_INFO); + + outb(HPDSPRESET_OFF, dev.io + HP_DSPR); + + mdelay(1); + + while (timeout-- > 0) { + + if (inb(dev.io + HP_CVR) == HP_CVR_DEF) + return 0; + + mdelay(1); + } + + printk(KERN_ERR LOGNAME ": Cannot reset DSP\n"); + + return -EIO; +} + +__initfunc(static int probe_multisound(void)) +{ + if (check_region(dev.io, dev.numio)) { + + printk(KERN_ERR LOGNAME ": I/O port conflict\n"); + return -ENODEV; + } + + request_region(dev.io, dev.numio, "probing"); + + if (reset_dsp() < 0) { + + release_region(dev.io, dev.numio); + return -ENODEV; + } + + printk(KERN_INFO LOGNAME ": DSP reset successful\n"); + + dev.name = "Classic/Tahiti/Monterey"; + + printk(KERN_INFO LOGNAME ": Turtle Beach %s, " + "I/O 0x%x-0x%x, IRQ %d, memory mapped to 0x%p-0x%p\n", + dev.name, + dev.io, dev.io + dev.numio - 1, + dev.irq, + dev.base, dev.base + 0x7fff); + + release_region(dev.io, dev.numio); + + return 0; +} + +__initfunc(static int init_sma(void)) +{ + int n; + LPDAQD lpDAQ; + + outb(dev.memid, dev.io + HP_MEMM); + + outb(HPBLKSEL_0, dev.io + HP_BLKS); + memset_io(dev.base, 0, 0x8000); + + outb(HPBLKSEL_1, dev.io + HP_BLKS); + memset_io(dev.base, 0, 0x8000); + + outb(HPBLKSEL_0, dev.io + HP_BLKS); + + dev.DAPQ = (struct JobQueueStruct *)(dev.base + DAPQ_OFFSET); + dev.DARQ = (struct JobQueueStruct *)(dev.base + DARQ_OFFSET); + dev.MODQ = (struct JobQueueStruct *)(dev.base + MODQ_OFFSET); + dev.MIDQ = (struct JobQueueStruct *)(dev.base + MIDQ_OFFSET); + dev.DSPQ = (struct JobQueueStruct *)(dev.base + DSPQ_OFFSET); + + dev.SMA = (struct SMA0_CommonData *)(dev.base + SMA_STRUCT_START); + + dev.CurDAQD = (LPDAQD)(dev.base + DAPQ_DATA_BUFF); + dev.CurDARQD = (LPDAQD)(dev.base + DARQ_DATA_BUFF); + + dev.sample_size = DEFSAMPLESIZE; + dev.sample_rate = DEFSAMPLERATE; + dev.channels = DEFCHANNELS; + + for (n = 0, lpDAQ = dev.CurDAQD; n < 3; ++n, ++lpDAQ) { + + writew(PCTODSP_BASED((DWORD)(DAP_BUFF_SIZE * n)), &lpDAQ->wStart); + writew(DAP_BUFF_SIZE, &lpDAQ->wSize); + writew(1, &lpDAQ->wFormat); + writew(dev.sample_size, &lpDAQ->wSampleSize); + writew(dev.channels, &lpDAQ->wChannels); + writew(dev.sample_rate, &lpDAQ->wSampleRate); + writew(HIMT_PLAY_DONE * 0x100 + n, &lpDAQ->wIntMsg); + writew(n + 1, &lpDAQ->wFlags); + } + + for (n = 0, lpDAQ = dev.CurDARQD; n < 3; ++n, ++lpDAQ) { + + writew(PCTODSP_BASED((DWORD)(DAR_BUFF_SIZE * n)) + 0x4000, &lpDAQ->wStart); + writew(DAR_BUFF_SIZE, &lpDAQ->wSize); + writew(1, &lpDAQ->wFormat); + writew(dev.sample_size, &lpDAQ->wSampleSize); + writew(dev.channels, &lpDAQ->wChannels); + writew(dev.sample_rate, &lpDAQ->wSampleRate); + writew(HIMT_RECORD_DONE * 0x100 + n, &lpDAQ->wIntMsg); + writew(n + 1, &lpDAQ->wFlags); + + } + + dev.pwDSPQData = (WORD *)(dev.base + DSPQ_DATA_BUFF); + dev.pwMODQData = (WORD *)(dev.base + MODQ_DATA_BUFF); + dev.pwMIDQData = (WORD *)(dev.base + MIDQ_DATA_BUFF); + + writew(PCTODSP_BASED(MIDQ_DATA_BUFF), &dev.MIDQ->wStart); + writew(PCTODSP_OFFSET(MIDQ_BUFF_SIZE) - 1, &dev.MIDQ->wSize); + writew(0, &dev.MIDQ->wHead); + writew(0, &dev.MIDQ->wTail); + + writew(PCTODSP_BASED(MODQ_DATA_BUFF), &dev.MODQ->wStart); + writew(PCTODSP_OFFSET(MODQ_BUFF_SIZE) - 1, &dev.MODQ->wSize); + writew(0, &dev.MODQ->wHead); + writew(0, &dev.MODQ->wTail); + + writew(PCTODSP_BASED(DAPQ_DATA_BUFF), &dev.DAPQ->wStart); + writew(PCTODSP_OFFSET(DAPQ_BUFF_SIZE) - 1, &dev.DAPQ->wSize); + writew(0, &dev.DAPQ->wHead); + writew(0, &dev.DAPQ->wTail); + + writew(PCTODSP_BASED(DARQ_DATA_BUFF), &dev.DARQ->wStart); + writew(PCTODSP_OFFSET(DARQ_BUFF_SIZE) - 1, &dev.DARQ->wSize); + writew(0, &dev.DARQ->wHead); + writew(0, &dev.DARQ->wTail); + + writew(PCTODSP_BASED(DSPQ_DATA_BUFF), &dev.DSPQ->wStart); + writew(PCTODSP_OFFSET(DSPQ_BUFF_SIZE) - 1, &dev.DSPQ->wSize); + writew(0, &dev.DSPQ->wHead); + writew(0, &dev.DSPQ->wTail); + + writew(0, &dev.SMA->wCurrPlayBytes); + writew(0, &dev.SMA->wCurrRecordBytes); + + writew(0, &dev.SMA->wCurrPlayVolLeft); + writew(0, &dev.SMA->wCurrPlayVolRight); + + writew(0, &dev.SMA->wCurrInVolLeft); + writew(0, &dev.SMA->wCurrInVolRight); + + writew(0, &dev.SMA->wCurrMastVolLeft); + writew(0, &dev.SMA->wCurrMastVolRight); + + writew(0x0000, &dev.SMA->wCurrDSPStatusFlags); + writew(0x0000, &dev.SMA->wCurrHostStatusFlags); + + writew(0x303, &dev.SMA->wCurrInputTagBits); + writew(0, &dev.SMA->wCurrLeftPeak); + writew(0, &dev.SMA->wCurrRightPeak); + + writeb(0, &dev.SMA->bInPotPosRight); + writeb(0, &dev.SMA->bInPotPosLeft); + + writeb(0, &dev.SMA->bAuxPotPosRight); + writeb(0, &dev.SMA->bAuxPotPosLeft); + + writew(dev.sample_rate, &dev.SMA->wCalFreqAtoD); + + return 0; +} + +__initfunc(static int calibrate_adc(WORD srate)) +{ + if (!dev.calibrate_signal) { + + printk(KERN_INFO LOGNAME ": ADC calibration to board ground "); + writew(readw(&dev.SMA->wCurrHostStatusFlags) + | 0x0001, &dev.SMA->wCurrHostStatusFlags); + } + else { + + printk(KERN_INFO LOGNAME ": ADC calibration to signal ground "); + writew(readw(&dev.SMA->wCurrHostStatusFlags) + & ~0x0001, &dev.SMA->wCurrHostStatusFlags); + } + + writew(srate, &dev.SMA->wCalFreqAtoD); + + if (msnd_send_word(&dev, 0, 0, HDEXAR_CAL_A_TO_D) == 0 && + msnd_send_dsp_cmd(&dev, HDEX_AUX_REQ) == 0) { + + current->state = TASK_INTERRUPTIBLE; + current->timeout = jiffies + HZ; + schedule(); + current->timeout = 0; + printk("successful\n"); + return 0; + } + + printk("failed\n"); + + return -EIO; +} + +__initfunc(static int upload_dsp_code(void)) +{ + outb(HPBLKSEL_0, dev.io + HP_BLKS); + +#ifdef HAVE_DSPCODEH + printk(KERN_INFO LOGNAME ": Using resident Turtle Beach DSP code\n"); +#else + printk(KERN_INFO LOGNAME ": Loading Turtle Beach DSP code\n"); + INITCODESIZE = mod_firmware_load(INITCODEFILE, &INITCODE); + if (!INITCODE) { + printk(KERN_ERR LOGNAME ": Error loading " INITCODEFILE); + return -EBUSY; + } + + PERMCODESIZE = mod_firmware_load(PERMCODEFILE, &PERMCODE); + if (!PERMCODE) { + printk(KERN_ERR LOGNAME ": Error loading " PERMCODEFILE); + vfree(INITCODE); + return -EBUSY; + } +#endif + memcpy_toio(dev.base, PERMCODE, PERMCODESIZE); + + if (msnd_upload_host(&dev, INITCODE, INITCODESIZE) < 0) { + + printk(KERN_WARNING LOGNAME ": Error uploading to DSP\n"); + return -ENODEV; + } + +#ifndef HAVE_DSPCODEH + vfree(INITCODE); + vfree(PERMCODE); +#endif + + return 0; +} + +__initfunc(static void reset_proteus(void)) +{ + outb(HPPRORESET_ON, dev.io + HP_PROR); + mdelay(TIME_PRO_RESET); + outb(HPPRORESET_OFF, dev.io + HP_PROR); + mdelay(TIME_PRO_RESET_DONE); +} + +__initfunc(static int initialize(void)) +{ + int err, timeout; + + outb(HPWAITSTATE_0, dev.io + HP_WAIT); + outb(HPBITMODE_16, dev.io + HP_BITM); + + reset_proteus(); + + if ((err = init_sma()) < 0) { + + printk(KERN_WARNING LOGNAME ": Cannot initialize SMA\n"); + return err; + } + + if ((err = reset_dsp()) < 0) + return err; + + if ((err = upload_dsp_code()) < 0) { + + printk(KERN_WARNING LOGNAME ": Cannot upload DSP code\n"); + return err; + + } else + printk(KERN_INFO LOGNAME ": DSP upload successful\n"); + + timeout = 2000; + + while (readw(dev.base)) { + + mdelay(1); + if (--timeout < 0) + return -EIO; + } + + return 0; +} + +__initfunc(static int attach_multisound(void)) +{ + int err; + + printk(KERN_DEBUG LOGNAME ": Intializing DSP\n"); + + if ((err = request_irq(dev.irq, intr, SA_SHIRQ, DEVNAME, &dev)) < 0) { + + printk(KERN_ERR LOGNAME ": Couldn't grab IRQ %d\n", dev.irq); + return err; + + } + + request_region(dev.io, dev.numio, DEVNAME); + + if ((err = initialize()) < 0) { + + printk(KERN_WARNING LOGNAME ": Initialization failure\n"); + release_region(dev.io, dev.numio); + free_irq(dev.irq, &dev); + return err; + + } + + if ((err = msnd_register(&dev)) < 0) { + + printk(KERN_ERR LOGNAME ": Unable to register MultiSound\n"); + release_region(dev.io, dev.numio); + free_irq(dev.irq, &dev); + return err; + } + + if ((DSPMINOR = register_sound_dsp(&dev_fileops)) < 0) { + + printk(KERN_ERR LOGNAME ": Unable to register DSP operations\n"); + msnd_unregister(&dev); + release_region(dev.io, dev.numio); + free_irq(dev.irq, &dev); + return DSPMINOR; + } + + if ((MIXERMINOR = register_sound_mixer(&dev_fileops)) < 0) { + + printk(KERN_ERR LOGNAME ": Unable to register mixer operations\n"); + unregister_sound_mixer(MIXERMINOR); + msnd_unregister(&dev); + release_region(dev.io, dev.numio); + free_irq(dev.irq, &dev); + return MIXERMINOR; + } + printk(KERN_INFO LOGNAME ": Using DSP minor %d, mixer minor %d\n", MIXERMINOR, DSPMINOR); + + calibrate_adc(dev.sample_rate); + set_recsrc(0); + + return 0; +} + +static void unload_multisound(void) +{ + release_region(dev.io, dev.numio); + free_irq(dev.irq, &dev); + unregister_sound_mixer(MIXERMINOR); + unregister_sound_dsp(DSPMINOR); + msnd_unregister(&dev); +} + +static void mod_inc_ref(void) +{ + MOD_INC_USE_COUNT; +} + +static void mod_dec_ref(void) +{ + MOD_DEC_USE_COUNT; +} + +#ifdef MODULE +MODULE_AUTHOR ("Andrew Veliath "); +MODULE_DESCRIPTION ("Turtle Beach " LONGNAME " Linux Driver"); +MODULE_PARM (io, "i"); +MODULE_PARM (irq, "i"); +MODULE_PARM (mem, "i"); +MODULE_PARM (major, "i"); +MODULE_PARM (fifosize, "i"); +MODULE_PARM (calibrate_signal, "i"); + +static int io __initdata = -1; +static int irq __initdata = -1; +static int mem __initdata = -1; +static int fifosize __initdata = DEFFIFOSIZE; +static int +calibrate_signal __initdata = 0; + +int init_module(void) +{ + int err; + + printk(KERN_INFO LOGNAME ": Turtle Beach " LONGNAME " Linux Driver Version " + VERSION ", Copyright (C) 1998 Andrew Veliath\n"); + + if (io == -1 || irq == -1 || mem == -1) { + + printk(KERN_WARNING LOGNAME ": io, irq and mem must be set\n"); + } + + if (io == -1 || + !(io == 0x290 || + io == 0x260 || + io == 0x250 || + io == 0x240 || + io == 0x230 || + io == 0x220 || + io == 0x210 || + io == 0x3e0)) { + + printk(KERN_ERR LOGNAME ": \"io\" - DSP I/O base must be set\n"); + return -EINVAL; + } + + if (irq == -1 || + !(irq == 5 || + irq == 7 || + irq == 9 || + irq == 10 || + irq == 11 || + irq == 12)) { + + printk(KERN_ERR LOGNAME ": \"irq\" - must be set to 5, 7, 9, 10, 11 or 12\n"); + return -EINVAL; + } + + if (mem == -1 || + !(mem == 0xb0000 || + mem == 0xc8000 || + mem == 0xd0000 || + mem == 0xd8000 || + mem == 0xe0000 || + mem == 0xe8000)) { + + printk(KERN_ERR LOGNAME ": \"mem\" - must be set to " + "0xb0000, 0xc8000, 0xd0000, 0xd8000, 0xe0000 or 0xe8000\n"); + return -EINVAL; + } + + switch (irq) { + case 5: dev.irqid = HPIRQ_5; break; + case 7: dev.irqid = HPIRQ_7; break; + case 9: dev.irqid = HPIRQ_9; break; + case 10: dev.irqid = HPIRQ_10; break; + case 11: dev.irqid = HPIRQ_11; break; + case 12: dev.irqid = HPIRQ_12; break; + } + + switch (mem) { + case 0xb0000: dev.memid = HPMEM_B000; break; + case 0xc8000: dev.memid = HPMEM_C800; break; + case 0xd0000: dev.memid = HPMEM_D000; break; + case 0xd8000: dev.memid = HPMEM_D800; break; + case 0xe0000: dev.memid = HPMEM_E000; break; + case 0xe8000: dev.memid = HPMEM_E800; break; + } + + if (fifosize < 16) + fifosize = 16; + + if (fifosize > 768) + fifosize = 768; + + dev.type = msndClassic; + dev.io = io; + dev.numio = DSP_NUMIO; + dev.irq = irq; + dev.base = phys_to_virt(mem); + dev.fifosize = fifosize * 1024; + dev.calibrate_signal = calibrate_signal ? 1 : 0; + dev.recsrc = 0; + dev.inc_ref = mod_inc_ref; + dev.dec_ref = mod_dec_ref; + + init_waitqueue(&dev.writeblock); + init_waitqueue(&dev.readblock); + msnd_fifo_init(&dev.DAPF); + msnd_fifo_init(&dev.DARF); + spin_lock_init(&dev.lock); + + printk(KERN_INFO LOGNAME ": Using %u byte digital audio FIFOs (x2)\n", dev.fifosize); + + if ((err = msnd_fifo_alloc(&dev.DAPF, dev.fifosize)) < 0) { + + printk(KERN_ERR LOGNAME ": Couldn't allocate write FIFO\n"); + return err; + } + + if ((err = msnd_fifo_alloc(&dev.DARF, dev.fifosize)) < 0) { + + printk(KERN_ERR LOGNAME ": Couldn't allocate read FIFO\n"); + msnd_fifo_free(&dev.DAPF); + return err; + } + + if ((err = probe_multisound()) < 0) { + + printk(KERN_ERR LOGNAME ": Probe failed\n"); + msnd_fifo_free(&dev.DAPF); + msnd_fifo_free(&dev.DARF); + return err; + + } + + if ((err = attach_multisound()) < 0) { + + printk(KERN_ERR LOGNAME ": Attach failed\n"); + msnd_fifo_free(&dev.DAPF); + msnd_fifo_free(&dev.DARF); + return err; + + } + + return 0; +} + +void cleanup_module(void) +{ + printk(KERN_INFO LOGNAME ": Unloading\n"); + + unload_multisound(); + + msnd_fifo_free(&dev.DAPF); + msnd_fifo_free(&dev.DARF); + +} +#endif diff -u --recursive --new-file v2.1.105/linux/drivers/sound/msnd_classic.h linux/drivers/sound/msnd_classic.h --- v2.1.105/linux/drivers/sound/msnd_classic.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/sound/msnd_classic.h Sat Jun 13 10:23:52 1998 @@ -0,0 +1,191 @@ +/********************************************************************* + * + * msnd_classic.h + * + * Turtle Beach MultiSound Soundcard Driver for Linux + * + * Some parts of this header file were derived from the Turtle Beach + * MultiSound Driver Development Kit. + * + * Copyright (C) 1998 Andrew Veliath + * Copyright (C) 1993 Turtle Beach Systems, Inc. + * + * 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. + * + * $Id: msnd_classic.h,v 1.3 1998/06/09 20:39:34 andrewtv Exp $ + * + ********************************************************************/ +#ifndef __MSND_CLASSIC_H +#define __MSND_CLASSIC_H + +#define DSP_NUMIO 0x10 + +#define HP_MEMM 0x08 + +#define HP_BITM 0x0E +#define HP_WAIT 0x0D +#define HP_DSPR 0x0A +#define HP_PROR 0x0B +#define HP_BLKS 0x0C + +#define HPPRORESET_OFF 0 +#define HPPRORESET_ON 1 + +#define HPDSPRESET_OFF 0 +#define HPDSPRESET_ON 1 + +#define HPBLKSEL_0 0 +#define HPBLKSEL_1 1 + +#define HPWAITSTATE_0 0 +#define HPWAITSTATE_1 1 + +#define HPBITMODE_16 0 +#define HPBITMODE_8 1 + +#define HIDSP_INT_PLAY_UNDER 0x00 +#define HIDSP_INT_RECORD_OVER 0x01 +#define HIDSP_INPUT_CLIPPING 0x02 +#define HIDSP_MIDI_IN_OVER 0x10 +#define HIDSP_MIDI_OVERRUN_ERR 0x13 + +#define HDEX_BASE 0x92 +#define HDEX_PLAY_START (0 + HDEX_BASE) +#define HDEX_PLAY_STOP (1 + HDEX_BASE) +#define HDEX_PLAY_PAUSE (2 + HDEX_BASE) +#define HDEX_PLAY_RESUME (3 + HDEX_BASE) +#define HDEX_RECORD_START (4 + HDEX_BASE) +#define HDEX_RECORD_STOP (5 + HDEX_BASE) +#define HDEX_MIDI_IN_START (6 + HDEX_BASE) +#define HDEX_MIDI_IN_STOP (7 + HDEX_BASE) +#define HDEX_MIDI_OUT_START (8 + HDEX_BASE) +#define HDEX_MIDI_OUT_STOP (9 + HDEX_BASE) +#define HDEX_AUX_REQ (10 + HDEX_BASE) + +#define HDEXAR_CLEAR_PEAKS 1 +#define HDEXAR_IN_SET_POTS 2 +#define HDEXAR_AUX_SET_POTS 3 +#define HDEXAR_CAL_A_TO_D 4 +#define HDEXAR_RD_EXT_DSP_BITS 5 + +#define TIME_PRO_RESET_DONE 0x028A +#define TIME_PRO_SYSEX 0x0040 +#define TIME_PRO_RESET 0x0032 + +#define AGND 0x01 +#define SIGNAL 0x02 + +#define EXT_DSP_BIT_DCAL 0x0001 +#define EXT_DSP_BIT_MIDI_CON 0x0002 + +#define BUFFSIZE 0x8000 +#define HOSTQ_SIZE 0x40 + +#define SRAM_CNTL_START 0x7F00 +#define SMA_STRUCT_START 0x7F40 + +#define DAP_BUFF_SIZE 0x2400 +#define DAR_BUFF_SIZE 0x2000 + +#define DAPQ_STRUCT_SIZE 0x10 +#define DARQ_STRUCT_SIZE 0x10 +#define DAPQ_BUFF_SIZE (3 * 0x10) +#define DARQ_BUFF_SIZE (3 * 0x10) +#define MODQ_BUFF_SIZE 0x400 +#define MIDQ_BUFF_SIZE 0x200 +#define DSPQ_BUFF_SIZE 0x40 + +#define DAPQ_DATA_BUFF 0x6C00 +#define DARQ_DATA_BUFF 0x6C30 +#define MODQ_DATA_BUFF 0x6C60 +#define MIDQ_DATA_BUFF 0x7060 +#define DSPQ_DATA_BUFF 0x7260 + +#define DAPQ_OFFSET SRAM_CNTL_START +#define DARQ_OFFSET (SRAM_CNTL_START + 0x08) +#define MODQ_OFFSET (SRAM_CNTL_START + 0x10) +#define MIDQ_OFFSET (SRAM_CNTL_START + 0x18) +#define DSPQ_OFFSET (SRAM_CNTL_START + 0x20) + +#define MOP_PROTEUS 0x10 +#define MOP_EXTOUT 0x32 +#define MOP_EXTTHRU 0x02 +#define MOP_OUTMASK 0x01 + +#define MIP_EXTIN 0x01 +#define MIP_PROTEUS 0x00 +#define MIP_INMASK 0x32 + +struct SMA0_CommonData { + WORD wCurrPlayBytes; + WORD wCurrRecordBytes; + WORD wCurrPlayVolLeft; + WORD wCurrPlayVolRight; + WORD wCurrInVolLeft; + WORD wCurrInVolRight; + WORD wUser_3; + WORD wUser_4; + DWORD dwUser_5; + DWORD dwUser_6; + WORD wUser_7; + WORD wReserved_A; + WORD wReserved_B; + WORD wReserved_C; + WORD wReserved_D; + WORD wReserved_E; + WORD wReserved_F; + WORD wReserved_G; + WORD wReserved_H; + WORD wCurrDSPStatusFlags; + WORD wCurrHostStatusFlags; + WORD wCurrInputTagBits; + WORD wCurrLeftPeak; + WORD wCurrRightPeak; + WORD wExtDSPbits; + BYTE bExtHostbits; + BYTE bBoardLevel; + BYTE bInPotPosRight; + BYTE bInPotPosLeft; + BYTE bAuxPotPosRight; + BYTE bAuxPotPosLeft; + WORD wCurrMastVolLeft; + WORD wCurrMastVolRight; + BYTE bUser_12; + BYTE bUser_13; + WORD wUser_14; + WORD wUser_15; + WORD wCalFreqAtoD; + WORD wUser_16; + WORD wUser_17; +} GCC_PACKED; + +#ifdef HAVE_DSPCODEH +# include "msndperm.c" +# include "msndinit.c" +# define PERMCODE msndperm +# define INITCODE msndinit +# define PERMCODESIZE sizeof(msndperm) +# define INITCODESIZE sizeof(msndinit) +#else +# define PERMCODEFILE CONFIG_MSNDCLAS_PERM_FILE +# define INITCODEFILE CONFIG_MSNDCLAS_INIT_FILE +# define PERMCODE dspini +# define INITCODE permini +# define PERMCODESIZE sizeof_dspini +# define INITCODESIZE sizeof_permini +#endif +#define LONGNAME "MultiSound (Classic/Monterey/Tahiti)" + +#endif /* __MSND_CLASSIC_H */ diff -u --recursive --new-file v2.1.105/linux/drivers/sound/msnd_pinnacle.c linux/drivers/sound/msnd_pinnacle.c --- v2.1.105/linux/drivers/sound/msnd_pinnacle.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/sound/msnd_pinnacle.c Sat Jun 13 10:23:52 1998 @@ -0,0 +1,1338 @@ +/********************************************************************* + * + * msnd_pinnacle.c - Support for Turtle Beach Pinnacle and Fiji + * + * Turtle Beach MultiSound Soundcard Driver for Linux + * + * Copyright (C) 1998 Andrew Veliath + * + * 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. + * + * $Id: msnd_pinnacle.c,v 1.2 1998/06/09 20:37:39 andrewtv Exp $ + * + ********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include "sound_config.h" +#include "sound_firmware.h" +#include "msnd.h" +#include "msnd_pinnacle.h" + +#define LOGNAME "msnd_pinnacle" +#define DEVNAME dev.name +#define MIXERMINOR dev.mixer_minor +#define DSPMINOR dev.dsp_minor + +multisound_dev_t dev; + +#ifndef HAVE_DSPCODEH +static char *dspini, *permini; +static int sizeof_dspini, sizeof_permini; +#endif + +static void reset_play_queue(void) +{ + int n; + LPDAQD lpDAQ; + + msnd_fifo_make_empty(&dev.DAPF); + dev.DAPQ->wHead = 0; + dev.DAPQ->wTail = PCTODSP_OFFSET(2 * DAPQ_STRUCT_SIZE); + dev.CurDAQD = (LPDAQD)(dev.base + 1 * DAPQ_DATA_BUFF); + outb(HPBLKSEL_0, dev.io + HP_BLKS); + memset_io(dev.base, 0, DAP_BUFF_SIZE * 3); + + for (n = 0, lpDAQ = dev.CurDAQD; n < 3; ++n, ++lpDAQ) { + + writew(PCTODSP_BASED((DWORD)(DAP_BUFF_SIZE * n)), &lpDAQ->wStart); + writew(DAP_BUFF_SIZE, &lpDAQ->wSize); + writew(1, &lpDAQ->wFormat); + writew(dev.sample_size, &lpDAQ->wSampleSize); + writew(dev.channels, &lpDAQ->wChannels); + writew(dev.sample_rate, &lpDAQ->wSampleRate); + writew(HIMT_PLAY_DONE * 0x100 + n, &lpDAQ->wIntMsg); + writew(n + 1, &lpDAQ->wFlags); + + } + + dev.lastbank = -1; +} + +static void reset_record_queue(void) +{ + int n; + LPDAQD lpDAQ; + + msnd_fifo_make_empty(&dev.DARF); + dev.DARQ->wHead = 0; + dev.DARQ->wTail = PCTODSP_OFFSET(2 * DARQ_STRUCT_SIZE); + dev.CurDARQD = (LPDAQD)(dev.base + 1 * DARQ_DATA_BUFF); + outb(HPBLKSEL_1, dev.io + HP_BLKS); + memset_io(dev.base, 0, DAR_BUFF_SIZE * 3); + outb(HPBLKSEL_0, dev.io + HP_BLKS); + + for (n = 0, lpDAQ = dev.CurDARQD; n < 3; ++n, ++lpDAQ) { + + writew(PCTODSP_BASED((DWORD)(DAR_BUFF_SIZE * n)) + 0x4000, &lpDAQ->wStart); + writew(DAR_BUFF_SIZE, &lpDAQ->wSize); + writew(1, &lpDAQ->wFormat); + writew(dev.sample_size, &lpDAQ->wSampleSize); + writew(dev.channels, &lpDAQ->wChannels); + writew(dev.sample_rate, &lpDAQ->wSampleRate); + writew(HIMT_RECORD_DONE * 0x100 + n, &lpDAQ->wIntMsg); + writew(n + 1, &lpDAQ->wFlags); + + } +} + +static void reset_queues(void) +{ + dev.DSPQ->wHead = dev.DSPQ->wTail = 0; + reset_play_queue(); + reset_record_queue(); +} + +static int dsp_ioctl(unsigned int cmd, unsigned long arg) +{ + int val, i, data; + LPDAQD lpDAQ, lpDARQ; + + lpDAQ = (LPDAQD)(dev.base + DAPQ_DATA_BUFF); + lpDARQ = (LPDAQD)(dev.base + DARQ_DATA_BUFF); + + switch (cmd) { + case SNDCTL_DSP_SUBDIVIDE: + case SNDCTL_DSP_SETFRAGMENT: + case SNDCTL_DSP_SETDUPLEX: + return 0; + + case SNDCTL_DSP_GETIPTR: + case SNDCTL_DSP_GETOPTR: + case SNDCTL_DSP_MAPINBUF: + case SNDCTL_DSP_MAPOUTBUF: + return -EINVAL; + + case SNDCTL_DSP_SYNC: + case SNDCTL_DSP_RESET: + + reset_play_queue(); + reset_record_queue(); + + return 0; + + case SNDCTL_DSP_GETBLKSIZE: + + if (put_user(dev.fifosize / 4, (int *)arg)) + return -EFAULT; + + return 0; + + case SNDCTL_DSP_NONBLOCK: + + dev.mode |= O_NONBLOCK; + + return 0; + + case SNDCTL_DSP_GETCAPS: + + val = DSP_CAP_DUPLEX | DSP_CAP_BATCH; + if (put_user(val, (int *)arg)) + return -EFAULT; + + return 0; + + case SNDCTL_DSP_SAMPLESIZE: + + if (get_user(val, (int *)arg)) + return -EFAULT; + + switch (val) { + case 16: + case 8: + data = val; + break; + default: + data = DEFSAMPLESIZE; + break; + } + + for (i = 0; i < 3; ++i, ++lpDAQ, ++lpDARQ) { + + lpDAQ->wSampleSize = data; + lpDARQ->wSampleSize = data; + } + + dev.sample_size = data; + + if (put_user(data, (int *)arg)) + return -EFAULT; + + return 0; + + case SNDCTL_DSP_SPEED: + + if (get_user(val, (int *)arg)) + return -EFAULT; + + if (val < 8000) + val = 8000; + + if (val > 48000) + val = 48000; + + data = val; + + for (i = 0; i < 3; ++i, ++lpDAQ, ++lpDARQ) { + + lpDAQ->wSampleRate = data; + lpDARQ->wSampleRate = data; + } + + dev.sample_rate = data; + + if (put_user(data, (int *)arg)) + return -EFAULT; + + return 0; + + case SNDCTL_DSP_CHANNELS: + + if (get_user(val, (int *)arg)) + return -EFAULT; + + switch (val) { + case 1: + case 2: + data = val; + break; + default: + val = data = 2; + break; + } + + for (i = 0; i < 3; ++i, ++lpDAQ, ++lpDARQ) { + + lpDAQ->wChannels = data; + lpDARQ->wChannels = data; + } + + dev.channels = data; + + if (put_user(val, (int *)arg)) + return -EFAULT; + + return 0; + + case SNDCTL_DSP_STEREO: + + if (get_user(val, (int *)arg)) + return -EFAULT; + + switch (val) { + case 0: + data = 1; + break; + default: + val = 1; + case 1: + data = 2; + break; + } + + for (i = 0; i < 3; ++i, ++lpDAQ, ++lpDARQ) { + + lpDAQ->wChannels = data; + lpDARQ->wChannels = data; + } + + dev.channels = data; + + if (put_user(val, (int *)arg)) + return -EFAULT; + + return 0; + } + + return -EINVAL; +} + +static int mixer_get(int d) +{ + if (d > 31) + return -EINVAL; + + switch (d) { + case SOUND_MIXER_VOLUME: + case SOUND_MIXER_SYNTH: + case SOUND_MIXER_PCM: + case SOUND_MIXER_LINE: + case SOUND_MIXER_MIC: + case SOUND_MIXER_IMIX: + case SOUND_MIXER_LINE1: + return (dev.left_levels[d] >> 8) * 100 / 0xff | + (((dev.right_levels[d] >> 8) * 100 / 0xff) << 8); + default: + return 0; + } +} + +#define update_vol(a,b,s) \ + writew(dev.left_levels[a] * readw(&dev.SMA->wCurrMastVolLeft) / 0xffff / s, \ + &dev.SMA->b##Left); \ + writew(dev.right_levels[a] * readw(&dev.SMA->wCurrMastVolRight) / 0xffff / s, \ + &dev.SMA->b##Right); + +static int mixer_set(int d, int value) +{ + int left = value & 0x000000ff; + int right = (value & 0x0000ff00) >> 8; + int bLeft, bRight; + int wLeft, wRight; + + if (d > 31) + return -EINVAL; + + bLeft = left * 0xff / 100; + wLeft = left * 0xffff / 100; + + bRight = right * 0xff / 100; + wRight = right * 0xffff / 100; + + dev.left_levels[d] = wLeft; + dev.right_levels[d] = wRight; + + switch (d) { + case SOUND_MIXER_VOLUME: /* master volume */ + writew(wLeft / 2, &dev.SMA->wCurrMastVolLeft); + writew(wRight / 2, &dev.SMA->wCurrMastVolRight); + break; + + /* pot controls */ + case SOUND_MIXER_LINE: /* aux pot control */ + writeb(bLeft, &dev.SMA->bInPotPosLeft); + writeb(bRight, &dev.SMA->bInPotPosRight); + if (msnd_send_word(&dev, 0, 0, HDEXAR_IN_SET_POTS) == 0) + msnd_send_dsp_cmd(&dev, HDEX_AUX_REQ); + break; + + case SOUND_MIXER_MIC: /* mic pot control */ + writeb(bLeft, &dev.SMA->bMicPotPosLeft); + writeb(bRight, &dev.SMA->bMicPotPosRight); + if (msnd_send_word(&dev, 0, 0, HDEXAR_MIC_SET_POTS) == 0) + msnd_send_dsp_cmd(&dev, HDEX_AUX_REQ); + break; + + case SOUND_MIXER_LINE1: /* line pot control */ + writeb(bLeft, &dev.SMA->bAuxPotPosLeft); + writeb(bRight, &dev.SMA->bAuxPotPosRight); + if (msnd_send_word(&dev, 0, 0, HDEXAR_AUX_SET_POTS) == 0) + msnd_send_dsp_cmd(&dev, HDEX_AUX_REQ); + break; + + /* digital controls */ + case SOUND_MIXER_SYNTH: /* synth vol (dsp mix) */ + case SOUND_MIXER_PCM: /* pcm vol (dsp mix) */ + case SOUND_MIXER_IMIX: /* input monitor (dsp mix) */ + break; + + default: + return 0; + } + + /* update digital controls for master volume */ + update_vol(SOUND_MIXER_PCM, wCurrPlayVol, 1); + update_vol(SOUND_MIXER_IMIX, wCurrInVol, 1); + update_vol(SOUND_MIXER_SYNTH, wCurrMHdrVol, 1); + + return mixer_get(d); +} + +static unsigned long set_recsrc(unsigned long recsrc) +{ +#ifdef HAVE_NORECSRC + if (recsrc == 0) + dev.recsrc = 0; + else +#endif + dev.recsrc ^= recsrc; + + if (dev.recsrc & SOUND_MASK_LINE) { + + if (msnd_send_word(&dev, 0, 0, HDEXAR_SET_ANA_IN) == 0) + msnd_send_dsp_cmd(&dev, HDEX_AUX_REQ); + + } + else if (dev.recsrc & SOUND_MASK_SYNTH) { + + if (msnd_send_word(&dev, 0, 0, HDEXAR_SET_SYNTH_IN) == 0) + msnd_send_dsp_cmd(&dev, HDEX_AUX_REQ); + + } + else { +#ifdef HAVE_NORECSRC + /* Select no input (?) */ + dev.recsrc = 0; +#else + dev.recsrc = SOUND_MASK_LINE; + if (msnd_send_word(&dev, 0, 0, HDEXAR_SET_ANA_IN) == 0) + msnd_send_dsp_cmd(&dev, HDEX_AUX_REQ); +#endif + } + + return dev.recsrc; +} + +static int mixer_ioctl(unsigned int cmd, unsigned long arg) +{ + int val = 0; + + if (((cmd >> 8) & 0xff) == 'M') { + + if (_SIOC_DIR(cmd) & _SIOC_WRITE) { + + switch (cmd & 0xff) { + case SOUND_MIXER_RECSRC: + if (get_user(val, (int *)arg)) + return -EFAULT; + val = set_recsrc(val); + break; + + default: + if (get_user(val, (int *)arg)) + return -EFAULT; + val = mixer_set(cmd & 0xff, val); + break; + } + + return put_user(val, (int *)arg); + } + else { + switch (cmd & 0xff) { + case SOUND_MIXER_RECSRC: + val = dev.recsrc; + break; + + case SOUND_MIXER_DEVMASK: + case SOUND_MIXER_STEREODEVS: + val = SOUND_MASK_VOLUME | + SOUND_MASK_SYNTH | + SOUND_MASK_PCM | + SOUND_MASK_LINE | + SOUND_MASK_IMIX | + SOUND_MASK_MIC; + break; + + case SOUND_MIXER_RECMASK: + val = SOUND_MASK_LINE | + SOUND_MASK_SYNTH; + break; + + case SOUND_MIXER_CAPS: + val = SOUND_CAP_EXCL_INPUT; + break; + + default: + if ((val = mixer_get(cmd & 0xff)) < 0) + return -EINVAL; + break; + } + } + + return put_user(val, (int *)arg); + } + + return -EINVAL; +} + +static int dev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + int minor = MINOR(inode->i_rdev); + + if (minor == DSPMINOR) + return dsp_ioctl(cmd, arg); + else if (minor == MIXERMINOR) + return mixer_ioctl(cmd, arg); + + return -EINVAL; +} + +static void dsp_halt(void) +{ + mdelay(1); + if (test_and_clear_bit(F_READING, &dev.flags)) { + + msnd_send_dsp_cmd(&dev, HDEX_RECORD_STOP); + msnd_disable_irq(&dev); + + } + mdelay(1); + if (test_and_clear_bit(F_WRITING, &dev.flags)) { + + msnd_send_dsp_cmd(&dev, HDEX_PLAY_STOP); + msnd_disable_irq(&dev); + + } + mdelay(1); + reset_queues(); +} + +static int dsp_open(struct file *file) +{ + dev.mode = file->f_mode; + set_bit(F_AUDIO_INUSE, &dev.flags); + reset_queues(); + return 0; +} + +static int dsp_close(void) +{ + dsp_halt(); + clear_bit(F_AUDIO_INUSE, &dev.flags); + return 0; +} + +static int dev_open(struct inode *inode, struct file *file) +{ + int minor = MINOR(inode->i_rdev); + int err = 0; + + if (minor == DSPMINOR) { + + if (test_bit(F_AUDIO_INUSE, &dev.flags)) + return -EBUSY; + + err = dsp_open(file); + } + else if (minor == MIXERMINOR) { + /* nothing */ + } else + err = -EINVAL; + + if (err >= 0) + MOD_INC_USE_COUNT; + + return err; +} + +static int dev_close(struct inode *inode, struct file *file) +{ + int minor = MINOR(inode->i_rdev); + int err = 0; + + if (minor == DSPMINOR) { + err = dsp_close(); + } + else if (minor == MIXERMINOR) { + /* nothing */ + } else + err = -EINVAL; + + if (err >= 0) + MOD_DEC_USE_COUNT; + + return err; +} + +static int DAPF_to_bank(int bank) +{ + return msnd_fifo_read(&dev.DAPF, dev.base + bank * DAP_BUFF_SIZE, DAP_BUFF_SIZE, 0); +} + +static int bank_to_DARF(int bank) +{ + return msnd_fifo_write(&dev.DARF, dev.base + bank * DAR_BUFF_SIZE, DAR_BUFF_SIZE, 0); +} + +static int dsp_read(char *buf, size_t len) +{ + int err = 0; + int count = len; + + while (count > 0) { + + int n; + + if ((n = msnd_fifo_read(&dev.DARF, buf, count, 1)) < 0) { + + printk(KERN_WARNING LOGNAME ": FIFO read error\n"); + return n; + } + + buf += n; + count -= n; + + if (!test_and_set_bit(F_READING, &dev.flags) && (dev.mode & FMODE_READ)) { + + reset_record_queue(); + msnd_enable_irq(&dev); + msnd_send_dsp_cmd(&dev, HDEX_RECORD_START); + + } + + if (dev.mode & O_NONBLOCK) + return count == len ? -EAGAIN : len - count; + + if (count > 0) { + + set_bit(F_READBLOCK, &dev.flags); + interruptible_sleep_on(&dev.readblock); + clear_bit(F_READBLOCK, &dev.flags); + + if (signal_pending(current)) + err = -EINTR; + + } + + if (err != 0) + return err; + } + + return len - count; +} + +static int dsp_write(const char *buf, size_t len) +{ + int err = 0; + int count = len; + + while (count > 0) { + + int n; + + if ((n = msnd_fifo_write(&dev.DAPF, buf, count, 1)) < 0) { + + printk(KERN_WARNING LOGNAME ": FIFO write error\n"); + return n; + } + + buf += n; + count -= n; + + if (!test_and_set_bit(F_WRITING, &dev.flags) && (dev.mode & FMODE_WRITE)) { + + reset_play_queue(); + msnd_enable_irq(&dev); + msnd_send_dsp_cmd(&dev, HDEX_PLAY_START); + + } + + if (dev.mode & O_NONBLOCK) + return count == len ? -EAGAIN : len - count; + + if (count > 0) { + + set_bit(F_WRITEBLOCK, &dev.flags); + interruptible_sleep_on(&dev.writeblock); + clear_bit(F_WRITEBLOCK, &dev.flags); + + if (signal_pending(current)) + err = -EINTR; + + } + + if (err != 0) + return err; + } + + return len - count; +} + +static ssize_t dev_read(struct file *file, char *buf, size_t count, loff_t *off) +{ + int minor = MINOR(file->f_dentry->d_inode->i_rdev); + + if (minor == DSPMINOR) { + + return dsp_read(buf, count); + + } else + return -EINVAL; +} + +static ssize_t dev_write(struct file *file, const char *buf, size_t count, loff_t *off) +{ + int minor = MINOR(file->f_dentry->d_inode->i_rdev); + + if (minor == DSPMINOR) { + + return dsp_write(buf, count); + + } else + return -EINVAL; +} + +static void eval_dsp_msg(WORD wMessage) +{ + switch (HIBYTE(wMessage)) { + case HIMT_PLAY_DONE: + + if (dev.lastbank == LOBYTE(wMessage)) + break; + + dev.lastbank = LOBYTE(wMessage); + + dev.CurDAQD->wSize = DAP_BUFF_SIZE; + + if ((dev.DAPQ->wTail += PCTODSP_OFFSET(DAPQ_STRUCT_SIZE)) > dev.DAPQ->wSize) + dev.DAPQ->wTail = 0; + + if (++dev.CurDAQD > (LPDAQD)(dev.base + DAPQ_DATA_BUFF + 2 * DAPQ_STRUCT_SIZE)) + dev.CurDAQD = (LPDAQD)(dev.base + DAPQ_DATA_BUFF); + + if (dev.lastbank < 3) { + + if (DAPF_to_bank(dev.lastbank) > 0) { + + mdelay(1); + msnd_send_dsp_cmd(&dev, HDEX_PLAY_START); + + } + else if (!test_bit(F_WRITEBLOCK, &dev.flags)) { + + memset_io(dev.base, 0, DAP_BUFF_SIZE * 3); + clear_bit(F_WRITING, &dev.flags); + msnd_disable_irq(&dev); + + } + } + + if (test_bit(F_WRITEBLOCK, &dev.flags)) + wake_up_interruptible(&dev.writeblock); + + break; + + case HIMT_RECORD_DONE: { + + WORD wTemp; + + wTemp = dev.DARQ->wTail + (DARQ_STRUCT_SIZE / 2); + + if (wTemp > dev.DARQ->wSize) + wTemp = 0; + + while (wTemp == dev.DARQ->wHead); + + dev.DARQ->wTail = wTemp; + + outb(HPBLKSEL_1, dev.io + HP_BLKS); + if (bank_to_DARF(LOBYTE(wMessage)) == 0 && + !test_bit(F_READBLOCK, &dev.flags)) { + + memset_io(dev.base, 0, DAR_BUFF_SIZE * 3); + clear_bit(F_READING, &dev.flags); + msnd_disable_irq(&dev); + + } + outb(HPBLKSEL_0, dev.io + HP_BLKS); + + if (test_bit(F_READBLOCK, &dev.flags)) + wake_up_interruptible(&dev.readblock); + + } break; + + case HIMT_DSP: + switch (LOBYTE(wMessage)) { + case HIDSP_PLAY_UNDER: + case HIDSP_INT_PLAY_UNDER: + printk(KERN_INFO LOGNAME ": Write underflow\n"); + reset_play_queue(); + break; + + case HIDSP_INT_RECORD_OVER: + printk(KERN_INFO LOGNAME ": Read overflow\n"); + reset_record_queue(); + break; + + default: + printk(KERN_INFO LOGNAME ": DSP message %u\n", LOBYTE(wMessage)); + break; + } + break; + + case HIMT_MIDI_IN_UCHAR: + if (dev.midi_in_interrupt) + (*dev.midi_in_interrupt)(&dev); + break; + + default: + break; + } +} + +static void intr(int irq, void *dev_id, struct pt_regs *regs) +{ + if (test_bit(F_INTERRUPT, &dev.flags) || + ((multisound_dev_t *)dev_id != &dev)) + return; + + set_bit(F_INTERRUPT, &dev.flags); + + if (test_bit(F_BANKONE, &dev.flags)) + outb(HPBLKSEL_0, dev.io + HP_BLKS); + + inb(dev.io + HP_RXL); + + while (dev.DSPQ->wTail != dev.DSPQ->wHead) { + + eval_dsp_msg(*(dev.pwDSPQData + dev.DSPQ->wHead)); + + if (++dev.DSPQ->wHead > dev.DSPQ->wSize) + dev.DSPQ->wHead = 0; + } + + if (test_bit(F_BANKONE, &dev.flags)) + outb(HPBLKSEL_1, dev.io + HP_BLKS); + + clear_bit(F_INTERRUPT, &dev.flags); +} + +static struct file_operations dev_fileops = { + NULL, + dev_read, + dev_write, + NULL, + NULL, + dev_ioctl, + NULL, + dev_open, + dev_close, +}; + +__initfunc(static int reset_dsp(void)) +{ + int timeout = 20000; + + outb(HPDSPRESET_ON, dev.io + HP_DSPR); + + mdelay(1); + + dev.info = inb(dev.io + HP_INFO); + + outb(HPDSPRESET_OFF, dev.io + HP_DSPR); + + mdelay(1); + + while (timeout-- > 0) { + + if (inb(dev.io + HP_CVR) == HP_CVR_DEF) + return 0; + + mdelay(1); + } + + printk(KERN_ERR LOGNAME ": Cannot reset DSP\n"); + + return -EIO; +} + +__initfunc(static int probe_multisound(void)) +{ + char *xv, *rev = NULL; + char *pin = "Pinnacle", *fiji = "Fiji"; + char *pinfiji = "Pinnacle/Fiji"; + + if (check_region(dev.io, dev.numio)) { + + printk(KERN_ERR LOGNAME ": I/O port conflict\n"); + return -ENODEV; + } + + request_region(dev.io, dev.numio, "probing"); + + if (reset_dsp() < 0) { + + release_region(dev.io, dev.numio); + return -ENODEV; + } + + printk(KERN_INFO LOGNAME ": DSP reset successful\n"); + + switch (dev.info >> 4) { + case 0xf: xv = "<= 1.15"; break; + case 0x1: xv = "1.18/1.2"; break; + case 0x2: xv = "1.3"; break; + case 0x3: xv = "1.4"; break; + default: xv = "unknown"; break; + } + + switch (dev.info & 0x7) { + case 0x0: rev = "I"; dev.name = pin; break; + case 0x1: rev = "F"; dev.name = pin; break; + case 0x2: rev = "G"; dev.name = pin; break; + case 0x3: rev = "H"; dev.name = pin; break; + case 0x4: rev = "E"; dev.name = fiji; break; + case 0x5: rev = "C"; dev.name = fiji; break; + case 0x6: rev = "D"; dev.name = fiji; break; + case 0x7: + rev = "A-B (Fiji) or A-E (Pinnacle)"; + dev.name = pinfiji; + break; + } + + printk(KERN_INFO LOGNAME ": Turtle Beach %s revision %s, Xilinx version %s, " + "I/O 0x%x-0x%x, IRQ %d, memory mapped to 0x%p-0x%p\n", + dev.name, + rev, xv, + dev.io, dev.io + dev.numio - 1, + dev.irq, + dev.base, dev.base + 0x7fff); + + release_region(dev.io, dev.numio); + + return 0; +} + +__initfunc(static int init_sma(void)) +{ + int n; + LPDAQD lpDAQ; + + outb(HPBLKSEL_0, dev.io + HP_BLKS); + memset_io(dev.base, 0, 0x8000); + + outb(HPBLKSEL_1, dev.io + HP_BLKS); + memset_io(dev.base, 0, 0x8000); + + outb(HPBLKSEL_0, dev.io + HP_BLKS); + + dev.DAPQ = (struct JobQueueStruct *)(dev.base + DAPQ_OFFSET); + dev.DARQ = (struct JobQueueStruct *)(dev.base + DARQ_OFFSET); + dev.MODQ = (struct JobQueueStruct *)(dev.base + MODQ_OFFSET); + dev.MIDQ = (struct JobQueueStruct *)(dev.base + MIDQ_OFFSET); + dev.DSPQ = (struct JobQueueStruct *)(dev.base + DSPQ_OFFSET); + + dev.SMA = (struct SMA0_CommonData *)(dev.base + SMA_STRUCT_START); + + dev.CurDAQD = (LPDAQD)(dev.base + DAPQ_DATA_BUFF); + dev.CurDARQD = (LPDAQD)(dev.base + DARQ_DATA_BUFF); + + dev.sample_size = DEFSAMPLESIZE; + dev.sample_rate = DEFSAMPLERATE; + dev.channels = DEFCHANNELS; + + for (n = 0, lpDAQ = dev.CurDAQD; n < 3; ++n, ++lpDAQ) { + + writew(PCTODSP_BASED((DWORD)(DAP_BUFF_SIZE * n)), &lpDAQ->wStart); + writew(DAP_BUFF_SIZE, &lpDAQ->wSize); + writew(1, &lpDAQ->wFormat); + writew(dev.sample_size, &lpDAQ->wSampleSize); + writew(dev.channels, &lpDAQ->wChannels); + writew(dev.sample_rate, &lpDAQ->wSampleRate); + writew(HIMT_PLAY_DONE * 0x100 + n, &lpDAQ->wIntMsg); + writew(n + 1, &lpDAQ->wFlags); + } + + for (n = 0, lpDAQ = dev.CurDARQD; n < 3; ++n, ++lpDAQ) { + + writew(PCTODSP_BASED((DWORD)(DAR_BUFF_SIZE * n)) + 0x4000, &lpDAQ->wStart); + writew(DAR_BUFF_SIZE, &lpDAQ->wSize); + writew(1, &lpDAQ->wFormat); + writew(dev.sample_size, &lpDAQ->wSampleSize); + writew(dev.channels, &lpDAQ->wChannels); + writew(dev.sample_rate, &lpDAQ->wSampleRate); + writew(HIMT_RECORD_DONE * 0x100 + n, &lpDAQ->wIntMsg); + writew(n + 1, &lpDAQ->wFlags); + + } + + dev.pwDSPQData = (WORD *)(dev.base + DSPQ_DATA_BUFF); + dev.pwMODQData = (WORD *)(dev.base + MODQ_DATA_BUFF); + dev.pwMIDQData = (WORD *)(dev.base + MIDQ_DATA_BUFF); + + writew(PCTODSP_BASED(MIDQ_DATA_BUFF), &dev.MIDQ->wStart); + writew(PCTODSP_OFFSET(MIDQ_BUFF_SIZE) - 1, &dev.MIDQ->wSize); + writew(0, &dev.MIDQ->wHead); + writew(0, &dev.MIDQ->wTail); + + writew(PCTODSP_BASED(MODQ_DATA_BUFF), &dev.MODQ->wStart); + writew(PCTODSP_OFFSET(MODQ_BUFF_SIZE) - 1, &dev.MODQ->wSize); + writew(0, &dev.MODQ->wHead); + writew(0, &dev.MODQ->wTail); + + writew(PCTODSP_BASED(DAPQ_DATA_BUFF), &dev.DAPQ->wStart); + writew(PCTODSP_OFFSET(DAPQ_BUFF_SIZE) - 1, &dev.DAPQ->wSize); + writew(0, &dev.DAPQ->wHead); + writew(0, &dev.DAPQ->wTail); + + writew(PCTODSP_BASED(DARQ_DATA_BUFF), &dev.DARQ->wStart); + writew(PCTODSP_OFFSET(DARQ_BUFF_SIZE) - 1, &dev.DARQ->wSize); + writew(0, &dev.DARQ->wHead); + writew(0, &dev.DARQ->wTail); + + writew(PCTODSP_BASED(DSPQ_DATA_BUFF), &dev.DSPQ->wStart); + writew(PCTODSP_OFFSET(DSPQ_BUFF_SIZE) - 1, &dev.DSPQ->wSize); + writew(0, &dev.DSPQ->wHead); + writew(0, &dev.DSPQ->wTail); + + writew(0, &dev.SMA->wCurrPlayBytes); + writew(0, &dev.SMA->wCurrRecordBytes); + + writew(0, &dev.SMA->wCurrPlayVolLeft); + writew(0, &dev.SMA->wCurrPlayVolRight); + + writew(0, &dev.SMA->wCurrInVolLeft); + writew(0, &dev.SMA->wCurrInVolRight); + + writew(0, &dev.SMA->wCurrMastVolLeft); + writew(0, &dev.SMA->wCurrMastVolRight); + + writel(0x00010000, &dev.SMA->dwCurrPlayPitch); + writel(0x00000001, &dev.SMA->dwCurrPlayRate); + + writew(0x0000, &dev.SMA->wCurrDSPStatusFlags); + writew(0x0000, &dev.SMA->wCurrHostStatusFlags); + + writew(0x303, &dev.SMA->wCurrInputTagBits); + writew(0, &dev.SMA->wCurrLeftPeak); + writew(0, &dev.SMA->wCurrRightPeak); + + writeb(0, &dev.SMA->bInPotPosRight); + writeb(0, &dev.SMA->bInPotPosLeft); + + writeb(0, &dev.SMA->bAuxPotPosRight); + writeb(0, &dev.SMA->bAuxPotPosLeft); + + writew(1, &dev.SMA->wCurrPlayFormat); + writew(dev.sample_size, &dev.SMA->wCurrPlaySampleSize); + writew(dev.channels, &dev.SMA->wCurrPlayChannels); + writew(dev.sample_rate, &dev.SMA->wCurrPlaySampleRate); + writew(dev.sample_rate, &dev.SMA->wCalFreqAtoD); + + return 0; +} + +__initfunc(static int calibrate_adc(WORD srate)) +{ + if (!dev.calibrate_signal) { + + printk(KERN_INFO LOGNAME ": ADC calibration to board ground "); + writew(readw(&dev.SMA->wCurrHostStatusFlags) + | 0x0001, &dev.SMA->wCurrHostStatusFlags); + } + else { + + printk(KERN_INFO LOGNAME ": ADC calibration to signal ground "); + writew(readw(&dev.SMA->wCurrHostStatusFlags) + & ~0x0001, &dev.SMA->wCurrHostStatusFlags); + } + + writew(srate, &dev.SMA->wCalFreqAtoD); + + if (msnd_send_word(&dev, 0, 0, HDEXAR_CAL_A_TO_D) == 0 && + msnd_send_dsp_cmd(&dev, HDEX_AUX_REQ) == 0) { + + current->state = TASK_INTERRUPTIBLE; + current->timeout = jiffies + HZ; + schedule(); + current->timeout = 0; + printk("successful\n"); + return 0; + } + + printk("failed\n"); + + return -EIO; +} + +__initfunc(static int upload_dsp_code(void)) +{ + outb(HPBLKSEL_0, dev.io + HP_BLKS); + +#ifdef HAVE_DSPCODEH + printk(KERN_INFO LOGNAME ": Using resident Turtle Beach DSP code\n"); +#else + printk(KERN_INFO LOGNAME ": Loading Turtle Beach DSP code\n"); + INITCODESIZE = mod_firmware_load(INITCODEFILE, &INITCODE); + if (!INITCODE) { + printk(KERN_ERR LOGNAME ": Error loading " INITCODEFILE); + return -EBUSY; + } + + PERMCODESIZE = mod_firmware_load(PERMCODEFILE, &PERMCODE); + if (!PERMCODE) { + printk(KERN_ERR LOGNAME ": Error loading " PERMCODEFILE); + vfree(INITCODE); + return -EBUSY; + } +#endif + memcpy_toio(dev.base, PERMCODE, PERMCODESIZE); + + if (msnd_upload_host(&dev, INITCODE, INITCODESIZE) < 0) { + + printk(KERN_WARNING LOGNAME ": Error uploading to DSP\n"); + return -ENODEV; + } + +#ifndef HAVE_DSPCODEH + vfree(INITCODE); + vfree(PERMCODE); +#endif + + return 0; +} + +__initfunc(static int initialize(void)) +{ + int err, timeout; + + if ((err = init_sma()) < 0) { + + printk(KERN_WARNING LOGNAME ": Cannot initialize SMA\n"); + return err; + } + + if ((err = reset_dsp()) < 0) + return err; + + if ((err = upload_dsp_code()) < 0) { + + printk(KERN_WARNING LOGNAME ": Cannot upload DSP code\n"); + return err; + + } else + printk(KERN_INFO LOGNAME ": DSP upload successful\n"); + + timeout = 2000; + + while (readw(dev.base)) { + + mdelay(1); + if (--timeout < 0) + return -EIO; + } + + return 0; +} + +__initfunc(static int attach_multisound(void)) +{ + int err; + + printk(KERN_DEBUG LOGNAME ": Intializing DSP\n"); + + if ((err = request_irq(dev.irq, intr, SA_SHIRQ, DEVNAME, &dev)) < 0) { + + printk(KERN_ERR LOGNAME ": Couldn't grab IRQ %d\n", dev.irq); + return err; + + } + + request_region(dev.io, dev.numio, DEVNAME); + + if ((err = initialize()) < 0) { + + printk(KERN_WARNING LOGNAME ": Initialization failure\n"); + release_region(dev.io, dev.numio); + free_irq(dev.irq, &dev); + return err; + + } + + if ((err = msnd_register(&dev)) < 0) { + + printk(KERN_ERR LOGNAME ": Unable to register MultiSound\n"); + release_region(dev.io, dev.numio); + free_irq(dev.irq, &dev); + return err; + } + + if ((DSPMINOR = register_sound_dsp(&dev_fileops)) < 0) { + + printk(KERN_ERR LOGNAME ": Unable to register DSP operations\n"); + msnd_unregister(&dev); + release_region(dev.io, dev.numio); + free_irq(dev.irq, &dev); + return DSPMINOR; + } + + if ((MIXERMINOR = register_sound_mixer(&dev_fileops)) < 0) { + + printk(KERN_ERR LOGNAME ": Unable to register mixer operations\n"); + unregister_sound_mixer(MIXERMINOR); + msnd_unregister(&dev); + release_region(dev.io, dev.numio); + free_irq(dev.irq, &dev); + return MIXERMINOR; + } + printk(KERN_INFO LOGNAME ": Using DSP minor %d, mixer minor %d\n", MIXERMINOR, DSPMINOR); + + calibrate_adc(dev.sample_rate); + set_recsrc(0); + + return 0; +} + +static void unload_multisound(void) +{ + release_region(dev.io, dev.numio); + free_irq(dev.irq, &dev); + unregister_sound_mixer(MIXERMINOR); + unregister_sound_dsp(DSPMINOR); + msnd_unregister(&dev); +} + +static void mod_inc_ref(void) +{ + MOD_INC_USE_COUNT; +} + +static void mod_dec_ref(void) +{ + MOD_DEC_USE_COUNT; +} + +#ifdef MODULE +MODULE_AUTHOR ("Andrew Veliath "); +MODULE_DESCRIPTION ("Turtle Beach " LONGNAME " Linux Driver"); +MODULE_PARM (io, "i"); +MODULE_PARM (irq, "i"); +MODULE_PARM (mem, "i"); +MODULE_PARM (major, "i"); +MODULE_PARM (fifosize, "i"); +MODULE_PARM (calibrate_signal, "i"); + +static int io __initdata = -1; +static int irq __initdata = -1; +static int mem __initdata = -1; +static int fifosize __initdata = DEFFIFOSIZE; +static int +calibrate_signal __initdata = 0; + +int init_module(void) +{ + int err; + + printk(KERN_INFO LOGNAME ": Turtle Beach " LONGNAME " Linux Driver Version " + VERSION ", Copyright (C) 1998 Andrew Veliath\n"); + + if (io == -1 || irq == -1 || mem == -1) { + + printk(KERN_WARNING LOGNAME ": io, irq and mem must be set\n"); + } + + if (io == -1 || + !(io == 0x290 || + io == 0x260 || + io == 0x250 || + io == 0x240 || + io == 0x230 || + io == 0x220 || + io == 0x210 || + io == 0x3e0)) { + + printk(KERN_ERR LOGNAME ": \"io\" - DSP I/O base must be set\n"); + return -EINVAL; + } + + if (irq == -1 || + !(irq == 5 || + irq == 7 || + irq == 9 || + irq == 10 || + irq == 11 || + irq == 12)) { + + printk(KERN_ERR LOGNAME ": \"irq\" - must be set to 5, 7, 9, 10, 11 or 12\n"); + return -EINVAL; + } + + if (mem == -1 || + !(mem == 0xb0000 || + mem == 0xc8000 || + mem == 0xd0000 || + mem == 0xd8000 || + mem == 0xe0000 || + mem == 0xe8000)) { + + printk(KERN_ERR LOGNAME ": \"mem\" - must be set to " + "0xb0000, 0xc8000, 0xd0000, 0xd8000, 0xe0000 or 0xe8000\n"); + return -EINVAL; + } + + if (fifosize < 16) + fifosize = 16; + + if (fifosize > 768) + fifosize = 768; + + dev.type = msndPinnacle; + dev.io = io; + dev.numio = DSP_NUMIO; + dev.irq = irq; + dev.base = phys_to_virt(mem); + dev.fifosize = fifosize * 1024; + dev.calibrate_signal = calibrate_signal ? 1 : 0; + dev.recsrc = 0; + dev.inc_ref = mod_inc_ref; + dev.dec_ref = mod_dec_ref; + + init_waitqueue(&dev.writeblock); + init_waitqueue(&dev.readblock); + msnd_fifo_init(&dev.DAPF); + msnd_fifo_init(&dev.DARF); + spin_lock_init(&dev.lock); + + printk(KERN_INFO LOGNAME ": Using %u byte digital audio FIFOs (x2)\n", dev.fifosize); + + if ((err = msnd_fifo_alloc(&dev.DAPF, dev.fifosize)) < 0) { + + printk(KERN_ERR LOGNAME ": Couldn't allocate write FIFO\n"); + return err; + } + + if ((err = msnd_fifo_alloc(&dev.DARF, dev.fifosize)) < 0) { + + printk(KERN_ERR LOGNAME ": Couldn't allocate read FIFO\n"); + msnd_fifo_free(&dev.DAPF); + return err; + } + + if ((err = probe_multisound()) < 0) { + + printk(KERN_ERR LOGNAME ": Probe failed\n"); + msnd_fifo_free(&dev.DAPF); + msnd_fifo_free(&dev.DARF); + return err; + + } + + if ((err = attach_multisound()) < 0) { + + printk(KERN_ERR LOGNAME ": Attach failed\n"); + msnd_fifo_free(&dev.DAPF); + msnd_fifo_free(&dev.DARF); + return err; + + } + + return 0; +} + +void cleanup_module(void) +{ + printk(KERN_INFO LOGNAME ": Unloading\n"); + + unload_multisound(); + + msnd_fifo_free(&dev.DAPF); + msnd_fifo_free(&dev.DARF); + +} +#endif diff -u --recursive --new-file v2.1.105/linux/drivers/sound/msnd_pinnacle.h linux/drivers/sound/msnd_pinnacle.h --- v2.1.105/linux/drivers/sound/msnd_pinnacle.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/sound/msnd_pinnacle.h Sat Jun 13 10:23:52 1998 @@ -0,0 +1,247 @@ +/********************************************************************* + * + * msnd_pinnacle.h + * + * Turtle Beach MultiSound Soundcard Driver for Linux + * + * Some parts of this header file were derived from the Turtle Beach + * MultiSound Driver Development Kit. + * + * Copyright (C) 1998 Andrew Veliath + * Copyright (C) 1993 Turtle Beach Systems, Inc. + * + * 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. + * + * $Id: msnd_pinnacle.h,v 1.3 1998/06/09 20:39:34 andrewtv Exp $ + * + ********************************************************************/ +#ifndef __MSND_PINNACLE_H +#define __MSND_PINNACLE_H + +#define DSP_NUMIO 0x08 + +#define HP_DSPR 0x04 +#define HP_BLKS 0x04 + +#define HPDSPRESET_OFF 2 +#define HPDSPRESET_ON 0 + +#define HPBLKSEL_0 2 +#define HPBLKSEL_1 3 + +#define HIMT_DAT_OFF 0x03 + +#define HIDSP_PLAY_UNDER 0x00 +#define HIDSP_INT_PLAY_UNDER 0x01 +#define HIDSP_SSI_TX_UNDER 0x02 +#define HIDSP_RECQ_OVERFLOW 0x08 +#define HIDSP_INT_RECORD_OVER 0x09 +#define HIDSP_SSI_RX_OVERFLOW 0x0a + +#define HIDSP_MIDI_IN_OVER 0x10 + +#define HIDSP_MIDI_FRAME_ERR 0x11 +#define HIDSP_MIDI_PARITY_ERR 0x12 +#define HIDSP_MIDI_OVERRUN_ERR 0x13 + +#define HIDSP_INPUT_CLIPPING 0x20 +#define HIDSP_MIX_CLIPPING 0x30 +#define HIDSP_DAT_IN_OFF 0x21 + +#define HDEX_BASE 0x92 +#define HDEX_PLAY_START (0 + HDEX_BASE) +#define HDEX_PLAY_STOP (1 + HDEX_BASE) +#define HDEX_PLAY_PAUSE (2 + HDEX_BASE) +#define HDEX_PLAY_RESUME (3 + HDEX_BASE) +#define HDEX_RECORD_START (4 + HDEX_BASE) +#define HDEX_RECORD_STOP (5 + HDEX_BASE) +#define HDEX_MIDI_IN_START (6 + HDEX_BASE) +#define HDEX_MIDI_IN_STOP (7 + HDEX_BASE) +#define HDEX_MIDI_OUT_START (8 + HDEX_BASE) +#define HDEX_MIDI_OUT_STOP (9 + HDEX_BASE) +#define HDEX_AUX_REQ (10 + HDEX_BASE) + +#define HDEXAR_SET_ANA_IN 0 +#define HDEXAR_CLEAR_PEAKS 1 +#define HDEXAR_IN_SET_POTS 2 +#define HDEXAR_AUX_SET_POTS 3 +#define HDEXAR_CAL_A_TO_D 4 +#define HDEXAR_RD_EXT_DSP_BITS 5 + +#define HDEXAR_SET_SYNTH_IN 4 +#define HDEXAR_READ_DAT_IN 5 +#define HDEXAR_MIC_SET_POTS 6 +#define HDEXAR_SET_DAT_IN 7 + +#define HDEXAR_SET_SYNTH_48 8 +#define HDEXAR_SET_SYNTH_44 9 + +#define TIME_PRO_RESET_DONE 0x028A +#define TIME_PRO_SYSEX 0x001E +#define TIME_PRO_RESET 0x0032 + +#define AGND 0x01 +#define SIGNAL 0x02 + +#define EXT_DSP_BIT_DCAL 0x0001 +#define EXT_DSP_BIT_MIDI_CON 0x0002 + +#define BUFFSIZE 0x8000 +#define HOSTQ_SIZE 0x40 + +#define SRAM_CNTL_START 0x7F00 +#define SMA_STRUCT_START 0x7F40 + +#define DAP_BUFF_SIZE 0x2400 +#define DAR_BUFF_SIZE 0x2000 + +#define DAPQ_STRUCT_SIZE 0x10 +#define DARQ_STRUCT_SIZE 0x10 +#define DAPQ_BUFF_SIZE (3 * 0x10) +#define DARQ_BUFF_SIZE (3 * 0x10) +#define MODQ_BUFF_SIZE 0x400 +#define MIDQ_BUFF_SIZE 0x800 +#define DSPQ_BUFF_SIZE 0x5A0 + +#define DAPQ_DATA_BUFF 0x6C00 +#define DARQ_DATA_BUFF 0x6C30 +#define MODQ_DATA_BUFF 0x6C60 +#define MIDQ_DATA_BUFF 0x7060 +#define DSPQ_DATA_BUFF 0x7860 + +#define DAPQ_OFFSET SRAM_CNTL_START +#define DARQ_OFFSET (SRAM_CNTL_START + 0x08) +#define MODQ_OFFSET (SRAM_CNTL_START + 0x10) +#define MIDQ_OFFSET (SRAM_CNTL_START + 0x18) +#define DSPQ_OFFSET (SRAM_CNTL_START + 0x20) + +#define WAVEHDR_MOP 0 +#define EXTOUT_MOP 1 +#define HWINIT_MOP 0xFE +#define NO_MOP 0xFF + +#define MAX_MOP 1 + +#define EXTIN_MIP 0 +#define WAVEHDR_MIP 1 +#define HWINIT_MIP 0xFE + +#define MAX_MIP 1 + +struct SMA0_CommonData { + WORD wCurrPlayBytes; + WORD wCurrRecordBytes; + WORD wCurrPlayVolLeft; + WORD wCurrPlayVolRight; + + WORD wCurrInVolLeft; + WORD wCurrInVolRight; + WORD wCurrMHdrVolLeft; + WORD wCurrMHdrVolRight; + + DWORD dwCurrPlayPitch; + DWORD dwCurrPlayRate; + + WORD wCurrMIDIIOPatch; + + WORD wCurrPlayFormat; + WORD wCurrPlaySampleSize; + WORD wCurrPlayChannels; + WORD wCurrPlaySampleRate; + + WORD wCurrRecordFormat; + WORD wCurrRecordSampleSize; + WORD wCurrRecordChannels; + WORD wCurrRecordSampleRate; + + WORD wCurrDSPStatusFlags; + WORD wCurrHostStatusFlags; + + WORD wCurrInputTagBits; + WORD wCurrLeftPeak; + WORD wCurrRightPeak; + + BYTE bMicPotPosLeft; + BYTE bMicPotPosRight; + + BYTE bMicPotMaxLeft; + BYTE bMicPotMaxRight; + + BYTE bInPotPosLeft; + BYTE bInPotPosRight; + + BYTE bAuxPotPosLeft; + BYTE bAuxPotPosRight; + + BYTE bInPotMaxLeft; + BYTE bInPotMaxRight; + BYTE bAuxPotMaxLeft; + BYTE bAuxPotMaxRight; + BYTE bInPotMaxMethod; + BYTE bAuxPotMaxMethod; + + WORD wCurrMastVolLeft; + WORD wCurrMastVolRight; + + WORD wCalFreqAtoD; + + WORD wCurrAuxVolLeft; + WORD wCurrAuxVolRight; + + WORD wCurrPlay1VolLeft; + WORD wCurrPlay1VolRight; + WORD wCurrPlay2VolLeft; + WORD wCurrPlay2VolRight; + WORD wCurrPlay3VolLeft; + WORD wCurrPlay3VolRight; + WORD wCurrPlay4VolLeft; + WORD wCurrPlay4VolRight; + WORD wCurrPlay1PeakLeft; + WORD wCurrPlay1PeakRight; + WORD wCurrPlay2PeakLeft; + WORD wCurrPlay2PeakRight; + WORD wCurrPlay3PeakLeft; + WORD wCurrPlay3PeakRight; + WORD wCurrPlay4PeakLeft; + WORD wCurrPlay4PeakRight; + WORD wCurrPlayPeakLeft; + WORD wCurrPlayPeakRight; + + WORD wCurrDATSR; + WORD wCurrDATRXCHNL; + WORD wCurrDATTXCHNL; + WORD wCurrDATRXRate; + + DWORD dwDSPPlayCount; +} GCC_PACKED; + +#ifdef HAVE_DSPCODEH +# include "pndsperm.c" +# include "pndspini.c" +# define PERMCODE pndsperm +# define INITCODE pndspini +# define PERMCODESIZE sizeof(pndsperm) +# define INITCODESIZE sizeof(pndspini) +#else +# define PERMCODEFILE CONFIG_MSNDPIN_PERM_FILE +# define INITCODEFILE CONFIG_MSNDPIN_INIT_FILE +# define PERMCODE dspini +# define INITCODE permini +# define PERMCODESIZE sizeof_dspini +# define INITCODESIZE sizeof_permini +#endif +#define LONGNAME "MultiSound (Pinnacle/Fiji)" + +#endif /* __MSND_PINNACLE_H */ diff -u --recursive --new-file v2.1.105/linux/drivers/sound/soundcard.c linux/drivers/sound/soundcard.c --- v2.1.105/linux/drivers/sound/soundcard.c Tue Jun 9 11:57:30 1998 +++ linux/drivers/sound/soundcard.c Sat Jun 13 11:40:31 1998 @@ -153,13 +153,16 @@ #else #define MODULEPROCSTRING "Driver compiled into kernel" #endif - + + down(&uts_sem); + len = sprintf(buffer, "OSS/Free:" SOUND_VERSION_STRING "\n" "Load type: " MODULEPROCSTRING "\n" "Kernel: %s %s %s %s %s\n" "Config options: %x\n\nInstalled drivers: \n", system_utsname.sysname, system_utsname.nodename, system_utsname.release, system_utsname.version, system_utsname.machine, SELECTED_SOUND_OPTIONS); + up(&uts_sem); for (i = 0; (i < num_sound_drivers) && (pos <= offset + length); i++) { if (!sound_drivers[i].card_type) diff -u --recursive --new-file v2.1.105/linux/drivers/sound/v_midi.c linux/drivers/sound/v_midi.c --- v2.1.105/linux/drivers/sound/v_midi.c Thu May 14 19:47:42 1998 +++ linux/drivers/sound/v_midi.c Sat Jun 13 10:23:52 1998 @@ -21,10 +21,11 @@ #include #include -#ifdef CONFIG_VMIDI - #include "sound_config.h" #include "soundmodule.h" + +#ifdef CONFIG_VMIDI + #include "v_midi.h" static vmidi_devc *v_devc[2] = { NULL, NULL}; diff -u --recursive --new-file v2.1.105/linux/drivers/zorro/Makefile linux/drivers/zorro/Makefile --- v2.1.105/linux/drivers/zorro/Makefile Wed Dec 31 16:00:00 1969 +++ linux/drivers/zorro/Makefile Mon Jun 8 11:03:49 1998 @@ -0,0 +1,12 @@ +# +# Makefile for the linux/drivers/zorro/ directory. +# + +SUB_DIRS := +MOD_SUB_DIRS := $(SUB_DIRS) +ALL_SUB_DIRS := $(SUB_DIRS) + +L_OBJS := zorro.o +L_TARGET := zorro.a + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.105/linux/drivers/zorro/zorro.c linux/drivers/zorro/zorro.c --- v2.1.105/linux/drivers/zorro/zorro.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/zorro/zorro.c Mon Jun 8 11:03:50 1998 @@ -0,0 +1,1245 @@ +/* + * linux/arch/m68k/amiga/zorro.c + * + * Copyright (C) 1995 Geert Uytterhoeven + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef CONFIG_ZORRO + + /* + * Zorro Expansion Device Manufacturers and Products + */ + +struct Manufacturer { + const char *Name; + u_short Manuf; + u_short NumProd; + const struct Product *Products; +}; + +struct Product { + const char *Name; + u_char Class; + u_char Prod; +}; + +struct GVP_Product { + const char *Name; + u_char Class; + u_char EPC; +}; + + + /* + * Macro's to make life easier + */ + +#define ARRAYSIZE(x) (sizeof(x)/sizeof(*(x))) + +#define BEGIN_PROD(id) \ + static struct Product Prod_##id[] = { +#define PROD(name, class, id) \ + { name, ZORRO_CLASS_##class, ZORRO_PROD(ZORRO_PROD_##id) }, + +#define BEGIN_GVP_PROD \ + static struct GVP_Product Ext_Prod_GVP[] = { +#define GVP_PROD(name, class, id) \ + { name, ZORRO_CLASS_##class, ZORRO_EPC(ZORRO_PROD_##id) }, + +#define BEGIN_MANUF \ + static struct Manufacturer Manufacturers[] = { +#define MANUF(name, id) \ + { name, ZORRO_MANUF_##id, ARRAYSIZE(Prod_##id), Prod_##id }, + +#define END \ + }; + + + /* + * Recognized Zorro Expansion Devices + */ + +BEGIN_PROD(PACIFIC_PERIPHERALS) + PROD("SE 2000 A500", HD, PACIFIC_PERIPHERALS_SE_2000_A500) + PROD(NULL, SCSI, PACIFIC_PERIPHERALS_SCSI) +END + +BEGIN_PROD(MACROSYSTEMS_USA_2) + PROD("Warp Engine", TURBO_SCSI_RAM, MACROSYSTEMS_WARP_ENGINE) +END + +BEGIN_PROD(KUPKE_1) + PROD("Golem RAM Box 2MB", RAM, KUPKE_GOLEM_RAM_BOX_2MB) +END + +BEGIN_PROD(MEMPHIS) + PROD("Stormbringer", TURBO, MEMPHIS_STORMBRINGER) +END + +BEGIN_PROD(3_STATE) + PROD("Megamix 2000", RAM, 3_STATE_MEGAMIX_2000) +END + +BEGIN_PROD(COMMODORE_BRAUNSCHWEIG) + PROD("A2088 XT/A2286 AT", BRIDGE, CBM_A2088_A2286) + PROD("A2286 AT", BRIDGE, CBM_A2286) + PROD("A4091", SCSI, CBM_A4091_1) + PROD("A2386-SX", BRIDGE, CBM_A2386SX_1) +END + +BEGIN_PROD(COMMODORE_WEST_CHESTER_1) + PROD("A2090/A2090A", SCSI, CBM_A2090A) + PROD("A590/A2091", SCSI, CBM_A590_A2091_1) + PROD("A590/A2091", SCSI, CBM_A590_A2091_2) + PROD("A2090B 2090 Autoboot", SCSI, CBM_A2090B) + PROD("A2060", ARCNET, CBM_A2060) + PROD("A590/A2052/A2058/A2091", RAM, CBM_A590_A2052_A2058_A2091) + PROD("A560", RAM, CBM_A560_RAM) + PROD("A2232 Prototype", MULTIIO, CBM_A2232_PROTOTYPE) + PROD("A2232", MULTIIO, CBM_A2232) + PROD("A2620 68020/RAM", TURBO_RAM, CBM_A2620) + PROD("A2630 68030/RAM", TURBO_RAM, CBM_A2630) + PROD("A4091", SCSI, CBM_A4091_2) + PROD("A2065", ETHERNET, CBM_A2065_1) + PROD("Romulator Card", UNKNOWN, CBM_ROMULATOR) + PROD("A3000 Test Fixture", MISC, CBM_A3000_TEST_FIXTURE) + PROD("A2386-SX", BRIDGE, CBM_A2386SX_2) + PROD("A2065", ETHERNET, CBM_A2065_2) +END + +BEGIN_PROD(COMMODORE_WEST_CHESTER_2) + PROD("A2090/A2090A Combitec/MacroSystem", SCSI, CBM_A2090A_CM) +END + +BEGIN_PROD(PROGRESSIVE_PERIPHERALS_AND_SYSTEMS_2) + PROD("EXP8000", RAM, PPS_EXP8000) +END + +BEGIN_PROD(KOLFF_COMPUTER_SUPPLIES) + PROD("KCS Power PC Board", BRIDGE, KCS_POWER_PC_BOARD) +END + +BEGIN_PROD(CARDCO_1) + PROD("Kronos 2000", SCSI, CARDCO_KRONOS_2000_1) + PROD("A1000", SCSI, CARDCO_A1000_1) + PROD("Escort", SCSI, CARDCO_ESCORT) + PROD("A2410 HiRes", GFX, CARDCO_A2410) +END + +BEGIN_PROD(A_SQUARED) + PROD("Live! 2000", VIDEO, A_SQUARED_LIVE_2000) +END + +BEGIN_PROD(COMSPEC_COMMUNICATIONS) + PROD("AX2000", RAM, COMSPEC_COMMUNICATIONS_AX2000) +END + +BEGIN_PROD(ANAKIN_RESEARCH) + PROD("Easyl", TABLET, ANAKIN_RESEARCH_EASYL) +END + +BEGIN_PROD(MICROBOTICS) + PROD("StarBoard II", RAM, MICROBOTICS_STARBOARD_II) + PROD("StarDrive", SCSI, MICROBOTICS_STARDRIVE) + PROD("8-Up (Rev A)", RAM, MICROBOTICS_8_UP_A) + PROD("8-Up (Rev Z)", RAM, MICROBOTICS_8_UP_Z) + PROD("Delta", RAM, MICROBOTICS_DELTA_RAM) + PROD("8-Star", RAM, MICROBOTICS_8_STAR_RAM) + PROD("8-Star", MISC, MICROBOTICS_8_STAR) + PROD("VXL RAM*32", RAM, MICROBOTICS_VXL_RAM_32) + PROD("VXL-30", TURBO, MICROBOTICS_VXL_68030) + PROD("Delta", MISC, MICROBOTICS_DELTA) + PROD("MBX 1200/1200z", RAM, MICROBOTICS_MBX_1200_1200Z_RAM) + PROD("Hardframe 2000", SCSI, MICROBOTICS_HARDFRAME_2000_1) + PROD("Hardframe 2000", SCSI, MICROBOTICS_HARDFRAME_2000_2) + PROD("MBX 1200/1200z", MISC, MICROBOTICS_MBX_1200_1200Z) +END + +BEGIN_PROD(ACCESS_ASSOCIATES_ALEGRA) +END + +BEGIN_PROD(EXPANSION_TECHNOLOGIES) +END + +BEGIN_PROD(ASDG) + PROD(NULL, RAM, ASDG_MEMORY_1) + PROD(NULL, RAM, ASDG_MEMORY_2) + PROD("EB-920 Lan Rover", ETHERNET, ASDG_EB920_LAN_ROVER) + PROD("GPIB/Dual IEEE-488/Twin-X", MULTIIO, ASDG_GPIB_DUALIEEE488_TWIN_X) +END + +BEGIN_PROD(IMTRONICS_1) + PROD("Hurricane 2800", TURBO_RAM, IMTRONICS_HURRICANE_2800_1) + PROD("Hurricane 2800", TURBO_RAM, IMTRONICS_HURRICANE_2800_2) +END + +BEGIN_PROD(CBM_UNIVERSITY_OF_LOWELL) + PROD("A2410 HiRes", GFX, CBM_A2410) +END + +BEGIN_PROD(AMERISTAR) + PROD("A2065", ETHERNET, AMERISTAR_A2065) + PROD("A560", ARCNET, AMERISTAR_A560) + PROD("A4066", ETHERNET, AMERISTAR_A4066) +END + +BEGIN_PROD(SUPRA) + PROD("SupraDrive 4x4", SCSI, SUPRA_SUPRADRIVE_4x4) + PROD("1000", RAM, SUPRA_1000_RAM) + PROD("2000 DMA", SCSI, SUPRA_2000_DMA) + PROD("500", SCSI_RAM, SUPRA_500) + PROD("500", SCSI, SUPRA_500_SCSI) + PROD("500XP/2000", RAM, SUPRA_500XP_2000_RAM) + PROD("500RX/2000", RAM, SUPRA_500RX_2000_RAM) + PROD("2400zi", MODEM, SUPRA_2400ZI) + PROD("500XP/SupraDrive WordSync", SCSI, SUPRA_500XP_SUPRADRIVE_WORDSYNC) + PROD("SupraDrive WordSync II", SCSI, SUPRA_SUPRADRIVE_WORDSYNC_II) + PROD("2400zi+", MODEM, SUPRA_2400ZIPLUS) +END + +BEGIN_PROD(COMPUTER_SYSTEMS_ASSOCIATES) + PROD("Magnum 40", TURBO_SCSI, CSA_MAGNUM) + PROD("12 Gauge", SCSI, CSA_12_GAUGE) +END + +BEGIN_PROD(MARC_MICHAEL_GROTH) +END + +BEGIN_PROD(M_TECH) + PROD("AT500", RAM, MTEC_AT500_1) +END + +BEGIN_PROD(GREAT_VALLEY_PRODUCTS_1) + PROD("Impact Series I", SCSI_RAM, GVP_IMPACT_SERIES_I) +END + +BEGIN_PROD(BYTEBOX) + PROD("A500", UNKNOWN, BYTEBOX_A500) +END + +BEGIN_PROD(DKB_POWER_COMPUTING) + PROD("SecureKey", UNKNOWN, DKB_POWER_COMPUTING_SECUREKEY) + PROD("DKM 3128", RAM, DKB_POWER_COMPUTING_DKM_3128) + PROD("Rapid Fire", SCSI, DKB_POWER_COMPUTING_RAPID_FIRE) + PROD("DKM 1202", FPU_RAM, DKB_POWER_COMPUTING_DKM_1202) + PROD("Cobra/Viper II 68EC030", TURBO, DKB_POWER_COMPUTING_COBRA_VIPER_II_68EC030) + PROD("WildFire 060", TURBO, DKB_POWER_COMPUTING_WILDFIRE_060_1) + PROD("WildFire 060", TURBO, DKB_POWER_COMPUTING_WILDFIRE_060_2) +END + +BEGIN_PROD(GREAT_VALLEY_PRODUCTS_2) + PROD("Impact Series I (4K)", SCSI, GVP_IMPACT_SERIES_I_4K) + PROD("Impact Series I (16K/2)", SCSI, GVP_IMPACT_SERIES_I_16K_2) + PROD("Impact Series I (16K/2)", SCSI, GVP_IMPACT_SERIES_I_16K_3) + PROD("Impact 3001", IDE, GVP_IMPACT_3001_IDE_1) + PROD("Impact 3001", RAM, GVP_IMPACT_3001_RAM) + PROD("Impact Series II", RAM, GVP_IMPACT_SERIES_II_RAM_1) +/* PROD(NULL, UNKNOWN, GVP_EPC_BASE) */ + PROD("Impact 3001", IDE, GVP_IMPACT_3001_IDE_2) +/* PROD("A2000 030", TURBO, GVP_A2000_030) */ +/* PROD("GForce 040", TURBO_SCSI, GFORCE_040_SCSI_2) */ + PROD("GForce 040/060", TURBO_SCSI, GVP_GFORCE_040_060) + PROD("Impact Vision 24", GFX, GVP_IMPACT_VISION_24) + PROD("GForce 040", TURBO, GVP_GFORCE_040_2) +END + +BEGIN_GVP_PROD /* ZORRO_PROD_GVP_EPC_BASE */ + GVP_PROD("GForce 040", TURBO, GVP_GFORCE_040_1) + GVP_PROD("GForce 040", TURBO_SCSI, GVP_GFORCE_040_SCSI_1) + GVP_PROD("A1291", SCSI, GVP_A1291) + GVP_PROD("Combo 030 R4", TURBO, GVP_COMBO_030_R4) + GVP_PROD("Combo 030 R4", TURBO_SCSI, GVP_COMBO_030_R4_SCSI) + GVP_PROD("Phone Pak", UNKNOWN, GVP_PHONEPAK) + GVP_PROD("IO-Extender", MULTIIO, GVP_IO_EXTENDER) + GVP_PROD("GForce 030", TURBO, GVP_GFORCE_030) + GVP_PROD("GForce 030", TURBO_SCSI, GVP_GFORCE_030_SCSI) + GVP_PROD("A530", TURBO, GVP_A530) + GVP_PROD("A530", TURBO_SCSI, GVP_A530_SCSI) + GVP_PROD("Combo 030 R3", TURBO, GVP_COMBO_030_R3) + GVP_PROD("Combo 030 R3", TURBO_SCSI, GVP_COMBO_030_R3_SCSI) + GVP_PROD("Series-II", SCSI, GVP_SERIES_II) +END + +BEGIN_PROD(CALIFORNIA_ACCESS_SYNERGY) + PROD("Malibu", SCSI, CALIFORNIA_ACCESS_SYNERGY_MALIBU) +END + +BEGIN_PROD(XETEC) + PROD("FastCard", SCSI, XETEC_FASTCARD) + PROD("FastCard", RAM, XETEC_FASTCARD_RAM) + PROD("FastCard Plus", SCSI, XETEC_FASTCARD_PLUS) +END + +BEGIN_PROD(PROGRESSIVE_PERIPHERALS_AND_SYSTEMS) + PROD("Mercury", TURBO, PPS_MERCURY) + PROD("A3000 68040", TURBO, PPS_A3000_68040) + PROD("A2000 68040", TURBO, PPS_A2000_68040) + PROD("Zeus", TURBO_SCSI_RAM, PPS_ZEUS) + PROD("A500 68040", TURBO, PPS_A500_68040) +END + +BEGIN_PROD(XEBEC) +END + +BEGIN_PROD(SPIRIT_TECHNOLOGY) + PROD("Insider IN1000", RAM, SPIRIT_TECHNOLOGY_INSIDER_IN1000) + PROD("Insider IN500", RAM, SPIRIT_TECHNOLOGY_INSIDER_IN500) + PROD("SIN500", RAM, SPIRIT_TECHNOLOGY_SIN500) + PROD("HDA 506", HD, SPIRIT_TECHNOLOGY_HDA_506) + PROD("AX-S", MISC, SPIRIT_TECHNOLOGY_AX_S) + PROD("OctaByte", RAM, SPIRIT_TECHNOLOGY_OCTABYTE) + PROD("Inmate", SCSI_RAM, SPIRIT_TECHNOLOGY_INMATE) +END + +BEGIN_PROD(SPIRIT_TECHNOLOGY_2) +END + +BEGIN_PROD(BSC_ALFADATA_1) + PROD("ALF 3", SCSI, BSC_ALF_3_1) +END + +BEGIN_PROD(BSC_ALFADATA_2) + PROD("ALF 2", SCSI, BSC_ALF_2_1) + PROD("ALF 2", SCSI, BSC_ALF_2_2) + PROD("ALF 3", SCSI, BSC_ALF_3_2) +END + +BEGIN_PROD(CARDCO_2) + PROD("Kronos", SCSI, CARDCO_KRONOS_2000_2) + PROD("A1000", SCSI, CARDCO_A1000_2) +END + +BEGIN_PROD(JOCHHEIM) + PROD(NULL, RAM, JOCHHEIM_RAM) +END + +BEGIN_PROD(CHECKPOINT_TECHNOLOGIES) + PROD("Serial Solution", SERIAL, CHECKPOINT_TECHNOLOGIES_SERIAL_SOLUTION) +END + +BEGIN_PROD(EDOTRONIK) + PROD("IEEE-488 Interface Board", UNKNOWN, EDOTRONIK_IEEE_488) + PROD("CBM-8032 Board", UNKNOWN, EDOTRONIK_8032) + PROD(NULL, SERIAL, EDOTRONIK_MULTISERIAL) + PROD("24Bit Realtime Video Digitizer", UNKNOWN, EDOTRONIK_VIDEODIGITIZER) + PROD("32Bit Parallel I/O Interface", UNKNOWN, EDOTRONIK_PARALLEL_IO) + PROD("PIC Prototyping Board", UNKNOWN, EDOTRONIK_PIC_PROTOYPING) + PROD("16 Channel ADC Interface", UNKNOWN, EDOTRONIK_ADC) + PROD("VME-Bus Controller", UNKNOWN, EDOTRONIK_VME) + PROD("DSP96000 Realtime Data Acquisition", DSP, EDOTRONIK_DSP96000) +END + +BEGIN_PROD(NES_INC) + PROD(NULL, RAM, NES_INC_RAM) +END + +BEGIN_PROD(ICD) + PROD("Advantage 2000", SCSI, ICD_ADVANTAGE_2000_SCSI) + PROD("Advantage", IDE, ICD_ADVANTAGE_2000_SCSI) + PROD("Advantage 2080", RAM, ICD_ADVANTAGE_2080_RAM) +END + +BEGIN_PROD(KUPKE_2) + PROD("Omti", HD, KUPKE_OMTI) + PROD("Golem SCSI-II", SCSI, KUPKE_SCSI_II) + PROD("Golem Box", UNKNOWN, KUPKE_GOLEM_BOX) + PROD("030/882", TURBO, KUPKE_030_882) + PROD("Golem", SCSI, KUPKE_SCSI_AT) +END + +BEGIN_PROD(GREAT_VALLEY_PRODUCTS_3) + PROD("A2000-RAM8/2", MISC, GVP_A2000_RAM8) + PROD("Impact Series II", RAM, GVP_IMPACT_SERIES_II_RAM_2) +END + +BEGIN_PROD(INTERWORKS_NETWORK) +END + +BEGIN_PROD(HARDITAL_SYNTHESIS) + PROD("TQM 68030+68882", TURBO, HARDITAL_SYNTHESIS_TQM_68030_68882) +END + +BEGIN_PROD(APPLIED_ENGINEERING) + PROD("DL2000", MODEM, APPLIED_ENGINEERING_DL2000) + PROD("RAM Works", RAM, APPLIED_ENGINEERING_RAM_WORKS) +END + +BEGIN_PROD(BSC_ALFADATA_3) + PROD("Oktagon 2008", SCSI, BSC_OKTAGON_2008) + PROD("Tandem AT-2008/508", IDE, BSC_TANDEM_AT_2008_508) + PROD("Alpha RAM 1200", RAM, BSC_ALFA_RAM_1200) + PROD("Oktagon 2008", RAM, BSC_OKTAGON_2008_RAM) + PROD("MultiFace I", MULTIIO, BSC_MULTIFACE_I) + PROD("MultiFace II", MULTIIO, BSC_MULTIFACE_II) + PROD("MultiFace III", MULTIIO, BSC_MULTIFACE_III) + PROD("Framebuffer", MISC, BSC_FRAMEBUFFER) + PROD("Graffiti", GFXRAM, BSC_GRAFFITI_RAM) + PROD("Graffiti", GFX, BSC_GRAFFITI_REG) + PROD("ISDN MasterCard", ISDN, BSC_ISDN_MASTERCARD) + PROD("ISDN MasterCard II", ISDN, BSC_ISDN_MASTERCARD_II) +END + +BEGIN_PROD(PHOENIX) + PROD("ST506", HD, PHOENIX_ST506) + PROD(NULL, SCSI, PHOENIX_SCSI) + PROD(NULL, RAM, PHOENIX_RAM) +END + +BEGIN_PROD(ADVANCED_STORAGE_SYSTEMS) + PROD("Nexus", SCSI, ADVANCED_STORAGE_SYSTEMS_NEXUS) + PROD("Nexus", RAM, ADVANCED_STORAGE_SYSTEMS_NEXUS_RAM) +END + +BEGIN_PROD(IMPULSE) + PROD("FireCracker 24", GFX, IMPULSE_FIRECRACKER_24) +END + +BEGIN_PROD(IVS) + PROD("GrandSlam PIC 2", RAM, IVS_GRANDSLAM_PIC_2) + PROD("GrandSlam PIC 1", RAM, IVS_GRANDSLAM_PIC_1) + PROD("OverDrive", HD, IVS_OVERDRIVE) + PROD("TrumpCard Classic", SCSI, IVS_TRUMPCARD_CLASSIC) + PROD("TrumpCard Pro/GrandSlam", SCSI, IVS_TRUMPCARD_PRO_GRANDSLAM) + PROD("Meta-4", RAM, IVS_META_4) + PROD("Wavetools", AUDIO, IVS_WAVETOOLS) + PROD("Vector", SCSI, IVS_VECTOR_1) + PROD("Vector", SCSI, IVS_VECTOR_2) +END + +BEGIN_PROD(VECTOR_1) + PROD("Connection", MULTIIO, VECTOR_CONNECTION_1) +END + +BEGIN_PROD(XPERT_PRODEV) + PROD("Visiona", GFXRAM, XPERT_PRODEV_VISIONA_RAM) + PROD("Visiona", GFX, XPERT_PRODEV_VISIONA_REG) + PROD("Merlin", GFXRAM, XPERT_PRODEV_MERLIN_RAM) + PROD("Merlin", GFX, XPERT_PRODEV_MERLIN_REG_1) + PROD("Merlin", GFX, XPERT_PRODEV_MERLIN_REG_2) +END + +BEGIN_PROD(HYDRA_SYSTEMS) + PROD("Amiganet", ETHERNET, HYDRA_SYSTEMS_AMIGANET) +END + +BEGIN_PROD(SUNRIZE_INDUSTRIES) + PROD("AD1012", AUDIO, SUNRIZE_INDUSTRIES_AD1012) + PROD("AD516", AUDIO, SUNRIZE_INDUSTRIES_AD516) + PROD("DD512", AUDIO, SUNRIZE_INDUSTRIES_DD512) +END + +BEGIN_PROD(TRICERATOPS) + PROD(NULL, MULTIIO, TRICERATOPS_MULTI_IO) +END + +BEGIN_PROD(APPLIED_MAGIC) + PROD("DMI Resolver", GFX, APPLIED_MAGIC_DMI_RESOLVER) + PROD("Digital Broadcaster", VIDEO, APPLIED_MAGIC_DIGITAL_BROADCASTER) +END + +BEGIN_PROD(GFX_BASE) + PROD("GDA-1 VRAM", GFX, GFX_BASE_GDA_1_VRAM) + PROD("GDA-1", GFX, GFX_BASE_GDA_1) +END + +BEGIN_PROD(ROCTEC) + PROD("RH 800C", HD, ROCTEC_RH_800C) + PROD("RH 800C", RAM, ROCTEC_RH_800C_RAM) +END + +BEGIN_PROD(KATO) + PROD("Melody MPEG", AUDIO, KATO_MELODY) + PROD("Rainbow II", GFX, HELFRICH_RAINBOW_II) /* ID clash!! */ + PROD("Rainbow III", GFX, HELFRICH_RAINBOW_III) /* ID clash!! */ +END + +BEGIN_PROD(ATLANTIS) +END + +BEGIN_PROD(PROTAR) +END + +BEGIN_PROD(ACS) +END + +BEGIN_PROD(SOFTWARE_RESULTS_ENTERPRISES) + PROD("Golden Gate 2 Bus+", BRIDGE, SOFTWARE_RESULTS_ENTERPRISES_GOLDEN_GATE_2_BUS_PLUS) +END + +BEGIN_PROD(MASOBOSHI) + PROD("MasterCard SC201", RAM, MASOBOSHI_MASTER_CARD_SC201) + PROD("MasterCard MC702", SCSI_IDE, MASOBOSHI_MASTER_CARD_MC702) + PROD("MVD 819", UNKNOWN, MASOBOSHI_MVD_819) +END + +BEGIN_PROD(MAINHATTAN_DATA) + PROD(NULL, IDE, MAINHATTAN_DATA_IDE) +END + +BEGIN_PROD(VILLAGE_TRONIC) + PROD("Domino", GFXRAM, VILLAGE_TRONIC_DOMINO_RAM) + PROD("Domino", GFX, VILLAGE_TRONIC_DOMINO_REG) + PROD("Domino 16M Prototype", GFX, VILLAGE_TRONIC_DOMINO_16M_PROTOTYPE) + PROD("Picasso II/II+", GFXRAM, VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM) + PROD("Picasso II/II+", GFX, VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG) + PROD("Picasso II/II+ (Segmented Mode)", GFX, VILLAGE_TRONIC_PICASSO_II_II_PLUS_SEGMENTED_MODE) + PROD("Picasso IV Z2", GFXRAM, VILLAGE_TRONIC_PICASSO_IV_Z2_MEM1) + PROD("Picasso IV Z2", GFXRAM, VILLAGE_TRONIC_PICASSO_IV_Z2_MEM2) + PROD("Picasso IV Z2", GFX, VILLAGE_TRONIC_PICASSO_IV_Z2_REG) + PROD("Picasso IV Z3", GFX, VILLAGE_TRONIC_PICASSO_IV_Z3) + PROD("Ariadne", ETHERNET_PARALLEL, VILLAGE_TRONIC_ARIADNE) +END + +BEGIN_PROD(UTILITIES_UNLIMITED) + PROD("Emplant Deluxe", MACEMU, UTILITIES_UNLIMITED_EMPLANT_DELUXE) + PROD("Emplant Deluxe", MACEMU, UTILITIES_UNLIMITED_EMPLANT_DELUXE2) +END + +BEGIN_PROD(AMITRIX) + PROD(NULL, MULTIIO, AMITRIX_MULTI_IO) + PROD("CD-RAM", RAM, AMITRIX_CD_RAM) +END + +BEGIN_PROD(ARMAX) + PROD("OmniBus", GFX, ARMAX_OMNIBUS) +END + +BEGIN_PROD(ZEUS) + PROD("Spider", VIDEO, ZEUS_SPIDER) +END + +BEGIN_PROD(NEWTEK) + PROD("VideoToaster", VIDEO, NEWTEK_VIDEOTOASTER) +END + +BEGIN_PROD(M_TECH_GERMANY) + PROD("AT500", IDE, MTEC_AT500_2) + PROD("68030", TURBO, MTEC_68030) + PROD("68020i", TURBO, MTEC_68020I) + PROD("A1200 T68030 RTC", TURBO, MTEC_A1200_T68030_RTC) + PROD("Viper Mk V/E-Matrix 530", TURBO_RAM, MTEC_VIPER_MK_V_E_MATRIX_530) + PROD("8MB", RAM, MTEC_8_MB_RAM) + PROD("Viper Mk V/E-Matrix 530 SCSI/IDE", SCSI_IDE, MTEC_VIPER_MK_V_E_MATRIX_530_SCSI_IDE) +END + +BEGIN_PROD(GREAT_VALLEY_PRODUCTS_4) + PROD("EGS 28/24 Spectrum", GFX, GVP_EGS_28_24_SPECTRUM_REG) + PROD("EGS 28/24 Spectrum", GFXRAM, GVP_EGS_28_24_SPECTRUM_RAM) +END + +BEGIN_PROD(APOLLO_1) + PROD("A1200", FPU_RAM, APOLLO_A1200) +END + +BEGIN_PROD(HELFRICH_2) + PROD("Piccolo", GFXRAM, HELFRICH_PICCOLO_RAM) + PROD("Piccolo", GFX, HELFRICH_PICCOLO_REG) + PROD("PeggyPlus MPEG", VIDEO, HELFRICH_PEGGY_PLUS_MPEG) + PROD("VideoCruncher", VIDEO, HELFRICH_VIDEOCRUNCHER) + PROD("Piccolo SD64", GFXRAM, HELFRICH_SD64_RAM) + PROD("Piccolo SD64", GFX, HELFRICH_SD64_REG) +END + +BEGIN_PROD(MACROSYSTEMS_USA) + PROD("Warp Engine 40xx", TURBO_SCSI_RAM, MACROSYSTEMS_WARP_ENGINE_40xx) +END + +BEGIN_PROD(ELBOX_COMPUTER) + PROD("1200/4", RAM, ELBOX_COMPUTER_1200_4) +END + +BEGIN_PROD(HARMS_PROFESSIONAL) + PROD("030 Plus", TURBO, HARMS_PROFESSIONAL_030_PLUS) + PROD("3500 Professional", TURBO_RAM, HARMS_PROFESSIONAL_3500) +END + +BEGIN_PROD(MICRONIK) + PROD("RCA 120", RAM, MICRONIK_RCA_120) +END + +BEGIN_PROD(MICRONIK2) + PROD("Z3i A1200 Zorro III + SCSI", SCSI, MICRONIK2_Z3I) +END + +BEGIN_PROD(MEGAMICRO) + PROD("SCRAM 500", SCSI, MEGAMICRO_SCRAM_500) + PROD("SCRAM 500", RAM, MEGAMICRO_SCRAM_500_RAM) +END + +BEGIN_PROD(IMTRONICS_2) + PROD("Hurricane 2800", TURBO_RAM, IMTRONICS_HURRICANE_2800_3) + PROD("Hurricane 2800", TURBO_RAM, IMTRONICS_HURRICANE_2800_4) +END + +BEGIN_PROD(INDIVIDUAL_COMPUTERS) + PROD("Buddha", IDE, INDIVIDUAL_COMPUTERS_BUDDHA) + PROD("Catweasel", IDE_FLOPPY, INDIVIDUAL_COMPUTERS_CATWEASEL) +END + +BEGIN_PROD(KUPKE_3) + PROD("Golem HD 3000", HD, KUPKE_GOLEM_HD_3000) +END + +BEGIN_PROD(ITH) + PROD("ISDN-Master II", ISDN, ITH_ISDN_MASTER_II) +END + +BEGIN_PROD(VMC) + PROD("ISDN Blaster Z2", ISDN, VMC_ISDN_BLASTER_Z2) + PROD("HyperCom 4", MULTIIO, VMC_HYPERCOM_4) +END + +BEGIN_PROD(INFORMATION) + PROD("ISDN Engine I", ISDN, INFORMATION_ISDN_ENGINE_I) +END + +BEGIN_PROD(VORTEX) + PROD("Golden Gate 80386SX", BRIDGE, VORTEX_GOLDEN_GATE_80386SX) + PROD("Golden Gate", RAM, VORTEX_GOLDEN_GATE_RAM) + PROD("Golden Gate 80486", BRIDGE, VORTEX_GOLDEN_GATE_80486) +END + +BEGIN_PROD(EXPANSION_SYSTEMS) + PROD("DataFlyer 4000SX", SCSI, EXPANSION_SYSTEMS_DATAFLYER_4000SX) + PROD("DataFlyer 4000SX", RAM, EXPANSION_SYSTEMS_DATAFLYER_4000SX_RAM) +END + +BEGIN_PROD(READYSOFT) + PROD("AMax II/IV", MACEMU, READYSOFT_AMAX_II_IV) +END + +BEGIN_PROD(PHASE5) + PROD("Blizzard", RAM, PHASE5_BLIZZARD_RAM) + PROD("Blizzard", TURBO, PHASE5_BLIZZARD) + PROD("Blizzard 1220-IV", TURBO, PHASE5_BLIZZARD_1220_IV) + PROD("FastLane Z3", RAM, PHASE5_FASTLANE_Z3_RAM) + PROD("Blizzard 1230-II/Fastlane Z3/CyberSCSI/CyberStorm060", TURBO_SCSI, PHASE5_BLIZZARD_1230_II_FASTLANE_Z3_CYBERSCSI_CYBERSTORM060) + PROD("Blizzard 1220/CyberStorm", TURBO_SCSI, PHASE5_BLIZZARD_1220_CYBERSTORM) + PROD("Blizzard 1230", TURBO, PHASE5_BLIZZARD_1230) + PROD("Blizzard 1230-IV/1260", TURBO, PHASE5_BLIZZARD_1230_IV_1260) + PROD("Blizzard 2060", TURBO, PHASE5_BLIZZARD_2060) + PROD("CyberStorm Mk II", FLASHROM, PHASE5_CYBERSTORM_MK_II) + PROD("CyberVision64", GFX, PHASE5_CYBERVISION64) + PROD("CyberVision64-3D Prototype", GFX, PHASE5_CYBERVISION64_3D_PROTOTYPE) + PROD("CyberVision64-3D", GFX, PHASE5_CYBERVISION64_3D) + PROD("CyberStorm Mk III", TURBO_SCSI, PHASE5_CYBERSTORM_MK_III) + PROD("Blizzard 603e+", TURBO_SCSI, PHASE5_BLIZZARD_603E_PLUS) +END + +BEGIN_PROD(DPS) + PROD("Personal Animation Recorder", VIDEO, DPS_PERSONAL_ANIMATION_RECORDER) +END + +BEGIN_PROD(APOLLO_2) + PROD("A620 68020", TURBO, APOLLO_A620_68020_1) + PROD("A620 68020", TURBO, APOLLO_A620_68020_2) +END + +BEGIN_PROD(APOLLO_3) + PROD("AT-Apollo", UNKNOWN, APOLLO_AT_APOLLO) + PROD("1230/1240/1260/2030/4040/4060", TURBO, APOLLO_1230_1240_1260_2030_4040_4060) +END + +BEGIN_PROD(PETSOFF_LP) + PROD("Delfina", AUDIO, PETSOFF_LP_DELFINA) + PROD("Delfina Lite", AUDIO, PETSOFF_LP_DELFINA_LITE) +END + +BEGIN_PROD(UWE_GERLACH) + PROD("RAM/ROM", MISC, UWE_GERLACH_RAM_ROM) +END + +BEGIN_PROD(ACT) + PROD("Prelude", AUDIO, ACT_PRELUDE) +END + +BEGIN_PROD(MACROSYSTEMS_GERMANY) + PROD("Maestro", AUDIO, MACROSYSTEMS_MAESTRO) + PROD("VLab", VIDEO, MACROSYSTEMS_VLAB) + PROD("Maestro Pro", AUDIO, MACROSYSTEMS_MAESTRO_PRO) + PROD("Retina", GFX, MACROSYSTEMS_RETINA) + PROD("MultiEvolution", SCSI, MACROSYSTEMS_MULTI_EVOLUTION) + PROD("Toccata", AUDIO, MACROSYSTEMS_TOCCATA) + PROD("Retina Z3", GFX, MACROSYSTEMS_RETINA_Z3) + PROD("VLab Motion", VIDEO, MACROSYSTEMS_VLAB_MOTION) + PROD("Altais", GFX, MACROSYSTEMS_ALTAIS) + PROD("Falcon '040", TURBO, MACROSYSTEMS_FALCON_040) +END + +BEGIN_PROD(COMBITEC) +END + +BEGIN_PROD(SKI_PERIPHERALS) + PROD("MAST Fireball", SCSI, SKI_PERIPHERALS_MAST_FIREBALL) + PROD("SCSI/Dual Serial", SCSI_SERIAL, SKI_PERIPHERALS_SCSI_DUAL_SERIAL) +END + +BEGIN_PROD(REIS_WARE_2) + PROD("Scan King", SCANNER, REIS_WARE_SCAN_KING) +END + +BEGIN_PROD(CAMERON) + PROD("Personal A4", SCANNER, CAMERON_PERSONAL_A4) +END + +BEGIN_PROD(REIS_WARE) + PROD("Handyscanner", SCANNER, REIS_WARE_HANDYSCANNER) +END + +BEGIN_PROD(PHOENIX_2) + PROD("ST506", HD, PHOENIX_ST506_2) + PROD(NULL, SCSI, PHOENIX_SCSI_2) + PROD(NULL, RAM, PHOENIX_RAM_2) +END + +BEGIN_PROD(COMBITEC_2) + PROD(NULL, HD, COMBITEC_HD) + PROD("SRAM", RAM, COMBITEC_SRAM) +END + +BEGIN_PROD(HACKER) /* Unused */ +END + + +BEGIN_MANUF + MANUF("Pacific Peripherals", PACIFIC_PERIPHERALS) + MANUF("MacroSystems USA", MACROSYSTEMS_USA_2) + MANUF("Kupke", KUPKE_1) + MANUF("Memphis", MEMPHIS) + MANUF("3-State", 3_STATE) + MANUF("Commodore Braunschweig", COMMODORE_BRAUNSCHWEIG) + MANUF("Commodore West Chester", COMMODORE_WEST_CHESTER_1) + MANUF("Commodore West Chester", COMMODORE_WEST_CHESTER_2) + MANUF("Progressive Peripherals & Systems", PROGRESSIVE_PERIPHERALS_AND_SYSTEMS_2) + MANUF("Kolff Computer Supplies", KOLFF_COMPUTER_SUPPLIES) + MANUF("Cardco Ltd.", CARDCO_1) + MANUF("A-Squared", A_SQUARED) + MANUF("Comspec Communications", COMSPEC_COMMUNICATIONS) + MANUF("Anakin Research", ANAKIN_RESEARCH) + MANUF("Microbotics", MICROBOTICS) + MANUF("Access Associates Alegra", ACCESS_ASSOCIATES_ALEGRA) + MANUF("Expansion Technologies (Pacific Cypress)", EXPANSION_TECHNOLOGIES) + MANUF("ASDG", ASDG) + MANUF("Ronin/Imtronics", IMTRONICS_1) + MANUF("Commodore/University of Lowell", CBM_UNIVERSITY_OF_LOWELL) + MANUF("Ameristar", AMERISTAR) + MANUF("Supra", SUPRA) + MANUF("Computer Systems Assosiates", COMPUTER_SYSTEMS_ASSOCIATES) + MANUF("Marc Michael Groth", MARC_MICHAEL_GROTH) + MANUF("M-Tech", M_TECH) + MANUF("Great Valley Products", GREAT_VALLEY_PRODUCTS_1) + MANUF("ByteBox", BYTEBOX) + MANUF("DKB/Power Computing", DKB_POWER_COMPUTING) + MANUF("Great Valley Products", GREAT_VALLEY_PRODUCTS_2) + MANUF("California Access (Synergy)", CALIFORNIA_ACCESS_SYNERGY) + MANUF("Xetec", XETEC) + MANUF("Progressive Peripherals & Systems", PROGRESSIVE_PERIPHERALS_AND_SYSTEMS) + MANUF("Xebec", XEBEC) + MANUF("Spirit Technology", SPIRIT_TECHNOLOGY) + MANUF("Spirit Technology", SPIRIT_TECHNOLOGY_2) + MANUF("BSC/Alfadata", BSC_ALFADATA_1) + MANUF("BSC/Alfadata", BSC_ALFADATA_2) + MANUF("Cardco Ltd.", CARDCO_2) + MANUF("Jochheim", JOCHHEIM) + MANUF("Checkpoint Technologies", CHECKPOINT_TECHNOLOGIES) + MANUF("Edotronik", EDOTRONIK) + MANUF("NES Inc.", NES_INC) + MANUF("ICD", ICD) + MANUF("Kupke", KUPKE_2) + MANUF("Great Valley Products", GREAT_VALLEY_PRODUCTS_3) + MANUF("Interworks Network", INTERWORKS_NETWORK) + MANUF("Hardital Synthesis", HARDITAL_SYNTHESIS) + MANUF("Applied Engineering", APPLIED_ENGINEERING) + MANUF("BSC/Alfadata", BSC_ALFADATA_3) + MANUF("Phoenix", PHOENIX) + MANUF("Advanced Storage Systems", ADVANCED_STORAGE_SYSTEMS) + MANUF("Impulse", IMPULSE) + MANUF("IVS", IVS) + MANUF("Vector", VECTOR_1) + MANUF("XPert ProDev", XPERT_PRODEV) + MANUF("Hydra Systems", HYDRA_SYSTEMS) + MANUF("Sunrize Industries", SUNRIZE_INDUSTRIES) + MANUF("Triceratops", TRICERATOPS) + MANUF("Applied Magic Inc.", APPLIED_MAGIC) + MANUF("GFX-Base", GFX_BASE) + MANUF("RocTec", ROCTEC) + MANUF("Kato", KATO) + MANUF("Atlantis", ATLANTIS) + MANUF("Protar", PROTAR) + MANUF("ACS", ACS) + MANUF("Software Results Enterprises", SOFTWARE_RESULTS_ENTERPRISES) + MANUF("Masoboshi", MASOBOSHI) + MANUF("Mainhattan-Data (A-Team)", MAINHATTAN_DATA) + MANUF("Village Tronic", VILLAGE_TRONIC) + MANUF("Utilities Unlimited", UTILITIES_UNLIMITED) + MANUF("Amitrix", AMITRIX) + MANUF("ArMax", ARMAX) + MANUF("ZEUS Electronic Development", ZEUS) + MANUF("NewTek", NEWTEK) + MANUF("M-Tech Germany", M_TECH_GERMANY) + MANUF("Great Valley Products", GREAT_VALLEY_PRODUCTS_4) + MANUF("Apollo", APOLLO_1) + MANUF("Ingenieurbüro Helfrich", HELFRICH_2) + MANUF("MacroSystems USA", MACROSYSTEMS_USA) + MANUF("ElBox Computer", ELBOX_COMPUTER) + MANUF("Harms Professional", HARMS_PROFESSIONAL) + MANUF("Micronik", MICRONIK) + MANUF("Micronik", MICRONIK2) + MANUF("MegaMicro", MEGAMICRO) + MANUF("Ronin/Imtronics", IMTRONICS_2) + MANUF("Individual Computers", INDIVIDUAL_COMPUTERS) + MANUF("Kupke", KUPKE_3) + MANUF("ITH", ITH) + MANUF("VMC", VMC) + MANUF("Information", INFORMATION) + MANUF("Vortex", VORTEX) + MANUF("Expansion Systems", EXPANSION_SYSTEMS) + MANUF("ReadySoft", READYSOFT) + MANUF("Phase 5", PHASE5) + MANUF("DPS", DPS) + MANUF("Apollo", APOLLO_2) + MANUF("Apollo", APOLLO_3) + MANUF("Petsoff LP", PETSOFF_LP) + MANUF("Uwe Gerlach", UWE_GERLACH) + MANUF("ACT", ACT) + MANUF("MacroSystems Germany", MACROSYSTEMS_GERMANY) + MANUF("Combitec", COMBITEC) + MANUF("SKI Peripherals", SKI_PERIPHERALS) + MANUF("Reis-Ware", REIS_WARE_2) + MANUF("Cameron", CAMERON) + MANUF("Reis-Ware", REIS_WARE) + MANUF("Hacker Test Board", HACKER) /* Unused */ + MANUF("Phoenix", PHOENIX_2) + MANUF("Combitec", COMBITEC_2) +END + +#define NUM_MANUF (ARRAYSIZE(Manufacturers)) +#define NUM_GVP_PROD (ARRAYSIZE(Ext_Prod_GVP)) + + + /* + * Zorro product classes + * + * Make sure to keep these in sync with include/linux/zorro.h! + */ + +static const char *classnames[] = { + NULL, /* ZORRO_CLASS_UNKNOWN */ + "ArcNet Card", /* ZORRO_CLASS_ARCNET */ + "Audio Board", /* ZORRO_CLASS_AUDIO */ + "ISA Bus Bridge", /* ZORRO_CLASS_BRIDGE */ + "DSP Board", /* ZORRO_CLASS_DSP */ + "Ethernet Card", /* ZORRO_CLASS_ETHERNET */ + "Ethernet Card and Parallel Ports", /* ZORRO_CLASS_ETHERNET_PARALLEL */ + "Flash ROM", /* ZORRO_CLASS_FLASHROM */ + "FPU and RAM Expansion", /* ZORRO_CLASS_FPU_RAM */ + "Graphics Board", /* ZORRO_CLASS_GFX */ + "Graphics Board (RAM)", /* ZORRO_CLASS_GFXRAM */ + "HD Controller", /* ZORRO_CLASS_HD */ + "HD Controller and RAM Expansion", /* ZORRO_CLASS_HD_RAM */ + "IDE Interface", /* ZORRO_CLASS_IDE */ + "IDE Interface and RAM Expansion", /* ZORRO_CLASS_IDE_RAM */ + "IDE Interface and Floppy Controller", /* ZORRO_CLASS_IDE_FLOPPY */ + "ISDN Interface", /* ZORRO_CLASS_ISDN */ + "Macintosh Emulator", /* ZORRO_CLASS_MACEMU */ + "Miscellaneous Expansion Card", /* ZORRO_CLASS_MISC */ + "Modem", /* ZORRO_CLASS_MODEM */ + "Multi I/O", /* ZORRO_CLASS_MULTIIO */ + "RAM Expansion", /* ZORRO_CLASS_RAM */ + "Scanner Interface", /* ZORRO_CLASS_SCANNER */ + "SCSI Host Adapter", /* ZORRO_CLASS_SCSI */ + "SCSI Host Adapter and IDE Interface", /* ZORRO_CLASS_SCSI_IDE */ + "SCSI Host Adapter and RAM Expansion", /* ZORRO_CLASS_SCSI_RAM */ + "SCSI Host Adapter and Serial Card", /* ZORRO_CLASS_SCSI_SERIAL */ + "Multi Serial", /* ZORRO_CLASS_SERIAL */ + "Drawing Tablet Interface", /* ZORRO_CLASS_TABLET */ + "Accelerator", /* ZORRO_CLASS_TURBO */ + "Accelerator and RAM Expansion", /* ZORRO_CLASS_TURBO_RAM */ + "Accelerator and HD Controller", /* ZORRO_CLASS_TURBO_HD */ + "Accelerator and IDE Interface", /* ZORRO_CLASS_TURBO_IDE */ + "Accelerator and SCSI Host Adapter", /* ZORRO_CLASS_TURBO_SCSI */ + "Accelerator, SCSI Host Adapter and RAM Expansion", /* ZORRO_CLASS_TURBO_SCSI */ + "Video Board", /* ZORRO_CLASS_VIDEO */ +}; + +static inline const char *get_class_name(enum Zorro_Classes class) +{ + if (class < ARRAYSIZE(classnames)) + return(classnames[class]); + else + return("(**Illegal**)"); +} + +#endif /* CONFIG_ZORRO */ + + + /* + * Expansion Devices + */ + +u_int zorro_num_autocon; +struct ConfigDev zorro_autocon[ZORRO_NUM_AUTO]; +static u32 BoardPartFlags[ZORRO_NUM_AUTO] = { 0, }; + + + /* + * Find the key for the next unconfigured expansion device of a specific + * type. + * + * Part is a device specific number (0 <= part <= 31) to allow for the + * independent configuration of independent parts of an expansion board. + * Thanks to Jes Soerensen for this idea! + * + * Index is used to specify the first board in the autocon list + * to be tested. It was inserted in order to solve the problem + * with the GVP boards that uses the same product code, but + * it should help if there are other companies which use the same + * method as GVP. Drivers for boards which are not using this + * method do not need to think of this - just set index = 0. + * + * Example: + * + * while ((key = zorro_find(ZORRO_PROD_MY_BOARD, MY_PART, 0))) { + * cd = zorro_get_board(key); + * initialise_this_board; + * zorro_config_board(key, MY_PART); + * } + */ + +u_int zorro_find(zorro_id id, u_int part, u_int index) +{ + u_int manuf = ZORRO_MANUF(id); + u_int prod = ZORRO_PROD(id); + u_int epc = ZORRO_EPC(id); + u_int key; + const struct ConfigDev *cd; + u_long addr; + + if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(ZORRO)) + return(0); + + if (part > 31) { + printk("zorro_find: bad part %d\n", part); + return(0); + } + + for (key = index + 1; key <= zorro_num_autocon; key++) { + cd = &zorro_autocon[key-1]; + addr = (u_long)cd->cd_BoardAddr; + if ((cd->cd_Rom.er_Manufacturer == manuf) && + (cd->cd_Rom.er_Product == prod) && + !(BoardPartFlags[key-1] & (1< zorro_num_autocon)) + printk("zorro_get_board: bad key %d\n", key); + else + cd = &zorro_autocon[key-1]; + + return(cd); +} + + + /* + * Mark a part of a board as configured + */ + +void zorro_config_board(u_int key, u_int part) +{ + if ((key < 1) || (key > zorro_num_autocon)) + printk("zorro_config_board: bad key %d\n", key); + else if (part > 31) + printk("zorro_config_board: bad part %d\n", part); + else if (BoardPartFlags[key-1] & (1< zorro_num_autocon)) + printk("zorro_unconfig_board: bad key %d\n", key); + else if (part > 31) + printk("zorro_unconfig_board: bad part %d\n", part); + else if (!(BoardPartFlags[key-1] & (1<cd_Rom.er_Manufacturer; + u_int prod = cd->cd_Rom.er_Product; + u_int class = ZORRO_CLASS_UNKNOWN; + u_int epc = 0; + const char *manufname = "Unknown"; + const char *prodname = "Unknown"; + const char *classname; + u_int i, j, k, len = 0; + u_long addr = (u_long)cd->cd_BoardAddr; + u_long size = cd->cd_BoardSize; + char mag; + int identified = 0, gvp = 0; + + if (manuf != ZORRO_MANUF(ZORRO_PROD_GVP_EPC_BASE) || + prod != ZORRO_PROD(ZORRO_PROD_GVP_EPC_BASE)) { + for (i = 0; i < NUM_MANUF; i++) + if (Manufacturers[i].Manuf == manuf) { + manufname = Manufacturers[i].Name; + for (j = 0; j < Manufacturers[i].NumProd; j++) + if (Manufacturers[i].Products[j].Prod == prod) { + prodname = Manufacturers[i].Products[j].Name; + class = Manufacturers[i].Products[j].Class; + identified = 1; + break; + } + } + /* Put workarounds for ID clashes here */ + if (manuf == ZORRO_MANUF(ZORRO_PROD_HELFRICH_RAINBOW_III) && + prod == ZORRO_PROD(ZORRO_PROD_HELFRICH_RAINBOW_III)) + manufname = "Ingenieurbüro Helfrich"; + } else { + manufname = "Great Valley Products"; + gvp = 1; + epc = *(u_short *)ZTWO_VADDR(addr+0x8000) & GVP_PRODMASK; + for (k = 0; k < NUM_GVP_PROD; k++) + if (epc == Ext_Prod_GVP[k].EPC) { + prodname = Ext_Prod_GVP[k].Name; + class = Ext_Prod_GVP[k].Class; + identified = 1; + break; + } + } + classname = get_class_name(class); + if (size & 0xfffff) { + size >>= 10; + mag = 'K'; + } else { + size >>= 20; + mag = 'M'; + } + if (verbose) { + const char *zorro; + int is_mem = cd->cd_Rom.er_Type & ERTF_MEMLIST; + switch (cd->cd_Rom.er_Type & ERT_TYPEMASK) { + case ERT_ZORROII: + zorro = "Zorro II"; + break; + case ERT_ZORROIII: + zorro = "Zorro III"; + break; + default: + zorro = "Unknown Zorro"; + break; + } + if (!prodname) + prodname = "Unknown"; + if (!classname) + classname = "Unknown"; + len = sprintf(buf, " Device %d at 0x%08lx: ID=%04x:%02x", devnum, + addr, manuf, prod); + if (gvp) + len += sprintf(buf+len, ":%02x", epc); + len += sprintf(buf+len, ", %s, %ld%c", zorro, size, mag); + if (is_mem) + len += sprintf(buf+len, ", System RAM"); + else + len += sprintf(buf+len, ", Configured=%08x", configured); + len += sprintf(buf+len, "\n" + " Manufacturer: %s\n" + " Product Name: %s\n" + " Board Class : %s\n", + manufname, prodname, classname); + } else { + len = sprintf(buf, " %c%08lx: ", configured ? '*' : ' ', addr); + if (identified) { + len += sprintf(buf+len, "%s", manufname); + if (prodname) + len += sprintf(buf+len, " %s", prodname); + if (classname) + len += sprintf(buf+len, " %s", classname); + } else if (manuf == ZORRO_MANUF_HACKER) + len += sprintf(buf+len, "Hacker Test Board %02x", prod); + else if (gvp) + len += sprintf(buf+len, "[%04x:%02x:%02x] made by %s", manuf, prod, + epc, manufname); + else + len += sprintf(buf+len, "[%04x:%02x] made by %s", manuf, prod, + manufname); + len += sprintf(buf+len, " (%ld%c)\n", size, mag); + if (!identified && manuf != ZORRO_MANUF_HACKER) + len += sprintf(buf+len, " Please report this unknown device to " + "zorro@linux-m68k.org\n"); + } + return(len); +} + + + /* + * Identify all known AutoConfig Expansion Devices + */ + +void zorro_identify(void) +{ + u_int i; + char tmp[256]; + + if (!AMIGAHW_PRESENT(ZORRO)) + return; + + printk("Probing AutoConfig expansion device(s):\n"); + for (i = 0; i < zorro_num_autocon; i++) { + identify(i, tmp, 0); + printk(tmp); + } + if (!zorro_num_autocon) + printk("No AutoConfig expansion devices present.\n"); +} + + + /* + * Get the list of all AutoConfig Expansion Devices + */ + +int zorro_get_list(char *buffer) +{ + u_int i, len = 0, len2; + char tmp[256]; + + if (MACH_IS_AMIGA && AMIGAHW_PRESENT(ZORRO)) { + len = sprintf(buffer, "AutoConfig expansion devices:\n"); + for (i = 0; i < zorro_num_autocon; i++) { + len2 = identify(i, tmp, 1); + if (len+len2 >= 4075) { + len += sprintf(buffer+len, "4K limit reached!\n"); + break; + } + strcpy(buffer+len, tmp); + len += len2; + } + } + return(len); +} + +#endif /* CONFIG_ZORRO */ + + + /* + * Bitmask indicating portions of available Zorro II RAM that are unused + * by the system. Every bit represents a 64K chunk, for a maximum of 8MB + * (128 chunks, physical 0x00200000-0x009fffff). + * + * If you want to use (= allocate) portions of this RAM, you should clear + * the corresponding bits. + * + * Possible uses: + * - z2ram device + * - SCSI DMA bounce buffers + */ + +u32 zorro_unused_z2ram[4] = { 0, 0, 0, 0 }; + + +static void mark_region(u_long addr, u_long size, int flag) +{ + u_long start, end, chunk; + + if (flag) { + start = (addr+Z2RAM_CHUNKMASK) & ~Z2RAM_CHUNKMASK; + end = (addr+size) & ~Z2RAM_CHUNKMASK; + } else { + start = addr & ~Z2RAM_CHUNKMASK; + end = (addr+size+Z2RAM_CHUNKMASK) & ~Z2RAM_CHUNKMASK; + } + if (end <= Z2RAM_START || start >= Z2RAM_END) + return; + start = start < Z2RAM_START ? 0x00000000 : start-Z2RAM_START; + end = end > Z2RAM_END ? Z2RAM_SIZE : end-Z2RAM_START; + while (start < end) { + chunk = start>>Z2RAM_CHUNKSHIFT; + if (flag) + set_bit( chunk, zorro_unused_z2ram ); + else + clear_bit( chunk, zorro_unused_z2ram ); + start += Z2RAM_CHUNKSIZE; + } +} + + + /* + * Initialization + */ + +void zorro_init(void) +{ + u_int i; + const struct ConfigDev *cd; + + if (!AMIGAHW_PRESENT(ZORRO)) + return; + + /* Mark all available Zorro II memory */ + for (i = 0; i < zorro_num_autocon; i++) { + cd = &zorro_autocon[i]; + if (cd->cd_Rom.er_Type & ERTF_MEMLIST) + mark_region((u_long)cd->cd_BoardAddr, cd->cd_BoardSize, 1); + } + + /* Unmark all used Zorro II memory */ + for (i = 0; i < m68k_num_memory; i++) + mark_region(m68k_memory[i].addr, m68k_memory[i].size, 0); +} diff -u --recursive --new-file v2.1.105/linux/fs/binfmt_aout.c linux/fs/binfmt_aout.c --- v2.1.105/linux/fs/binfmt_aout.c Thu Apr 23 20:21:35 1998 +++ linux/fs/binfmt_aout.c Sat Jun 13 12:10:31 1998 @@ -129,7 +129,7 @@ if (get_write_access(inode)) goto end_coredump; if (init_private_file(&file, dentry, 3)) - goto end_coredump; + goto end_coredump_write; if (!file.f_op->write) goto close_coredump; has_dumped = 1; @@ -213,6 +213,7 @@ close_coredump: if (file.f_op->release) file.f_op->release(inode,&file); +end_coredump_write: put_write_access(inode); end_coredump: set_fs(fs); diff -u --recursive --new-file v2.1.105/linux/fs/devpts/inode.c linux/fs/devpts/inode.c --- v2.1.105/linux/fs/devpts/inode.c Mon Apr 6 17:41:00 1998 +++ linux/fs/devpts/inode.c Sat Jun 13 13:25:12 1998 @@ -28,15 +28,6 @@ static struct super_block *mounts = NULL; -static void devpts_put_inode(struct inode *inode) -{ -} - -static void devpts_delete_inode(struct inode *inode) -{ - inode->i_size = 0; -} - static void devpts_put_super(struct super_block *sb) { struct devpts_sb_info *sbi = SBI(sb); @@ -48,6 +39,7 @@ if ( inode->i_count != 1 ) printk("devpts_put_super: badness: entry %d count %d\n", i, inode->i_count); + inode->i_nlink--; iput(inode); } } @@ -70,8 +62,8 @@ static struct super_operations devpts_sops = { devpts_read_inode, devpts_write_inode, - devpts_put_inode, - devpts_delete_inode, + NULL, /* put_inode */ + NULL, /* delete_inode */ NULL, /* notify_change */ devpts_put_super, NULL, /* write_super */ @@ -281,8 +273,6 @@ if ( ino >= NR_PTYS ) return; /* Bogus */ - inode->i_nlink = 1; - inode->i_mode = S_IFCHR; inode->i_rdev = MKDEV(0,0); /* Gets filled in by devpts_pty_new() */ @@ -322,6 +312,7 @@ inode->i_gid = sbi->setgid ? sbi->gid : current->fsgid; inode->i_mode = sbi->mode | S_IFCHR; inode->i_rdev = device; + inode->i_nlink++; sbi->inodes[number] = inode; } } @@ -340,7 +331,7 @@ if ( inode ) { sbi->inodes[number] = NULL; - inode->i_nlink = 0; /* Is this right? */ + inode->i_nlink--; iput(inode); } } diff -u --recursive --new-file v2.1.105/linux/fs/filesystems.c linux/fs/filesystems.c --- v2.1.105/linux/fs/filesystems.c Thu May 14 19:47:43 1998 +++ linux/fs/filesystems.c Sat Jun 13 13:33:24 1998 @@ -144,6 +144,10 @@ init_adfs_fs(); #endif +#ifdef CONFIG_ADFS_FS + init_adfs_fs(); +#endif + #ifdef CONFIG_DEVPTS_FS init_devpts_fs(); #endif diff -u --recursive --new-file v2.1.105/linux/fs/isofs/dir.c linux/fs/isofs/dir.c --- v2.1.105/linux/fs/isofs/dir.c Tue Mar 10 10:03:34 1998 +++ linux/fs/isofs/dir.c Sat Jun 13 13:39:15 1998 @@ -91,6 +91,32 @@ return i; } +/* Acorn extensions written by Matthew Wilcox 1998 */ +int get_acorn_filename(struct iso_directory_record * de, + char * retname, struct inode * inode) +{ + int std; + unsigned char * chr; + int retnamlen = isofs_name_translate(de->name, + de->name_len[0], retname); + if (retnamlen == 0) return 0; + std = sizeof(struct iso_directory_record) + de->name_len[0]; + if (std & 1) std++; + if ((*((unsigned char *) de) - std) != 32) return retnamlen; + chr = ((unsigned char *) de) + std; + if (strncmp(chr, "ARCHIMEDES", 10)) return retnamlen; + if ((*retname == '_') && ((chr[19] & 1) == 1)) *retname = '!'; + if (((de->flags[0] & 2) == 0) && (chr[13] == 0xff) + && ((chr[12] & 0xf0) == 0xf0)) + { + retname[retnamlen] = ','; + sprintf(retname+retnamlen+1, "%3.3x", + ((chr[12] & 0xf) << 8) | chr[11]); + retnamlen += 4; + } + return retnamlen; +} + /* * This should _really_ be cleaned up some day.. */ @@ -230,15 +256,17 @@ p = tmpname; } else #endif - { - if (inode->i_sb->u.isofs_sb.s_mapping == 'n') { - len = isofs_name_translate(de->name, de->name_len[0], - tmpname); - p = tmpname; - } else { - p = de->name; - len = de->name_len[0]; - } + if (inode->i_sb->u.isofs_sb.s_mapping == 'a') { + len = get_acorn_filename(de, tmpname, inode); + p = tmpname; + } else + if (inode->i_sb->u.isofs_sb.s_mapping == 'n') { + len = isofs_name_translate(de->name, + de->name_len[0], tmpname); + p = tmpname; + } else { + p = de->name; + len = de->name_len[0]; } } if (len > 0) { diff -u --recursive --new-file v2.1.105/linux/fs/isofs/inode.c linux/fs/isofs/inode.c --- v2.1.105/linux/fs/isofs/inode.c Thu May 14 19:47:43 1998 +++ linux/fs/isofs/inode.c Sat Jun 13 13:39:16 1998 @@ -90,7 +90,7 @@ { char *this_char,*value; - popt->map = 'n'; + popt->map = 'a'; popt->rock = 'y'; popt->joliet = 'y'; popt->cruft = 'n'; @@ -141,10 +141,11 @@ } else #endif if (!strcmp(this_char,"map") && value) { - if (value[0] && !value[1] && strchr("on",*value)) + if (value[0] && !value[1] && strchr("ano",*value)) popt->map = *value; else if (!strcmp(value,"off")) popt->map = 'o'; else if (!strcmp(value,"normal")) popt->map = 'n'; + else if (!strcmp(value,"acorn")) popt->map = 'a'; else return 0; } else if (!strcmp(this_char,"check") && value) { diff -u --recursive --new-file v2.1.105/linux/fs/isofs/namei.c linux/fs/isofs/namei.c --- v2.1.105/linux/fs/isofs/namei.c Wed Dec 3 04:24:29 1997 +++ linux/fs/isofs/namei.c Sat Jun 13 13:39:16 1998 @@ -178,6 +178,9 @@ dlen = get_joliet_filename(de, dir, page); dpnt = page; #endif + } else if (dir->i_sb->u.isofs_sb.s_mapping == 'a') { + dlen = get_acorn_filename(de, page, dir); + dpnt = page; } else if (dir->i_sb->u.isofs_sb.s_mapping == 'n') { for (i = 0; i < dlen; i++) { c = dpnt[i]; diff -u --recursive --new-file v2.1.105/linux/fs/minix/bitmap.c linux/fs/minix/bitmap.c --- v2.1.105/linux/fs/minix/bitmap.c Fri Dec 19 15:55:45 1997 +++ linux/fs/minix/bitmap.c Sat Jun 13 13:25:12 1998 @@ -36,16 +36,17 @@ if (numblocks==0 || !(bh=map[numblocks-1])) return(0); - i = (numbits-(numblocks-1)*BLOCK_SIZE*8)/8; + i = ((numbits-(numblocks-1)*BLOCK_SIZE*8)/16)*2; for (j=0; jb_data[j] & 0xf] + nibblemap[(bh->b_data[j]>>4) & 0xf]; } - i = numbits%8; + i = numbits%16; if (i!=0) { - i = bh->b_data[j] | ~((1<b_data[j]) | ~((1<>4) & 0xf]; + sum += nibblemap[(i>>8) & 0xf] + nibblemap[(i>>12) & 0xf]; } return(sum); } @@ -71,11 +72,11 @@ zone = block - sb->u.minix_sb.s_firstdatazone + 1; bit = zone & 8191; zone >>= 13; - bh = sb->u.minix_sb.s_zmap[zone]; - if (!bh) { + if (zone >= sb->u.minix_sb.s_zmap_blocks) { printk("minix_free_block: nonexistent bitmap buffer\n"); return; } + bh = sb->u.minix_sb.s_zmap[zone]; if (!minix_clear_bit(bit,bh->b_data)) printk("free_block (%s:%d): bit already cleared\n", kdevname(sb->s_dev), block); @@ -94,11 +95,13 @@ } repeat: j = 8192; - for (i=0 ; i<64 ; i++) - if ((bh=sb->u.minix_sb.s_zmap[i]) != NULL) - if ((j=minix_find_first_zero_bit(bh->b_data, 8192)) < 8192) - break; - if (i>=64 || !bh || j>=8192) + bh = NULL; + for (i = 0; i < sb->u.minix_sb.s_zmap_blocks; i++) { + bh = sb->u.minix_sb.s_zmap[i]; + if ((j = minix_find_first_zero_bit(bh->b_data, 8192)) < 8192) + break; + } + if (!bh || j >= 8192) return 0; if (minix_set_bit(j,bh->b_data)) { printk("new_block: bit already set"); @@ -134,7 +137,7 @@ int ino, block; ino = inode->i_ino; - if (!ino || ino >= inode->i_sb->u.minix_sb.s_ninodes) { + if (!ino || ino > inode->i_sb->u.minix_sb.s_ninodes) { printk("Bad inode number on dev %s: %d is out of range\n", kdevname(inode->i_dev), ino); return 0; @@ -162,7 +165,7 @@ int ino, block; ino = inode->i_ino; - if (!ino || ino >= inode->i_sb->u.minix_sb.s_ninodes) { + if (!ino || ino > inode->i_sb->u.minix_sb.s_ninodes) { printk("Bad inode number on dev %s: %d is out of range\n", kdevname(inode->i_dev), ino); return 0; @@ -218,15 +221,16 @@ printk("free_inode: inode on nonexistent device\n"); return; } - if (inode->i_ino < 1 || inode->i_ino >= inode->i_sb->u.minix_sb.s_ninodes) { + if (inode->i_ino < 1 || inode->i_ino > inode->i_sb->u.minix_sb.s_ninodes) { printk("free_inode: inode 0 or nonexistent inode\n"); return; } ino = inode->i_ino; - if (!(bh=inode->i_sb->u.minix_sb.s_imap[ino >> 13])) { + if ((ino >> 13) >= inode->i_sb->u.minix_sb.s_imap_blocks) { printk("free_inode: nonexistent imap in superblock\n"); return; } + bh = inode->i_sb->u.minix_sb.s_imap[ino >> 13]; minix_clear_inode(inode); clear_inode(inode); if (!minix_clear_bit(ino & 8191, bh->b_data)) @@ -247,10 +251,12 @@ inode->i_sb = sb; inode->i_flags = inode->i_sb->s_flags; j = 8192; - for (i=0 ; i<8 ; i++) - if ((bh = inode->i_sb->u.minix_sb.s_imap[i]) != NULL) - if ((j=minix_find_first_zero_bit(bh->b_data, 8192)) < 8192) - break; + bh = NULL; + for (i = 0; i < sb->u.minix_sb.s_imap_blocks; i++) { + bh = inode->i_sb->u.minix_sb.s_imap[i]; + if ((j = minix_find_first_zero_bit(bh->b_data, 8192)) < 8192) + break; + } if (!bh || j >= 8192) { iput(inode); return NULL; @@ -262,7 +268,7 @@ } mark_buffer_dirty(bh, 1); j += i*8192; - if (!j || j >= inode->i_sb->u.minix_sb.s_ninodes) { + if (!j || j > inode->i_sb->u.minix_sb.s_ninodes) { iput(inode); return NULL; } diff -u --recursive --new-file v2.1.105/linux/fs/minix/inode.c linux/fs/minix/inode.c --- v2.1.105/linux/fs/minix/inode.c Mon Apr 6 17:41:01 1998 +++ linux/fs/minix/inode.c Sat Jun 13 13:25:12 1998 @@ -63,9 +63,9 @@ sb->u.minix_sb.s_ms->s_state = sb->u.minix_sb.s_mount_state; mark_buffer_dirty(sb->u.minix_sb.s_sbh, 1); } - for(i = 0 ; i < MINIX_I_MAP_SLOTS ; i++) + for (i = 0; i < sb->u.minix_sb.s_imap_blocks; i++) brelse(sb->u.minix_sb.s_imap[i]); - for(i = 0 ; i < MINIX_Z_MAP_SLOTS ; i++) + for (i = 0; i < sb->u.minix_sb.s_zmap_blocks; i++) brelse(sb->u.minix_sb.s_zmap[i]); brelse (sb->u.minix_sb.s_sbh); kfree(sb->u.minix_sb.s_imap); @@ -173,7 +173,8 @@ const char * errmsg; struct inode *root_inode; - /* N.B. These should be compile-time tests */ + /* N.B. These should be compile-time tests. + Unfortunately that is impossible. */ if (32 != sizeof (struct minix_inode)) panic("bad V1 i-node size"); if (64 != sizeof(struct minix2_inode)) @@ -203,33 +204,37 @@ s->u.minix_sb.s_version = MINIX_V1; s->u.minix_sb.s_dirsize = 16; s->u.minix_sb.s_namelen = 14; + s->u.minix_sb.s_link_max = MINIX_LINK_MAX; } else if (s->s_magic == MINIX_SUPER_MAGIC2) { s->u.minix_sb.s_version = MINIX_V1; s->u.minix_sb.s_dirsize = 32; s->u.minix_sb.s_namelen = 30; + s->u.minix_sb.s_link_max = MINIX_LINK_MAX; } else if (s->s_magic == MINIX2_SUPER_MAGIC) { s->u.minix_sb.s_version = MINIX_V2; + s->u.minix_sb.s_nzones = ms->s_zones; s->u.minix_sb.s_dirsize = 16; s->u.minix_sb.s_namelen = 14; + s->u.minix_sb.s_link_max = MINIX2_LINK_MAX; } else if (s->s_magic == MINIX2_SUPER_MAGIC2) { s->u.minix_sb.s_version = MINIX_V2; + s->u.minix_sb.s_nzones = ms->s_zones; s->u.minix_sb.s_dirsize = 32; s->u.minix_sb.s_namelen = 30; + s->u.minix_sb.s_link_max = MINIX2_LINK_MAX; } else goto out_no_fs; - if (s->u.minix_sb.s_zmap_blocks > MINIX_Z_MAP_SLOTS) - goto out_too_big; /* * Allocate the buffer map to keep the superblock small. */ - i = (MINIX_I_MAP_SLOTS + MINIX_Z_MAP_SLOTS) * sizeof(bh); + i = (s->u.minix_sb.s_imap_blocks + s->u.minix_sb.s_zmap_blocks) * sizeof(bh); map = kmalloc(i, GFP_KERNEL); if (!map) goto out_no_map; memset(map, 0, i); s->u.minix_sb.s_imap = &map[0]; - s->u.minix_sb.s_zmap = &map[MINIX_I_MAP_SLOTS]; + s->u.minix_sb.s_zmap = &map[s->u.minix_sb.s_imap_blocks]; block=2; for (i=0 ; i < s->u.minix_sb.s_imap_blocks ; i++) { @@ -242,8 +247,6 @@ goto out_no_bitmap; block++; } - if (block != 2+s->u.minix_sb.s_imap_blocks+s->u.minix_sb.s_zmap_blocks) - goto out_no_bitmap; minix_set_bit(0,s->u.minix_sb.s_imap[0]->b_data); minix_set_bit(0,s->u.minix_sb.s_zmap[0]->b_data); @@ -263,6 +266,8 @@ if (!s->s_root) goto out_iput; + s->s_root->d_op = &minix_dentry_operations; + if (!(s->s_flags & MS_RDONLY)) { ms->s_state &= ~MINIX_VALID_FS; mark_buffer_dirty(bh, 1); @@ -292,9 +297,9 @@ out_no_bitmap: printk("MINIX-fs: bad superblock or unable to read bitmaps\n"); out_freemap: - for(i=0;iu.minix_sb.s_imap_blocks; i++) brelse(s->u.minix_sb.s_imap[i]); - for(i=0;iu.minix_sb.s_zmap_blocks; i++) brelse(s->u.minix_sb.s_zmap[i]); kfree(s->u.minix_sb.s_imap); goto out_release; @@ -304,11 +309,6 @@ printk ("MINIX-fs: can't allocate map\n"); goto out_release; -out_too_big: - if (!silent) - printk ("MINIX-fs: filesystem too big\n"); - goto out_release; - out_no_fs: if (!silent) printk("VFS: Can't find a minix or minix V2 filesystem on dev " @@ -729,7 +729,7 @@ ino = inode->i_ino; inode->i_op = NULL; inode->i_mode = 0; - if (!ino || ino >= inode->i_sb->u.minix_sb.s_ninodes) { + if (!ino || ino > inode->i_sb->u.minix_sb.s_ninodes) { printk("Bad inode number on dev %s" ": %d is out of range\n", kdevname(inode->i_dev), ino); @@ -783,7 +783,7 @@ ino = inode->i_ino; inode->i_op = NULL; inode->i_mode = 0; - if (!ino || ino >= inode->i_sb->u.minix_sb.s_ninodes) { + if (!ino || ino > inode->i_sb->u.minix_sb.s_ninodes) { printk("Bad inode number on dev %s" ": %d is out of range\n", kdevname(inode->i_dev), ino); @@ -848,7 +848,7 @@ int ino, block; ino = inode->i_ino; - if (!ino || ino >= inode->i_sb->u.minix_sb.s_ninodes) { + if (!ino || ino > inode->i_sb->u.minix_sb.s_ninodes) { printk("Bad inode number on dev %s" ": %d is out of range\n", kdevname(inode->i_dev), ino); @@ -886,7 +886,7 @@ int ino, block; ino = inode->i_ino; - if (!ino || ino >= inode->i_sb->u.minix_sb.s_ninodes) { + if (!ino || ino > inode->i_sb->u.minix_sb.s_ninodes) { printk("Bad inode number on dev %s" ": %d is out of range\n", kdevname(inode->i_dev), ino); diff -u --recursive --new-file v2.1.105/linux/fs/minix/namei.c linux/fs/minix/namei.c --- v2.1.105/linux/fs/minix/namei.c Thu May 7 22:51:53 1998 +++ linux/fs/minix/namei.c Sat Jun 13 13:25:12 1998 @@ -23,34 +23,12 @@ static inline int namecompare(int len, int maxlen, const char * name, const char * buffer) { - if (len > maxlen) - return 0; if (len < maxlen && buffer[len]) return 0; return !memcmp(name, buffer, len); } /* - * ok, we cannot use strncmp, as the name is not in our data space. - * Thus we'll have to use minix_match. No big problem. Match also makes - * some sanity tests. - * - * NOTE! unlike strncmp, minix_match returns 1 for success, 0 for failure. - */ -static int minix_match(int len, const char * name, - struct buffer_head * bh, unsigned long * offset, - struct minix_sb_info * info) -{ - struct minix_dir_entry * de; - - de = (struct minix_dir_entry *) (bh->b_data + *offset); - *offset += info->s_dirsize; - if (!de->inode || len > info->s_namelen) - return 0; - return namecompare(len,info->s_namelen,name,de->name); -} - -/* * minix_find_entry() * * finds an entry in the specified directory with the wanted name. It @@ -64,6 +42,7 @@ unsigned long block, offset; struct buffer_head * bh; struct minix_sb_info * info; + struct minix_dir_entry *de; *res_dir = NULL; if (!dir || !dir->i_sb) @@ -86,9 +65,12 @@ continue; } } - *res_dir = (struct minix_dir_entry *) (bh->b_data + offset); - if (minix_match(namelen,name,bh,&offset,info)) + de = (struct minix_dir_entry *) (bh->b_data + offset); + offset += info->s_dirsize; + if (de->inode && namecompare(namelen,info->s_namelen,name,de->name)) { + *res_dir = de; return bh; + } if (offset < bh->b_size) continue; brelse(bh); @@ -97,16 +79,52 @@ block++; } brelse(bh); - *res_dir = NULL; return NULL; } +#ifndef NO_TRUNCATE + +static int minix_hash(struct dentry *dentry, struct qstr *qstr) +{ + unsigned long hash; + int i; + const char *name; + + i = dentry->d_inode->i_sb->u.minix_sb.s_namelen; + if (i >= qstr->len) + return 0; + /* Truncate the name in place, avoids having to define a compare + function. */ + qstr->len = i; + name = qstr->name; + hash = init_name_hash(); + while (i--) + hash = partial_name_hash(*name++, hash); + qstr->hash = end_name_hash(hash); + return 0; +} + +#endif + +struct dentry_operations minix_dentry_operations = { + 0, /* revalidate */ +#ifndef NO_TRUNCATE + minix_hash, +#else + 0, +#endif + 0 /* compare */ +}; + int minix_lookup(struct inode * dir, struct dentry *dentry) { struct inode * inode = NULL; struct minix_dir_entry * de; struct buffer_head * bh; +#ifndef NO_TRUNCATE + dentry->d_op = &minix_dentry_operations; +#endif bh = minix_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de); if (bh) { int ino = de->inode; @@ -296,7 +314,7 @@ brelse(bh); return -EEXIST; } - if (dir->i_nlink >= MINIX_LINK_MAX) + if (dir->i_nlink >= info->s_link_max) return -EMLINK; inode = minix_new_inode(dir); if (!inode) @@ -434,7 +452,7 @@ retval = -ENOENT; goto end_rmdir; } - if (inode->i_count > 1) { + if (dentry->d_count > 1) { retval = -EBUSY; goto end_rmdir; } @@ -573,7 +591,7 @@ if (S_ISDIR(inode->i_mode)) return -EPERM; - if (inode->i_nlink >= MINIX_LINK_MAX) + if (inode->i_nlink >= inode->i_sb->u.minix_sb.s_link_max) return -EMLINK; bh = minix_find_entry(dir, dentry->d_name.name, @@ -689,7 +707,7 @@ if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino) goto end_rename; retval = -EMLINK; - if (!new_inode && new_dir->i_nlink >= MINIX_LINK_MAX) + if (!new_inode && new_dir->i_nlink >= info->s_link_max) goto end_rename; } if (!new_bh) { diff -u --recursive --new-file v2.1.105/linux/fs/nfsd/nfsproc.c linux/fs/nfsd/nfsproc.c --- v2.1.105/linux/fs/nfsd/nfsproc.c Fri Jan 30 11:28:08 1998 +++ linux/fs/nfsd/nfsproc.c Sat Jun 13 09:58:14 1998 @@ -180,10 +180,8 @@ /* * CREATE processing is complicated. The keyword here is `overloaded.' - * There's a small race condition here between the check for existence - * and the actual create() call, but one could even consider this a - * feature because this only happens if someone else creates the file - * at the same time. + * The parent directory is kept locked between the check for existence + * and the actual create() call in compliance with VFS protocols. * N.B. After this call _both_ argp->fh and resp->fh need an fh_put */ static int @@ -193,15 +191,14 @@ svc_fh *dirfhp = &argp->fh; svc_fh *newfhp = &resp->fh; struct iattr *attr = &argp->attrs; - struct inode *inode = NULL; - int nfserr, type, mode; - int rdonly = 0, exists; + struct inode *inode; + int nfserr, type, mode, rdonly = 0; dev_t rdev = NODEV; dprintk("nfsd: CREATE %d/%ld %s\n", SVCFH_DEV(dirfhp), SVCFH_INO(dirfhp), argp->name); - /* Get the directory inode */ + /* First verify the parent filehandle */ nfserr = fh_verify(rqstp, dirfhp, S_IFDIR, MAY_EXEC); if (nfserr) goto done; /* must fh_put dirfhp even on error */ @@ -214,18 +211,32 @@ } else if (nfserr) goto done; - /* First, check if the file already exists. */ - exists = !nfsd_lookup(rqstp, dirfhp, argp->name, argp->len, newfhp); - - if (newfhp->fh_dverified) - inode = newfhp->fh_dentry->d_inode; + /* + * Do a lookup to verify the new filehandle. + */ + nfserr = nfsd_lookup(rqstp, dirfhp, argp->name, argp->len, newfhp); + if (nfserr) { + if (nfserr != nfserr_noent) + goto done; + /* + * If the new filehandle wasn't verified, we can't tell + * whether the file exists or not. Time to bail ... + */ + nfserr = nfserr_acces; + if (!newfhp->fh_dverified) { + printk(KERN_WARNING + "nfsd_proc_create: filehandle not verified\n"); + goto done; + } + } - /* Get rid of this soon... */ - if (exists && !inode) { - printk("nfsd_proc_create: Wheee... exists but d_inode==NULL\n"); - nfserr = nfserr_rofs; + /* + * Lock the parent directory and check for existence. + */ + nfserr = fh_lock_parent(dirfhp, newfhp->fh_dentry); + if (nfserr) goto done; - } + inode = newfhp->fh_dentry->d_inode; /* Unfudge the mode bits */ if (attr->ia_valid & ATTR_MODE) { @@ -233,7 +244,7 @@ mode = attr->ia_mode & ~S_IFMT; if (!type) /* HP weirdness */ type = S_IFREG; - } else if (exists) { + } else if (inode) { type = inode->i_mode & S_IFMT; mode = inode->i_mode & ~S_IFMT; } else { @@ -243,8 +254,8 @@ /* This is for "echo > /dev/null" a la SunOS. Argh. */ nfserr = nfserr_rofs; - if (rdonly && (!exists || type == S_IFREG)) - goto done; + if (rdonly && (!inode || type == S_IFREG)) + goto out_unlock; attr->ia_valid |= ATTR_MODE; attr->ia_mode = type | mode; @@ -252,7 +263,6 @@ /* Special treatment for non-regular files according to the * gospel of sun micro */ - nfserr = 0; if (type != S_IFREG) { int is_borc = 0; u32 size = attr->ia_size; @@ -267,21 +277,21 @@ } else if (size != rdev) { /* dev got truncated because of 16bit Linux dev_t */ nfserr = nfserr_io; /* or nfserr_inval? */ - goto done; + goto out_unlock; } else { /* Okay, char or block special */ is_borc = 1; } /* Make sure the type and device matches */ - if (exists && (type != (inode->i_mode & S_IFMT) - || (is_borc && inode->i_rdev != rdev))) { - nfserr = nfserr_exist; - goto done; - } + nfserr = nfserr_exist; + if (inode && (type != (inode->i_mode & S_IFMT) || + (is_borc && inode->i_rdev != rdev))) + goto out_unlock; } - if (!exists) { + nfserr = 0; + if (!inode) { /* File doesn't exist. Create it and set attrs */ nfserr = nfsd_create(rqstp, dirfhp, argp->name, argp->len, attr, type, rdev, newfhp); @@ -297,6 +307,10 @@ nfserr = nfsd_setattr(rqstp, newfhp, attr); } +out_unlock: + /* We don't really need to unlock, as fh_put does it. */ + fh_unlock(dirfhp); + done: fh_put(dirfhp); RETURN(nfserr); @@ -359,9 +373,9 @@ int nfserr; dprintk("nfsd: SYMLINK %p %s -> %s\n", - SVCFH_DENTRY(&argp->ffh), - argp->fname, argp->tname); + SVCFH_DENTRY(&argp->ffh), argp->fname, argp->tname); + memset(&newfh, 0, sizeof(struct svc_fh)); /* * Create the link, look up new file and set attrs. */ @@ -386,12 +400,13 @@ { int nfserr; - dprintk("nfsd: MKDIR %p %s\n", - SVCFH_DENTRY(&argp->fh), - argp->name); + dprintk("nfsd: MKDIR %p %s\n", SVCFH_DENTRY(&argp->fh), argp->name); + + if (resp->fh.fh_dverified) { + printk(KERN_WARNING + "nfsd_proc_mkdir: response already verified??\n"); + } - /* N.B. what about the dentry count?? */ - resp->fh.fh_dverified = 0; /* paranoia */ nfserr = nfsd_create(rqstp, &argp->fh, argp->name, argp->len, &argp->attrs, S_IFDIR, 0, &resp->fh); fh_put(&argp->fh); diff -u --recursive --new-file v2.1.105/linux/fs/nfsd/vfs.c linux/fs/nfsd/vfs.c --- v2.1.105/linux/fs/nfsd/vfs.c Fri May 8 23:14:53 1998 +++ linux/fs/nfsd/vfs.c Sat Jun 13 09:58:14 1998 @@ -31,14 +31,13 @@ #include #include +#include #include #if LINUX_VERSION_CODE >= 0x020100 #include #endif -extern void fh_update(struct svc_fh*); - #define NFSDDBG_FACILITY NFSDDBG_FILEOP /* Open mode for nfsd_open */ @@ -77,6 +76,41 @@ static struct raparms * raparm_cache = 0; /* + * Lock a parent directory following the VFS locking protocol. + */ +int +fh_lock_parent(struct svc_fh *parent_fh, struct dentry *dchild) +{ + int nfserr = 0; + + fh_lock(parent_fh); + /* + * Make sure the parent->child relationship still holds, + * and that the child is still hashed. + */ + if (dchild->d_parent != parent_fh->fh_dentry) + goto out_not_parent; + if (list_empty(&dchild->d_hash)) + goto out_not_hashed; +out: + return nfserr; + +out_not_parent: + printk(KERN_WARNING + "fh_lock_parent: %s/%s parent changed\n", + dchild->d_parent->d_name.name, dchild->d_name.name); + goto out_unlock; +out_not_hashed: + printk(KERN_WARNING + "fh_lock_parent: %s/%s unhashed\n", + dchild->d_parent->d_name.name, dchild->d_name.name); +out_unlock: + nfserr = nfserr_noent; + fh_unlock(parent_fh); + goto out; +} + +/* * Deny access to certain file systems */ static inline int @@ -546,8 +580,11 @@ } /* - * Create a file (regular, directory, device, fifo). - * UNIX sockets not yet implemented. + * Create a file (regular, directory, device, fifo); UNIX sockets + * not yet implemented. + * If the response fh has been verified, the parent directory should + * already be locked. Note that the parent directory is left locked. + * * N.B. Every call to nfsd_create needs an fh_put for _both_ fhp and resfhp */ int @@ -557,13 +594,12 @@ { struct dentry *dentry, *dchild; struct inode *dirp; + nfsd_dirop_t opfunc = NULL; int err; err = nfserr_perm; if (!flen) goto out; - if (!(iap->ia_valid & ATTR_MODE)) - iap->ia_mode = 0; err = fh_verify(rqstp, fhp, S_IFDIR, MAY_CREATE); if (err) goto out; @@ -571,64 +607,74 @@ dentry = fhp->fh_dentry; dirp = dentry->d_inode; - /* Get all the sanity checks out of the way before we lock the parent. */ err = nfserr_notdir; if(!dirp->i_op || !dirp->i_op->lookup) goto out; - err = nfserr_perm; - if (type == S_IFREG) { - if(!dirp->i_op->create) - goto out; - } else if(type == S_IFDIR) { - if(!dirp->i_op->mkdir) - goto out; - } else if((type == S_IFCHR) || (type == S_IFBLK) || (type == S_IFIFO)) { - if(!dirp->i_op->mknod) - goto out; - } else { - goto out; - } - /* - * The response filehandle may have been setup already ... + * Check whether the response filehandle has been verified yet. + * If it has, the parent directory should already be locked. */ if (!resfhp->fh_dverified) { dchild = lookup_dentry(fname, dget(dentry), 0); err = PTR_ERR(dchild); - if(IS_ERR(dchild)) + if (IS_ERR(dchild)) goto out_nfserr; fh_compose(resfhp, fhp->fh_export, dchild); - } else + /* Lock the parent and check for errors ... */ + err = fh_lock_parent(fhp, dchild); + if (err) + goto out; + } else { dchild = resfhp->fh_dentry; + if (!fhp->fh_locked) + printk(KERN_ERR + "nfsd_create: parent %s/%s not locked!\n", + dentry->d_parent->d_name.name, + dentry->d_name.name); + } /* * Make sure the child dentry is still negative ... */ + err = nfserr_exist; if (dchild->d_inode) { - printk("nfsd_create: dentry %s/%s not negative!\n", - dentry->d_parent->d_name.name, dentry->d_name.name); + printk(KERN_WARNING + "nfsd_create: dentry %s/%s not negative!\n", + dentry->d_name.name, dchild->d_name.name); + goto out; } - /* Looks good, lock the directory. */ - fh_lock(fhp); - DQUOT_INIT(dirp); + /* + * Get the dir op function pointer. + */ + err = nfserr_perm; switch (type) { case S_IFREG: - err = dirp->i_op->create(dirp, dchild, iap->ia_mode); + opfunc = (nfsd_dirop_t) dirp->i_op->create; break; case S_IFDIR: - err = dirp->i_op->mkdir(dirp, dchild, iap->ia_mode); + opfunc = (nfsd_dirop_t) dirp->i_op->mkdir; break; case S_IFCHR: case S_IFBLK: case S_IFIFO: - err = dirp->i_op->mknod(dirp, dchild, iap->ia_mode, rdev); + opfunc = dirp->i_op->mknod; break; } - DQUOT_DROP(dirp); - fh_unlock(fhp); + if (!opfunc) + goto out; + if (!(iap->ia_valid & ATTR_MODE)) + iap->ia_mode = 0; + + /* + * Call the dir op function to create the object. + */ + DQUOT_INIT(dirp); + err = opfunc(dirp, dchild, iap->ia_mode, rdev); + DQUOT_DROP(dirp); if (err < 0) goto out_nfserr; + if (EX_ISSYNC(fhp->fh_export)) write_inode_now(dirp); @@ -778,21 +824,29 @@ if (IS_ERR(dnew)) goto out_nfserr; - err = -EEXIST; + /* + * Lock the parent before checking for existence + */ + err = fh_lock_parent(fhp, dnew); + if (err) + goto out_compose; + + err = nfserr_exist; if (!dnew->d_inode) { - fh_lock(fhp); DQUOT_INIT(dirp); err = dirp->i_op->symlink(dirp, dnew, path); DQUOT_DROP(dirp); - fh_unlock(fhp); if (!err) { if (EX_ISSYNC(fhp->fh_export)) write_inode_now(dirp); - } + } else + err = nfserrno(-err); } + fh_unlock(fhp); + + /* Compose the fh so the dentry will be freed ... */ +out_compose: fh_compose(resfhp, fhp->fh_export, dnew); - if (err) - goto out_nfserr; out: return err; @@ -820,6 +874,10 @@ if (err) goto out; + err = nfserr_perm; + if (!len) + goto out; + ddir = ffhp->fh_dentry; dirp = ddir->d_inode; @@ -827,44 +885,48 @@ err = PTR_ERR(dnew); if (IS_ERR(dnew)) goto out_nfserr; + /* + * Lock the parent before checking for existence + */ + err = fh_lock_parent(ffhp, dnew); + if (err) + goto out_dput; - err = -EEXIST; + err = nfserr_exist; if (dnew->d_inode) - goto dput_and_out; - - err = -EPERM; - if (!len) - goto dput_and_out; + goto out_unlock; dold = tfhp->fh_dentry; dest = dold->d_inode; - err = -EACCES; + err = nfserr_acces; if (nfsd_iscovered(ddir, ffhp->fh_export)) - goto dput_and_out; + goto out_unlock; + /* FIXME: nxdev for NFSv3 */ if (dirp->i_dev != dest->i_dev) - goto dput_and_out; /* FIXME: nxdev for NFSv3 */ + goto out_unlock; - err = -EPERM; + err = nfserr_perm; if (IS_IMMUTABLE(dest) /* || IS_APPEND(dest) */ ) - goto dput_and_out; + goto out_unlock; if (!dirp->i_op || !dirp->i_op->link) - goto dput_and_out; + goto out_unlock; - fh_lock(ffhp); DQUOT_INIT(dirp); err = dirp->i_op->link(dold, dirp, dnew); DQUOT_DROP(dirp); - fh_unlock(ffhp); + if (!err) { + if (EX_ISSYNC(ffhp->fh_export)) { + write_inode_now(dirp); + write_inode_now(dest); + } + } else + err = nfserrno(-err); - if (!err && EX_ISSYNC(ffhp->fh_export)) { - write_inode_now(dirp); - write_inode_now(dest); - } -dput_and_out: +out_unlock: + fh_unlock(ffhp); +out_dput: dput(dnew); - if (err) - goto out_nfserr; out: return err; @@ -1005,7 +1067,10 @@ if (IS_ERR(rdentry)) goto out_nfserr; - fh_lock(fhp); + err = fh_lock_parent(fhp, rdentry); + if (err) + goto out; + DQUOT_INIT(dirp); if (type == S_IFDIR) { err = -ENOTDIR; diff -u --recursive --new-file v2.1.105/linux/fs/proc/array.c linux/fs/proc/array.c --- v2.1.105/linux/fs/proc/array.c Tue Jun 9 11:57:30 1998 +++ linux/fs/proc/array.c Sat Jun 13 12:59:15 1998 @@ -544,6 +544,23 @@ } #elif defined(__powerpc__) return (p->tss.wchan); +#elif defined (CONFIG_ARM) + { + unsigned long fp, lr; + unsigned long stack_page; + int count = 0; + + stack_page = 4096 + (unsigned long)p; + fp = get_css_fp (&p->tss); + do { + if (fp < stack_page || fp > 4092+stack_page) + return 0; + lr = pc_pointer (((unsigned long *)fp)[-1]); + if (lr < first_sched || lr > last_sched) + return lr; + fp = *(unsigned long *) (fp - 12); + } while (count ++ < 16); + } #endif return 0; } @@ -560,6 +577,9 @@ # define KSTK_EIP(tsk) \ (*(unsigned long *)(PT_REG(pc) + PAGE_SIZE + (unsigned long)(tsk))) # define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->tss.usp) +#elif defined(CONFIG_ARM) +# define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1022]) +# define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1020]) #elif defined(__mc68000__) #define KSTK_EIP(tsk) \ ({ \ @@ -704,21 +724,6 @@ data - stack, stack, exec - lib, lib); } - return buffer; -} - -char * render_sigset_t(sigset_t *set, char *buffer) -{ - int i = _NSIG, x; - do { - i -= 4, x = 0; - if (sigismember(set, i+1)) x |= 1; - if (sigismember(set, i+2)) x |= 2; - if (sigismember(set, i+3)) x |= 4; - if (sigismember(set, i+4)) x |= 8; - *buffer++ = (x < 10 ? '0' : 'a' - 10) + x; - } while (i >= 4); - *buffer = 0; return buffer; } diff -u --recursive --new-file v2.1.105/linux/fs/romfs/inode.c linux/fs/romfs/inode.c --- v2.1.105/linux/fs/romfs/inode.c Mon Apr 6 17:41:01 1998 +++ linux/fs/romfs/inode.c Wed Jun 10 11:17:29 1998 @@ -282,7 +282,7 @@ /* Not really failsafe, but we are read-only... */ for(;;) { if (!offset || offset >= maxoff) { - offset = 0xffffffff; + offset = maxoff; filp->f_pos = offset; return stored; } diff -u --recursive --new-file v2.1.105/linux/include/asm-alpha/bitops.h linux/include/asm-alpha/bitops.h --- v2.1.105/linux/include/asm-alpha/bitops.h Wed Apr 1 20:11:53 1998 +++ linux/include/asm-alpha/bitops.h Sat Jun 13 12:56:46 1998 @@ -183,6 +183,24 @@ } /* + * ffs: find first bit set. This is defined the same way as + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + */ + +#define ffs(x) generic_ffs(x) + +/* + * hweightN: returns the hamming weight (i.e. the number + * of bits set) of a N-bit word + */ + +#define hweight32(x) generic_hweight32(x) +#define hweight16(x) generic_hweight16(x) +#define hweight8(x) generic_hweight8(x) + + +/* * Find next zero bit in a bitmap reasonably efficiently.. */ extern inline unsigned long find_next_zero_bit(void * addr, unsigned long size, unsigned long offset) diff -u --recursive --new-file v2.1.105/linux/include/asm-alpha/pgtable.h linux/include/asm-alpha/pgtable.h --- v2.1.105/linux/include/asm-alpha/pgtable.h Wed Apr 1 20:11:53 1998 +++ linux/include/asm-alpha/pgtable.h Sat Jun 13 12:48:10 1998 @@ -11,6 +11,7 @@ #include #include +#include /* For TASK_SIZE */ #include /* Caches aren't brain-dead on the alpha. */ @@ -181,6 +182,7 @@ #define PTRS_PER_PTE (1UL << (PAGE_SHIFT-3)) #define PTRS_PER_PMD (1UL << (PAGE_SHIFT-3)) #define PTRS_PER_PGD ((1UL << (PAGE_SHIFT-3))-1) +#define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE) /* the no. of pointers that fit on a page: this will go away */ #define PTRS_PER_PAGE (1UL << (PAGE_SHIFT-3)) @@ -401,126 +403,174 @@ * used to allocate a kernel page table - this turns on ASN bits * if any. */ -extern inline void pte_free_kernel(pte_t * pte) +#ifndef __SMP__ +extern struct pgtable_cache_struct { + unsigned long *pgd_cache; + unsigned long *pte_cache; + unsigned long pgtable_cache_sz; +} quicklists; +#else +#include +#define quicklists cpu_data[smp_processor_id()] +#endif +#define pgd_quicklist (quicklists.pgd_cache) +#define pmd_quicklist ((unsigned long *)0) +#define pte_quicklist (quicklists.pte_cache) +#define pgtable_cache_size (quicklists.pgtable_cache_sz) + +extern __inline__ pgd_t *get_pgd_slow(void) +{ + pgd_t *ret = (pgd_t *)__get_free_page(GFP_KERNEL), *init; + + if (ret) { + init = pgd_offset(&init_mm, 0); + memset (ret, 0, USER_PTRS_PER_PGD * sizeof(pgd_t)); + memcpy (ret + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD, + (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); + } + return ret; +} + +extern __inline__ pgd_t *get_pgd_fast(void) { - free_page((unsigned long) pte); + unsigned long *ret; + + if((ret = pgd_quicklist) != NULL) { + pgd_quicklist = (unsigned long *)(*ret); + ret[0] = ret[1]; + pgtable_cache_size--; + } else + ret = (unsigned long *)get_pgd_slow(); + return (pgd_t *)ret; } -extern inline pte_t * pte_alloc_kernel(pmd_t *pmd, unsigned long address) +extern __inline__ void free_pgd_fast(pgd_t *pgd) { - address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); - if (pmd_none(*pmd)) { - pte_t *page = (pte_t *) get_free_page(GFP_KERNEL); - if (pmd_none(*pmd)) { - if (page) { - pmd_set(pmd, page); - return page + address; - } - pmd_set(pmd, (pte_t *) BAD_PAGETABLE); - return NULL; - } - free_page((unsigned long) page); - } - if (pmd_bad(*pmd)) { - printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd)); - pmd_set(pmd, (pte_t *) BAD_PAGETABLE); - return NULL; - } - return (pte_t *) pmd_page(*pmd) + address; + *(unsigned long *)pgd = (unsigned long) pgd_quicklist; + pgd_quicklist = (unsigned long *) pgd; + pgtable_cache_size++; } -extern inline void pmd_free_kernel(pmd_t * pmd) +extern __inline__ void free_pgd_slow(pgd_t *pgd) { - free_page((unsigned long) pmd); + free_page((unsigned long)pgd); } -extern inline pmd_t * pmd_alloc_kernel(pgd_t *pgd, unsigned long address) +extern pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long address_premasked); + +extern __inline__ pmd_t *get_pmd_fast(void) { - address = (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1); - if (pgd_none(*pgd)) { - pmd_t *page = (pmd_t *) get_free_page(GFP_KERNEL); - if (pgd_none(*pgd)) { - if (page) { - pgd_set(pgd, page); - return page + address; - } - pgd_set(pgd, BAD_PAGETABLE); - return NULL; - } - free_page((unsigned long) page); + unsigned long *ret; + + if((ret = (unsigned long *)pte_quicklist) != NULL) { + pte_quicklist = (unsigned long *)(*ret); + ret[0] = ret[1]; + pgtable_cache_size--; } - if (pgd_bad(*pgd)) { - printk("Bad pgd in pmd_alloc: %08lx\n", pgd_val(*pgd)); - pgd_set(pgd, BAD_PAGETABLE); - return NULL; + return (pmd_t *)ret; +} + +extern __inline__ void free_pmd_fast(pmd_t *pmd) +{ + *(unsigned long *)pmd = (unsigned long) pte_quicklist; + pte_quicklist = (unsigned long *) pmd; + pgtable_cache_size++; +} + +extern __inline__ void free_pmd_slow(pmd_t *pmd) +{ + free_page((unsigned long)pmd); +} + +extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted); + +extern __inline__ pte_t *get_pte_fast(void) +{ + unsigned long *ret; + + if((ret = (unsigned long *)pte_quicklist) != NULL) { + pte_quicklist = (unsigned long *)(*ret); + ret[0] = ret[1]; + pgtable_cache_size--; } - return (pmd_t *) pgd_page(*pgd) + address; + return (pte_t *)ret; } -extern inline void pte_free(pte_t * pte) +extern __inline__ void free_pte_fast(pte_t *pte) { - free_page((unsigned long) pte); + *(unsigned long *)pte = (unsigned long) pte_quicklist; + pte_quicklist = (unsigned long *) pte; + pgtable_cache_size++; } +extern __inline__ void free_pte_slow(pte_t *pte) +{ + free_page((unsigned long)pte); +} + +extern void __bad_pte(pmd_t *pmd); +extern void __bad_pmd(pgd_t *pgd); + +#define pte_free_kernel(pte) free_pte_fast(pte) +#define pte_free(pte) free_pte_fast(pte) +#define pmd_free_kernel(pmd) free_pmd_fast(pmd) +#define pmd_free(pmd) free_pmd_fast(pmd) +#define pgd_free(pgd) free_pgd_fast(pgd) +#define pgd_alloc() get_pgd_fast() + extern inline pte_t * pte_alloc(pmd_t *pmd, unsigned long address) { address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); if (pmd_none(*pmd)) { - pte_t *page = (pte_t *) get_free_page(GFP_KERNEL); - if (pmd_none(*pmd)) { - if (page) { - pmd_set(pmd, page); - return page + address; - } - pmd_set(pmd, (pte_t *) BAD_PAGETABLE); - return NULL; - } - free_page((unsigned long) page); + pte_t *page = get_pte_fast(); + + if (!page) + return get_pte_slow(pmd, address); + pmd_set(pmd, page); + return page + address; } if (pmd_bad(*pmd)) { - printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd)); - pmd_set(pmd, (pte_t *) BAD_PAGETABLE); + __bad_pte(pmd); return NULL; } return (pte_t *) pmd_page(*pmd) + address; } -extern inline void pmd_free(pmd_t * pmd) -{ - free_page((unsigned long) pmd); -} - extern inline pmd_t * pmd_alloc(pgd_t *pgd, unsigned long address) { address = (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1); if (pgd_none(*pgd)) { - pmd_t *page = (pmd_t *) get_free_page(GFP_KERNEL); - if (pgd_none(*pgd)) { - if (page) { - pgd_set(pgd, page); - return page + address; - } - pgd_set(pgd, BAD_PAGETABLE); - return NULL; - } - free_page((unsigned long) page); + pmd_t *page = get_pmd_fast(); + + if (!page) + return get_pmd_slow(pgd, address); + pgd_set(pgd, page); + return page + address; } if (pgd_bad(*pgd)) { - printk("Bad pgd in pmd_alloc: %08lx\n", pgd_val(*pgd)); - pgd_set(pgd, BAD_PAGETABLE); + __bad_pmd(pgd); return NULL; } return (pmd_t *) pgd_page(*pgd) + address; } -extern inline void pgd_free(pgd_t * pgd) -{ - free_page((unsigned long) pgd); -} +#define pte_alloc_kernel pte_alloc +#define pmd_alloc_kernel pmd_alloc -extern inline pgd_t * pgd_alloc(void) +extern inline void set_pgdir(unsigned long address, pgd_t entry) { - return (pgd_t *) get_free_page(GFP_KERNEL); + struct task_struct * p; + pgd_t *pgd; + + read_lock(&tasklist_lock); + for_each_task(p) { + if (!p->mm) + continue; + *pgd_offset(p->mm,address) = entry; + } + read_unlock(&tasklist_lock); + for (pgd = (pgd_t *)pgd_quicklist; pgd; pgd = (pgd_t *)*(unsigned long *)pgd) + pgd[(address >> PGDIR_SHIFT) & (PTRS_PER_PAGE - 1)] = entry; } extern pgd_t swapper_pg_dir[1024]; diff -u --recursive --new-file v2.1.105/linux/include/asm-alpha/signal.h linux/include/asm-alpha/signal.h --- v2.1.105/linux/include/asm-alpha/signal.h Thu Feb 12 20:56:12 1998 +++ linux/include/asm-alpha/signal.h Tue Jun 9 00:55:10 1998 @@ -76,7 +76,7 @@ /* * SA_FLAGS values: * - * SA_ONSTACK is not currently supported, but will allow sigaltstack(2). + * SA_ONSTACK indicates that a registered stack_t will be used. * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the * SA_RESTART flag to get restarting signals (which were the default long ago) * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. @@ -100,6 +100,16 @@ #define SA_NOMASK SA_NODEFER #define SA_INTERRUPT 0x20000000 /* dummy -- ignored */ +/* + * sigaltstack controls + */ +#define SS_ONSTACK 1 +#define SS_DISABLE 2 + +#define MINSIGSTKSZ 4096 +#define SIGSTKSZ 16384 + + #ifdef __KERNEL__ /* * These values of sa_flags are used only by the kernel as part of the @@ -163,6 +173,15 @@ int ss_flags; size_t ss_size; } stack_t; + +/* sigstack(2) is deprecated, and will be withdrawn in a future version + of the X/Open CAE Specification. Use sigaltstack instead. It is only + implemented here for OSF/1 compatability. */ + +struct sigstack { + void *ss_sp; + int ss_onstack; +}; #ifdef __KERNEL__ #include diff -u --recursive --new-file v2.1.105/linux/include/asm-alpha/smp.h linux/include/asm-alpha/smp.h --- v2.1.105/linux/include/asm-alpha/smp.h Wed Apr 1 20:11:53 1998 +++ linux/include/asm-alpha/smp.h Sat Jun 13 12:48:11 1998 @@ -10,6 +10,9 @@ struct cpuinfo_alpha { unsigned long loops_per_sec; unsigned int next; + unsigned long *pgd_cache; + unsigned long *pte_cache; + unsigned long pgtable_cache_sz; }; extern struct cpuinfo_alpha cpu_data[NR_CPUS]; diff -u --recursive --new-file v2.1.105/linux/include/asm-alpha/unistd.h linux/include/asm-alpha/unistd.h --- v2.1.105/linux/include/asm-alpha/unistd.h Sun Jun 7 11:16:36 1998 +++ linux/include/asm-alpha/unistd.h Tue Jun 9 13:34:01 1998 @@ -113,7 +113,7 @@ #define __NR_osf_old_sigblock 109 /* not implemented */ #define __NR_osf_old_sigsetmask 110 /* not implemented */ #define __NR_sigsuspend 111 -#define __NR_osf_sigstack 112 /* not implemented */ +#define __NR_osf_sigstack 112 #define __NR_recvmsg 113 #define __NR_sendmsg 114 #define __NR_osf_old_vtrace 115 /* not implemented */ @@ -205,7 +205,7 @@ #define __NR_getpgid 233 #define __NR_getsid 234 -#define __NR_osf_sigaltstack 235 /* not implemented */ +#define __NR_sigaltstack 235 #define __NR_osf_waitid 236 /* not implemented */ #define __NR_osf_priocntlset 237 /* not implemented */ #define __NR_osf_sigsendset 238 /* not implemented */ @@ -305,7 +305,8 @@ #define __NR_wait4 365 #define __NR_adjtimex 366 #define __NR_getcwd 367 - +#define __NR_capget 368 +#define __NR_capset 369 #if defined(__LIBRARY__) && defined(__GNUC__) diff -u --recursive --new-file v2.1.105/linux/include/asm-arm/arch-a5k/a.out.h linux/include/asm-arm/arch-a5k/a.out.h --- v2.1.105/linux/include/asm-arm/arch-a5k/a.out.h Fri May 8 23:14:54 1998 +++ linux/include/asm-arm/arch-a5k/a.out.h Wed Dec 31 16:00:00 1969 @@ -1,16 +0,0 @@ -/* - * linux/include/asm-arm/arch-a5k/a.out.h - * - * Copyright (C) 1996 Russell King - */ - -#ifndef __ASM_ARCH_A_OUT_H -#define __ASM_ARCH_A_OUT_H - -#ifdef __KERNEL__ -#define STACK_TOP (0x01a00000) -#define LIBRARY_START_TEXT (0x00c00000) -#endif - -#endif - diff -u --recursive --new-file v2.1.105/linux/include/asm-arm/arch-a5k/dma.h linux/include/asm-arm/arch-a5k/dma.h --- v2.1.105/linux/include/asm-arm/arch-a5k/dma.h Fri May 8 23:14:54 1998 +++ linux/include/asm-arm/arch-a5k/dma.h Wed Dec 31 16:00:00 1969 @@ -1,101 +0,0 @@ -#ifndef __ASM_ARCH_DMA_H -#define __ASM_ARCH_DMA_H - -#define MAX_DMA_ADDRESS 0x03000000 - -#ifdef KERNEL_ARCH_DMA - -static inline void arch_disable_dma (int dmanr) -{ - printk (dma_str, "arch_disable_dma", dmanr); -} - -static inline void arch_enable_dma (int dmanr) -{ - printk (dma_str, "arch_enable_dma", dmanr); -} - -static inline void arch_set_dma_addr (int dmanr, unsigned int addr) -{ - printk (dma_str, "arch_set_dma_addr", dmanr); -} - -static inline void arch_set_dma_count (int dmanr, unsigned int count) -{ - printk (dma_str, "arch_set_dma_count", dmanr); -} - -static inline void arch_set_dma_mode (int dmanr, char mode) -{ - printk (dma_str, "arch_set_dma_mode", dmanr); -} - -static inline int arch_dma_count (int dmanr) -{ - printk (dma_str, "arch_dma_count", dmanr); - return 0; -} - -#endif - -/* enable/disable a specific DMA channel */ -extern void enable_dma(unsigned int dmanr); - -static __inline__ void disable_dma(unsigned int dmanr) -{ - switch(dmanr) { - case 2: disable_irq(64); break; - default: printk (dma_str, "disable_dma", dmanr); break; - } -} - -/* Clear the 'DMA Pointer Flip Flop'. - * Write 0 for LSB/MSB, 1 for MSB/LSB access. - * Use this once to initialize the FF to a known state. - * After that, keep track of it. :-) - * --- In order to do that, the DMA routines below should --- - * --- only be used while interrupts are disabled! --- - */ -static __inline__ void clear_dma_ff(unsigned int dmanr) -{ - switch(dmanr) { - case 2: break; - default: printk (dma_str, "clear_dma_ff", dmanr); break; - } -} - -/* set mode (above) for a specific DMA channel */ -extern void set_dma_mode(unsigned int dmanr, char mode); - -/* Set only the page register bits of the transfer address. - * This is used for successive transfers when we know the contents of - * the lower 16 bits of the DMA current address register, but a 64k boundary - * may have been crossed. - */ -static __inline__ void set_dma_page(unsigned int dmanr, char pagenr) -{ - printk (dma_str, "set_dma_page", dmanr); -} - - -/* Set transfer address & page bits for specific DMA channel. - * Assumes dma flipflop is clear. - */ -extern void set_dma_addr(unsigned int dmanr, unsigned int addr); - -/* Set transfer size for a specific DMA channel. - */ -extern void set_dma_count(unsigned int dmanr, unsigned int count); - -/* Get DMA residue count. After a DMA transfer, this - * should return zero. Reading this while a DMA transfer is - * still in progress will return unpredictable results. - * If called before the channel has been used, it may return 1. - * Otherwise, it returns the number of _bytes_ left to transfer. - * - * Assumes DMA flip-flop is clear. - */ -extern int get_dma_residue(unsigned int dmanr); - -#endif /* _ASM_ARCH_DMA_H */ - diff -u --recursive --new-file v2.1.105/linux/include/asm-arm/arch-a5k/hardware.h linux/include/asm-arm/arch-a5k/hardware.h --- v2.1.105/linux/include/asm-arm/arch-a5k/hardware.h Fri May 8 23:14:54 1998 +++ linux/include/asm-arm/arch-a5k/hardware.h Wed Dec 31 16:00:00 1969 @@ -1,81 +0,0 @@ -/* - * linux/include/asm-arm/arch-a5k/hardware.h - * - * Copyright (C) 1996 Russell King. - * - * This file contains the hardware definitions of the A5000 series machines. - */ - -#ifndef __ASM_ARCH_HARDWARE_H -#define __ASM_ARCH_HARDWARE_H - -/* - * What hardware must be present - */ -#define HAS_IOC -#define HAS_PCIO -#define HAS_MEMC -#define HAS_MEMC1A -#define HAS_VIDC - -/* - * Optional hardware - */ -#define HAS_EXPMASK - -#ifndef __ASSEMBLER__ - -/* - * for use with inb/outb - */ -#define VIDC_BASE 0x80100000 -#define IOCEC4IO_BASE 0x8009c000 -#define IOCECIO_BASE 0x80090000 -#define IOC_BASE 0x80080000 -#define MEMCECIO_BASE 0x80000000 - -/* - * IO definitions - */ -#define EXPMASK_BASE ((volatile unsigned char *)0x03360000) -#define IOEB_BASE ((volatile unsigned char *)0x03350050) -#define PCIO_FLOPPYDMABASE ((volatile unsigned char *)0x0302a000) -#define PCIO_BASE 0x03010000 - -/* - * Mapping areas - */ -#define IO_END 0x03ffffff -#define IO_BASE 0x03000000 -#define IO_SIZE (IO_END - IO_BASE) -#define IO_START 0x03000000 - -/* - * Screen mapping information - */ -#define SCREEN2_END 0x02078000 -#define SCREEN2_BASE 0x02000000 -#define SCREEN1_END SCREEN2_BASE -#define SCREEN1_BASE 0x01f88000 -#define SCREEN_START 0x02000000 - -/* - * RAM definitions - */ -#define MAPTOPHYS(a) (((unsigned long)a & 0x007fffff) + PAGE_OFFSET) -#define KERNTOPHYS(a) ((((unsigned long)(&a)) & 0x007fffff) + PAGE_OFFSET) -#define GET_MEMORY_END(p) (PAGE_OFFSET + (p->u1.s.page_size) * (p->u1.s.nr_pages)) -#define PARAMS_BASE (PAGE_OFFSET + 0x7c000) -#define KERNEL_BASE (PAGE_OFFSET + 0x80000) - -#else - -#define IOEB_BASE 0x03350050 -#define IOC_BASE 0x03200000 -#define PCIO_FLOPPYDMABASE 0x0302a000 -#define PCIO_BASE 0x03010000 -#define IO_BASE 0x03000000 - -#endif -#endif - diff -u --recursive --new-file v2.1.105/linux/include/asm-arm/arch-a5k/ide.h linux/include/asm-arm/arch-a5k/ide.h --- v2.1.105/linux/include/asm-arm/arch-a5k/ide.h Fri May 8 23:14:54 1998 +++ linux/include/asm-arm/arch-a5k/ide.h Wed Dec 31 16:00:00 1969 @@ -1,44 +0,0 @@ -/* - * linux/include/asm-arm/arch-a5k/ide.h - * - * Copyright (c) 1997 Russell King - */ - -static __inline__ int -ide_default_irq(ide_ioreg_t base) -{ - if (base == 0x1f0) - return 11; - return 0; -} - -static __inline__ ide_ioreg_t -ide_default_io_base(int index) -{ - if (index == 0) - return 0x1f0; - return 0; -} - -static __inline__ int -ide_default_stepping(int index) -{ - return 0; -} - -static __inline__ void -ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int stepping, int *irq) -{ - ide_ioreg_t port = base; - ide_ioreg_t ctrl = base + 0x206; - int i; - - i = 8; - while (i--) { - *p++ = port; - port += 1 << stepping; - } - *p++ = ctrl; - if (irq != NULL) - irq = 0; -} diff -u --recursive --new-file v2.1.105/linux/include/asm-arm/arch-a5k/io.h linux/include/asm-arm/arch-a5k/io.h --- v2.1.105/linux/include/asm-arm/arch-a5k/io.h Fri May 8 23:14:54 1998 +++ linux/include/asm-arm/arch-a5k/io.h Wed Dec 31 16:00:00 1969 @@ -1,215 +0,0 @@ -/* - * linux/include/asm-arm/arch-a5k/io.h - * - * Copyright (C) 1997 Russell King - * - * Modifications: - * 06-Dec-1997 RMK Created. - */ -#ifndef __ASM_ARM_ARCH_IO_H -#define __ASM_ARM_ARCH_IO_H - -/* - * Virtual view <-> DMA view memory address translations - * virt_to_bus: Used to translate the virtual address to an - * address suitable to be passed to set_dma_addr - * bus_to_virt: Used to convert an address for DMA operations - * to an address that the kernel can use. - */ -#define virt_to_bus(x) ((unsigned long)(x)) -#define bus_to_virt(x) ((void *)(x)) - -/* - * This architecture does not require any delayed IO, and - * has the constant-optimised IO - */ -#undef ARCH_IO_DELAY - -/* - * We use two different types of addressing - PC style addresses, and ARM - * addresses. PC style accesses the PC hardware with the normal PC IO - * addresses, eg 0x3f8 for serial#1. ARM addresses are 0x80000000+ - * and are translated to the start of IO. Note that all addresses are - * shifted left! - */ -#define __PORT_PCIO(x) (!((x) & 0x80000000)) - -/* - * Dynamic IO functions - let the compiler - * optimize the expressions - */ -extern __inline__ void __outb (unsigned int value, unsigned int port) -{ - unsigned long temp; - __asm__ __volatile__( - "tst %2, #0x80000000\n\t" - "mov %0, %4\n\t" - "addeq %0, %0, %3\n\t" - "strb %1, [%0, %2, lsl #2]" - : "=&r" (temp) - : "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) - : "cc"); -} - -extern __inline__ void __outw (unsigned int value, unsigned int port) -{ - unsigned long temp; - __asm__ __volatile__( - "tst %2, #0x80000000\n\t" - "mov %0, %4\n\t" - "addeq %0, %0, %3\n\t" - "str %1, [%0, %2, lsl #2]" - : "=&r" (temp) - : "r" (value|value<<16), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) - : "cc"); -} - -extern __inline__ void __outl (unsigned int value, unsigned int port) -{ - unsigned long temp; - __asm__ __volatile__( - "tst %2, #0x80000000\n\t" - "mov %0, %4\n\t" - "addeq %0, %0, %3\n\t" - "str %1, [%0, %2, lsl #2]" - : "=&r" (temp) - : "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) - : "cc"); -} - -#define DECLARE_DYN_IN(sz,fnsuffix,instr) \ -extern __inline__ unsigned sz __in##fnsuffix (unsigned int port) \ -{ \ - unsigned long temp, value; \ - __asm__ __volatile__( \ - "tst %2, #0x80000000\n\t" \ - "mov %0, %4\n\t" \ - "addeq %0, %0, %3\n\t" \ - "ldr" ##instr## " %1, [%0, %2, lsl #2]" \ - : "=&r" (temp), "=r" (value) \ - : "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) \ - : "cc"); \ - return (unsigned sz)value; \ -} - -extern __inline__ unsigned int __ioaddr (unsigned int port) \ -{ \ - if (__PORT_PCIO(port)) \ - return (unsigned int)(PCIO_BASE + (port << 2)); \ - else \ - return (unsigned int)(IO_BASE + (port << 2)); \ -} - -#define DECLARE_IO(sz,fnsuffix,instr) \ - DECLARE_DYN_IN(sz,fnsuffix,instr) - -DECLARE_IO(char,b,"b") -DECLARE_IO(short,w,"") -DECLARE_IO(long,l,"") - -#undef DECLARE_IO -#undef DECLARE_DYN_IN - -/* - * Constant address IO functions - * - * These have to be macros for the 'J' constraint to work - - * +/-4096 immediate operand. - */ -#define __outbc(value,port) \ -({ \ - if (__PORT_PCIO((port))) \ - __asm__ __volatile__( \ - "strb %0, [%1, %2]" \ - : : "r" (value), "r" (PCIO_BASE), "Jr" ((port) << 2)); \ - else \ - __asm__ __volatile__( \ - "strb %0, [%1, %2]" \ - : : "r" (value), "r" (IO_BASE), "r" ((port) << 2)); \ -}) - -#define __inbc(port) \ -({ \ - unsigned char result; \ - if (__PORT_PCIO((port))) \ - __asm__ __volatile__( \ - "ldrb %0, [%1, %2]" \ - : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \ - else \ - __asm__ __volatile__( \ - "ldrb %0, [%1, %2]" \ - : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \ - result; \ -}) - -#define __outwc(value,port) \ -({ \ - unsigned long v = value; \ - if (__PORT_PCIO((port))) \ - __asm__ __volatile__( \ - "str %0, [%1, %2]" \ - : : "r" (v|v<<16), "r" (PCIO_BASE), "Jr" ((port) << 2)); \ - else \ - __asm__ __volatile__( \ - "str %0, [%1, %2]" \ - : : "r" (v|v<<16), "r" (IO_BASE), "r" ((port) << 2)); \ -}) - -#define __inwc(port) \ -({ \ - unsigned short result; \ - if (__PORT_PCIO((port))) \ - __asm__ __volatile__( \ - "ldr %0, [%1, %2]" \ - : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \ - else \ - __asm__ __volatile__( \ - "ldr %0, [%1, %2]" \ - : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \ - result & 0xffff; \ -}) - -#define __outlc(v,p) __outwc((v),(p)) - -#define __inlc(port) \ -({ \ - unsigned long result; \ - if (__PORT_PCIO((port))) \ - __asm__ __volatile__( \ - "ldr %0, [%1, %2]" \ - : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \ - else \ - __asm__ __volatile__( \ - "ldr %0, [%1, %2]" \ - : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \ - result; \ -}) - -#define __ioaddrc(port) \ -({ \ - unsigned long addr; \ - if (__PORT_PCIO((port))) \ - addr = PCIO_BASE + ((port) << 2); \ - else \ - addr = IO_BASE + ((port) << 2); \ - addr; \ -}) - -/* - * Translated address IO functions - * - * IO address has already been translated to a virtual address - */ -#define outb_t(v,p) \ - (*(volatile unsigned char *)(p) = (v)) - -#define inb_t(p) \ - (*(volatile unsigned char *)(p)) - -#define outl_t(v,p) \ - (*(volatile unsigned long *)(p) = (v)) - -#define inl_t(p) \ - (*(volatile unsigned long *)(p)) - -#endif diff -u --recursive --new-file v2.1.105/linux/include/asm-arm/arch-a5k/irq.h linux/include/asm-arm/arch-a5k/irq.h --- v2.1.105/linux/include/asm-arm/arch-a5k/irq.h Fri May 8 23:14:54 1998 +++ linux/include/asm-arm/arch-a5k/irq.h Wed Dec 31 16:00:00 1969 @@ -1,130 +0,0 @@ -/* - * include/asm-arm/arch-a5k/irq.h - * - * Copyright (C) 1996 Russell King - * - * Changelog: - * 24-09-1996 RMK Created - * 10-10-1996 RMK Brought up to date with arch-sa110eval - * 22-10-1996 RMK Changed interrupt numbers & uses new inb/outb macros - * 11-01-1998 RMK Added mask_and_ack_irq - */ - -#define BUILD_IRQ(s,n,m) \ - void IRQ##n##_interrupt(void); \ - void fast_IRQ##n##_interrupt(void); \ - void bad_IRQ##n##_interrupt(void); \ - void probe_IRQ##n##_interrupt(void); - -/* - * The timer is a special interrupt - */ -#define IRQ5_interrupt timer_IRQ_interrupt - -#define IRQ_INTERRUPT(n) IRQ##n##_interrupt -#define FAST_INTERRUPT(n) fast_IRQ##n##_interrupt -#define BAD_INTERRUPT(n) bad_IRQ##n##_interrupt -#define PROBE_INTERRUPT(n) probe_IRQ##n##_interrupt - -#define X(x) (x)|0x01, (x)|0x02, (x)|0x04, (x)|0x08, (x)|0x10, (x)|0x20, (x)|0x40, (x)|0x80 -#define Z(x) (x), (x), (x), (x), (x), (x), (x), (x) - -static __inline__ void mask_and_ack_irq(unsigned int irq) -{ - static const int addrmasks[] = { - X((IOC_IRQMASKA - IOC_BASE)<<18 | (1 << 15)), - X((IOC_IRQMASKB - IOC_BASE)<<18), - Z(0), - Z(0), - Z(0), - Z(0), - Z(0), - Z(0), - X((IOC_FIQMASK - IOC_BASE)<<18), - Z(0), - Z(0), - Z(0), - Z(0), - Z(0), - Z(0), - Z(0) - }; - unsigned int temp1, temp2; - - __asm__ __volatile__( -" ldr %1, [%5, %3, lsl #2]\n" -" teq %1, #0\n" -" beq 2f\n" -" ldrb %0, [%2, %1, lsr #16]\n" -" bic %0, %0, %1\n" -" strb %0, [%2, %1, lsr #16]\n" -" tst %1, #0x8000\n" /* do we need an IRQ clear? */ -" strneb %1, [%2, %4]\n" -"2:" - : "=&r" (temp1), "=&r" (temp2) - : "r" (ioaddr(IOC_BASE)), "r" (irq), - "I" ((IOC_IRQCLRA - IOC_BASE) << 2), "r" (addrmasks)); -} - -#undef X -#undef Z - -static __inline__ void mask_irq(unsigned int irq) -{ - extern void ecard_disableirq (unsigned int); - extern void ecard_disablefiq (unsigned int); - unsigned char mask = 1 << (irq & 7); - - switch (irq >> 3) { - case 0: - outb(inb(IOC_IRQMASKA) & ~mask, IOC_IRQMASKA); - break; - case 1: - outb(inb(IOC_IRQMASKB) & ~mask, IOC_IRQMASKB); - break; - case 4: - ecard_disableirq (irq & 7); - break; - case 8: - outb(inb(IOC_FIQMASK) & ~mask, IOC_FIQMASK); - break; - case 12: - ecard_disablefiq (irq & 7); - } -} - -static __inline__ void unmask_irq(unsigned int irq) -{ - extern void ecard_enableirq (unsigned int); - extern void ecard_enablefiq (unsigned int); - unsigned char mask = 1 << (irq & 7); - - switch (irq >> 3) { - case 0: - outb(inb(IOC_IRQMASKA) | mask, IOC_IRQMASKA); - break; - case 1: - outb(inb(IOC_IRQMASKB) | mask, IOC_IRQMASKB); - break; - case 4: - ecard_enableirq (irq & 7); - break; - case 8: - outb(inb(IOC_FIQMASK) | mask, IOC_FIQMASK); - break; - case 12: - ecard_enablefiq (irq & 7); - } -} - -static __inline__ unsigned long get_enabled_irqs(void) -{ - return inb(IOC_IRQMASKA) | inb(IOC_IRQMASKB) << 8; -} - -static __inline__ void irq_init_irq(void) -{ - outb(0, IOC_IRQMASKA); - outb(0, IOC_IRQMASKB); - outb(0, IOC_FIQMASK); -} diff -u --recursive --new-file v2.1.105/linux/include/asm-arm/arch-a5k/irqs.h linux/include/asm-arm/arch-a5k/irqs.h --- v2.1.105/linux/include/asm-arm/arch-a5k/irqs.h Fri May 8 23:14:54 1998 +++ linux/include/asm-arm/arch-a5k/irqs.h Wed Dec 31 16:00:00 1969 @@ -1,28 +0,0 @@ -/* - * linux/include/asm-arm/arch-a5k/irqs.h - * - * Copyright (C) 1996 Russell King - */ - -#define IRQ_PRINTER 0 -#define IRQ_BATLOW 1 -#define IRQ_FLOPPYINDEX 2 -#define IRQ_VSYNCPULSE 3 -#define IRQ_POWERON 4 -#define IRQ_TIMER0 5 -#define IRQ_TIMER1 6 -#define IRQ_IMMEDIATE 7 -#define IRQ_EXPCARDFIQ 8 -#define IRQ_SOUNDCHANGE 9 -#define IRQ_SERIALPORT 10 -#define IRQ_HARDDISK 11 -#define IRQ_FLOPPYDISK 12 -#define IRQ_EXPANSIONCARD 13 -#define IRQ_KEYBOARDTX 14 -#define IRQ_KEYBOARDRX 15 - -#define FIQ_FLOPPYDATA 0 -#define FIQ_ECONET 2 -#define FIQ_SERIALPORT 4 -#define FIQ_EXPANSIONCARD 6 -#define FIQ_FORCE 7 diff -u --recursive --new-file v2.1.105/linux/include/asm-arm/arch-a5k/mmu.h linux/include/asm-arm/arch-a5k/mmu.h --- v2.1.105/linux/include/asm-arm/arch-a5k/mmu.h Fri May 8 23:14:54 1998 +++ linux/include/asm-arm/arch-a5k/mmu.h Wed Dec 31 16:00:00 1969 @@ -1,15 +0,0 @@ -/* - * linux/include/asm-arm/arch-a5k/mmu.h - * - * Copyright (c) 1996 Russell King. - * - * Changelog: - * 22-11-1996 RMK Created - */ -#ifndef __ASM_ARCH_MMU_H -#define __ASM_ARCH_MMU_H - -#define __virt_to_phys(vpage) vpage -#define __phys_to_virt(ppage) ppage - -#endif diff -u --recursive --new-file v2.1.105/linux/include/asm-arm/arch-a5k/oldlatches.h linux/include/asm-arm/arch-a5k/oldlatches.h --- v2.1.105/linux/include/asm-arm/arch-a5k/oldlatches.h Fri May 8 23:14:54 1998 +++ linux/include/asm-arm/arch-a5k/oldlatches.h Wed Dec 31 16:00:00 1969 @@ -1,9 +0,0 @@ -/* - * Dummy oldlatches.h - * - * Copyright (C) 1996 Russell King - */ - -#ifdef __need_oldlatches -#error "Old latches not present in this (a5k) machine" -#endif diff -u --recursive --new-file v2.1.105/linux/include/asm-arm/arch-a5k/processor.h linux/include/asm-arm/arch-a5k/processor.h --- v2.1.105/linux/include/asm-arm/arch-a5k/processor.h Fri May 8 23:14:54 1998 +++ linux/include/asm-arm/arch-a5k/processor.h Wed Dec 31 16:00:00 1969 @@ -1,35 +0,0 @@ -/* - * linux/include/asm-arm/arch-a5k/processor.h - * - * Copyright (c) 1996 Russell King. - * - * Changelog: - * 10-09-1996 RMK Created - */ - -#ifndef __ASM_ARCH_PROCESSOR_H -#define __ASM_ARCH_PROCESSOR_H - -/* - * Bus types - */ -#define EISA_bus 0 -#define EISA_bus__is_a_macro /* for versions in ksyms.c */ -#define MCA_bus 0 -#define MCA_bus__is_a_macro /* for versions in ksyms.c */ - -/* - * User space: 26MB - */ -#define TASK_SIZE (0x01a00000UL) - -/* This decides where the kernel will search for a free chunk of vm - * space during mmap's. - */ -#define TASK_UNMAPPED_BASE(off) (TASK_SIZE / 3) -#define TASK_UNMAPPED_ALIGN(addr, off) PAGE_ALIGN(addr) - -#define INIT_MMAP \ -{ &init_mm, 0, 0x02000000, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap } - -#endif diff -u --recursive --new-file v2.1.105/linux/include/asm-arm/arch-a5k/serial.h linux/include/asm-arm/arch-a5k/serial.h --- v2.1.105/linux/include/asm-arm/arch-a5k/serial.h Fri May 8 23:14:54 1998 +++ linux/include/asm-arm/arch-a5k/serial.h Wed Dec 31 16:00:00 1969 @@ -1,40 +0,0 @@ -/* - * linux/include/asm-arm/arch-a5k/serial.h - * - * Copyright (c) 1996 Russell King. - * - * Changelog: - * 15-10-1996 RMK Created - */ -#ifndef __ASM_ARCH_SERIAL_H -#define __ASM_ARCH_SERIAL_H - -/* - * This assumes you have a 1.8432 MHz clock for your UART. - * - * It'd be nice if someone built a serial card with a 24.576 MHz - * clock, since the 16550A is capable of handling a top speed of 1.5 - * megabits/second; but this requires the faster clock. - */ -#define BASE_BAUD (1843200 / 16) - -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) - - /* UART CLK PORT IRQ FLAGS */ -#define RS_UARTS \ - { 0, BASE_BAUD, 0x3F8, 10, STD_COM_FLAGS }, /* ttyS0 */ \ - { 0, BASE_BAUD, 0x2F8, 10, STD_COM_FLAGS }, /* ttyS1 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS2 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS3 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS4 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS5 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS6 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS7 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS8 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS9 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS10 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS11 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS12 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS13 */ - -#endif diff -u --recursive --new-file v2.1.105/linux/include/asm-arm/arch-a5k/shmparam.h linux/include/asm-arm/arch-a5k/shmparam.h --- v2.1.105/linux/include/asm-arm/arch-a5k/shmparam.h Fri May 8 23:14:54 1998 +++ linux/include/asm-arm/arch-a5k/shmparam.h Wed Dec 31 16:00:00 1969 @@ -1,5 +0,0 @@ -/* - * linux/include/asm-arm/arch-a5k/shmparam.h - * - * Copyright (c) 1996 Russell King. - */ diff -u --recursive --new-file v2.1.105/linux/include/asm-arm/arch-a5k/system.h linux/include/asm-arm/arch-a5k/system.h --- v2.1.105/linux/include/asm-arm/arch-a5k/system.h Fri May 8 23:14:54 1998 +++ linux/include/asm-arm/arch-a5k/system.h Wed Dec 31 16:00:00 1969 @@ -1,30 +0,0 @@ -/* - * linux/include/asm-arm/arch-a5k/system.h - * - * Copyright (c) 1996 Russell King - */ -#ifndef __ASM_ARCH_SYSTEM_H -#define __ASM_ARCH_SYSTEM_H - -extern __inline__ void arch_hard_reset (void) -{ - extern void ecard_reset (int card); - - /* - * Reset all expansion cards. - */ - ecard_reset (-1); - - /* - * copy branch instruction to reset location and call it - */ - *(unsigned long *)0 = *(unsigned long *)0x03800000; - ((void(*)(void))0)(); - - /* - * If that didn't work, loop endlessly - */ - while (1); -} - -#endif diff -u --recursive --new-file v2.1.105/linux/include/asm-arm/arch-a5k/time.h linux/include/asm-arm/arch-a5k/time.h --- v2.1.105/linux/include/asm-arm/arch-a5k/time.h Fri May 8 23:14:54 1998 +++ linux/include/asm-arm/arch-a5k/time.h Wed Dec 31 16:00:00 1969 @@ -1,96 +0,0 @@ -/* - * linux/include/asm-arm/arch-a5k/time.h - * - * Copyright (c) 1996 Russell King. - * - * Changelog: - * 24-Sep-1996 RMK Created - * 10-Oct-1996 RMK Brought up to date with arch-sa110eval - * 04-Dec-1997 RMK Updated for new arch/arm/time.c - */ - -extern __inline__ unsigned long gettimeoffset (void) -{ - unsigned int count1, count2, status1, status2; - unsigned long offset = 0; - - status1 = IOC_IRQREQA; - barrier (); - outb (0, IOC_T0LATCH); - barrier (); - count1 = inb(IOC_T0CNTL) | (inb(IOC_T0CNTH) << 8); - barrier (); - status2 = inb(IOC_IRQREQA); - barrier (); - outb (0, IOC_T0LATCH); - barrier (); - count2 = inb(IOC_T0CNTL) | (inb(IOC_T0CNTH) << 8); - - if (count2 < count1) { - /* - * This means that we haven't just had an interrupt - * while reading into status2. - */ - if (status2 & (1 << 5)) - offset = tick; - count1 = count2; - } else if (count2 > count1) { - /* - * We have just had another interrupt while reading - * status2. - */ - offset += tick; - count1 = count2; - } - - count1 = LATCH - count1; - /* - * count1 = number of clock ticks since last interrupt - */ - offset += count1 * tick / LATCH; - return offset; -} - -/* - * No need to reset the timer at every irq - */ -#define reset_timer() 1 - -/* - * Updating of the RTC. We don't currently write the time to the - * CMOS clock. - */ -#define update_rtc() - -/* - * Set up timer interrupt, and return the current time in seconds. - */ -extern __inline__ unsigned long setup_timer (void) -{ - extern int iic_control (unsigned char, int, char *, int); - unsigned int year, mon, day, hour, min, sec; - char buf[8]; - - outb(LATCH & 255, IOC_T0LTCHL); - outb(LATCH >> 8, IOC_T0LTCHH); - outb(0, IOC_T0GO); - - iic_control (0xa0, 0xc0, buf, 1); - year = buf[0]; - if ((year += 1900) < 1970) - year += 100; - - iic_control (0xa0, 2, buf, 5); - mon = buf[4] & 0x1f; - day = buf[3] & 0x3f; - hour = buf[2]; - min = buf[1]; - sec = buf[0]; - BCD_TO_BIN(mon); - BCD_TO_BIN(day); - BCD_TO_BIN(hour); - BCD_TO_BIN(min); - BCD_TO_BIN(sec); - - return mktime(year, mon, day, hour, min, sec); -} diff -u --recursive --new-file v2.1.105/linux/include/asm-arm/arch-a5k/timex.h linux/include/asm-arm/arch-a5k/timex.h --- v2.1.105/linux/include/asm-arm/arch-a5k/timex.h Fri May 8 23:14:54 1998 +++ linux/include/asm-arm/arch-a5k/timex.h Wed Dec 31 16:00:00 1969 @@ -1,13 +0,0 @@ -/* - * linux/include/asm-arm/arch-a5k/timex.h - * - * A5000 architecture timex specifications - * - * Copyright (C) 1997, 1998 Russell King - */ - -/* - * On the RiscPC, the clock ticks at 2MHz. - */ -#define CLOCK_TICK_RATE 2000000 - diff -u --recursive --new-file v2.1.105/linux/include/asm-arm/arch-a5k/uncompress.h linux/include/asm-arm/arch-a5k/uncompress.h --- v2.1.105/linux/include/asm-arm/arch-a5k/uncompress.h Fri May 8 23:14:54 1998 +++ linux/include/asm-arm/arch-a5k/uncompress.h Wed Dec 31 16:00:00 1969 @@ -1,104 +0,0 @@ -/* - * linux/include/asm-arm/arch-a5k/uncompress.h - * - * Copyright (C) 1996 Russell King - */ -#define VIDMEM ((char *)0x02000000) - -#include "../arch/arm/drivers/char/font.h" - -int video_num_columns, video_num_lines, video_size_row; -int white, bytes_per_char_h; -extern unsigned long con_charconvtable[256]; - -struct param_struct { - unsigned long page_size; - unsigned long nr_pages; - unsigned long ramdisk_size; - unsigned long mountrootrdonly; - unsigned long rootdev; - unsigned long video_num_cols; - unsigned long video_num_rows; - unsigned long video_x; - unsigned long video_y; - unsigned long memc_control_reg; - unsigned char sounddefault; - unsigned char adfsdrives; - unsigned char bytes_per_char_h; - unsigned char bytes_per_char_v; - unsigned long unused[256/4-11]; -}; - -static struct param_struct *params = (struct param_struct *)0x0207c000; - -/* - * This does not append a newline - */ -static void puts(const char *s) -{ - extern void ll_write_char(char *, unsigned long); - int x,y; - unsigned char c; - char *ptr; - - x = params->video_x; - y = params->video_y; - - while ( ( c = *(unsigned char *)s++ ) != '\0' ) { - if ( c == '\n' ) { - x = 0; - if ( ++y >= video_num_lines ) { - y--; - } - } else { - ptr = VIDMEM + ((y*video_num_columns*params->bytes_per_char_v+x)*bytes_per_char_h); - ll_write_char(ptr, c|(white<<8)); - if ( ++x >= video_num_columns ) { - x = 0; - if ( ++y >= video_num_lines ) { - y--; - } - } - } - } - - params->video_x = x; - params->video_y = y; -} - -static void error(char *x); - -/* - * Setup for decompression - */ -static void arch_decomp_setup(void) -{ - int i; - - video_num_lines = params->video_num_rows; - video_num_columns = params->video_num_cols; - bytes_per_char_h = params->bytes_per_char_h; - video_size_row = video_num_columns * bytes_per_char_h; - if (bytes_per_char_h == 4) - for (i = 0; i < 256; i++) - con_charconvtable[i] = - (i & 128 ? 1 << 0 : 0) | - (i & 64 ? 1 << 4 : 0) | - (i & 32 ? 1 << 8 : 0) | - (i & 16 ? 1 << 12 : 0) | - (i & 8 ? 1 << 16 : 0) | - (i & 4 ? 1 << 20 : 0) | - (i & 2 ? 1 << 24 : 0) | - (i & 1 ? 1 << 28 : 0); - else - for (i = 0; i < 16; i++) - con_charconvtable[i] = - (i & 8 ? 1 << 0 : 0) | - (i & 4 ? 1 << 8 : 0) | - (i & 2 ? 1 << 16 : 0) | - (i & 1 ? 1 << 24 : 0); - - white = bytes_per_char_h == 8 ? 0xfc : 7; - - if (params->nr_pages * params->page_size < 4096*1024) error("<4M of mem\n"); -} diff -u --recursive --new-file v2.1.105/linux/include/asm-arm/arch-ebsa110/mmap.h linux/include/asm-arm/arch-ebsa110/mmap.h --- v2.1.105/linux/include/asm-arm/arch-ebsa110/mmap.h Fri May 8 23:14:54 1998 +++ linux/include/asm-arm/arch-ebsa110/mmap.h Wed Dec 31 16:00:00 1969 @@ -1,10 +0,0 @@ -/* - * linux/include/asm-arm/arch-ebsa110/mmap.h - * - * Copyright (C) 1996,1997,1998 Russell King - */ - -/* - * Use SRAM for cache flushing - */ -#define SAFE_ADDR 0x40000000 diff -u --recursive --new-file v2.1.105/linux/include/asm-arm/arch-ebsa285/io.h linux/include/asm-arm/arch-ebsa285/io.h --- v2.1.105/linux/include/asm-arm/arch-ebsa285/io.h Tue Apr 14 14:29:25 1998 +++ linux/include/asm-arm/arch-ebsa285/io.h Sat Jun 13 13:11:12 1998 @@ -140,4 +140,26 @@ #define inl_t(p) \ (*(volatile unsigned long *)(p)) +/* + * This is not sufficient... (and it's a hack anyway) + */ +static inline void writeb(unsigned char b, unsigned int addr) +{ + *(volatile unsigned char *)(0xe0000000 + (addr)) = b; +} + +static inline unsigned char readb(unsigned int addr) +{ + return *(volatile unsigned char *)(0xe0000000 + (addr)); +} + +static inline void writew(unsigned short b, unsigned int addr) +{ + *(volatile unsigned short *)(0xe0000000 + (addr)) = b; +} + +static inline unsigned short readw(unsigned int addr) +{ + return *(volatile unsigned short *)(0xe0000000 + (addr)); +} #endif diff -u --recursive --new-file v2.1.105/linux/include/asm-arm/arch-ebsa285/processor.h linux/include/asm-arm/arch-ebsa285/processor.h --- v2.1.105/linux/include/asm-arm/arch-ebsa285/processor.h Fri May 8 23:14:54 1998 +++ linux/include/asm-arm/arch-ebsa285/processor.h Sat Jun 13 13:11:12 1998 @@ -23,7 +23,11 @@ /* This decides where the kernel will search for a free chunk of vm * space during mmap's. */ +#if 0 #define TASK_UNMAPPED_BASE(off) (TASK_SIZE / 3) +#else +#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) +#endif #define TASK_UNMAPPED_ALIGN(addr, off) PAGE_ALIGN(addr) #define INIT_MMAP \ diff -u --recursive --new-file v2.1.105/linux/include/asm-arm/arch-nexuspci/mmap.h linux/include/asm-arm/arch-nexuspci/mmap.h --- v2.1.105/linux/include/asm-arm/arch-nexuspci/mmap.h Fri May 8 23:14:54 1998 +++ linux/include/asm-arm/arch-nexuspci/mmap.h Wed Dec 31 16:00:00 1969 @@ -1,10 +0,0 @@ -/* - * linux/include/asm-arm/arch-ebsa110/mmap.h - * - * Copyright (C) 1996,1997,1998 Russell King - */ - -/* - * Use SRAM for cache flushing - */ -#define SAFE_ADDR 0x40000000 diff -u --recursive --new-file v2.1.105/linux/include/asm-arm/arch-nexuspci/serial.h linux/include/asm-arm/arch-nexuspci/serial.h --- v2.1.105/linux/include/asm-arm/arch-nexuspci/serial.h Fri May 8 23:14:54 1998 +++ linux/include/asm-arm/arch-nexuspci/serial.h Wed Dec 31 16:00:00 1969 @@ -1,41 +0,0 @@ -/* - * linux/include/asm-arm/arch-ebsa110/serial.h - * - * Copyright (c) 1996,1997,1998 Russell King. - * - * Changelog: - * 15-10-1996 RMK Created - */ -#ifndef __ASM_ARCH_SERIAL_H -#define __ASM_ARCH_SERIAL_H - -/* - * This assumes you have a 1.8432 MHz clock for your UART. - * - * It'd be nice if someone built a serial card with a 24.576 MHz - * clock, since the 16550A is capable of handling a top speed of 1.5 - * megabits/second; but this requires the faster clock. - */ -#define BASE_BAUD (1843200 / 16) - -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) - - /* UART CLK PORT IRQ FLAGS */ -#define RS_UARTS \ - { 0, BASE_BAUD, 0x3F8, 1, STD_COM_FLAGS }, /* ttyS0 */ \ - { 0, BASE_BAUD, 0x2F8, 2, STD_COM_FLAGS }, /* ttyS1 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS2 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS3 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS4 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS5 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS6 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS7 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS8 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS9 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS10 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS11 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS12 */ \ - { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS13 */ - -#endif - diff -u --recursive --new-file v2.1.105/linux/include/asm-arm/arch-rpc/mmap.h linux/include/asm-arm/arch-rpc/mmap.h --- v2.1.105/linux/include/asm-arm/arch-rpc/mmap.h Fri May 8 23:14:54 1998 +++ linux/include/asm-arm/arch-rpc/mmap.h Wed Dec 31 16:00:00 1969 @@ -1,48 +0,0 @@ -/* - * linux/include/asm-arm/arch-rpc/mmap.h - * - * Copyright (C) 1996 Russell King - */ - -#define HAVE_MAP_VID_MEM -#define SAFE_ADDR 0x00000000 /* ROM */ - -unsigned long map_screen_mem(unsigned long log_start, unsigned long kmem, int update) -{ - static int updated = 0; - unsigned long address; - pgd_t *pgd; - - if (updated) - return 0; - updated = update; - - address = SCREEN_START | PMD_TYPE_SECT | PMD_DOMAIN(DOMAIN_KERNEL) | PMD_SECT_AP_WRITE; - pgd = swapper_pg_dir + (SCREEN2_BASE >> PGDIR_SHIFT); - pgd_val(pgd[0]) = address; - pgd_val(pgd[1]) = address + (1 << PGDIR_SHIFT); - - if (update) { - unsigned long pgtable = PAGE_ALIGN(kmem), *p; - int i; - - memzero ((void *)pgtable, 4096); - - pgd_val(pgd[-2]) = virt_to_phys(pgtable) | PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_KERNEL); - pgd_val(pgd[-1]) = virt_to_phys(pgtable + PTRS_PER_PTE*4) | PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_KERNEL); - p = (unsigned long *)pgtable; - - i = PTRS_PER_PTE * 2 - ((SCREEN1_END - log_start) >> PAGE_SHIFT); - address = SCREEN_START | PTE_TYPE_SMALL | PTE_AP_WRITE; - - while (i < PTRS_PER_PTE * 2) { - p[i++] = address; - address += PAGE_SIZE; - } - - flush_page_to_ram(pgtable); - - kmem = pgtable + PAGE_SIZE; - } - return kmem; -} diff -u --recursive --new-file v2.1.105/linux/include/asm-arm/bitops.h linux/include/asm-arm/bitops.h --- v2.1.105/linux/include/asm-arm/bitops.h Tue Jan 20 16:39:42 1998 +++ linux/include/asm-arm/bitops.h Sat Jun 13 12:56:46 1998 @@ -53,6 +53,24 @@ return k; } +/* + * ffs: find first bit set. This is defined the same way as + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + */ + +#define ffs(x) generic_ffs(x) + +/* + * hweightN: returns the hamming weight (i.e. the number + * of bits set) of a N-bit word + */ + +#define hweight32(x) generic_hweight32(x) +#define hweight16(x) generic_hweight16(x) +#define hweight8(x) generic_hweight8(x) + + #ifdef __KERNEL__ #define ext2_set_bit test_and_set_bit diff -u --recursive --new-file v2.1.105/linux/include/asm-arm/fiq.h linux/include/asm-arm/fiq.h --- v2.1.105/linux/include/asm-arm/fiq.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/fiq.h Sat Jun 13 13:11:12 1998 @@ -0,0 +1,16 @@ +/* Support for FIQ on ARM architectures. + * Written by Philip Blundell , 1998 + */ + +#ifndef __ASM_FIQ_H +#define __ASM_FIQ_H + +struct fiq_handler { + const char *name; + int (*callback)(void); +}; + +extern int claim_fiq(struct fiq_handler *f); +extern void release_fiq(struct fiq_handler *f); + +#endif diff -u --recursive --new-file v2.1.105/linux/include/asm-arm/floppy.h linux/include/asm-arm/floppy.h --- v2.1.105/linux/include/asm-arm/floppy.h Tue Jan 20 16:39:42 1998 +++ linux/include/asm-arm/floppy.h Sat Jun 13 13:11:12 1998 @@ -9,7 +9,14 @@ #include #endif -#define fd_outb(val,port) outb((val),(port)) +#define fd_outb(val,port) \ + do { \ + if ((port) == FD_DOR) \ + fd_setdor((val)); \ + else \ + outb((val),(port)); \ + } while(0) + #define fd_inb(port) inb((port)) #define fd_request_irq() request_irq(IRQ_FLOPPYDISK,floppy_interrupt,\ SA_INTERRUPT|SA_SAMPLE_RANDOM,"floppy",NULL) @@ -27,6 +34,9 @@ #define fd_set_dma_count(len) set_dma_count(FLOPPY_DMA, (len)) #define fd_cacheflush(addr,sz) +/* need to clean up dma.h */ +#define DMA_FLOPPYDISK DMA_FLOPPY + /* Floppy_selects is the list of DOR's to select drive fd * * On initialisation, the floppy list is scanned, and the drives allocated @@ -40,13 +50,14 @@ { 0x10, 0x21, 0x23, 0x33 } }; -#define fd_setdor(dor) \ -do { \ - int new_dor = (dor); \ - if (new_dor & 0xf0) \ - fd_outb((new_dor & 0x0c) | floppy_selects[fdc][new_dor & 3], FD_DOR); \ - else \ - fd_outb((new_dor & 0x0c), FD_DOR); \ +#define fd_setdor(dor) \ +do { \ + int new_dor = (dor); \ + if (new_dor & 0xf0) \ + new_dor = (new_dor & 0x0c) | floppy_selects[fdc][new_dor & 3]; \ + else \ + new_dor &= 0x0c; \ + outb(new_dor, FD_DOR); \ } while (0) /* diff -u --recursive --new-file v2.1.105/linux/include/asm-arm/hardirq.h linux/include/asm-arm/hardirq.h --- v2.1.105/linux/include/asm-arm/hardirq.h Tue Apr 14 14:29:25 1998 +++ linux/include/asm-arm/hardirq.h Sat Jun 13 13:11:12 1998 @@ -5,6 +5,12 @@ extern unsigned int local_irq_count[NR_CPUS]; +/* + * Are we in an interrupt context? Either doing bottom half + * or hardware interrupt processing? + */ +#define in_interrupt() (local_irq_count[smp_processor_id()] + local_bh_count[smp_processor_id()] != 0) + #ifndef __SMP__ #define hardirq_trylock(cpu) (local_irq_count[cpu] == 0) diff -u --recursive --new-file v2.1.105/linux/include/asm-arm/io.h linux/include/asm-arm/io.h --- v2.1.105/linux/include/asm-arm/io.h Tue Apr 14 14:29:25 1998 +++ linux/include/asm-arm/io.h Sat Jun 13 13:11:12 1998 @@ -170,44 +170,5 @@ #undef ARCH_IO_DELAY #undef ARCH_IO_CONSTANT -/* - * Leftovers... - */ -#if 0 -#define __outwc(value,port) \ -({ \ - if (port < 256) \ - __asm__ __volatile__( \ - "strh %0, [%1, %2]" \ - : : "r" (value), "r" (PCIO_BASE), "J" (port << 2)); \ - else if (__PORT_PCIO(port)) \ - __asm__ __volatile__( \ - "strh %0, [%1, %2]" \ - : : "r" (value), "r" (PCIO_BASE), "r" (port << 2)); \ - else \ - __asm__ __volatile__( \ - "strh %0, [%1, %2]" \ - : : "r" (value), "r" (IO_BASE), "r" (port << 2)); \ -}) - -#define __inwc(port) \ -({ \ - unsigned short result; \ - if (port < 256) \ - __asm__ __volatile__( \ - "ldrh %0, [%1, %2]" \ - : "=r" (result) : "r" (PCIO_BASE), "J" (port << 2)); \ - else \ - if (__PORT_PCIO(port)) \ - __asm__ __volatile__( \ - "ldrh %0, [%1, %2]" \ - : "=r" (result) : "r" (PCIO_BASE), "r" (port << 2)); \ - else \ - __asm__ __volatile__( \ - "ldrh %0, [%1, %2]" \ - : "=r" (result) : "r" (IO_BASE), "r" (port << 2)); \ - result; \ -}) -#endif #endif diff -u --recursive --new-file v2.1.105/linux/include/asm-arm/ioctl.h linux/include/asm-arm/ioctl.h --- v2.1.105/linux/include/asm-arm/ioctl.h Fri May 8 23:14:54 1998 +++ linux/include/asm-arm/ioctl.h Sat Jun 13 13:11:12 1998 @@ -1,5 +1,4 @@ -/* $Id: ioctl.h,v 1.1 1998/01/28 09:56:22 ecd Exp $ - * +/* * linux/ioctl.h for Linux by H.H. Bergman. */ diff -u --recursive --new-file v2.1.105/linux/include/asm-arm/irq-no.h linux/include/asm-arm/irq-no.h --- v2.1.105/linux/include/asm-arm/irq-no.h Fri May 8 23:14:54 1998 +++ linux/include/asm-arm/irq-no.h Wed Dec 31 16:00:00 1969 @@ -1,11 +0,0 @@ -/* - * linux/include/asm-arm/irq-no.h - * - * Machine independent interrupt numbers - */ - -#include - -#ifndef NR_IRQS -#define NR_IRQS 128 -#endif diff -u --recursive --new-file v2.1.105/linux/include/asm-arm/namei.h linux/include/asm-arm/namei.h --- v2.1.105/linux/include/asm-arm/namei.h Fri May 8 23:14:54 1998 +++ linux/include/asm-arm/namei.h Sat Jun 13 13:11:12 1998 @@ -1,4 +1,4 @@ -/* $Id: namei.h,v 1.1 1998/01/28 09:56:37 ecd Exp $ +/* * linux/include/asm-i386/namei.h * * Included from linux/fs/namei.c diff -u --recursive --new-file v2.1.105/linux/include/asm-generic/bitops.h linux/include/asm-generic/bitops.h --- v2.1.105/linux/include/asm-generic/bitops.h Mon Aug 15 00:54:22 1994 +++ linux/include/asm-generic/bitops.h Sat Jun 13 12:56:46 1998 @@ -50,4 +50,22 @@ mask = 1 << (nr & 0x1f); return ((mask & *addr) != 0); } + +/* + * ffs: find first bit set. This is defined the same way as + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + */ + +#define ffs(x) generic_ffs(x) + +/* + * hweightN: returns the hamming weight (i.e. the number + * of bits set) of a N-bit word + */ + +#define hweight32(x) generic_hweight32(x) +#define hweight16(x) generic_hweight16(x) +#define hweight8(x) generic_hweight8(x) + #endif /* _ASM_GENERIC_BITOPS_H */ diff -u --recursive --new-file v2.1.105/linux/include/asm-i386/bitops.h linux/include/asm-i386/bitops.h --- v2.1.105/linux/include/asm-i386/bitops.h Mon Dec 1 11:16:57 1997 +++ linux/include/asm-i386/bitops.h Sat Jun 13 12:56:46 1998 @@ -187,6 +187,33 @@ return word; } +/* + * ffs: find first bit set. This is defined the same way as + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + */ + +extern __inline__ int ffs(int x) +{ + int r; + + __asm__("bsfl %1,%0\n\t" + "jnz 1f\n\t" + "movl $-1,%0\n" + "1:" : "=r" (r) : "g" (x)); + return r+1; +} + +/* + * hweightN: returns the hamming weight (i.e. the number + * of bits set) of a N-bit word + */ + +#define hweight32(x) generic_hweight32(x) +#define hweight16(x) generic_hweight16(x) +#define hweight8(x) generic_hweight8(x) + + #ifdef __KERNEL__ #define ext2_set_bit test_and_set_bit diff -u --recursive --new-file v2.1.105/linux/include/asm-i386/math_emu.h linux/include/asm-i386/math_emu.h --- v2.1.105/linux/include/asm-i386/math_emu.h Tue Dec 9 17:57:09 1997 +++ linux/include/asm-i386/math_emu.h Tue Jun 9 00:55:10 1998 @@ -3,8 +3,8 @@ #include -void restore_i387_soft(void *s387, struct _fpstate *buf); -struct _fpstate * save_i387_soft(void *s387, struct _fpstate * buf); +int restore_i387_soft(void *s387, struct _fpstate *buf); +int save_i387_soft(void *s387, struct _fpstate * buf); /* This structure matches the layout of the data saved to the stack following a device-not-present interrupt, part of it saved diff -u --recursive --new-file v2.1.105/linux/include/asm-i386/pgtable.h linux/include/asm-i386/pgtable.h --- v2.1.105/linux/include/asm-i386/pgtable.h Tue Mar 17 22:18:15 1998 +++ linux/include/asm-i386/pgtable.h Sat Jun 13 13:48:21 1998 @@ -12,8 +12,10 @@ * This file contains the functions and defines necessary to modify and use * the i386 page table tree. */ - #ifndef __ASSEMBLY__ +#include +#include + /* Caches aren't brain-dead on the intel. */ #define flush_cache_all() do { } while (0) #define flush_cache_mm(mm) do { } while (0) @@ -38,7 +40,7 @@ #define __flush_tlb() \ do { unsigned long tmpreg; __asm__ __volatile__("movl %%cr3,%0\n\tmovl %0,%%cr3":"=r" (tmpreg) : :"memory"); } while (0) -#if defined(CONFIG_M386) || defined(CONFIG_AMD_K5_INVBUG) +#ifdef CONFIG_M386 #define __flush_tlb_one(addr) flush_tlb() #else #define __flush_tlb_one(addr) \ @@ -182,6 +184,7 @@ #define PTRS_PER_PTE 1024 #define PTRS_PER_PMD 1 #define PTRS_PER_PGD 1024 +#define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE) /* * pgd entries used up by user/kernel: @@ -385,85 +388,137 @@ * used to allocate a kernel page table - this turns on ASN bits * if any. */ -extern inline void pte_free_kernel(pte_t * pte) + +#define pgd_quicklist (current_cpu_data.pgd_quick) +#define pmd_quicklist ((unsigned long *)0) +#define pte_quicklist (current_cpu_data.pte_quick) +#define pgtable_cache_size (current_cpu_data.pgtable_cache_sz) + +extern __inline__ pgd_t *get_pgd_slow(void) +{ + pgd_t *ret = (pgd_t *)__get_free_page(GFP_KERNEL), *init; + + if (ret) { + init = pgd_offset(&init_mm, 0); + memset (ret, 0, USER_PTRS_PER_PGD * sizeof(pgd_t)); + memcpy (ret + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD, + (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); + } + return ret; +} + +extern __inline__ pgd_t *get_pgd_fast(void) { - free_page((unsigned long) pte); + unsigned long *ret; + + if((ret = pgd_quicklist) != NULL) { + pgd_quicklist = (unsigned long *)(*ret); + ret[0] = ret[1]; + pgtable_cache_size--; + } else + ret = (unsigned long *)get_pgd_slow(); + return (pgd_t *)ret; } -extern const char bad_pmd_string[]; +extern __inline__ void free_pgd_fast(pgd_t *pgd) +{ + *(unsigned long *)pgd = (unsigned long) pgd_quicklist; + pgd_quicklist = (unsigned long *) pgd; + pgtable_cache_size++; +} -extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address) +extern __inline__ void free_pgd_slow(pgd_t *pgd) { - address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); - if (pmd_none(*pmd)) { - pte_t * page = (pte_t *) get_free_page(GFP_KERNEL); - if (pmd_none(*pmd)) { - if (page) { - pmd_val(*pmd) = _KERNPG_TABLE + __pa(page); - return page + address; - } - pmd_val(*pmd) = _KERNPG_TABLE + __pa(BAD_PAGETABLE); - return NULL; - } - free_page((unsigned long) page); - } - if (pmd_bad(*pmd)) { - printk(bad_pmd_string, pmd_val(*pmd)); - pmd_val(*pmd) = _KERNPG_TABLE + __pa(BAD_PAGETABLE); - return NULL; + free_page((unsigned long)pgd); +} + +extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted); +extern pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long address_preadjusted); + +extern __inline__ pte_t *get_pte_fast(void) +{ + unsigned long *ret; + + if((ret = (unsigned long *)pte_quicklist) != NULL) { + pte_quicklist = (unsigned long *)(*ret); + ret[0] = ret[1]; + pgtable_cache_size--; } - return (pte_t *) pmd_page(*pmd) + address; + return (pte_t *)ret; } -/* - * allocating and freeing a pmd is trivial: the 1-entry pmd is - * inside the pgd, so has no extra memory associated with it. - */ -extern inline void pmd_free_kernel(pmd_t * pmd) +extern __inline__ void free_pte_fast(pte_t *pte) { - pmd_val(*pmd) = 0; + *(unsigned long *)pte = (unsigned long) pte_quicklist; + pte_quicklist = (unsigned long *) pte; + pgtable_cache_size++; } -extern inline pmd_t * pmd_alloc_kernel(pgd_t * pgd, unsigned long address) +extern __inline__ void free_pte_slow(pte_t *pte) { - return (pmd_t *) pgd; + free_page((unsigned long)pte); +} + +/* We don't use pmd cache, so these are dummy routines */ +extern __inline__ pmd_t *get_pmd_fast(void) +{ + return (pmd_t *)0; } -extern inline void pte_free(pte_t * pte) +extern __inline__ void free_pmd_fast(pmd_t *pmd) { - free_page((unsigned long) pte); +} + +extern __inline__ void free_pmd_slow(pmd_t *pmd) +{ +} + +extern void __bad_pte(pmd_t *pmd); +extern void __bad_pte_kernel(pmd_t *pmd); + +#define pte_free_kernel(pte) free_pte_fast(pte) +#define pte_free(pte) free_pte_fast(pte) +#define pgd_free(pgd) free_pgd_fast(pgd) +#define pgd_alloc() get_pgd_fast() + +extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address) +{ + address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); + if (pmd_none(*pmd)) { + pte_t * page = (pte_t *) get_pte_fast(); + + if (!page) + return get_pte_kernel_slow(pmd, address); + pmd_val(*pmd) = _KERNPG_TABLE + __pa(page); + return page + address; + } + if (pmd_bad(*pmd)) { + __bad_pte_kernel(pmd); + return NULL; + } + return (pte_t *) pmd_page(*pmd) + address; } extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address) { address = (address >> (PAGE_SHIFT-2)) & 4*(PTRS_PER_PTE - 1); -repeat: if (pmd_none(*pmd)) goto getnew; if (pmd_bad(*pmd)) goto fix; return (pte_t *) (pmd_page(*pmd) + address); - getnew: { - unsigned long page = __get_free_page(GFP_KERNEL); - if (!pmd_none(*pmd)) - goto freenew; + unsigned long page = (unsigned long) get_pte_fast(); + if (!page) - goto oom; - memset((void *) page, 0, PAGE_SIZE); + return get_pte_slow(pmd, address); pmd_val(*pmd) = _PAGE_TABLE + __pa(page); return (pte_t *) (page + address); -freenew: - free_page(page); - goto repeat; } - fix: - printk(bad_pmd_string, pmd_val(*pmd)); -oom: - pmd_val(*pmd) = _PAGE_TABLE + __pa(BAD_PAGETABLE); + __bad_pte(pmd); return NULL; } @@ -473,7 +528,6 @@ */ extern inline void pmd_free(pmd_t * pmd) { - pmd_val(*pmd) = 0; } extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address) @@ -481,14 +535,34 @@ return (pmd_t *) pgd; } -extern inline void pgd_free(pgd_t * pgd) -{ - free_page((unsigned long) pgd); -} +#define pmd_free_kernel pmd_free +#define pmd_alloc_kernel pmd_alloc -extern inline pgd_t * pgd_alloc(void) +extern inline void set_pgdir(unsigned long address, pgd_t entry) { - return (pgd_t *) get_free_page(GFP_KERNEL); + struct task_struct * p; + pgd_t *pgd; +#ifdef __SMP__ + int i; +#endif + + read_lock(&tasklist_lock); + for_each_task(p) { + if (!p->mm) + continue; + *pgd_offset(p->mm,address) = entry; + } + read_unlock(&tasklist_lock); +#ifndef __SMP__ + for (pgd = (pgd_t *)pgd_quicklist; pgd; pgd = (pgd_t *)*(unsigned long *)pgd) + pgd[address >> PGDIR_SHIFT] = entry; +#else + /* To pgd_alloc/pgd_free, one holds master kernel lock and so does our callee, so we can + modify pgd caches of other CPUs as well. -jj */ + for (i = 0; i < NR_CPUS; i++) + for (pgd = (pgd_t *)cpu_data[i].pgd_quick; pgd; pgd = (pgd_t *)*(unsigned long *)pgd) + pgd[address >> PGDIR_SHIFT] = entry; +#endif } extern pgd_t swapper_pg_dir[1024]; diff -u --recursive --new-file v2.1.105/linux/include/asm-i386/processor.h linux/include/asm-i386/processor.h --- v2.1.105/linux/include/asm-i386/processor.h Wed May 20 19:10:41 1998 +++ linux/include/asm-i386/processor.h Sat Jun 13 12:48:11 1998 @@ -34,6 +34,9 @@ int fdiv_bug; int f00f_bug; unsigned long loops_per_sec; + unsigned long *pgd_quick; + unsigned long *pte_quick; + unsigned long pgtable_cache_sz; }; #define X86_VENDOR_INTEL 0 diff -u --recursive --new-file v2.1.105/linux/include/asm-i386/signal.h linux/include/asm-i386/signal.h --- v2.1.105/linux/include/asm-i386/signal.h Thu Feb 12 20:56:12 1998 +++ linux/include/asm-i386/signal.h Tue Jun 9 00:55:10 1998 @@ -72,7 +72,7 @@ /* * SA_FLAGS values: * - * SA_ONSTACK is not currently supported, but will allow sigaltstack(2). + * SA_ONSTACK indicates that a registered stack_t will be used. * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the * SA_RESTART flag to get restarting signals (which were the default long ago) * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. @@ -96,6 +96,15 @@ #define SA_INTERRUPT 0x20000000 /* dummy -- ignored */ #define SA_RESTORER 0x04000000 + +/* + * sigaltstack controls + */ +#define SS_ONSTACK 1 +#define SS_DISABLE 2 + +#define MINSIGSTKSZ 2048 +#define SIGSTKSZ 8192 #ifdef __KERNEL__ diff -u --recursive --new-file v2.1.105/linux/include/asm-i386/termios.h linux/include/asm-i386/termios.h --- v2.1.105/linux/include/asm-i386/termios.h Wed Apr 8 19:36:29 1998 +++ linux/include/asm-i386/termios.h Mon Jun 8 10:02:35 1998 @@ -47,6 +47,7 @@ #define N_AX25 5 #define N_X25 6 /* X.25 async */ #define N_6PACK 7 +#define N_MASC 8 /* Reserved fo Mobitex module */ #ifdef __KERNEL__ diff -u --recursive --new-file v2.1.105/linux/include/asm-i386/unistd.h linux/include/asm-i386/unistd.h --- v2.1.105/linux/include/asm-i386/unistd.h Thu May 7 22:51:54 1998 +++ linux/include/asm-i386/unistd.h Tue Jun 9 00:55:10 1998 @@ -191,6 +191,7 @@ #define __NR_getcwd 183 #define __NR_capget 184 #define __NR_capset 185 +#define __NR_sigaltstack 186 /* user-visible error numbers are in the range -1 - -122: see */ diff -u --recursive --new-file v2.1.105/linux/include/asm-m68k/amifd.h linux/include/asm-m68k/amifd.h --- v2.1.105/linux/include/asm-m68k/amifd.h Thu Mar 26 15:57:05 1998 +++ linux/include/asm-m68k/amifd.h Wed Dec 31 16:00:00 1969 @@ -1,61 +0,0 @@ -#ifndef _ASM_M68K_AMIFD_H -#define _ASM_M68K_AMIFD_H - -/* Definitions for the Amiga floppy driver */ - -#include - -#define FD_MAX_UNITS 4 /* Max. Number of drives */ -#define FLOPPY_MAX_SECTORS 22 /* Max. Number of sectors per track */ - -#ifndef ASSEMBLER - -struct fd_data_type { - char *name; /* description of data type */ - int sects; /* sectors per track */ -#ifdef __STDC__ - int (*read_fkt)(int); - void (*write_fkt)(int); -#else - int (*read_fkt)(); /* read whole track */ - void (*write_fkt)(); /* write whole track */ -#endif -}; - -/* -** Floppy type descriptions -*/ - -struct fd_drive_type { - unsigned long code; /* code returned from drive */ - char *name; /* description of drive */ - unsigned int tracks; /* number of tracks */ - unsigned int heads; /* number of heads */ - unsigned int read_size; /* raw read size for one track */ - unsigned int write_size; /* raw write size for one track */ - unsigned int sect_mult; /* sectors and gap multiplier (HD = 2) */ - unsigned int precomp1; /* start track for precomp 1 */ - unsigned int precomp2; /* start track for precomp 2 */ - unsigned int step_delay; /* time (in ms) for delay after step */ - unsigned int settle_time; /* time to settle after dir change */ - unsigned int side_time; /* time needed to change sides */ -}; - -struct amiga_floppy_struct { - struct fd_drive_type *type; /* type of floppy for this unit */ - struct fd_data_type *dtype; /* type of floppy for this unit */ - int track; /* current track (-1 == unknown) */ - unsigned char *trackbuf; /* current track (kmaloc()'d */ - - int blocks; /* total # blocks on disk */ - - int changed; /* true when not known */ - int disk; /* disk in drive (-1 == unknown) */ - int motor; /* true when motor is at speed */ - int busy; /* true when drive is active */ - int dirty; /* true when trackbuf is not on disk */ - int status; /* current error code for unit */ -}; -#endif - -#endif diff -u --recursive --new-file v2.1.105/linux/include/asm-m68k/amifdreg.h linux/include/asm-m68k/amifdreg.h --- v2.1.105/linux/include/asm-m68k/amifdreg.h Wed Dec 27 12:46:43 1995 +++ linux/include/asm-m68k/amifdreg.h Wed Dec 31 16:00:00 1969 @@ -1,81 +0,0 @@ -#ifndef _LINUX_AMIFDREG_H -#define _LINUX_AMIFDREG_H - -/* -** CIAAPRA bits (read only) -*/ - -#define DSKRDY (0x1<<5) /* disk ready when low */ -#define DSKTRACK0 (0x1<<4) /* head at track zero when low */ -#define DSKPROT (0x1<<3) /* disk protected when low */ -#define DSKCHANGE (0x1<<2) /* low when disk removed */ - -/* -** CIAAPRB bits (read/write) -*/ - -#define DSKMOTOR (0x1<<7) /* motor on when low */ -#define DSKSEL3 (0x1<<6) /* select drive 3 when low */ -#define DSKSEL2 (0x1<<5) /* select drive 2 when low */ -#define DSKSEL1 (0x1<<4) /* select drive 1 when low */ -#define DSKSEL0 (0x1<<3) /* select drive 0 when low */ -#define DSKSIDE (0x1<<2) /* side selection: 0 = upper, 1 = lower */ -#define DSKDIREC (0x1<<1) /* step direction: 0=in, 1=out (to trk 0) */ -#define DSKSTEP (0x1) /* pulse low to step head 1 track */ - -/* -** DSKBYTR bits (read only) -*/ - -#define DSKBYT (1<<15) /* register contains valid byte when set */ -#define DMAON (1<<14) /* disk DMA enabled */ -#define DISKWRITE (1<<13) /* disk write bit in DSKLEN enabled */ -#define WORDEQUAL (1<<12) /* DSKSYNC register match when true */ -/* bits 7-0 are data */ - -/* -** ADKCON/ADKCONR bits -*/ - -#ifndef SETCLR -#define ADK_SETCLR (1<<15) /* control bit */ -#endif -#define ADK_PRECOMP1 (1<<14) /* precompensation selection */ -#define ADK_PRECOMP0 (1<<13) /* 00=none, 01=140ns, 10=280ns, 11=500ns */ -#define ADK_MFMPREC (1<<12) /* 0=GCR precomp., 1=MFM precomp. */ -#define ADK_WORDSYNC (1<<10) /* enable DSKSYNC auto DMA */ -#define ADK_MSBSYNC (1<<9) /* when 1, enable sync on MSbit (for GCR) */ -#define ADK_FAST (1<<8) /* bit cell: 0=2us (GCR), 1=1us (MFM) */ - -/* -** DSKLEN bits -*/ - -#define DSKLEN_DMAEN (1<<15) -#define DSKLEN_WRITE (1<<14) - -/* -** INTENA/INTREQ bits -*/ - -#define DSKINDEX (0x1<<4) /* DSKINDEX bit */ - -/* -** Misc -*/ - -#define MFM_SYNC 0x4489 /* standard MFM sync value */ - -/* Values for FD_COMMAND */ -#define FD_RECALIBRATE 0x07 /* move to track 0 */ -#define FD_SEEK 0x0F /* seek track */ -#define FD_READ 0xE6 /* read with MT, MFM, SKip deleted */ -#define FD_WRITE 0xC5 /* write with MT, MFM */ -#define FD_SENSEI 0x08 /* Sense Interrupt Status */ -#define FD_SPECIFY 0x03 /* specify HUT etc */ -#define FD_FORMAT 0x4D /* format one track */ -#define FD_VERSION 0x10 /* get version code */ -#define FD_CONFIGURE 0x13 /* configure FIFO operation */ -#define FD_PERPENDICULAR 0x12 /* perpendicular r/w mode */ - -#endif /* _LINUX_AMIFDREG_H */ diff -u --recursive --new-file v2.1.105/linux/include/asm-m68k/amigahw.h linux/include/asm-m68k/amigahw.h --- v2.1.105/linux/include/asm-m68k/amigahw.h Tue Feb 17 13:12:48 1998 +++ linux/include/asm-m68k/amigahw.h Sat Jun 13 13:14:33 1998 @@ -332,4 +332,4 @@ #define TOD2000_HOUR1_PM (1<<2) #define TOD_2000 ((struct tod2000 *)(zTwoBase+0xDC0000)) -#endif /* __ASMm68k_AMIGAHW_H */ +#endif /* _M68K_AMIGAHW_H */ diff -u --recursive --new-file v2.1.105/linux/include/asm-m68k/amigardb.h linux/include/asm-m68k/amigardb.h --- v2.1.105/linux/include/asm-m68k/amigardb.h Wed Dec 27 12:46:44 1995 +++ linux/include/asm-m68k/amigardb.h Wed Dec 31 16:00:00 1969 @@ -1,126 +0,0 @@ -#ifndef _LINUX_AMIGARDB_H -#define _LINUX_AMIGARDB_H 1 - -#define ULONG u_long -#define LONG long -#define UBYTE u_char - -/* definitions for the Amiga RigidDiskBlock layout, which always starts in - cylinder 0 of a medium. Taken from page 254f of the RKM: Devices */ - -struct RigidDiskBlock { - ULONG rdb_ID; /* 4 character identifier */ - ULONG rdb_SummedLongs; /* size of this checksummed structure */ - LONG rdb_ChkSum; /* block checksum (longword sum to zero) */ - ULONG rdb_HostID; /* SCSI Target ID of host */ - ULONG rdb_BlockBytes; /* size of disk blocks */ - ULONG rdb_Flags; /* see below for defines */ - /* block list heads */ - ULONG rdb_BadBlockList; /* optional bad block list */ - ULONG rdb_PartitionList; /* optional first partition block */ - ULONG rdb_FileSysHeaderList; /* optional file system header block */ - ULONG rdb_DriveInit; /* optional drive-specific init code */ - /* DriveInit(lun,rdb,ior): "C" stk & d0/a0/a1 */ - ULONG rdb_Reserved1[6]; /* set to $ffffffff */ - /* physical drive characteristics */ - ULONG rdb_Cylinders; /* number of drive cylinders */ - ULONG rdb_Sectors; /* sectors per track */ - ULONG rdb_Heads; /* number of drive heads */ - ULONG rdb_Interleave; /* interleave */ - ULONG rdb_Park; /* landing zone cylinder */ - ULONG rdb_Reserved2[3]; - ULONG rdb_WritePreComp; /* starting cylinder: write precompensation */ - ULONG rdb_ReducedWrite; /* starting cylinder: reduced write current */ - ULONG rdb_StepRate; /* drive step rate */ - ULONG rdb_Reserved3[5]; - /* logical drive characteristics */ - ULONG rdb_RDBBlocksLo; /* low block of range reserved for hardblocks */ - ULONG rdb_RDBBlocksHi; /* high block of range for these hardblocks */ - ULONG rdb_LoCylinder; /* low cylinder of partitionable disk area */ - ULONG rdb_HiCylinder; /* high cylinder of partitionable data area */ - ULONG rdb_CylBlocks; /* number of blocks available per cylinder */ - ULONG rdb_AutoParkSeconds; /* zero for no auto park */ - ULONG rdb_HighRDSKBlock; /* highest block used by RDSK */ - /* (not including replacement bad blocks) */ - ULONG rdb_Reserved4; - /* drive identification */ - char rdb_DiskVendor[8]; - char rdb_DiskProduct[16]; - char rdb_DiskRevision[4]; - char rdb_ControllerVendor[8]; - char rdb_ControllerProduct[16]; - char rdb_ControllerRevision[4]; - ULONG rdb_Reserved5[10]; -}; - -#define IDNAME_RIGIDDISK 0x5244534B /* 'RDSK' */ - -#define RDB_LOCATION_LIMIT 16 - -#define RDBFB_LAST 0 /* no disks exist to be configured after */ -#define RDBFF_LAST 0x01L /* this one on this controller */ -#define RDBFB_LASTLUN 1 /* no LUNs exist to be configured greater */ -#define RDBFF_LASTLUN 0x02L /* than this one at this SCSI Target ID */ -#define RDBFB_LASTTID 2 /* no Target IDs exist to be configured */ -#define RDBFF_LASTTID 0x04L /* greater than this one on this SCSI bus */ -#define RDBFB_NORESELECT 3 /* don't bother trying to perform reselection */ -#define RDBFF_NORESELECT 0x08L /* when talking to this drive */ -#define RDBFB_DISKID 4 /* rdb_Disk... identification valid */ -#define RDBFF_DISKID 0x10L -#define RDBFB_CTRLRID 5 /* rdb_Controller... identification valid */ -#define RDBFF_CTRLRID 0x20L - /* added 7/20/89 by commodore: */ -#define RDBFB_SYNCH 6 /* drive supports scsi synchronous mode */ -#define RDBFF_SYNCH 0x40L /* CAN BE DANGEROUS TO USE IF IT DOESN'T! */ - -struct PartitionBlock { - ULONG pb_ID; /* 4 character identifier */ - ULONG pb_SummedLongs; /* size of this checksummed structure */ - LONG pb_ChkSum; /* block checksum (longword sum to zero) */ - ULONG pb_HostID; /* SCSI Target ID of host */ - ULONG pb_Next; /* block number of the next PartitionBlock */ - ULONG pb_Flags; /* see below for defines */ - ULONG pb_Reserved1[2]; - ULONG pb_DevFlags; /* preferred flags for OpenDevice */ - UBYTE pb_DriveName[32]; /* preferred DOS device name: BSTR form */ - /* (not used if this name is in use) */ - ULONG pb_Reserved2[15]; /* filler to 32 longwords */ - ULONG pb_Environment[17]; /* environment vector for this partition */ - ULONG pb_EReserved[15]; /* reserved for future environment vector */ -}; - -#define IDNAME_PARTITION 0x50415254 /* 'PART' */ - -#define PBFB_BOOTABLE 0 /* this partition is intended to be bootable */ -#define PBFF_BOOTABLE 1L /* (expected directories and files exist) */ -#define PBFB_NOMOUNT 1 /* do not mount this partition (e.g. manually */ -#define PBFF_NOMOUNT 2L /* mounted, but space reserved here) */ - -/* this is from */ - -#define DE_TABLESIZE 0 /* minimum value is 11 (includes NumBuffers) */ -#define DE_SIZEBLOCK 1 /* in longwords: standard value is 128 */ -#define DE_SECORG 2 /* not used; must be 0 */ -#define DE_NUMHEADS 3 /* # of heads (surfaces). drive specific */ -#define DE_SECSPERBLK 4 /* not used; must be 1 */ -#define DE_BLKSPERTRACK 5 /* blocks per track. drive specific */ -#define DE_RESERVEDBLKS 6 /* unavailable blocks at start. usually 2 */ -#define DE_PREFAC 7 /* not used; must be 0 */ -#define DE_INTERLEAVE 8 /* usually 0 */ -#define DE_LOWCYL 9 /* starting cylinder. typically 0 */ -#define DE_UPPERCYL 10 /* max cylinder. drive specific */ -#define DE_NUMBUFFERS 11 /* starting # of buffers. typically 5 */ -#define DE_MEMBUFTYPE 12 /* type of mem to allocate for buffers. */ -#define DE_BUFMEMTYPE 12 /* same as above, better name - * 1 is public, 3 is chip, 5 is fast */ -#define DE_MAXTRANSFER 13 /* Max number bytes to transfer at a time */ -#define DE_MASK 14 /* Address Mask to block out certain memory */ -#define DE_BOOTPRI 15 /* Boot priority for autoboot */ -#define DE_DOSTYPE 16 /* ASCII (HEX) string showing filesystem type; - * 0X444F5300 is old filesystem, - * 0X444F5301 is fast file system */ -#define DE_BAUD 17 /* Baud rate for serial handler */ -#define DE_CONTROL 18 /* Control word for handler/filesystem */ -#define DE_BOOTBLOCKS 19 /* Number of blocks containing boot code */ - -#endif /* _LINUX_AMIGARDB_H */ diff -u --recursive --new-file v2.1.105/linux/include/asm-m68k/atari_SCCserial.h linux/include/asm-m68k/atari_SCCserial.h --- v2.1.105/linux/include/asm-m68k/atari_SCCserial.h Tue Feb 17 13:12:48 1998 +++ linux/include/asm-m68k/atari_SCCserial.h Sat Jun 13 13:14:33 1998 @@ -29,8 +29,9 @@ * clock sources */ #define SCC_BAUD_BASE_MVME_PCLK 781250 /* 12.5 MHz */ -#define SCC_BAUD_BASE_BVM 460800 /* 7.3728 MHz */ #define SCC_BAUD_BASE_MVME 625000 /* 10.000 MHz */ +#define SCC_BAUD_BASE_BVME_PCLK 781250 /* 12.5 MHz */ /* XXX ??? */ +#define SCC_BAUD_BASE_BVME 460800 /* 7.3728 MHz */ /* The SCC configuration structure */ diff -u --recursive --new-file v2.1.105/linux/include/asm-m68k/atari_mouse.h linux/include/asm-m68k/atari_mouse.h --- v2.1.105/linux/include/asm-m68k/atari_mouse.h Mon Mar 4 12:47:32 1996 +++ linux/include/asm-m68k/atari_mouse.h Wed Dec 31 16:00:00 1969 @@ -1,20 +0,0 @@ -#ifndef _LINUX_ATARI_MOUSE_H -#define _LINUX_ATARI_MOUSE_H - -/* - * linux/include/linux/atari_mouse.h - * header file for Atari Mouse driver - * by Robert de Vries (robert@and.nl) on 19Jul93 - */ - -struct mouse_status { - char buttons; - short dx; - short dy; - int ready; - int active; - struct wait_queue *wait; - struct fasync_struct *fasyncptr; -}; - -#endif diff -u --recursive --new-file v2.1.105/linux/include/asm-m68k/bitops.h linux/include/asm-m68k/bitops.h --- v2.1.105/linux/include/asm-m68k/bitops.h Tue Feb 17 13:12:48 1998 +++ linux/include/asm-m68k/bitops.h Sat Jun 13 12:56:46 1998 @@ -210,6 +210,23 @@ return res ^ 31; } +/* + * ffs: find first bit set. This is defined the same way as + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + */ + +#define ffs(x) generic_ffs(x) + +/* + * hweightN: returns the hamming weight (i.e. the number + * of bits set) of a N-bit word + */ + +#define hweight32(x) generic_hweight32(x) +#define hweight16(x) generic_hweight16(x) +#define hweight8(x) generic_hweight8(x) + /* Bitmap functions for the minix filesystem */ extern __inline__ int diff -u --recursive --new-file v2.1.105/linux/include/asm-m68k/blinken.h linux/include/asm-m68k/blinken.h --- v2.1.105/linux/include/asm-m68k/blinken.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-m68k/blinken.h Sat Jun 13 13:14:33 1998 @@ -0,0 +1,27 @@ +/* +** asm/blinken.h -- m68k blinkenlights support (currently hp300 only) +** +** (c) 1998 Phil Blundell +** +** This file is subject to the terms and conditions of the GNU General Public +** License. See the file COPYING in the main directory of this archive +** for more details. +** +*/ + +#ifndef _M68K_BLINKEN_H +#define _M68K_BLINKEN_H + +#include + +#define HP300_LEDS 0xf001ffff + +static __inline__ void blinken_leds(int x) +{ + if (MACH_IS_HP300) + { + *((volatile unsigned char *)HP300_LEDS) = (x); + } +} + +#endif diff -u --recursive --new-file v2.1.105/linux/include/asm-m68k/bootinfo.h linux/include/asm-m68k/bootinfo.h --- v2.1.105/linux/include/asm-m68k/bootinfo.h Tue Feb 17 13:12:49 1998 +++ linux/include/asm-m68k/bootinfo.h Sat Jun 13 13:14:33 1998 @@ -109,7 +109,7 @@ #define ATARI_MACH_AB40 3 /* Afterburner040 on Falcon */ /* - * Macintosh-specific tags + * Macintosh-specific tags (all u_long) */ #define BI_MAC_MODEL 0x8000 /* Mac Gestalt ID (model type) */ @@ -123,9 +123,37 @@ #define BI_MAC_GMTBIAS 0x8008 /* Mac GMT timezone offset */ #define BI_MAC_MEMSIZE 0x8009 /* Mac RAM size (sanity check) */ #define BI_MAC_CPUID 0x800a /* Mac CPU type (sanity check) */ +#define BI_MAC_ROMBASE 0x800b /* Mac system ROM base address */ + + /* + * Macintosh hardware profile data - unused, see macintosh.h for + * resonable type values + */ + +#define BI_MAC_VIA1BASE 0x8010 /* Mac VIA1 base address (always present) */ +#define BI_MAC_VIA2BASE 0x8011 /* Mac VIA2 base address (type varies) */ +#define BI_MAC_VIA2TYPE 0x8012 /* Mac VIA2 type (VIA, RBV, OSS) */ +#define BI_MAC_ADBTYPE 0x8013 /* Mac ADB interface type */ +#define BI_MAC_ASCBASE 0x8014 /* Mac Apple Sound Chip base address */ +#define BI_MAC_SCSI5380 0x8015 /* Mac NCR 5380 SCSI (base address, multi) */ +#define BI_MAC_SCSIDMA 0x8016 /* Mac SCSI DMA (base address) */ +#define BI_MAC_SCSI5396 0x8017 /* Mac NCR 53C96 SCSI (base address, multi) */ +#define BI_MAC_IDETYPE 0x8018 /* Mac IDE interface type */ +#define BI_MAC_IDEBASE 0x8019 /* Mac IDE interface base address */ +#define BI_MAC_NUBUS 0x801a /* Mac Nubus type (none, regular, pseudo) */ +#define BI_MAC_SLOTMASK 0x801b /* Mac Nubus slots present */ +#define BI_MAC_SCCTYPE 0x801c /* Mac SCC serial type (normal, IOP) */ +#define BI_MAC_ETHTYPE 0x801d /* Mac builtin ethernet type (Sonic, MACE */ +#define BI_MAC_ETHBASE 0x801e /* Mac builtin ethernet base address */ +#define BI_MAC_PMU 0x801f /* Mac power managment / poweroff hardware */ +#define BI_MAC_IOP_SWIM 0x8020 /* Mac SWIM floppy IOP */ +#define BI_MAC_IOP_ADB 0x8021 /* Mac ADB IOP */ /* * Mac: compatibility with old booter data format (temporarily) + * Fields unused with the new bootinfo can be deleted now; instead of + * adding new fields the struct might be splitted into a hardware address + * part and a hardware type part */ #ifndef __ASSEMBLY__ @@ -198,6 +226,7 @@ #define ATARI_BOOTI_VERSION MK_BI_VERSION( 2, 1 ) #define MAC_BOOTI_VERSION MK_BI_VERSION( 2, 0 ) #define MVME16x_BOOTI_VERSION MK_BI_VERSION( 2, 0 ) +#define BVME6000_BOOTI_VERSION MK_BI_VERSION( 2, 0 ) #ifdef BOOTINFO_COMPAT_1_0 diff -u --recursive --new-file v2.1.105/linux/include/asm-m68k/bvme6000hw.h linux/include/asm-m68k/bvme6000hw.h --- v2.1.105/linux/include/asm-m68k/bvme6000hw.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-m68k/bvme6000hw.h Sat Jun 13 13:14:33 1998 @@ -0,0 +1,129 @@ +#ifndef _M68K_BVME6000HW_H_ +#define _M68K_BVME6000HW_H_ + +#include + +/* + * PIT structure + */ + +#define BVME_PIT_BASE 0xffa00000 + +typedef struct { + unsigned char + pad_a[3], pgcr, + pad_b[3], psrr, + pad_c[3], paddr, + pad_d[3], pbddr, + pad_e[3], pcddr, + pad_f[3], pivr, + pad_g[3], pacr, + pad_h[3], pbcr, + pad_i[3], padr, + pad_j[3], pbdr, + pad_k[3], paar, + pad_l[3], pbar, + pad_m[3], pcdr, + pad_n[3], psr, + pad_o[3], res1, + pad_p[3], res2, + pad_q[3], tcr, + pad_r[3], tivr, + pad_s[3], res3, + pad_t[3], cprh, + pad_u[3], cprm, + pad_v[3], cprl, + pad_w[3], res4, + pad_x[3], crh, + pad_y[3], crm, + pad_z[3], crl, + pad_A[3], tsr, + pad_B[3], res5; +} PitRegs_t, *PitRegsPtr; + +#define bvmepit ((*(volatile PitRegsPtr)(BVME_PIT_BASE))) + +#define BVME_RTC_BASE 0xff900000 + +typedef struct { + unsigned char + pad_a[3], msr, + pad_b[3], t0cr_rtmr, + pad_c[3], t1cr_omr, + pad_d[3], pfr_icr0, + pad_e[3], irr_icr1, + pad_f[3], bcd_tenms, + pad_g[3], bcd_sec, + pad_h[3], bcd_min, + pad_i[3], bcd_hr, + pad_j[3], bcd_dom, + pad_k[3], bcd_mth, + pad_l[3], bcd_year, + pad_m[3], bcd_ujcc, + pad_n[3], bcd_hjcc, + pad_o[3], bcd_dow, + pad_p[3], t0lsb, + pad_q[3], t0msb, + pad_r[3], t1lsb, + pad_s[3], t1msb, + pad_t[3], cmp_sec, + pad_u[3], cmp_min, + pad_v[3], cmp_hr, + pad_w[3], cmp_dom, + pad_x[3], cmp_mth, + pad_y[3], cmp_dow, + pad_z[3], sav_sec, + pad_A[3], sav_min, + pad_B[3], sav_hr, + pad_C[3], sav_dom, + pad_D[3], sav_mth, + pad_E[3], ram, + pad_F[3], test; +} RtcRegs_t, *RtcPtr_t; + + +#define BVME_I596_BASE 0xff100000 + +#define BVME_ETHIRQ_REG 0xff20000b + +#define BVME_LOCAL_IRQ_STAT 0xff20000f + +#define BVME_ETHERR 0x02 +#define BVME_ABORT_STATUS 0x08 + +#define BVME_NCR53C710_BASE 0xff000000 + +#define BVME_SCC_A_ADDR 0xffb0000b +#define BVME_SCC_B_ADDR 0xffb00003 + +#define BVME_CONFIG_REG 0xff500003 + +#define config_reg_ptr (unsigned char *)BVME_CONFIG_REG + +#define BVME_CONFIG_SW1 0x08 +#define BVME_CONFIG_SW2 0x04 +#define BVME_CONFIG_SW3 0x02 +#define BVME_CONFIG_SW4 0x01 + + +#define BVME_IRQ_TYPE_PRIO 0 + +#define BVME_IRQ_PRN 0x54 +#define BVME_IRQ_I596 0x1a +#define BVME_IRQ_SCSI 0x1b +#define BVME_IRQ_TIMER 0x59 +#define BVME_IRQ_RTC 0x1e +#define BVME_IRQ_ABORT 0x1f + +/* SCC interrupts */ +#define BVME_IRQ_SCC_BASE 0x40 +#define BVME_IRQ_SCCB_TX 0x40 +#define BVME_IRQ_SCCB_STAT 0x42 +#define BVME_IRQ_SCCB_RX 0x44 +#define BVME_IRQ_SCCB_SPCOND 0x46 +#define BVME_IRQ_SCCA_TX 0x48 +#define BVME_IRQ_SCCA_STAT 0x4a +#define BVME_IRQ_SCCA_RX 0x4c +#define BVME_IRQ_SCCA_SPCOND 0x4e + +#endif diff -u --recursive --new-file v2.1.105/linux/include/asm-m68k/checksum.h linux/include/asm-m68k/checksum.h --- v2.1.105/linux/include/asm-m68k/checksum.h Sat May 2 14:19:54 1998 +++ linux/include/asm-m68k/checksum.h Sat Jun 13 13:14:33 1998 @@ -39,6 +39,10 @@ csum_partial_copy_from_user ( const char *src, char *dst, int len, int sum, int *csum_err); +/* FIXME: this needs to be written to really do no check -- Cort */ +#define csum_partial_copy_nocheck(src, dst, len, sum) \ + csum_partial_copy((src), (dst), (len), (sum)) + /* * This is a version of ip_compute_csum() optimized for IP headers, * which always checksum on 4 octet boundaries. diff -u --recursive --new-file v2.1.105/linux/include/asm-m68k/entry.h linux/include/asm-m68k/entry.h --- v2.1.105/linux/include/asm-m68k/entry.h Tue Feb 17 13:12:49 1998 +++ linux/include/asm-m68k/entry.h Sat Jun 13 13:14:33 1998 @@ -54,7 +54,7 @@ LTSS_FPCTXT = 24 /* the following macro is used when enabling interrupts */ -#if defined(MACH_ATARI_ONLY) && !defined(CONFIG_HADES) +#if defined(CONFIG_ATARI_ONLY) && !defined(CONFIG_HADES) /* block out HSYNC on the atari */ #define ALLOWINT 0xfbff #define MAX_NOINT_IPL 3 diff -u --recursive --new-file v2.1.105/linux/include/asm-m68k/hardirq.h linux/include/asm-m68k/hardirq.h --- v2.1.105/linux/include/asm-m68k/hardirq.h Tue Feb 17 13:12:49 1998 +++ linux/include/asm-m68k/hardirq.h Sat Jun 13 13:14:33 1998 @@ -5,6 +5,8 @@ extern unsigned int local_irq_count[NR_CPUS]; +#define in_interrupt() (local_irq_count[smp_processor_id()] + local_bh_count[smp_processor_id()] != 0) + #define hardirq_trylock(cpu) (++local_irq_count[cpu], (cpu) == 0) #define hardirq_endlock(cpu) (--local_irq_count[cpu]) diff -u --recursive --new-file v2.1.105/linux/include/asm-m68k/hwtest.h linux/include/asm-m68k/hwtest.h --- v2.1.105/linux/include/asm-m68k/hwtest.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-m68k/hwtest.h Sat Jun 13 13:14:33 1998 @@ -0,0 +1,15 @@ +/* Routines to test for presence/absence of hardware registers: + * see arch/m68k/mm/hwtest.c. + * -- PMM 05/1998 + * + * Removed initfunc from decls. We might want them in modules, and + * the code is tiny anyway. 16/5/98 pb + */ + +#ifndef __ASM_HWTEST_H +#define __ASM_HWTEST_H + +extern int hwreg_present(volatile void *regp); +extern int hwreg_write(volatile void *regp, unsigned short val); + +#endif diff -u --recursive --new-file v2.1.105/linux/include/asm-m68k/ide.h linux/include/asm-m68k/ide.h --- v2.1.105/linux/include/asm-m68k/ide.h Thu May 7 22:51:54 1998 +++ linux/include/asm-m68k/ide.h Sat Jun 13 13:14:33 1998 @@ -41,6 +41,10 @@ #include #endif +#ifdef CONFIG_MAC +#include +#endif + typedef unsigned char * ide_ioreg_t; #ifndef MAX_HWIFS @@ -71,6 +75,10 @@ } b; } select_t; +#ifdef CONFIG_MAC /* MSch: Hack; wrapper for ide_intr */ +void mac_ide_intr(int irq, void *dev_id, struct pt_regs *regs); +#endif + static __inline__ int ide_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *device, void *dev_id) { @@ -78,6 +86,14 @@ if (MACH_IS_AMIGA) return request_irq(irq, handler, 0, device, dev_id); #endif /* CONFIG_AMIGA */ +#ifdef CONFIG_MAC + if (MACH_IS_MAC) +#if 0 /* MSch Hack: maybe later we'll call ide_intr without a wrapper */ + return nubus_request_irq(12, dev_id, handler); +#else + return nubus_request_irq(12, dev_id, mac_ide_intr); +#endif +#endif /* CONFIG_MAC */ return 0; } @@ -87,6 +103,10 @@ if (MACH_IS_AMIGA) free_irq(irq, dev_id); #endif /* CONFIG_AMIGA */ +#ifdef CONFIG_MAC + if (MACH_IS_MAC) + nubus_free_irq(12); +#endif /* CONFIG_MAC */ } /* @@ -117,81 +137,83 @@ #define insl(data_reg, buffer, wcount) insw(data_reg, buffer, (wcount)<<1) #define outsl(data_reg, buffer, wcount) outsw(data_reg, buffer, (wcount)<<1) -#define insw(port, buf, nr) \ - if ((nr) % 16) \ - __asm__ __volatile__ \ - ("movel %0,%/a0; \ - movel %1,%/a1; \ - movel %2,%/d6; \ - subql #1,%/d6; \ - 1:movew %/a0@,%/a1@+; \ - dbra %/d6,1b" : \ - : "g" (port), "g" (buf), "g" (nr) \ - : "a0", "a1", "d6"); \ - else \ - __asm__ __volatile__ \ - ("movel %0,%/a0; \ - movel %1,%/a1; \ - movel %2,%/d6; \ - lsrl #4,%/d6; \ - subql #1,%/d6; \ - 1:movew %/a0@,%/a1@+; \ - movew %/a0@,%/a1@+; \ - movew %/a0@,%/a1@+; \ - movew %/a0@,%/a1@+; \ - movew %/a0@,%/a1@+; \ - movew %/a0@,%/a1@+; \ - movew %/a0@,%/a1@+; \ - movew %/a0@,%/a1@+; \ - movew %/a0@,%/a1@+; \ - movew %/a0@,%/a1@+; \ - movew %/a0@,%/a1@+; \ - movew %/a0@,%/a1@+; \ - movew %/a0@,%/a1@+; \ - movew %/a0@,%/a1@+; \ - movew %/a0@,%/a1@+; \ - movew %/a0@,%/a1@+; \ - dbra %/d6,1b" : \ - : "g" (port), "g" (buf), "g" (nr) \ - : "a0", "a1", "d6") - -#define outsw(port, buf, nr) \ - if ((nr) % 16) \ - __asm__ __volatile__ \ - ("movel %0,%/a0; \ - movel %1,%/a1; \ - movel %2,%/d6; \ - subql #1,%/d6; \ - 1:movew %/a1@+,%/a0@; \ - dbra %/d6,1b" : \ - : "g" (port), "g" (buf), "g" (nr) \ - : "a0", "a1", "d6"); \ - else \ - __asm__ __volatile__ \ - ("movel %0,%/a0; \ - movel %1,%/a1; \ - movel %2,%/d6; \ - lsrl #4,%/d6; \ - subql #1,%/d6; \ - 1:movew %/a1@+,%/a0@; \ - movew %/a1@+,%/a0@; \ - movew %/a1@+,%/a0@; \ - movew %/a1@+,%/a0@; \ - movew %/a1@+,%/a0@; \ - movew %/a1@+,%/a0@; \ - movew %/a1@+,%/a0@; \ - movew %/a1@+,%/a0@; \ - movew %/a1@+,%/a0@; \ - movew %/a1@+,%/a0@; \ - movew %/a1@+,%/a0@; \ - movew %/a1@+,%/a0@; \ - movew %/a1@+,%/a0@; \ - movew %/a1@+,%/a0@; \ - movew %/a1@+,%/a0@; \ - movew %/a1@+,%/a0@; \ - dbra %/d6,1b" : \ - : "g" (port), "g" (buf), "g" (nr) \ - : "a0", "a1", "d6") +#define insw(port, buf, nr) ({ \ + unsigned char *_port = (unsigned char *)(port); \ + unsigned char *_buf = (buf); \ + int _nr = (nr); \ + unsigned long _tmp; \ + \ + if (_nr & 15) { \ + _tmp = (_nr & 15) - 1; \ + asm volatile ( \ + "1: movew %2@,%3@+; dbra %4,1b" \ + : "=a" (_buf), "=d" (_tmp) \ + : "a" (_port), "0" (_buf), \ + "1" (_tmp)); \ + } \ + _tmp = (_nr >> 4) - 1; \ + asm volatile ( \ + "1: " \ + "movew %2@,%3@+; " \ + "movew %2@,%3@+; " \ + "movew %2@,%3@+; " \ + "movew %2@,%3@+; " \ + "movew %2@,%3@+; " \ + "movew %2@,%3@+; " \ + "movew %2@,%3@+; " \ + "movew %2@,%3@+; " \ + "movew %2@,%3@+; " \ + "movew %2@,%3@+; " \ + "movew %2@,%3@+; " \ + "movew %2@,%3@+; " \ + "movew %2@,%3@+; " \ + "movew %2@,%3@+; " \ + "movew %2@,%3@+; " \ + "movew %2@,%3@+; " \ + "dbra %4,1b" \ + : "=a" (_buf), "=d" (_tmp) \ + : "a" (_port), "0" (_buf), \ + "1" (_tmp)); \ +}) + +#define outsw(port, buf, nr) ({ \ + unsigned char *_port = (unsigned char *)(port); \ + unsigned char *_buf = (buf); \ + int _nr = (nr); \ + unsigned long _tmp; \ + \ + if (_nr & 15) { \ + _tmp = (_nr & 15) - 1; \ + asm volatile ( \ + "1: movew %3@,%2@+; dbra %4,1b" \ + : "=a" (_buf), "=d" (_tmp) \ + : "a" (_port), "0" (_buf), \ + "1" (_tmp)); \ + } \ + _tmp = (_nr >> 4) - 1; \ + asm volatile ( \ + "1: " \ + "movew %3@+,%2@; " \ + "movew %3@+,%2@; " \ + "movew %3@+,%2@; " \ + "movew %3@+,%2@; " \ + "movew %3@+,%2@; " \ + "movew %3@+,%2@; " \ + "movew %3@+,%2@; " \ + "movew %3@+,%2@; " \ + "movew %3@+,%2@; " \ + "movew %3@+,%2@; " \ + "movew %3@+,%2@; " \ + "movew %3@+,%2@; " \ + "movew %3@+,%2@; " \ + "movew %3@+,%2@; " \ + "movew %3@+,%2@; " \ + "movew %3@+,%2@; " \ + "dbra %4,1b" \ + : "=a" (_buf), "=d" (_tmp) \ + : "a" (_port), "0" (_buf), \ + "1" (_tmp)); \ +}) #ifdef CONFIG_ATARI #define insl_swapw(data_reg, buffer, wcount) \ @@ -310,11 +332,11 @@ #define D_INT(cnt) (T_INT | (cnt)) #define D_TEXT(cnt) (T_TEXT | (cnt)) -#ifdef CONFIG_AMIGA +#if defined(CONFIG_AMIGA) || defined (CONFIG_MAC) static u_short driveid_types[] = { D_SHORT(10), /* config - vendor2 */ D_TEXT(20), /* serial_no */ - D_SHORT(3), /* buf_type - ecc_bytes */ + D_SHORT(3), /* buf_type, buf_size - ecc_bytes */ D_TEXT(48), /* fw_rev - model */ D_CHAR(2), /* max_multsect - vendor3 */ D_SHORT(1), /* dword_io */ @@ -333,12 +355,12 @@ static __inline__ void ide_fix_driveid(struct hd_driveid *id) { -#ifdef CONFIG_AMIGA +#if defined(CONFIG_AMIGA) || defined (CONFIG_MAC) u_char *p = (u_char *)id; int i, j, cnt; u_char t; - if (!MACH_IS_AMIGA) + if (!MACH_IS_AMIGA && !MACH_IS_MAC) return; for (i = 0; i < num_driveid_types; i++) { cnt = driveid_types[i] & T_MASK_COUNT; @@ -423,7 +445,7 @@ * an interrupt, and in that case it does nothing. Hope that is reasonable and * works. (Roman) */ -#if defined(CONFIG_ATARI) && !defined(CONFIG_AMIGA) +#ifdef CONFIG_ATARI_ONLY #define ide__sti() \ do { \ if (!in_interrupt()) __sti(); \ diff -u --recursive --new-file v2.1.105/linux/include/asm-m68k/io.h linux/include/asm-m68k/io.h --- v2.1.105/linux/include/asm-m68k/io.h Mon Feb 23 18:12:11 1998 +++ linux/include/asm-m68k/io.h Sat Jun 13 13:14:33 1998 @@ -28,9 +28,9 @@ #define readl(addr) \ ({ unsigned int __v = (*(volatile unsigned int *) (addr)); __v; }) -#define writeb(b,addr) ((*(volatile unsigned char *) (addr)) = (b)) -#define writew(b,addr) ((*(volatile unsigned short *) (addr)) = (b)) -#define writel(b,addr) ((*(volatile unsigned int *) (addr)) = (b)) +#define writeb(b,addr) (void)((*(volatile unsigned char *) (addr)) = (b)) +#define writew(b,addr) (void)((*(volatile unsigned short *) (addr)) = (b)) +#define writel(b,addr) (void)((*(volatile unsigned int *) (addr)) = (b)) #define memset_io(a,b,c) memset((void *)(a),(b),(c)) #define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c)) diff -u --recursive --new-file v2.1.105/linux/include/asm-m68k/machw.h linux/include/asm-m68k/machw.h --- v2.1.105/linux/include/asm-m68k/machw.h Tue Feb 17 13:12:49 1998 +++ linux/include/asm-m68k/machw.h Sat Jun 13 13:14:33 1998 @@ -100,9 +100,16 @@ # define via_1 ((*(volatile struct VIA *)VIA1_BAS)) # define via_2 ((*(volatile struct VIA *)VIA2_BAS)) # define via1_regp ((volatile unsigned char *)VIA1_BAS) - -# define via2_regp ((volatile unsigned char *)VIA2_BAS) -# define via2_ci_regp ((volatile unsigned char *)VIA2_BAS_IIci) -# define rbv_regp ((volatile unsigned char *)VIA2_BAS_IIci) +/* + * OSS/RBV base address + */ + +#define OSS_BAS 0x50f1a000 +#define PSC_BAS 0x50f31000 + +/* move to oss.h?? */ +#define nIFR 0x203 +#define oIFR 0x202 + #endif /* linux/machw.h */ diff -u --recursive --new-file v2.1.105/linux/include/asm-m68k/macintosh.h linux/include/asm-m68k/macintosh.h --- v2.1.105/linux/include/asm-m68k/macintosh.h Fri May 8 23:14:55 1998 +++ linux/include/asm-m68k/macintosh.h Sat Jun 13 13:14:33 1998 @@ -76,6 +76,7 @@ #define MAC_SCC_II 1 #define MAC_SCC_QUADRA 2 #define MAC_SCC_QUADRA2 3 +#define MAC_SCC_IOP 4 #define MAC_ETHER_NONE 0 #define MAC_ETHER_SONIC 1 @@ -94,6 +95,7 @@ #define MAC_MODEL_IICI 11 #define MAC_MODEL_IIFX 13 /* And well numbered it is too */ #define MAC_MODEL_IISI 18 +#define MAC_MODEL_LC 19 #define MAC_MODEL_Q900 20 #define MAC_MODEL_PB170 21 #define MAC_MODEL_Q700 22 @@ -131,9 +133,11 @@ #define MAC_MODEL_PB190 85 #define MAC_MODEL_TV 88 #define MAC_MODEL_P475 89 /* aka: LC475, P476 */ +#define MAC_MODEL_P475F 90 /* aka: P475 w/ FPU (no LC040) */ #define MAC_MODEL_P575 92 /* aka: LC575/580, P577/578/508 */ #define MAC_MODEL_Q605 94 #define MAC_MODEL_Q630 98 /* aka: LC630, P630/631/636/640 */ +#define MAC_MODEL_P588 99 /* aka: ?? */ #define MAC_MODEL_PB280 102 #define MAC_MODEL_PB280C 103 #define MAC_MODEL_PB150 115 diff -u --recursive --new-file v2.1.105/linux/include/asm-m68k/macints.h linux/include/asm-m68k/macints.h --- v2.1.105/linux/include/asm-m68k/macints.h Fri May 8 23:14:55 1998 +++ linux/include/asm-m68k/macints.h Sat Jun 13 13:14:33 1998 @@ -26,9 +26,9 @@ #define VIA1_SOURCE_BASE 8 #define VIA2_SOURCE_BASE 16 -#define RBF_SOURCE_BASE 24 +#define RBV_SOURCE_BASE 24 #define MAC_SCC_SOURCE_BASE 32 -#define NUBUS_SOURCE_BASE 40 +#define NUBUS_SOURCE_BASE 56 #define NUBUS_MAX_SOURCES 8 /* FIXME: sources not contigous ... */ @@ -42,14 +42,6 @@ */ #define IRQ_IDX(irq) (irq) -#if 0 -/* convert vector number to int source number */ -#define IRQ_VECTOR_TO_SOURCE(v) (v) - -/* convert irq_handler index to vector number */ -#define IRQ_SOURCE_TO_VECTOR(i) (i) -#endif - /* interrupt service types */ #define IRQ_TYPE_SLOW 0 #define IRQ_TYPE_FAST 1 @@ -96,6 +88,7 @@ #define IRQ_VIA2_6 (22) #define IRQ_VIA2_7 (23) +#if 0 /* RBV interrupts */ #define IRQ_RBV_0 (24) #define IRQ_RBV_1 (25) @@ -105,10 +98,19 @@ #define IRQ_RBV_5 (29) #define IRQ_RBV_6 (30) #define IRQ_RBV_7 (31) +#endif +/* Level 3 (PSC, AV Macs only) interrupts */ +#define IRQ_PSC3_0 (24) +#define IRQ_MAC_MACE IRQ_PSC3_0 +#define IRQ_PSC3_1 (25) +#define IRQ_PSC3_2 (26) +#define IRQ_PSC3_3 (27) + +/* Level 4 (SCC) interrupts */ #define IRQ_SCC (32) -#define IRQ_SCCB (32) -#define IRQ_SCCA (33) +#define IRQ_SCCB (33) +#define IRQ_SCCA (34) #if 0 /* FIXME: are there multiple interrupt conditions on the SCC ?? */ /* SCC interrupts */ #define IRQ_SCCB_TX (32) @@ -121,7 +123,27 @@ #define IRQ_SCCA_SPCOND (39) #endif -#define IRQ_NUBUS_1 (40) +/* Level 4 (PSC, AV Macs only) interrupts */ +#define IRQ_PSC4_0 (32) +#define IRQ_PSC4_1 (33) +#define IRQ_PSC4_2 (34) +#define IRQ_PSC4_3 (35) +#define IRQ_MAC_MACE_DMA IRQ_PSC4_3 + +/* Level 5 (PSC, AV Macs only) interrupts */ +#define IRQ_PSC5_0 (40) +#define IRQ_PSC5_1 (41) +#define IRQ_PSC5_2 (42) +#define IRQ_PSC5_3 (43) + +/* Level 6 (PSC, AV Macs only) interrupts */ +#define IRQ_PSC6_0 (48) +#define IRQ_PSC6_1 (49) +#define IRQ_PSC6_2 (50) +#define IRQ_PSC6_3 (51) + +/* Nubus interrupts (cascaded to VIA2) */ +#define IRQ_NUBUS_1 (56) #define INT_CLK 24576 /* CLK while int_clk =2.456MHz and divide = 100 */ #define INT_TICKS 246 /* to make sched_time = 99.902... HZ */ diff -u --recursive --new-file v2.1.105/linux/include/asm-m68k/mvme16xhw.h linux/include/asm-m68k/mvme16xhw.h --- v2.1.105/linux/include/asm-m68k/mvme16xhw.h Tue Feb 17 13:12:49 1998 +++ linux/include/asm-m68k/mvme16xhw.h Sat Jun 13 13:14:33 1998 @@ -34,37 +34,59 @@ spare3, spare4, data; -} lpr_ctrl; +} MVMElp, *MVMElpPtr; -#define LPR_REGS ((volatile lpr_ctrl *)0xfff42030) +#define MVME_LPR_BASE 0xfff42030 -#define I596_BASE 0xfff46000 +#define mvmelp ((*(volatile MVMElpPtr)(MVME_LPR_BASE))) -#define SCC_A_ADDR 0xfff45005 -#define SCC_B_ADDR 0xfff45001 - -#define IRQ_MVME162_TYPE_PRIO 0 - -#define IRQ_MVME167_PRN 0x54 -#define IRQ_MVME16x_I596 0x57 -#define IRQ_MVME16x_SCSI 0x55 -#define IRQ_MVME16x_FLY 0x7f -#define IRQ_MVME167_SER_ERR 0x5c -#define IRQ_MVME167_SER_MODEM 0x5d -#define IRQ_MVME167_SER_TX 0x5e -#define IRQ_MVME167_SER_RX 0x5f -#define IRQ_MVME16x_TIMER 0x59 +typedef struct { + unsigned char + ctrl, + bcd_sec, + bcd_min, + bcd_hr, + bcd_dow, + bcd_dom, + bcd_mth, + bcd_year; +} MK48T08_t, *MK48T08ptr_t; + +#define RTC_WRITE 0x80 +#define RTC_READ 0x40 +#define RTC_STOP 0x20 + +#define MVME_RTC_BASE 0xfffc1ff8 + +#define MVME_I596_BASE 0xfff46000 + +#define MVME_SCC_A_ADDR 0xfff45005 +#define MVME_SCC_B_ADDR 0xfff45001 + +#define MVME162_IRQ_TYPE_PRIO 0 + +#define MVME167_IRQ_PRN 0x54 +#define MVME16x_IRQ_I596 0x57 +#define MVME16x_IRQ_SCSI 0x55 +#define MVME16x_IRQ_FLY 0x7f +#define MVME167_IRQ_SER_ERR 0x5c +#define MVME167_IRQ_SER_MODEM 0x5d +#define MVME167_IRQ_SER_TX 0x5e +#define MVME167_IRQ_SER_RX 0x5f +#define MVME16x_IRQ_TIMER 0x59 +#define MVME167_IRQ_ABORT 0x6e +#define MVME162_IRQ_ABORT 0x5e /* SCC interrupts, for MVME162 */ -#define IRQ_MVME162_SCC_BASE 0x40 -#define IRQ_MVME162_SCCB_TX 0x40 -#define IRQ_MVME162_SCCB_STAT 0x42 -#define IRQ_MVME162_SCCB_RX 0x44 -#define IRQ_MVME162_SCCB_SPCOND 0x46 -#define IRQ_MVME162_SCCA_TX 0x48 -#define IRQ_MVME162_SCCA_STAT 0x4a -#define IRQ_MVME162_SCCA_RX 0x4c -#define IRQ_MVME162_SCCA_SPCOND 0x4e +#define MVME162_IRQ_SCC_BASE 0x40 +#define MVME162_IRQ_SCCB_TX 0x40 +#define MVME162_IRQ_SCCB_STAT 0x42 +#define MVME162_IRQ_SCCB_RX 0x44 +#define MVME162_IRQ_SCCB_SPCOND 0x46 +#define MVME162_IRQ_SCCA_TX 0x48 +#define MVME162_IRQ_SCCA_STAT 0x4a +#define MVME162_IRQ_SCCA_RX 0x4c +#define MVME162_IRQ_SCCA_SPCOND 0x4e /* MVME162 version register */ @@ -85,34 +107,4 @@ #define MVME16x_CONFIG_GOT_SCCA 0x0400 #define MVME16x_CONFIG_GOT_SCCB 0x0800 -/* Specials for the ethernet driver */ - -#define CA() (((struct i596_reg *)dev->base_addr)->ca = 1) - -#define MPU_PORT(c,x) \ - ((struct i596_reg *)(dev->base_addr))->porthi = ((c) | (u32)(x)) & 0xffff; \ - ((struct i596_reg *)(dev->base_addr))->portlo = ((c) | (u32)(x)) >> 16 - -#define SCP_SYSBUS 0x00000054 - -#define WSWAPrfd(x) ((struct i596_rfd *) (((u32)(x)<<16) | ((((u32)(x)))>>16))) -#define WSWAPrbd(x) ((struct i596_rbd *) (((u32)(x)<<16) | ((((u32)(x)))>>16))) -#define WSWAPiscp(x) ((struct i596_iscp *)(((u32)(x)<<16) | ((((u32)(x)))>>16))) -#define WSWAPscb(x) ((struct i596_scb *) (((u32)(x)<<16) | ((((u32)(x)))>>16))) -#define WSWAPcmd(x) ((struct i596_cmd *) (((u32)(x)<<16) | ((((u32)(x)))>>16))) -#define WSWAPtbd(x) ((struct i596_tbd *) (((u32)(x)<<16) | ((((u32)(x)))>>16))) -#define WSWAPchar(x) ((char *) (((u32)(x)<<16) | ((((u32)(x)))>>16))) - -/* - * The MPU_PORT command allows direct access to the 82596. With PORT access - * the following commands are available (p5-18). The 32-bit port command - * must be word-swapped with the most significant word written first. - */ -#define PORT_RESET 0x00 /* reset 82596 */ -#define PORT_SELFTEST 0x01 /* selftest */ -#define PORT_ALTSCP 0x02 /* alternate SCB address */ -#define PORT_ALTDUMP 0x03 /* Alternate DUMP address */ - -#define ISCP_BUSY 0x00010000 - -#endif /* _M68K_MVME16xHW_H_ */ +#endif diff -u --recursive --new-file v2.1.105/linux/include/asm-m68k/pgtable.h linux/include/asm-m68k/pgtable.h --- v2.1.105/linux/include/asm-m68k/pgtable.h Fri May 8 23:14:55 1998 +++ linux/include/asm-m68k/pgtable.h Sat Jun 13 13:14:33 1998 @@ -328,6 +328,16 @@ * and initialized in head.S */ extern int m68k_pgtable_cachemode; +/* This is the cache mode for normal pages, for supervisor access on + * processors >= '040. It is used in pte_mkcache(), and the variable is + * defined and initialized in head.S */ + +#if defined(CONFIG_060_WRITETHROUGH) +extern int m68k_supervisor_cachemode; +#else +#define m68k_supervisor_cachemode _PAGE_CACHE040 +#endif + #if defined(CPU_M68040_OR_M68060_ONLY) #define mm_cachebits _PAGE_CACHE040 #elif defined(CPU_M68020_OR_M68030_ONLY) @@ -495,7 +505,7 @@ pte_val(pte) = (pte_val(pte) & _CACHEMASK040) | m68k_pgtable_cachemode; return pte; } -extern inline pte_t pte_mkcache(pte_t pte) { pte_val(pte) = (pte_val(pte) & _CACHEMASK040) | _PAGE_CACHE040; return pte; } +extern inline pte_t pte_mkcache(pte_t pte) { pte_val(pte) = (pte_val(pte) & _CACHEMASK040) | m68k_supervisor_cachemode; return pte; } /* to set the page-dir */ extern inline void SET_PAGE_DIR(struct task_struct * tsk, pgd_t * pgdir) diff -u --recursive --new-file v2.1.105/linux/include/asm-m68k/processor.h linux/include/asm-m68k/processor.h --- v2.1.105/linux/include/asm-m68k/processor.h Fri May 8 23:14:55 1998 +++ linux/include/asm-m68k/processor.h Sat Jun 13 13:14:33 1998 @@ -19,7 +19,7 @@ /* This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#define TASK_UNMAPPED_BASE(off) 0xC0000000UL +#define TASK_UNMAPPED_BASE 0xC0000000UL #define TASK_UNMAPPED_ALIGN(addr, off) PAGE_ALIGN(addr) /* @@ -72,6 +72,9 @@ { } +#define copy_segments(nr, tsk, mm) do { } while (0) +#define release_segments(mm) do { } while (0) + /* * Free current thread data structures etc.. */ @@ -84,19 +87,16 @@ */ extern inline unsigned long thread_saved_pc(struct thread_struct *t) { - extern int sys_pause(void); - extern void schedule(void); + extern void scheduling_functions_start_here(void); + extern void scheduling_functions_end_here(void); struct switch_stack *sw = (struct switch_stack *)t->ksp; /* Check whether the thread is blocked in resume() */ - if (sw->retpc >= (unsigned long)schedule && - sw->retpc < (unsigned long)sys_pause) + if (sw->retpc > (unsigned long)scheduling_functions_start_here && + sw->retpc < (unsigned long)scheduling_functions_end_here) return ((unsigned long *)sw->a6)[1]; else return sw->retpc; } - -#define copy_segments(nr, tsk, mm) do { } while (0) -#define release_segments(mm) do { } while (0) /* Allocation and freeing of basic task resources. */ #define alloc_task_struct() \ diff -u --recursive --new-file v2.1.105/linux/include/asm-m68k/serial.h linux/include/asm-m68k/serial.h --- v2.1.105/linux/include/asm-m68k/serial.h Tue Feb 17 13:12:49 1998 +++ linux/include/asm-m68k/serial.h Sat Jun 13 13:14:33 1998 @@ -34,6 +34,8 @@ #define SER_WHIPPET 108 /* Amiga Hisoft Whippet PCMCIA (16c550B) */ #define SER_SCC_MVME 109 /* MVME162/MVME172 ports */ #define SER_SCC_MAC 110 /* Macintosh SCC channel */ +#define SER_HPDCA 111 /* HP DCA serial */ +#define SER_SCC_BVME 112 /* BVME6000 ports */ struct serial_struct { int type; diff -u --recursive --new-file v2.1.105/linux/include/asm-m68k/setup.h linux/include/asm-m68k/setup.h --- v2.1.105/linux/include/asm-m68k/setup.h Thu Mar 26 15:57:05 1998 +++ linux/include/asm-m68k/setup.h Sat Jun 13 13:14:33 1998 @@ -38,6 +38,7 @@ #define MACH_MVME147 6 #define MACH_MVME16x 7 #define MACH_BVME6000 8 +#define MACH_HP300 9 #ifdef __KERNEL__ @@ -48,10 +49,10 @@ #if !defined(CONFIG_AMIGA) # define MACH_IS_AMIGA (0) #elif defined(CONFIG_ATARI) || defined(CONFIG_MAC) || defined(CONFIG_APOLLO) \ - || defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000) + || defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000) || defined(CONFIG_HP300) # define MACH_IS_AMIGA (m68k_machtype == MACH_AMIGA) #else -# define MACH_AMIGA_ONLY +# define CONFIG_AMIGA_ONLY # define MACH_IS_AMIGA (1) # define MACH_TYPE (MACH_AMIGA) #endif @@ -59,17 +60,18 @@ #if !defined(CONFIG_ATARI) # define MACH_IS_ATARI (0) #elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_APOLLO) \ - || defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000) + || defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000) || defined(CONFIG_HP300) # define MACH_IS_ATARI (m68k_machtype == MACH_ATARI) #else -# define MACH_ATARI_ONLY +# define CONFIG_ATARI_ONLY # define MACH_IS_ATARI (1) # define MACH_TYPE (MACH_ATARI) #endif #if !defined(CONFIG_MAC) # define MACH_IS_MAC (0) -#elif defined(CONFIG_AMIGA) || defined(CONFIG_ATARI) || defined(CONFIG_APOLLO) +#elif defined(CONFIG_AMIGA) || defined(CONFIG_ATARI) || defined(CONFIG_APOLLO) \ + || defined(CONFIG_HP300) || defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000) # define MACH_IS_MAC (m68k_machtype == MACH_MAC) #else # define CONFIG_MAC_ONLY @@ -86,7 +88,7 @@ #if !defined (CONFIG_APOLLO) # define MACH_IS_APOLLO (0) #elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \ - || defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000) + || defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000) || defined(CONFIG_HP300) # define MACH_IS_APOLLO (m68k_machtype == MACH_APOLLO) #else # define CONFIG_APOLLO_ONLY @@ -97,7 +99,7 @@ #if !defined (CONFIG_MVME16x) # define MACH_IS_MVME16x (0) #elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \ - || defined(CONFIG_APOLLO) || defined(CONFIG_BVME6000) + || defined(CONFIG_APOLLO) || defined(CONFIG_BVME6000) || defined(CONFIG_HP300) # define MACH_IS_MVME16x (m68k_machtype == MACH_MVME16x) #else # define CONFIG_MVME16x_ONLY @@ -108,7 +110,7 @@ #if !defined (CONFIG_BVME6000) # define MACH_IS_BVME6000 (0) #elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \ - || defined(CONFIG_APOLLO) || defined(CONFIG_MVME16x) + || defined(CONFIG_APOLLO) || defined(CONFIG_MVME16x) || defined(CONFIG_HP300) # define MACH_IS_BVME6000 (m68k_machtype == MACH_BVME6000) #else # define CONFIG_BVME6000_ONLY @@ -116,6 +118,16 @@ # define MACH_TYPE (MACH_BVME6000) #endif +#if !defined (CONFIG_HP300) +# define MACH_IS_HP300 (0) +#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \ + || defined(CONFIG_APOLLO) || defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000) +# define MAC_IS_HP300 (m68k_machtype == MACH_HP300) +#else +# define CONFIG_HP300_ONLY +# define MACH_IS_HP300 (1) +# define MACH_TYPE (MACH_HP300) +#endif #ifndef MACH_TYPE # define MACH_TYPE (m68k_machtype) diff -u --recursive --new-file v2.1.105/linux/include/asm-m68k/signal.h linux/include/asm-m68k/signal.h --- v2.1.105/linux/include/asm-m68k/signal.h Thu Mar 26 15:57:05 1998 +++ linux/include/asm-m68k/signal.h Sat Jun 13 13:14:33 1998 @@ -142,11 +142,18 @@ /* Here we must cater to libcs that poke about in kernel headers. */ struct sigaction { - __sighandler_t sa_handler; + union { + __sighandler_t _sa_handler; + void (*_sa_sigaction)(int, struct siginfo *, void *); + } _u; sigset_t sa_mask; unsigned long sa_flags; void (*sa_restorer)(void); }; + +#define sa_handler _u._sa_handler +#define sa_sigaction _u._sa_sigaction + #endif /* __KERNEL__ */ typedef struct sigaltstack { diff -u --recursive --new-file v2.1.105/linux/include/asm-m68k/stat.h linux/include/asm-m68k/stat.h --- v2.1.105/linux/include/asm-m68k/stat.h Fri May 8 23:14:55 1998 +++ linux/include/asm-m68k/stat.h Sat Jun 13 13:14:33 1998 @@ -38,6 +38,7 @@ unsigned long __unused5; }; +#if 0 typedef struct { unsigned int major; unsigned int minor; @@ -62,6 +63,7 @@ unsigned long st_blksize; unsigned long __unused4; }; +#endif #define __XSTAT_VER_1 1 #define __XSTAT_VER_2 2 diff -u --recursive --new-file v2.1.105/linux/include/asm-m68k/system.h linux/include/asm-m68k/system.h --- v2.1.105/linux/include/asm-m68k/system.h Tue Feb 17 13:12:49 1998 +++ linux/include/asm-m68k/system.h Sat Jun 13 13:14:33 1998 @@ -60,7 +60,7 @@ struct __xchg_dummy { unsigned long a[100]; }; #define __xg(x) ((volatile struct __xchg_dummy *)(x)) -#if defined(CONFIG_ATARI) && !defined(CONFIG_AMIGA) && !defined(CONFIG_MAC) && !defined(CONFIG_HADES) +#if defined(CONFIG_ATARI) && !defined(CONFIG_AMIGA) && !defined(CONFIG_MAC) && !defined(CONFIG_HADES) && !defined(CONFIG_VME) && !defined(CONFIG_APOLLO) /* block out HSYNC on the atari */ #define __sti() __asm__ __volatile__ ("andiw #0xfbff,%/sr": : : "memory") #else /* portable version */ diff -u --recursive --new-file v2.1.105/linux/include/asm-m68k/unistd.h linux/include/asm-m68k/unistd.h --- v2.1.105/linux/include/asm-m68k/unistd.h Wed Apr 8 19:36:29 1998 +++ linux/include/asm-m68k/unistd.h Sat Jun 13 13:14:33 1998 @@ -187,6 +187,9 @@ #define __NR_pread 180 #define __NR_pwrite 181 #define __NR_lchown 182 +#define __NR_getcwd 183 +#define __NR_capget 184 +#define __NR_capset 185 /* user-visible error numbers are in the range -1 - -122: see */ diff -u --recursive --new-file v2.1.105/linux/include/asm-mips/bitops.h linux/include/asm-mips/bitops.h --- v2.1.105/linux/include/asm-mips/bitops.h Tue Dec 16 12:45:55 1997 +++ linux/include/asm-mips/bitops.h Sat Jun 13 12:56:46 1998 @@ -372,6 +372,23 @@ return __res; } +/* + * ffs: find first bit set. This is defined the same way as + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + */ + +#define ffs(x) generic_ffs(x) + +/* + * hweightN: returns the hamming weight (i.e. the number + * of bits set) of a N-bit word + */ + +#define hweight32(x) generic_hweight32(x) +#define hweight16(x) generic_hweight16(x) +#define hweight8(x) generic_hweight8(x) + #ifdef __MIPSEB__ /* For now I steal the Sparc C versions, no need for speed, just need to * get it working. diff -u --recursive --new-file v2.1.105/linux/include/asm-ppc/bitops.h linux/include/asm-ppc/bitops.h --- v2.1.105/linux/include/asm-ppc/bitops.h Sat Aug 16 09:51:09 1997 +++ linux/include/asm-ppc/bitops.h Sat Jun 13 12:56:46 1998 @@ -97,6 +97,34 @@ } /* + * ffs: find first bit set. This is defined the same way as + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + */ + +#define ffs(x) generic_ffs(x) + +#if 0 +/* untested, someone with PPC knowledge? */ +/* From Alexander Kjeldaas */ +extern __inline__ int ffs(int x) +{ + int result; + asm ("cntlzw %0,%1" : "=r" (result) : "r" (x)); + return 32 - result; /* IBM backwards ordering of bits */ +} +#endif + +/* + * hweightN: returns the hamming weight (i.e. the number + * of bits set) of a N-bit word + */ + +#define hweight32(x) generic_hweight32(x) +#define hweight16(x) generic_hweight16(x) +#define hweight8(x) generic_hweight8(x) + +/* * This implementation of find_{first,next}_zero_bit was stolen from * Linus' asm-alpha/bitops.h. */ diff -u --recursive --new-file v2.1.105/linux/include/asm-sparc/bitops.h linux/include/asm-sparc/bitops.h --- v2.1.105/linux/include/asm-sparc/bitops.h Thu Apr 23 20:21:38 1998 +++ linux/include/asm-sparc/bitops.h Sat Jun 13 12:56:46 1998 @@ -182,6 +182,24 @@ return result; } +/* + * ffs: find first bit set. This is defined the same way as + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + */ + +#define ffs(x) generic_ffs(x) + +/* + * hweightN: returns the hamming weight (i.e. the number + * of bits set) of a N-bit word + */ + +#define hweight32(x) generic_hweight32(x) +#define hweight16(x) generic_hweight16(x) +#define hweight8(x) generic_hweight8(x) + + /* find_next_zero_bit() finds the first zero bit in a bit string of length * 'size' bits, starting the search at bit 'offset'. This is largely based * on Linus's ALPHA routines, which are pretty portable BTW. diff -u --recursive --new-file v2.1.105/linux/include/asm-sparc64/bitops.h linux/include/asm-sparc64/bitops.h --- v2.1.105/linux/include/asm-sparc64/bitops.h Mon Jan 12 15:15:54 1998 +++ linux/include/asm-sparc64/bitops.h Sat Jun 13 12:56:47 1998 @@ -186,6 +186,53 @@ return result; } +/* + * ffs: find first bit set. This is defined the same way as + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + */ + +#define ffs(x) generic_ffs(x) + +/* + * hweightN: returns the hamming weight (i.e. the number + * of bits set) of a N-bit word + */ + +#ifdef ULTRA_HAS_POPULATION_COUNT + +extern __inline__ unsigned int hweight32(unsigned int w) +{ + unsigned int res; + + __asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xffffffff)); + return res; +} + +extern __inline__ unsigned int hweight16(unsigned int w) +{ + unsigned int res; + + __asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xffff)); + return res; +} + +extern __inline__ unsigned int hweight8(unsigned int w) +{ + unsigned int res; + + __asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xff)); + return res; +} + +#else + +#define hweight32(x) generic_hweight32(x) +#define hweight16(x) generic_hweight16(x) +#define hweight8(x) generic_hweight8(x) + +#endif + /* find_next_zero_bit() finds the first zero bit in a bit string of length * 'size' bits, starting the search at bit 'offset'. This is largely based * on Linus's ALPHA routines, which are pretty portable BTW. diff -u --recursive --new-file v2.1.105/linux/include/linux/adfs_fs.h linux/include/linux/adfs_fs.h --- v2.1.105/linux/include/linux/adfs_fs.h Fri Feb 6 15:32:54 1998 +++ linux/include/linux/adfs_fs.h Sat Jun 13 13:32:04 1998 @@ -111,30 +111,22 @@ }; #ifdef __KERNEL__ - - /* * Calculate the boot block checksum on an ADFS drive. Note that this will * appear to be correct if the sector contains all zeros, so also check that * the disk size is non-zero!!! */ - extern inline int adfs_checkbblk(unsigned char *ptr) { - int i = 511; - - int result = 0; + unsigned int result = 0; + unsigned char *p = ptr + 511; do { - result = (result & 0xff) + (result >> 8); - result = result + ptr[i]; - i--; - } - while (i != 0); - - result &= 0xff; - return result != ptr[511]; - return 0; + result = (result & 0xff) + (result >> 8); + result = result + *--p; + } while (p != ptr); + + return (result & 0xff) != ptr[511]; } /* dir.c */ diff -u --recursive --new-file v2.1.105/linux/include/linux/bitops.h linux/include/linux/bitops.h --- v2.1.105/linux/include/linux/bitops.h Wed Dec 31 16:00:00 1969 +++ linux/include/linux/bitops.h Sat Jun 13 12:56:47 1998 @@ -0,0 +1,72 @@ +#ifndef _LINUX_BITOPS_H +#define _LINUX_BITOPS_H + + +/* + * ffs: find first bit set. This is defined the same way as + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + */ + +extern __inline__ int generic_ffs(int x) +{ + int r = 1; + + if (!x) + return 0; + if (!(x & 0xffff)) { + x >>= 16; + r += 16; + } + if (!(x & 0xff)) { + x >>= 8; + r += 8; + } + if (!(x & 0xf)) { + x >>= 4; + r += 4; + } + if (!(x & 3)) { + x >>= 2; + r += 2; + } + if (!(x & 1)) { + x >>= 1; + r += 1; + } + return r; +} + +/* + * hweightN: returns the hamming weight (i.e. the number + * of bits set) of a N-bit word + */ + +extern __inline__ unsigned int generic_hweight32(unsigned int w) +{ + unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555); + res = (res & 0x33333333) + ((res >> 2) & 0x33333333); + res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F); + res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF); + return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF); +} + +extern __inline__ unsigned int generic_hweight16(unsigned int w) +{ + unsigned int res = (w & 0x5555) + ((w >> 1) & 0x5555); + res = (res & 0x3333) + ((res >> 2) & 0x3333); + res = (res & 0x0F0F) + ((res >> 4) & 0x0F0F); + return (res & 0x00FF) + ((res >> 8) & 0x00FF); +} + +extern __inline__ unsigned int generic_hweight8(unsigned int w) +{ + unsigned int res = (w & 0x55) + ((w >> 1) & 0x55); + res = (res & 0x33) + ((res >> 2) & 0x33); + return (res & 0x0F) + ((res >> 4) & 0x0F); +} + +#include + + +#endif diff -u --recursive --new-file v2.1.105/linux/include/linux/blk.h linux/include/linux/blk.h --- v2.1.105/linux/include/linux/blk.h Fri May 8 23:14:56 1998 +++ linux/include/linux/blk.h Sat Jun 13 13:48:44 1998 @@ -339,6 +339,15 @@ #define DEVICE_ON(device) #define DEVICE_OFF(device) +#elif (MAJOR_NR == MFM_ACORN_MAJOR) + +#define DEVICE_NAME "mfm disk" +#define DEVICE_INTR do_mfm +#define DEVICE_REQUEST do_mfm_request +#define DEVICE_NR(device) (MINOR(device) >> 6) +#define DEVICE_ON(device) +#define DEVICE_OFF(device) + #elif (MAJOR_NR == NBD_MAJOR) #define DEVICE_NAME "nbd" diff -u --recursive --new-file v2.1.105/linux/include/linux/dio.h linux/include/linux/dio.h --- v2.1.105/linux/include/linux/dio.h Wed Dec 31 16:00:00 1969 +++ linux/include/linux/dio.h Sat Jun 13 13:14:32 1998 @@ -0,0 +1,204 @@ +/* header file for DIO boards for the HP300 architecture. + * Maybe this should handle DIO-II later? + * The general structure of this is vaguely based on how + * the Amiga port handles Zorro boards. + * Copyright (C) Peter Maydell 05/1998 + * + * The board IDs are from the NetBSD kernel, which for once provided + * helpful comments... + * + * This goes with arch/m68k/hp300/dio.c + */ + +#ifndef _LINUX_DIO_H +#define _LINUX_DIO_H + +/* The DIO boards in a system are distinguished by 'select codes' which + * range from 0-63 (DIO) and 132-255 (DIO-II). + * The DIO board with select code sc is located at physical address + * 0x600000 + sc * 0x10000 + * So DIO cards cover [0x600000-0x800000); the areas [0x200000-0x400000) and + * [0x800000-0x1000000) are for additional space required by things + * like framebuffers. [0x400000-0x600000) is for miscellaneous internal I/O. + * On Linux, this is currently all mapped into the virtual address space + * at 0xf0000000 on bootup. + * DIO-II boards are at 0x1000000 + (sc - 132) * 0x400000 + * which is address range [0x1000000-0x20000000) -- too big to map completely, + * so currently we just don't handle DIO-II boards. It wouldn't be hard to + * do with ioremap() though. + */ +#ifdef __KERNEL__ +/* DIO/DIO-II boards all have the following 8bit registers. + * These are offsets from the base of the device. + */ +#define DIO_IDOFF 0x01 /* primary device ID */ +#define DIO_IPLOFF 0x03 /* interrupt priority level */ +#define DIO_SECIDOFF 0x15 /* secondary device ID */ +#define DIOII_SIZEOFF 0x101 /* device size, DIO-II only */ + +/* The internal HPIB device is special; this is its physaddr; its select code is 7. + * The reason why we have to treat it specially is because apparently it's broken: + * the device ID isn't consistent/reliable. *sigh* + */ +#define DIO_IHPIBADDR 0x47800 +#define DIO_IHPIBSCODE 7 + +/* If we don't have the internal HPIB defined, then treat select code 7 like + * any other. If we *do* have internal HPIB, then we just have to assume that + * select code 7 is the internal HPIB regardless of the ID register :-< + */ +#define CONFIG_IHPIB /* hack hack : not yet a proper config option */ +#ifdef CONFIG_IHPIB +#define DIO_ISIHPIB(scode) ((scode) == DIO_IHPIBSCODE) +#else +#define DIO_ISIHPIB(scode) 0 +#endif + +#define DIO_VIRADDRBASE 0xf0000000 /* vir addr where IOspace is mapped */ + +#define DIO_BASE 0x600000 /* start of DIO space */ +#define DIO_END 0x1000000 /* end of DIO space */ +#define DIO_DEVSIZE 0x10000 /* size of a DIO device */ + +#define DIOII_BASE 0x01000000 /* start of DIO-II space */ +#define DIOII_END 0x20000000 /* end of DIO-II space */ +#define DIOII_DEVSIZE 0x00400000 /* size of a DIO-II device */ + +/* Highest valid select code. If we add DIO-II support this should become + * 256 for everything except HP320, which only has DIO. + */ +#define DIO_SCMAX 32 +#define DIOII_SCBASE 132 /* lowest DIO-II select code */ +#define DIO_SCINHOLE(scode) (((scode) >= 32) && ((scode) < DIOII_SCBASE)) + +/* macros to read device IDs, given base address */ +#define DIO_ID(baseaddr) readb((baseaddr) + DIO_IDOFF) +#define DIO_SECID(baseaddr) readb((baseaddr) + DIO_SECIDOFF) + +/* extract the interrupt level */ +#define DIO_IPL(baseaddr) (((readb((baseaddr) + DIO_IPLOFF) >> 4) & 0x03) + 3) + +/* find the size of a DIO-II board's address space. + * DIO boards are all fixed length. + */ +#define DIOII_SIZE(baseaddr) ((readb((baseaddr) + DIOII_SIZEOFF) + 1) * 0x100000) + +/* general purpose macro for both DIO and DIO-II */ +#define DIO_SIZE(scode, base) (DIO_ISDIOII((scode)) ? DIOII_SIZE((base)) : DIO_DEVSIZE) + +/* The hardware has primary and secondary IDs; we encode these in a single + * int as PRIMARY ID & (SECONDARY ID << 8). + * In practice this is only important for framebuffers, + * and everybody else just sets ID fields equal to the DIO_ID_FOO value. + */ +#define DIO_ENCODE_ID(pr,sec) ((((int)sec & 0xff) << 8) & ((int)pr & 0xff)) +/* macro to determine whether a given primary ID requires a secondary ID byte */ +#define DIO_NEEDSSECID(id) ((id) == DIO_ID_FBUFFER) + +/* Now a whole slew of macros giving device IDs and descriptive strings: */ +#define DIO_ID_DCA0 0x02 /* 98644A serial */ +#define DIO_DESC_DCA0 "98644A DCA0 serial" +#define DIO_ID_DCA0REM 0x82 /* 98644A serial */ +#define DIO_DESC_DCA0REM "98644A DCA0REM serial" +#define DIO_ID_DCA1 0x42 /* 98644A serial */ +#define DIO_DESC_DCA1 "98644A DCA1 serial" +#define DIO_ID_DCA1REM 0xc2 /* 98644A serial */ +#define DIO_DESC_DCA1REM "98644A DCA1REM serial" +#define DIO_ID_DCM 0x05 /* 98642A serial MUX */ +#define DIO_DESC_DCM "98642A DCM serial MUX" +#define DIO_ID_DCMREM 0x85 /* 98642A serial MUX */ +#define DIO_DESC_DCMREM "98642A DCMREM serial MUX" +#define DIO_ID_LAN 0x15 /* 98643A LAN */ +#define DIO_DESC_LAN "98643A LAN" +#define DIO_ID_FHPIB 0x08 /* 98625A/98625B fast HP-IB */ +#define DIO_DESC_FHPIB "98625A/98625B fast HPIB" +#define DIO_ID_NHPIB 0x80 /* 98624A HP-IB (normal ie slow) */ +#define DIO_DESC_NHPIB "98624A HPIB" +#define DIO_ID_IHPIB 0x00 /* internal HPIB (not its real ID, it hasn't got one! */ +#define DIO_DESC_IHPIB "internal HPIB" +#define DIO_ID_SCSI0 0x07 /* 98625A SCSI */ +#define DIO_DESC_SCSI0 "98625A SCSI0" +#define DIO_ID_SCSI1 0x27 /* ditto */ +#define DIO_DESC_SCSI1 "98625A SCSI1" +#define DIO_ID_SCSI2 0x47 /* ditto */ +#define DIO_DESC_SCSI2 "98625A SCSI2" +#define DIO_ID_SCSI3 0x67 /* ditto */ +#define DIO_DESC_SCSI3 "98625A SCSI3" +#define DIO_ID_FBUFFER 0x39 /* framebuffer: flavour is distinguished by secondary ID */ +#define DIO_DESC_FBUFFER "bitmapped display" +/* the NetBSD kernel source is a bit unsure as to what these next IDs actually do :-> */ +#define DIO_ID_MISC0 0x03 /* 98622A */ +#define DIO_DESC_MISC0 "98622A" +#define DIO_ID_MISC1 0x04 /* 98623A */ +#define DIO_DESC_MISC1 "98623A" +#define DIO_ID_PARALLEL 0x06 /* internal parallel */ +#define DIO_DESC_PARALLEL "internal parallel" +#define DIO_ID_MISC2 0x09 /* 98287A keyboard */ +#define DIO_DESC_MISC2 "98287A keyboard" +#define DIO_ID_MISC3 0x0a /* HP98635A FP accelerator */ +#define DIO_DESC_MISC3 "HP98635A FP accelerator" +#define DIO_ID_MISC4 0x0b /* timer */ +#define DIO_DESC_MISC4 "timer" +#define DIO_ID_MISC5 0x12 /* 98640A */ +#define DIO_DESC_MISC5 "98640A" +#define DIO_ID_MISC6 0x16 /* 98659A */ +#define DIO_DESC_MISC6 "98659A" +#define DIO_ID_MISC7 0x19 /* 237 display */ +#define DIO_DESC_MISC7 "237 display" +#define DIO_ID_MISC8 0x1a /* quad-wide card */ +#define DIO_DESC_MISC8 "quad-wide card" +#define DIO_ID_MISC9 0x1b /* 98253A */ +#define DIO_DESC_MISC9 "98253A" +#define DIO_ID_MISC10 0x1c /* 98627A */ +#define DIO_DESC_MISC10 "98253A" +#define DIO_ID_MISC11 0x1d /* 98633A */ +#define DIO_DESC_MISC11 "98633A" +#define DIO_ID_MISC12 0x1e /* 98259A */ +#define DIO_DESC_MISC12 "98259A" +#define DIO_ID_MISC13 0x1f /* 8741 */ +#define DIO_DESC_MISC13 "8741" +#define DIO_ID_VME 0x31 /* 98577A VME adapter */ +#define DIO_DESC_VME "98577A VME adapter" +#define DIO_ID_DCL 0x34 /* 98628A serial */ +#define DIO_DESC_DCL "98628A DCL serial" +#define DIO_ID_DCLREM 0xb4 /* 98628A serial */ +#define DIO_DESC_DCLREM "98628A DCLREM serial" +/* These are the secondary IDs for the framebuffers */ +#define DIO_ID2_GATORBOX 0x01 /* 98700/98710 "gatorbox" */ +#define DIO_DESC2_GATORBOX "98700/98710 \"gatorbox\" display" +#define DIO_ID2_TOPCAT 0x02 /* 98544/98545/98547 "topcat" */ +#define DIO_DESC2_TOPCAT "98544/98545/98547 \"topcat\" display" +#define DIO_ID2_RENAISSANCE 0x04 /* 98720/98721 "renaissance" */ +#define DIO_DESC2_RENAISSANCE "98720/98721 \"renaissance\" display" +#define DIO_ID2_LRCATSEYE 0x05 /* lowres "catseye" */ +#define DIO_DESC2_LRCATSEYE "low-res catseye display" +#define DIO_ID2_HRCCATSEYE 0x06 /* highres colour "catseye" */ +#define DIO_DESC2_HRCCATSEYE "high-res color catseye display" +#define DIO_ID2_HRMCATSEYE 0x07 /* highres mono "catseye" */ +#define DIO_DESC2_HRMCATSEYE "high-res mono catseye display" +#define DIO_ID2_DAVINCI 0x08 /* 98730/98731 "davinci" */ +#define DIO_DESC2_DAVINCI "98730/98731 \"davinci\" display" +#define DIO_ID2_XXXCATSEYE 0x09 /* "catseye" */ +#define DIO_DESC2_XXXCATSEYE "catseye display" +#define DIO_ID2_HYPERION 0x0e /* A1096A "hyperion" */ +#define DIO_DESC2_HYPERION "A1096A \"hyperion\" display" +#define DIO_ID2_XGENESIS 0x0b /* "x-genesis"; no NetBSD support */ +#define DIO_DESC2_XGENESIS "\"x-genesis\" display" +#define DIO_ID2_TIGER 0x0c /* "tiger"; no NetBSD support */ +#define DIO_DESC2_TIGER "\"tiger\" display" +#define DIO_ID2_YGENESIS 0x0d /* "y-genesis"; no NetBSD support */ +#define DIO_DESC2_YGENESIS "\"y-genesis\" display" +/* if you add new IDs then you should tell dio.c about them so it can + * identify them... + */ + +extern void dio_init(void); +extern int dio_find(int deviceid); +extern void *dio_scodetoviraddr(int scode); +extern int dio_scodetoipl(int scode); +extern void dio_config_board(int scode); +extern void dio_unconfig_board(int scode); + + +#endif /* __KERNEL__ */ +#endif /* ndef _LINUX_DIO_H */ diff -u --recursive --new-file v2.1.105/linux/include/linux/if_ether.h linux/include/linux/if_ether.h --- v2.1.105/linux/include/linux/if_ether.h Sun Feb 2 05:18:47 1997 +++ linux/include/linux/if_ether.h Mon Jun 8 10:02:35 1998 @@ -72,6 +72,7 @@ #define ETH_P_LOCALTALK 0x0009 /* Localtalk pseudo type */ #define ETH_P_PPPTALK 0x0010 /* Dummy type for Atalk over PPP*/ #define ETH_P_TR_802_2 0x0011 /* 802.2 frames */ +#define ETH_P_MOBITEX 0x0015 /* Mobitex (kaz@cafe.net) */ /* * This is an Ethernet frame header. diff -u --recursive --new-file v2.1.105/linux/include/linux/in_route.h linux/include/linux/in_route.h --- v2.1.105/linux/include/linux/in_route.h Tue Mar 10 10:03:35 1998 +++ linux/include/linux/in_route.h Thu Jun 11 22:52:33 1998 @@ -18,7 +18,6 @@ #define RTCF_MASQ 0x00400000 #define RTCF_SNAT 0x00800000 #define RTCF_DOREDIRECT 0x01000000 -#define RTCF_LOG 0x02000000 #define RTCF_DIRECTSRC 0x04000000 #define RTCF_DNAT 0x08000000 #define RTCF_BROADCAST 0x10000000 diff -u --recursive --new-file v2.1.105/linux/include/linux/iso_fs.h linux/include/linux/iso_fs.h --- v2.1.105/linux/include/linux/iso_fs.h Thu Feb 12 20:56:13 1998 +++ linux/include/linux/iso_fs.h Sat Jun 13 13:39:16 1998 @@ -182,6 +182,7 @@ extern int find_rock_ridge_relocation(struct iso_directory_record *, struct inode *); int get_joliet_filename(struct iso_directory_record *, struct inode *, unsigned char *); +int get_acorn_filename(struct iso_directory_record *, char *, struct inode *); /* The stuff that follows may be totally unneeded. I have not checked to see which prototypes we are still using. */ @@ -227,6 +228,3 @@ #endif /* __KERNEL__ */ #endif - - - diff -u --recursive --new-file v2.1.105/linux/include/linux/iso_fs_sb.h linux/include/linux/iso_fs_sb.h --- v2.1.105/linux/include/linux/iso_fs_sb.h Thu Feb 12 20:56:13 1998 +++ linux/include/linux/iso_fs_sb.h Sat Jun 13 13:39:16 1998 @@ -30,10 +30,3 @@ }; #endif - - - - - - - diff -u --recursive --new-file v2.1.105/linux/include/linux/minix_fs.h linux/include/linux/minix_fs.h --- v2.1.105/linux/include/linux/minix_fs.h Tue Jan 6 12:26:59 1998 +++ linux/include/linux/minix_fs.h Sat Jun 13 13:25:12 1998 @@ -15,6 +15,7 @@ /* Not the same as the bogus LINK_MAX in . Oh well. */ #define MINIX_LINK_MAX 250 +#define MINIX2_LINK_MAX 65530 #define MINIX_I_MAP_SLOTS 8 #define MINIX_Z_MAP_SLOTS 64 @@ -126,6 +127,7 @@ extern struct inode_operations minix_file_inode_operations; extern struct inode_operations minix_dir_inode_operations; extern struct inode_operations minix_symlink_inode_operations; +extern struct dentry_operations minix_dentry_operations; #endif /* __KERNEL__ */ diff -u --recursive --new-file v2.1.105/linux/include/linux/minix_fs_sb.h linux/include/linux/minix_fs_sb.h --- v2.1.105/linux/include/linux/minix_fs_sb.h Fri Jan 23 18:10:32 1998 +++ linux/include/linux/minix_fs_sb.h Sat Jun 13 13:25:12 1998 @@ -12,8 +12,9 @@ unsigned long s_firstdatazone; unsigned long s_log_zone_size; unsigned long s_max_size; - unsigned long s_dirsize; - unsigned long s_namelen; + int s_dirsize; + int s_namelen; + int s_link_max; struct buffer_head ** s_imap; struct buffer_head ** s_zmap; struct buffer_head * s_sbh; diff -u --recursive --new-file v2.1.105/linux/include/linux/mm.h linux/include/linux/mm.h --- v2.1.105/linux/include/linux/mm.h Wed Apr 8 19:36:29 1998 +++ linux/include/linux/mm.h Sat Jun 13 13:48:23 1998 @@ -290,6 +290,7 @@ extern void vmtruncate(struct inode * inode, unsigned long offset); extern void handle_mm_fault(struct task_struct *tsk,struct vm_area_struct *vma, unsigned long address, int write_access); +extern void check_pgt_cache(void); extern unsigned long paging_init(unsigned long start_mem, unsigned long end_mem); extern void mem_init(unsigned long start_mem, unsigned long end_mem); @@ -299,13 +300,14 @@ /* mmap.c */ extern void vma_init(void); -extern unsigned long do_mmap(struct file * file, unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, unsigned long off); extern void merge_segments(struct mm_struct *, unsigned long, unsigned long); extern void insert_vm_struct(struct mm_struct *, struct vm_area_struct *); extern void exit_mmap(struct mm_struct *); -extern int do_munmap(unsigned long, size_t); extern unsigned long get_unmapped_area(unsigned long, unsigned long); + +extern unsigned long do_mmap(struct file *, unsigned long, unsigned long, + unsigned long, unsigned long, unsigned long); +extern int do_munmap(unsigned long, size_t); /* filemap.c */ extern unsigned long page_unuse(unsigned long); diff -u --recursive --new-file v2.1.105/linux/include/linux/netdevice.h linux/include/linux/netdevice.h --- v2.1.105/linux/include/linux/netdevice.h Sat May 2 14:19:54 1998 +++ linux/include/linux/netdevice.h Sat Jun 13 13:49:23 1998 @@ -253,6 +253,7 @@ void *atalk_ptr; /* Appletalk link */ void *ip_ptr; /* IPv4 specific data */ + void *dn_ptr; /* DECnet specific data */ struct Qdisc *qdisc; struct Qdisc *qdisc_sleeping; diff -u --recursive --new-file v2.1.105/linux/include/linux/nfsd/nfsd.h linux/include/linux/nfsd/nfsd.h --- v2.1.105/linux/include/linux/nfsd/nfsd.h Fri Feb 6 15:34:24 1998 +++ linux/include/linux/nfsd/nfsd.h Sat Jun 13 13:50:34 1998 @@ -60,6 +60,7 @@ }; typedef int (*encode_dent_fn)(struct readdir_cd *, const char *, int, off_t, ino_t); +typedef int (*nfsd_dirop_t)(struct inode *, struct dentry *, int, int); /* * Procedure table for NFSv2 @@ -72,6 +73,8 @@ */ int nfsd_svc(unsigned short port, int nrservs); +/* nfsd/vfs.c */ +int fh_lock_parent(struct svc_fh *, struct dentry *); void nfsd_racache_init(void); int nfsd_lookup(struct svc_rqst *, struct svc_fh *, const char *, int, struct svc_fh *); diff -u --recursive --new-file v2.1.105/linux/include/linux/parport.h linux/include/linux/parport.h --- v2.1.105/linux/include/linux/parport.h Tue Jun 9 11:57:31 1998 +++ linux/include/linux/parport.h Sat Jun 13 12:56:47 1998 @@ -106,6 +106,11 @@ void (*release_resources)(struct parport *); int (*claim_resources)(struct parport *); + void (*epp_write_data)(struct parport *, unsigned char); + unsigned char (*epp_read_data)(struct parport *); + void (*epp_write_addr)(struct parport *, unsigned char); + unsigned char (*epp_read_addr)(struct parport *); + int (*epp_check_timeout)(struct parport *); size_t (*epp_write_block)(struct parport *, void *, size_t); size_t (*epp_read_block)(struct parport *, void *, size_t); @@ -330,6 +335,11 @@ #define parport_change_mode(p,m) parport_pc_change_mode(p,m) #define parport_release_resources(p) parport_pc_release_resources(p) #define parport_claim_resources(p) parport_pc_claim_resources(p) +#define parport_epp_write_data(p,x) parport_pc_write_epp(p,x) +#define parport_epp_read_data(p) parport_pc_read_epp(p) +#define parport_epp_write_addr(p,x) parport_pc_write_epp_addr(p,x) +#define parport_epp_read_addr(p) parport_pc_read_epp_addr(p) +#define parport_epp_check_timeout(p) parport_pc_check_epp_timeout(p) #endif #ifdef PARPORT_NEED_GENERIC_OPS @@ -349,6 +359,11 @@ #define parport_change_mode(p,m) (p)->ops->change_mode(p,m) #define parport_release_resources(p) (p)->ops->release_resources(p) #define parport_claim_resources(p) (p)->ops->claim_resources(p) +#define parport_epp_write_data(p,x) (p)->ops->epp_write_data(p,x) +#define parport_epp_read_data(p) (p)->ops->epp_read_data(p) +#define parport_epp_write_addr(p,x) (p)->ops->epp_write_addr(p,x) +#define parport_epp_read_addr(p) (p)->ops->epp_read_addr(p) +#define parport_epp_check_timeout(p) (p)->ops->epp_check_timeout(p) #endif #endif /* __KERNEL__ */ diff -u --recursive --new-file v2.1.105/linux/include/linux/parport_pc.h linux/include/linux/parport_pc.h --- v2.1.105/linux/include/linux/parport_pc.h Tue Jun 9 11:57:31 1998 +++ linux/include/linux/parport_pc.h Sat Jun 13 12:56:47 1998 @@ -8,19 +8,41 @@ #define ECONTROL 0x402 #define CONFIGB 0x401 #define CONFIGA 0x400 -#define EPPREG 0x4 +#define EPPDATA 0x4 +#define EPPADDR 0x3 #define CONTROL 0x2 #define STATUS 0x1 #define DATA 0 +extern int parport_pc_epp_clear_timeout(struct parport *pb); + + extern __inline__ void parport_pc_write_epp(struct parport *p, unsigned char d) { - outb(d, p->base+EPPREG); + outb(d, p->base+EPPDATA); } extern __inline__ unsigned char parport_pc_read_epp(struct parport *p) { - return inb(p->base+EPPREG); + return inb(p->base+EPPDATA); +} + +extern __inline__ void parport_pc_write_epp_addr(struct parport *p, unsigned char d) +{ + outb(d, p->base+EPPADDR); +} + +extern __inline__ unsigned char parport_pc_read_epp_addr(struct parport *p) +{ + return inb(p->base+EPPADDR); +} + +extern __inline__ int parport_pc_check_epp_timeout(struct parport *p) +{ + if (!(inb(p->base+STATUS) & 1)) + return 0; + parport_pc_epp_clear_timeout(p); + return 1; } extern __inline__ unsigned char parport_pc_read_configb(struct parport *p) diff -u --recursive --new-file v2.1.105/linux/include/linux/pg.h linux/include/linux/pg.h --- v2.1.105/linux/include/linux/pg.h Wed Dec 31 16:00:00 1969 +++ linux/include/linux/pg.h Sat Jun 13 12:08:20 1998 @@ -0,0 +1,63 @@ +/* pg.h (c) 1998 Grant R. Guenther + Under the terms of the GNU public license + + + pg.h defines the user interface to the generic ATAPI packet + command driver for parallel port ATAPI devices (pg). The + driver is loosely modelled after the generic SCSI driver, sg, + although the actual interface is different. + + The pg driver provides a simple character device interface for + sending ATAPI commands to a device. With the exception of the + ATAPI reset operation, all operations are performed by a pair + of read and write operations to the appropriate /dev/pgN device. + A write operation delivers a command and any outbound data in + a single buffer. Normally, the write will succeed unless the + device is offline or malfunctioning, or there is already another + command pending. If the write succeeds, it should be followed + immediately by a read operation, to obtain any returned data and + status information. A read will fail if there is no operation + in progress. + + As a special case, the device can be reset with a write operation, + and in this case, no following read is expected, or permitted. + + There are no ioctl() operations. Any single operation + may transfer at most PG_MAX_DATA bytes. Note that the driver must + copy the data through an internal buffer. In keeping with all + current ATAPI devices, command packets are assumed to be exactly + 12 bytes in length. + + To permit future changes to this interface, the headers in the + read and write buffers contain a single character "magic" flag. + Currently this flag must be the character "P". + +*/ + +#define PG_MAGIC 'P' +#define PG_RESET 'Z' +#define PG_COMMAND 'C' + +#define PG_MAX_DATA 32768 + +struct pg_write_hdr { + + char magic; /* == PG_MAGIC */ + char func; /* PG_RESET or PG_COMMAND */ + int dlen; /* number of bytes expected to transfer */ + int timeout; /* number of seconds before timeout */ + char packet[12]; /* packet command */ + +}; + +struct pg_read_hdr { + + char magic; /* == PG_MAGIC */ + char scsi; /* "scsi" status == sense key */ + int dlen; /* size of device transfer request */ + int duration; /* time in seconds command took */ + char pad[12]; /* not used */ + +}; + +/* end of pg.h */ diff -u --recursive --new-file v2.1.105/linux/include/linux/poll.h linux/include/linux/poll.h --- v2.1.105/linux/include/linux/poll.h Tue Mar 10 10:03:35 1998 +++ linux/include/linux/poll.h Sat Jun 13 13:49:01 1998 @@ -79,8 +79,8 @@ if (ufdset) { int error; error = verify_area(VERIFY_WRITE, ufdset, nr); - if (!error) - error = __copy_from_user(fdset, ufdset, nr); + if (!error && __copy_from_user(fdset, ufdset, nr)) + error = -EFAULT; return error; } memset(fdset, 0, nr); diff -u --recursive --new-file v2.1.105/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h --- v2.1.105/linux/include/linux/proc_fs.h Thu May 14 19:47:43 1998 +++ linux/include/linux/proc_fs.h Sat Jun 13 13:48:33 1998 @@ -49,6 +49,7 @@ PROC_SLABINFO, PROC_PARPORT, PROC_PPC_HTAB, + PROC_STRAM, PROC_SOUND, PROC_MTRR, /* whether enabled or not */ PROC_FS diff -u --recursive --new-file v2.1.105/linux/include/linux/rtnetlink.h linux/include/linux/rtnetlink.h --- v2.1.105/linux/include/linux/rtnetlink.h Sat May 2 14:19:54 1998 +++ linux/include/linux/rtnetlink.h Sat Jun 13 11:40:31 1998 @@ -658,7 +658,7 @@ atomic_dec(&rtnl_rlockct); if (atomic_read(&rtnl_rlockct) <= 1) { wake_up(&rtnl_wait); - if (rtnl->receive_queue.qlen) + if (rtnl && rtnl->receive_queue.qlen) rtnl->data_ready(rtnl, 0); } } @@ -672,7 +672,7 @@ atomic_dec(&rtnl_rlockct); \ if (atomic_read(&rtnl_rlockct) <= 1) { \ wake_up(&rtnl_wait); \ - if (rtnl->receive_queue.qlen) \ + if (rtnl && rtnl->receive_queue.qlen) \ rtnl->data_ready(rtnl, 0); \ } \ }) diff -u --recursive --new-file v2.1.105/linux/include/linux/sched.h linux/include/linux/sched.h --- v2.1.105/linux/include/linux/sched.h Sun Jun 7 11:16:39 1998 +++ linux/include/linux/sched.h Sat Jun 13 13:48:22 1998 @@ -284,6 +284,8 @@ struct signal_struct *sig; sigset_t signal, blocked; struct signal_queue *sigqueue, **sigqueue_tail; + unsigned long sas_ss_sp; + size_t sas_ss_size; /* SMP state */ int has_cpu; int processor; @@ -365,6 +367,7 @@ /* files */ &init_files, \ /* mm */ &init_mm, \ /* signals */ &init_signals, {{0}}, {{0}}, NULL, &init_task.sigqueue, \ + 0, 0, \ /* SMP */ 0,0,0,0, \ /* locks */ INIT_LOCKS \ } @@ -480,6 +483,7 @@ extern int kill_proc(pid_t, int, int); extern int do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact); +extern int do_sigaltstack(const stack_t *ss, stack_t *oss, unsigned long sp); extern inline int signal_pending(struct task_struct *p) { @@ -517,6 +521,19 @@ t->sigpending = (ready != 0); } +/* True if we are on the alternate signal stack. */ + +static inline int on_sig_stack(unsigned long sp) +{ + return (sp >= current->sas_ss_sp + && sp < current->sas_ss_sp + current->sas_ss_size); +} + +static inline int sas_ss_flags(unsigned long sp) +{ + return (current->sas_ss_size == 0 ? SS_DISABLE + : on_sig_stack(sp) ? SS_ONSTACK : 0); +} extern int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), diff -u --recursive --new-file v2.1.105/linux/include/linux/signal.h linux/include/linux/signal.h --- v2.1.105/linux/include/linux/signal.h Fri Feb 6 15:32:54 1998 +++ linux/include/linux/signal.h Sat Jun 13 13:08:19 1998 @@ -162,6 +162,8 @@ } } +extern char * render_sigset_t(sigset_t *set, char *buffer); + /* Some extensions for manipulating the low 32 signals in particular. */ extern inline void sigaddsetmask(sigset_t *set, unsigned long mask) diff -u --recursive --new-file v2.1.105/linux/include/linux/swap.h linux/include/linux/swap.h --- v2.1.105/linux/include/linux/swap.h Wed Apr 8 19:36:29 1998 +++ linux/include/linux/swap.h Sat Jun 13 13:28:33 1998 @@ -75,6 +75,11 @@ void si_swapinfo(struct sysinfo *); unsigned long get_swap_page(void); extern void FASTCALL(swap_free(unsigned long)); +struct swap_list_t { + int head; /* head of priority-ordered swapfile list */ + int next; /* swapfile to be used next */ +}; +extern struct swap_list_t swap_list; /* * vm_ops not present page codes for shared memory. diff -u --recursive --new-file v2.1.105/linux/include/linux/sysctl.h linux/include/linux/sysctl.h --- v2.1.105/linux/include/linux/sysctl.h Fri May 8 23:14:57 1998 +++ linux/include/linux/sysctl.h Sat Jun 13 12:48:11 1998 @@ -80,7 +80,8 @@ VM_OVERCOMMIT_MEMORY, /* Turn off the virtual memory safety limit */ VM_BUFFERMEM, /* struct: Set buffer memory thresholds */ VM_PAGECACHE, /* struct: Set cache memory thresholds */ - VM_PAGERDAEMON /* struct: Control kswapd behaviour */ + VM_PAGERDAEMON, /* struct: Control kswapd behaviour */ + VM_PGT_CACHE /* struct: Set page table cache parameters */ }; diff -u --recursive --new-file v2.1.105/linux/include/linux/timer.h linux/include/linux/timer.h --- v2.1.105/linux/include/linux/timer.h Thu Mar 26 15:57:06 1998 +++ linux/include/linux/timer.h Sat Jun 13 11:45:10 1998 @@ -71,4 +71,22 @@ timer->prev = NULL; } +/* + * These inlines deal with timer wrapping correctly. You are + * strongly encouraged to use them + * 1. Because people otherwise forget + * 2. Because if the timer wrap changes in future you wont have to + * alter your driver code. + */ + +extern inline int time_before(unsigned long a, unsigned long b) +{ + return((long)((a) - (b)) < 0L); +} + +extern inline int time_after(unsigned long a, unsigned long b) +{ + return((long)((a) - (b)) > 0L); +} + #endif diff -u --recursive --new-file v2.1.105/linux/include/linux/utsname.h linux/include/linux/utsname.h --- v2.1.105/linux/include/linux/utsname.h Wed Dec 1 04:44:15 1993 +++ linux/include/linux/utsname.h Sat Jun 13 11:45:09 1998 @@ -32,4 +32,5 @@ extern struct new_utsname system_utsname; +extern struct semaphore uts_sem; #endif diff -u --recursive --new-file v2.1.105/linux/include/linux/vmalloc.h linux/include/linux/vmalloc.h --- v2.1.105/linux/include/linux/vmalloc.h Wed Apr 1 20:11:54 1998 +++ linux/include/linux/vmalloc.h Sat Jun 13 13:48:23 1998 @@ -20,20 +20,5 @@ void vmfree_area_pages(unsigned long address, unsigned long size); int vmalloc_area_pages(unsigned long address, unsigned long size); -extern inline void set_pgdir(unsigned long address, pgd_t entry) -{ -#if !defined(__mc68000__) && !defined(__sparc_v9__) - struct task_struct * p; - - read_lock(&tasklist_lock); - for_each_task(p) { - if (!p->mm) - continue; - *pgd_offset(p->mm,address) = entry; - } - read_unlock(&tasklist_lock); -#endif -} - #endif diff -u --recursive --new-file v2.1.105/linux/include/linux/zorro.h linux/include/linux/zorro.h --- v2.1.105/linux/include/linux/zorro.h Sun Jun 7 11:16:39 1998 +++ linux/include/linux/zorro.h Mon Jun 8 11:03:50 1998 @@ -87,7 +87,7 @@ #define ZORRO_ID(manuf, prod, epc) \ ((ZORRO_MANUF_##manuf << 16) | ((prod) << 8) | (epc)) -typedef u32 zorro_id; +typedef __u32 zorro_id; #define ZORRO_MANUF_PACIFIC_PERIPHERALS 0x00D3 @@ -462,6 +462,9 @@ #define ZORRO_MANUF_ARMAX 0x0885 #define ZORRO_PROD_ARMAX_OMNIBUS ZORRO_ID(ARMAX, 0x00, 0) +#define ZORRO_MANUF_ZEUS 0x088d +#define ZORRO_PROD_ZEUS_SPIDER ZORRO_ID(ZEUS, 0x04, 0) + #define ZORRO_MANUF_NEWTEK 0x088F #define ZORRO_PROD_NEWTEK_VIDEOTOASTER ZORRO_ID(NEWTEK, 0x00, 0) @@ -558,6 +561,7 @@ #define ZORRO_PROD_PHASE5_CYBERVISION64_3D_PROTOTYPE ZORRO_ID(PHASE5, 0x32, 0) #define ZORRO_PROD_PHASE5_CYBERVISION64_3D ZORRO_ID(PHASE5, 0x43, 0) #define ZORRO_PROD_PHASE5_CYBERSTORM_MK_III ZORRO_ID(PHASE5, 0x64, 0) +#define ZORRO_PROD_PHASE5_BLIZZARD_603E_PLUS ZORRO_ID(PHASE5, 0x6e, 0) #define ZORRO_MANUF_DPS 0x2169 #define ZORRO_PROD_DPS_PERSONAL_ANIMATION_RECORDER ZORRO_ID(DPS, 0x01, 0) @@ -576,6 +580,9 @@ #define ZORRO_MANUF_UWE_GERLACH 0x3FF7 #define ZORRO_PROD_UWE_GERLACH_RAM_ROM ZORRO_ID(UWE_GERLACH, 0xd4, 0) + +#define ZORRO_MANUF_ACT 0x4231 +#define ZORRO_PROD_ACT_PRELUDE ZORRO_ID(ACT, 0x01, 0) #define ZORRO_MANUF_MACROSYSTEMS_GERMANY 0x4754 #define ZORRO_PROD_MACROSYSTEMS_MAESTRO ZORRO_ID(MACROSYSTEMS_GERMANY, 0x03, 0) diff -u --recursive --new-file v2.1.105/linux/include/net/tcp.h linux/include/net/tcp.h --- v2.1.105/linux/include/net/tcp.h Thu May 7 22:51:55 1998 +++ linux/include/net/tcp.h Sat Jun 13 13:51:26 1998 @@ -654,17 +654,24 @@ return mss_now; } -/* Compute the actual receive window we are currently advertising. */ +/* Compute the actual receive window we are currently advertising. + * Rcv_nxt can be after the window if our peer push more data + * than the offered window. + */ static __inline__ u32 tcp_receive_window(struct tcp_opt *tp) { - return tp->rcv_wup - (tp->rcv_nxt - tp->rcv_wnd); + s32 win = tp->rcv_wup + tp->rcv_wnd - tp->rcv_nxt; + + if (win < 0) + win = 0; + return (u32) win; } /* Choose a new window, without checks for shrinking, and without * scaling applied to the result. The caller does these things * if necessary. This is a "raw" window selection. */ -extern u32 __tcp_select_window(struct sock *sk); +extern u32 __tcp_select_window(struct sock *sk, u32 cur_win); /* Chose a new window to advertise, update state in tcp_opt for the * socket, and return result with RFC1323 scaling applied. The return @@ -674,8 +681,8 @@ extern __inline__ u16 tcp_select_window(struct sock *sk) { struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); - u32 new_win = __tcp_select_window(sk); u32 cur_win = tcp_receive_window(tp); + u32 new_win = __tcp_select_window(sk, cur_win); /* Never shrink the offered window */ if(new_win < cur_win) @@ -694,8 +701,8 @@ extern __inline__ int tcp_raise_window(struct sock *sk) { struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); - u32 new_win = __tcp_select_window(sk); u32 cur_win = tcp_receive_window(tp); + u32 new_win = __tcp_select_window(sk, cur_win); return (new_win && (new_win > (cur_win << 1))); } diff -u --recursive --new-file v2.1.105/linux/init/main.c linux/init/main.c --- v2.1.105/linux/init/main.c Tue Jun 9 11:57:31 1998 +++ linux/init/main.c Sat Jun 13 13:14:32 1998 @@ -44,6 +44,10 @@ #include #endif +#ifdef CONFIG_DIO +#include +#endif + /* * Versions of gcc older than that listed below may actually compile * and link okay, but the end product can have subtle run time bugs. @@ -76,6 +80,10 @@ extern void filescache_init(void); extern void signals_init(void); +#ifdef CONFIG_ARCH_ACORN +extern void ecard_init(void); +#endif + extern void smp_setup(char *str, int *ints); #ifdef __i386__ extern void ioapic_pirq_setup(char *str, int *ints); @@ -124,6 +132,9 @@ #ifdef CONFIG_PARIDE_PT extern void pt_setup(char *str, int *ints); #endif +#ifdef CONFIG_PARIDE_PG +extern void pg_setup(char *str, int *ints); +#endif #ifdef CONFIG_PARIDE_PCD extern void pcd_setup(char *str, int *ints); #endif @@ -378,6 +389,17 @@ { "sdc", 0x0820 }, { "sdd", 0x0830 }, { "sde", 0x0840 }, + { "sdf", 0x0850 }, + { "sdg", 0x0860 }, + { "sdh", 0x0870 }, + { "sdi", 0x0880 }, + { "sdj", 0x0890 }, + { "sdk", 0x08a0 }, + { "sdl", 0x08b0 }, + { "sdm", 0x08c0 }, + { "sdn", 0x08d0 }, + { "sdo", 0x08e0 }, + { "sdp", 0x08f0 }, #endif #ifdef CONFIG_ATARI_ACSI { "ada", 0x1c00 }, @@ -667,7 +689,7 @@ #ifdef CONFIG_ISP16_CDI { "isp16=", isp16_setup }, #endif CONFIG_ISP16_CDI -#ifdef CONFIG_SOUND +#ifdef CONFIG_SOUND_OSS { "sound=", sound_setup }, #endif #ifdef CONFIG_ISDN_DRV_ICN @@ -778,6 +800,9 @@ #ifdef CONFIG_PARIDE_PT { "pt.", pt_setup }, #endif +#ifdef CONFIG_PARIDE_PG + { "pg.", pg_setup }, +#endif { 0, 0 } }; @@ -1090,6 +1115,9 @@ #ifdef CONFIG_SYSCTL sysctl_init(); #endif +#ifdef CONFIG_DIO + dio_init(); +#endif /* * Ok, at this point all CPU's should be initialized, so @@ -1106,6 +1134,9 @@ #endif #ifdef CONFIG_MCA mca_init(); +#endif +#ifdef CONFIG_ARCH_ACORN + ecard_init(); #endif /* diff -u --recursive --new-file v2.1.105/linux/ipc/shm.c linux/ipc/shm.c --- v2.1.105/linux/ipc/shm.c Thu May 7 22:51:55 1998 +++ linux/ipc/shm.c Tue Jun 9 10:34:33 1998 @@ -136,6 +136,7 @@ struct shmid_ds *shp; int err, id = 0; + down(¤t->mm->mmap_sem); lock_kernel(); if (size < 0 || size > SHMMAX) { err = -EINVAL; @@ -160,6 +161,7 @@ err = (int) shp->shm_perm.seq * SHMMNI + id; } unlock_kernel(); + up(¤t->mm->mmap_sem); return err; } @@ -484,6 +486,7 @@ unsigned long addr; unsigned long len; + down(¤t->mm->mmap_sem); lock_kernel(); if (shmid < 0) { /* printk("shmat() -> EINVAL because shmid = %d < 0\n",shmid); */ @@ -584,6 +587,7 @@ err = 0; out: unlock_kernel(); + up(¤t->mm->mmap_sem); return err; } @@ -634,6 +638,7 @@ { struct vm_area_struct *shmd, *shmdnext; + down(¤t->mm->mmap_sem); lock_kernel(); for (shmd = current->mm->mmap; shmd; shmd = shmdnext) { shmdnext = shmd->vm_next; @@ -642,6 +647,7 @@ do_munmap(shmd->vm_start, shmd->vm_end - shmd->vm_start); } unlock_kernel(); + up(¤t->mm->mmap_sem); return 0; } diff -u --recursive --new-file v2.1.105/linux/kernel/fork.c linux/kernel/fork.c --- v2.1.105/linux/kernel/fork.c Thu May 7 22:51:55 1998 +++ linux/kernel/fork.c Tue Jun 9 10:37:17 1998 @@ -204,7 +204,6 @@ int retval; flush_cache_mm(current->mm); - down(¤t->mm->mmap_sem); pprev = &mm->mmap; for (mpnt = current->mm->mmap ; mpnt ; mpnt = mpnt->vm_next) { struct file *file; @@ -254,7 +253,6 @@ fail_nomem: flush_tlb_mm(current->mm); - up(¤t->mm->mmap_sem); return retval; } @@ -466,6 +464,7 @@ int error = -ENOMEM; struct task_struct *p; + down(¤t->mm->mmap_sem); lock_kernel(); p = alloc_task_struct(); if (!p) @@ -570,6 +569,7 @@ ++total_forks; error = p->pid; bad_fork: + up(¤t->mm->mmap_sem); unlock_kernel(); return error; diff -u --recursive --new-file v2.1.105/linux/kernel/kmod.c linux/kernel/kmod.c --- v2.1.105/linux/kernel/kmod.c Tue Jun 9 11:57:31 1998 +++ linux/kernel/kmod.c Sat Jun 13 10:23:41 1998 @@ -93,6 +93,13 @@ int pid; int waitpid_result; + /* Don't allow request_module() before the root fs is mounted! */ + if ( ! current->fs->root ) { + printk(KERN_ERR "request_module[%s]: Root fs not mounted\n", + module_name); + return -EPERM; + } + pid = kernel_thread(exec_modprobe, (void*) module_name, CLONE_FS); if (pid < 0) { printk(KERN_ERR "kmod: fork failed, errno %d\n", -pid); diff -u --recursive --new-file v2.1.105/linux/kernel/ksyms.c linux/kernel/ksyms.c --- v2.1.105/linux/kernel/ksyms.c Fri May 8 23:14:57 1998 +++ linux/kernel/ksyms.c Sat Jun 13 11:45:09 1998 @@ -326,7 +326,8 @@ EXPORT_SYMBOL(vsprintf); EXPORT_SYMBOL(kdevname); EXPORT_SYMBOL(simple_strtoul); -EXPORT_SYMBOL(system_utsname); +EXPORT_SYMBOL(system_utsname); /* UTS data */ +EXPORT_SYMBOL(uts_sem); /* UTS semaphore */ EXPORT_SYMBOL(sys_call_table); EXPORT_SYMBOL(machine_restart); EXPORT_SYMBOL(machine_halt); diff -u --recursive --new-file v2.1.105/linux/kernel/sched.c linux/kernel/sched.c --- v2.1.105/linux/kernel/sched.c Sun Jun 7 11:16:40 1998 +++ linux/kernel/sched.c Sat Jun 13 11:58:58 1998 @@ -1564,7 +1564,6 @@ printk("\n"); { - extern char * render_sigset_t(sigset_t *set, char *buffer); struct signal_queue *q; char s[sizeof(sigset_t)*2+1], b[sizeof(sigset_t)*2+1]; @@ -1575,6 +1574,21 @@ printk(" %d", q->info.si_signo); printk(" X\n"); } +} + +char * render_sigset_t(sigset_t *set, char *buffer) +{ + int i = _NSIG, x; + do { + i -= 4, x = 0; + if (sigismember(set, i+1)) x |= 1; + if (sigismember(set, i+2)) x |= 2; + if (sigismember(set, i+3)) x |= 4; + if (sigismember(set, i+4)) x |= 8; + *buffer++ = (x < 10 ? '0' : 'a' - 10) + x; + } while (i >= 4); + *buffer = 0; + return buffer; } void show_state(void) diff -u --recursive --new-file v2.1.105/linux/kernel/signal.c linux/kernel/signal.c --- v2.1.105/linux/kernel/signal.c Thu May 7 22:51:55 1998 +++ linux/kernel/signal.c Tue Jun 9 10:14:12 1998 @@ -840,6 +840,62 @@ return 0; } +int +do_sigaltstack (const stack_t *uss, stack_t *uoss, unsigned long sp) +{ + stack_t oss; + int error; + + if (uoss) { + oss.ss_sp = (void *) current->sas_ss_sp; + oss.ss_size = current->sas_ss_size; + oss.ss_flags = sas_ss_flags(sp); + } + + if (uss) { + void *ss_sp; + size_t ss_size; + int ss_flags; + + error = -EFAULT; + if (verify_area(VERIFY_READ, uss, sizeof(*uss)) + || __get_user(ss_sp, &uss->ss_sp) + || __get_user(ss_flags, &uss->ss_flags) + || __get_user(ss_size, &uss->ss_size)) + goto out; + + error = -EPERM; + if (on_sig_stack (sp)) + goto out; + + error = -EINVAL; + if (ss_flags & ~SS_DISABLE) + goto out; + + if (ss_flags & SS_DISABLE) { + ss_size = 0; + ss_sp = NULL; + } else { + error = -ENOMEM; + if (ss_size < MINSIGSTKSZ) + goto out; + } + + current->sas_ss_sp = (unsigned long) ss_sp; + current->sas_ss_size = ss_size; + } + + if (uoss) { + error = -EFAULT; + if (copy_to_user(uoss, &oss, sizeof(oss))) + goto out; + } + + error = 0; +out: + return error; +} + #if !defined(__alpha__) /* Alpha has its own versions with special arguments. */ @@ -908,6 +964,7 @@ return error; } +#ifndef __sparc__ asmlinkage int sys_rt_sigaction(int sig, const struct sigaction *act, struct sigaction *oact, size_t sigsetsize) @@ -933,6 +990,7 @@ out: return ret; } +#endif /* __sparc__ */ #endif #if !defined(__alpha__) diff -u --recursive --new-file v2.1.105/linux/kernel/sysctl.c linux/kernel/sysctl.c --- v2.1.105/linux/kernel/sysctl.c Fri May 8 23:14:57 1998 +++ linux/kernel/sysctl.c Sat Jun 13 12:48:11 1998 @@ -55,8 +55,12 @@ extern unsigned long htab_reclaim_on, zero_paged_on; #endif +extern int pgt_cache_water[]; + static int parse_table(int *, int, void *, size_t *, void *, size_t, ctl_table *, void **); +static int proc_doutsstring(ctl_table *table, int write, struct file *filp, + void *buffer, size_t *lenp); static ctl_table root_table[]; @@ -138,15 +142,15 @@ static ctl_table kern_table[] = { {KERN_OSTYPE, "ostype", system_utsname.sysname, 64, - 0444, NULL, &proc_dostring, &sysctl_string}, + 0444, NULL, &proc_doutsstring, &sysctl_string}, {KERN_OSRELEASE, "osrelease", system_utsname.release, 64, - 0444, NULL, &proc_dostring, &sysctl_string}, + 0444, NULL, &proc_doutsstring, &sysctl_string}, {KERN_VERSION, "version", system_utsname.version, 64, - 0444, NULL, &proc_dostring, &sysctl_string}, + 0444, NULL, &proc_doutsstring, &sysctl_string}, {KERN_NODENAME, "hostname", system_utsname.nodename, 64, - 0644, NULL, &proc_dostring, &sysctl_string}, + 0644, NULL, &proc_doutsstring, &sysctl_string}, {KERN_DOMAINNAME, "domainname", system_utsname.domainname, 64, - 0644, NULL, &proc_dostring, &sysctl_string}, + 0644, NULL, &proc_doutsstring, &sysctl_string}, {KERN_PANIC, "panic", &panic_timeout, sizeof(int), 0644, NULL, &proc_dointvec}, #ifdef CONFIG_BLK_DEV_INITRD @@ -202,6 +206,8 @@ &page_cache, sizeof(buffer_mem_t), 0644, NULL, &proc_dointvec}, {VM_PAGERDAEMON, "kswapd", &pager_daemon, sizeof(pager_daemon_t), 0644, NULL, &proc_dointvec}, + {VM_PGT_CACHE, "pagetable_cache", + &pgt_cache_water, 2*sizeof(int), 0600, NULL, &proc_dointvec}, {0} }; @@ -627,6 +633,21 @@ filp->f_pos += len; } return 0; +} + +/* + * Special case of dostring for the UTS structure. This has locks + * to observe. Should this be in kernel/sys.c ???? + */ + +static int proc_doutsstring(ctl_table *table, int write, struct file *filp, + void *buffer, size_t *lenp) +{ + int r; + down(&uts_sem); + r=proc_dostring(table,write,filp,buffer,lenp); + up(&uts_sem); + return r; } static int do_proc_dointvec(ctl_table *table, int write, struct file *filp, diff -u --recursive --new-file v2.1.105/linux/mm/filemap.c linux/mm/filemap.c --- v2.1.105/linux/mm/filemap.c Thu Mar 26 15:57:06 1998 +++ linux/mm/filemap.c Tue Jun 9 10:34:03 1998 @@ -1256,6 +1256,7 @@ struct vm_area_struct * vma; int unmapped_error, error = -EINVAL; + down(¤t->mm->mmap_sem); lock_kernel(); if (start & ~PAGE_MASK) goto out; @@ -1303,6 +1304,7 @@ } out: unlock_kernel(); + up(¤t->mm->mmap_sem); return error; } diff -u --recursive --new-file v2.1.105/linux/mm/memory.c linux/mm/memory.c --- v2.1.105/linux/mm/memory.c Tue Mar 10 10:03:36 1998 +++ linux/mm/memory.c Sat Jun 13 12:48:11 1998 @@ -44,6 +44,8 @@ #include #include #include +#include +#include #include #include @@ -68,8 +70,6 @@ copy_page(to, from); } -#define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE) - mem_map_t * mem_map = NULL; /* @@ -163,13 +163,10 @@ int new_page_tables(struct task_struct * tsk) { - pgd_t * page_dir, * new_pg; + pgd_t * new_pg; if (!(new_pg = pgd_alloc())) return -ENOMEM; - page_dir = pgd_offset(&init_mm, 0); - memcpy(new_pg + USER_PTRS_PER_PGD, page_dir + USER_PTRS_PER_PGD, - (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof (pgd_t)); SET_PAGE_DIR(tsk, new_pg); tsk->mm->pgd = new_pg; return 0; @@ -895,6 +892,9 @@ do_wp_page(tsk, vma, address, write_access, pte); } +/* + * By the time we get here, we already hold the mm semaphore + */ void handle_mm_fault(struct task_struct *tsk, struct vm_area_struct * vma, unsigned long address, int write_access) { @@ -909,9 +909,30 @@ pte = pte_alloc(pmd, address); if (!pte) goto no_memory; + lock_kernel(); handle_pte_fault(tsk, vma, address, write_access, pte); + unlock_kernel(); update_mmu_cache(vma, address, *pte); return; no_memory: oom(tsk); +} + +/* Low and high watermarks for page table cache. + The system should try to have pgt_water[0] <= cache elements <= pgt_water[1] + */ +int pgt_cache_water[2] = { 25, 50 }; + +void check_pgt_cache(void) +{ + if(pgtable_cache_size > pgt_cache_water[0]) { + do { + if(pgd_quicklist) + free_pgd_slow(get_pgd_fast()); + if(pmd_quicklist) + free_pmd_slow(get_pmd_fast()); + if(pte_quicklist) + free_pte_slow(get_pte_fast()); + } while(pgtable_cache_size > pgt_cache_water[1]); + } } diff -u --recursive --new-file v2.1.105/linux/mm/mlock.c linux/mm/mlock.c --- v2.1.105/linux/mm/mlock.c Fri May 8 23:14:57 1998 +++ linux/mm/mlock.c Tue Jun 9 11:10:20 1998 @@ -127,13 +127,25 @@ pages = -pages; vma->vm_mm->locked_vm += pages; - if (newflags & VM_LOCKED) +#if 0 +/* + * This is horribly broken. See the comment on the same + * brokenness in mm/mmap.c (essentially, this doesn't + * work anyway for PROT_NONE and writable pages, and now + * that we properly get the mmap semaphore it would just + * lock up on us). + * + * Fix the same way. + */ + if (newflags & VM_LOCKED) { while (start < end) { int c; get_user(c,(int *) start); __asm__ __volatile__("": :"r" (c)); start += PAGE_SIZE; } + } +#endif } return retval; } @@ -192,6 +204,7 @@ unsigned long lock_limit; int error = -ENOMEM; + down(¤t->mm->mmap_sem); lock_kernel(); len = (len + (start & ~PAGE_MASK) + ~PAGE_MASK) & PAGE_MASK; start &= PAGE_MASK; @@ -214,6 +227,7 @@ error = do_mlock(start, len, 1); out: unlock_kernel(); + up(¤t->mm->mmap_sem); return error; } @@ -221,11 +235,13 @@ { int ret; + down(¤t->mm->mmap_sem); lock_kernel(); len = (len + (start & ~PAGE_MASK) + ~PAGE_MASK) & PAGE_MASK; start &= PAGE_MASK; ret = do_mlock(start, len, 0); unlock_kernel(); + up(¤t->mm->mmap_sem); return ret; } @@ -263,6 +279,7 @@ unsigned long lock_limit; int ret = -EINVAL; + down(¤t->mm->mmap_sem); lock_kernel(); if (!flags || (flags & ~(MCL_CURRENT | MCL_FUTURE))) goto out; @@ -282,6 +299,7 @@ ret = do_mlockall(flags); out: unlock_kernel(); + up(¤t->mm->mmap_sem); return ret; } @@ -289,8 +307,10 @@ { int ret; + down(¤t->mm->mmap_sem); lock_kernel(); ret = do_mlockall(0); unlock_kernel(); + up(¤t->mm->mmap_sem); return ret; } diff -u --recursive --new-file v2.1.105/linux/mm/mmap.c linux/mm/mmap.c --- v2.1.105/linux/mm/mmap.c Tue Mar 10 10:03:36 1998 +++ linux/mm/mmap.c Sat Jun 13 13:13:20 1998 @@ -92,6 +92,7 @@ unsigned long newbrk, oldbrk; struct mm_struct *mm = current->mm; + down(&mm->mmap_sem); lock_kernel(); if (brk < mm->end_code) goto out; @@ -109,9 +110,7 @@ /* Check against rlimit and stack.. */ rlim = current->rlim[RLIMIT_DATA].rlim_cur; - if (rlim >= RLIM_INFINITY) - rlim = ~0; - if (brk - mm->end_code > rlim) + if (rlim < RLIM_INFINITY && brk - mm->end_code > rlim) goto out; /* Check against existing mmap mappings. */ @@ -132,6 +131,7 @@ out: retval = mm->brk; unlock_kernel(); + up(&mm->mmap_sem); return retval; } @@ -316,9 +316,21 @@ merge_segments(mm, vma->vm_start, vma->vm_end); mm->total_vm += len >> PAGE_SHIFT; - if ((flags & VM_LOCKED) && !(flags & VM_IO)) { - unsigned long start = addr; + if (flags & VM_LOCKED) { mm->locked_vm += len >> PAGE_SHIFT; + +/* + * This used to be just slightly broken, now it's just completely + * buggered. We can't take a page fault here, because we already + * hold the mm semaphore (as is proper). We should do this by hand + * by calling the appropriate fault-in routine. + * + * That would also fix this routine wrt writes and PROT_NONE + * areas, both of which can't be handled by the page fault + * approach anyway. + */ +#if 0 + unsigned long start = addr; do { char c; get_user(c,(char *) start); @@ -326,6 +338,7 @@ start += PAGE_SIZE; __asm__ __volatile__("": :"r" (c)); } while (len > 0); +#endif } return addr; @@ -442,16 +455,6 @@ return 1; } -asmlinkage int sys_munmap(unsigned long addr, size_t len) -{ - int ret; - - lock_kernel(); - ret = do_munmap(addr, len); - unlock_kernel(); - return ret; -} - /* Munmap is split into 2 main parts -- this part which finds * what needs doing, and the areas themselves, which do the * work. This now handles partial unmappings. @@ -460,7 +463,7 @@ int do_munmap(unsigned long addr, size_t len) { struct mm_struct * mm; - struct vm_area_struct *mpnt, *next, *free, *extra; + struct vm_area_struct *mpnt, *free, *extra; int freed; if ((addr & ~PAGE_MASK) || addr > TASK_SIZE || len > TASK_SIZE-addr) @@ -481,6 +484,11 @@ if (!mpnt) return 0; + /* If we'll make "hole", check the vm areas limit */ + if ((mpnt->vm_start < addr && mpnt->vm_end > addr+len) && + mm->map_count > MAX_MAP_COUNT) + return -ENOMEM; + /* * We may need one additional vma to fix up the mappings ... * and this is the last chance for an easy error exit. @@ -489,9 +497,7 @@ if (!extra) return -ENOMEM; - next = mpnt->vm_next; - - /* we have mpnt->vm_next = next and addr < mpnt->vm_end */ + /* we have addr < mpnt->vm_end */ free = NULL; for ( ; mpnt && mpnt->vm_start < addr+len; ) { struct vm_area_struct *next = mpnt->vm_next; @@ -505,13 +511,6 @@ mpnt = next; } - if (free && (free->vm_start < addr) && (free->vm_end > addr+len)) { - if (mm->map_count > MAX_MAP_COUNT) { - kmem_cache_free(vm_area_cachep, extra); - return -ENOMEM; - } - } - /* Ok - we have the memory areas we should free on the 'free' list, * so release them, and unmap the page range.. * If the one of the segments is only being partially unmapped, @@ -555,6 +554,18 @@ return 0; } +asmlinkage int sys_munmap(unsigned long addr, size_t len) +{ + int ret; + + down(¤t->mm->mmap_sem); + lock_kernel(); + ret = do_munmap(addr, len); + unlock_kernel(); + up(¤t->mm->mmap_sem); + return ret; +} + /* Release all mmaps. */ void exit_mmap(struct mm_struct * mm) { @@ -630,13 +641,13 @@ * This assumes that the list is ordered by address. * We don't need to traverse the entire list, only those segments * which intersect or are adjacent to a given interval. + * + * We must already hold the mm semaphore when we get here.. */ void merge_segments (struct mm_struct * mm, unsigned long start_addr, unsigned long end_addr) { struct vm_area_struct *prev, *mpnt, *next; - down(&mm->mmap_sem); - prev = NULL; mpnt = mm->mmap; while(mpnt && mpnt->vm_end <= start_addr) { @@ -644,7 +655,7 @@ mpnt = mpnt->vm_next; } if (!mpnt) - goto no_vma; + return; next = mpnt->vm_next; @@ -700,8 +711,6 @@ mpnt = prev; } mm->mmap_cache = NULL; /* Kill the cache. */ -no_vma: - up(&mm->mmap_sem); } __initfunc(void vma_init(void)) diff -u --recursive --new-file v2.1.105/linux/mm/mprotect.c linux/mm/mprotect.c --- v2.1.105/linux/mm/mprotect.c Thu Mar 26 15:57:06 1998 +++ linux/mm/mprotect.c Tue Jun 9 10:33:10 1998 @@ -208,18 +208,20 @@ struct vm_area_struct * vma, * next; int error = -EINVAL; - lock_kernel(); if (start & ~PAGE_MASK) - goto out; + return -EINVAL; len = (len + ~PAGE_MASK) & PAGE_MASK; end = start + len; if (end < start) - goto out; + return -EINVAL; if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) - goto out; - error = 0; + return -EINVAL; if (end == start) - goto out; + return 0; + + down(¤t->mm->mmap_sem); + lock_kernel(); + vma = find_vma(current->mm, start); error = -EFAULT; if (!vma || vma->vm_start > start) @@ -256,5 +258,6 @@ merge_segments(current->mm, start, end); out: unlock_kernel(); + up(¤t->mm->mmap_sem); return error; } diff -u --recursive --new-file v2.1.105/linux/mm/mremap.c linux/mm/mremap.c --- v2.1.105/linux/mm/mremap.c Tue Mar 10 10:03:36 1998 +++ linux/mm/mremap.c Tue Jun 9 10:33:20 1998 @@ -167,6 +167,7 @@ struct vm_area_struct *vma; unsigned long ret = -EINVAL; + down(¤t->mm->mmap_sem); lock_kernel(); if (addr & ~PAGE_MASK) goto out; @@ -233,5 +234,6 @@ ret = -ENOMEM; out: unlock_kernel(); + up(¤t->mm->mmap_sem); return ret; } diff -u --recursive --new-file v2.1.105/linux/mm/swapfile.c linux/mm/swapfile.c --- v2.1.105/linux/mm/swapfile.c Thu May 7 22:51:55 1998 +++ linux/mm/swapfile.c Sat Jun 13 13:28:34 1998 @@ -28,10 +28,7 @@ unsigned int nr_swapfiles = 0; -static struct { - int head; /* head of priority-ordered swapfile list */ - int next; /* swapfile to be used next */ -} swap_list = {-1, -1}; +struct swap_list_t swap_list = {-1, -1}; struct swap_info_struct swap_info[MAX_SWAPFILES]; @@ -595,7 +592,7 @@ p->flags = SWP_WRITEOK; p->pages = j; nr_swap_pages += j; - printk("Adding Swap: %dk swap-space (priority %d)\n", + printk(KERN_INFO "Adding Swap: %dk swap-space (priority %d)\n", j<<(PAGE_SHIFT-10), p->prio); /* insert swap space into swap_list: */ diff -u --recursive --new-file v2.1.105/linux/mm/vmalloc.c linux/mm/vmalloc.c --- v2.1.105/linux/mm/vmalloc.c Wed Apr 1 20:11:55 1998 +++ linux/mm/vmalloc.c Sat Jun 13 12:48:11 1998 @@ -133,12 +133,16 @@ dir = pgd_offset_k(address); flush_cache_all(); while (address < end) { - pmd_t *pmd = pmd_alloc_kernel(dir, address); + pmd_t *pmd; + pgd_t olddir = *dir; + + pmd = pmd_alloc_kernel(dir, address); if (!pmd) return -ENOMEM; if (alloc_area_pmd(pmd, address, end - address)) return -ENOMEM; - set_pgdir(address, *dir); + if (pgd_val(olddir) != pgd_val(*dir)) + set_pgdir(address, *dir); address = (address + PGDIR_SIZE) & PGDIR_MASK; dir++; } @@ -155,14 +159,13 @@ if (!area) return NULL; addr = (void *) VMALLOC_START; - area->size = size + PAGE_SIZE; - area->next = NULL; for (p = &vmlist; (tmp = *p) ; p = &tmp->next) { if (size + (unsigned long) addr < (unsigned long) tmp->addr) break; addr = (void *) (tmp->size + (unsigned long) tmp->addr); } area->addr = addr; + area->size = size + PAGE_SIZE; area->next = *p; *p = area; return area; @@ -210,16 +213,18 @@ long vread(char *buf, char *addr, unsigned long count) { - struct vm_struct **p, *tmp; + struct vm_struct *tmp; char *vaddr, *buf_start = buf; - int n; + unsigned long n; /* Don't allow overflow */ if ((unsigned long) addr + count < count) count = -(unsigned long) addr; - for (p = &vmlist; (tmp = *p) ; p = &tmp->next) { + for (tmp = vmlist; tmp; tmp = tmp->next) { vaddr = (char *) tmp->addr; + if (addr >= vaddr + tmp->size - PAGE_SIZE) + continue; while (addr < vaddr) { if (count == 0) goto finished; @@ -228,17 +233,15 @@ addr++; count--; } - n = tmp->size - PAGE_SIZE; - if (addr > vaddr) - n -= addr - vaddr; - while (--n >= 0) { + n = vaddr + tmp->size - PAGE_SIZE - addr; + do { if (count == 0) goto finished; put_user(*addr, buf); buf++; addr++; count--; - } + } while (--n > 0); } finished: return buf - buf_start; diff -u --recursive --new-file v2.1.105/linux/net/802/psnap.c linux/net/802/psnap.c --- v2.1.105/linux/net/802/psnap.c Mon Feb 23 18:12:12 1998 +++ linux/net/802/psnap.c Sat Jun 13 10:23:41 1998 @@ -95,7 +95,7 @@ } /* - * Register SNAP clients. We don't yet use this for IP or IPX. + * Register SNAP clients. We don't yet use this for IP. */ struct datalink_proto *register_snap_client(unsigned char *desc, int (*rcvfunc)(struct sk_buff *, struct device *, struct packet_type *)) diff -u --recursive --new-file v2.1.105/linux/net/Config.in linux/net/Config.in --- v2.1.105/linux/net/Config.in Sat May 2 14:19:54 1998 +++ linux/net/Config.in Mon Jun 8 10:02:34 1998 @@ -56,7 +56,7 @@ if [ "$CONFIG_NET_SCHED" = "y" ]; then source net/sched/Config.in fi - bool 'Network code profiler' CONFIG_NET_PROFILE +# bool 'Network code profiler' CONFIG_NET_PROFILE fi fi endmenu diff -u --recursive --new-file v2.1.105/linux/net/core/dev.c linux/net/core/dev.c --- v2.1.105/linux/net/core/dev.c Thu May 7 22:51:55 1998 +++ linux/net/core/dev.c Sat Jun 13 12:10:31 1998 @@ -1097,7 +1097,7 @@ int size; if (stats) - size = sprintf(buffer, "%6s:%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu %8lu %8lu %4lu %4lu %4lu %5lu %4lu %4lu\n", + size = sprintf(buffer, "%6s:%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu %8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n", dev->name, stats->rx_bytes, stats->rx_packets, stats->rx_errors, @@ -1325,7 +1325,7 @@ dev->flags = (flags & (IFF_DEBUG|IFF_NOTRAILERS|IFF_RUNNING|IFF_NOARP| IFF_SLAVE|IFF_MASTER| IFF_MULTICAST|IFF_PORTSEL|IFF_AUTOMEDIA)) | - (dev->flags & (IFF_UP|IFF_VOLATILE|IFF_PROMISC)); + (dev->flags & (IFF_UP|IFF_VOLATILE|IFF_PROMISC|IFF_ALLMULTI)); /* * Load in the correct multicast list now the flags have changed. @@ -1346,13 +1346,11 @@ if (ret == 0) dev_mc_upload(dev); - } + } if (dev->flags&IFF_UP && - ((old_flags^dev->flags)&~(IFF_UP|IFF_RUNNING|IFF_PROMISC|IFF_VOLATILE))) { - printk(KERN_DEBUG "SIFFL %s(%s)\n", dev->name, current->comm); + ((old_flags^dev->flags)&~(IFF_UP|IFF_RUNNING|IFF_PROMISC|IFF_ALLMULTI|IFF_VOLATILE))) notifier_call_chain(&netdev_chain, NETDEV_CHANGE, dev); - } if ((flags^dev->gflags)&IFF_PROMISC) { int inc = (flags&IFF_PROMISC) ? +1 : -1; @@ -1360,6 +1358,16 @@ dev_set_promiscuity(dev, inc); } + /* NOTE: order of synchronization of IFF_PROMISC and IFF_ALLMULTI + is important. Some (broken) drivers set IFF_PROMISC, when + IFF_ALLMULTI is requested not asking us and not reporting. + */ + if ((flags^dev->gflags)&IFF_ALLMULTI) { + int inc = (flags&IFF_ALLMULTI) ? +1 : -1; + dev->gflags ^= IFF_ALLMULTI; + dev_set_allmulti(dev, inc); + } + return ret; } @@ -1378,7 +1386,8 @@ switch(cmd) { case SIOCGIFFLAGS: /* Get interface flags */ - ifr->ifr_flags = (dev->flags&~IFF_PROMISC)|(dev->gflags&IFF_PROMISC); + ifr->ifr_flags = (dev->flags&~(IFF_PROMISC|IFF_ALLMULTI)) + |(dev->gflags&(IFF_PROMISC|IFF_ALLMULTI)); return 0; case SIOCSIFFLAGS: /* Set interface flags */ diff -u --recursive --new-file v2.1.105/linux/net/core/profile.c linux/net/core/profile.c --- v2.1.105/linux/net/core/profile.c Thu Feb 12 20:56:14 1998 +++ linux/net/core/profile.c Sat Jun 13 10:23:41 1998 @@ -277,7 +277,7 @@ printk("Evaluating net profiler cost ..."); #if CPU == 586 || CPU == 686 if (!(boot_cpu_data.x86_capability & 16)) { - panic("Sorry, you CPU does not support tsc. I am dying...\n"); + printk(KERN_ERR "Sorry, your CPU does not support TSC. Net profiler disabled.\n"); return -1; } #endif diff -u --recursive --new-file v2.1.105/linux/net/core/sock.c linux/net/core/sock.c --- v2.1.105/linux/net/core/sock.c Thu May 7 22:51:55 1998 +++ linux/net/core/sock.c Sat Jun 13 11:45:10 1998 @@ -206,18 +206,14 @@ sk->broadcast=valbool; break; case SO_SNDBUF: - /* - * The spec isnt clear if ENOBUFS or EINVAL - * is best - */ - - /* printk(KERN_DEBUG "setting SO_SNDBUF %d\n", val); */ + /* Don't error on this BSD doesn't and if you think + about it this is right. Otherwise apps have to + play 'guess the biggest size' games. RCVBUF/SNDBUF + are treated in BSD as hints */ + if (val > sysctl_wmem_max) - return -EINVAL; + return 0; - /* FIXME: the tcp code should be made to work even - * with small sndbuf values. - */ sk->sndbuf = max(val*2,2048); /* @@ -228,10 +224,13 @@ break; case SO_RCVBUF: - /* printk(KERN_DEBUG "setting SO_RCVBUF %d\n", val); */ - + /* Don't error on this BSD doesn't and if you think + about it this is right. Otherwise apps have to + play 'guess the biggest size' games. RCVBUF/SNDBUF + are treated in BSD as hints */ + if (val > sysctl_rmem_max) - return -EINVAL; + return 0; /* FIXME: is this lower bound the right one? */ sk->rcvbuf = max(val*2,256); @@ -480,8 +479,8 @@ { struct sock *sk = kmem_cache_alloc(sk_cachep, priority); - if(sk && zero_it) { - memset(sk, 0, sizeof(struct sock)); + if(sk) { + if (zero_it) memset(sk, 0, sizeof(struct sock)); sk->family = family; } @@ -564,15 +563,18 @@ void *sock_kmalloc(struct sock *sk, int size, int priority) { - void *mem = NULL; if (atomic_read(&sk->omem_alloc)+size < sysctl_optmem_max) { + void *mem; /* First do the add, to avoid the race if kmalloc * might sleep. */ atomic_add(size, &sk->omem_alloc); mem = kmalloc(size, priority); + if (mem) + return mem; + atomic_sub(size, &sk->omem_alloc); } - return mem; + return NULL; } void sock_kfree_s(struct sock *sk, void *mem, int size) @@ -880,7 +882,7 @@ unsigned int sock_no_poll(struct file * file, struct socket *sock, poll_table *pt) { - return -EOPNOTSUPP; + return 0; } int sock_no_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) diff -u --recursive --new-file v2.1.105/linux/net/ipv4/fib_frontend.c linux/net/ipv4/fib_frontend.c --- v2.1.105/linux/net/ipv4/fib_frontend.c Thu May 14 19:47:44 1998 +++ linux/net/ipv4/fib_frontend.c Thu Jun 11 22:52:34 1998 @@ -5,7 +5,7 @@ * * IPv4 Forwarding Information Base: FIB frontend. * - * Version: $Id: fib_frontend.c,v 1.10 1998/05/08 21:06:27 davem Exp $ + * Version: $Id: fib_frontend.c,v 1.11 1998/06/11 03:15:40 davem Exp $ * * Authors: Alexey Kuznetsov, * @@ -271,6 +271,8 @@ if (tb) err = tb->tb_insert(tb, &req.rtm, &rta, &req.nlh, NULL); } + if (rta.rta_mx) + kfree(rta.rta_mx); } rtnl_unlock(); return err; diff -u --recursive --new-file v2.1.105/linux/net/ipv4/fib_semantics.c linux/net/ipv4/fib_semantics.c --- v2.1.105/linux/net/ipv4/fib_semantics.c Sat May 2 14:19:55 1998 +++ linux/net/ipv4/fib_semantics.c Thu Jun 11 22:52:34 1998 @@ -5,7 +5,7 @@ * * IPv4 Forwarding Information Base: semantics. * - * Version: $Id: fib_semantics.c,v 1.8 1998/04/28 06:21:58 davem Exp $ + * Version: $Id: fib_semantics.c,v 1.9 1998/06/11 03:15:41 davem Exp $ * * Authors: Alexey Kuznetsov, * @@ -866,8 +866,36 @@ *rta->rta_mtu = r->rt_mtu; } #else - if (r->rt_flags&(RTF_MTU|RTF_WINDOW|RTF_IRTT)) - printk(KERN_DEBUG "SIOCRT*: mtu/window/irtt are not implemnted.\n"); + if (r->rt_flags&(RTF_MTU|RTF_WINDOW|RTF_IRTT)) { + struct rtattr *rec; + struct rtattr *mx = kmalloc(RTA_LENGTH(3*RTA_LENGTH(4)), GFP_KERNEL); + if (mx == NULL) + return -ENOMEM; + rta->rta_mx = mx; + mx->rta_type = RTA_METRICS; + mx->rta_len = RTA_LENGTH(0); + if (r->rt_flags&RTF_MTU) { + rec = (void*)((char*)mx + RTA_ALIGN(mx->rta_len)); + rec->rta_type = RTAX_MTU; + rec->rta_len = RTA_LENGTH(4); + mx->rta_len += RTA_LENGTH(4); + *(u32*)RTA_DATA(rec) = r->rt_mtu; + } + if (r->rt_flags&RTF_WINDOW) { + rec = (void*)((char*)mx + RTA_ALIGN(mx->rta_len)); + rec->rta_type = RTAX_WINDOW; + rec->rta_len = RTA_LENGTH(4); + mx->rta_len += RTA_LENGTH(4); + *(u32*)RTA_DATA(rec) = r->rt_window; + } + if (r->rt_flags&RTF_IRTT) { + rec = (void*)((char*)mx + RTA_ALIGN(mx->rta_len)); + rec->rta_type = RTAX_RTT; + rec->rta_len = RTA_LENGTH(4); + mx->rta_len += RTA_LENGTH(4); + *(u32*)RTA_DATA(rec) = r->rt_irtt; + } + } #endif return 0; } diff -u --recursive --new-file v2.1.105/linux/net/ipv4/icmp.c linux/net/ipv4/icmp.c --- v2.1.105/linux/net/ipv4/icmp.c Sat May 2 14:19:55 1998 +++ linux/net/ipv4/icmp.c Thu Jun 11 22:52:35 1998 @@ -3,7 +3,7 @@ * * Alan Cox, * - * Version: $Id: icmp.c,v 1.41 1998/04/29 22:12:10 alan Exp $ + * Version: $Id: icmp.c,v 1.43 1998/06/11 03:15:43 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -539,7 +539,7 @@ */ saddr = iph->daddr; - if (!(rt->rt_flags&RTCF_LOCAL)) + if (!(rt->rt_flags & RTCF_LOCAL)) saddr = 0; tos = icmp_pointers[type].error ? diff -u --recursive --new-file v2.1.105/linux/net/ipv4/ip_fragment.c linux/net/ipv4/ip_fragment.c --- v2.1.105/linux/net/ipv4/ip_fragment.c Thu Apr 23 20:21:39 1998 +++ linux/net/ipv4/ip_fragment.c Thu Jun 11 22:52:35 1998 @@ -5,7 +5,7 @@ * * The IP fragmentation functionality. * - * Version: $Id: ip_fragment.c,v 1.36 1998/04/18 02:13:07 davem Exp $ + * Version: $Id: ip_fragment.c,v 1.37 1998/06/10 00:22:00 davem Exp $ * * Authors: Fred N. van Kempen * Alan Cox @@ -16,6 +16,7 @@ * Andi Kleen : Add sysctls. * xxxx : Overlapfrag bug. * Ultima : ip_expire() kernel panic. + * Bill Hawes : Frag accounting and evictor fixes. */ #include @@ -76,8 +77,6 @@ atomic_t ip_frag_mem = ATOMIC_INIT(0); /* Memory used for fragments */ -char *in_ntoa(__u32 in); - /* Memory Tracking Functions. */ extern __inline__ void frag_kfree_skb(struct sk_buff *skb) { @@ -88,12 +87,12 @@ extern __inline__ void frag_kfree_s(void *ptr, int len) { atomic_sub(len, &ip_frag_mem); - kfree_s(ptr,len); + kfree(ptr); } extern __inline__ void *frag_kmalloc(int size, int pri) { - void *vp=kmalloc(size,pri); + void *vp = kmalloc(size, pri); if(!vp) return NULL; @@ -108,10 +107,8 @@ struct ipfrag *fp; fp = (struct ipfrag *) frag_kmalloc(sizeof(struct ipfrag), GFP_ATOMIC); - if (fp == NULL) { - NETDEBUG(printk(KERN_ERR "IP: frag_create: no memory left !\n")); - return(NULL); - } + if (fp == NULL) + goto out_nomem; /* Fill in the structure. */ fp->offset = offset; @@ -125,6 +122,10 @@ atomic_add(skb->truesize, &ip_frag_mem); return(fp); + +out_nomem: + NETDEBUG(printk(KERN_ERR "IP: frag_create: no memory left !\n")); + return(NULL); } /* Find the correct entry in the "incomplete datagrams" queue for @@ -139,7 +140,7 @@ unsigned int hash = ipqhashfn(id, saddr, daddr, protocol); struct ipq *qp; - start_bh_atomic(); + /* Always, we are in a BH context, so no locking. -DaveM */ for(qp = ipq_hash[hash]; qp; qp = qp->next) { if(qp->iph->id == id && qp->iph->saddr == saddr && @@ -149,13 +150,15 @@ break; } } - end_bh_atomic(); return qp; } /* Remove an entry from the "incomplete datagrams" queue, either * because we completed, reassembled and processed it, or because * it timed out. + * + * This is called _only_ from BH contexts, on packet reception + * processing and from frag queue expiration timers. -DaveM */ static void ip_free(struct ipq *qp) { @@ -165,11 +168,9 @@ del_timer(&qp->timer); /* Remove this entry from the "incomplete datagrams" queue. */ - start_bh_atomic(); if(qp->next) qp->next->pprev = qp->pprev; *qp->pprev = qp->next; - end_bh_atomic(); /* Release all fragment data. */ fp = qp->fragments; @@ -188,7 +189,9 @@ frag_kfree_s(qp, sizeof(struct ipq)); } -/* Oops, a fragment queue timed out. Kill it and send an ICMP reply. */ +/* + * Oops, a fragment queue timed out. Kill it and send an ICMP reply. + */ static void ip_expire(unsigned long arg) { struct ipq *qp = (struct ipq *) arg; @@ -198,15 +201,15 @@ #ifdef IP_EXPIRE_DEBUG printk("warning: possible ip-expire attack\n"); #endif - ip_free(qp); - return; + goto out; } /* Send an ICMP "Fragment Reassembly Timeout" message. */ ip_statistics.IpReasmTimeout++; ip_statistics.IpReasmFails++; - icmp_send(qp->fragments->skb,ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0); + icmp_send(qp->fragments->skb, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0); +out: /* Nuke the fragment queue. */ ip_free(qp); } @@ -216,17 +219,30 @@ */ static void ip_evictor(void) { - while(atomic_read(&ip_frag_mem)>sysctl_ipfrag_low_thresh) { - int i; + int i, progress; - /* FIXME: Make LRU queue of frag heads. -DaveM */ - for(i = 0; i < IPQ_HASHSZ; i++) - if(ipq_hash[i]) - break; - if(i >= IPQ_HASHSZ) - panic("ip_evictor: memcount"); - ip_free(ipq_hash[i]); +restart: + progress = 0; + /* FIXME: Make LRU queue of frag heads. -DaveM */ + for (i = 0; i < IPQ_HASHSZ; i++) { + struct ipq *qp; + if (atomic_read(&ip_frag_mem) <= sysctl_ipfrag_low_thresh) + return; + /* We are in a BH context, so these queue + * accesses are safe. -DaveM + */ + qp = ipq_hash[i]; + if (qp) { + /* find the oldest queue for this hash bucket */ + while (qp->next) + qp = qp->next; + ip_free(qp); + progress = 1; + } } + if (progress) + goto restart; + panic("ip_evictor: memcount"); } /* Add an entry to the 'ipq' queue for a newly received IP datagram. @@ -241,20 +257,15 @@ int ihlen; qp = (struct ipq *) frag_kmalloc(sizeof(struct ipq), GFP_ATOMIC); - if (qp == NULL) { - NETDEBUG(printk(KERN_ERR "IP: create: no memory left !\n")); - return(NULL); - } + if (qp == NULL) + goto out_nomem; /* Allocate memory for the IP header (plus 8 octets for ICMP). */ ihlen = iph->ihl * 4; qp->iph = (struct iphdr *) frag_kmalloc(64 + 8, GFP_ATOMIC); - if (qp->iph == NULL) { - NETDEBUG(printk(KERN_ERR "IP: create: no memory left !\n")); - frag_kfree_s(qp, sizeof(struct ipq)); - return NULL; - } + if (qp->iph == NULL) + goto out_free; memcpy(qp->iph, iph, ihlen + 8); qp->len = 0; @@ -262,24 +273,28 @@ qp->fragments = NULL; qp->dev = skb->dev; - /* Start a timer for this entry. */ + /* Initialize a timer for this entry. */ init_timer(&qp->timer); - qp->timer.expires = jiffies + sysctl_ipfrag_time; /* about 30 seconds */ - qp->timer.data = (unsigned long) qp; /* pointer to queue */ - qp->timer.function = ip_expire; /* expire function */ - add_timer(&qp->timer); + qp->timer.expires = 0; /* (to be set later) */ + qp->timer.data = (unsigned long) qp; /* pointer to queue */ + qp->timer.function = ip_expire; /* expire function */ /* Add this entry to the queue. */ hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol); - start_bh_atomic(); + /* We are in a BH context, no locking necessary. -DaveM */ if((qp->next = ipq_hash[hash]) != NULL) qp->next->pprev = &qp->next; ipq_hash[hash] = qp; qp->pprev = &ipq_hash[hash]; - end_bh_atomic(); return qp; + +out_free: + frag_kfree_s(qp, sizeof(struct ipq)); +out_nomem: + NETDEBUG(printk(KERN_ERR "IP: create: no memory left !\n")); + return(NULL); } /* See if a fragment queue is complete. */ @@ -323,24 +338,16 @@ /* Allocate a new buffer for the datagram. */ len = qp->ihlen + qp->len; - if(len>65535) { - if (net_ratelimit()) - printk(KERN_INFO "Oversized IP packet from %d.%d.%d.%d.\n", NIPQUAD(qp->iph->saddr)); - ip_statistics.IpReasmFails++; - ip_free(qp); - return NULL; - } + if(len > 65535) + goto out_oversize; - if ((skb = dev_alloc_skb(len)) == NULL) { - ip_statistics.IpReasmFails++; - NETDEBUG(printk(KERN_ERR "IP: queue_glue: no memory for gluing queue %p\n", qp)); - ip_free(qp); - return NULL; - } + skb = dev_alloc_skb(len); + if (!skb) + goto out_nomem; /* Fill in the basic details. */ skb->mac.raw = ptr = skb->data; - skb->nh.iph = iph = (struct iphdr*)skb_put(skb,len); + skb->nh.iph = iph = (struct iphdr *) skb_put(skb, len); /* Copy the original IP headers into the new buffer. */ memcpy(ptr, qp->iph, qp->ihlen); @@ -350,14 +357,8 @@ fp = qp->fragments; count = qp->ihlen; while(fp) { - if (fp->len < 0 || count+fp->len > skb->len) { - NETDEBUG(printk(KERN_ERR "Invalid fragment list: " - "Fragment over size.\n")); - ip_free(qp); - kfree_skb(skb); - ip_statistics.IpReasmFails++; - return NULL; - } + if ((fp->len < 0) || ((count + fp->len) > skb->len)) + goto out_invalid; memcpy((ptr + fp->offset), fp->ptr, fp->len); if (count == qp->ihlen) { skb->dst = dst_clone(fp->skb->dst); @@ -369,26 +370,40 @@ skb->pkt_type = qp->fragments->skb->pkt_type; skb->protocol = qp->fragments->skb->protocol; - /* We glued together all fragments, so remove the queue entry. */ - ip_free(qp); /* Done with all fragments. Fixup the new IP header. */ iph = skb->nh.iph; iph->frag_off = 0; iph->tot_len = htons(count); - ip_statistics.IpReasmOKs++; return skb; + +out_invalid: + NETDEBUG(printk(KERN_ERR + "Invalid fragment list: Fragment over size.\n")); + kfree_skb(skb); + goto out_fail; +out_nomem: + NETDEBUG(printk(KERN_ERR + "IP: queue_glue: no memory for gluing queue %p\n", + qp)); + goto out_fail; +out_oversize: + if (net_ratelimit()) + printk(KERN_INFO + "Oversized IP packet from %d.%d.%d.%d.\n", + NIPQUAD(qp->iph->saddr)); +out_fail: + ip_statistics.IpReasmFails++; + return NULL; } /* Process an incoming IP datagram fragment. */ struct sk_buff *ip_defrag(struct sk_buff *skb) { struct iphdr *iph = skb->nh.iph; - struct ipfrag *prev, *next, *tmp; - struct ipfrag *tfp; + struct ipfrag *prev, *next, *tmp, *tfp; struct ipq *qp; - struct sk_buff *skb2; unsigned char *ptr; int flags, offset; int i, ihl, end; @@ -396,65 +411,58 @@ ip_statistics.IpReasmReqds++; /* Start by cleaning up the memory. */ - if(atomic_read(&ip_frag_mem)>sysctl_ipfrag_high_thresh) + if (atomic_read(&ip_frag_mem) > sysctl_ipfrag_high_thresh) ip_evictor(); - /* Find the entry of this IP datagram in the "incomplete datagrams" queue. */ + /* + * Look for the entry for this IP datagram in the + * "incomplete datagrams" queue. If found, the + * timer is removed. + */ qp = ip_find(iph, skb->dst); /* Is this a non-fragmented datagram? */ offset = ntohs(iph->frag_off); flags = offset & ~IP_OFFSET; offset &= IP_OFFSET; - if (((flags & IP_MF) == 0) && (offset == 0)) { - if (qp != NULL) { - /* Fragmented frame replaced by full unfragmented copy. */ - ip_free(qp); - } - return skb; - } offset <<= 3; /* offset is in 8-byte chunks */ ihl = iph->ihl * 4; - /* If the queue already existed, keep restarting its timer as long - * as we still are receiving fragments. Otherwise, create a fresh - * queue entry. + /* + * Check whether to create a fresh queue entry. If the + * queue already exists, its timer will be restarted as + * long as we continue to receive fragments. */ if (qp) { /* ANK. If the first fragment is received, * we should remember the correct IP header (with options) */ if (offset == 0) { + /* Fragmented frame replaced by unfragmented copy? */ + if ((flags & IP_MF) == 0) + goto out_freequeue; qp->ihlen = ihl; - memcpy(qp->iph, iph, ihl+8); + memcpy(qp->iph, iph, (ihl + 8)); } - /* about 30 seconds */ - mod_timer(&qp->timer, jiffies + sysctl_ipfrag_time); } else { + /* Fragmented frame replaced by unfragmented copy? */ + if ((offset == 0) && ((flags & IP_MF) == 0)) + goto out_skb; + /* If we failed to create it, then discard the frame. */ - if ((qp = ip_create(skb, iph)) == NULL) { - kfree_skb(skb); - ip_statistics.IpReasmFails++; - return NULL; - } + qp = ip_create(skb, iph); + if (!qp) + goto out_freeskb; } /* Attempt to construct an oversize packet. */ - if(ntohs(iph->tot_len)+(int)offset>65535) { - if (net_ratelimit()) - printk(KERN_INFO "Oversized packet received from %d.%d.%d.%d\n", NIPQUAD(iph->saddr)); - frag_kfree_skb(skb); - ip_statistics.IpReasmFails++; - return NULL; - } + if((ntohs(iph->tot_len) + ((int) offset)) > 65535) + goto out_oversize; /* Determine the position of this fragment. */ end = offset + ntohs(iph->tot_len) - ihl; - /* Point into the IP datagram 'data' part. */ - ptr = skb->data + ihl; - /* Is this the final fragment? */ if ((flags & IP_MF) == 0) qp->len = end; @@ -470,11 +478,14 @@ prev = next; } + /* Point into the IP datagram 'data' part. */ + ptr = skb->data + ihl; + /* We found where to put this one. Check for overlap with * preceding fragment, and, if needed, align things so that * any overlaps are eliminated. */ - if (prev != NULL && offset < prev->end) { + if ((prev != NULL) && (offset < prev->end)) { i = prev->end - offset; offset += i; /* ptr into datagram */ ptr += i; /* ptr into fragment data */ @@ -483,14 +494,14 @@ /* Look for overlap with succeeding segments. * If we can merge fragments, do it. */ - for(tmp=next; tmp != NULL; tmp = tfp) { + for (tmp = next; tmp != NULL; tmp = tfp) { tfp = tmp->next; if (tmp->offset >= end) - break; /* no overlaps at all */ + break; /* no overlaps at all */ - i = end - next->offset; /* overlap is 'i' bytes */ - tmp->len -= i; /* so reduce size of */ - tmp->offset += i; /* next fragment */ + i = end - next->offset; /* overlap is 'i' bytes */ + tmp->len -= i; /* so reduce size of */ + tmp->offset += i; /* next fragment */ tmp->ptr += i; /* If we get a frag size of <= 0, remove it and the packet @@ -513,15 +524,15 @@ } } - /* Insert this fragment in the chain of fragments. */ - tfp = NULL; + /* + * Create a fragment to hold this skb. + * No memory to save the fragment? throw the lot ... + */ tfp = ip_frag_create(offset, end, skb, ptr); + if (!tfp) + goto out_freeskb; - /* No memory to save the fragment - so throw the lot. */ - if (!tfp) { - frag_kfree_skb(skb); - return NULL; - } + /* Insert this fragment in the chain of fragments. */ tfp->prev = prev; tfp->next = next; if (prev != NULL) @@ -538,8 +549,34 @@ */ if (ip_done(qp)) { /* Glue together the fragments. */ - skb2 = ip_glue(qp); - return(skb2); + skb = ip_glue(qp); + /* Free the queue entry. */ +out_freequeue: + ip_free(qp); +out_skb: + return skb; } + + /* + * The queue is still active ... reset its timer. + */ +out_timer: + mod_timer(&qp->timer, jiffies + sysctl_ipfrag_time); /* ~ 30 seconds */ +out: return NULL; + + /* + * Error exits ... we need to reset the timer if there's a queue. + */ +out_oversize: + if (net_ratelimit()) + printk(KERN_INFO "Oversized packet received from %d.%d.%d.%d\n", + NIPQUAD(iph->saddr)); + /* the skb isn't in a fragment, so fall through to free it */ +out_freeskb: + kfree_skb(skb); + ip_statistics.IpReasmFails++; + if (qp) + goto out_timer; + goto out; } diff -u --recursive --new-file v2.1.105/linux/net/ipv4/ip_fw.c linux/net/ipv4/ip_fw.c --- v2.1.105/linux/net/ipv4/ip_fw.c Thu May 14 19:47:44 1998 +++ linux/net/ipv4/ip_fw.c Thu Jun 11 22:52:35 1998 @@ -1,6 +1,6 @@ /* - * This code is heavily based on the code in ip_fw.c; see that file for - * copyrights and attributions. This code is basically GPL. + * This code is heavily based on the code on the old ip_fw.c code; see below for + * copyrights and attributions of the old code. This code is basically GPL. * * 15-Aug-1997: Major changes to allow graphs for firewall rules. * Paul Russell and @@ -26,10 +26,32 @@ * Added packet and byte counters for policy matches. * 26-Feb-1998: Fixed race conditions, added SMP support. * 18-Mar-1998: Fix SMP, fix race condition fix. - * 1-May-1998: Remove caching of device pointer, added caching - * for proc output (no longer order n^2). + * 1-May-1998: Remove caching of device pointer. + * 12-May-1998: Allow tiny fragment case for TCP/UDP. + * 15-May-1998: Treat short packets as fragments, don't just block. */ +/* + * + * The origina Linux port was done Alan Cox, with changes/fixes from + * Pauline Middlelink, Jos Vos, Thomas Quinot, Wouter Gadeyne, Juan + * Jose Ciarlante, Bernd Eckenfels, Keith Owens and others. + * + * Copyright from the original FreeBSD version follows: + * + * Copyright (c) 1993 Daniel Boulet + * Copyright (c) 1994 Ugen J.S.Antsilevich + * + * Redistribution and use in source forms, with and without modification, + * are permitted provided that this entire comment appears intact. + * + * Redistribution in binary form may occur without any restrictions. + * Obviously, it would be nice if you gave credit where credit is due + * but requiring it would be too onerous. + * + * This software is provided ``AS IS'' without any warranties of any kind. */ + + #include #include @@ -76,6 +98,12 @@ * * For SMP (kernel v2.1+), multiply this by # CPUs. * + * [Note that this in not correct for 2.2 - because the socket code always + * uses lock_kernel() to serialize, and bottom halves (timers and net_bhs) + * only run on one CPU at a time. This will probably change for 2.3. + * It is still good to use spinlocks because that avoids the global cli() + * for updating the tables, which is rather costly in SMP kernels -AK] + * * This means counters and backchains can get corrupted if no precautions * are taken. * @@ -573,14 +601,10 @@ return FW_BLOCK; } - /* Check for too-small packets (not non-first fragments). - * For each protocol, we assume that we can get the required - * information, eg. port number or ICMP type. If this fails, - * reject it. - * - * Sizes might as well be rounded up to 8 here, since either - * there are more fragments to come (which must be on 8-byte - * boundaries), or this is a bogus packet anyway. + /* If we can't investigate ports, treat as fragment. It's + * either a trucated whole packet, or a truncated first + * fragment, or a TCP first fragment of length 8-15, in which + * case the above rule stops reassembly. */ if (offset == 0) { unsigned int size_req; @@ -598,13 +622,7 @@ default: size_req = 0; } - if (ntohs(ip->tot_len) < (ip->ihl<<2)+size_req) { - if (!testing && net_ratelimit()) { - printk("Packet too short.\n"); - dump_packet(ip,rif,NULL,NULL,0,0); - } - return FW_BLOCK; - } + offset = (ntohs(ip->tot_len) < (ip->ihl<<2)+size_req); } src = ip->saddr; @@ -613,10 +631,10 @@ /* * If we got interface from which packet came - * we can use the address directly. This is unlike - * 4.4BSD derived systems that have an address chain - * per device. We have a device per address with dummy - * devices instead. + * we can use the address directly. Linux 2.1 now uses address + * chains per device too, but unlike BSD we first check if the + * incoming packet matches a device address and the routing + * table before calling the firewall. */ dprintf("Packet "); @@ -1117,7 +1135,7 @@ return NULL; } -#if DEBUG_IP_FIREWALL_USER +#ifdef DEBUG_IP_FIREWALL_USER /* These are sanity checks that don't really matter. * We can get rid of these once testing is complete. */ diff -u --recursive --new-file v2.1.105/linux/net/ipv4/ip_input.c linux/net/ipv4/ip_input.c --- v2.1.105/linux/net/ipv4/ip_input.c Thu May 14 19:47:44 1998 +++ linux/net/ipv4/ip_input.c Thu Jun 11 22:52:35 1998 @@ -5,7 +5,7 @@ * * The Internet Protocol (IP) module. * - * Version: $Id: ip_input.c,v 1.30 1998/05/08 01:54:54 davem Exp $ + * Version: $Id: ip_input.c,v 1.31 1998/05/17 02:19:15 freitag Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -97,7 +97,6 @@ * Alan Cox : Multicast routing hooks * Jos Vos : Do accounting *before* call_in_firewall * Willy Konynenberg : Transparent proxying support - * Mike McLagan : Routing by source * * * @@ -470,6 +469,15 @@ /* * See if the firewall wants to dispose of the packet. + * + * Note: the current standard firewall code expects that the + * destination address was already checked against the interface + * address lists. + * + * If this code is ever moved in front of ip_route_input() you need + * to fix the fw code [moving it might be a good idea anyways, + * so that we can firewall against potentially bugs in the options + * or routing code] */ #ifdef CONFIG_FIREWALL diff -u --recursive --new-file v2.1.105/linux/net/ipv4/ip_output.c linux/net/ipv4/ip_output.c --- v2.1.105/linux/net/ipv4/ip_output.c Thu May 14 19:47:44 1998 +++ linux/net/ipv4/ip_output.c Thu Jun 11 22:52:35 1998 @@ -5,7 +5,7 @@ * * The Internet Protocol (IP) output module. * - * Version: $Id: ip_output.c,v 1.57 1998/05/08 01:54:56 davem Exp $ + * Version: $Id: ip_output.c,v 1.58 1998/05/15 15:21:36 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -99,6 +99,7 @@ { struct rtable *rt = (struct rtable *)skb->dst; struct iphdr *iph; + struct device *dev; /* Build the IP header. */ if (opt) @@ -126,10 +127,19 @@ ip_options_build(skb, opt, daddr, rt, 0); } + dev = rt->u.dst.dev; + + if (call_out_firewall(PF_INET, dev, iph, NULL, &skb) < FW_ACCEPT) + goto drop; + ip_send_check(iph); /* Send it out. */ skb->dst->output(skb); + return; + +drop: + kfree_skb(skb); } int __ip_finish_output(struct sk_buff *skb) diff -u --recursive --new-file v2.1.105/linux/net/ipv4/ipconfig.c linux/net/ipv4/ipconfig.c --- v2.1.105/linux/net/ipv4/ipconfig.c Fri May 8 23:14:57 1998 +++ linux/net/ipv4/ipconfig.c Sat Jun 13 11:46:12 1998 @@ -1,5 +1,5 @@ /* - * $Id: ipconfig.c,v 1.12 1998/05/03 14:30:53 alan Exp $ + * $Id: ipconfig.c,v 1.13 1998/06/09 03:40:47 zaitcev Exp $ * * Automatic Configuration of IP -- use BOOTP or RARP or user-supplied * information to configure own IP address and routes. @@ -248,6 +248,11 @@ __initfunc(int ic_defaults(void)) { + /* + * At this point we have no userspace running so need not + * claim locks on system_utsname + */ + if (!ic_host_name_set) strcpy(system_utsname.nodename, in_ntoa(ic_myaddr)); @@ -1072,8 +1077,8 @@ } /* - * Decode any IP configuration options in the "ipconfig" kernel command - * line parameter. It consists of option fields separated by colons in + * Decode any IP configuration options in the "ip=" or "nfsaddrs=" kernel + * command line parameter. It consists of option fields separated by colons in * the following order: * * :::::: diff -u --recursive --new-file v2.1.105/linux/net/ipv4/route.c linux/net/ipv4/route.c --- v2.1.105/linux/net/ipv4/route.c Thu May 14 19:47:44 1998 +++ linux/net/ipv4/route.c Thu Jun 11 22:52:35 1998 @@ -5,7 +5,7 @@ * * ROUTE - implementation of the IP router. * - * Version: $Id: route.c,v 1.50 1998/05/13 06:23:25 davem Exp $ + * Version: $Id: route.c,v 1.52 1998/06/11 03:15:47 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -1095,11 +1095,12 @@ rth->rt_gateway = daddr; rth->rt_spec_dst= spec_dst; rth->u.dst.input= ip_local_deliver; + rth->rt_flags = flags|RTCF_LOCAL; if (res.type == RTN_UNREACHABLE) { rth->u.dst.input= ip_error; - rth->u.dst.error= err; + rth->u.dst.error= -err; + rth->rt_flags &= ~RTCF_LOCAL; } - rth->rt_flags = flags|RTCF_LOCAL; rth->rt_type = res.type; skb->dst = (struct dst_entry*)rt_intern_hash(hash, rth); return 0; diff -u --recursive --new-file v2.1.105/linux/net/ipv4/syncookies.c linux/net/ipv4/syncookies.c --- v2.1.105/linux/net/ipv4/syncookies.c Sun Jun 7 11:16:40 1998 +++ linux/net/ipv4/syncookies.c Thu Jun 11 22:52:35 1998 @@ -9,7 +9,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * - * $Id: syncookies.c,v 1.5 1998/04/03 09:49:46 freitag Exp $ + * $Id: syncookies.c,v 1.6 1998/06/10 07:29:22 davem Exp $ * * Missing: IPv6 support. */ diff -u --recursive --new-file v2.1.105/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c --- v2.1.105/linux/net/ipv4/tcp.c Sat May 2 14:19:55 1998 +++ linux/net/ipv4/tcp.c Thu Jun 11 22:52:35 1998 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp.c,v 1.114 1998/04/26 01:11:33 davem Exp $ + * Version: $Id: tcp.c,v 1.115 1998/05/13 13:44:13 alan Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -1069,6 +1069,13 @@ add_wait_queue(sk->sleep, &wait); lock_sock(sk); + + /* + * BUG BUG BUG + * This violates 1003.1g compliance. We must wait for + * data to exist even if we read none! + */ + while (len > 0) { struct sk_buff * skb; u32 offset; diff -u --recursive --new-file v2.1.105/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c --- v2.1.105/linux/net/ipv4/tcp_input.c Fri May 8 23:14:57 1998 +++ linux/net/ipv4/tcp_input.c Thu Jun 11 22:52:35 1998 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_input.c,v 1.118 1998/05/06 04:53:48 davem Exp $ + * Version: $Id: tcp_input.c,v 1.119 1998/05/23 13:10:24 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -1686,8 +1686,13 @@ } } else if (TCP_SKB_CB(skb)->ack_seq == tp->snd_una) { /* Bulk data transfer: receiver */ - if (atomic_read(&sk->rmem_alloc) > sk->rcvbuf) + if (atomic_read(&sk->rmem_alloc) > sk->rcvbuf) { + /* We must send an ACK for zero window probes. */ + if (!before(TCP_SKB_CB(skb)->seq, + tp->rcv_wup + tp->rcv_wnd)) + tcp_send_ack(sk); goto discard; + } skb_pull(skb,th->doff*4); @@ -1714,15 +1719,21 @@ } if (!tcp_sequence(tp, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq)) { - if (!th->rst) { - if (after(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) { - SOCK_DEBUG(sk, "seq:%d end:%d wup:%d wnd:%d\n", - TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq, - tp->rcv_wup, tp->rcv_wnd); - } - tcp_send_ack(sk); + /* RFC793, page 37: "In all states except SYN-SENT, all reset + * (RST) segments are validated by checking their SEQ-fields." + * And page 69: "If an incoming segment is not acceptable, + * an acknowledgment should be sent in reply (unless the RST bit + * is set, if so drop the segment and return)". + */ + if (th->rst) goto discard; + if (after(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) { + SOCK_DEBUG(sk, "seq:%d end:%d wup:%d wnd:%d\n", + TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq, + tp->rcv_wup, tp->rcv_wnd); } + tcp_send_ack(sk); + goto discard; } if(th->syn && TCP_SKB_CB(skb)->seq != tp->syn_seq) { diff -u --recursive --new-file v2.1.105/linux/net/ipv4/tcp_output.c linux/net/ipv4/tcp_output.c --- v2.1.105/linux/net/ipv4/tcp_output.c Fri May 8 23:14:57 1998 +++ linux/net/ipv4/tcp_output.c Thu Jun 11 22:52:35 1998 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_output.c,v 1.90 1998/05/06 04:59:15 davem Exp $ + * Version: $Id: tcp_output.c,v 1.91 1998/05/23 13:10:21 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -331,16 +331,18 @@ * * Note, we don't "adjust" for TIMESTAMP or SACK option bytes. */ -u32 __tcp_select_window(struct sock *sk) +u32 __tcp_select_window(struct sock *sk, u32 cur_win) { struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; unsigned int mss = sk->mss; - unsigned int free_space; - u32 window, cur_win; + int free_space; + u32 window; + /* Sometimes free_space can be < 0. */ free_space = (sk->rcvbuf - atomic_read(&sk->rmem_alloc)) / 2; if (tp->window_clamp) { - free_space = min(tp->window_clamp, free_space); + if (free_space > ((int) tp->window_clamp)) + free_space = tp->window_clamp; mss = min(tp->window_clamp, mss); } else { printk("tcp_select_window: tp->window_clamp == 0.\n"); @@ -351,8 +353,7 @@ printk("tcp_select_window: sk->mss fell to 0.\n"); } - cur_win = tcp_receive_window(tp); - if (free_space < sk->rcvbuf/4 && free_space < mss/2) { + if ((free_space < (sk->rcvbuf/4)) && (free_space < ((int) (mss/2)))) { window = 0; } else { /* Get the largest window that is a nice multiple of mss. @@ -364,8 +365,9 @@ * is too small. */ window = tp->rcv_wnd; - if ((window <= (free_space - mss)) || (window > free_space)) - window = (free_space/mss)*mss; + if ((((int) window) <= (free_space - ((int) mss))) || + (((int) window) > free_space)) + window = (((unsigned int) free_space)/mss)*mss; } return window; } diff -u --recursive --new-file v2.1.105/linux/net/ipv4/udp.c linux/net/ipv4/udp.c --- v2.1.105/linux/net/ipv4/udp.c Thu May 14 19:47:45 1998 +++ linux/net/ipv4/udp.c Thu Jun 11 22:52:35 1998 @@ -5,7 +5,7 @@ * * The User Datagram Protocol (UDP). * - * Version: $Id: udp.c,v 1.56 1998/05/08 21:06:30 davem Exp $ + * Version: $Id: udp.c,v 1.57 1998/05/14 06:32:44 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -57,6 +57,8 @@ * Andi Kleen : Some cleanups, cache destination entry * for connect. * Vitaly E. Lavrov : Transparent proxy revived after year coma. + * Melvin Smith : Check msg_name not msg_namelen in sendto(), + * return ENOTCONN for unconnected sockets (POSIX) * * * This program is free software; you can redistribute it and/or @@ -657,7 +659,7 @@ * Get and verify the address. */ - if (msg->msg_namelen) { + if (msg->msg_name) { struct sockaddr_in * usin = (struct sockaddr_in*)msg->msg_name; if (msg->msg_namelen < sizeof(*usin)) return(-EINVAL); @@ -684,7 +686,7 @@ */ } else { if (sk->state != TCP_ESTABLISHED) - return -EINVAL; + return -ENOTCONN; ufh.daddr = sk->daddr; ufh.uh.dest = sk->dport; diff -u --recursive --new-file v2.1.105/linux/net/ipv6/af_inet6.c linux/net/ipv6/af_inet6.c --- v2.1.105/linux/net/ipv6/af_inet6.c Sun Jun 7 11:16:40 1998 +++ linux/net/ipv6/af_inet6.c Thu Jun 11 22:52:36 1998 @@ -7,7 +7,7 @@ * * Adapted from linux/net/ipv4/af_inet.c * - * $Id: af_inet6.c,v 1.33 1998/05/08 21:06:32 davem Exp $ + * $Id: af_inet6.c,v 1.36 1998/06/10 07:29:25 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -422,6 +422,11 @@ } #endif +#if defined(MODULE) && defined(CONFIG_SYSCTL) +extern void ipv6_sysctl_register(void); +extern void ipv6_sysctl_unregister(void); +#endif + #ifdef MODULE int init_module(void) #else @@ -515,7 +520,7 @@ void cleanup_module(void) { /* First of all disallow new sockets creation. */ - sock_unregister(AF_INET6); + sock_unregister(PF_INET6); #ifdef CONFIG_PROC_FS proc_net_unregister(proc_net_raw6.low_ino); proc_net_unregister(proc_net_tcp6.low_ino); diff -u --recursive --new-file v2.1.105/linux/net/ipv6/tcp_ipv6.c linux/net/ipv6/tcp_ipv6.c --- v2.1.105/linux/net/ipv6/tcp_ipv6.c Fri May 8 23:14:57 1998 +++ linux/net/ipv6/tcp_ipv6.c Thu Jun 11 22:52:36 1998 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: tcp_ipv6.c,v 1.81 1998/05/03 14:31:10 alan Exp $ + * $Id: tcp_ipv6.c,v 1.82 1998/06/11 03:15:52 davem Exp $ * * Based on: * linux/net/ipv4/tcp.c @@ -64,9 +64,7 @@ { int hashent = (lport ^ fport); - hashent ^= (laddr->s6_addr32[0] ^ laddr->s6_addr32[1]); - hashent ^= (faddr->s6_addr32[0] ^ faddr->s6_addr32[1]); - hashent ^= (faddr->s6_addr32[2] ^ faddr->s6_addr32[3]); + hashent ^= (laddr->s6_addr32[3] ^ faddr->s6_addr32[3]); return (hashent & ((TCP_HTABLE_SIZE/2) - 1)); } @@ -145,6 +143,13 @@ static void tcp_v6_hash(struct sock *sk) { + /* Well, I know that it is ugly... + All this ->prot, ->af_specific etc. need LARGE cleanup --ANK + */ + if (sk->tp_pinfo.af_tcp.af_specific == &ipv6_mapped) { + tcp_prot.hash(sk); + return; + } if(sk->state != TCP_CLOSE) { struct sock **skp; @@ -415,8 +420,14 @@ if (err) { sk->tp_pinfo.af_tcp.af_specific = &ipv6_specific; sk->backlog_rcv = tcp_v6_do_rcv; + } else { + /* Yuup... And it is not the only place... --ANK */ + ipv6_addr_set(&np->saddr, 0, 0, __constant_htonl(0x0000FFFF), + sk->saddr); + ipv6_addr_set(&np->rcv_saddr, 0, 0, __constant_htonl(0x0000FFFF), + sk->rcv_saddr); } - + return err; } diff -u --recursive --new-file v2.1.105/linux/net/ipv6/udp.c linux/net/ipv6/udp.c --- v2.1.105/linux/net/ipv6/udp.c Fri May 8 23:14:57 1998 +++ linux/net/ipv6/udp.c Thu Jun 11 22:52:36 1998 @@ -7,7 +7,7 @@ * * Based on linux/ipv4/udp.c * - * $Id: udp.c,v 1.28 1998/05/03 14:31:12 alan Exp $ + * $Id: udp.c,v 1.29 1998/05/15 15:21:39 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -689,7 +689,7 @@ } } else { if (sk->state != TCP_ESTABLISHED) - return(-EINVAL); + return(-ENOTCONN); udh.uh.dest = sk->dport; daddr = &sk->net_pinfo.af_inet6.daddr; diff -u --recursive --new-file v2.1.105/linux/net/sched/cls_rsvp.h linux/net/sched/cls_rsvp.h --- v2.1.105/linux/net/sched/cls_rsvp.h Thu May 14 19:47:45 1998 +++ linux/net/sched/cls_rsvp.h Thu Jun 11 22:52:36 1998 @@ -525,6 +525,7 @@ break; f->next = *fp; *fp = f; + *arg = (unsigned long)f; return 0; } } diff -u --recursive --new-file v2.1.105/linux/net/sched/sch_cbq.c linux/net/sched/sch_cbq.c --- v2.1.105/linux/net/sched/sch_cbq.c Thu May 14 19:47:45 1998 +++ linux/net/sched/sch_cbq.c Thu Jun 11 22:52:36 1998 @@ -1435,7 +1435,7 @@ if (cl->police) { opt.police = cl->police; - RTA_PUT(skb, TCA_CBQ_OVL_STRATEGY, sizeof(opt), &opt); + RTA_PUT(skb, TCA_CBQ_POLICE, sizeof(opt), &opt); } return skb->len; diff -u --recursive --new-file v2.1.105/linux/net/sched/sch_teql.c linux/net/sched/sch_teql.c --- v2.1.105/linux/net/sched/sch_teql.c Thu May 14 19:47:45 1998 +++ linux/net/sched/sch_teql.c Thu Jun 11 22:52:36 1998 @@ -252,7 +252,7 @@ return 0; } neigh_release(n); - return (skb_res != NULL); + return (skb_res == NULL) ? -EAGAIN : 1; } static __inline__ int @@ -280,7 +280,7 @@ restart: nores = 0; - busy = 1; + busy = 0; if ((q = start) == NULL) goto drop; @@ -288,34 +288,39 @@ do { struct device *slave = q->dev; - if (!slave->tbusy && slave->qdisc_sleeping == q) { - busy = 0; - - if (q->h.forw == NULL) { - q->h.forw = qdisc_head.forw; - qdisc_head.forw = &q->h; - } + if (slave->qdisc_sleeping != q) + continue; + if (slave->tbusy) { + busy = 1; + continue; + } - switch (teql_resolve(skb, skb_res, slave)) { - case 0: - if (slave->hard_start_xmit(skb, slave) == 0) { - master->slaves = NEXT_SLAVE(q); - dev->tbusy = 0; - master->stats.tx_packets++; - master->stats.tx_bytes += len; - return 0; - } - break; - case 1: + if (q->h.forw == NULL) { + q->h.forw = qdisc_head.forw; + qdisc_head.forw = &q->h; + } + + switch (teql_resolve(skb, skb_res, slave)) { + case 0: + if (slave->hard_start_xmit(skb, slave) == 0) { master->slaves = NEXT_SLAVE(q); dev->tbusy = 0; - return 0; - default: - nores = 1; - break; + master->stats.tx_packets++; + master->stats.tx_bytes += len; + return 0; } - __skb_pull(skb, skb->nh.raw - skb->data); + if (dev->tbusy) + busy = 1; + break; + case 1: + master->slaves = NEXT_SLAVE(q); + dev->tbusy = 0; + return 0; + default: + nores = 1; + break; } + __skb_pull(skb, skb->nh.raw - skb->data); } while ((q = NEXT_SLAVE(q)) != start); if (nores && skb_res == NULL) { diff -u --recursive --new-file v2.1.105/linux/net/unix/af_unix.c linux/net/unix/af_unix.c --- v2.1.105/linux/net/unix/af_unix.c Fri May 8 23:14:58 1998 +++ linux/net/unix/af_unix.c Tue Jun 9 01:21:50 1998 @@ -86,6 +86,7 @@ #include #include #include +#include #include @@ -100,6 +101,8 @@ #define UNIX_ABSTRACT(sk) ((sk)->protinfo.af_unix.addr->hash!=UNIX_HASH_SIZE) +static void unix_destroy_socket(unix_socket *sk); + extern __inline__ unsigned unix_hash_fold(unsigned hash) { hash ^= hash>>16; @@ -127,7 +130,7 @@ extern __inline__ int unix_unlock(unix_socket *sk) { - return sk->sock_readers--; + return --sk->sock_readers; } extern __inline__ int unix_locked(unix_socket *sk) @@ -254,6 +257,10 @@ if(!unix_locked(sk) && atomic_read(&sk->wmem_alloc) == 0) { sk_free(sk); + unix_remove_socket(sk); + + /* socket destroyed, decrement count */ + MOD_DEC_USE_COUNT; return; } @@ -273,28 +280,56 @@ sk->timer.function=unix_destroy_timer; add_timer(&sk->timer); } + +static int unix_release_sock (unix_socket *sk) +{ + unix_socket *skpair; + + sk->state_change(sk); + sk->dead=1; + sk->socket = NULL; + + skpair=unix_peer(sk); + + /* Try to flush out this socket. Throw out buffers at least */ + unix_destroy_socket(sk); + + if (skpair!=NULL) + { + if (sk->type==SOCK_STREAM && unix_our_peer(sk, skpair)) + { + skpair->state_change(skpair); + skpair->shutdown=SHUTDOWN_MASK; /* No more writes*/ + } + unix_unlock(skpair); /* It may now die */ + } + + /* + * Fixme: BSD difference: In BSD all sockets connected to use get + * ECONNRESET and we die on the spot. In Linux we behave + * like files and pipes do and wait for the last + * dereference. + * + * Can't we simply set sock->err? + */ + + unix_gc(); /* Garbage collect fds */ + return 0; +} static void unix_destroy_socket(unix_socket *sk) { struct sk_buff *skb; - unix_remove_socket(sk); - while((skb=skb_dequeue(&sk->receive_queue))!=NULL) { if(sk->state==TCP_LISTEN) { - unix_socket *osk=skb->sk; - osk->state=TCP_CLOSE; - kfree_skb(skb); /* Now surplus - free the skb first before the socket */ - osk->state_change(osk); /* So the connect wakes and cleans up (if any) */ - /* osk will be destroyed when it gets to close or the timer fires */ - } - else - { - /* passed fds are erased in the kfree_skb hook */ - kfree_skb(skb); + unix_unlock(sk); + unix_release_sock(skb->sk); } + /* passed fds are erased in the kfree_skb hook */ + kfree_skb(skb); } if(sk->protinfo.af_unix.dentry!=NULL) @@ -306,15 +341,18 @@ if(!unix_unlock(sk) && atomic_read(&sk->wmem_alloc) == 0) { sk_free(sk); + unix_remove_socket(sk); + + /* socket destroyed, decrement count */ + MOD_DEC_USE_COUNT; } else { + sk->state=TCP_CLOSE; sk->dead=1; unix_delayed_delete(sk); /* Try every so often until buffers are all freed */ } - /* socket destroyed, decrement count */ - MOD_DEC_USE_COUNT; } static int unix_listen(struct socket *sock, int backlog) @@ -332,23 +370,29 @@ sk->state_change(sk); sk->state=TCP_LISTEN; sock->flags |= SO_ACCEPTCON; + /* set credentials so connect can copy them */ + sk->peercred.pid = current->pid; + sk->peercred.uid = current->euid; + sk->peercred.gid = current->egid; return 0; } extern struct proto_ops unix_stream_ops; extern struct proto_ops unix_dgram_ops; -static int unix_create(struct socket *sock, int protocol) +static int unix_create1(struct socket *sock, struct sock **skp, int protocol) { struct sock *sk; - sock->state = SS_UNCONNECTED; - if (protocol && protocol != PF_UNIX) return -EPROTONOSUPPORT; - switch (sock->type) + if (sock) { + sock->state = SS_UNCONNECTED; + + switch (sock->type) + { case SOCK_STREAM: sock->ops = &unix_stream_ops; break; @@ -363,6 +407,7 @@ break; default: return -ESOCKTNOSUPPORT; + } } sk = sk_alloc(PF_UNIX, GFP_KERNEL, 1); if (!sk) @@ -378,51 +423,32 @@ sk->mtu=4096; sk->protinfo.af_unix.list=&unix_sockets_unbound; unix_insert_socket(sk); - + if (skp) + *skp =sk; + /* socket created, increment count */ MOD_INC_USE_COUNT; return 0; } +static int unix_create(struct socket *sock, int protocol) +{ + return unix_create1(sock, NULL, protocol); +} + static int unix_release(struct socket *sock, struct socket *peer) { unix_socket *sk = sock->sk; - unix_socket *skpair; if (!sk) return 0; + sock->sk = NULL; if (sock->state != SS_UNCONNECTED) sock->state = SS_DISCONNECTING; - sk->state_change(sk); - sk->dead=1; - skpair=unix_peer(sk); - if (sock->type==SOCK_STREAM && skpair) - { - if (unix_our_peer(sk, skpair)) - skpair->shutdown=SHUTDOWN_MASK; /* No more writes */ - if (skpair->state!=TCP_LISTEN) - skpair->state_change(skpair); /* Wake any blocked writes */ - } - if (skpair!=NULL) - unix_unlock(skpair); /* It may now die */ - unix_peer(sk)=NULL; /* No pair */ - unix_destroy_socket(sk); /* Try to flush out this socket. Throw out buffers at least */ - unix_gc(); /* Garbage collect fds */ - - /* - * FIXME: BSD difference: In BSD all sockets connected to use get ECONNRESET and we die on the spot. In - * Linux we behave like files and pipes do and wait for the last dereference. - */ - if (sk->socket) - { - sk->socket = NULL; - sock->sk = NULL; - } - - return 0; + return unix_release_sock (sk); } static int unix_autobind(struct socket *sock) @@ -625,18 +651,17 @@ return 0; } -static int unix_stream_connect1(struct socket *sock, struct msghdr *msg, - int len, struct unix_skb_parms *cmsg, int nonblock) +static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr, + int addr_len, int flags) { - struct sockaddr_un *sunaddr=(struct sockaddr_un *)msg->msg_name; - struct sock *sk = sock->sk; + struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr; + struct sock *sk = sock->sk, *newsk; unix_socket *other; struct sk_buff *skb; int err; unsigned hash; - int addr_len; - addr_len = unix_mkname(sunaddr, msg->msg_namelen, &hash); + addr_len = unix_mkname(sunaddr, addr_len, &hash); if (addr_len < 0) return addr_len; @@ -648,123 +673,80 @@ case SS_CONNECTED: /* Socket is already connected */ return -EISCONN; - case SS_CONNECTING: - /* Not yet connected... we will check this. */ - break; default: return(-EINVAL); } + /* + * Now ready to connect + */ + + sk->state=TCP_CLOSE; + + /* Find listening sock */ + other=unix_find_other(sunaddr, addr_len, sk->type, hash, &err); + if(other==NULL) + goto out; - if (unix_peer(sk)) - { - if (sock->state==SS_CONNECTING && sk->state==TCP_ESTABLISHED) - { - sock->state=SS_CONNECTED; - if (!sk->protinfo.af_unix.addr) - unix_autobind(sock); - return 0; - } - if (sock->state==SS_CONNECTING && sk->state == TCP_CLOSE) - { - sock->state=SS_UNCONNECTED; - return -ECONNREFUSED; - } - if (sock->state!=SS_CONNECTING) - return -EISCONN; - if (nonblock) - return -EALREADY; - /* - * Drop through the connect up logic to the wait. - */ - } + /* create new sock for complete connection */ + err = unix_create1(NULL, &newsk, PF_UNIX); + if (newsk == NULL) + goto out; - if (sock->state==SS_UNCONNECTED) - { + /* Allocate skb for sending to listening sock */ + skb=sock_alloc_send_skb(newsk, 0, 0, flags&O_NONBLOCK, &err); + if(skb==NULL) /* - * Now ready to connect + * if it gives EAGAIN we should give back + * EINPROGRESS. But this should not happen since the + * socket should have some writespace left (it did not + * allocate any memory until now) */ - - skb=sock_alloc_send_skb(sk, len, 0, nonblock, &err); /* Marker object */ - if(skb==NULL) - goto out; - memcpy(&UNIXCB(skb), cmsg, sizeof(*cmsg)); - if (len) { - err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, - len); - if (err) - goto out_free; - } + goto out_release; - sk->state=TCP_CLOSE; - other=unix_find_other(sunaddr, addr_len, sk->type, hash, &err); - if(other==NULL) - goto out_free; - other->ack_backlog++; - unix_peer(sk)=other; - skb_queue_tail(&other->receive_queue,skb); - sk->state=TCP_SYN_SENT; - sock->state=SS_CONNECTING; - other->data_ready(other,0); /* Wake up ! */ - } - - - /* Wait for an accept */ - - while(sk->state==TCP_SYN_SENT) - { - if(nonblock) - return -EINPROGRESS; - interruptible_sleep_on(sk->sleep); - if(signal_pending(current)) - return -ERESTARTSYS; - } - - /* - * Has the other end closed on us ? - */ - - if(sk->state==TCP_CLOSE) - { - unix_unlock(unix_peer(sk)); - unix_peer(sk)=NULL; - sock->state=SS_UNCONNECTED; - return -ECONNREFUSED; - } - - /* - * Amazingly it has worked - */ - + UNIXCB(skb).attr = MSG_SYN; + + /* set up connecting socket */ sock->state=SS_CONNECTED; if (!sk->protinfo.af_unix.addr) unix_autobind(sock); + unix_peer(sk)=newsk; + unix_lock(sk); + sk->state=TCP_ESTABLISHED; + /* Set credentials */ + sk->peercred = other->peercred; + + /* set up newly created sock */ + unix_peer(newsk)=sk; + unix_lock(newsk); + newsk->state=TCP_ESTABLISHED; + newsk->type=SOCK_STREAM; + newsk->peercred.pid = current->pid; + newsk->peercred.uid = current->euid; + newsk->peercred.gid = current->egid; + + /* copy address information from listening to new sock*/ + if (other->protinfo.af_unix.addr) + { + atomic_inc(&other->protinfo.af_unix.addr->refcnt); + newsk->protinfo.af_unix.addr=other->protinfo.af_unix.addr; + } + if (other->protinfo.af_unix.dentry) + newsk->protinfo.af_unix.dentry=dget(other->protinfo.af_unix.dentry); + + /* send info to listening sock */ + other->ack_backlog++; + skb_queue_tail(&other->receive_queue,skb); + other->data_ready(other,0); /* Wake up ! */ + return 0; -out_free: - kfree_skb(skb); +out_release: + unix_destroy_socket(newsk); out: return err; } - -static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr, - int addr_len, int flags) -{ - struct msghdr msg; - struct unix_skb_parms cmsg; - - msg.msg_name = uaddr; - msg.msg_namelen = addr_len; - cmsg.fp = NULL; - cmsg.attr = MSG_SYN; - cmsg.creds.pid = current->pid; - cmsg.creds.uid = current->euid; - cmsg.creds.gid = current->egid; - - return unix_stream_connect1(sock, &msg, 0, &cmsg, flags&O_NONBLOCK); -} - static int unix_socketpair(struct socket *socka, struct socket *sockb) { struct sock *ska=socka->sk, *skb = sockb->sk; @@ -802,14 +784,6 @@ if (sk->state!=TCP_LISTEN) return -EINVAL; - if (sk->protinfo.af_unix.addr) - { - atomic_inc(&sk->protinfo.af_unix.addr->refcnt); - newsk->protinfo.af_unix.addr=sk->protinfo.af_unix.addr; - } - if (sk->protinfo.af_unix.dentry) - newsk->protinfo.af_unix.dentry=dget(sk->protinfo.af_unix.dentry); - for (;;) { skb=skb_dequeue(&sk->receive_queue); @@ -834,20 +808,19 @@ tsk=skb->sk; sk->ack_backlog--; - unix_peer(newsk)=tsk; - unix_peer(tsk)=newsk; - tsk->state=TCP_ESTABLISHED; - newsk->state=TCP_ESTABLISHED; - memcpy(&newsk->peercred, UNIXCREDS(skb), sizeof(struct ucred)); - tsk->peercred.pid = current->pid; - tsk->peercred.uid = current->euid; - tsk->peercred.gid = current->egid; - unix_lock(newsk); /* Swap lock over */ - unix_unlock(sk); /* Locked to child socket not master */ - unix_lock(tsk); /* Back lock */ - kfree_skb(skb); /* The buffer is just used as a tag */ - tsk->state_change(tsk); /* Wake up any sleeping connect */ - sock_wake_async(tsk->socket, 0); + unix_unlock(sk); /* No longer locked to master */ + kfree_skb(skb); + + /* attach accepted sock to socket */ + newsock->state=SS_CONNECTED; + newsock->sk=tsk; + tsk->sleep=newsk->sleep; + tsk->socket=newsock; + + /* destroy handed sock */ + newsk->socket = NULL; + unix_destroy_socket(newsk); + return 0; } @@ -1389,6 +1362,38 @@ return(0); } +static unsigned int unix_poll(struct file * file, struct socket *sock, poll_table *wait) +{ + struct sock *sk = sock->sk; + unsigned int mask; + + poll_wait(file, sk->sleep, wait); + mask = 0; + + /* exceptional events? */ + if (sk->err) + mask |= POLLERR; + if (sk->shutdown & RCV_SHUTDOWN) + mask |= POLLHUP; + + /* readable? */ + if (!skb_queue_empty(&sk->receive_queue)) + mask |= POLLIN | POLLRDNORM; + + /* Connection-based need to check for termination and startup */ + if (sk->type == SOCK_STREAM && sk->state==TCP_CLOSE) + mask |= POLLHUP; + + /* + * we set writable also when the other side has shut down the + * connection. This prevents stuck sockets. + */ + if (sk->sndbuf - atomic_read(&sk->wmem_alloc) >= MIN_WRITE_SPACE) + mask |= POLLOUT | POLLWRNORM | POLLWRBAND; + + return mask; +} + #ifdef CONFIG_PROC_FS static int unix_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data) @@ -1410,7 +1415,9 @@ 0, s->socket ? s->socket->flags : 0, s->type, - s->socket ? s->socket->state : 0, + s->socket ? s->socket->state : + (s->state == TCP_ESTABLISHED ? + SS_CONNECTING : SS_DISCONNECTING), s->socket ? s->socket->inode->i_ino : 0); if (s->protinfo.af_unix.addr) @@ -1426,7 +1433,7 @@ } buffer[len++]='\n'; - pos=begin+len; + pos+=len; if(poslength) len=length; + if (len < 0) + len = 0; return len; } #endif @@ -1455,7 +1464,7 @@ unix_socketpair, unix_accept, unix_getname, - datagram_poll, + unix_poll, unix_ioctl, unix_listen, unix_shutdown, @@ -1537,6 +1546,9 @@ sock_unregister(PF_UNIX); #ifdef CONFIG_SYSCTL unix_sysctl_unregister(); +#endif +#ifdef CONFIG_PROC_FS + remove_proc_entry("net/unix", 0); #endif } #endif diff -u --recursive --new-file v2.1.105/linux/scripts/mkdep.c linux/scripts/mkdep.c --- v2.1.105/linux/scripts/mkdep.c Mon Jan 5 01:41:01 1998 +++ linux/scripts/mkdep.c Sat Jun 13 13:36:13 1998 @@ -118,7 +118,7 @@ /* * Clear the set of configuration strings. */ -void clear_config( ) +void clear_config(void) { len_config = 0; define_config(0, "", 0); @@ -193,7 +193,7 @@ * Thus, there is one memory access per sizeof(unsigned long) characters. */ -#if defined(__alpha__) || defined(__i386__) +#if defined(__alpha__) || defined(__i386__) || defined(__arm__) #define LE_MACHINE #endif