From 34b2a5d20e523de4d0854ac9653914f3d6cfea07 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:10:59 -0500 Subject: [PATCH] Import pre2.0.3 --- CREDITS | 5 +- Documentation/Configure.help | 213 +- Documentation/cdrom/cdrom-standard.tex | 142 +- Documentation/devices.tex | 44 +- Documentation/devices.txt | 41 +- Documentation/java.txt | 32 +- Documentation/svga.txt | 3 +- Documentation/watchdog.txt | 31 +- Makefile | 2 +- arch/alpha/defconfig | 2 +- arch/i386/boot/video.S | 6 +- arch/i386/config.in | 4 +- arch/i386/defconfig | 3 +- arch/i386/kernel/smp.c | 2 + drivers/block/genhd.c | 13 +- drivers/block/linear.c | 3 +- drivers/cdrom/cdrom.c | 16 +- drivers/cdrom/cm206.c | 26 +- drivers/cdrom/mcdx.c | 2673 ++++++++++-------------- drivers/cdrom/sbpcd.c | 31 +- drivers/char/Config.in | 4 +- drivers/char/Makefile | 10 +- drivers/char/keyboard.c | 42 +- drivers/char/softdog.c | 90 +- drivers/char/vt.c | 3 +- drivers/isdn/isdn_tty.c | 2 +- drivers/net/Config.in | 1 + drivers/net/slip.c | 3 - drivers/scsi/ultrastor.c | 4 +- drivers/scsi/ultrastor.h | 2 +- fs/Config.in | 1 + fs/binfmt_java.c | 11 +- fs/devices.c | 2 +- fs/dquot.c | 3 +- fs/file_table.c | 4 +- fs/locks.c | 18 +- fs/ufs/ufs_inode.c | 2 +- include/linux/cm206.h | 2 +- include/linux/mcdx.h | 181 +- include/linux/skbuff.h | 2 +- include/linux/sysctl.h | 2 + include/linux/ucdrom.h | 36 +- include/net/af_unix.h | 7 +- kernel/ksyms.c | 3 + kernel/sys.c | 2 +- kernel/sysctl.c | 9 + net/README | 18 +- net/appletalk/aarp.c | 2 +- net/appletalk/ddp.c | 6 +- net/ax25/af_ax25.c | 12 +- net/ax25/ax25_out.c | 4 +- net/ax25/ax25_route.c | 4 +- net/bridge/br.c | 32 +- net/bridge/br_tree.c | 3 +- net/core/dev.c | 4 +- net/core/net_alias.c | 38 +- net/core/skbuff.c | 20 +- net/ethernet/eth.c | 4 +- net/ipv4/Config.in | 2 +- net/ipv4/arp.c | 6 +- net/ipv4/igmp.c | 4 +- net/ipv4/ip_alias.c | 2 +- net/ipv4/ip_forward.c | 2 +- net/ipv4/ip_fragment.c | 2 +- net/ipv4/ipip.c | 7 +- net/ipv4/ipmr.c | 2 +- net/ipv4/rarp.c | 2 +- net/ipv4/tcp.c | 4 +- net/ipv4/tcp_input.c | 2 +- net/ipv4/tcp_output.c | 10 +- net/ipv4/tcp_timer.c | 4 +- net/ipx/af_ipx.c | 10 +- net/netlink.c | 4 +- net/netrom/af_netrom.c | 4 +- net/netrom/nr_dev.c | 2 +- net/netrom/nr_in.c | 2 +- net/netrom/nr_subr.c | 2 +- net/socket.c | 6 +- net/unix/af_unix.c | 9 +- net/unix/garbage.c | 41 +- 80 files changed, 1850 insertions(+), 2164 deletions(-) diff --git a/CREDITS b/CREDITS index 33312b6c1335..6284e2fcbe85 100644 --- a/CREDITS +++ b/CREDITS @@ -755,7 +755,8 @@ D: SLS distribution D: Initial implementation of VC's, pty's and select() N: James B. MacLean -E: jmaclean@fox.nstn.ns.ca +E: macleajb@ednet.ns.ca +W: http://www.ednet.ns.ca/~macleajb/dosemu.html D: Coordinator of DOSEMU releases D: Program in DOSEMU S: PO BOX 220, HFX. CENTRAL @@ -1007,7 +1008,7 @@ D: Author, Emacs VC and GUD modes N: Stefan Reinauer E: stepan@home.culture.mipt.ru W: http://home.culture.mipt.ru/~stepan -D: Modulized affs and ufs. Minor fixes. +D: Modularized affs and ufs. Minor fixes. S: Rebmannsweg 34h S: 79539 Loerrach S: Germany diff --git a/Documentation/Configure.help b/Documentation/Configure.help index c21cd1ec22ad..dd08d84bcf18 100644 --- a/Documentation/Configure.help +++ b/Documentation/Configure.help @@ -39,12 +39,16 @@ CONFIG_EXPERIMENTAL testing is not yet high enough for general use. This is usually known as the "alpha-test" phase amongst developers. If a feature is currently in alpha-test, then the developers usually discourage - widespread use of this feature by the general public to avoid - "Why doesn't this work?" type mail messages. However, active testing - and and detailed bug reports from people familiar with the kernel's - internals are usually welcomed by the developers. Unless you intend - to help test and develop a feature or driver that falls into this - category, you should probably say N here, which will cause this + uninformed widespread use of this feature by the general public to + avoid "Why doesn't this work?" type mail messages. However, active + testing and use of these systems is welcomed. Just be aware that it + may not meet the normal level of reliability or it may fail to work + in some special cases. Detailed bug reports from people familiar with + the kernel internals are usually welcomed by the developers. + + Unless you intend to help test and develop a feature or driver that + falls into this category, or you have a situation that requires using + these features you should probably say N here, which will cause this configure script to present you with fewer choices. If you say Y here, you will be offered the choice of using features or drivers that are currently considered to be in the alpha-test phase. @@ -403,7 +407,8 @@ CONFIG_FIREWALL net is inspected by the firewall first. If you want to configure your Linux box as a firewall for a local network, say Y here. If your local network is TCP/IP based, you will have to say Y to "IP: - firewalling", below. Chances are that you don't want this, so say N. + firewalling", below. Chances are that you should use this on any + machine being run as a router and not on a host. Sun floppy controller support CONFIG_BLK_DEV_SUNFD @@ -465,7 +470,7 @@ CONFIG_MAX_16M option to the kernel 3) passing the "mem=4M" option to the kernel (thereby disabling all but the first 4M of RAM) 4) disabling the cache from your BIOS settings 5) exchanging RAM chips 6) exchanging - the motherboard 7) committing suicide. + the motherboard. Using SRM as bootloader CONFIG_ALPHA_SRM @@ -772,9 +777,9 @@ CONFIG_IP_FORWARD IP: multicasting CONFIG_IP_MULTICAST This is code for addressing several networked computers at once, - enlarging your kernel by about 2 kB. Some versions of gated, the - program which constantly updates a networked computer's routing - tables, require that this option be compiled in. You also need + enlarging your kernel by about 2 kB. If you are using gated, the + to update your computer's routing tables and are using RIP2 or OSPF + you will need to have this option compiled in. You also need multicasting if you intend to participate in the MBONE, a high bandwidth network on top of the internet which carries audio and video broadcasts. More information about the MBONE is on the WWW at @@ -789,28 +794,22 @@ CONFIG_IP_ROUTER Some Linux network drivers use a technique called copy and checksum to optimize host performance. For a machine which is forwarding most packets to another host this is however a loss. This parameter turns - off copy and checksum from devices. It may also do other changes in + off copy and checksum from devices. It may make other changes in the future. IP: firewalling CONFIG_IP_FIREWALL - A firewall is a computer which protects a local network from the - rest of the internet: all traffic to and from computers on the local - net is inspected by the firewall first. If you want to configure - your Linux box as a firewall for a local TCP/IP based network, say Y - here. This will enlarge your kernel by about 2kB. You will need to - read the FIREWALL-HOWTO, available via ftp (user: anonymous) in - sunsite.unc.edu:/pub/Linux/docs/HOWTO. Also, you will have to use - the ipfw tool from the net-tools package, available via ftp (user: - anonymous) from - ftp.linux.org.uk:/pub/linux/Networking/PROGRAMS/NetTools, or - preferably ipfwadm from ftp.xos.nl:/pub/linux/ipfwadm/. These - programs allow selective blocking of internet traffic based on type, - origin and destination. You need to enable IP firewalling in order - to be able to use IP masquerading (i.e. local computers can chat - with an outside host, but that outside host is made to think that it - is talking to the firewall box. Makes the local network completely - invisible). Chances are that you don't want this, so say N. + If you want to configure your Linux box as a firewall for a local + TCP/IP based network, say Y here. This will enlarge your kernel by + about 2kB. You may need to read the FIREWALL-HOWTO, available via + ftp (user: anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO. Also, + you will need the ipfwadm tool to allow selective blocking of internet + traffic based on type, origin and destination. You need to enable IP + firewalling in order to be able to use IP masquerading (i.e. local + computers can chat with an outside host, but that outside host is + made to think that it is talking to the firewall box. Makes the local + network completely invisible) or to use the ip packet accounting to see + what is using all your network bandwidth. IP: accounting CONFIG_IP_ACCT @@ -821,13 +820,7 @@ CONFIG_IP_ACCT firewalling. The data is accessible with "cat /proc/net/ip_acct", so you want to say Y to the /proc filesystem below, if you say Y here. To specify what exactly should be recorded, you need the tool - ipfw from the net-tools package, available via ftp (user: - anonymous) from - ftp.linux.org.uk:/pub/Linux/Networking/PROGRAMS/NetTools. Also, you - might want to have a look at the net-acct package, available via ftp - (user: anonymous) from - sunsite.unc.edu:/pub/Linux/system/Network/management. Most people - say N, however. + ipfwadm (available from ftp.xos.nl if you don't have a copy already). IP: tunneling CONFIG_NET_IPIP @@ -840,8 +833,7 @@ CONFIG_NET_IPIP mobile IP facilities (which effectively are doing that). Enabling this option will produce two modules ( = code which can be inserted in and removed from the running kernel whenever you want), one - encapsulator and one decapsulator. This is still alpha code, which - means that it need not be completely stable. You can read details in + encapsulator and one decapsulator. You can read details in drivers/net/README.tunnel. Most people can say N. IP: firewall packet logging @@ -905,8 +897,9 @@ PC/TCP compatibility mode CONFIG_INET_PCTCP If you have been having difficulties telneting to your Linux machine from a DOS system that uses (broken) PC/TCP networking software (all - versions up to OnNet 2.0), try enabling this option. Everyone else - says N. + versions up to OnNet 2.0) over your local ethernet try enabling this + option. Everyone else says N. People having problems with NCSA telnet + should see the file linux/Documentation/networking/ncsa-telnet. Reverse ARP CONFIG_INET_RARP @@ -939,7 +932,8 @@ CONFIG_NO_PATH_MTU_DISCOVERY we adjust to a smaller size. This is good, so most people say N. However, some versions of DOS NCSA telnet (and other software) are broken and can only connect to your Linux machine if you say Y - here. + here. See also Documentation/networking/ncsa-telnet for the location + of fixed NCSA telnet clients. Disable NAGLE algorithm (normally enabled) CONFIG_TCP_NAGLE_OFF @@ -957,26 +951,24 @@ CONFIG_IP_NOSR decide how to forward the frame. However, there is a feature of the IP protocol that allows to specify the full route for a given frame already at its origin. A frame with such a fully specified route is - called "source routed". The question now is whether we should honor + called "source routed". The question now is whether we should honour these route requests when such frames arrive, or if we should - drop all those frames instead. Honoring can introduce security - problems (and is not required by the IP specification), and hence it - is recommended to say Y here unless you really know what you're - doing. + drop all those frames instead. Honouring them can introduce security + problems (and is rarely a useful feature), and hence it is recommended + that you say Y here unless you really know what you're doing. IP: Allow large windows (not recommend if <16Mb of memory) CONFIG_SKB_LARGE - This option can speed up network performance. It works by increasing - the size of socket buffers, thereby reducing overhead but increasing - memory usage. Say N if you have less than 16Mb of RAM, otherwise Y. - Note for machines with more that 64MB of RAM: in order for the kernel - to be able to use the memory above 64MB, pass the command line option - "mem=XXXM" (where XXX is the memory size in megabytes) to your - kernel. See the documentation of your boot loader (lilo or loadlin) - about how to pass options to the kernel. The lilo procedure is also - explained in the SCSI-HOWTO, available via ftp (user: anonymous) in - sunsite.unc.edu:/pub/Linux/docs/HOWTO. You also need at least 512kB - of RAM cache if you have more than 64MB of RAM. + On high speed, long distance networks the performance limit on + networking becomes the amount of data a machine can buffer until the + other end confirms its reception. (At 45Mbit/second there are a lot + of bits between New York and London ..). This option allows larger + amounts of data to be "in flight" at a given time. It also means a user + process can require a lot more memory for network buffers and thus this + option is best only used on machines with 16Mb of memory or higher. + Unless you are using long links with end to end speeds of over 2Mbit + a second or satellite links this option will make no difference to + performance. The IPX protocol CONFIG_IPX @@ -1018,9 +1010,10 @@ CONFIG_IPX_INTERN Appletalk DDP CONFIG_ATALK - Appletalk is the way Apple computers speak to each other on an - Ethernet (Apple calls it EtherTalk) network. If your linux box is - connected to such a network and you want to join the conversation, + Appletalk is the way Apple computers speak to each other on a + network. EtherTalk is the name used for appletalk over ethernet and + Localtalk is appletalk over the apple serial links. If your linux box + is connected to such a network and you 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 @@ -1034,6 +1027,10 @@ CONFIG_ATALK want). 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. + At the time the kernel is released the localtalk drivers are not + yet ready to ship. The kernel however supports localtalk and when + such drivers become available all you will need to do is download + and install the localtalk driver. Amateur Radio AX.25 Level 2 CONFIG_AX25 @@ -1044,24 +1041,22 @@ CONFIG_AX25 use a low speed TNC (a Terminal Node Controller acts as a kind of modem connecting your computer's serial port to your radio's microphone input and speaker output) supporting the KISS protocol or - the much faster Ottawa PI card (to enable support for this card, - you'll have to answer Y to the question about ALPHA test drivers, - below) or the Z8530 SCC cards; the latter two require an additional - radio modem. In order to use AX.25, you need to get a set of - supporting software tools via ftp (user: anonymous) from - sunacm.swan.ac.uk:/pub/misc/Linux/Radio/. A comprehensive listing of - all the software for Linux amateur radio users as well as - information about how to configure an AX.25 port is contained in the - HAM-HOWTO, available via ftp (user: anonymous) in - sunsite.unc.edu:/pub/Linux/docs/HOWTO. You might also want to check - out the file Documentation/networking/ax25.txt in the kernel - source. More information about digital amateur radio in general is - on the WWW at + the various SCC cards that are supported by the Ottowa PI, the + Gracilis Packetwin and the generic Z8530 driver. + At the moment there is no driver for the Baycom modem serial and parallel + port hacks although one is being written (see the HAM-HOWTO). The other + baycom cards (SCC) are supported by the Z8530 driver. + In order to use AX.25, you need to get a set of all the software for + Linux amateur radio users as well as information about how to + configure an AX.25 port is contained in the HAM-HOWTO, available via + ftp (user: anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO. You + might also want to check out the file Documentation/networking/ax25.txt + in the kernel source. More information about digital amateur radio + in general is on the WWW at http://www.cis.ohio-state.edu/hypertext/faq/usenet/radio/ham-radio/digital-faq/faq.html (To browse the WWW, you need to have access to a machine on the Internet that has one of the programs lynx, netscape or - Mosaic). AX.25 support is actively being developed, so it's best to - get the very latest 1.3 kernel if you intend to use this. + Mosaic). Amateur Radio NET/ROM CONFIG_NETROM @@ -1076,9 +1071,7 @@ CONFIG_NETROM http://www.cis.ohio-state.edu/hypertext/faq/usenet/radio/ham-radio/digital-faq/faq.html (To browse the WWW, you need to have access to a machine on the Internet that has one of the programs lynx, netscape or - Mosaic). Amateur radio support is actively being developed, so you - might want to get the very latest 1.3 kernel if you intend to use - this. + Mosaic). AX.25 over Ethernet CONFIG_BPQETHER @@ -1094,11 +1087,12 @@ CONFIG_BRIDGE ethernet bridge, which means that the different ethernet segments it is connected to will appear as one ethernet to the participants. Several such bridges can work together to create even - larger networks of ethernets using a cool spanning tree - algorithm. Note that if your box acts as a bridge, it probably - contains several ethernet devices, but the kernel is not able to - recognize more than one at boot time without help; for details read - the Multiple-Ethernet-mini-HOWTO, available via ftp (user: + larger networks of ethernets using the IEEE802.1 spanning tree + algorithm. As this is a standard Linux bridges will interwork properly + with other third party bridge products. Note that if your box acts as + a bridge, it probably contains several ethernet devices, but the kernel + is not able to recognize more than one at boot time without help; for + details read the Multiple-Ethernet-mini-HOWTO, available via ftp (user: anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. The Bridging code is still in test. If unsure, say N. The bridge configuration tools are available via ftp from shadow.cabi.net. @@ -1531,8 +1525,8 @@ CONFIG_NETDEVICES Dummy net driver support CONFIG_DUMMY - This is essentially a loopback device (i.e. traffic you send to this - device is immediately returned back to you) with a configurable IP + This is essentially a bit-bucket device (i.e. traffic you send to + this device is consigned into oblivion) with a configurable IP address different from the usual 127.0.0.1. It is most commonly used in order to make your currently inactive SLIP address seem like a real address for local programs. If you use SLIP or PPP, you might @@ -1592,6 +1586,14 @@ CONFIG_SLIP_SMART RELCOM line fill and keepalive monitoring. Ideal on poor quality analogue lines. +Six bit SLIP encapsulation +CONFIG_SLIP_MODE_SLIP6 + Just occasionally you may need to run IP over hostile serial networks that + don't pass all control characters or are only seven bit. This adds an + extra mode you can use with SLIP "slip6" which contains only the normal + ascii symbols. Its good enough, for example, to run IP over the async + ports of a Camtec JNT Pad. + Radio network interfaces CONFIG_NET_RADIO Radio based interfaces for Linux. Both amateur radio (AX.25) and other @@ -1651,13 +1653,10 @@ CONFIG_STRIP WIC (Radio IP bridge) CONFIG_WIC - Don't know what this is; has something to do with the parallel - port. Say N and that's that. But if you want to compile it 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. :-) + Support for the WIC parallel port radio bridge. You'll probably want + to say N. -Z8530 SCC kiss emulation driver for AX.2 +Z8530 SCC kiss emulation driver for AX.25 CONFIG_SCC These cards are used to connect your Linux box to an amateur radio and communicate with other computers. If you want to use this, read @@ -1765,6 +1764,10 @@ CONFIG_SDLA from the running kernel whenever you want). If you want to compile it as a module, say M here and read Documentation/modules.txt. +Ethernet (10 or 100Mbit) +CONFIG_NET_ETHERNET + Say yes if you want to select support for ethernet cards. + Sun LANCE Ethernet support CONFIG_SUN_LANCE This is support for lance ethernet cards on Sun workstations such as @@ -1816,6 +1819,9 @@ CONFIG_ULTRA more than one network card under linux, read the Multiple-Ethernet-mini-HOWTO, available from sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + Important: There have been many reports that, with some motherboards + mixing an SMC Ultra and an Adaptec AHA1542 SCSI card causes corruption + problems with many operating systems. SMC 9194 Support CONFIG_SMC9194 @@ -1858,15 +1864,14 @@ CONFIG_EL1 If you have a network (ethernet) card of this type, say Y and read the Ethernet-HOWTO, available via ftp (user: anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO. Also, consider buying a new - card, since the 3c501 is buggy and obsolete and the driver is - unsupported. This driver is also available as a module ( = 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 as well as - Documentation/networking/net-modules.txt. If you plan to use more - than one network card under linux, read the - Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + card, since the 3c501 is slow and obsolete. This driver is also + available as a module ( = 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 as well + as Documentation/networking/net-modules.txt. If you plan to use more + than one network card under linux, read the + Multiple-Ethernet-mini-HOWTO, available from + sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini - and don't use 3c501s. 3c503 support CONFIG_EL2 @@ -2558,6 +2563,14 @@ CONFIG_QUOTA use it. Probably this is only useful for multi user systems. If unsure, say N. +Mandatory lock support +CONFIG_LOCK_MANDATORY + Mandatory locking is used by some System 5 style database applications. + To use this option safely you must have newer NFS daemons, new samba, + new netatalk, new mars-nwe and other file servers. At the time of + writing none of these are available. Unless you need this feature say + N. + Standard (minix) fs support CONFIG_MINIX_FS Minix is a simple operating system used in many classes about diff --git a/Documentation/cdrom/cdrom-standard.tex b/Documentation/cdrom/cdrom-standard.tex index d5dfc457d1be..80c889a6dc65 100644 --- a/Documentation/cdrom/cdrom-standard.tex +++ b/Documentation/cdrom/cdrom-standard.tex @@ -1,5 +1,5 @@ \documentclass{article} -\def\version{$Id: cdrom-standard.tex,v 0.4 1996/04/17 20:46:34 david Exp $} +\def\version{$Id: cdrom-standard.tex,v 0.5 1996/05/12 22:00:00 emoenke Exp $} \evensidemargin=0pt \oddsidemargin=0pt @@ -29,26 +29,66 @@ variety of hardware devices. The reasons for this are presumably \item The large list of different hardware devices available for the popular IBM PC-architecture, \item The open design of the operating system, such that everybody can -write a driver for Linux. +write a driver for Linux (source code examples). \end{itemize} The vast choice and openness has lead not only to a wide support of -hardware devices, but also to a certain divergence in -behavior. Especially for \cdrom\ devices, the way a particular drive -reacts to a `standard' $ioctl()$ call varies a lot from one brand -to another. - -Undoubtedly, this has a reason. Since the beginning of the \cdrom, -many different interfaces developed. Most of them had proprietary -interfaces, which means that a separate driver had to be written for -each new type of interface. Nowadays, all new \cdrom\ types are either -ATAPI/IDE or SCSI. But history has delivered us \cdrom\ support for -some 10 or so different interfaces. Not all drives have the same -capabilities, and all different interfaces use different i/o formats -for the data. For the interfacing with the \linux\ operating system -and software, this has lead to a rather wild set of commands and data -formats. Presumably, every \cdrom\ device drive author has added his -own set of ioctl commands and used a format reminiscent of the -underlying hardware. Any structure is lost. +hardware devices, but also to a certain divergence in behavior. Especially +for \cdrom\ devices, the way a particular drive reacts to a `standard' +$ioctl()$ call varies a lot from one brand to another; until today, the +\linux \cdrom\ driver writers kept away from wilderness by a good practice: +to evolve a new driver by copying, understanding and changing an existing +one. + +Since the beginning of the \cdrom, many different interfaces developed. +Some of them had their own proprietary design (Sony, Mitsumi, Panasonic), +other manufacturers adopted an existing electrical interface and changed +the functionality (CreativeLabs/SoundBlaster, Teac, Funai) or simply adapted +their drives to one or more of the already existing electrical interfaces +(Aztech, Sanyo, Funai, Vertos, Longshine, Optics Storage and most of the +`NoName' manufacturers). +In cases where a new drive really brought his own interface or used his +own command set and flow control scheme, either a separate driver had to +be written, or an existing driver had to get enhanced. + +Nowadays, almost all new \cdrom\ types are either ATAPI/IDE or SCSI; +it is very unlikely that any manufacturer still will create a new +interface, and new drives for the existing proprietary interfaces are +getting rare. +But history has delivered us \cdrom\ support for many different interfaces. + +Some of the \linux\ \cdrom\ driver writers look at the existing standard +which is expressed through as to a rather wild set of +commands and data formats and feel that any structure is lost, and from +this point of view, this documentation shall help to achieve a common +programming interface. + +Others - mainly those who used the already existing drivers not only as +a coding example, but also as a `user interface' reference during their +own development - have taken care that reflects a +software interface to `user programs' which is unique between all drivers +as much as possible; these driver writers will continue to refine the +existing where it seems necessary, and they tend to look +if any newly requested functionality isn't already there before they are +ready to define new structures. The sbpcd driver gives an example that +it is possible to let a robot arm play juke box - either with audio or +with data CDs -, and that it is possible to let the juke box work on +even if a disk has fallen upon the floor and the drive door has closed +without having a disk inside; without any new software layer or any +structures which are not already present in . +This `other' group of \linux\ \cdrom\ driver writers explicitely does +NOT support the idea to define an additional software layer between driver +and user program. + + +The following text reflects the opinion of the first mentioned \linux\ +\cdrom\ driver writer group only; the other group (not only the `silent +majority') sees this text as a good base for a future documentation of the +existing common \linux\ \cdrom\ programming interface, as it is stated +within . Where needs some external +explanation, this text can give it if the reader is aware that - at least +at the moment - this text claims to be the proposal of something else than +. + Apart from the somewhat unstructured interfacing with software, the actual execution of the commands is different for most of the @@ -140,21 +180,21 @@ $$ \halign{$#$\ \hfil&$#$\ \hfil&\hbox to 10em{$#$\hss}& $/*$ \rm# $*/$\hfil\cr struct& cdrom_device_ops\ \{ \hidewidth\cr - &int& (* open)(dev_t, int)\cr - &void& (* release)(dev_t);\cr - &int& (* open_files)(dev_t); \cr - &int& (* drive_status)(dev_t);\cr - &int& (* disc_status)(dev_t);\cr - &int& (* media_changed)(dev_t);\cr - &int& (* tray_move)(dev_t, int);\cr - &int& (* lock_door)(dev_t, int);\cr - &int& (* select_speed)(dev_t, int);\cr - &int& (* select_disc)(dev_t, int);\cr - &int& (* get_last_session) (dev_t, struct\ cdrom_multisession *{});\cr - &int& (* get_mcn)(dev_t, struct\ cdrom_mcn *{});\cr - &int& (* reset)(dev_t);\cr - &int& (* audio_ioctl)(dev_t, unsigned\ int, void *{});\cr - &int& (* dev_ioctl)(dev_t, unsigned\ int, unsigned\ long);\cr + &int& (* open)(kdev_t, int)\cr + &void& (* release)(kdev_t);\cr + &int& (* open_files)(kdev_t); \cr + &int& (* drive_status)(kdev_t);\cr + &int& (* disc_status)(kdev_t);\cr + &int& (* media_changed)(kdev_t);\cr + &int& (* tray_move)(kdev_t, int);\cr + &int& (* lock_door)(kdev_t, int);\cr + &int& (* select_speed)(kdev_t, int);\cr + &int& (* select_disc)(kdev_t, int);\cr + &int& (* get_last_session) (kdev_t, struct\ cdrom_multisession *{});\cr + &int& (* get_mcn)(kdev_t, struct\ cdrom_mcn *{});\cr + &int& (* reset)(kdev_t);\cr + &int& (* audio_ioctl)(kdev_t, unsigned\ int, void *{});\cr + &int& (* dev_ioctl)(kdev_t, unsigned\ int, unsigned\ long);\cr \noalign{\medskip} &\llap{const\ }int& capability;& capability flags \cr &int& mask;& mask of capability: disables them \cr @@ -213,7 +253,7 @@ negative on error. A function call should return only after the command has completed, but of course waiting for the device should not use processor time. -\subsection{$Open(dev_t\ dev, int\ purpose)$} +\subsection{$Open(kdev_t\ dev, int\ purpose)$} $Open()$ should try to open the device for a specific $purpose$, which can be either: @@ -235,7 +275,7 @@ done by the calling routine in \cdromc, so the low-level routine should only be concerned with proper initialization and device-use count. -\subsection{$Release(dev_t\ dev)$} +\subsection{$Release(kdev_t\ dev)$} The use-count of the device $dev$ should be decreased by 1, and a single call $MOD_DEC_USE_COUNT$ should be coded here. Possibly other @@ -245,14 +285,14 @@ unlocking the door, should be left over to the general routine $cdrom_release()$. Also, the invalidation of the allocated buffers in the VFS is taken care of by the routine in \cdromc. -\subsection{$Open_files(dev_t\ dev)$} +\subsection{$Open_files(kdev_t\ dev)$} This function should return the internal variable use-count of the device $dev$. The use-count is not implemented in the routines in \cdromc\ itself, because there may be many minor devices connected to a single low-level driver. -\subsection{$Drive_status(dev_t\ dev)$} +\subsection{$Drive_status(kdev_t\ dev)$} \label{drive status} The function $drive_status$, if implemented, should provide @@ -269,7 +309,7 @@ CDS_DISC_OK& a disc is loaded and everything is fine\cr } $$ -\subsection{$Disc_status(dev_t\ dev)$} +\subsection{$Disc_status(kdev_t\ dev)$} \label{disc status} As a complement to $drive_status()$, this function can provide the @@ -301,7 +341,7 @@ this function through $cdrom_media_changed()$, we can implement separate queues for the VFS and a new $ioctl()$ function that can report device changes to software (e.g., an auto-mounting daemon). -\subsection{$Tray_move(dev_t\ dev, int\ position)$} +\subsection{$Tray_move(kdev_t\ dev, int\ position)$} This function, if implemented, should control the tray movement. (No other function should control this.) The parameter $position$ controls @@ -314,7 +354,7 @@ This function returns 0 upon success, and a non-zero value upon error. Note that if the tray is already in the desired position, no action need be taken, and the return value should be 0. -\subsection{$Lock_door(dev_t\ dev, int\ lock)$} +\subsection{$Lock_door(kdev_t\ dev, int\ lock)$} This function (and no other code) controls locking of the door, if the drive allows this. The value of $lock$ controls the desired locking @@ -325,7 +365,7 @@ state: \end{itemize} Return values are as for $tray_move()$. -\subsection{$Select_speed(dev_t\ dev, int\ speed)$} +\subsection{$Select_speed(kdev_t\ dev, int\ speed)$} Although none of the drivers has implemented this function so far, some drives are capable of head-speed selection, and hence this is a @@ -341,7 +381,7 @@ for it, more than real-time playback of audio might be used for high-speed copying of audio tracks). Badly pressed \cdrom s may benefit from less-than-maximum head rate. -\subsection{$Select_disc(dev_t\ dev, int\ number)$} +\subsection{$Select_disc(kdev_t\ dev, int\ number)$} If the drive can store multiple discs (a juke-box), it is likely that a disc selection can be made by software. This function should perform @@ -350,7 +390,7 @@ success, a negative value on error. Currently, none of the \linux\ \cdrom\ drivers appears to support such functionality, but it is defined here for future purposes. -\subsection{$Get_last_session(dev_t\ dev, struct\ cdrom_multisession * +\subsection{$Get_last_session(kdev_t\ dev, struct\ cdrom_multisession * ms_info)$} This function should implement the old corresponding $ioctl()$. For @@ -364,7 +404,7 @@ format if it wishes so (setting the $ms_info\rightarrow addr_format$ field appropriately, of course) and the routines in \cdromc\ will make the transform if necessary. The return value is 0 upon success. -\subsection{$Get_mcn(dev_t\ dev, struct\ cdrom_mcn * mcn)$} +\subsection{$Get_mcn(kdev_t\ dev, struct\ cdrom_mcn * mcn)$} Some discs carry a `Media Catalog Number' (MCN), also called `Universal Product Code' (UPC). This number should reflect the number that @@ -374,14 +414,14 @@ format. The return argument to this function is a pointer to a pre-declared memory region of type $struct\ cdrom_mcn$. The MCN is expected as a 13-character string, terminated by a null-character. -\subsection{$Reset(dev_t dev)$} +\subsection{$Reset(kdev_t dev)$} This call should implement hard-resetting the drive (although in circumstances that a hard-reset is necessary, a drive may very well not listen to commands anymore). Preferably, control is returned to the caller only after the drive has finished resetting. -\subsection{$Audio_ioctl(dev_t\ dev, unsigned\ int\ cmd, void * +\subsection{$Audio_ioctl(kdev_t\ dev, unsigned\ int\ cmd, void * arg)$} Some of the \cdrom-$ioctl$s defined in {\tt cdrom.h} can be @@ -405,7 +445,7 @@ errors should be according to the standards, whatever they are. (We may decide to sanitize the return value in $cdrom_ioctl()$, in order to guarantee a uniform interface to the audio-player software.) -\subsection{$Dev_ioctl(dev_t\ dev, unsigned\ int\ cmd, unsigned\ long\ +\subsection{$Dev_ioctl(kdev_t\ dev, unsigned\ int\ cmd, unsigned\ long\ arg)$} Some $ioctl$s seem to be specific to certain \cdrom\ drives. That is, @@ -772,12 +812,6 @@ if implemented. No memory allocation or verification is carried out. \subsection{How to update your driver} -We hope all \cdrom\ driver maintainers will understand the advantages -of re-routing the interface to the kernel though the new routines in -\cdromc. The following scheme should help you to update your -driver. It should not be too much work. We hope you want to take these -steps, in order to make the \linux\ \cdrom\ support more uniform and -more flexible. \begin{enumerate} \item Make a backup of your current driver. \item Get hold of the files \cdromc\ and \ucdrom, they should be in diff --git a/Documentation/devices.tex b/Documentation/devices.tex index 47870506e070..4ac188d08ced 100644 --- a/Documentation/devices.tex +++ b/Documentation/devices.tex @@ -42,7 +42,7 @@ foo \kill}% % \title{{\bf Linux Allocated Devices}} \author{Maintained by H. Peter Anvin $<$hpa@zytor.com$>$} -\date{Last revised: May 9, 1996} +\date{Last revised: May 12, 1996} \maketitle % \noindent @@ -61,9 +61,10 @@ tsx-11.mit.edu in the directory {\file /pub/linux/docs/linux-standards/fsstnd}. To have a major number allocated, or a minor number in situations -where that applies (e.g.\ busmice), please contact me. Also, if you -have additional information regarding any of the devices listed below, -or if I have made a mistake, I would greatly appreciate a note. +where that applies (e.g.\ busmice), please contact me with the +appropriate device information. Also, if you have additional +information regarding any of the devices listed below, or if I have +made a mistake, I would greatly appreciate a note. Allocations marked (68k/Amiga) apply to Linux/68k on the Amiga platform only. Allocations marked (68k/Atari) apply to Linux/68k on @@ -389,13 +390,38 @@ disk. \begin{devicelist} \major{ 9}{}{char }{SCSI tape devices} - \minor{0}{/dev/st0}{First SCSI tape} - \minor{1}{/dev/st1}{Second SCSI tape} + \minor{0}{/dev/st0}{First SCSI tape, mode 0} + \minor{1}{/dev/st1}{Second SCSI tape, mode 0} \minordots - \minor{128}{/dev/nst0}{First SCSI tape, no rewind-on-close} - \minor{129}{/dev/nst1}{Second SCSI tape, no rewind-on-close} + \minor{32}{/dev/st0l}{First SCSI tape, mode 1} + \minor{33}{/dev/st1l}{Second SCSI tape, mode 1} \minordots -\\ + \minor{64}{/dev/st0m}{First SCSI tape, mode 2} + \minor{65}{/dev/st1m}{Second SCSI tape, mode 2} + \minordots + \minor{96}{/dev/st0a}{First SCSI tape, mode 3} + \minor{97}{/dev/st1a}{Second SCSI tape, mode 4} + \minordots + \minor{128}{/dev/nst0}{First SCSI tape, mode 0, no rewind} + \minor{129}{/dev/nst1}{Second SCSI tape, mode 0, no rewind} + \minordots + \minor{160}{/dev/nst0l}{First SCSI tape, mode 1, no rewind} + \minor{161}{/dev/nst1l}{Second SCSI tape, mode 1, no rewind} + \minordots + \minor{192}{/dev/nst0m}{First SCSI tape, mode 2, no rewind} + \minor{193}{/dev/nst1m}{Second SCSI tape, mode 2, no rewind} + \minordots + \minor{224}{/dev/nst0a}{First SCSI tape, mode 3, no rewind} + \minor{225}{/dev/nst1a}{Second SCSI tape, mode 3, no rewind} + \minordots +\end{devicelist} + +\noindent +``No rewind'' refers to the omission of the default automatic rewind +on device close. The {\file MTREW} or {\file MTOFFL} ioctl()s can be +used to rewind the tape regardless of the device used to access it. + +\begin{devicelist} \major{ }{}{block}{Metadisk (RAID) devices} \minor{0}{/dev/md0}{First metadisk group} \minor{1}{/dev/md1}{Second metadisk group} diff --git a/Documentation/devices.txt b/Documentation/devices.txt index 39afd54c1991..b32820a34db7 100644 --- a/Documentation/devices.txt +++ b/Documentation/devices.txt @@ -2,7 +2,7 @@ Maintained by H. Peter Anvin - Last revised: May 9, 1996 + Last revised: May 12, 1996 This list is the successor to Rick Miller's Linux Device List, which he stopped maintaining when he got busy with other things in 1993. It @@ -18,9 +18,10 @@ Standard (FSSTND). The FSSTND is available via FTP from tsx-11.mit.edu in the directory /pub/linux/docs/linux-standards/fsstnd. To have a major number allocated, or a minor number in situations -where that applies (e.g. busmice), please contact me. Also, if you -have additional information regarding any of the devices listed below, -or if I have made a mistake, I would greatly appreciate a note. +where that applies (e.g. busmice), please contact me with the +appropriate device information. Also, if you have additional +information regarding any of the devices listed below, or if I have +made a mistake, I would greatly appreciate a note. Allocations marked (68k/Amiga) apply to Linux/68k on the Amiga platform only. Allocations marked (68k/Atari) apply to Linux/68k on @@ -214,12 +215,36 @@ least not without contacting me first. partitions is 15. 9 char SCSI tape devices - 0 = /dev/st0 First SCSI tape - 1 = /dev/st1 Second SCSI tape + 0 = /dev/st0 First SCSI tape, mode 0 + 1 = /dev/st1 Second SCSI tape, mode 0 ... - 128 = /dev/nst0 First SCSI tape, no rewind-on-close - 129 = /dev/nst1 Second SCSI tape, no rewind-on-close + 32 = /dev/st0l First SCSI tape, mode 1 + 33 = /dev/st1l Second SCSI tape, mode 1 ... + 64 = /dev/st0m First SCSI tape, mode 2 + 65 = /dev/st1m Second SCSI tape, mode 2 + ... + 96 = /dev/st0a First SCSI tape, mode 3 + 97 = /dev/st1a Second SCSI tape, mode 3 + ... + 128 = /dev/nst0 First SCSI tape, mode 0, no rewind + 129 = /dev/nst1 Second SCSI tape, mode 0, no rewind + ... + 160 = /dev/nst0l First SCSI tape, mode 1, no rewind + 161 = /dev/nst1l Second SCSI tape, mode 1, no rewind + ... + 192 = /dev/nst0m First SCSI tape, mode 2, no rewind + 193 = /dev/nst1m Second SCSI tape, mode 2, no rewind + ... + 224 = /dev/nst0a First SCSI tape, mode 3, no rewind + 225 = /dev/nst1a Second SCSI tape, mode 3, no rewind + ... + + "No rewind" refers to the omission of the default + automatic rewind on device close. The MTREW or MTOFFL + ioctl()'s can be used to rewind the tape regardless of + the device used to access it. + block Metadisk (RAID) devices 0 = /dev/md0 First metadisk group 1 = /dev/md1 Second metadisk group diff --git a/Documentation/java.txt b/Documentation/java.txt index ba6d4cf0d603..624fcc560439 100644 --- a/Documentation/java.txt +++ b/Documentation/java.txt @@ -1,5 +1,5 @@ - JAVA Binary Kernel Support for Linux v1.01 - ------------------------------------------ + Java(tm) Binary Kernel Support for Linux v1.01 + ---------------------------------------------- Linux beats them ALL! While all other OS's are TALKING about direct support of Java Binaries in the OS, Linux is doing it! @@ -14,9 +14,15 @@ small details: ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/Java-HOWTO If you install the JDK in a location other than the suggested - directory of /usr/local/java, then you will need to edit the - kernel's fs/binfmt_java.c file and make the needed change to the - _PATH_JAVA definition at the top of that file. + directory of /usr/local/java, then you will need to tell the + kernel where you put the Java interpreter. + There are two ways to do this. + One, edit fs/binfmt_java.c file and make the needed change to + the _PATH_JAVA definition at the top of that file. + Two, as root, issue the command: + echo "/path/to/java/interpreter" > /proc/sys/kernel/java-interpreter + (Currently, this does not work if you're using a module for + Java support.) 2) You must chmod the '*.class' files you wish to execute with the execute bit. This is not normally (till now) done with @@ -30,7 +36,6 @@ small details: as a loadable module. If a module, load it with insmod or kerneld. - To test your new setup, enter in the following simple Java app, and name it "HelloWorld.java": @@ -75,9 +80,15 @@ demo/Blink/example1.html file), and: with all known browsers. 2) If you install the JDK in a location other than the suggested - directory of /usr/local/java, then you will need to edit the - kernel's fs/binfmt_java.c file and make the needed change to the - _PATH_APPLET definition at the top of that file. + directory of /usr/local/java, then you will need to tell the + kernel where you put the Java appletviewer. + There are two ways to do this. + One, edit fs/binfmt_java.c file and make the needed change to + the _PATH_APPLET definition at the top of that file. + Two, as root, issue the command: + echo "/path/to/java/appletviewer" > /proc/sys/kernel/java-appletviewer + (Currently, this does not work if you're using a module for + Java support.) 3) You must chmod the '*.html' files you wish to execute with the execute bit. This is not normally (till now) done with @@ -86,6 +97,7 @@ demo/Blink/example1.html file), and: 4) And then execute it. - Brian A. Lantz brian@lantz.com +(/proc/sys/kernel/java-* support by Mike Shaver (shaver@ingenia.com)) + diff --git a/Documentation/svga.txt b/Documentation/svga.txt index 4b520cbb13c4..09c1d078fc2b 100644 --- a/Documentation/svga.txt +++ b/Documentation/svga.txt @@ -1,4 +1,4 @@ - Video Mode Selection Support 2.7 + Video Mode Selection Support 2.9 (c) 1995, 1996 Martin Mares, -------------------------------------------------------------------------------- @@ -243,3 +243,4 @@ this must be done manually -- no autodetection mechanisms are available. - Screen store/restore fixed. 2.8 (14-Apr-96) - Previous release was not compilable without CONFIG_VIDEO_SVGA. - Better recognition of text modes during mode scan. +2.9 (12-May-96) - Ignored VESA modes 0x80 - 0xff (more VESA BIOS bugs!) diff --git a/Documentation/watchdog.txt b/Documentation/watchdog.txt index 5315158399e1..376911245281 100644 --- a/Documentation/watchdog.txt +++ b/Documentation/watchdog.txt @@ -2,14 +2,14 @@ Alan Cox - Custom Linux Driver And Program Development + Custom Linux Driver And Program Development The following watchdog drivers are currently implemented: - IMS WDT501-P - INS WDT501-P (no fan tachometer) - IMS WDT500-P + ICS WDT501-P + ICS WDT501-P (no fan tachometer) + ICS WDT500-P Software Only All four interfaces provide /dev/watchdog, which when open must be written @@ -40,6 +40,7 @@ Power Over X o o Overheat X o o The external event interfaces on the WDT boards are not currently supported. +Minor numbers are however allocated for it. Example Watchdog Driver @@ -65,11 +66,17 @@ int main(int argc, const char *argv[]) } -> People keep asking about the WDT watchdog timer hardware: The phone contacts -> for Industrial Computer Source are: -> -> US: 619 677 0898 (sales) 0895 (general) -> UK: 01243 533900 -> France (1) 69.18.74.30 -> -> and please mention Linux when enquiring. +Contact Information + +People keep asking about the WDT watchdog timer hardware: The phone contacts +for Industrial Computer Source are: + +US: 619 677 0877 (sales) 0895 (fax) +UK: 01243 533900 +France (1) 69.18.74.30 + +Industrial Computer Source +9950 Barnes Canyon Road +San Diego, CA + +and please mention Linux when enquiring. diff --git a/Makefile b/Makefile index d6191f4c1f31..6f6fff2096c8 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 1 PATCHLEVEL = 99 -SUBLEVEL = 2 +SUBLEVEL = 3 ARCH = i386 diff --git a/arch/alpha/defconfig b/arch/alpha/defconfig index 4555376ee301..174ecb0349d6 100644 --- a/arch/alpha/defconfig +++ b/arch/alpha/defconfig @@ -69,7 +69,6 @@ CONFIG_INET=y # CONFIG_INET_PCTCP is not set # CONFIG_INET_RARP is not set # CONFIG_NO_PATH_MTU_DISCOVERY is not set -# CONFIG_TCP_NAGLE_OFF is not set CONFIG_IP_NOSR=y CONFIG_SKB_LARGE=y @@ -164,6 +163,7 @@ CONFIG_DE4X5=y # Filesystems # # CONFIG_QUOTA is not set +# CONFIG_LOCK_MANDATORY is not set # CONFIG_MINIX_FS is not set # CONFIG_EXT_FS is not set CONFIG_EXT2_FS=y diff --git a/arch/i386/boot/video.S b/arch/i386/boot/video.S index 289f8cebc151..3db2f7c9517a 100644 --- a/arch/i386/boot/video.S +++ b/arch/i386/boot/video.S @@ -1,5 +1,5 @@ ! -! Display adapter & video mode setup, version 2.8 (14-Apr-96) +! Display adapter & video mode setup, version 2.9 (12-May-96) ! ! Copyright (C) 1995, 1996 Martin Mares ! Based on the original setup.S code (C) Linus Torvalds @@ -879,8 +879,8 @@ vesa1: seg gs ! Get next mode in the list jz vesar cmp ax,#0x0080 ! Check validity of mode ID jc vesa2 - or ah,ah ! Valid ID's are 0x0000-0x007f - jz vesae ! and 0x0100-0x07ff. + or ah,ah ! Valid ID's are 0x0000-0x007f and 0x0100-0x07ff + jz vesan ! [Certain BIOSes errorneously report 0x80-0xff] cmp ax,#0x0800 jnc vesae vesa2: push cx diff --git a/arch/i386/config.in b/arch/i386/config.in index 020bb67d2431..0e207fa9a10e 100644 --- a/arch/i386/config.in +++ b/arch/i386/config.in @@ -33,7 +33,9 @@ fi bool 'System V IPC' CONFIG_SYSVIPC tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF -tristate 'Kernel support for JAVA binaries' CONFIG_BINFMT_JAVA +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + tristate 'Kernel support for JAVA binaries' CONFIG_BINFMT_JAVA +fi bool 'Compile kernel as ELF - if your GCC is ELF-GCC' CONFIG_KERNEL_ELF choice 'Processor type' \ diff --git a/arch/i386/defconfig b/arch/i386/defconfig index 301b181939e1..252db60ca1e1 100644 --- a/arch/i386/defconfig +++ b/arch/i386/defconfig @@ -24,7 +24,6 @@ CONFIG_PCI=y CONFIG_SYSVIPC=y CONFIG_BINFMT_AOUT=y CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_JAVA is not set CONFIG_KERNEL_ELF=y # CONFIG_M386 is not set # CONFIG_M486 is not set @@ -69,7 +68,6 @@ CONFIG_INET=y # CONFIG_INET_PCTCP is not set # CONFIG_INET_RARP is not set # CONFIG_NO_PATH_MTU_DISCOVERY is not set -# CONFIG_TCP_NAGLE_OFF is not set CONFIG_IP_NOSR=y CONFIG_SKB_LARGE=y @@ -124,6 +122,7 @@ CONFIG_EL3=y # Filesystems # # CONFIG_QUOTA is not set +# CONFIG_LOCK_MANDATORY is not set CONFIG_MINIX_FS=y # CONFIG_EXT_FS is not set CONFIG_EXT2_FS=y diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c index 8825530c38c1..129dc928a79b 100644 --- a/arch/i386/kernel/smp.c +++ b/arch/i386/kernel/smp.c @@ -534,8 +534,10 @@ void smp_commence(void) void smp_callin(void) { + extern void calibrate_delay(void); int cpuid=GET_APIC_ID(apic_read(APIC_ID)); unsigned long l; + /* * Activate our APIC */ diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c index f31f9a70ed70..7a86984ec2e9 100644 --- a/drivers/block/genhd.c +++ b/drivers/block/genhd.c @@ -213,7 +213,7 @@ done: * Create devices for BSD partitions listed in a disklabel, under a * dos-like partition. See extended_partition() for more information. */ -static void bsd_disklabel_partition(struct gendisk *hd, int dev) +static void bsd_disklabel_partition(struct gendisk *hd, kdev_t dev) { struct buffer_head *bh; struct bsd_disklabel *l; @@ -470,7 +470,7 @@ static int osf_partition(struct gendisk *hd, unsigned int dev, unsigned long fir #ifdef CONFIG_SUN_PARTITION -static int sun_partition(struct gendisk *hd, unsigned int dev, unsigned long first_sector) +static int sun_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector) { int i, csum; unsigned short *ush; @@ -512,13 +512,15 @@ static int sun_partition(struct gendisk *hd, unsigned int dev, unsigned long fir : (__u32)(x)) if(!(bh = bread(dev, 0, 1024))) { - printk("Dev %d: unable to read partition table\n", dev); + printk("Dev %s: unable to read partition table\n", + kdevname(dev)); return -1; } label = (struct sun_disklabel *) bh->b_data; p = label->partitions; if (label->magic != SUN_LABEL_MAGIC && label->magic != SUN_LABEL_MAGIC_SWAPPED) { - printk("Dev %d Sun disklabel: bad magic %04x\n", dev, label->magic); + printk("Dev %s Sun disklabel: bad magic %04x\n", + kdevname(dev), label->magic); brelse(bh); return 0; } @@ -528,7 +530,8 @@ static int sun_partition(struct gendisk *hd, unsigned int dev, unsigned long fir for(csum = 0; ush >= ((unsigned short *) label);) csum ^= *ush--; if(csum) { - printk("Dev %d Sun disklabel: Csum bad, label corrupted\n", dev); + printk("Dev %s Sun disklabel: Csum bad, label corrupted\n", + kdevname(dev)); brelse(bh); return 0; } diff --git a/drivers/block/linear.c b/drivers/block/linear.c index 740ec2d54bd5..a91ba9655b81 100644 --- a/drivers/block/linear.c +++ b/drivers/block/linear.c @@ -128,7 +128,8 @@ static int linear_map (struct md_dev *mddev, kdev_t *rdev, tmp_dev=hash->dev0; if (block >= (tmp_dev->size + tmp_dev->offset) || block < tmp_dev->offset) - printk ("Block %ld out of bounds on dev %04x size %d offset %d\n", block, tmp_dev->dev, tmp_dev->size, tmp_dev->offset); + printk ("Block %ld out of bounds on dev %s size %d offset %d\n", + block, kdevname(tmp_dev->dev), tmp_dev->size, tmp_dev->offset); *rdev=tmp_dev->dev; *rsector=(block-(tmp_dev->offset)) << 1; diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index d077478b7c4c..2dd5c4e13e1b 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -28,7 +28,7 @@ int cdrom_open(struct inode *ip, struct file *fp); void cdrom_release(struct inode *ip, struct file *fp); int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg); -int cdrom_media_changed(dev_t dev); +int cdrom_media_changed(kdev_t dev); struct file_operations cdrom_fops = { @@ -107,11 +107,11 @@ int unregister_cdrom(int major, char *name) * is in their own interest: device control becomes a lot easier * this way. */ -int open_for_data(struct cdrom_device_ops *, int); +int open_for_data(struct cdrom_device_ops *, kdev_t); int cdrom_open(struct inode *ip, struct file *fp) { - dev_t dev = ip->i_rdev; + kdev_t dev = ip->i_rdev; struct cdrom_device_ops *cdo = cdromdevs[MAJOR(dev)]; int purpose = !!(fp->f_flags & O_NONBLOCK); @@ -126,7 +126,7 @@ int cdrom_open(struct inode *ip, struct file *fp) return open_for_data(cdo, dev); } -int open_for_data(struct cdrom_device_ops * cdo, int dev) +int open_for_data(struct cdrom_device_ops * cdo, kdev_t dev) { int ret; if (cdo->drive_status != NULL) { @@ -163,7 +163,7 @@ int open_for_data(struct cdrom_device_ops * cdo, int dev) /* Admittedly, the logic below could be performed in a nicer way. */ void cdrom_release(struct inode *ip, struct file *fp) { - dev_t dev = ip->i_rdev; + kdev_t dev = ip->i_rdev; struct cdrom_device_ops *cdo = cdromdevs[MAJOR(dev)]; if (cdo == NULL || MINOR(dev) >= cdo->minors) @@ -192,7 +192,7 @@ void cdrom_release(struct inode *ip, struct file *fp) * in the lower 16 bits, queue 1 in the higher 16 bits. */ -int media_changed(dev_t dev, int queue) +int media_changed(kdev_t dev, int queue) { unsigned int major = MAJOR(dev); unsigned int minor = MINOR(dev); @@ -212,7 +212,7 @@ int media_changed(dev_t dev, int queue) return ret; } -int cdrom_media_changed(dev_t dev) +int cdrom_media_changed(kdev_t dev) { struct cdrom_device_ops *cdo = cdromdevs[MAJOR(dev)]; if (cdo == NULL || MINOR(dev) >= cdo->minors) @@ -290,7 +290,7 @@ void sanitize_format(union cdrom_addr *addr, int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg) { - dev_t dev = ip->i_rdev; + kdev_t dev = ip->i_rdev; struct cdrom_device_ops *cdo = cdromdevs[MAJOR(dev)]; if (cdo == NULL || MINOR(dev) >= cdo->minors) diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c index 02153279343c..c823faf5f1fa 100644 --- a/drivers/cdrom/cm206.c +++ b/drivers/cdrom/cm206.c @@ -580,7 +580,7 @@ void get_disc_status(void) /* The new open. The real opening strategy is defined in cdrom.c. */ -static int cm206_open(dev_t dev, int purpose) +static int cm206_open(kdev_t dev, int purpose) { if (!cd->openfiles) { /* reset only first time */ cd->background=0; @@ -593,7 +593,7 @@ static int cm206_open(dev_t dev, int purpose) return 0; } -static void cm206_release(dev_t dev) +static void cm206_release(kdev_t dev) { if (cd->openfiles==1) { if (cd->background) { @@ -885,7 +885,7 @@ void get_toc_entry(struct cdrom_tocentry * ep) * upon success. Memory checking has been done by cdrom_ioctl(), the * calling function, as well as LBA/MSF sanitization. */ -int cm206_audio_ioctl(dev_t dev, unsigned int cmd, void * arg) +int cm206_audio_ioctl(kdev_t dev, unsigned int cmd, void * arg) { switch (cmd) { case CDROMREADTOCHDR: @@ -930,7 +930,7 @@ int cm206_audio_ioctl(dev_t dev, unsigned int cmd, void * arg) some driver statistics accessible through ioctl calls. */ -static int cm206_ioctl(dev_t dev, unsigned int cmd, unsigned long arg) +static int cm206_ioctl(kdev_t dev, unsigned int cmd, unsigned long arg) { switch (cmd) { #ifdef STATISTICS @@ -947,7 +947,7 @@ static int cm206_ioctl(dev_t dev, unsigned int cmd, unsigned long arg) } } -int cm206_media_changed(dev_t dev) +int cm206_media_changed(kdev_t dev) { if (cd != NULL) { int r; @@ -963,14 +963,14 @@ int cm206_media_changed(dev_t dev) the logic should be in cdrom.c */ /* returns number of times device is in use */ -int cm206_open_files(dev_t dev) +int cm206_open_files(kdev_t dev) { if (cd) return cd->openfiles; return -1; } /* controls tray movement */ -int cm206_tray_move(dev_t dev, int position) +int cm206_tray_move(kdev_t dev, int position) { if (position) { /* 1: eject */ type_0_command(c_open_tray,1); @@ -981,7 +981,7 @@ int cm206_tray_move(dev_t dev, int position) } /* gives current state of the drive */ -int cm206_drive_status(dev_t dev) +int cm206_drive_status(kdev_t dev) { get_drive_status(); if (cd->dsb & dsb_tray_not_closed) return CDS_TRAY_OPEN; @@ -991,7 +991,7 @@ int cm206_drive_status(dev_t dev) } /* gives current state of disc in drive */ -int cm206_disc_status(dev_t dev) +int cm206_disc_status(kdev_t dev) { uch xa; get_drive_status(); @@ -1009,7 +1009,7 @@ int cm206_disc_status(dev_t dev) } /* locks or unlocks door lock==1: lock; return 0 upon success */ -int cm206_lock_door(dev_t dev, int lock) +int cm206_lock_door(kdev_t dev, int lock) { uch command = (lock) ? c_lock_tray : c_unlock_tray; type_0_command(command, 1); /* wait and get dsb */ @@ -1020,7 +1020,7 @@ int cm206_lock_door(dev_t dev, int lock) /* Although a session start should be in LBA format, we return it in MSF format because it is slightly easier, and the new generic ioctl will take care of the necessary conversion. */ -int cm206_get_last_session(dev_t dev, struct cdrom_multisession * mssp) +int cm206_get_last_session(kdev_t dev, struct cdrom_multisession * mssp) { if (!FIRST_TRACK) get_disc_status(); if (mssp != NULL) { @@ -1038,7 +1038,7 @@ int cm206_get_last_session(dev_t dev, struct cdrom_multisession * mssp) return 0; } -int cm206_get_upc(dev_t dev, struct cdrom_mcn * mcn) +int cm206_get_upc(kdev_t dev, struct cdrom_mcn * mcn) { uch upc[10]; char * ret = mcn->medium_catalog_number; @@ -1054,7 +1054,7 @@ int cm206_get_upc(dev_t dev, struct cdrom_mcn * mcn) return 0; } -int cm206_reset(dev_t dev) +int cm206_reset(kdev_t dev) { stop_read(); reset_cm260(); diff --git a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c index 68daebacfe1e..84a791d92c0f 100644 --- a/drivers/cdrom/mcdx.c +++ b/drivers/cdrom/mcdx.c @@ -1,16 +1,7 @@ /* * The Mitsumi CDROM interface * Copyright (C) 1995 Heiko Schlittermann - * VERSION: 1.9 - * - ****************** H E L P ********************************* - * If you ever plan to update your CD ROM drive and perhaps - * want to sell or simply give away your Mitsumi FX-001[DS] - * -- Please, Please -- - * mail me (heiko@lotte.sax.de). When my last drive goes - * ballistic no more driver support will be available from me !!! - ************************************************************* - * + * VERSION: 2.2 * * 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 @@ -38,14 +29,14 @@ * Nils Faerber and Roger E. Wolff (extensively tested the LU portion) * Andreas Kies (testing the mysterious hang up's) * ... somebody forgotten? - * + * + * 2.1 1996/04/29 Marcin Dalecki + * Far too many bugfixes/changes to mention them all separately. + * 2.2 1996/05/06 Marcin Dalecki + * Mostly fixes to some silly bugs in the previous release :-). + * (Hi Michael Thimm! Thank's for lending me Your's double speed drive.) */ - - -#if RCS -static const char *mcdx_c_version - = "mcdx.c,v 1.2 1996/03/22 01:14:59 heiko Exp"; -#endif +#define VERSION "2.2" #include #include @@ -63,202 +54,152 @@ static const char *mcdx_c_version #include #include - #include #define MAJOR_NR MITSUMI_X_CDROM_MAJOR #include -/* for compatible parameter passing with "insmod" */ -#define mcdx_drive_map mcdx +/* + * for compatible parameter passing with "insmod" + */ +#define mcdx_drive_map mcdx #include -#ifndef HZ -#error HZ not defined -#endif - -/* CONSTANTS *******************************************************/ - -const int REQUEST_SIZE = 200; -const int DIRECT_SIZE = 200; -const unsigned long ACLOSE_INHIBIT = 800; /* 1/100 s of autoclose inhibit */ - -enum drivemodes { TOC, DATA, RAW, COOKED }; -enum datamodes { MODE0, MODE1, MODE2 }; -enum resetmodes { SOFT, HARD }; +#define REQUEST_SIZE 200 +#define DIRECT_SIZE 200 -const int SINGLE = 0x01; /* single speed drive (FX001S, LU) */ -const int DOUBLE = 0x02; /* double speed drive (FX001D, ..? */ -const int DOOR = 0x04; /* door locking capability */ -const int MULTI = 0x08; /* multi session capability */ +enum drivemodes { + TOC, DATA, RAW, COOKED +}; -const unsigned char READ1X = 0xc0; -const unsigned char READ2X = 0xc1; +#define MODE0 0x00 +#define MODE1 0x01 +#define MODE2 0x02 +#define DOOR_LOCK 0x01 +#define DOOR_UNLOCK 0x00 -/* DECLARATIONS ****************************************************/ -struct s_msf { - unsigned char minute; - unsigned char second; - unsigned char frame; -}; +/* + * Structs used to gather info reported by the drive. + */ struct s_subqcode { - unsigned char control; - unsigned char tno; - unsigned char index; - struct s_msf tt; - struct s_msf dt; + u_char adr:4; + u_char ctrl:4; + u_char tno; + u_char index; + struct cdrom_msf0 tt; + u_char dummy; /* padding for matching the returned struct */ + struct cdrom_msf0 dt; }; -struct s_diskinfo { - unsigned int n_first; - unsigned int n_last; - struct s_msf msf_leadout; - struct s_msf msf_first; -}; - struct s_multi { unsigned char multi; - struct s_msf msf_last; + struct cdrom_msf0 msf_last; }; -struct s_version { - unsigned char code; - unsigned char ver; +struct s_play { + struct cdrom_msf0 start; + struct cdrom_msf0 stop; }; -/* Per drive/controller stuff **************************************/ +/* + * Per drive/controller stuff. + */ struct s_drive_stuff { - /* waitqueues */ - struct wait_queue *busyq; - struct wait_queue *lockq; - struct wait_queue *sleepq; - - /* flags */ - volatile int introk; /* status of last irq operation */ - volatile int busy; /* drive performs an operation */ - volatile int lock; /* exclusive usage */ - int eject_sw; /* 1 - eject on last close (default 0) */ - int autoclose; /* 1 - close the door on open (default 1) */ - + struct wait_queue *busyq; + + /* flags */ + u_char introk:1; /* status of last irq operation */ + u_char busy:1; /* drive performs an operation */ + u_char eject_sw:1; /* 1 - eject on last close (default 0) */ + u_char autoclose:1; /* 1 - close the door on open (default 1) */ + u_char xxx:1; /* set if changed, reset while open */ + u_char xa:1; /* 1 if xa disk */ + u_char audio:1; /* 1 if audio disk */ + u_char eom:1; /* end of media reached during read request */ + + /* drives capabilities */ + u_char door:1; /* can close/lock tray */ + u_char multi_cap:1; /* multisession capable */ + u_char double_speed:1; /* double speed drive */ + /* cd infos */ - struct s_diskinfo di; + unsigned int n_first; + unsigned int n_last; + struct cdrom_msf0 msf_leadout; struct s_multi multi; - struct s_subqcode* toc; /* first entry of the toc array */ - struct s_subqcode start; - struct s_subqcode stop; - int xa; /* 1 if xa disk */ - int audio; /* 1 if audio disk */ - int audiostatus; + + struct s_subqcode *toc; /* first entry of the toc array */ + struct s_play resume; /* where to resume after pause */ + + int audiostatus; /* `buffer' control */ - volatile int valid; - volatile int pending; - volatile int off_direct; - volatile int off_requested; - - /* adds and odds */ - void* wreg_data; /* w data */ - void* wreg_reset; /* w hardware reset */ - void* wreg_hcon; /* w hardware conf */ - void* wreg_chn; /* w channel */ - void* rreg_data; /* r data */ - void* rreg_status; /* r status */ - - int irq; /* irq used by this drive */ - int minor; /* minor number of this drive */ - int present; /* drive present and its capabilities */ - unsigned char readcmd; /* read cmd depends on single/double speed */ - unsigned char playcmd; /* play should always be single speed */ - unsigned int xxx; /* set if changed, reset while open */ - unsigned int yyy; /* set if changed, reset by media_changed */ - unsigned long ejected; /* time we called the eject function */ - int users; /* keeps track of open/close */ - int lastsector; /* last block accessible */ - int status; /* last operation's error / status */ - int readerrs; /* # of blocks read w/o error */ + unsigned int valid:1; + int pending; + int off_direct; + int off_requested; + + int irq; /* irq used by this drive */ + unsigned int base; /* base for all registers of the drive */ + int users; /* keeps track of open/close */ + int lastsector; /* last accessible blocks */ }; +/* + * Macros for accessing interface registers + */ -/* Prototypes ******************************************************/ - -/* The following prototypes are already declared elsewhere. They are - repeated here to show what's going on. And to sense, if they're - changed elsewhere. */ +#define DATA_REG (stuffp->base) +#define RESET_REG (stuffp->base+1) +#define STAT_REG (stuffp->base+1) +#define CHAN_REG (stuffp->base+3) -/* declared in blk.h */ +/* + * declared in blk.h + */ int mcdx_init(void); void do_mcdx_request(void); -int check_mcdx_media_change(kdev_t); -/* already declared in init/main */ +/* + * already declared in init/main + */ void mcdx_setup(char *, int *); -/* Indirect exported functions. These functions are exported by their - addresses, such as mcdx_open and mcdx_close in the - structure fops. */ - -/* ??? exported by the mcdx_sigaction struct */ -static void mcdx_intr(int, void *, struct pt_regs*); - -/* exported by file_ops */ -static int mcdx_open(struct inode*, struct file*); -static void mcdx_close(struct inode*, struct file*); -static int mcdx_ioctl(struct inode*, struct file*, unsigned int, unsigned long); - -/* misc internal support functions */ -static void log2msf(unsigned int, struct s_msf*); -static unsigned int msf2log(const struct s_msf*); -static unsigned int uint2bcd(unsigned int); -static unsigned int bcd2uint(unsigned char); -#if MCDX_DEBUG -static void TRACE((int level, const char* fmt, ...)); -#endif -static void warn(const char* fmt, ...); -static char *port(int*); -static int irq(int*); -static void mcdx_delay(struct s_drive_stuff*, long jifs); -static int mcdx_transfer(struct s_drive_stuff*, char* buf, int sector, int nr_sectors); -static int mcdx_xfer(struct s_drive_stuff*, char* buf, int sector, int nr_sectors); - -static int mcdx_config(struct s_drive_stuff*, int); -static int mcdx_closedoor(struct s_drive_stuff*, int); -static int mcdx_requestversion(struct s_drive_stuff*, struct s_version*, int); -static int mcdx_lockdoor(struct s_drive_stuff*, int, int); -static int mcdx_stop(struct s_drive_stuff*, int); -static int mcdx_hold(struct s_drive_stuff*, int); -static int mcdx_reset(struct s_drive_stuff*, enum resetmodes, int); -static int mcdx_eject(struct s_drive_stuff*, int); -static int mcdx_setdrivemode(struct s_drive_stuff*, enum drivemodes, int); -static int mcdx_setdatamode(struct s_drive_stuff*, enum datamodes, int); -static int mcdx_requestsubqcode(struct s_drive_stuff*, struct s_subqcode*, int); -static int mcdx_requestmultidiskinfo(struct s_drive_stuff*, struct s_multi*, int); -static int mcdx_requesttocdata(struct s_drive_stuff*, struct s_diskinfo*, int); -static int mcdx_getstatus(struct s_drive_stuff*, int); -static int mcdx_getval(struct s_drive_stuff*, int to, int delay, char*); -static int mcdx_talk(struct s_drive_stuff*, - const unsigned char* cmd, size_t, - void *buffer, size_t size, - unsigned int timeout, int); -static int mcdx_readtoc(struct s_drive_stuff*); -static int mcdx_playtrk(struct s_drive_stuff*, const struct cdrom_ti*); -static int mcdx_playmsf(struct s_drive_stuff*, const struct cdrom_msf*); -static int mcdx_setattentuator(struct s_drive_stuff*, struct cdrom_volctrl*, int); - -/* static variables ************************************************/ +/* + * Indirect exported functions. These functions are exported by their + * addresses, such as mcdx_open and mcdx_close in the + * structure fops. + */ + +/* + * ??? exported by the mcdx_sigaction struct + */ +static void mcdx_intr(int, void *, struct pt_regs *); + +/* + * exported by file_ops + */ +static int mcdx_open(struct inode *, struct file *); +static void mcdx_close(struct inode *, struct file *); +static int mcdx_ioctl(struct inode *, struct file *, + unsigned int, unsigned long); +static int mcdx_media_change(kdev_t); + static int mcdx_blocksizes[MCDX_NDRIVES]; static int mcdx_drive_map[][2] = MCDX_DRIVEMAP; -static struct s_drive_stuff* mcdx_stuffp[MCDX_NDRIVES]; -static struct s_drive_stuff* mcdx_irq_map[16] = - {0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0}; +static struct s_drive_stuff *mcdx_stuffp[MCDX_NDRIVES]; +static struct s_drive_stuff *mcdx_irq_map[16] = +{0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}; -static struct file_operations mcdx_fops = { +static struct file_operations mcdx_fops = +{ NULL, /* lseek - use kernel default */ block_read, /* read - general block-dev read */ - block_write, /* write - general block-dev write */ + block_write, /* write - general block-dev write */ NULL, /* no readdir */ NULL, /* no select */ mcdx_ioctl, /* ioctl() */ @@ -266,1591 +207,1191 @@ static struct file_operations mcdx_fops = { mcdx_open, /* open() */ mcdx_close, /* close() */ NULL, /* fsync */ - NULL, /* fasync */ - check_mcdx_media_change, /* media_change */ - NULL /* revalidate */ + NULL, /* fasync */ + mcdx_media_change, /* media_change */ + NULL /* revalidate */ }; -/* KERNEL INTERFACE FUNCTIONS **************************************/ - -static int -mcdx_ioctl( - struct inode* ip, struct file* fp, - unsigned int cmd, unsigned long arg) -{ - struct s_drive_stuff *stuffp = mcdx_stuffp[MINOR(ip->i_rdev)]; - - if (!stuffp->present) return -ENXIO; - if (!ip) return -EINVAL; - - switch (cmd) { - case CDROMSTART: { - TRACE((IOCTL, "ioctl() START\n")); - return 0; - } - - case CDROMSTOP: { - TRACE((IOCTL, "ioctl() STOP\n")); - stuffp->audiostatus = CDROM_AUDIO_INVALID; - if (-1 == mcdx_stop(stuffp, 1)) - return -EIO; - return 0; - } +/* + * Misc number converters + */ - case CDROMPLAYTRKIND: { - int ans; - struct cdrom_ti ti; +static unsigned int bcd2uint(unsigned char c) +{ + return (c >> 4) * 10 + (c & 0x0f); +} - TRACE((IOCTL, "ioctl() PLAYTRKIND\n")); - if ((ans = verify_area(VERIFY_READ, (void*) arg, sizeof(ti)))) - return ans; - memcpy_fromfs(&ti, (void*) arg, sizeof(ti)); - if ((ti.cdti_trk0 < stuffp->di.n_first) - || (ti.cdti_trk0 > stuffp->di.n_last) - || (ti.cdti_trk1 < stuffp->di.n_first)) - return -EINVAL; - if (ti.cdti_trk1 > stuffp->di.n_last) ti.cdti_trk1 = stuffp->di.n_last; - TRACE((PLAYTRK, "ioctl() track %d to %d\n", ti.cdti_trk0, ti.cdti_trk1)); +static unsigned int uint2bcd(unsigned int ival) +{ + return ((ival / 10) << 4) | (ival % 10); +} - return mcdx_playtrk(stuffp, &ti); - } +static unsigned int msf2log(const struct cdrom_msf0 *pmsf) +{ + return bcd2uint(pmsf->frame) + + bcd2uint(pmsf->second) * 75 + + bcd2uint(pmsf->minute) * 4500 + - CD_BLOCK_OFFSET; +} - case CDROMPLAYMSF: { - int ans; - struct cdrom_msf msf; +/* + * Access to elements of the mcdx_drive_map members + */ +static inline unsigned int port(int *ip) +{ + return (unsigned int) ip[0]; +} - TRACE((IOCTL, "ioctl() PLAYMSF\n")); +static inline int irq(int *ip) +{ + return ip[1]; +} - if ((stuffp->audiostatus == CDROM_AUDIO_PLAY) - && (-1 == mcdx_hold(stuffp, 1))) return -EIO; - if ((ans = verify_area( - VERIFY_READ, (void*) arg, sizeof(struct cdrom_msf)))) - return ans; +/* + * Low level hardware related functions. + */ - memcpy_fromfs(&msf, (void*) arg, sizeof msf); +/* + * Return drives status in case of success, -1 otherwise. + * + * First we try to get the status information quickly. + * Then we sleep repeatedly for about 10 usecs, befor we finally reach the + * timeout. For this reason this command must be called with the drive beeing + * locked! + */ +static int get_status(struct s_drive_stuff *stuffp, + unsigned long timeout) +{ + unsigned long bang = jiffies + 2; + timeout += jiffies; - msf.cdmsf_min0 = uint2bcd(msf.cdmsf_min0); - msf.cdmsf_sec0 = uint2bcd(msf.cdmsf_sec0); - msf.cdmsf_frame0 = uint2bcd(msf.cdmsf_frame0); + do { + if (!(inb(STAT_REG) & MCDX_RBIT_STEN)) { + return (inb(DATA_REG) & 0xff); + } + } while (jiffies < bang); - msf.cdmsf_min1 = uint2bcd(msf.cdmsf_min1); - msf.cdmsf_sec1 = uint2bcd(msf.cdmsf_sec1); - msf.cdmsf_frame1 = uint2bcd(msf.cdmsf_frame1); + while (inb(STAT_REG) & MCDX_RBIT_STEN) { + if (jiffies > timeout) + return -1; + current->state = TASK_INTERRUPTIBLE; + current->timeout = jiffies + HZ / 2; + schedule(); + } + return (inb(DATA_REG) & 0xff); +} - return mcdx_playmsf(stuffp, &msf); - } +/* Send a command to the drive, wait for the result. + * returns -1 on timeout, drive status otherwise. + * If buffer is not zero, the result (length size) is stored there. + * If buffer is zero the size should be the number of bytes to read + * from the drive. These bytes are discarded. + */ +static int talk(struct s_drive_stuff *stuffp, + const unsigned char command, + void *pars, size_t parslen, + void *buffer, size_t size, + unsigned int timeout) +{ + int st; - case CDROMRESUME: { - TRACE((IOCTL, "ioctl() RESUME\n")); - return mcdx_playtrk(stuffp, NULL); - } + while (stuffp->busy) { + interruptible_sleep_on(&stuffp->busyq); + } + stuffp->busy = 1; + stuffp->valid = 0; + outb(command, DATA_REG); + if (parslen) + outsb(DATA_REG, pars, parslen); + + if (-1 == (st = get_status(stuffp, timeout))) { + goto end_talk; + } + if (st & MCDX_RBIT_CMDERR) { + printk(KERN_ERR MCDX ": error in command 0x%2x\n", command); + st = -1; + goto end_talk; + } + /* audio status? */ + if (stuffp->audiostatus == CDROM_AUDIO_INVALID) { + stuffp->audiostatus = + (st & MCDX_RBIT_AUDIOBS) ? CDROM_AUDIO_PLAY : CDROM_AUDIO_NO_STATUS; + } else if (stuffp->audiostatus == CDROM_AUDIO_PLAY + && !(st & MCDX_RBIT_AUDIOBS)) { + stuffp->audiostatus = CDROM_AUDIO_COMPLETED; + } + /* media change? */ + if (st & MCDX_RBIT_CHANGED) { + stuffp->xxx = 1; + if (stuffp->toc) { + kfree(stuffp->toc); + stuffp->toc = 0; + } + } + /* now actually get the data */ + while (size--) { + if (-1 == (st = get_status(stuffp, timeout))) { + break; + } + *((char *) buffer) = st; + buffer++; + } - case CDROMREADTOCENTRY: { - struct cdrom_tocentry entry; - struct s_subqcode *tp = NULL; - int ans; + end_talk: + stuffp->busy = 0; + wake_up_interruptible(&stuffp->busyq); - TRACE((IOCTL, "ioctl() READTOCENTRY\n")); + return st; +} - if (-1 == mcdx_readtoc(stuffp)) return -1; +static int issue_command(struct s_drive_stuff *stuffp, + unsigned char command, + unsigned int timeout) +{ + return talk(stuffp, command, 0, 0, NULL, 0, timeout); +} - if ((ans = verify_area(VERIFY_READ, (void *) arg, sizeof(entry)))) return ans; - memcpy_fromfs(&entry, (void *) arg, sizeof(entry)); +static inline int set_command(struct s_drive_stuff *stuffp, + const unsigned char command, + void *pars, size_t parlen, + unsigned int timeout) +{ + return talk(stuffp, command, pars, parlen, NULL, 0, timeout); +} - if (entry.cdte_track == CDROM_LEADOUT) - tp = &stuffp->toc[stuffp->di.n_last - stuffp->di.n_first + 1]; - else if (entry.cdte_track > stuffp->di.n_last - || entry.cdte_track < stuffp->di.n_first) return -EINVAL; - else tp = &stuffp->toc[entry.cdte_track - stuffp->di.n_first]; +static inline int get_command(struct s_drive_stuff *stuffp, + const unsigned char command, + void *buffer, size_t size, + unsigned int timeout) +{ + return talk(stuffp, command, NULL, 0, buffer, size, timeout); +} - if (NULL == tp) WARN(("FATAL.\n")); +static int request_subq_code(struct s_drive_stuff *stuffp, + struct s_subqcode *sub) +{ + return get_command(stuffp, MCDX_CMD_GET_SUBQ_CODE, + sub, sizeof(struct s_subqcode), 2 * HZ); +} - entry.cdte_adr = tp->control; - entry.cdte_ctrl = tp->control >> 4; +static int request_toc_data(struct s_drive_stuff *stuffp) +{ + char buf[8]; + int ans; - if (entry.cdte_format == CDROM_MSF) { - entry.cdte_addr.msf.minute = bcd2uint(tp->dt.minute); - entry.cdte_addr.msf.second = bcd2uint(tp->dt.second); - entry.cdte_addr.msf.frame = bcd2uint(tp->dt.frame); - } else if (entry.cdte_format == CDROM_LBA) - entry.cdte_addr.lba = msf2log(&tp->dt); - else return -EINVAL; + ans = get_command(stuffp, MCDX_CMD_GET_TOC, buf, sizeof(buf), 2 * HZ); + if (ans == -1) { + stuffp->n_first = 0; + stuffp->n_last = 0; + } else { + stuffp->n_first = bcd2uint(buf[0]); + stuffp->n_last = bcd2uint(buf[1]); + memcpy(&(stuffp->msf_leadout), buf + 2, 3); + } + return ans; +} - if ((ans = verify_area(VERIFY_WRITE, (void*) arg, sizeof(entry)))) return ans; - memcpy_tofs((void*) arg, &entry, sizeof(entry)); +static int set_drive_mode(struct s_drive_stuff *stuffp, enum drivemodes mode) +{ + char value; + if (-1 == get_command(stuffp, MCDX_CMD_GET_DRIVE_MODE, + &value, 1, 5 * HZ)) + return -1; + switch (mode) { + case TOC: + value |= 0x04; + break; + case DATA: + value &= ~0x04; + break; + case RAW: + value |= 0x40; + break; + case COOKED: + value &= ~0x40; + break; + default: + break; + } + return set_command(stuffp, MCDX_CMD_SET_DRIVE_MODE, &value, 1, 5 * HZ); +} - return 0; - } +static int config_drive(struct s_drive_stuff *stuffp) +{ + unsigned char buf[2]; + buf[0] = 0x10; /* irq enable */ + buf[1] = 0x05; /* pre, err irq enable */ - case CDROMSUBCHNL: { - int ans; - struct cdrom_subchnl sub; - struct s_subqcode q; - - TRACE((IOCTL, "ioctl() SUBCHNL\n")); - - if ((ans = verify_area(VERIFY_READ, - (void*) arg, sizeof(sub)))) return ans; - - memcpy_fromfs(&sub, (void*) arg, sizeof(sub)); - - if (-1 == mcdx_requestsubqcode(stuffp, &q, 2)) return -EIO; - - TRACE((SUBCHNL, "audiostatus: %x\n", stuffp->audiostatus)); - sub.cdsc_audiostatus = stuffp->audiostatus; - sub.cdsc_adr = q.control; - sub.cdsc_ctrl = q.control >> 4; - sub.cdsc_trk = bcd2uint(q.tno); - sub.cdsc_ind = bcd2uint(q.index); - - TRACE((SUBCHNL, "trk %d, ind %d\n", - sub.cdsc_trk, sub.cdsc_ind)); - - if (sub.cdsc_format == CDROM_LBA) { - sub.cdsc_absaddr.lba = msf2log(&q.dt); - sub.cdsc_reladdr.lba = msf2log(&q.tt); - TRACE((SUBCHNL, "lba: abs %d, rel %d\n", - sub.cdsc_absaddr.lba, - sub.cdsc_reladdr.lba)); - } else if (sub.cdsc_format == CDROM_MSF) { - sub.cdsc_absaddr.msf.minute = bcd2uint(q.dt.minute); - sub.cdsc_absaddr.msf.second = bcd2uint(q.dt.second); - sub.cdsc_absaddr.msf.frame = bcd2uint(q.dt.frame); - sub.cdsc_reladdr.msf.minute = bcd2uint(q.tt.minute); - sub.cdsc_reladdr.msf.second = bcd2uint(q.tt.second); - sub.cdsc_reladdr.msf.frame = bcd2uint(q.tt.frame); - TRACE((SUBCHNL, - "msf: abs %02d:%02d:%02d, rel %02d:%02d:%02d\n", - sub.cdsc_absaddr.msf.minute, - sub.cdsc_absaddr.msf.second, - sub.cdsc_absaddr.msf.frame, - sub.cdsc_reladdr.msf.minute, - sub.cdsc_reladdr.msf.second, - sub.cdsc_reladdr.msf.frame)); - } else return -EINVAL; - - if ((ans = verify_area(VERIFY_WRITE, (void*) arg, sizeof(sub)))) - return ans; - memcpy_tofs((void*) arg, &sub, sizeof(sub)); + if (-1 == set_command(stuffp, MCDX_CMD_CONFIG, buf, + sizeof(buf), 1 * HZ)) + return -1; - return 0; - } + buf[0] = 0x02; /* dma select */ + buf[1] = 0x00; /* no dma */ - case CDROMREADTOCHDR: { - struct cdrom_tochdr toc; - int ans; + return set_command(stuffp, MCDX_CMD_CONFIG, buf, sizeof(buf), 1 * HZ); +} - TRACE((IOCTL, "ioctl() READTOCHDR\n")); - if ((ans = verify_area(VERIFY_WRITE, (void*) arg, sizeof toc))) - return ans; - toc.cdth_trk0 = stuffp->di.n_first; - toc.cdth_trk1 = stuffp->di.n_last; - memcpy_tofs((void*) arg, &toc, sizeof toc); - TRACE((TOCHDR, "ioctl() track0 = %d, track1 = %d\n", - stuffp->di.n_first, stuffp->di.n_last)); - return 0; - } +/* + * Read the toc entries from the CD. + * Return: -1 on failure, else 0 + */ +int read_toc(struct s_drive_stuff *stuffp) +{ + int trk; + int retries; - case CDROMPAUSE: { - TRACE((IOCTL, "ioctl() PAUSE\n")); - if (stuffp->audiostatus != CDROM_AUDIO_PLAY) return -EINVAL; - if (-1 == mcdx_stop(stuffp, 1)) return -EIO; - stuffp->audiostatus = CDROM_AUDIO_PAUSED; - if (-1 == mcdx_requestsubqcode(stuffp, &stuffp->start, 1)) - return -EIO; - return 0; - } + if (stuffp->toc) + return 0; + if (-1 == issue_command(stuffp, MCDX_CMD_HOLD, 2 * HZ)) + return -1; + if (-1 == set_drive_mode(stuffp, TOC)) + return -EIO; - case CDROMMULTISESSION: { - int ans; - struct cdrom_multisession ms; - TRACE((IOCTL, "ioctl() MULTISESSION\n")); - if (0 != (ans = verify_area(VERIFY_READ, (void*) arg, - sizeof(struct cdrom_multisession)))) - return ans; - - memcpy_fromfs(&ms, (void*) arg, sizeof(struct cdrom_multisession)); - if (ms.addr_format == CDROM_MSF) { - ms.addr.msf.minute = bcd2uint(stuffp->multi.msf_last.minute); - ms.addr.msf.second = bcd2uint(stuffp->multi.msf_last.second); - ms.addr.msf.frame = bcd2uint(stuffp->multi.msf_last.frame); - } else if (ms.addr_format == CDROM_LBA) - ms.addr.lba = msf2log(&stuffp->multi.msf_last); - else - return -EINVAL; - ms.xa_flag = !!stuffp->multi.multi; - - if (0 != (ans = verify_area(VERIFY_WRITE, (void*) arg, - sizeof(struct cdrom_multisession)))) - return ans; - - memcpy_tofs((void*) arg, &ms, sizeof(struct cdrom_multisession)); - if (ms.addr_format == CDROM_MSF) - TRACE((MS, - "ioctl() (%d, %02x:%02x.%02x [%02x:%02x.%02x])\n", - ms.xa_flag, - ms.addr.msf.minute, - ms.addr.msf.second, - ms.addr.msf.frame, - stuffp->multi.msf_last.minute, - stuffp->multi.msf_last.second, - stuffp->multi.msf_last.frame)); - else - { - TRACE((MS, - "ioctl() (%d, 0x%08x [%02x:%02x.%02x])\n", - ms.xa_flag, - ms.addr.lba, - stuffp->multi.msf_last.minute, - stuffp->multi.msf_last.second, - stuffp->multi.msf_last.frame)); - } - return 0; + /* all seems to be ok so far ... malloc */ + stuffp->toc = kmalloc(sizeof(struct s_subqcode) * + (stuffp->n_last - stuffp->n_first + 2), GFP_KERNEL); + if (!stuffp->toc) { + printk(KERN_ERR MCDX ": malloc for toc failed\n"); + set_drive_mode(stuffp, DATA); + return -EIO; + } + /* now read actually the index tarcks */ + for (trk = 0; + trk < (stuffp->n_last - stuffp->n_first + 1); + trk++) + stuffp->toc[trk].index = 0; + + for (retries = 300; retries; retries--) { /* why 300? */ + struct s_subqcode q; + unsigned int idx; + + if (-1 == request_subq_code(stuffp, &q)) { + set_drive_mode(stuffp, DATA); + return -EIO; } - - case CDROMEJECT: { - TRACE((IOCTL, "ioctl() EJECT\n")); - if (stuffp->users > 1) return -EBUSY; - if (-1 == mcdx_eject(stuffp, 1)) return -EIO; - return 0; + idx = bcd2uint(q.index); + + if ((idx > 0) + && (idx <= stuffp->n_last) + && (q.tno == 0) + && (stuffp->toc[idx - stuffp->n_first].index == 0)) { + stuffp->toc[idx - stuffp->n_first] = q; + trk--; } + if (trk == 0) + break; + } + memset(&stuffp->toc[stuffp->n_last - stuffp->n_first + 1], + 0, sizeof(stuffp->toc[0])); + stuffp->toc[stuffp->n_last - stuffp->n_first + 1].dt + = stuffp->msf_leadout; - case CDROMEJECT_SW: { - stuffp->eject_sw = arg; - return 0; - } - - case CDROMVOLCTRL: { - int ans; - struct cdrom_volctrl volctrl; + /* unset toc mode */ + if (-1 == set_drive_mode(stuffp, DATA)) + return -EIO; - TRACE((IOCTL, "ioctl() VOLCTRL\n")); - if ((ans = verify_area( - VERIFY_READ, - (void*) arg, - sizeof(volctrl)))) - return ans; + return 0; +} - memcpy_fromfs(&volctrl, (char *) arg, sizeof(volctrl)); - return mcdx_setattentuator(stuffp, &volctrl, 1); - } +/* + * Return 0 on success, error value -1 otherwise. + */ +static int play_track(struct s_drive_stuff *stuffp, const struct cdrom_ti *ti) +{ + struct s_play times; - default: - WARN(("ioctl(): unknown request 0x%04x\n", cmd)); - return -EINVAL; + if (ti) { + if (-1 == read_toc(stuffp)) { + stuffp->audiostatus = CDROM_AUDIO_ERROR; + return -EIO; + } + times.start = stuffp->toc[ti->cdti_trk0 - stuffp->n_first].dt; + times.stop = stuffp->resume.stop = + stuffp->toc[ti->cdti_trk1 - stuffp->n_first + 1].dt; + } else { + times = stuffp->resume; + } + if (-1 == set_command(stuffp, MCDX_CMD_PLAY, + ×, sizeof(times), 5 * HZ)) { + printk(KERN_WARNING MCDX ": play track timeout\n"); + stuffp->audiostatus = CDROM_AUDIO_ERROR; + return -EIO; } + stuffp->audiostatus = CDROM_AUDIO_PLAY; + + return 0; } -void do_mcdx_request() +static int lock_door(struct s_drive_stuff *stuffp, u_char lock) { - int dev; - struct s_drive_stuff *stuffp; - - again: - - TRACE((REQUEST, "do_request()\n")); + if (stuffp->door) + return set_command(stuffp, MCDX_CMD_LOCK_DOOR, + &lock, sizeof(lock), 5 * HZ); + return 0; +} /* + * KERNEL INTERFACE FUNCTIONS + */ +static int mcdx_ioctl(struct inode *ip, struct file *fp, + unsigned int command, unsigned long arg) +{ + int ans; + struct cdrom_ti ti; + struct cdrom_msf msf; + struct cdrom_tocentry entry; + struct s_subqcode *tp = NULL; + struct cdrom_subchnl sub; + struct s_subqcode q; + struct cdrom_tochdr toc; + struct cdrom_multisession ms; + struct cdrom_volctrl volctrl; + struct s_drive_stuff *stuffp = mcdx_stuffp[MINOR(ip->i_rdev)]; - if ((CURRENT == NULL) || (CURRENT->rq_status == RQ_INACTIVE)) { - TRACE((REQUEST, "do_request() done\n")); - return; + MCDX_TRACE_IOCTL(("mcdx_ioctl():\n")); + + if (!stuffp) + return -ENXIO; + if (!ip) + return -EINVAL; + + /* + * Update disk information, when necessary. + * This part will only work, when the new disk is of the same type as + * the one which was previousley there, esp. also for audio diks. + * This doesn't hurt us, since otherwise the mouting/unmounting scheme + * will ensure correct operation. + */ + if (stuffp->xxx) { /* disk changed */ + if ((-1 == request_toc_data(stuffp)) || + (-1 == read_toc(stuffp))) + return -EIO; + stuffp->xxx = 0; } + switch (command) { + case CDROMSTART: /* spin up the drive */ + MCDX_TRACE_IOCTL(("CDROMSTART\n")); + /* Don't think we can do this. Even if we could, + * I think the drive times out and stops after a while + * anyway. For now, ignore it. + */ + return 0; - stuffp = mcdx_stuffp[MINOR(CURRENT->rq_dev)]; - TRACE((REQUEST, "do_request() stuffp = %p\n", stuffp)); + case CDROMSTOP: + MCDX_TRACE_IOCTL(("CDROMSTOP\n")); + stuffp->audiostatus = CDROM_AUDIO_INVALID; + if (-1 == issue_command(stuffp, MCDX_CMD_STOP, 2 * HZ)) + return -EIO; + return 0; - INIT_REQUEST; - dev = MINOR(CURRENT->rq_dev); + case CDROMPLAYTRKIND: + MCDX_TRACE_IOCTL(("CDROMPLAYTRKIND\n")); + + if ((ans = verify_area(VERIFY_READ, (void *) arg, sizeof(ti)))) + return ans; + memcpy_fromfs(&ti, (void *) arg, sizeof(ti)); + if ((ti.cdti_trk0 < stuffp->n_first) + || (ti.cdti_trk0 > stuffp->n_last) + || (ti.cdti_trk1 < stuffp->n_first)) + return -EINVAL; + if (ti.cdti_trk1 > stuffp->n_last) + ti.cdti_trk1 = stuffp->n_last; + return play_track(stuffp, &ti); + + case CDROMPLAYMSF: + MCDX_TRACE_IOCTL(("CDROMPLAYMSF ")); + + if ((ans = verify_area(VERIFY_READ, (void *) arg, + sizeof(struct cdrom_msf)))) + return ans; + memcpy_fromfs(&msf, (void *) arg, sizeof msf); + msf.cdmsf_min0 = uint2bcd(msf.cdmsf_min0); + msf.cdmsf_sec0 = uint2bcd(msf.cdmsf_sec0); + msf.cdmsf_frame0 = uint2bcd(msf.cdmsf_frame0); + msf.cdmsf_min1 = uint2bcd(msf.cdmsf_min1); + msf.cdmsf_sec1 = uint2bcd(msf.cdmsf_sec1); + msf.cdmsf_frame1 = uint2bcd(msf.cdmsf_frame1); + stuffp->resume.stop.minute = msf.cdmsf_min1; + stuffp->resume.stop.second = msf.cdmsf_sec1; + stuffp->resume.stop.frame = msf.cdmsf_frame1; + if (-1 == set_command(stuffp, MCDX_CMD_PLAY, + &msf, sizeof(msf), 3 * HZ)) { + return -1; + } + stuffp->audiostatus = CDROM_AUDIO_PLAY; + return 0; - if ((dev < 0) || (dev >= MCDX_NDRIVES) || (!stuffp->present)) { - WARN(("do_request(): bad device: %s\n", - kdevname(CURRENT->rq_dev))); - end_request(0); - goto again; - } + case CDROMPAUSE: + MCDX_TRACE_IOCTL(("CDROMPAUSE\n")); - if (stuffp->audio) { - WARN(("do_request() attempt to read from audio cd\n")); - end_request(0); - goto again; - } + if (stuffp->audiostatus != CDROM_AUDIO_PLAY) + return -EINVAL; - switch (CURRENT->cmd) { - case WRITE: - WARN(("do_request(): attempt to write to cd!!\n")); - end_request(0); - break; - - case READ: - stuffp->status = 0; - while (CURRENT->nr_sectors) { - int i; - - if (-1 == (i = mcdx_transfer( - stuffp, - CURRENT->buffer, - CURRENT->sector, - CURRENT->nr_sectors))) { - /*INFO(("do_request() read error\n"));*/ - xwarn("do_request() read error\n"); - if (stuffp->status & MCDX_ST_EOM) { - CURRENT->sector += CURRENT->nr_sectors; - CURRENT->nr_sectors = 0; - } - invalidate_buffers(CURRENT->rq_dev); - end_request(0); - goto again; - } - CURRENT->sector += i; - CURRENT->nr_sectors -= i; - CURRENT->buffer += (i * 512); - - } - - end_request(1); - break; - - default: - panic(MCDX "do_request: unknown command.\n"); - break; - } - - goto again; -} + if (-1 == issue_command(stuffp, MCDX_CMD_STOP, 2 * HZ)) + return -EIO; + if (-1 == request_subq_code(stuffp, &q)) { + stuffp->audiostatus = CDROM_AUDIO_NO_STATUS; + return 0; + } + stuffp->resume.start = q.dt; + stuffp->audiostatus = CDROM_AUDIO_PAUSED; + return 0; -static int -mcdx_open(struct inode *ip, struct file *fp) -/* actions done on open: - * 1) get the drives status */ -{ - struct s_drive_stuff *stuffp; + case CDROMRESUME: + MCDX_TRACE_IOCTL(("CDROMRESUME\n")); - TRACE((OPENCLOSE, "open()\n")); - stuffp = mcdx_stuffp[MINOR(ip->i_rdev)]; - if (!stuffp->present) return -ENXIO; + if (stuffp->audiostatus != CDROM_AUDIO_PAUSED) + return -EINVAL; + return play_track(stuffp, NULL); + case CDROMREADTOCENTRY: + MCDX_TRACE_IOCTL(("CDROMREADTOCENTRY\n")); - /* this is only done to test if the drive talks with us */ - if (-1 == mcdx_getstatus(stuffp, 1)) return -EIO; + if (-1 == read_toc(stuffp)) + return -1; + if ((ans = verify_area(VERIFY_READ, (void *) arg, sizeof(entry)))) + return ans; + memcpy_fromfs(&entry, (void *) arg, sizeof(entry)); + + if (entry.cdte_track == CDROM_LEADOUT) + tp = &stuffp->toc[stuffp->n_last - stuffp->n_first + 1]; + else if (entry.cdte_track > stuffp->n_last + || entry.cdte_track < stuffp->n_first) + return -EINVAL; + else + tp = &stuffp->toc[entry.cdte_track - stuffp->n_first]; + + if (NULL == tp) + printk(KERN_ERR MCDX ": FATAL.\n"); + + entry.cdte_adr = tp->adr; + entry.cdte_ctrl = tp->ctrl; + + if (entry.cdte_format == CDROM_MSF) { + entry.cdte_addr.msf.minute = bcd2uint(tp->dt.minute); + entry.cdte_addr.msf.second = bcd2uint(tp->dt.second); + entry.cdte_addr.msf.frame = bcd2uint(tp->dt.frame); + } else if (entry.cdte_format == CDROM_LBA) + entry.cdte_addr.lba = msf2log(&tp->dt); + else + return -EINVAL; + + if ((ans = verify_area(VERIFY_WRITE, (void *) arg, sizeof(entry)))) + return ans; + memcpy_tofs((void *) arg, &entry, sizeof(entry)); - /* close the door, if necessary (get the door information - from the hardware status register). - If the last eject is too recent, an autoclose wouldn't probably - be what we want ..., if we can't read the CD after an autoclose - no further autocloses will be tried */ - if (inb((unsigned int) stuffp->rreg_status) & MCDX_RBIT_DOOR) { - if (jiffies - stuffp->ejected < ACLOSE_INHIBIT) return -EIO; - if (stuffp->autoclose) mcdx_closedoor(stuffp, 1); - else return -EIO; - } - - /* if the media changed we will have to do a little more */ - if (stuffp->xxx) { + return 0; - TRACE((OPENCLOSE, "open() media changed\n")); - /* but wait - the time of media change will be set at the - very last of this block - it seems, some of the following - talk() will detect a media change ... (I think, config() - is the reason. */ + case CDROMSUBCHNL: + MCDX_TRACE_IOCTL(("CDROMSUBCHNL\n")); - stuffp->audiostatus = CDROM_AUDIO_INVALID; + if ((ans = verify_area(VERIFY_READ, + (void *) arg, sizeof(sub)))) + return ans; - /* get the multisession information */ - TRACE((OPENCLOSE, "open() Request multisession info\n")); - if (-1 == mcdx_requestmultidiskinfo( - stuffp, &stuffp->multi, 6)) { - INFO(("No multidiskinfo\n")); - stuffp->autoclose = 0; - } else { - /* we succeeded, so on next open(2) we could try auto close - again */ - stuffp->autoclose = 1; - -#if !MCDX_QUIET - if (stuffp->multi.multi > 2) - INFO(("open() unknown multisession value (%d)\n", - stuffp->multi.multi)); -#endif + memcpy_fromfs(&sub, (void *) arg, sizeof(sub)); - /* multisession ? */ - if (!stuffp->multi.multi) - stuffp->multi.msf_last.second = 2; + if (-1 == request_subq_code(stuffp, &q)) + return -EIO; - TRACE((OPENCLOSE, "open() MS: %d, last @ %02x:%02x.%02x\n", - stuffp->multi.multi, - stuffp->multi.msf_last.minute, - stuffp->multi.msf_last.second, - stuffp->multi.msf_last.frame)); + sub.cdsc_audiostatus = stuffp->audiostatus; + sub.cdsc_adr = q.adr; + sub.cdsc_ctrl = q.ctrl; + sub.cdsc_trk = bcd2uint(q.tno); + sub.cdsc_ind = bcd2uint(q.index); + + if (sub.cdsc_format == CDROM_LBA) { + sub.cdsc_absaddr.lba = msf2log(&q.dt); + sub.cdsc_reladdr.lba = msf2log(&q.tt); + } else if (sub.cdsc_format == CDROM_MSF) { + sub.cdsc_absaddr.msf.minute = bcd2uint(q.dt.minute); + sub.cdsc_absaddr.msf.second = bcd2uint(q.dt.second); + sub.cdsc_absaddr.msf.frame = bcd2uint(q.dt.frame); + sub.cdsc_reladdr.msf.minute = bcd2uint(q.tt.minute); + sub.cdsc_reladdr.msf.second = bcd2uint(q.tt.second); + sub.cdsc_reladdr.msf.frame = bcd2uint(q.tt.frame); + } else + return -EINVAL; + + if ((ans = verify_area(VERIFY_WRITE, + (void *) arg, sizeof(sub)))) + return ans; + memcpy_tofs((void *) arg, &sub, sizeof(sub)); - } /* got multisession information */ + return 0; - /* request the disks table of contents (aka diskinfo) */ - if (-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1)) { + case CDROMREADTOCHDR: + MCDX_TRACE_IOCTL(("CDROMREADTOCHDR\n")); - stuffp->lastsector = -1; + if ((ans = verify_area(VERIFY_WRITE, (void *) arg, sizeof toc))) + return ans; - } else { + toc.cdth_trk0 = stuffp->n_first; + toc.cdth_trk1 = stuffp->n_last; + memcpy_tofs((void *) arg, &toc, sizeof toc); + return 0; - stuffp->lastsector = (CD_FRAMESIZE / 512) - * msf2log(&stuffp->di.msf_leadout) - 1; - - TRACE((OPENCLOSE, "open() start %d (%02x:%02x.%02x) %d\n", - stuffp->di.n_first, - stuffp->di.msf_first.minute, - stuffp->di.msf_first.second, - stuffp->di.msf_first.frame, - msf2log(&stuffp->di.msf_first))); - TRACE((OPENCLOSE, "open() last %d (%02x:%02x.%02x) %d\n", - stuffp->di.n_last, - stuffp->di.msf_leadout.minute, - stuffp->di.msf_leadout.second, - stuffp->di.msf_leadout.frame, - msf2log(&stuffp->di.msf_leadout))); - } + case CDROMMULTISESSION: + MCDX_TRACE_IOCTL(("CDROMMULTISESSION\n")); + + if (0 != (ans = verify_area(VERIFY_READ, (void *) arg, + sizeof(struct cdrom_multisession)))) + return ans; + + memcpy_fromfs(&ms, + (void *) arg, sizeof(struct cdrom_multisession)); + if (ms.addr_format == CDROM_MSF) { + ms.addr.msf.minute = + bcd2uint(stuffp->multi.msf_last.minute); + ms.addr.msf.second = + bcd2uint(stuffp->multi.msf_last.second); + ms.addr.msf.frame = + bcd2uint(stuffp->multi.msf_last.frame); + } else if (ms.addr_format == CDROM_LBA) + ms.addr.lba = msf2log(&stuffp->multi.msf_last); + else + return -EINVAL; + ms.xa_flag = !!stuffp->multi.multi; + + if (0 != (ans = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(struct cdrom_multisession)))) + return ans; + + memcpy_tofs((void *) arg, + &ms, sizeof(struct cdrom_multisession)); + return 0; + case CDROMEJECT: + MCDX_TRACE_IOCTL(("CDROMEJECT\n")); + if (stuffp->users > 1) + return -EBUSY; + if (stuffp->door) { + if (-1 == issue_command(stuffp, MCDX_CMD_EJECT, 5 * HZ)) + return -EIO; + } + /* + * Force rereading of toc next time the disk gets accessed! + */ if (stuffp->toc) { - TRACE((MALLOC, "open() free old toc @ %p\n", stuffp->toc)); kfree(stuffp->toc); - - stuffp->toc = NULL; + stuffp->toc = 0; } + return 0; - TRACE((OPENCLOSE, "open() init irq generation\n")); - if (-1 == mcdx_config(stuffp, 1)) return -EIO; - -#if FALLBACK - /* Set the read speed */ - WARN(("AAA %x AAA\n", stuffp->readcmd)); - if (stuffp->readerrs) stuffp->readcmd = READ1X; - else stuffp->readcmd = - stuffp->present | SINGLE ? READ1X : READ2X; - WARN(("XXX %x XXX\n", stuffp->readcmd)); -#endif - - /* try to get the first sector, iff any ... */ - if (stuffp->lastsector >= 0) { - char buf[512]; - int ans; - int tries; - - stuffp->xa = 0; - stuffp->audio = 0; + case CDROMEJECT_SW: + MCDX_TRACE_IOCTL(("CDROMEJECT_SW\n")); - for (tries = 6; tries; tries--) { + stuffp->eject_sw = !!arg; + return 0; - stuffp->introk = 1; + case CDROMVOLCTRL: + MCDX_TRACE_IOCTL(("CDROMVOLCTRL\n")); + + if ((ans = verify_area(VERIFY_READ, + (void *) arg, + sizeof(volctrl)))) + return ans; + + memcpy_fromfs(&volctrl, (char *) arg, sizeof(volctrl)); + /* Adjust for the wiredness of workman. */ + volctrl.channel2 = volctrl.channel1; + volctrl.channel1 = volctrl.channel3 = 0xff; + return talk(stuffp, MCDX_CMD_SET_ATTENATOR, + &volctrl, sizeof(volctrl), + &volctrl, sizeof(volctrl), 2 * HZ); + + default: + printk(KERN_WARNING MCDX + ": unknown ioctl request 0x%04x\n", command); + return -EINVAL; + } +} - TRACE((OPENCLOSE, "open() try as %s\n", - stuffp->xa ? "XA" : "normal")); +/* + * This does actually the transfer from the drive. + * Return: -1 on timeout or other error + * else status byte (as in stuff->st) + * FIXME: the excessive jumping throught wait queues degrades the + * performance significantly. + */ +static int transfer_data(struct s_drive_stuff *stuffp, + char *p, int sector, int nr_sectors) +{ + int off; + int done = 0; + + if (stuffp->valid + && (sector >= stuffp->pending) + && (sector < stuffp->off_direct)) { + off = stuffp->off_requested < (off = sector + nr_sectors) + ? stuffp->off_requested : off; + + do { + /* wait for the drive become idle, but first + * check for possible occurred errors --- the drive + * seems to report them asynchronously + */ + current->timeout = jiffies + 5 * HZ; + while (stuffp->introk && stuffp->busy + && current->timeout) { + interruptible_sleep_on(&stuffp->busyq); + } - /* set data mode */ - if (-1 == (ans = mcdx_setdatamode(stuffp, - stuffp->xa ? MODE2 : MODE1, 1))) { - /* return -EIO; */ - stuffp->xa = 0; - break; + /* test for possible errors */ + if (current->timeout == 0 || !stuffp->introk) { + if (current->timeout == 0) { + printk(KERN_ERR MCDX ": transfer timeout\n"); + } else if (!stuffp->introk) { + printk(KERN_ERR MCDX + ": error via irq in transfer reported\n"); } - if ((stuffp->audio = e_audio(ans))) break; - - while (0 == (ans = mcdx_transfer(stuffp, buf, 0, 1))) - ; - - if (ans == 1) break; - stuffp->xa = !stuffp->xa; + stuffp->busy = 0; + stuffp->valid = 0; + stuffp->introk = 1; + return -1; } - /* if (!tries) return -EIO; */ - } + /* test if it's the first sector of a block, + * there we have to skip some bytes as we read raw data + */ + if (stuffp->xa && (0 == (stuffp->pending & 3))) { + insb(DATA_REG, p, + CD_FRAMESIZE_RAW - CD_XA_TAIL - CD_FRAMESIZE); + } + /* now actually read the data */ + insb(DATA_REG, p, 512); + + /* test if it's the last sector of a block, + * if so, we have to expect an interrupt and to skip + * some data too + */ + if ((stuffp->busy = (3 == (stuffp->pending & 3))) + && stuffp->xa) { + int i; + for (i = 0; i < CD_XA_TAIL; ++i) + inb(DATA_REG); + } + if (stuffp->pending == sector) { + p += 512; + done++; + sector++; + } + } while (++(stuffp->pending) < off); + } else { + unsigned char cmd[6]; + stuffp->valid = 1; + stuffp->pending = sector & ~3; - /* xa disks will be read in raw mode, others not */ - if (-1 == mcdx_setdrivemode(stuffp, - stuffp->xa ? RAW : COOKED, 1)) - return -EIO; + /* do some sanity checks */ + if (stuffp->pending > stuffp->lastsector) { + printk(KERN_ERR MCDX + ": sector %d transfer from nirvana requested.\n", + stuffp->pending); + stuffp->eom = 1; + stuffp->valid = 0; + return -1; + } + if ((stuffp->off_direct = stuffp->pending + DIRECT_SIZE) + > stuffp->lastsector + 1) + stuffp->off_direct = stuffp->lastsector + 1; + if ((stuffp->off_requested = stuffp->pending + REQUEST_SIZE) + > stuffp->lastsector + 1) + stuffp->off_requested = stuffp->lastsector + 1; + { + unsigned int l = (stuffp->pending / 4) + + CD_BLOCK_OFFSET; - if (stuffp->audio) { - INFO(("open() audio disk found\n")); - } else if (stuffp->lastsector >= 0) { - INFO(("open() %s%s disk found\n", - stuffp->xa ? "XA / " : "", - stuffp->multi.multi ? "Multi Session" : "Single Session")); - } + cmd[0] = uint2bcd(l / 4500), l %= 4500; + /* minute */ + cmd[1] = uint2bcd(l / 75); /* second */ + cmd[2] = uint2bcd(l % 75); /* frame */ + } - stuffp->xxx = 0; + stuffp->busy = 1; + /* + * FIXME: What about the ominous frame length?! + */ + cmd[3] = ~0; + cmd[4] = ~0; + cmd[5] = ~0; + + outb(stuffp->double_speed ? MCDX_CMD_PLAY_2X : MCDX_CMD_PLAY, + DATA_REG); + outsb(DATA_REG, cmd, 6); } - /* lock the door if not already done */ - if (0 == stuffp->users && (-1 == mcdx_lockdoor(stuffp, 1, 1))) - return -EIO; + stuffp->off_direct = + (stuffp->off_direct += done) < stuffp->off_requested + ? stuffp->off_direct + : stuffp->off_requested; - stuffp->users++; - MOD_INC_USE_COUNT; - return 0; + return done; } -static void -mcdx_close(struct inode *ip, struct file *fp) +void do_mcdx_request() { - struct s_drive_stuff *stuffp; + int dev; + struct s_drive_stuff *stuffp; - TRACE((OPENCLOSE, "close()\n")); + again: - stuffp = mcdx_stuffp[MINOR(ip->i_rdev)]; - - if (0 == --stuffp->users) { - sync_dev(ip->i_rdev); /* needed for r/o device? */ + if ((CURRENT == NULL) || (CURRENT->rq_status == RQ_INACTIVE)) { + return; + } + stuffp = mcdx_stuffp[MINOR(CURRENT->rq_dev)]; - /* invalidate_inodes(ip->i_rdev); */ - invalidate_buffers(ip->i_rdev); + INIT_REQUEST; + dev = MINOR(CURRENT->rq_dev); + if ((dev < 0) || (dev >= MCDX_NDRIVES) || (!stuffp)) { + printk(KERN_WARNING MCDX ": bad device requested: %s\n", + kdevname(CURRENT->rq_dev)); + end_request(0); + goto again; + } + if (stuffp->audio) { + printk(KERN_WARNING MCDX ": attempt to read from audio cd\n"); + end_request(0); + goto again; + } + switch (CURRENT->cmd) { + case WRITE: + printk(KERN_ERR MCDX ": attempt to write to cd!!\n"); + end_request(0); + break; -#if !MCDX_QUIET - if (-1 == mcdx_lockdoor(stuffp, 0, 3)) - INFO(("close() Cannot unlock the door\n")); -#else - mcdx_lockdoor(stuffp, 0, 3); -#endif + case READ: + stuffp->eom = 0; /* clear end of media flag */ + while (CURRENT->nr_sectors) { + int i; - /* eject if wished */ - if (stuffp->eject_sw) mcdx_eject(stuffp, 1); + if (-1 == (i = transfer_data(stuffp, + CURRENT->buffer, + CURRENT->sector, + CURRENT->nr_sectors))) { + if (stuffp->eom) { + CURRENT->sector += CURRENT->nr_sectors; + CURRENT->nr_sectors = 0; + } else { + /* + * FIXME: TRY SOME ERROR RECOVERY HERE! + */ + } + end_request(0); + goto again; + } + CURRENT->sector += i; + CURRENT->nr_sectors -= i; + CURRENT->buffer += (i * 512); + } + end_request(1); + break; - } - MOD_DEC_USE_COUNT; + default: + panic(MCDX "do_request: unknown command.\n"); + break; + } - return; + goto again; } -int check_mcdx_media_change(kdev_t full_dev) -/* Return: 1 if media changed since last call to this function - 0 otherwise */ +/* + * actions done on open: + * 1) get the drives status + */ +static int mcdx_open(struct inode *ip, struct file *fp) { - struct s_drive_stuff *stuffp; - - INFO(("check_mcdx_media_change called for device %s\n", - kdevname(full_dev))); - - stuffp = mcdx_stuffp[MINOR(full_dev)]; - mcdx_getstatus(stuffp, 1); - - if (stuffp->yyy == 0) return 0; - - stuffp->yyy = 0; - return 1; -} + struct s_drive_stuff *stuffp = mcdx_stuffp[MINOR(ip->i_rdev)]; + int st = 0; + unsigned long bang; -void mcdx_setup(char *str, int *pi) -{ - if (pi[0] > 0) mcdx_drive_map[0][0] = pi[1]; - if (pi[0] > 1) mcdx_drive_map[0][1] = pi[2]; -} + MCDX_TRACE(("mcdx_open()\n")); -/* DIRTY PART ******************************************************/ + if (!stuffp) + return -ENXIO; -static void mcdx_delay(struct s_drive_stuff *stuff, long jifs) -/* This routine is used for sleeping. - May be we could use a simple count loop w/ jumps to itself, but - I wanna make this independent of cpu speed. [1 jiffy is 1/HZ] sec */ -{ - unsigned long tout = jiffies + jifs; - if (jifs < 0) return; - - /* TRACE((INIT, "mcdx_delay %d\n", jifs)); */ - - if (current->pid == 0) { /* no sleep allowed */ - while (jiffies < tout) { - current->timeout = jiffies; - schedule(); - } - } else { /* sleeping is allowed */ - current->timeout = tout; - /* current->state = TASK_INTERRUPTIBLE; */ - /* And perhaps we should remove the while() { ... } */ - while (current->timeout) { - interruptible_sleep_on(&stuff->sleepq); - TRACE((SLEEP, "delay: to is %d\n", current->timeout)); - } - } -} + /* close the door, if necessary (get the door information + * from the hardware status register). + * If we can't read the CD after an autoclose + * no further autocloses will be tried + */ + if (inb(STAT_REG) & MCDX_RBIT_DOOR) { + if (stuffp->autoclose && (stuffp->door)) + issue_command(stuffp, MCDX_CMD_CLOSE_DOOR, 10 * HZ); + else + return -EIO; + } + /* + * Check if a disk is in. + */ bang = jiffies + 10 * HZ; + while (jiffies < bang) { + st = issue_command(stuffp, MCDX_CMD_GET_STATUS, 5 * HZ); + if (st != -1 && (st & MCDX_RBIT_DISKSET)) + break; + current->state = TASK_INTERRUPTIBLE; + current->timeout = jiffies + 1 * HZ; + schedule(); + } + if (st == -1 || (st & MCDX_RBIT_DISKSET) == 0) { + printk(KERN_INFO MCDX ": no disk in drive\n"); + return -EIO; + } + /* if the media changed we will have to do a little more + * FIXME: after removing of the mcdx_requestmultisession() it is showed + * that the logics of this may be broken. + */ + if (stuffp->xxx) { + /* but wait - the time of media change will be set at the + * very last of this block. + */ -static void -mcdx_intr(int irq, void *dev_id, struct pt_regs* regs) -{ - struct s_drive_stuff *stuffp; - unsigned char b; + stuffp->audiostatus = CDROM_AUDIO_INVALID; + stuffp->autoclose = 1; - stuffp = mcdx_irq_map[irq]; + /* get the multisession information */ - if (stuffp == NULL ) { - xwarn("mcdx: no device for intr %d\n", irq); - return; - } + if (stuffp->multi_cap) { + int i = 6; /* number of retries */ + while (i && (-1 == get_command(stuffp, + MCDX_CMD_GET_MDISK_INFO, + &stuffp->multi, sizeof(struct s_multi), 2 * HZ))) + --i; + if (!i) { + stuffp->autoclose = 0; + /* + * No multidisk info + */ + } + } else + stuffp->multi.multi = 0; - /* get the interrupt status */ - b = inb((unsigned int) stuffp->rreg_status); - stuffp->introk = ~b & MCDX_RBIT_DTEN; + if (stuffp->autoclose) { + /* we succeeded, so on next open(2) we could try + * auto close again + */ - /* NOTE: We only should get interrupts if data were requested. - But the drive seems to generate ``asynchronous'' interrupts - on several error conditions too. (Despite the err int enable - setting during initialisation) */ - - /* if not ok, read the next byte as the drives status */ - if (!stuffp->introk) { - TRACE((IRQ, "intr() irq %d hw status 0x%02x\n", irq, b)); - if (~b & MCDX_RBIT_STEN) { - xinfo( "intr() irq %d status 0x%02x\n", - irq, inb((unsigned int) stuffp->rreg_data)); + /* multisession ? */ + if (!stuffp->multi.multi) + stuffp->multi.msf_last.second = 2; + } /* got multisession information */ + /* request the disks table of contents (aka diskinfo) */ + if (-1 == request_toc_data(stuffp)) { + stuffp->lastsector = -1; } else { - xinfo( "intr() irq %d ambiguous hw status\n", irq); + stuffp->lastsector = (CD_FRAMESIZE / 512) + * msf2log(&stuffp->msf_leadout) - 1; } - } else { - TRACE((IRQ, "irq() irq %d ok, status %02x\n", irq, b)); - } - stuffp->busy = 0; - wake_up_interruptible(&stuffp->busyq); -} + if (stuffp->toc) { + kfree(stuffp->toc); + stuffp->toc = 0; + } + if (-1 == config_drive(stuffp)) + return -EIO; + /* try to get the first sector, iff any ... */ + if (stuffp->lastsector >= 0) { + char buf[512]; + int ans; + int tries; -static int -mcdx_talk ( - struct s_drive_stuff *stuffp, - const unsigned char *cmd, size_t cmdlen, - void *buffer, size_t size, - unsigned int timeout, int tries) -/* Send a command to the drive, wait for the result. - * returns -1 on timeout, drive status otherwise - * If buffer is not zero, the result (length size) is stored there. - * If buffer is zero the size should be the number of bytes to read - * from the drive. These bytes are discarded. - */ -{ - int st; - char c; - int discard; + stuffp->xa = 0; + stuffp->audio = 0; - if ((discard = (buffer == NULL))) buffer = &c; + for (tries = 6; tries; tries--) { + unsigned char c; + stuffp->introk = 1; - while (stuffp->lock) { - interruptible_sleep_on(&stuffp->lockq); - TRACE((SLEEP, "talk: lock = %d\n", - stuffp->lock)); - } + /* set data mode */ + c = stuffp->xa ? MODE2 : MODE1; + ans = set_command(stuffp, + MCDX_CMD_SET_DATA_MODE, + &c, sizeof(c), 5 * HZ); - stuffp->lock = 1; - stuffp->valid = 0; + if (-1 == ans) { + /* return -EIO; */ + stuffp->xa = 0; + break; + } else if (ans & MCDX_RBIT_AUDIOTR) { + stuffp->audio = 1; + break; + } + + while (0 == (ans = transfer_data(stuffp, buf, + 0, 1))); -#if MCDX_DEBUG & TALK - { - unsigned char i; - TRACE((TALK, "talk() %d / %d tries, res.size %d, command 0x%02x", - tries, timeout, size, (unsigned char) cmd[0])); - for (i = 1; i < cmdlen; i++) printk(" 0x%02x", cmd[i]); - printk("\n"); + if (ans == 1) + break; + stuffp->xa = !stuffp->xa; + } + /* if (!tries) return -EIO; */ + } + /* xa disks will be read in raw mode, others not */ + if (-1 == set_drive_mode(stuffp, stuffp->xa ? RAW : COOKED)) + return -EIO; + stuffp->xxx = 0; } -#endif + /* lock the door if not already done */ + if (0 == stuffp->users && (-1 == lock_door(stuffp, DOOR_LOCK))) + return -EIO; - /* give up if all tries are done (bad) or if the status - * st != -1 (good) */ - for (st = -1; st == -1 && tries; tries--) { - - char *bp = (char*) buffer; - size_t sz = size; - - outsb((unsigned int) stuffp->wreg_data, cmd, cmdlen); - TRACE((TALK, "talk() command sent\n")); - - /* get the status byte */ - if (-1 == mcdx_getval(stuffp, timeout, 0, bp)) { - INFO(("talk() %02x timed out (status), %d tr%s left\n", - cmd[0], tries - 1, tries == 2 ? "y" : "ies")); - continue; - } - st = *bp; - sz--; - if (!discard) bp++; - - TRACE((TALK, "talk() got status 0x%02x\n", st)); - - /* command error? */ - if (e_cmderr(st)) { - WARN(("command error cmd = %02x %s \n", - cmd[0], cmdlen > 1 ? "..." : "")); - st = -1; - continue; - } + stuffp->users++; + MOD_INC_USE_COUNT; + return 0; +} - /* audio status? */ - if (stuffp->audiostatus == CDROM_AUDIO_INVALID) - stuffp->audiostatus = - e_audiobusy(st) ? CDROM_AUDIO_PLAY : CDROM_AUDIO_NO_STATUS; - else if (stuffp->audiostatus == CDROM_AUDIO_PLAY - && e_audiobusy(st) == 0) - stuffp->audiostatus = CDROM_AUDIO_COMPLETED; - - /* media change? */ - if (e_changed(st)) { - INFO(("talk() media changed\n")); - stuffp->xxx = stuffp->yyy = 1; - } - - /* now actually get the data */ - while (sz--) { - if (-1 == mcdx_getval(stuffp, timeout, 0, bp)) { - INFO(("talk() %02x timed out (data), %d tr%s left\n", - cmd[0], tries - 1, tries == 2 ? "y" : "ies")); - st = -1; break; - } - if (!discard) bp++; - TRACE((TALK, "talk() got 0x%02x\n", *(bp - 1))); - } - } - -#if !MCDX_QUIET - if (!tries && st == -1) INFO(("talk() giving up\n")); -#endif +static void mcdx_close(struct inode *ip, struct file *fp) +{ + struct s_drive_stuff *stuffp = mcdx_stuffp[MINOR(ip->i_rdev)]; - stuffp->lock = 0; - wake_up_interruptible(&stuffp->lockq); + MCDX_TRACE(("mcdx_close()\n")); - TRACE((TALK, "talk() done with 0x%02x\n", st)); - return st; -} - -/* MODULE STUFF ***********************************************************/ -#ifdef MODULE + if (0 == --stuffp->users) { + sync_dev(ip->i_rdev); /* needed for r/o device? */ -int init_module(void) -{ - int i; - int drives = 0; + /* invalidate_inodes(ip->i_rdev); */ + invalidate_buffers(ip->i_rdev); + lock_door(stuffp, DOOR_UNLOCK); - mcdx_init(); - for (i = 0; i < MCDX_NDRIVES; i++) { - if (mcdx_stuffp[i]) { - TRACE((INIT, "init_module() drive %d stuff @ %p\n", - i, mcdx_stuffp[i])); - drives++; + /* eject if wished and possible */ + if (stuffp->eject_sw && (stuffp->door)) { + issue_command(stuffp, MCDX_CMD_EJECT, 5 * HZ); } } + MOD_DEC_USE_COUNT; - if (!drives) - return -EIO; - - register_symtab(0); - return 0; + return; } -void cleanup_module(void) +/* + * Return: 1 if media changed since last call to this function + * 0 otherwise + */ +static int mcdx_media_change(kdev_t full_dev) { - int i; + struct s_drive_stuff *stuffp; - INFO(("cleanup_module called\n")); - - for (i = 0; i < MCDX_NDRIVES; i++) { - struct s_drive_stuff *stuffp; - stuffp = mcdx_stuffp[i]; - if (!stuffp) continue; - release_region((unsigned long) stuffp->wreg_data, MCDX_IO_SIZE); - free_irq(stuffp->irq, NULL); - if (stuffp->toc) { - TRACE((MALLOC, "cleanup_module() free toc @ %p\n", stuffp->toc)); - kfree(stuffp->toc); - } - TRACE((MALLOC, "cleanup_module() free stuffp @ %p\n", stuffp)); - mcdx_stuffp[i] = NULL; - kfree(stuffp); - } + MCDX_TRACE(("mcdx_media_change()\n")); - if (unregister_blkdev(MAJOR_NR, DEVICE_NAME) != 0) { - WARN(("cleanup() unregister_blkdev() failed\n")); - } -#if !MCDX_QUIET - else INFO(("cleanup() succeeded\n")); -#endif -} - -#endif MODULE - -/* Support functions ************************************************/ + /* + * FIXME: propably this is unneded or should be simplified! + */ + issue_command(stuffp = mcdx_stuffp[MINOR(full_dev)], + MCDX_CMD_GET_STATUS, 5 * HZ); -#if MCDX_DEBUG -void trace(int level, const char* fmt, ...) -{ - char s[255]; - va_list args; - if (level < 1) return; - va_start(args, fmt); - if (sizeof(s) < vsprintf(s, fmt, args)) - printk(MCDX ":: dprintf exceeds limit!!\n"); - else printk(MCDX ":: %s", s); - va_end(args); + return stuffp->xxx; } -#endif -void warn(const char* fmt, ...) +/* Interrupt handler routine. + * This function is called, when during transfer the end of a physical 2048 + * byte block is reached. + */ +static void mcdx_intr(int irq, void *dev_id, struct pt_regs *regs) { - char s[255]; - va_list args; - va_start(args, fmt); - if (sizeof(s) < vsprintf(s, fmt, args)) - printk(MCDX ":: dprintf exceeds limit!!\n"); - else printk(MCDX ": %s", s); - va_end(args); + struct s_drive_stuff *stuffp; + u_char b; + + if (!(stuffp = mcdx_irq_map[irq])) { + return; /* hugh? */ + } + + /* NOTE: We only should get interrupts if data were requested. + * But the drive seems to generate ``asynchronous'' interrupts + * on several error conditions too. (Despite the err int enable + * setting during initialisation) + */ + + /* get the interrupt status */ + b = inb(STAT_REG); + if (!(b & MCDX_RBIT_DTEN)) { + stuffp->introk = 1; + } else { + stuffp->introk = 0; + if (!(b & MCDX_RBIT_STEN)) { + printk(KERN_DEBUG MCDX ": irq %d status 0x%02x\n", + irq, inb(DATA_REG)); + } else { + MCDX_TRACE(("irq %d ambiguous hw status\n", irq)); + } + } + stuffp->busy = 0; + wake_up_interruptible(&stuffp->busyq); } +/* + * FIXME! + * This seems to hang badly, when the driver is loaded with inappriopriate + * port/irq settings! + */ int mcdx_init(void) { int drive; #ifdef MODULE - WARN(("Version 1.9 for %s\n", kernel_version)); + printk(KERN_INFO "Mitsumi driver version " VERSION " for %s\n", + kernel_version); #else - WARN(("Version 1.9\n")); + printk(KERN_INFO "Mitsumi driver version " VERSION "\n"); #endif - - WARN(("mcdx.c,v 1.2 1996/03/22 01:14:59 heiko Exp\n")); - - /* zero the pointer array */ - for (drive = 0; drive < MCDX_NDRIVES; drive++) - mcdx_stuffp[drive] = NULL; - - /* do the initialisation */ - for (drive = 0; drive < MCDX_NDRIVES; drive++) { - struct s_version version; - struct s_drive_stuff* stuffp; - int size; + printk("%d\n", MCDX_NDRIVES); + for (drive = 0; drive < MCDX_NDRIVES; drive++) { + struct { + u_char code; + u_char version; + } firmware; + int i; + struct s_drive_stuff *stuffp; + int size; mcdx_blocksizes[drive] = 0; + mcdx_stuffp[drive] = 0; - size = sizeof(*stuffp); - - TRACE((INIT, "init() try drive %d\n", drive)); + size = sizeof(*stuffp); - TRACE((INIT, "kmalloc space for stuffpt's\n")); - TRACE((MALLOC, "init() malloc %d bytes\n", size)); if (!(stuffp = kmalloc(size, GFP_KERNEL))) { - WARN(("init() malloc failed\n")); - break; + printk(KERN_ERR MCDX + ": malloc of drives data failed!\n"); + break; } + /* set default values */ memset(stuffp, 0, sizeof(*stuffp)); + stuffp->autoclose = 1; /* close the door on open(2) */ - TRACE((INIT, "init() got %d bytes for drive stuff @ %p\n", sizeof(*stuffp), stuffp)); - - /* set default values */ - memset(stuffp, 0, sizeof(*stuffp)); - stuffp->autoclose = 1; /* close the door on open(2) */ - - stuffp->present = 0; /* this should be 0 already */ - stuffp->toc = NULL; /* this should be NULL already */ - - /* setup our irq and i/o addresses */ stuffp->irq = irq(mcdx_drive_map[drive]); - stuffp->wreg_data = stuffp->rreg_data = port(mcdx_drive_map[drive]); - stuffp->wreg_reset = stuffp->rreg_status = stuffp->wreg_data + 1; - stuffp->wreg_hcon = stuffp->wreg_reset + 1; - stuffp->wreg_chn = stuffp->wreg_hcon + 1; + stuffp->base = port(mcdx_drive_map[drive]); /* check if i/o addresses are available */ - if (0 != check_region((unsigned int) stuffp->wreg_data, MCDX_IO_SIZE)) { - WARN(("0x%3p,%d: " - "Init failed. I/O ports (0x%3p..0x%3p) already in use.\n", - stuffp->wreg_data, stuffp->irq, - stuffp->wreg_data, - stuffp->wreg_data + MCDX_IO_SIZE - 1)); - TRACE((MALLOC, "init() free stuffp @ %p\n", stuffp)); - kfree(stuffp); - TRACE((INIT, "init() continue at next drive\n")); - continue; /* next drive */ + if (check_region(stuffp->base, MCDX_IO_SIZE)) { + printk(KERN_WARNING + "Init failed. I/O ports (0x%3x..0x%3x) " + "already in use.\n", + stuffp->base, stuffp->base + MCDX_IO_SIZE - 1); + kfree(stuffp); + continue; /* next drive */ } - - TRACE((INIT, "init() i/o port is available at 0x%3p\n", stuffp->wreg_data)); - - TRACE((INIT, "init() hardware reset\n")); - mcdx_reset(stuffp, HARD, 1); - - TRACE((INIT, "init() get version\n")); - if (-1 == mcdx_requestversion(stuffp, &version, 4)) { + /* + * Hardware reset. + */ + outb(0, CHAN_REG); /* no dma, no irq -> hardware */ + outb(0, RESET_REG); /* hw reset */ + + i = 10; /* number of retries */ + while (-1 == get_command(stuffp, MCDX_CMD_GET_FIRMWARE, + &firmware, sizeof(firmware), 2 * HZ)) + --i; + if (!i) { /* failed, next drive */ - WARN(("%s=0x%3p,%d: Init failed. Can't get version.\n", - MCDX, - stuffp->wreg_data, stuffp->irq)); - TRACE((MALLOC, "init() free stuffp @ %p\n", stuffp)); - kfree(stuffp); - TRACE((INIT, "init() continue at next drive\n")); + printk(KERN_WARNING + "%s=0x%3x,%d: Init failed. Can't get version.\n", + MCDX, stuffp->base, stuffp->irq); + kfree(stuffp); continue; } - - switch (version.code) { - case 'D': - stuffp->readcmd = READ2X; - stuffp->present = DOUBLE | DOOR | MULTI; - break; - case 'F': - stuffp->readcmd = READ1X; - stuffp->present = SINGLE | DOOR | MULTI; - break; - case 'M': - stuffp->readcmd = READ1X; - stuffp->present = SINGLE; - break; - default: - stuffp->present = 0; break; - } - - stuffp->playcmd = READ1X; - - - if (!stuffp->present) { - WARN(("%s=0x%3p,%d: Init failed. No Mitsumi CD-ROM?.\n", - MCDX, stuffp->wreg_data, stuffp->irq)); + switch (firmware.code) { + case 'D': + stuffp->double_speed = stuffp->door = + stuffp->multi_cap = 1; + break; + case 'F': + stuffp->door = stuffp->multi_cap = 1; + break; + case 'M': + break; + default: kfree(stuffp); - continue; /* next drive */ } - TRACE((INIT, "init() register blkdev\n")); - if (register_blkdev(MAJOR_NR, DEVICE_NAME, &mcdx_fops) != 0) { - WARN(("%s=0x%3p,%d: Init failed. Can't get major %d.\n", - MCDX, - stuffp->wreg_data, stuffp->irq, MAJOR_NR)); + if (!stuffp) + continue; /* next drive */ + + if (register_blkdev(MAJOR_NR, DEVICE_NAME, &mcdx_fops)) { kfree(stuffp); - continue; /* next drive */ + continue; /* next drive */ } - blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; read_ahead[MAJOR_NR] = READ_AHEAD; blksize_size[MAJOR_NR] = mcdx_blocksizes; - TRACE((INIT, "init() subscribe irq and i/o\n")); mcdx_irq_map[stuffp->irq] = stuffp; - if (request_irq(stuffp->irq, mcdx_intr, SA_INTERRUPT, DEVICE_NAME, NULL)) { - WARN(("%s=0x%3p,%d: Init failed. Can't get irq (%d).\n", - MCDX, - stuffp->wreg_data, stuffp->irq, stuffp->irq)); + if (request_irq(stuffp->irq, mcdx_intr, + SA_INTERRUPT, DEVICE_NAME, NULL)) { stuffp->irq = 0; kfree(stuffp); - continue; - } - request_region((unsigned int) stuffp->wreg_data, - MCDX_IO_SIZE, - DEVICE_NAME); - - TRACE((INIT, "init() get garbage\n")); - { - int i; - mcdx_delay(stuffp, HZ/2); - for (i = 100; i; i--) (void) inb((unsigned int) stuffp->rreg_status); + continue; /* next drive */ } + request_region(stuffp->base, MCDX_IO_SIZE, DEVICE_NAME); + /* get junk after some delay. + */ + current->state = TASK_INTERRUPTIBLE; + current->timeout = jiffies + HZ / 2; + schedule(); + for (i = 100; i; i--) + (void) inb(STAT_REG); #if WE_KNOW_WHY - outb(0x50, (unsigned int) stuffp->wreg_chn); /* irq 11 -> channel register */ + outb(0x50, CHAN_REG); /* irq 11 -> channel register */ #endif - TRACE((INIT, "init() set non dma but irq mode\n")); - mcdx_config(stuffp, 1); + config_drive(stuffp); - stuffp->minor = drive; - - WARN((DEVICE_NAME " installed at 0x%3p, irq %d." - " (Firmware version %c %x)\n", - stuffp->wreg_data, stuffp->irq, version.code, - version.ver)); + printk(KERN_INFO MCDX "%d: at 0x%3x, irq %d, firmware: %c %x\n", + drive, stuffp->base, stuffp->irq, + firmware.code, firmware.version); mcdx_stuffp[drive] = stuffp; - TRACE((INIT, "init() mcdx_stuffp[%d] = %p\n", drive, stuffp)); } return 0; } -static int -mcdx_transfer(struct s_drive_stuff *stuffp, - char *p, int sector, int nr_sectors) -/* This seems to do the actually transfer. But it does more. It - keeps track of errors occurred and will (if possible) fall back - to single speed on error. - Return: -1 on timeout or other error - else status byte (as in stuff->st) */ -{ - int ans; - - ans = mcdx_xfer(stuffp, p, sector, nr_sectors); - return ans; -#if FALLBACK - if (-1 == ans) stuffp->readerrs++; - else return ans; - - if (stuffp->readerrs && stuffp->readcmd == READ1X) { - WARN(("XXX Already reading 1x -- no chance\n")); - return -1; - } - - WARN(("XXX Fallback to 1x\n")); - - stuffp->readcmd = READ1X; - return mcdx_transfer(stuffp, p, sector, nr_sectors); -#endif - -} - - -static int mcdx_xfer(struct s_drive_stuff *stuffp, - char *p, int sector, int nr_sectors) -/* This does actually the transfer from the drive. - Return: -1 on timeout or other error - else status byte (as in stuff->st) */ -{ - int off; - int done = 0; - - TRACE((TRANSFER, "transfer() %d sectors at sector %d\n", - nr_sectors, sector)); - - if (stuffp->audio) { - WARN(("attempt to read from audio cd\n")); - return -1; - } - - while (stuffp->lock) { - interruptible_sleep_on(&stuffp->lockq); - TRACE((SLEEP, "xfer: lock = %d\n", - stuffp->lock)); - } - - if (stuffp->valid - && (sector >= stuffp->pending) - && (sector < stuffp->off_direct)) { - - - off = stuffp->off_requested < (off = sector + nr_sectors) - ? stuffp->off_requested : off; - - stuffp->lock = current->pid; - - do { - /* wait for the drive become idle, but first - check for possible occurred errors --- the drive - seems to report them asynchronously */ - - current->timeout = jiffies + 5 * HZ; - while (stuffp->introk && stuffp->busy && current->timeout) { - interruptible_sleep_on(&stuffp->busyq); - TRACE((SLEEP, "request: busy = %d, timeout = %d\n", - stuffp->busy, current->timeout)); - } - - /* test for possible errors */ - if (current->timeout == 0 || !stuffp->introk) { - if (current->timeout == 0) { - WARN(("mcdx_transfer() timeout\n")); - } else if (!stuffp->introk) { - WARN(("mcdx_transfer() error via irq reported\n")); - } else { - WARN(("mcdx_transfer() unknown failure in data request\n")); - } - - stuffp->lock = 0; - stuffp->busy = 0; - stuffp->valid = 0; - - wake_up_interruptible(&stuffp->lockq); - TRACE((TRANSFER, "transfer() done (-1)\n")); - return -1; - } - - /* test if it's the first sector of a block, - * there we have to skip some bytes as we read raw data */ - if (stuffp->xa && (0 == (stuffp->pending & 3))) { - const int HEAD = CD_FRAMESIZE_RAW - CD_XA_TAIL - CD_FRAMESIZE; - TRACE((TRANSFER, "transfer() sector %d, skip %d header bytes\n", - stuffp->pending, HEAD)); - insb((unsigned int) stuffp->rreg_data, p, HEAD); - } - - /* now actually read the data */ - - TRACE((TRANSFER, "transfer() read sector %d\n", stuffp->pending)); - insb((unsigned int) stuffp->rreg_data, p, 512); - - /* test if it's the last sector of a block, - * if so, we have to expect an interrupt and to skip some - * data too */ - if ((stuffp->busy = (3 == (stuffp->pending & 3))) && stuffp->xa) { - char dummy[CD_XA_TAIL]; - TRACE((TRANSFER, "transfer() sector %d, skip %d trailer bytes\n", - stuffp->pending, CD_XA_TAIL)); - insb((unsigned int) stuffp->rreg_data, &dummy[0], CD_XA_TAIL); - } - - if (stuffp->pending == sector) { - p += 512; - done++; - sector++; - } - } while (++(stuffp->pending) < off); - - stuffp->lock = 0; - wake_up_interruptible(&stuffp->lockq); - - } else { - - static unsigned char cmd[] = { - 0, - 0, 0, 0, - 0, 0, 0 - }; - - cmd[0] = stuffp->readcmd; - - stuffp->valid = 1; - stuffp->pending = sector & ~3; - - /* do some sanity checks */ - TRACE((TRANSFER, "transfer() request sector %d\n", stuffp->pending)); - if (stuffp->pending > stuffp->lastsector) { - WARN(("transfer() sector %d from nirvana requested.\n", - stuffp->pending)); - stuffp->status = MCDX_ST_EOM; - stuffp->valid = 0; - TRACE((TRANSFER, "transfer() done (-1)\n")); - return -1; - } - - if ((stuffp->off_direct = stuffp->pending + DIRECT_SIZE) - > stuffp->lastsector + 1) - stuffp->off_direct = stuffp->lastsector + 1; - if ((stuffp->off_requested = stuffp->pending + REQUEST_SIZE) - > stuffp->lastsector + 1) - stuffp->off_requested = stuffp->lastsector + 1; - - TRACE((TRANSFER, "transfer() pending %d\n", stuffp->pending)); - TRACE((TRANSFER, "transfer() off_dir %d\n", stuffp->off_direct)); - TRACE((TRANSFER, "transfer() off_req %d\n", stuffp->off_requested)); - - { - struct s_msf pending; - log2msf(stuffp->pending / 4, &pending); - cmd[1] = pending.minute; - cmd[2] = pending.second; - cmd[3] = pending.frame; - } - - stuffp->busy = 1; - cmd[6] = (unsigned char) (stuffp->off_requested - stuffp->pending) / 4; - - outsb((unsigned int) stuffp->wreg_data, cmd, sizeof cmd); - - } - - stuffp->off_direct = (stuffp->off_direct += done) < stuffp->off_requested - ? stuffp->off_direct : stuffp->off_requested; - - TRACE((TRANSFER, "transfer() done (%d)\n", done)); - return done; -} - - -/* Access to elements of the mcdx_drive_map members */ - -static char* port(int *ip) { return (char*) ip[0]; } -static int irq(int *ip) { return ip[1]; } - -/* Misc number converters */ - -static unsigned int bcd2uint(unsigned char c) -{ return (c >> 4) * 10 + (c & 0x0f); } - -static unsigned int uint2bcd(unsigned int ival) -{ return ((ival / 10) << 4) | (ival % 10); } - -static void log2msf(unsigned int l, struct s_msf* pmsf) -{ - l += CD_BLOCK_OFFSET; - pmsf->minute = uint2bcd(l / 4500), l %= 4500; - pmsf->second = uint2bcd(l / 75); - pmsf->frame = uint2bcd(l % 75); -} +#ifdef MODULE -static unsigned int msf2log(const struct s_msf* pmsf) -{ - return bcd2uint(pmsf->frame) - + bcd2uint(pmsf->second) * 75 - + bcd2uint(pmsf->minute) * 4500 - - CD_BLOCK_OFFSET; -} - -int mcdx_readtoc(struct s_drive_stuff* stuffp) -/* Read the toc entries from the CD, - * Return: -1 on failure, else 0 */ +int init_module(void) { + int i; - if (stuffp->toc) { - TRACE((READTOC, "ioctl() toc already read\n")); - return 0; - } - - TRACE((READTOC, "ioctl() readtoc for %d tracks\n", - stuffp->di.n_last - stuffp->di.n_first + 1)); - - if (-1 == mcdx_hold(stuffp, 1)) return -1; - - TRACE((READTOC, "ioctl() tocmode\n")); - if (-1 == mcdx_setdrivemode(stuffp, TOC, 1)) return -EIO; - - /* all seems to be ok so far ... malloc */ - { - int size; - size = sizeof(struct s_subqcode) * (stuffp->di.n_last - stuffp->di.n_first + 2); - - TRACE((MALLOC, "ioctl() malloc %d bytes\n", size)); - stuffp->toc = kmalloc(size, GFP_KERNEL); - if (!stuffp->toc) { - WARN(("Cannot malloc %s bytes for toc\n", size)); - mcdx_setdrivemode(stuffp, DATA, 1); - return -EIO; - } - } - - /* now read actually the index */ - { - int trk; - int retries; - - for (trk = 0; - trk < (stuffp->di.n_last - stuffp->di.n_first + 1); - trk++) - stuffp->toc[trk].index = 0; - - for (retries = 300; retries; retries--) { /* why 300? */ - struct s_subqcode q; - unsigned int idx; - - if (-1 == mcdx_requestsubqcode(stuffp, &q, 1)) { - mcdx_setdrivemode(stuffp, DATA, 1); - return -EIO; - } - - idx = bcd2uint(q.index); - - if ((idx > 0) - && (idx <= stuffp->di.n_last) - && (q.tno == 0) - && (stuffp->toc[idx - stuffp->di.n_first].index == 0)) { - stuffp->toc[idx - stuffp->di.n_first] = q; - TRACE((READTOC, "ioctl() toc idx %d (trk %d)\n", idx, trk)); - trk--; - } - if (trk == 0) break; + mcdx_init(); + for (i = 0; i < MCDX_NDRIVES; i++) { + if (mcdx_stuffp[i]) { + register_symtab(0); + return 0; } - memset(&stuffp->toc[stuffp->di.n_last - stuffp->di.n_first + 1], - 0, sizeof(stuffp->toc[0])); - stuffp->toc[stuffp->di.n_last - stuffp->di.n_first + 1].dt - = stuffp->di.msf_leadout; } - - /* unset toc mode */ - TRACE((READTOC, "ioctl() undo toc mode\n")); - if (-1 == mcdx_setdrivemode(stuffp, DATA, 2)) - return -EIO; - -#if MCDX_DEBUG && READTOC - { int trk; - for (trk = 0; - trk < (stuffp->di.n_last - stuffp->di.n_first + 2); - trk++) - TRACE((READTOC, "ioctl() %d readtoc %02x %02x %02x" - " %02x:%02x.%02x %02x:%02x.%02x\n", - trk + stuffp->di.n_first, - stuffp->toc[trk].control, stuffp->toc[trk].tno, stuffp->toc[trk].index, - stuffp->toc[trk].tt.minute, stuffp->toc[trk].tt.second, stuffp->toc[trk].tt.frame, - stuffp->toc[trk].dt.minute, stuffp->toc[trk].dt.second, stuffp->toc[trk].dt.frame)); - } -#endif - - return 0; + return -EIO; } -static int -mcdx_playmsf(struct s_drive_stuff* stuffp, const struct cdrom_msf* msf) -{ - unsigned char cmd[7] = { - 0, 0, 0, 0, 0, 0, 0 - }; - - cmd[0] = stuffp->playcmd; - - cmd[1] = msf->cdmsf_min0; - cmd[2] = msf->cdmsf_sec0; - cmd[3] = msf->cdmsf_frame0; - cmd[4] = msf->cdmsf_min1; - cmd[5] = msf->cdmsf_sec1; - cmd[6] = msf->cdmsf_frame1; - - TRACE((PLAYMSF, "ioctl(): play %x " - "%02x:%02x:%02x -- %02x:%02x:%02x\n", - cmd[0], cmd[1], cmd[2], cmd[3], - cmd[4], cmd[5], cmd[6])); - - outsb((unsigned int) stuffp->wreg_data, cmd, sizeof cmd); - - if (-1 == mcdx_getval(stuffp, 3 * HZ, 0, NULL)) { - WARN(("playmsf() timeout\n")); - return -1; - } - - stuffp->audiostatus = CDROM_AUDIO_PLAY; - return 0; -} - -static int -mcdx_playtrk(struct s_drive_stuff* stuffp, const struct cdrom_ti* ti) -{ - struct s_subqcode* p; - struct cdrom_msf msf; - - if (-1 == mcdx_readtoc(stuffp)) return -1; - - if (ti) p = &stuffp->toc[ti->cdti_trk0 - stuffp->di.n_first]; - else p = &stuffp->start; - - msf.cdmsf_min0 = p->dt.minute; - msf.cdmsf_sec0 = p->dt.second; - msf.cdmsf_frame0 = p->dt.frame; - - if (ti) { - p = &stuffp->toc[ti->cdti_trk1 - stuffp->di.n_first + 1]; - stuffp->stop = *p; - } else p = &stuffp->stop; - - msf.cdmsf_min1 = p->dt.minute; - msf.cdmsf_sec1 = p->dt.second; - msf.cdmsf_frame1 = p->dt.frame; - - return mcdx_playmsf(stuffp, &msf); -} - - -/* Drive functions ************************************************/ - -static int -mcdx_closedoor(struct s_drive_stuff *stuffp, int tries) -{ - if (stuffp->present & DOOR) - return mcdx_talk(stuffp, "\xf8", 1, NULL, 1, 5 * HZ, tries); - else - return 0; -} - -static int -mcdx_stop(struct s_drive_stuff *stuffp, int tries) -{ return mcdx_talk(stuffp, "\xf0", 1, NULL, 1, 2 * HZ, tries); } - -static int -mcdx_hold(struct s_drive_stuff *stuffp, int tries) -{ return mcdx_talk(stuffp, "\x70", 1, NULL, 1, 2 * HZ, tries); } - -static int -mcdx_eject(struct s_drive_stuff *stuffp, int tries) -{ - if (stuffp->present & DOOR) { - stuffp->ejected = jiffies; - return mcdx_talk(stuffp, "\xf6", 1, NULL, 1, 5 * HZ, tries); - } else return 0; -} - -static int -mcdx_requestsubqcode(struct s_drive_stuff *stuffp, - struct s_subqcode *sub, - int tries) -{ - char buf[11]; - int ans; - - if (-1 == (ans = mcdx_talk( - stuffp, "\x20", 1, buf, sizeof(buf), - 2 * HZ, tries))) - return -1; - sub->control = buf[1]; - sub->tno = buf[2]; - sub->index = buf[3]; - sub->tt.minute = buf[4]; - sub->tt.second = buf[5]; - sub->tt.frame = buf[6]; - sub->dt.minute = buf[8]; - sub->dt.second = buf[9]; - sub->dt.frame = buf[10]; - - return ans; -} - -static int -mcdx_requestmultidiskinfo(struct s_drive_stuff *stuffp, struct s_multi *multi, int tries) -{ - char buf[5]; - int ans; - - if (stuffp->present & MULTI) { - ans = mcdx_talk(stuffp, "\x11", 1, buf, sizeof(buf), 2 * HZ, tries); - multi->multi = buf[1]; - multi->msf_last.minute = buf[2]; - multi->msf_last.second = buf[3]; - multi->msf_last.frame = buf[4]; - return ans; - } else { - multi->multi = 0; - return 0; - } -} - -static int -mcdx_requesttocdata(struct s_drive_stuff *stuffp, struct s_diskinfo *info, int tries) -{ - char buf[9]; - int ans; - ans = mcdx_talk(stuffp, "\x10", 1, buf, sizeof(buf), 2 * HZ, tries); - if (ans == -1) { - info->n_first = 0; - info->n_last = 0; - } else { - info->n_first = bcd2uint(buf[1]); - info->n_last = bcd2uint(buf[2]); - info->msf_leadout.minute = buf[3]; - info->msf_leadout.second = buf[4]; - info->msf_leadout.frame = buf[5]; - info->msf_first.minute = buf[6]; - info->msf_first.second = buf[7]; - info->msf_first.frame = buf[8]; - } - return ans; -} - -static int -mcdx_setdrivemode(struct s_drive_stuff *stuffp, enum drivemodes mode, int tries) +void cleanup_module(void) { - char cmd[2]; - int ans; - - TRACE((HW, "setdrivemode() %d\n", mode)); - - if (-1 == (ans = mcdx_talk(stuffp, "\xc2", 1, cmd, sizeof(cmd), 5 * HZ, tries))) - return -1; + int i; - switch (mode) { - case TOC: cmd[1] |= 0x04; break; - case DATA: cmd[1] &= ~0x04; break; - case RAW: cmd[1] |= 0x40; break; - case COOKED: cmd[1] &= ~0x40; break; - default: break; - } - cmd[0] = 0x50; - return mcdx_talk(stuffp, cmd, 2, NULL, 1, 5 * HZ, tries); -} + unregister_blkdev(MAJOR_NR, DEVICE_NAME); -static int -mcdx_setdatamode(struct s_drive_stuff *stuffp, enum datamodes mode, int tries) -{ - unsigned char cmd[2] = { 0xa0 }; - TRACE((HW, "setdatamode() %d\n", mode)); - switch (mode) { - case MODE0: cmd[1] = 0x00; break; - case MODE1: cmd[1] = 0x01; break; - case MODE2: cmd[1] = 0x02; break; - default: return -EINVAL; + for (i = 0; i < MCDX_NDRIVES; i++) { + struct s_drive_stuff *stuffp; + stuffp = mcdx_stuffp[i]; + if (!stuffp) + continue; + release_region(stuffp->base, MCDX_IO_SIZE); + free_irq(stuffp->irq, NULL); + if (stuffp->toc) { + kfree(stuffp->toc); + } + mcdx_stuffp[i] = NULL; + kfree(stuffp); } - return mcdx_talk(stuffp, cmd, 2, NULL, 1, 5 * HZ, tries); + blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; } -static int -mcdx_config(struct s_drive_stuff *stuffp, int tries) -{ - char cmd[4]; - - TRACE((HW, "config()\n")); - - cmd[0] = 0x90; - - cmd[1] = 0x10; /* irq enable */ - cmd[2] = 0x05; /* pre, err irq enable */ - - if (-1 == mcdx_talk(stuffp, cmd, 3, NULL, 1, 1 * HZ, tries)) - return -1; - - cmd[1] = 0x02; /* dma select */ - cmd[2] = 0x00; /* no dma */ - - return mcdx_talk(stuffp, cmd, 3, NULL, 1, 1 * HZ, tries); -} - -static int -mcdx_requestversion(struct s_drive_stuff *stuffp, struct s_version *ver, int tries) -{ - char buf[3]; - int ans; +#else /* MODULE */ - if (-1 == (ans = mcdx_talk(stuffp, "\xdc", - 1, buf, sizeof(buf), 2 * HZ, tries))) - return ans; - - ver->code = buf[1]; - ver->ver = buf[2]; - - return ans; -} - -static int -mcdx_reset(struct s_drive_stuff *stuffp, enum resetmodes mode, int tries) -{ - if (mode == HARD) { - outb(0, (unsigned int) stuffp->wreg_chn); /* no dma, no irq -> hardware */ - outb(0, (unsigned int) stuffp->wreg_reset); /* hw reset */ - return 0; - } else return mcdx_talk(stuffp, "\x60", 1, NULL, 1, 5 * HZ, tries); -} - -static int -mcdx_lockdoor(struct s_drive_stuff *stuffp, int lock, int tries) -{ - char cmd[2] = { 0xfe }; - if (stuffp->present & DOOR) { - cmd[1] = lock ? 0x01 : 0x00; - return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 1, 5 * HZ, tries); - } else return 0; -} - -static int -mcdx_getstatus(struct s_drive_stuff *stuffp, int tries) -{ return mcdx_talk(stuffp, "\x40", 1, NULL, 1, 5 * HZ, tries); } - -static int -mcdx_getval(struct s_drive_stuff *stuffp, int to, int delay, char* buf) -{ - unsigned long timeout = to + jiffies; - char c; - - if (!buf) buf = &c; - - while (inb((unsigned int) stuffp->rreg_status) & MCDX_RBIT_STEN) { - if (jiffies > timeout) return -1; - mcdx_delay(stuffp, delay); - } - - *buf = (unsigned char) inb((unsigned int) stuffp->rreg_data) & 0xff; - - return 0; -} - -static int -mcdx_setattentuator( - struct s_drive_stuff* stuffp, - struct cdrom_volctrl* vol, - int tries) +/* + * This function is used by the kernel in init/main.c to provide semantics + * for the corresponding kernel options. It's unused otherwise. + */ +void mcdx_setup(char *str, int *pi) { - char cmd[5]; - cmd[0] = 0xae; - cmd[1] = vol->channel0; - cmd[2] = 0; - cmd[3] = vol->channel1; - cmd[4] = 0; - - return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 5, 200, tries); + if (pi[0] > 0) + mcdx_drive_map[0][0] = pi[1]; + if (pi[0] > 1) + mcdx_drive_map[0][1] = pi[2]; } - -/* ex:set ts=4 sw=4: */ +#endif /* MODULE */ diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c index 2caf2a23791f..2838359b0416 100644 --- a/drivers/cdrom/sbpcd.c +++ b/drivers/cdrom/sbpcd.c @@ -9,11 +9,11 @@ * Also for the TEAC CD-55A drive. * Also for the ECS-AT "Vertos 100" drive. * Not for Sanyo drives (but for the H94A, sjcd is there...). - * Not for any other Funai drives than the CD200 types - * (sometimes labelled E2550UA or MK4015 or E2880UA). + * Not for any other Funai drives than the CD200 types (sometimes + * labelled E2550UA or MK4015 or 2800F). */ -#define VERSION "v4.2 Eberhard Moenkeberg " +#define VERSION "v4.3 Eberhard Moenkeberg " /* Copyright (C) 1993, 1994, 1995 Eberhard Moenkeberg * @@ -274,6 +274,11 @@ * is user-configurable (even at runtime), but to get aware of this, one * needs a special mental quality: the ability to read. * + * 4.3 CD200F does not like to receive a command while the drive is + * reading the ToC; still trying to solve it. + * Removed some redundant verify_area calls (yes, Heiko Eissfeldt + * is visiting all the Linux CDROM drivers ;-). + * * * TODO * @@ -728,6 +733,12 @@ static struct timer_list audio_timer = { NULL, NULL, 0, 0, mark_timeout_audio}; */ static void msg(int level, const char *fmt, ...) { +#if DISTRIBUTION +#define MSG_LEVEL KERN_NOTICE +#else +#define MSG_LEVEL KERN_INFO +#endif DISTRIBUTION + char buf[256]; va_list args; @@ -735,7 +746,7 @@ static void msg(int level, const char *fmt, ...) msgnum++; if (msgnum>99) msgnum=0; - sprintf(buf, KERN_NOTICE "%s-%d [%02d]: ", major_name, d, msgnum); + sprintf(buf, MSG_LEVEL "%s-%d [%02d]: ", major_name, d, msgnum); va_start(args, fmt); vsprintf(&buf[18], fmt, args); va_end(args); @@ -1645,7 +1656,7 @@ static int cc_SetSpeed(u_char speed, u_char x1, u_char x2) drvcmd[2]=0; drvcmd[3]=150; } - flags_cmd_out=f_putcmd|f_ResponseStatus; + flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; } else if (famT_drive) { @@ -3975,7 +3986,7 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd, case CDROMREADTOCENTRY: /* Read an entry in the table of contents */ msg(DBG_IOC,"ioctl: CDROMREADTOCENTRY entered.\n"); - st=verify_area(VERIFY_READ, (void *) arg, sizeof(struct cdrom_tocentry)); + st=verify_area(VERIFY_WRITE,(void *) arg, sizeof(struct cdrom_tocentry)); if (st) return (st); memcpy_fromfs(&tocentry, (void *) arg, sizeof(struct cdrom_tocentry)); i=tocentry.cdte_track; @@ -3993,8 +4004,6 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd, else if (tocentry.cdte_format==CDROM_LBA) /* blk required */ tocentry.cdte_addr.lba=msf2blk(D_S[d].TocBuffer[i].address); else return (-EINVAL); - st=verify_area(VERIFY_WRITE,(void *) arg, sizeof(struct cdrom_tocentry)); - if (st) return (st); memcpy_tofs((void *) arg, &tocentry, sizeof(struct cdrom_tocentry)); return (0); @@ -4069,8 +4078,6 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd, } st=verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct cdrom_subchnl)); if (st) return (st); - st=verify_area(VERIFY_READ, (void *) arg, sizeof(struct cdrom_subchnl)); - if (st) return (st); memcpy_fromfs(&SC, (void *) arg, sizeof(struct cdrom_subchnl)); switch (D_S[d].audio_state) { @@ -4355,7 +4362,7 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd, case CDROMMULTISESSION: /* tell start-of-last-session */ msg(DBG_IOC,"ioctl: CDROMMULTISESSION entered.\n"); - st=verify_area(VERIFY_READ, (void *) arg, sizeof(struct cdrom_multisession)); + st=verify_area(VERIFY_WRITE,(void *) arg, sizeof(struct cdrom_multisession)); if (st) return (st); memcpy_fromfs(&ms_info, (void *) arg, sizeof(struct cdrom_multisession)); if (ms_info.addr_format==CDROM_MSF) /* MSF-bin requested */ @@ -4365,8 +4372,6 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd, else return (-EINVAL); if (D_S[d].f_multisession) ms_info.xa_flag=1; /* valid redirection address */ else ms_info.xa_flag=0; /* invalid redirection address */ - st=verify_area(VERIFY_WRITE,(void *) arg, sizeof(struct cdrom_multisession)); - if (st) return (st); memcpy_tofs((void *) arg, &ms_info, sizeof(struct cdrom_multisession)); msg(DBG_MUL,"ioctl: CDROMMULTISESSION done (%d, %08X).\n", ms_info.xa_flag, ms_info.addr.lba); diff --git a/drivers/char/Config.in b/drivers/char/Config.in index 4a1f1d50535e..160b4fc462fa 100644 --- a/drivers/char/Config.in +++ b/drivers/char/Config.in @@ -52,13 +52,13 @@ bool 'Watchdog Timer Support' CONFIG_WATCHDOG if [ "$CONFIG_WATCHDOG" != "n" ]; then bool ' Disable watchdog shutdown on close' CONFIG_WATCHDOG_NOWAYOUT tristate ' WDT Watchdog timer' CONFIG_WDT - if [ "$CONFIG_WDT" = "y" ]; then + if [ "$CONFIG_WDT" != "n" ]; then bool ' WDT501 features' CONFIG_WDT_501 if [ "$CONFIG_WDT_501" = "y" ]; then bool ' Fan Tachometer' CONFIG_WDT_501_FAN fi else - bool ' Software Watchdog' CONFIG_SOFT_WATCHDOG + tristate ' Software Watchdog' CONFIG_SOFT_WATCHDOG fi fi bool 'Enhanced Real Time Clock Support' CONFIG_RTC diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 91c2a7049e06..866706edabc7 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -127,10 +127,14 @@ ifeq ($(CONFIG_UMISC),y) M = y endif -ifdef CONFIG_SOFT_WATCHDOG -L_OBJS += softdog.o +ifeq ($(CONFIG_SOFT_WATCHDOG),y) M = y -# This is not modularized, so if configured then "misc.c" will be resident +L_OBJS += softdog.o +else + ifeq ($(CONFIG_SOFT_WATCHDOG),m) + M_OBJS += softdog.o + MM = m + endif endif ifdef CONFIG_SUN_MOUSE diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 2d9c711be00d..10a981186f44 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -173,7 +173,7 @@ static inline void kb_wait(void) for (i=0; i<0x100000; i++) if ((inb_p(0x64) & 0x02) == 0) return; - printk("Keyboard timed out\n"); + printk(KERN_WARNING "Keyboard timed out\n"); } static inline void send_cmd(unsigned char c) @@ -361,7 +361,7 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs) if (!(status & 0x21)) { /* neither ODS nor OBF */ scancode = inb(0x60); /* read data anyway */ #if 0 - printk("keyboard: status 0x%x mask 0x%x data 0x%x\n", + printk(KERN_DEBUG "keyboard: status 0x%x mask 0x%x data 0x%x\n", status, kbd_read_mask, scancode); #endif } @@ -383,12 +383,13 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs) /* strange ... */ reply_expected = 1; #if 0 - printk("keyboard reply expected - got %02x\n", scancode); + printk(KERN_DEBUG "keyboard reply expected - got %02x\n", + scancode); #endif } if (scancode == 0) { #ifdef KBD_REPORT_ERR - printk("keyboard buffer overflow\n"); + printk(KERN_INFO "keyboard buffer overflow\n"); #endif prev_scancode = 0; goto end_kbd_intr; @@ -412,7 +413,7 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs) #ifndef KBD_IS_FOCUS_9000 #ifdef KBD_REPORT_ERR if (!raw_mode) - printk("keyboard error\n"); + printk(KERN_DEBUG "keyboard error\n"); #endif #endif prev_scancode = 0; @@ -445,7 +446,7 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs) } else { #ifdef KBD_REPORT_UNKN if (!raw_mode) - printk("keyboard: unknown e1 escape sequence\n"); + printk(KERN_INFO "keyboard: unknown e1 escape sequence\n"); #endif prev_scancode = 0; goto end_kbd_intr; @@ -473,7 +474,8 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs) else { #ifdef KBD_REPORT_UNKN if (!raw_mode) - printk("keyboard: unknown scancode e0 %02x\n", scancode); + printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n", + scancode); #endif goto end_kbd_intr; } @@ -494,8 +496,8 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs) if (!keycode) { if (!raw_mode) { #ifdef KBD_REPORT_UNKN - printk("keyboard: unrecognized scancode (%02x) - ignored\n" - , scancode); + printk(KERN_INFO "keyboard: unrecognized scancode (%02x)" + " - ignored\n", scancode); #endif } goto end_kbd_intr; @@ -796,7 +798,7 @@ static void do_spec(unsigned char value, char up_flag) static void do_lowercase(unsigned char value, char up_flag) { - printk("keyboard.c: do_lowercase was called - impossible\n"); + printk(KERN_ERR "keyboard.c: do_lowercase was called - impossible\n"); } static void do_self(unsigned char value, char up_flag) @@ -878,7 +880,7 @@ static void do_fn(unsigned char value, char up_flag) if (func_table[value]) puts_queue(func_table[value]); } else - printk("do_fn called with value=%d\n", value); + printk(KERN_ERR "do_fn called with value=%d\n", value); } static void do_pad(unsigned char value, char up_flag) @@ -1313,7 +1315,8 @@ static int initialize_kbd(void) */ kbd_write(KBD_CNTL_REG, KBD_SELF_TEST); if (kbd_wait_for_input() != 0x55) { - printk("initialize_kbd: keyboard failed self test.\n"); + printk(KERN_WARNING "initialize_kbd: " + "keyboard failed self test.\n"); restore_flags(flags); return(-1); } @@ -1325,7 +1328,8 @@ static int initialize_kbd(void) */ kbd_write(KBD_CNTL_REG, KBD_SELF_TEST2); if (kbd_wait_for_input() != 0x00) { - printk("initialize_kbd: keyboard failed self test 2.\n"); + printk(KERN_WARNING "initialize_kbd: " + "keyboard failed self test 2.\n"); restore_flags(flags); return(-1); } @@ -1341,13 +1345,15 @@ static int initialize_kbd(void) */ kbd_write(KBD_DATA_REG, KBD_RESET); if (kbd_wait_for_input() != KBD_ACK) { - printk("initialize_kbd: reset kbd failed, no ACK.\n"); + printk(KERN_WARNING "initialize_kbd: " + "reset kbd failed, no ACK.\n"); restore_flags(flags); return(-1); } if (kbd_wait_for_input() != KBD_POR) { - printk("initialize_kbd: reset kbd failed, not POR.\n"); + printk(KERN_WARNING "initialize_kbd: " + "reset kbd failed, not POR.\n"); restore_flags(flags); return(-1); } @@ -1357,7 +1363,8 @@ static int initialize_kbd(void) */ kbd_write(KBD_DATA_REG, KBD_DISABLE); if (kbd_wait_for_input() != KBD_ACK) { - printk("initialize_kbd: disable kbd failed, no ACK.\n"); + printk(KERN_WARNING "initialize_kbd: " + "disable kbd failed, no ACK.\n"); restore_flags(flags); return(-1); } @@ -1375,7 +1382,8 @@ static int initialize_kbd(void) */ kbd_write(KBD_DATA_REG, KBD_ENABLE); if (kbd_wait_for_input() != KBD_ACK) { - printk("initialize_kbd: keyboard enable failed.\n"); + printk(KERN_WARNING "initialize_kbd: " + "keyboard enable failed.\n"); restore_flags(flags); return(-1); } diff --git a/drivers/char/softdog.c b/drivers/char/softdog.c index 1a32144890ff..d8d71aec0411 100644 --- a/drivers/char/softdog.c +++ b/drivers/char/softdog.c @@ -1,5 +1,5 @@ /* - * SoftDog 0.02: A Software Watchdog Device + * SoftDog 0.04: A Software Watchdog Device * * (c) Copyright 1995 Alan Cox * @@ -16,8 +16,15 @@ * * Software only watchdog driver. Unlike its big brother the WDT501P * driver this won't always recover a failed machine. + * + * 03/96: Angelo Haritsis : + * Modularised. + * Added soft_margin; use upon insmod to change the timer delay. + * NB: uses same minor as wdt (WATCHDOG_MINOR); we could use separate + * minors. */ +#include #include #include #include @@ -26,7 +33,9 @@ #include #define WATCHDOG_MINOR 130 -#define TIMER_MARGIN (60*HZ) /* Allow 1 minute */ +#define TIMER_MARGIN 60 /* (secs) Default is 1 minute */ + +static int soft_margin = TIMER_MARGIN; /* in seconds */ /* * Our timer @@ -43,8 +52,13 @@ static int timer_alive = 0; static void watchdog_fire(unsigned long data) { extern void hard_reset_now(void); +#ifdef ONLY_TESTING + printk(KERN_CRIT "SOFTDOG: Would Reboot.\n"); +#else + printk(KERN_CRIT "SOFTDOG: Initiating system reboot.\n"); hard_reset_now(); printk("WATCHDOG: Reboot didn't ?????\n"); +#endif } /* @@ -55,10 +69,11 @@ static int softdog_open(struct inode *inode, struct file *file) { if(timer_alive) return -EBUSY; + MOD_INC_USE_COUNT; /* * Activate timer */ - watchdog_ticktock.expires=jiffies+TIMER_MARGIN; + watchdog_ticktock.expires=jiffies + (soft_margin * HZ); add_timer(&watchdog_ticktock); timer_alive++; return 0; @@ -68,11 +83,13 @@ static void softdog_release(struct inode *inode, struct file *file) { /* * Shut off the timer. + * Lock it in if it's a module and we defined ...NOWAYOUT */ #ifndef CONFIG_WATCHDOG_NOWAYOUT del_timer(&watchdog_ticktock); -#endif + MOD_DEC_USE_COUNT; timer_alive=0; +#endif } static int softdog_write(struct inode *inode, struct file *file, const char *data, int len) @@ -81,39 +98,50 @@ static int softdog_write(struct inode *inode, struct file *file, const char *dat * Refresh the timer. */ del_timer(&watchdog_ticktock); - watchdog_ticktock.expires=jiffies+TIMER_MARGIN; + watchdog_ticktock.expires=jiffies + (soft_margin * HZ); add_timer(&watchdog_ticktock); return 1; } -/* - * The mouse stuff ought to be renamed misc_register etc before 1.4... - */ - -void watchdog_init(void) +static struct file_operations softdog_fops= +{ + NULL, /* Seek */ + NULL, /* Read */ + softdog_write, /* Write */ + NULL, /* Readdir */ + NULL, /* Select */ + NULL, /* Ioctl */ + NULL, /* MMap */ + softdog_open, + softdog_release, + NULL, + NULL /* Fasync */ +}; + +static struct miscdevice softdog_miscdev= { - static struct file_operations softdog_fops= - { - NULL, /* Seek */ - NULL, /* Read */ - softdog_write, /* Write */ - NULL, /* Readdir */ - NULL, /* Select */ - NULL, /* Ioctl */ - NULL, /* MMap */ - softdog_open, - softdog_release, - NULL, - NULL /* Fasync */ - }; - static struct miscdevice softdog_mouse={ - WATCHDOG_MINOR, - "softdog", - &softdog_fops - }; + WATCHDOG_MINOR, + "softdog", + &softdog_fops +}; - misc_register(&softdog_mouse); +void watchdog_init(void) +{ + misc_register(&softdog_miscdev); init_timer(&watchdog_ticktock); watchdog_ticktock.function=watchdog_fire; - printk("Software Watchdog Timer: 0.03\n"); + printk("Software Watchdog Timer: 0.04, timer margin: %d sec\n", soft_margin); } + +#ifdef MODULE +int init_module(void) +{ + watchdog_init(); + return 0; +} + +void cleanup_module(void) +{ + misc_deregister(&softdog_miscdev); +} +#endif diff --git a/drivers/char/vt.c b/drivers/char/vt.c index d7c4f7fa6a08..0d9254054dd5 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -236,6 +236,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, * If the time is zero, turn off sound ourselves. */ ticks = HZ * ((arg >> 16) & 0xffff) / 1000; + if ((arg & 0xffff) == 0 ) arg |= 1; /* jp: huh? */ count = ticks ? (1193180 / (arg & 0xffff)) : 0; kd_mksound(count, ticks); return 0; @@ -700,7 +701,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, if (!perm) return -EPERM; - i = verify_area(VERIFY_WRITE, (void *)vtmode, sizeof(struct vt_mode)); + i = verify_area(VERIFY_READ, (void *)vtmode, sizeof(struct vt_mode)); if (i) return i; mode = get_user(&vtmode->mode); diff --git a/drivers/isdn/isdn_tty.c b/drivers/isdn/isdn_tty.c index f03078fe6bbe..efa95c3562da 100644 --- a/drivers/isdn/isdn_tty.c +++ b/drivers/isdn/isdn_tty.c @@ -219,7 +219,7 @@ void isdn_tty_modem_hup(modem_info * info) } } -static inline int isdn_tty_paranoia_check(modem_info * info, dev_t device, const char *routine) +static inline int isdn_tty_paranoia_check(modem_info * info, kdev_t device, const char *routine) { #ifdef MODEM_PARANOIA_CHECK if (!info) { diff --git a/drivers/net/Config.in b/drivers/net/Config.in index 3dec452a06ad..9117c69fe935 100644 --- a/drivers/net/Config.in +++ b/drivers/net/Config.in @@ -20,6 +20,7 @@ tristate 'SLIP (serial line) support' CONFIG_SLIP if [ "$CONFIG_SLIP" != "n" ]; then bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED bool ' Keepalive and linefill' CONFIG_SLIP_SMART + bool ' Six bit SLIP encapsulation' CONFIG_SLIP_MODE_SLIP6 fi bool 'Radio network interfaces' CONFIG_NET_RADIO if [ "$CONFIG_NET_RADIO" != "n" ]; then diff --git a/drivers/net/slip.c b/drivers/net/slip.c index 4d3c053bb22e..56f881d39a42 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c @@ -56,9 +56,6 @@ #include #include -/* Undef this, if you don't need 6bit encapsulation code in the driver */ -#define CONFIG_SLIP_MODE_SLIP6 - #include #include #include diff --git a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c index de49f45f0a3c..14135464fd42 100644 --- a/drivers/scsi/ultrastor.c +++ b/drivers/scsi/ultrastor.c @@ -951,7 +951,7 @@ int ultrastor_abort(Scsi_Cmnd *SCpnt) return SCSI_ABORT_SUCCESS; } -int ultrastor_reset(Scsi_Cmnd * SCpnt) +int ultrastor_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags) { int flags; register int i; @@ -1044,7 +1044,7 @@ static void ultrastor_interrupt(int irq, void *dev_id, struct pt_regs *regs) printk("Ux4F interrupt: bad MSCP address %x\n", (unsigned int) mscp); /* A command has been lost. Reset and report an error for all commands. */ - ultrastor_reset(NULL); + ultrastor_reset(NULL, 0); return; } #endif diff --git a/drivers/scsi/ultrastor.h b/drivers/scsi/ultrastor.h index 10cf63f2e841..7a40acc5820f 100644 --- a/drivers/scsi/ultrastor.h +++ b/drivers/scsi/ultrastor.h @@ -18,7 +18,7 @@ int ultrastor_detect(Scsi_Host_Template *); const char *ultrastor_info(struct Scsi_Host * shpnt); int ultrastor_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int ultrastor_abort(Scsi_Cmnd *); -int ultrastor_reset(Scsi_Cmnd *); +int ultrastor_reset(Scsi_Cmnd *, unsigned int); int ultrastor_biosparam(Disk *, kdev_t, int *); diff --git a/fs/Config.in b/fs/Config.in index 999fb5f5dc05..208856183fe8 100644 --- a/fs/Config.in +++ b/fs/Config.in @@ -5,6 +5,7 @@ mainmenu_option next_comment comment 'Filesystems' bool 'Quota support' CONFIG_QUOTA +bool 'Mandatory lock support' CONFIG_LOCK_MANDATORY tristate 'Minix fs support' CONFIG_MINIX_FS tristate 'Extended fs support' CONFIG_EXT_FS tristate 'Second extended fs support' CONFIG_EXT2_FS diff --git a/fs/binfmt_java.c b/fs/binfmt_java.c index 0e0c407eddc4..36fdd9258597 100644 --- a/fs/binfmt_java.c +++ b/fs/binfmt_java.c @@ -14,7 +14,10 @@ #define _PATH_JAVA "/usr/bin/java" #define _PATH_APPLET "/usr/bin/appletviewer" -#define _PATH_SH "/bin/sh" +#define _PATH_SH "/bin/bash" + +char binfmt_java_interpreter[65] = _PATH_JAVA; +char binfmt_java_appletviewer[65] = _PATH_APPLET; static int do_load_script(struct linux_binprm *bprm,struct pt_regs *regs) { @@ -47,7 +50,7 @@ static int do_load_script(struct linux_binprm *bprm,struct pt_regs *regs) bprm->p = copy_strings(1, &i_name, bprm->page, bprm->p, 2); bprm->argc++; - strcpy (bprm->buf, _PATH_JAVA); + strcpy (bprm->buf, binfmt_java_interpreter); cp = bprm->buf; bprm->p = copy_strings(1, &cp, bprm->page, bprm->p, 2); bprm->argc++; @@ -102,12 +105,12 @@ static int do_load_applet(struct linux_binprm *bprm,struct pt_regs *regs) bprm->p = copy_strings(1, &i_name, bprm->page, bprm->p, 2); bprm->argc++; - strcpy (bprm->buf, _PATH_APPLET); + strcpy (bprm->buf, binfmt_java_appletviewer); cp = bprm->buf; bprm->p = copy_strings(1, &cp, bprm->page, bprm->p, 2); bprm->argc++; - strcpy (bprm->buf, _PATH_BSHELL); + strcpy (bprm->buf, _PATH_SH); interp = bprm->buf; if ((i_name = strrchr (bprm->buf, '/')) != NULL) i_name++; diff --git a/fs/devices.c b/fs/devices.c index f161ca730db0..94e5cad61a81 100644 --- a/fs/devices.c +++ b/fs/devices.c @@ -25,7 +25,7 @@ /* serial module kerneld load support */ struct tty_driver *get_tty_driver(kdev_t device); #define isa_tty_dev(ma) (ma == TTY_MAJOR || ma == TTYAUX_MAJOR) -#define need_serial(ma,mi) (get_tty_driver(to_kdev_t(MKDEV(ma,mi))) == NULL) +#define need_serial(ma,mi) (get_tty_driver(MKDEV(ma,mi)) == NULL) #endif struct device_struct { diff --git a/fs/dquot.c b/fs/dquot.c index 414b758a2eed..4dd1683ea389 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -904,7 +904,8 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr, char direction) void dquot_init(void) { - printk("VFS: Diskquotas version %s initialized\r\n", __DQUOT_VERSION__); + printk(KERN_NOTICE "VFS: Diskquotas version %s initialized\r\n", + __DQUOT_VERSION__); memset(hash_table, 0, sizeof(hash_table)); memset((caddr_t)&dqstats, 0, sizeof(dqstats)); first_dquot = NODQUOT; diff --git a/fs/file_table.c b/fs/file_table.c index 67fa62dc2c94..a1f215c73315 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -124,7 +124,7 @@ struct file * get_empty_filp(void) #ifdef CONFIG_QUOTA -void add_dquot_ref(dev_t dev, short type) +void add_dquot_ref(kdev_t dev, short type) { struct file *filp; int cnt; @@ -139,7 +139,7 @@ void add_dquot_ref(dev_t dev, short type) } } -void reset_dquot_ptrs(dev_t dev, short type) +void reset_dquot_ptrs(kdev_t dev, short type) { struct file *filp; int cnt; diff --git a/fs/locks.c b/fs/locks.c index b8038e468ee5..c7949bd769d2 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -75,8 +75,14 @@ * Fixed deadlock condition for pathological code that mixes calls to * flock() and fcntl(). * Andy Walker (andy@lysaker.kvaerner.no), April 29, 1996. + * + * BUG: MUST DISALLOW MANDATORY LOCK ON NFS/SMB/NCP FILE SYSTEM + * TO MATCH SYS5.4 SEMANTICS. + * */ +#include + #include #include #include @@ -336,6 +342,7 @@ int locks_verify_locked(struct inode *inode) int locks_mandatory_locked(struct inode *inode) { +#ifdef CONFIG_LOCK_MANDATORY struct file_lock *fl; /* Search the lock list for this inode for any POSIX locks. @@ -344,6 +351,7 @@ int locks_mandatory_locked(struct inode *inode) if ((fl->fl_flags & F_POSIX) && (fl->fl_owner != current)) return (-EAGAIN); } +#endif return (0); } @@ -353,16 +361,19 @@ int locks_verify_area(int read_write, struct inode *inode, struct file *filp, /* Candidates for mandatory locking have the setgid bit set * but no group execute bit - an otherwise meaningless combination. */ +#ifdef CONFIG_LOCK_MANDATORY if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) return (locks_mandatory_area(read_write, inode, filp, offset, count)); +#endif return (0); } - + int locks_mandatory_area(int read_write, struct inode *inode, struct file *filp, unsigned int offset, unsigned int count) { +#ifdef CONFIG_LOCK_MANDATORY struct file_lock *fl; repeat: @@ -401,6 +412,7 @@ repeat: goto repeat; } } +#endif return (0); } @@ -936,8 +948,8 @@ static char *lock_get_status(struct file_lock *fl, char *p, int id, char *pfx) p += sprintf(p, "FLOCK ADVISORY "); } p += sprintf(p, "%s ", (fl->fl_type == F_RDLCK) ? "READ " : "WRITE"); - p += sprintf(p, "%d %04x:%ld %ld %ld ", - fl->fl_owner->pid, fl->fl_file->f_inode->i_dev, + p += sprintf(p, "%d %s:%ld %ld %ld ", + fl->fl_owner->pid, kdevname(fl->fl_file->f_inode->i_dev), fl->fl_file->f_inode->i_ino, fl->fl_start, fl->fl_end); p += sprintf(p, "%08lx %08lx %08lx %08lx %08lx\n%d:%s", diff --git a/fs/ufs/ufs_inode.c b/fs/ufs/ufs_inode.c index ec568f5026e8..12081f7825ce 100644 --- a/fs/ufs/ufs_inode.c +++ b/fs/ufs/ufs_inode.c @@ -185,7 +185,7 @@ void ufs_read_inode(struct inode * inode) if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { /* XXX - should be ui_db[1] on little endian ufs filesystems */ - inode->i_rdev = ufsip->ui_db[0]; + inode->i_rdev = to_kdev_t(ufsip->ui_db[0]); } /* XXX - implement fast and slow symlinks */ diff --git a/include/linux/cm206.h b/include/linux/cm206.h index 32b7e3bda827..a052a26a75b8 100644 --- a/include/linux/cm206.h +++ b/include/linux/cm206.h @@ -56,7 +56,7 @@ dc_mask_transmit_ready) /* now some constants related to the cm206 */ -/* another drive status byte, echoed by the cm206 on most commmands */ +/* another drive status byte, echoed by the cm206 on most commands */ #define dsb_error_condition 0x1 #define dsb_play_in_progress 0x4 diff --git a/include/linux/mcdx.h b/include/linux/mcdx.h index 18652e909f41..41437f32ff29 100644 --- a/include/linux/mcdx.h +++ b/include/linux/mcdx.h @@ -1,7 +1,7 @@ /* * Definitions for the Mitsumi CDROM interface * Copyright (C) 1995 Heiko Schlittermann - * VERSION: 1.9 + * VERSION: 2.2 * * 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 @@ -32,167 +32,102 @@ * */ +#ifndef __MCDX_H +#define __MCDX_H /* - * The following lines are for user configuration - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * PLEASE CONFIGURE THIS ACCORIDNG TO YOURS HARDWARE/JUMPER SETTINGS. * - * {0|1} -- 1 if you want the driver detect your drive, may crash and - * needs a long time to seek. The higher the address the longer the - * seek. + * o MCDX_NDRIVES : number of used entries of the following table + * o MCDX_DRIVEMAP : table of {i/o base, irq} per controller * - * WARNING: AUTOPROBE doesn't work. + * NOTE: I didn't get a drive at irq 9(2) working. Not even alone. */ -#define MCDX_AUTOPROBE 0 - -/* - * Drive specific settings according to the jumpers on the controller - * board(s). - * o MCDX_NDRIVES : number of used entries of the following table - * o MCDX_DRIVEMAP : table of {i/o base, irq} per controller - * - * NOTE: I didn't get a drive at irq 9(2) working. Not even alone. - */ -#if MCDX_AUTOPROBE == 0 - #define MCDX_NDRIVES 1 - #define MCDX_DRIVEMAP { \ - {0x300, 11}, \ + /* #define I_WAS_IN_MCDX_H */ +#define MCDX_NDRIVES 1 +#define MCDX_DRIVEMAP { {0x300, 11}, \ {0x304, 05}, \ {0x000, 00}, \ {0x000, 00}, \ {0x000, 00}, \ - } -#else - #error Autoprobing is not implemented yet. -#endif - -#ifndef MCDX_QUIET -#define MCDX_QUIET 1 -#endif - -#ifndef MCDX_DEBUG -#define MCDX_DEBUG 0 -#endif - -/* *** make the following line uncommented, if you're sure, - * *** all configuration is done */ -/* #define I_WAS_HERE */ +} + +/* + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!NO USER INTERVENTION NEEDED BELOW + * If You are shure that all configuration is done, please uncomment the + * line below. + */ -/* The name of the device */ -#define MCDX "mcdx" +#undef MCDX_DEBUG /* This is *REALLY* only for developement! */ -#if MCDX_QUIET == 1 -#define INFO(x) -#define xinfo(fmt, args...) +#ifdef MCDX_DEBUG +#define MCDX_TRACE(x) printk x +#define MCDX_TRACE_IOCTL(x) printk x #else -#define INFO(x) warn x -#define xinfo(fmt, args...) _warn(fmt, ## args) +#define MCDX_TRACE(x) +#define MCDX_TRACE_IOCTL(x) #endif -#define WARN(x) warn x -#define xwarn(fmt, args...) _warn(fmt, ## args) -#define _warn warn - -#if MCDX_DEBUG == 1 -#define TRACE(x) trace x -#define INIT 0 -#define MALLOC 0 -#define IOCTL 0 -#define PLAYTRK 0 -#define SUBCHNL 0 -#define TOCHDR 0 -#define MS 0 -#define PLAYMSF 0 -#define READTOC 0 -#define OPENCLOSE 0 -#define HW 0 -#define TALK 0 -#define IRQ 0 -#define TRANSFER 0 -#define REQUEST 0 -#define SLEEP 0 -#else -#define TRACE(x) -#endif +/* The name of the device */ +#define MCDX "mcdx" -/* The following addresses are taken from the Mitsumi Reference - * and describe the possible i/o range for the controller. +/* + * Per controller 4 bytes i/o are needed. */ -#define MCDX_IO_BEGIN ((char*) 0x300) /* first base of i/o addr */ -#define MCDX_IO_END ((char*) 0x3fc) /* last base of i/o addr */ - -/* Per controller 4 bytes i/o are needed. */ #define MCDX_IO_SIZE 4 -/* - * Bits +/* + * Masks for the status byte, returned from every command, set if + * the description is true */ - -/* The status byte, returned from every command, set if - * the description is true */ #define MCDX_RBIT_OPEN 0x80 /* door is open */ #define MCDX_RBIT_DISKSET 0x40 /* disk set (recognised) */ #define MCDX_RBIT_CHANGED 0x20 /* disk was changed */ #define MCDX_RBIT_CHECK 0x10 /* disk rotates, servo is on */ -#define MCDX_RBIT_AUDIOTR 0x08 /* current track is audio */ +#define MCDX_RBIT_AUDIOTR 0x08 /* current track is audio */ #define MCDX_RBIT_RDERR 0x04 /* read error, refer SENSE KEY */ #define MCDX_RBIT_AUDIOBS 0x02 /* currently playing audio */ #define MCDX_RBIT_CMDERR 0x01 /* command, param or format error */ -/* The I/O Register holding the h/w status of the drive, - * can be read at i/o base + 1 */ +/* + * The I/O Register holding the h/w status of the drive, + * can be read at i/o base + 1 + */ #define MCDX_RBIT_DOOR 0x10 /* door is open */ #define MCDX_RBIT_STEN 0x04 /* if 0, i/o base contains drive status */ #define MCDX_RBIT_DTEN 0x02 /* if 0, i/o base contains data */ /* - * The commands. + * The commands. */ - -#define OPCODE 1 /* offset of opcode */ -#define MCDX_CMD_REQUEST_TOC 1, 0x10 -#define MCDX_CMD_REQUEST_STATUS 1, 0x40 -#define MCDX_CMD_RESET 1, 0x60 -#define MCDX_CMD_REQUEST_DRIVE_MODE 1, 0xc2 -#define MCDX_CMD_SET_INTERLEAVE 2, 0xc8, 0 -#define MCDX_CMD_DATAMODE_SET 2, 0xa0, 0 - #define MCDX_DATAMODE1 0x01 - #define MCDX_DATAMODE2 0x02 -#define MCDX_CMD_LOCK_DOOR 2, 0xfe, 0 +#define MCDX_CMD_GET_TOC 0x10 +#define MCDX_CMD_GET_MDISK_INFO 0x11 +#define MCDX_CMD_GET_SUBQ_CODE 0x20 +#define MCDX_CMD_GET_STATUS 0x40 +#define MCDX_CMD_SET_DRIVE_MODE 0x50 +#define MCDX_CMD_RESET 0x60 +#define MCDX_CMD_HOLD 0x70 +#define MCDX_CMD_CONFIG 0x90 +#define MCDX_CMD_SET_ATTENATOR 0xae +#define MCDX_CMD_PLAY 0xc0 +#define MCDX_CMD_PLAY_2X 0xc1 +#define MCDX_CMD_GET_DRIVE_MODE 0xc2 +#define MCDX_CMD_SET_INTERLEAVE 0xc8 +#define MCDX_CMD_GET_FIRMWARE 0xdc +#define MCDX_CMD_SET_DATA_MODE 0xa0 +#define MCDX_CMD_STOP 0xf0 +#define MCDX_CMD_EJECT 0xf6 +#define MCDX_CMD_CLOSE_DOOR 0xf8 +#define MCDX_CMD_LOCK_DOOR 0xfe #define READ_AHEAD 4 /* 8 Sectors (4K) */ -/* Useful macros */ -#define e_door(x) ((x) & MCDX_RBIT_OPEN) -#define e_check(x) (~(x) & MCDX_RBIT_CHECK) -#define e_notset(x) (~(x) & MCDX_RBIT_DISKSET) -#define e_changed(x) ((x) & MCDX_RBIT_CHANGED) -#define e_audio(x) ((x) & MCDX_RBIT_AUDIOTR) -#define e_audiobusy(x) ((x) & MCDX_RBIT_AUDIOBS) -#define e_cmderr(x) ((x) & MCDX_RBIT_CMDERR) -#define e_readerr(x) ((x) & MCDX_RBIT_RDERR) - -/** no drive specific */ #define MCDX_CDBLK 2048 /* 2048 cooked data each blk */ -#define MCDX_DATA_TIMEOUT (HZ/10) /* 0.1 second */ - -/* - * Access to the msf array - */ -#define MSF_MIN 0 /* minute */ -#define MSF_SEC 1 /* second */ -#define MSF_FRM 2 /* frame */ - -/* - * Errors - */ -#define MCDX_E 1 /* unspec error */ -#define MCDX_ST_EOM 0x0100 /* end of media */ -#define MCDX_ST_DRV 0x00ff /* mask to query the drive status */ +#define MCDX_DATA_TIMEOUT (HZ/10) /* 0.1 second */ -#ifndef I_WAS_HERE +#ifndef I_WAS_IN_MCDX_H #warning You have not edited mcdx.h #warning Perhaps irq and i/o settings are wrong. #endif -/* ex:set ts=4 sw=4: */ +#endif /* __MCDX_H */ \ No newline at end of file diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 82b1c8103a90..07b078c9000c 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -110,7 +110,7 @@ struct sk_buff unsigned char *data; /* Data head pointer */ unsigned char *tail; /* Tail pointer */ unsigned char *end; /* End pointer */ - void (*destructor)(struct sk_buff *this); /* Destruct function */ + void (*destructor)(struct sk_buff *); /* Destruct function */ }; #ifdef CONFIG_SKB_LARGE diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 8de1b562513e..d819661be4b8 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -59,6 +59,8 @@ struct __sysctl_args { #define KERN_REALROOTDEV 16 /* real root device to mount after initrd */ #define KERN_NFSRNAME 17 /* NFS root name */ #define KERN_NFSRADDRS 18 /* NFS root addresses */ +#define KERN_JAVA_INTERPRETER 19 /* path to Java(tm) interpreter */ +#define KERN_JAVA_APPLETVIEWER 20 /* path to Java(tm) appletviewer */ /* CTL_VM names: */ #define VM_SWAPCTL 1 /* struct: Set vm swapping control */ diff --git a/include/linux/ucdrom.h b/include/linux/ucdrom.h index 34bb37ed297a..8dd2c4524f09 100644 --- a/include/linux/ucdrom.h +++ b/include/linux/ucdrom.h @@ -5,23 +5,24 @@ #ifndef LINUX_UCDROM_H #define LINUX_UCDROM_H +#ifdef __KERNEL__ struct cdrom_device_ops { /* routines */ - int (*open) (dev_t, int); - void (*release) (dev_t); - int (*open_files) (dev_t); /* number of open files */ - int (*drive_status) (dev_t); - int (*disc_status) (dev_t); - int (*media_changed) (dev_t); - int (*tray_move) (dev_t, int); - int (*lock_door) (dev_t, int); - int (*select_speed) (dev_t, int); - int (*select_disc) (dev_t, int); - int (*get_last_session) (dev_t, struct cdrom_multisession *); - int (*get_mcn) (dev_t, struct cdrom_mcn *); - int (*reset) (dev_t dev); /* hard reset device */ - int (*audio_ioctl) (dev_t, unsigned int, void *); /* play stuff */ - int (*dev_ioctl) (dev_t, unsigned int, unsigned long); /* dev-specific */ + int (*open) (kdev_t, int); + void (*release) (kdev_t); + int (*open_files) (kdev_t); /* number of open files */ + int (*drive_status) (kdev_t); + int (*disc_status) (kdev_t); + int (*media_changed) (kdev_t); + int (*tray_move) (kdev_t, int); + int (*lock_door) (kdev_t, int); + int (*select_speed) (kdev_t, int); + int (*select_disc) (kdev_t, int); + int (*get_last_session) (kdev_t, struct cdrom_multisession *); + int (*get_mcn) (kdev_t, struct cdrom_mcn *); + int (*reset) (kdev_t dev); /* hard reset device */ + int (*audio_ioctl) (kdev_t, unsigned int, void *); /* play stuff */ + int (*dev_ioctl) (kdev_t, unsigned int, unsigned long); /* dev-specific */ /* specifications */ const int capability; /* capability flags */ int mask; /* mask of capability: disables them */ @@ -32,6 +33,7 @@ struct cdrom_device_ops { int options; /* options flags */ long mc_flags; /* media change buffer flags (2*16) */ }; +#endif /* capability flags */ #define CDC_CLOSE_TRAY 0x1 /* caddy systems _can't_ close */ @@ -74,15 +76,17 @@ struct cdrom_device_ops { #define CDROM_DRIVE_STATUS 0x5326 /* tray position, etc. */ #define CDROM_DISC_STATUS 0x5327 /* disc type etc. */ -/* Rename and old ioctl */ +/* Rename an old ioctl */ #define CDROM_GET_MCN CDROM_GET_UPC /* medium catalog number */ +#ifdef __KERNEL__ /* the general file operations structure: */ extern struct file_operations cdrom_fops; extern int register_cdrom(int major, char *name, struct cdrom_device_ops *cdo); extern int unregister_cdrom(int major, char *name); +#endif #endif /* LINUX_UCDROM_H */ /* diff --git a/include/net/af_unix.h b/include/net/af_unix.h index 93f4c0a7adb9..86b0e1ea16b1 100644 --- a/include/net/af_unix.h +++ b/include/net/af_unix.h @@ -1,9 +1,14 @@ +#ifndef __LINUX_NET_AFUNIX_H +#define __LINUX_NET_AFUNIX_H extern void unix_proto_init(struct net_proto *pro); extern struct proto_ops unix_proto_ops; extern void unix_inflight(struct file *fp); extern void unix_notinflight(struct file *fp); typedef struct sock unix_socket; +extern void unix_gc(void); -unix_socket *unix_socket_list; +extern unix_socket *unix_socket_list; #define UNIX_MAX_FD 8 + +#endif diff --git a/kernel/ksyms.c b/kernel/ksyms.c index 4d53a2c8b02c..bba28660c5ad 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -74,6 +74,8 @@ extern int sys_tz; extern int request_dma(unsigned int dmanr, char * deviceID); extern void free_dma(unsigned int dmanr); +extern void hard_reset_now(void); + struct symbol_table symbol_table = { #include #ifdef MODVERSIONS @@ -292,6 +294,7 @@ struct symbol_table symbol_table = { X(simple_strtoul), X(system_utsname), X(sys_call_table), + X(hard_reset_now), /* Signal interfaces */ X(send_sig), diff --git a/kernel/sys.c b/kernel/sys.c index 987eed971664..a6821332fa92 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -304,7 +304,7 @@ int acct_process(long exitcode) ac.ac_uid = current->uid; ac.ac_gid = current->gid; ac.ac_tty = (current)->tty == NULL ? -1 : - MKDEV(4, current->tty->device); + kdev_t_to_nr(current->tty->device); ac.ac_flag = 0; if (current->flags & PF_FORKNOEXEC) ac.ac_flag |= AFORK; diff --git a/kernel/sysctl.c b/kernel/sysctl.c index db1787d18e55..f334acdc2be1 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -5,6 +5,7 @@ * Added /proc support, Dec 1995 * Added bdflush entry and intvec min/max checking, 2/23/96, Tom Dyas. * Added hooks for /proc/sys/net (minor, minor patch), 96/4/1, Mike Shaver. + * Added kernel/java-{interpreter,appletviewer}, 96/5/10, Mike Shaver. */ #include @@ -97,6 +98,8 @@ extern int bdf_prm[], bdflush_min[], bdflush_max[]; static int do_securelevel_strategy (ctl_table *, int *, int, void *, size_t *, void *, size_t, void **); +extern char binfmt_java_interpreter[], binfmt_java_appletviewer[]; + /* The default sysctl tables: */ static ctl_table root_table[] = { @@ -138,6 +141,12 @@ static ctl_table kern_table[] = { 0644, NULL, &proc_dostring, &sysctl_string }, {KERN_NFSRNAME, "nfs-root-addrs", nfs_root_addrs, NFS_ROOT_ADDRS_LEN, 0644, NULL, &proc_dostring, &sysctl_string }, +#endif +#ifdef CONFIG_BINFMT_JAVA + {KERN_JAVA_INTERPRETER, "java-interpreter", binfmt_java_interpreter, + 64, 0644, NULL, &proc_dostring, &sysctl_string }, + {KERN_JAVA_APPLETVIEWER, "java-appletviewer", binfmt_java_appletviewer, + 64, 0644, NULL, &proc_dostring, &sysctl_string }, #endif {0} }; diff --git a/net/README b/net/README index 69ba2561c6ec..dbe0c43c9071 100644 --- a/net/README +++ b/net/README @@ -3,26 +3,26 @@ Maintainers and developers for networking code sections Code Section Bug Report Contact -------------------+------------------------------------------- -802 [other ] alan@cymru.net +802 [other ] alan@lxorguk.ukuu.org.uk [token ring ] needs a maintainer/debugger -appletalk alan@cymru.net and netatalk@umich.edu +appletalk alan@lxorguk.ukuu.org.uk and netatalk@umich.edu ax25 jsn@cs.nott.ac.uk -core alan@cymru.net -ethernet alan@cymru.net -ipv4 alan@cymru.net -ipx alan@cymru.net,greg@caldera.com +core alan@lxorguk.ukuu.org.uk +ethernet alan@lxorguk.ukuu.org.uk +ipv4 alan@lxorguk.ukuu.org.uk +ipx alan@lxorguk.ukuu.org.uk,greg@caldera.com netrom jsn@cs.nott.ac.uk -unix alan@cymru.net +unix alan@lxorguk.ukuu.org.uk - If in doubt contact me first. + If in doubt contact me first. --------------------------------------------------------------------------- For commercial UK custom Linux networking projects, drivers and development (but not free support!) I can be contacted via - I^2IT Ltd, The Innovation Centre, University Of Wales + CymruNET Ltd, The Innovation Centre, University Of Wales Swansea SA2 8PP. Fax: +44 1792 295811 Tel: +44 1792 295213 diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c index 17e066e298df..3deceee2afdb 100644 --- a/net/appletalk/aarp.c +++ b/net/appletalk/aarp.c @@ -794,7 +794,7 @@ static char aarp_snap_id[]={0x00,0x00,0x00,0x80,0xF3}; void aarp_proto_init(void) { if((aarp_dl=register_snap_client(aarp_snap_id, aarp_rcv))==NULL) - printk("Unable to register AARP with SNAP.\n"); + printk(KERN_CRIT "Unable to register AARP with SNAP.\n"); init_timer(&aarp_timer); aarp_timer.function=aarp_expire_timeout; aarp_timer.data=0; diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 5c5ee4a7b5c3..2d6bd446a56a 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -830,7 +830,7 @@ int atif_ioctl(int cmd, void *arg) limit=ntohs(nr->nr_lastnet); if(limit-ntohs(nr->nr_firstnet) > 256) { - printk("Too many routes/iface.\n"); + printk(KERN_WARING "Too many routes/iface.\n"); return -EINVAL; } for(ct=ntohs(nr->nr_firstnet);ct<=limit;ct++) @@ -2013,7 +2013,7 @@ void atalk_proto_init(struct net_proto *pro) { (void) sock_register(atalk_proto_ops.family, &atalk_proto_ops); if ((ddp_dl = register_snap_client(ddp_snap_id, atalk_rcv)) == NULL) - printk("Unable to register DDP with SNAP.\n"); + printk(KERN_CRIT "Unable to register DDP with SNAP.\n"); ltalk_packet_type.type=htons(ETH_P_LOCALTALK); dev_add_pack(<alk_packet_type); @@ -2043,7 +2043,7 @@ void atalk_proto_init(struct net_proto *pro) atalk_if_get_info }); - printk(KERN_INFO "Appletalk 0.17 for Linux NET3.034\n"); + printk(KERN_INFO "Appletalk 0.17 for Linux NET3.035\n"); } #ifdef MODULE diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index f151fbbcd394..8006926388a6 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -636,8 +636,10 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void *arg) case AX25_PACLEN: if (ax25_ctl.arg < 16 || ax25_ctl.arg > 65535) return -EINVAL; +#if 0 if (ax25_ctl.arg > 256) /* we probably want this */ - printk("ax25_ctl_ioctl: Warning --- huge paclen %d\n", (int)ax25_ctl.arg); + printk(KERN_WARNING "ax25_ctl_ioctl: Warning --- huge paclen %d\n", (int)ax25_ctl.arg); +#endif ax25->paclen = ax25_ctl.arg; break; @@ -2413,7 +2415,7 @@ void ax25_proto_init(struct net_proto *pro) ax25_cs_get_info }); - printk("G4KLX/GW4PTS AX.25 for Linux. Version 0.32 BETA for Linux NET3.034 (Linux 1.3.77)\n"); + printk(KERN_INFO "G4KLX/GW4PTS AX.25 for Linux. Version 0.32 BETA for Linux NET3.035 (Linux 2.0)\n"); #ifdef CONFIG_BPQETHER proc_net_register(&(struct proc_dir_entry) { @@ -2423,7 +2425,7 @@ void ax25_proto_init(struct net_proto *pro) ax25_bpq_get_info }); - printk("G8BPQ Encapsulation of AX.25 frames enabled\n"); + printk(KERN_INFO "G8BPQ Encapsulation of AX.25 frames enabled\n"); #endif } @@ -2451,7 +2453,7 @@ void ax25_queue_xmit(struct sk_buff *skb, struct device *dev, int pri) int size; if(skb_headroom(skb) < AX25_BPQ_HEADER_LEN) { - printk("ax25_queue_xmit: not enough space to add BPQ Ether header\n"); + printk(KERN_CRIT "ax25_queue_xmit: not enough space to add BPQ Ether header\n"); dev_kfree_skb(skb, FREE_WRITE); return; } @@ -2522,7 +2524,7 @@ int ax25_encapsulate(struct sk_buff *skb, struct device *dev, unsigned short typ *buff++ = AX25_P_ARP; break; default: - printk("wrong protocol type 0x%x2.2\n", type); + printk(KERN_ERR "wrong protocol type 0x%x2.2\n", type); *buff++ = 0; break; } diff --git a/net/ax25/ax25_out.c b/net/ax25/ax25_out.c index c81aabc16e08..a8a7ed58d6fd 100644 --- a/net/ax25/ax25_out.c +++ b/net/ax25/ax25_out.c @@ -99,7 +99,7 @@ void ax25_output(ax25_cb *ax25, struct sk_buff *skb) */ if ((skbn = alloc_skb(mtu + 2 + frontlen, GFP_ATOMIC)) == NULL) { restore_flags(flags); - printk("ax25_output: alloc_skb returned NULL\n"); + printk(KERN_DEBUG "ax25_output: alloc_skb returned NULL\n"); if (skb_device_locked(skb)) skb_device_unlock(skb); return; @@ -268,7 +268,7 @@ void ax25_transmit_buffer(ax25_cb *ax25, struct sk_buff *skb, int type) } if (skb_headroom(skb) < size_ax25_addr(ax25->digipeat)) { - printk("ax25_transmit_buffer: not enough room for digi-peaters\n"); + printk(KERN_CRIT "ax25_transmit_buffer: not enough room for digi-peaters\n"); skb->free = 1; kfree_skb(skb, FREE_WRITE); return; diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c index e0f49ce71477..d770710d94fd 100644 --- a/net/ax25/ax25_route.c +++ b/net/ax25/ax25_route.c @@ -598,7 +598,7 @@ void ax25_dg_build_path(struct sk_buff *skb, ax25_address *addr, struct device * len = ax25_rt->digipeat->ndigi * AX25_ADDR_LEN; if (skb_headroom(skb) < len) { - printk("ax25_dg_build_path: not enough headroom for digis in skb\n"); + printk(KERN_CRIT "ax25_dg_build_path: not enough headroom for digis in skb\n"); return; } @@ -659,7 +659,7 @@ unsigned short ax25_dev_get_value(struct device *dev, int valueno) struct ax25_dev *ax25_dev; if ((ax25_dev = ax25_dev_get_dev(dev)) == NULL) { - printk("ax25_dev_get_flag called with invalid device\n"); + printk(KERN_WARNING "ax25_dev_get_flag called with invalid device\n"); return 1; } diff --git a/net/bridge/br.c b/net/bridge/br.c index 2d9a0863fa99..ad35365cff0c 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c @@ -579,6 +579,7 @@ void br_init(void) { /* (4.8.1) */ int port_no; + printk(KERN_INFO "Ethernet Bridge 002 for NET3.035 (Linux 2.0)\n"); bridge_info.designated_root = bridge_info.bridge_id; /* (4.8.1.1) */ bridge_info.root_path_cost = Zero; bridge_info.root_port = No_port; @@ -876,7 +877,7 @@ int size; unsigned long flags; if (port_info[port_no].state == Disabled) { - printk("send_config_bpdu: port %i not valid\n",port_no); + printk(KERN_DEBUG "send_config_bpdu: port %i not valid\n",port_no); return(-1); } if (br_stats.flags & BR_DEBUG) @@ -887,7 +888,7 @@ unsigned long flags; size = sizeof(Config_bpdu) + dev->hard_header_len; skb = alloc_skb(size, GFP_ATOMIC); if (skb == NULL) { - printk("send_config_bpdu: no skb available\n"); + printk(KERN_DEBUG "send_config_bpdu: no skb available\n"); return(-1); } skb->dev = dev; @@ -935,7 +936,7 @@ int size; unsigned long flags; if (port_info[port_no].state == Disabled) { - printk("send_tcn_bpdu: port %i not valid\n",port_no); + printk(KERN_DEBUG "send_tcn_bpdu: port %i not valid\n",port_no); return(-1); } if (br_stats.flags & BR_DEBUG) @@ -943,7 +944,7 @@ unsigned long flags; size = sizeof(Tcn_bpdu) + dev->hard_header_len; skb = alloc_skb(size, GFP_ATOMIC); if (skb == NULL) { - printk("send_tcn_bpdu: no skb available\n"); + printk(KERN_DEBUG "send_tcn_bpdu: no skb available\n"); return(-1); } skb->dev = dev; @@ -1033,9 +1034,11 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v } } break; +#if 0 default: printk("br_device_event: unknown event [%x]\n", (unsigned int)event); +#endif } return NOTIFY_DONE; } @@ -1054,7 +1057,7 @@ int br_receive_frame(struct sk_buff *skb) /* 3.5 */ printk("br_receive_frame: "); /* sanity */ if (!skb) { - printk("no skb!\n"); + printk(KERN_CRIT "br_receive_frame: no skb!\n"); return(1); } @@ -1134,7 +1137,7 @@ int br_receive_frame(struct sk_buff *skb) /* 3.5 */ skb_device_lock(skb); return(br_forward(skb, port)); default: - printk("br_receive_frame: port [%i] unknown state [%i]\n", + printk(KERN_DEBUG "br_receive_frame: port [%i] unknown state [%i]\n", port, port_info[port].state); return(0); /* pass frame up stack? */ } @@ -1153,7 +1156,7 @@ int br_tx_frame(struct sk_buff *skb) /* 3.5 */ /* sanity */ if (!skb) { - printk("br_tx_frame: no skb!\n"); + printk(KERN_CRIT "br_tx_frame: no skb!\n"); return(0); } /* check for loopback */ @@ -1208,7 +1211,7 @@ int br_learn(struct sk_buff *skb, int port) /* 3.8 */ GFP_ATOMIC); if (!f) { - printk("br_learn: unable to malloc fdb\n"); + printk(KERN_DEBUG "br_learn: unable to malloc fdb\n"); return(-1); } f->port = port; /* source port */ @@ -1260,7 +1263,6 @@ int br_dev_drop(struct sk_buff *skb) int br_forward(struct sk_buff *skb, int port) /* 3.7 */ { struct fdb *f; - unsigned long flags; /* * flood all ports with frames destined for a group @@ -1344,7 +1346,6 @@ int br_flood(struct sk_buff *skb, int port) { int i; struct sk_buff *nskb; - unsigned long flags; for (i = One; i <= No_of_ports; i++) { @@ -1411,7 +1412,7 @@ void br_bpdu(struct sk_buff *skb) /* consumes skb */ received_tcn_bpdu(port, bpdu); break; default: - printk("br_bpdu: received unknown bpdu, type = %i\n", + printk(KERN_DEBUG "br_bpdu: received unknown bpdu, type = %i\n", bpdu->type); /* break; */ } @@ -1422,7 +1423,6 @@ int br_ioctl(unsigned int cmd, void *arg) { int err; struct br_cf bcf; - int i; switch(cmd) { @@ -1447,14 +1447,14 @@ int br_ioctl(unsigned int cmd, void *arg) case BRCMD_BRIDGE_ENABLE: if (br_stats.flags & BR_UP) return(-EALREADY); - printk("br: enabling bridging function\n"); + printk(KERN_DEBUG "br: enabling bridging function\n"); br_stats.flags |= BR_UP; /* enable bridge */ start_hello_timer(); break; case BRCMD_BRIDGE_DISABLE: if (!(br_stats.flags & BR_UP)) return(-EALREADY); - printk("br: disabling bridging function\n"); + printk(KERN_DEBUG "br: disabling bridging function\n"); br_stats.flags &= ~BR_UP; /* disable bridge */ stop_hello_timer(); #if 0 @@ -1468,7 +1468,7 @@ int br_ioctl(unsigned int cmd, void *arg) return(-EINVAL); if (port_info[bcf.arg1].state != Disabled) return(-EALREADY); - printk("br: enabling port %i\n",bcf.arg1); + printk(KERN_DEBUG "br: enabling port %i\n",bcf.arg1); enable_port(bcf.arg1); break; case BRCMD_PORT_DISABLE: @@ -1476,7 +1476,7 @@ int br_ioctl(unsigned int cmd, void *arg) return(-EINVAL); if (port_info[bcf.arg1].state == Disabled) return(-EALREADY); - printk("br: disabling port %i\n",bcf.arg1); + printk(KERN_DEBUG "br: disabling port %i\n",bcf.arg1); disable_port(bcf.arg1); break; case BRCMD_SET_BRIDGE_PRIORITY: diff --git a/net/bridge/br_tree.c b/net/bridge/br_tree.c index 70c34adff693..a1965d49874b 100644 --- a/net/bridge/br_tree.c +++ b/net/bridge/br_tree.c @@ -24,7 +24,6 @@ struct fdb **fhpp = &fhp; static int fdb_inited = 0; int addr_cmp(unsigned char *a1, unsigned char *a2); -static void printk_avl (struct fdb * tree); /* * fdb_head is the AVL tree corresponding to fdb @@ -264,7 +263,7 @@ br_avl_remove (struct fdb * node_to_delete) struct fdb * node = *nodeplace; if (node == avl_br_empty) { /* what? node_to_delete not found in tree? */ - printk("avl_remove: node to delete not found in tree\n"); + printk(KERN_ERR "br: avl_remove: node to delete not found in tree\n"); return(-1); } *stack_ptr++ = nodeplace; stack_count++; diff --git a/net/core/dev.c b/net/core/dev.c index 9598a098ce20..61eeda3db3cf 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -184,7 +184,7 @@ void dev_remove_pack(struct packet_type *pt) return; } } - printk("dev_remove_pack: %p not found.\n", pt); + printk(KERN_WARNING "dev_remove_pack: %p not found.\n", pt); } /***************************************************************************************** @@ -360,7 +360,7 @@ void dev_queue_xmit(struct sk_buff *skb, struct device *dev, int pri) #ifdef CONFIG_NET_DEBUG if (pri >= DEV_NUMBUFFS) { - printk("bad priority in dev_queue_xmit.\n"); + printk(KERN_WARNING "bad priority in dev_queue_xmit.\n"); pri = 1; } #endif diff --git a/net/core/net_alias.c b/net/core/net_alias.c index 0a1785c1d5ae..f74cf0333d79 100644 --- a/net/core/net_alias.c +++ b/net/core/net_alias.c @@ -157,7 +157,7 @@ nat_attach_chg(struct net_alias_type *nat, int delta) if (n_at < 0) { restore_flags(flags); - printk("net_alias: tried to set n_attach < 0 for (family==%d) nat object.\n", + printk(KERN_WARNING "net_alias: tried to set n_attach < 0 for (family==%d) nat object.\n", nat->type); return -1; } @@ -229,7 +229,7 @@ net_alias_devinit(struct device *dev) static int net_alias_hard_start_xmit(struct sk_buff *skb, struct device *dev) { - printk("net_alias: net_alias_hard_start_xmit() for %s called (ignored)!!\n", dev->name); + printk(KERN_WARNING "net_alias: net_alias_hard_start_xmit() for %s called (ignored)!!\n", dev->name); dev_kfree_skb(skb, FREE_WRITE); return 0; } @@ -363,7 +363,7 @@ net_alias_dev_create(struct device *main_dev, int slot, int *err, struct sockadd nat = nat_getbytype(family); if (!nat) { #endif - printk("net_alias_dev_create(%s:%d): unregistered family==%d\n", + printk(KERN_WARNING "net_alias_dev_create(%s:%d): unregistered family==%d\n", main_dev->name, slot, family); /* *err = -EAFNOSUPPORT; */ *err = -EINVAL; @@ -509,7 +509,7 @@ net_alias_dev_delete(struct device *main_dev, int slot, int *err) { if (!(alias = prevdev->next->my_alias)) { - printk("ERROR: net_alias_dev_delete(): incorrect non-alias device after maindev\n"); + printk(KERN_ERR "ERROR: net_alias_dev_delete(): incorrect non-alias device after maindev\n"); continue; /* or should give up? */ } if (alias->slot == slot) break; @@ -534,10 +534,10 @@ net_alias_dev_delete(struct device *main_dev, int slot, int *err) if (*aliasp != alias) if ((aliasp = net_alias_slow_findp(alias_info, alias))) - printk("net_alias_dev_delete(%s): bad hashing recovered\n", alias->name); + printk(KERN_WARNING "net_alias_dev_delete(%s): bad hashing recovered\n", alias->name); else { - printk("ERROR: net_alias_dev_delete(%s): unhashed alias!\n",alias->name); + printk(KERN_ERR "ERROR: net_alias_dev_delete(%s): unhashed alias!\n",alias->name); return NULL; /* ENODEV */ } @@ -654,11 +654,11 @@ net_alias_free(struct device *main_dev) continue; } else - printk("net_alias_free(%s): '%s' is not my alias\n", + printk(KERN_ERR "net_alias_free(%s): '%s' is not my alias\n", main_dev->name, alias->name); } else - printk("net_alias_free(%s): found a non-alias after device!\n", + printk(KERN_ERR "net_alias_free(%s): found a non-alias after device!\n", main_dev->name); dev = dev->next; } @@ -760,7 +760,7 @@ net_alias_dev_rehash(struct device *dev, struct sockaddr *sa) if (!sa) { - printk("ERROR: net_alias_rehash(): NULL sockaddr passed\n"); + printk(KERN_ERR "ERROR: net_alias_rehash(): NULL sockaddr passed\n"); return -1; } @@ -770,7 +770,7 @@ net_alias_dev_rehash(struct device *dev, struct sockaddr *sa) if ( (main_dev = alias->main_dev) == NULL ) { - printk("ERROR: net_alias_rehash for %s: NULL maindev\n", alias->name); + printk(KERN_ERR "ERROR: net_alias_rehash for %s: NULL maindev\n", alias->name); return -1; } @@ -780,7 +780,7 @@ net_alias_dev_rehash(struct device *dev, struct sockaddr *sa) if (!(alias_info=main_dev->alias_info)) { - printk("ERROR: net_alias_rehash for %s: NULL alias_info\n", alias->name); + printk(KERN_ERR "ERROR: net_alias_rehash for %s: NULL alias_info\n", alias->name); return -1; } @@ -791,7 +791,7 @@ net_alias_dev_rehash(struct device *dev, struct sockaddr *sa) o_nat = alias->nat; if (!o_nat) { - printk("ERROR: net_alias_rehash(%s): unbound alias.\n", alias->name); + printk(KERN_ERR "ERROR: net_alias_rehash(%s): unbound alias.\n", alias->name); return -1; } @@ -806,7 +806,7 @@ net_alias_dev_rehash(struct device *dev, struct sockaddr *sa) n_nat = nat_getbytype(sa->sa_family); if (!n_nat) { - printk("ERROR: net_alias_rehash(%s): unreg family==%d.\n", alias->name, sa->sa_family); + printk(KERN_ERR "ERROR: net_alias_rehash(%s): unreg family==%d.\n", alias->name, sa->sa_family); return -1; } } @@ -832,10 +832,10 @@ net_alias_dev_rehash(struct device *dev, struct sockaddr *sa) if(!*aliasp) if ((aliasp = net_alias_slow_findp(alias_info, alias))) - printk("net_alias_rehash(%s): bad hashing recovered\n", alias->name); + printk(KERN_WARNING "net_alias_rehash(%s): bad hashing recovered\n", alias->name); else { - printk("ERROR: net_alias_rehash(%s): unhashed alias!\n", alias->name); + printk(KERN_ERR "ERROR: net_alias_rehash(%s): unhashed alias!\n", alias->name); return -1; } @@ -1309,7 +1309,7 @@ int register_net_alias_type(struct net_alias_type *nat, int type) unsigned long flags; if (!nat) { - printk("register_net_alias_type(): NULL arg\n"); + printk(KERN_ERR "register_net_alias_type(): NULL arg\n"); return -EINVAL; } nat->type = type; @@ -1334,7 +1334,7 @@ int unregister_net_alias_type(struct net_alias_type *nat) if (!nat) { - printk("unregister_net_alias_type(): NULL arg\n"); + printk(KERN_ERR "unregister_net_alias_type(): NULL arg\n"); return -EINVAL; } @@ -1343,7 +1343,7 @@ int unregister_net_alias_type(struct net_alias_type *nat) */ if (nat->n_attach) { - printk("unregister_net_alias_type(): has %d attachments. failed\n", + printk(KERN_ERR "unregister_net_alias_type(): has %d attachments. failed\n", nat->n_attach); return -EINVAL; } @@ -1360,7 +1360,7 @@ int unregister_net_alias_type(struct net_alias_type *nat) } } restore_flags(flags); - printk("unregister_net_alias_type(type=%d): not found!\n", nat->type); + printk(KERN_ERR "unregister_net_alias_type(type=%d): not found!\n", nat->type); return -EINVAL; } diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 63ead6139bba..f19d761ec1ba 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -69,13 +69,13 @@ extern atomic_t ip_frag_mem; void show_net_buffers(void) { - printk("Networking buffers in use : %u\n",net_skbcount); - printk("Network buffers locked by drivers : %u\n",net_locked); - printk("Total network buffer allocations : %u\n",net_allocs); - printk("Total failed network buffer allocs : %u\n",net_fails); - printk("Total free while locked events : %u\n",net_free_locked); + printk(KERN_INFO "Networking buffers in use : %u\n",net_skbcount); + printk(KERN_INFO "Network buffers locked by drivers : %u\n",net_locked); + printk(KERN_INFO "Total network buffer allocations : %u\n",net_allocs); + printk(KERN_INFO "Total failed network buffer allocs : %u\n",net_fails); + printk(KERN_INFO "Total free while locked events : %u\n",net_free_locked); #ifdef CONFIG_INET - printk("IP fragment buffer size : %u\n",ip_frag_mem); + printk(KERN_INFO "IP fragment buffer size : %u\n",ip_frag_mem); #endif } @@ -578,7 +578,7 @@ void kfree_skb(struct sk_buff *skb, int rw) { if (skb == NULL) { - printk("kfree_skb: skb = NULL (from %p)\n", + printk(KERN_CRIT "kfree_skb: skb = NULL (from %p)\n", __builtin_return_address(0)); return; } @@ -592,10 +592,10 @@ void kfree_skb(struct sk_buff *skb, int rw) return; } if (skb->free == 2) - printk("Warning: kfree_skb passed an skb that nobody set the free flag on! (from %p)\n", + printk(KERN_WARNING "Warning: kfree_skb passed an skb that nobody set the free flag on! (from %p)\n", __builtin_return_address(0)); if (skb->list) - printk("Warning: kfree_skb passed an skb still on a list (from %p).\n", + printk(KERN_WARNING "Warning: kfree_skb passed an skb still on a list (from %p).\n", __builtin_return_address(0)); if(skb->destructor) @@ -641,7 +641,7 @@ struct sk_buff *alloc_skb(unsigned int size,int priority) { static int count = 0; if (++count < 5) { - printk("alloc_skb called nonatomically from interrupt %p\n", + printk(KERN_ERR "alloc_skb called nonatomically from interrupt %p\n", __builtin_return_address(0)); priority = GFP_ATOMIC; } diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index bc35bbb18bf8..f6e94551a233 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c @@ -231,7 +231,7 @@ void eth_header_cache_bind(struct hh_cache ** hhp, struct device *dev, if (htype != ETH_P_IP) { - printk("eth_header_cache_bind: %04x cache is not implemented\n", htype); + printk(KERN_DEBUG "eth_header_cache_bind: %04x cache is not implemented\n", htype); return; } if (arp_bind_cache(hhp, dev, htype, daddr)) @@ -252,7 +252,7 @@ void eth_header_cache_update(struct hh_cache *hh, struct device *dev, unsigned c { if (hh->hh_type != ETH_P_IP) { - printk("eth_header_cache_update: %04x cache is not implemented\n", hh->hh_type); + printk(KERN_DEBUG "eth_header_cache_update: %04x cache is not implemented\n", hh->hh_type); return; } memcpy(hh->hh_data, haddr, ETH_ALEN); diff --git a/net/ipv4/Config.in b/net/ipv4/Config.in index fef49012e004..88f622058404 100644 --- a/net/ipv4/Config.in +++ b/net/ipv4/Config.in @@ -30,6 +30,6 @@ comment '(it is safe to leave these untouched)' bool 'IP: PC/TCP compatibility mode' CONFIG_INET_PCTCP tristate 'IP: Reverse ARP' CONFIG_INET_RARP bool 'IP: Disable Path MTU Discovery (normally enabled)' CONFIG_NO_PATH_MTU_DISCOVERY -bool 'IP: Disable NAGLE algorithm (normally enabled)' CONFIG_TCP_NAGLE_OFF +#bool 'IP: Disable NAGLE algorithm (normally enabled)' CONFIG_TCP_NAGLE_OFF bool 'IP: Drop source routed frames' CONFIG_IP_NOSR bool 'IP: Allow large windows (not recommended if <16Mb of memory)' CONFIG_SKB_LARGE diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index f1da2268d4c6..c5a2466d6a9b 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -1105,7 +1105,7 @@ static void arp_send_q(struct arp_table *entry) if(!(entry->flags&ATF_COM)) { - printk("arp_send_q: incomplete entry for %s\n", + printk(KERN_ERR "arp_send_q: incomplete entry for %s\n", in_ntoa(entry->ip)); /* Can't flush the skb, because RFC1122 says to hang on to */ /* at least one from any unresolved entry. --MS */ @@ -1670,7 +1670,7 @@ void arp_send(int type, int ptype, u32 dest_ip, + dev->hard_header_len, GFP_ATOMIC); if (skb == NULL) { - printk("ARP: no memory to send an arp packet\n"); + printk(KERN_DEBUG "ARP: no memory to send an arp packet\n"); return; } skb_reserve(skb, dev->hard_header_len); @@ -1798,7 +1798,7 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt) break; default: - printk("ARP: dev->type mangled!\n"); + printk(KERN_ERR "ARP: dev->type mangled!\n"); kfree_skb(skb, FREE_READ); return 0; } diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 18383a84d86c..be5c45c3e816 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -203,7 +203,7 @@ static void igmp_stop_timer(struct ip_mc_list *im) im->tm_running=0; } else { - printk("igmp_stop_timer() called with timer not running by %p\n",__builtin_return_address(0)); + printk(KERN_ERR "igmp_stop_timer() called with timer not running by %p\n",__builtin_return_address(0)); } } @@ -459,7 +459,7 @@ int igmp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt, if(saddr==0) { - printk("Broken multicast host using 0.0.0.0 heard on %s\n", + printk(KERN_INFO "Broken multicast host using 0.0.0.0 heard on %s\n", dev->name); kfree_skb(skb, FREE_READ); return 0; diff --git a/net/ipv4/ip_alias.c b/net/ipv4/ip_alias.c index e9507c99d126..488de23d4242 100644 --- a/net/ipv4/ip_alias.c +++ b/net/ipv4/ip_alias.c @@ -159,7 +159,7 @@ int init_module(void) void cleanup_module(void) { if (ip_alias_done() != 0) - printk("ip_alias: can't remove module"); + printk(KERN_INFO "ip_alias: can't remove module"); } #endif /* MODULE */ diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index e71ab06f1dcc..f4da9729c230 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c @@ -399,7 +399,7 @@ int ip_forward(struct sk_buff *skb, struct device *dev, int is_frag, optptr[2] = srrptr+4; } else - printk("ip_forward(): Argh! Destination lost!\n"); + printk(KERN_CRIT "ip_forward(): Argh! Destination lost!\n"); } if (opt->ts_needaddr) { diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index e5fc277aac09..1d7f778c2069 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c @@ -707,7 +707,7 @@ void ip_fragment(struct sock *sk, struct sk_buff *skb, struct device *dev, int i skb2->arp = skb->arp; if(skb->free==0) - printk("IP fragmenter: BUG free!=1 in fragmenter\n"); + printk(KERN_ERR "IP fragmenter: BUG free!=1 in fragmenter\n"); skb2->free = 1; skb_put(skb2,len + hlen); skb2->h.raw=(char *) skb2->data; diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 7b18ac107dce..372417cb1e9a 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -21,7 +21,6 @@ #include -#include #include #include #include @@ -31,7 +30,6 @@ #include #include #include -#include /* For CONFIG_FIREWALL */ #include #include @@ -53,9 +51,6 @@ int ipip_rcv(struct sk_buff *skb, struct device *dev, struct options *opt, __u32 daddr, unsigned short len, __u32 saddr, int redo, struct inet_protocol *protocol) { -#ifdef CONFIG_FIREWALL - int err; -#endif /* Don't unlink in the middle of a turnaround */ MOD_INC_USE_COUNT; #ifdef TUNNEL_DEBUG @@ -116,7 +111,7 @@ int init_module( void) void cleanup_module( void) { if ( inet_del_protocol(&ipip_protocol) < 0 ) - printk("ipip close: can't remove protocol\n"); + printk(KERN_INFO "ipip close: can't remove protocol\n"); } #endif diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index c051043d88d8..a179613364d6 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -908,7 +908,7 @@ done: void ip_mr_init(void) { - printk("Linux IP multicast router 0.05-maybe-works 8)\n"); + printk(KERN_INFO "Linux IP multicast router 0.05.\n"); register_netdevice_notifier(&ip_mr_notifier); proc_net_register(&(struct proc_dir_entry) { PROC_NET_IPMR_VIF, 9 ,"ip_mr_vif", diff --git a/net/ipv4/rarp.c b/net/ipv4/rarp.c index d2bba0ecde37..5d135583ad8c 100644 --- a/net/ipv4/rarp.c +++ b/net/ipv4/rarp.c @@ -320,7 +320,7 @@ static int rarp_req_set(struct arpreq *req) ip = si->sin_addr.s_addr; if (ip == 0) { - printk("RARP: SETRARP: requested PA is 0.0.0.0 !\n"); + printk(KERN_DEBUG "RARP: SETRARP: requested PA is 0.0.0.0 !\n"); return -EINVAL; } diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 7fba12416051..457c35236160 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -985,7 +985,7 @@ static int do_tcp_sendmsg(struct sock *sk, copy = min(sk->mss - tcp_size, seglen); if (copy <= 0) { - printk("TCP: **bug**: \"copy\" <= 0\n"); + printk(KERN_CRIT "TCP: **bug**: \"copy\" <= 0\n"); return -EFAULT; } tcp_size += copy; @@ -1023,7 +1023,7 @@ static int do_tcp_sendmsg(struct sock *sk, copy = seglen; if (copy <= 0) { - printk("TCP: **bug**: copy=%d, sk->mss=%d\n", copy, sk->mss); + printk(KERN_CRIT "TCP: **bug**: copy=%d, sk->mss=%d\n", copy, sk->mss); return -EFAULT; } diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 99aae5271aa5..630ad87110eb 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -1666,7 +1666,7 @@ int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt, if (!sk->prot) { - printk("IMPOSSIBLE 3\n"); + printk(KERN_CRIT "IMPOSSIBLE 3\n"); return(0); } diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 63517cd806bf..36a912eef31c 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -120,7 +120,7 @@ void tcp_send_skb(struct sock *sk, struct sk_buff *skb) if (size < sizeof(struct tcphdr) || size > skb->len) { - printk("tcp_send_skb: bad skb (skb = %p, data = %p, th = %p, len = %lu)\n", + printk(KERN_ERR "tcp_send_skb: bad skb (skb = %p, data = %p, th = %p, len = %lu)\n", skb, skb->data, th, skb->len); kfree_skb(skb, FREE_WRITE); return; @@ -136,7 +136,7 @@ void tcp_send_skb(struct sock *sk, struct sk_buff *skb) /* If it's got a syn or fin it's notionally included in the size..*/ if(!th->syn && !th->fin) { - printk("tcp_send_skb: attempt to queue a bogon.\n"); + printk(KERN_ERR "tcp_send_skb: attempt to queue a bogon.\n"); kfree_skb(skb,FREE_WRITE); return; } @@ -167,7 +167,7 @@ void tcp_send_skb(struct sock *sk, struct sk_buff *skb) th->check = 0; if (skb->next != NULL) { - printk("tcp_send_partial: next != NULL\n"); + printk(KERN_ERR "tcp_send_partial: next != NULL\n"); skb_unlink(skb); } skb_queue_tail(&sk->write_queue, skb); @@ -648,7 +648,7 @@ void tcp_send_fin(struct sock *sk) if (buff == NULL) { /* This is a disaster if it occurs */ - printk("tcp_send_fin: Impossible malloc failure"); + printk(KERN_CRIT "tcp_send_fin: Impossible malloc failure"); return; } @@ -713,7 +713,7 @@ void tcp_send_fin(struct sock *sk) buff->free = 0; if (buff->next != NULL) { - printk("tcp_send_fin: next != NULL\n"); + printk(KERN_ERR "tcp_send_fin: next != NULL\n"); skb_unlink(buff); } skb_queue_tail(&sk->write_queue, buff); diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index de9f49722f52..68c1f7dfc6b1 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -38,7 +38,7 @@ void tcp_reset_xmit_timer(struct sock *sk, int why, unsigned long when) if((long)when < 0) { when=3; - printk("Error: Negative timer in xmit_timer\n"); + printk(KERN_ERR "Error: Negative timer in xmit_timer\n"); } sk->retransmit_timer.expires=jiffies+when; add_timer(&sk->retransmit_timer); @@ -257,7 +257,7 @@ void tcp_retransmit_timer(unsigned long data) break; default: - printk ("rexmit_timer: timer expired - reason unknown\n"); + printk (KERN_ERR "rexmit_timer: timer expired - reason unknown\n"); break; } } diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index d4967b0679ab..72cc3c6fe5ef 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -756,7 +756,7 @@ static int ipxitf_rcv(ipx_interface *intrfc, struct sk_buff *skb) } else { - printk("IPX: Network number collision %lx\n\t%s %s and %s %s\n", + printk(KERN_WARNING "IPX: Network number collision %lx\n\t%s %s and %s %s\n", htonl(ipx->ipx_source.net), ipx_device_name(i), ipx_frame_name(i->if_dlink_type), @@ -2353,13 +2353,13 @@ ipx_proto_init(struct net_proto *pro) dev_add_pack(&ipx_8023_packet_type); if ((p8022_datalink = register_8022_client(ipx_8022_type, ipx_rcv)) == NULL) - printk("IPX: Unable to register with 802.2\n"); + printk(KERN_CRIT "IPX: Unable to register with 802.2\n"); if ((p8022tr_datalink = register_8022tr_client(ipx_8022_type, ipx_rcv)) == NULL) - printk("IPX: Unable to register with 802.2TR\n"); + printk(KERN_CRIT "IPX: Unable to register with 802.2TR\n"); if ((pSNAP_datalink = register_snap_client(ipx_snap_id, ipx_rcv)) == NULL) - printk("IPX: Unable to register with SNAP\n"); + printk(KERN_CRIT "IPX: Unable to register with SNAP\n"); register_netdevice_notifier(&ipx_dev_notifier); @@ -2367,7 +2367,7 @@ ipx_proto_init(struct net_proto *pro) proc_net_register(&ipx_if_procinfo); proc_net_register(&ipx_rt_procinfo); - printk(KERN_INFO "Swansea University Computer Society IPX 0.34 for NET3.034\n"); + printk(KERN_INFO "Swansea University Computer Society IPX 0.34 for NET3.035\n"); printk(KERN_INFO "IPX Portions Copyright (c) 1995 Caldera, Inc.\n"); } diff --git a/net/netlink.c b/net/netlink.c index fb3edeb36ee6..ac4db4a68fa6 100644 --- a/net/netlink.c +++ b/net/netlink.c @@ -218,7 +218,7 @@ int init_netlink(void) int ct; if(register_chrdev(NETLINK_MAJOR,"netlink", &netlink_fops)) { - printk("netlink: unable to get major %d\n", NETLINK_MAJOR); + printk(KERN_ERR "netlink: unable to get major %d\n", NETLINK_MAJOR); return -EIO; } for(ct=0;ct 65535) return -EINVAL; if (nr_ctl.arg > 236) /* we probably want this */ - printk("nr_ctl_ioctl: Warning --- huge paclen %d\n", (int)nr_ctl.arg); + printk(KERN_WARNING "nr_ctl_ioctl: Warning --- huge paclen %d\n", (int)nr_ctl.arg); sk->nr->paclen = nr_ctl.arg; break; @@ -1406,7 +1406,7 @@ void nr_proto_init(struct net_proto *pro) { sock_register(nr_proto_ops.family, &nr_proto_ops); register_netdevice_notifier(&nr_dev_notifier); - printk("G4KLX NET/ROM for Linux. Version 0.4 ALPHA for AX25.032 Linux 1.3.77\n"); + printk(KERN_INFO "G4KLX NET/ROM for Linux. Version 0.5 for AX25.032 Linux 2.0\n"); nr_default.quality = NR_DEFAULT_QUAL; nr_default.obs_count = NR_DEFAULT_OBS; diff --git a/net/netrom/nr_dev.c b/net/netrom/nr_dev.c index 3426106fa6f2..eaab1bdd670f 100644 --- a/net/netrom/nr_dev.c +++ b/net/netrom/nr_dev.c @@ -181,7 +181,7 @@ static int nr_xmit(struct sk_buff *skb, struct device *dev) return 0; if (!dev->start) { - printk("netrom: xmit call when iface is down\n"); + printk(KERN_ERR "netrom: xmit call when iface is down\n"); return 1; } diff --git a/net/netrom/nr_in.c b/net/netrom/nr_in.c index 213c4081135e..a4a735453624 100644 --- a/net/netrom/nr_in.c +++ b/net/netrom/nr_in.c @@ -316,7 +316,7 @@ int nr_process_rx_frame(struct sock *sk, struct sk_buff *skb) if (sk->nr->state != NR_STATE_1 && sk->nr->state != NR_STATE_2 && sk->nr->state != NR_STATE_3) { - printk("nr_process_rx_frame: frame received - state: %d\n", sk->nr->state); + printk(KERN_ERR "nr_process_rx_frame: frame received - state: %d\n", sk->nr->state); return queued; } diff --git a/net/netrom/nr_subr.c b/net/netrom/nr_subr.c index 6198574e489c..12ea151eee89 100644 --- a/net/netrom/nr_subr.c +++ b/net/netrom/nr_subr.c @@ -168,7 +168,7 @@ void nr_write_internal(struct sock *sk, int frametype) case NR_INFOACK: break; default: - printk("nr_write_internal: invalid frame type %d\n", frametype); + printk(KERN_ERR "nr_write_internal: invalid frame type %d\n", frametype); return; } diff --git a/net/socket.c b/net/socket.c index 653f9f615eaf..a881ddf1b3f8 100644 --- a/net/socket.c +++ b/net/socket.c @@ -577,7 +577,7 @@ asmlinkage int sys_socket(int family, int type, int protocol) if (!(sock = sock_alloc())) { - printk("NET: sys_socket: no more sockets\n"); + printk(KERN_WARNING "socket: no more sockets\n"); return(-ENOSR); /* Was: EAGAIN, but we are out of system resources! */ } @@ -754,7 +754,7 @@ asmlinkage int sys_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_ad if (!(newsock = sock_alloc())) { - printk("NET: sock_accept: no more sockets\n"); + printk(KERN_WARNING "accept: no more sockets\n"); return(-ENOSR); /* Was: EAGAIN, but we are out of system resources! */ } @@ -1397,7 +1397,7 @@ void sock_init(void) { int i; - printk("Swansea University Computer Society NET3.034 for Linux 1.3.77\n"); + printk(KERN_INFO "Swansea University Computer Society NET3.035 for Linux 2.0\n"); /* * Initialize all address (protocol) families. diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 4ed43a090d84..b3e8c056bf13 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -188,7 +188,7 @@ static void unix_destroy_socket(unix_socket *sk) } else { - /* passed fds are erased where?? */ + /* passed fds are erased in the kfree_skb hook */ kfree_skb(skb,FREE_WRITE); } } @@ -354,7 +354,8 @@ static int unix_release(struct socket *sock, struct socket *peer) skpair->protinfo.af_unix.locks--; /* It may now die */ sk->protinfo.af_unix.other=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. @@ -1085,7 +1086,7 @@ static int unix_recvmsg(struct socket *sock, struct msghdr *msg, int size, int n ) { kfree(cm); - printk("recvmsg: Bad msg_accrights\n"); +/* printk("recvmsg: Bad msg_accrights\n");*/ return -EINVAL; } } @@ -1305,7 +1306,7 @@ struct proto_ops unix_proto_ops = { void unix_proto_init(struct net_proto *pro) { - printk("NET3: Unix domain sockets 0.12 for Linux NET3.033.\n"); + printk(KERN_INFO "NET3: Unix domain sockets 0.12 for Linux NET3.035.\n"); sock_register(unix_proto_ops.family, &unix_proto_ops); #ifdef CONFIG_PROC_FS proc_net_register(&(struct proc_dir_entry) { diff --git a/net/unix/garbage.c b/net/unix/garbage.c index f4fb29923ded..3b7e114dda3d 100644 --- a/net/unix/garbage.c +++ b/net/unix/garbage.c @@ -1,14 +1,10 @@ /* - * NET3: Garbage Collector For AF_UNIX sockets (STUBS) + * NET3: Garbage Collector For AF_UNIX sockets * * Garbage Collector: * Copyright (C) Barak A. Pearlmutter. * Released under the GPL version 2 or later. * - * NOTE: - * We don't actually call this yet. I'm finishing some tests before I - * enable it. The bold can add it in themselves. - * * Chopped about by Alan Cox 22/3/96 to make it fit the AF_UNIX socket problem. * If it doesn't work blame me, it worked when Barak sent it. * @@ -70,22 +66,22 @@ static int in_stack = 0; /* first free entry in stack */ extern inline unix_socket *unix_get_socket(struct file *filp) { - struct socket *s; + unix_socket * u_sock = NULL; + struct inode *inode = filp->f_inode; + /* * Socket ? */ - if(filp->f_inode->i_mode!=S_IFSOCK) - return NULL; - s=&(filp->f_inode->u.socket_i); - /* - * AF_UNIX ? - */ - if(s->ops!=&unix_proto_ops) - return NULL; - /* - * Got one. - */ - return s->data; + if (inode && inode->i_sock) { + struct socket * s = &inode->u.socket_i; + + /* + * AF_UNIX ? + */ + if (s->ops == &unix_proto_ops) + u_sock = s->data; + } + return u_sock; } /* @@ -263,8 +259,15 @@ tail: * We exist only in the passing tree of sockets * that is no longer connected to active descriptors * Time to die.. + * + * Subtle item: We will correctly sweep out the + * socket that has just been closed by the user. + * We must not close this as we are in the middle + * of its close at this moment. Skip that file + * using f_count==0 to spot it. */ - if(s->socket && s->socket->file) + + if(s->socket && s->socket->file && s->socket->file->f_count) close_fp(s->socket->file); } else -- 2.39.5