diff -u --recursive --new-file v2.1.123/linux/CREDITS linux/CREDITS --- v2.1.123/linux/CREDITS Thu Sep 17 17:53:33 1998 +++ linux/CREDITS Sun Oct 4 10:00:27 1998 @@ -943,8 +943,8 @@ S: Luxembourg N: Gerd Knorr -E: kraxel@cs.tu-berlin.de -D: SCSI CD-ROM driver hacking, minor bug fixes +E: kraxel@goldbach.in-berlin.de +D: SCSI CD-ROM driver hacking, vesafb, v4l, minor bug fixes N: Harald Koenig E: koenig@tat.physik.uni-tuebingen.de diff -u --recursive --new-file v2.1.123/linux/Documentation/Changes linux/Documentation/Changes --- v2.1.123/linux/Documentation/Changes Wed Sep 9 14:51:03 1998 +++ linux/Documentation/Changes Sun Oct 4 10:21:45 1998 @@ -226,6 +226,9 @@ http://www.adelaide.net.au/~rustcorp/ipfwchains/ipfwchains.html, and use that instead of ipfwadm. + To use port forwarding and auto forwarding you will need 'ipmasqadm' +tool, available from http://juanjox.home.ml.org. + Memory ====== @@ -539,6 +542,11 @@ The 1.3.3 release: http://www.adelaide.net.au/~rustcorp/ipfwchains/ipchains-source-1.3.3.tar.gz http://www.adelaide.net.au/~rustcorp/ipfwchains/ipchains-source-1.3.3.tar.bz2 + +IP Masq Adm +=========== +The 0.4.1 release: +http://juanjox.home.ml.org/ipmasqadm-0.4.1.tar.gz iBCS ==== diff -u --recursive --new-file v2.1.123/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.1.123/linux/Documentation/Configure.help Mon Sep 28 10:51:32 1998 +++ linux/Documentation/Configure.help Sun Oct 4 10:21:45 1998 @@ -431,6 +431,20 @@ It is safe to say Y to this question. +Boot off-board chipsets first support +CONFIG_BLK_DEV_OFFBOARD + Normally, IDE controllers built into the motherboard (on-board + controllers) are assigned to ide0 and ide1 while those on add-in + PCI cards (off-board controllers) are relegated to ide2 and ide3. + Saying Y to here will reverse the situation, with off-board + controllers on ide0/1 and on-board controllers on ide2/3. This + can improve the usability of some boot managers such as LILO + when booting from a drive on an off-board controller. + Note that this will rearrange the order of the hd* devices and + may require modification of fstab and other files. + + If in doubt, say N. + Use DMA by default when available CONFIG_IDEDMA_AUTO Prior to kernel version 2.1.112, Linux used to automatically use @@ -650,9 +664,11 @@ The module will be called pg.o. You must also have at least one parallel port protocol driver in your system. This driver implements an API loosely related to the generic SCSI driver. - See /usr/include/linux/pg.h for details, or visit - http://www.torque.net/parport/cdr.html for more information and - the required patches to cdrecord. + See /usr/include/linux/pg.h for details. + + You can obtain the most recent version of cdrecord from + ftp://ftp.fokus.gmd.de/pub/unix/cdrecord/ . Versions 1.6.1a3 and + later fully support the pg driver. ATEN EH-100 protocol CONFIG_PARIDE_ATEN @@ -1173,7 +1189,8 @@ that implements the TGA interface (much like the VGA standard, but older TGA adapters are *not* VGA compatible). On such systems, you should say Y here so that the TGA driver rather than the standard - VGA driver is used. + VGA driver is used. Note that, at this time, there is no X server + for these systems. If unsure, try N. PCI support CONFIG_PCI @@ -1462,6 +1479,13 @@ display that complies with the generic VGA standard. Virtually everyone wants that. Say Y. +Use 64KB of VGA video RAM (aka: Maximum VGA Scrollback) +CONFIG_VGA_GET_64KB + Use 64K rather than 32K of video RAM. This doesn't actually work + on all "VGA" controllers. If your vga card can do it, then you + can say Y here to get more scrollback buffer (shift-pgup) on VGA + consoles. + Video mode selection support CONFIG_VIDEO_SELECT This enables support for text mode selection on kernel startup. If @@ -1483,26 +1507,20 @@ hardware. It represents the frame buffer of some video hardware and allows application software to access the graphics hardware through a well-defined interface, so the software doesn't need to know - anything about the low-level (hardware register) stuff. + anything about the low-level (hardware register) stuff. This works + across the different architectures supported by Linux and makes the + implementation of application programs easier and more portable; at + this point, an X server exists which uses the frame buffer device + exclusively. - Frame buffer devices work identically across the different - architectures supported by Linux and make the implementation of - application programs easier and more portable; at this point, an X - server exists which uses the frame buffer device exclusively. - On several non-X86 architectures, the frame buffer device is the - only way to use the graphics hardware. - The device is accessed through special device nodes, usually located in the /dev directory, i.e. /dev/fb*. - You need an utility program called fbset to make full use of frame - buffer devices. Please read the file - Documentation/fb/framebuffer.txt for more information. - - If you want to play with it, say Y here and also to the driver for - your graphics board, below. If unsure, say N, unless you are - compiling a kernel for a non-X86 architecture, in which case you - should say Y. + Please read the file Documentation/fb/framebuffer.txt for more + information. + + If you want to play with it, say Y here and to the driver for your + graphics board, below. If unsure, say N. Acorn VIDC support CONFIG_FB_ACORN @@ -1541,34 +1559,33 @@ Amiga CyberVision support CONFIG_FB_CYBER - This enables support for the Cybervision 64 graphics card from - Phase5. Please note that its use is not all that intuitive (i.e. if - you have any questions, be sure to ask!). Say N unless you have a - Cybervision 64 or plan to get one before you next recompile the - kernel. Please note that this driver DOES NOT support the - Cybervision 64 3D card, as they use incompatible video chips. + This enables support for the Cybervision 64 graphics card from Phase5. + Please note that its use is not all that intuitive (i.e. if you have + any questions, be sure to ask!). Say N unless you have a Cybervision + 64 or plan to get one before you next recompile the kernel. + Please note that this driver DOES NOT support the Cybervision 64 3D + card, as they use incompatible video chips. Amiga CyberVision3D support (EXPERIMENTAL) CONFIG_FB_VIRGE - This enables support for the Cybervision 64/3D graphics card from - Phase5. Please note that its use is not all that intuitive (i.e. if - you have any questions, be sure to ask!). Say N unless you have a - Cybervision 64/3D or plan to get one before you next recompile the - kernel. Please note that this driver DOES NOT support the older - Cybervision 64 card, as they use incompatible video chips. + This enables support for the Cybervision 64/3D graphics card from Phase5. + Please note that its use is not all that intuitive (i.e. if you have + any questions, be sure to ask!). Say N unless you have a Cybervision + 64/3D or plan to get one before you next recompile the kernel. + Please note that this driver DOES NOT support the older Cybervision 64 + card, as they use incompatible video chips. Amiga RetinaZ3 support (EXPERIMENTAL) CONFIG_FB_RETINAZ3 - This enables support for the Retina Z3 graphics card. Say N unless - you have a Retina Z3 or plan to get one before you next recompile - the kernel. + This enables support for the Retina Z3 graphics card. Say N unless you + have a Retina Z3 or plan to get one before you next recompile the kernel. Amiga CLgen driver (EXPERIMENTAL) CONFIG_FB_CLGEN - This enables support for Cirrus Logic GD542x/543x based boards on - Amiga: SD64, Piccolo, Picasso II/II+, Picasso IV, or EGS Spectrum. - Say N unless you have such a graphics board or plan to get one - before you next recompile the kernel. + This enables support for Cirrus Logic GD542x/543x based boards on Amiga: + SD64, Piccolo, Picasso II/II+, Picasso IV, or EGS Spectrum. Say N + unless you have such a graphics board or plan to get one before you next + recompile the kernel. Atari native chipset support CONFIG_FB_ATARI @@ -1597,6 +1614,11 @@ This driver supports a frame buffer for the "platinum" graphics adapter in some Power Macintoshes. +PowerMac "valkyrie" frame buffer device support +CONFIG_FB_VALKYRIE + This driver supports a frame buffer for the "valkyrie" graphics adapter + in some Power Macintoshes. + Chips 65550 display support CONFIG_FB_CT65550 This is the frame buffer device driver for the Chips & Technologies @@ -1612,36 +1634,26 @@ This is the frame buffer device driver for the Topcat graphics hardware found in HP300 workstations. -VGA chipset support (text only) -CONFIG_FB_VGA - This is the frame buffer device driver for generic VGA chips. This - driver works only in text mode and is deprecated; it is preferable - to say Y to "VGA text console" instead. For a graphical frame buffer - device driver that works for VGA cards, say Y to "VESA VGA graphics - console" below. - -TGA frame buffer support' +TGA frame buffer support CONFIG_FB_TGA This is the frame buffer device driver for generic TGA graphic cards. Say Y if you have one of those. VESA VGA graphics console CONFIG_FB_VESA - This is the frame buffer device driver for generic VESA graphic - cards. You will get a boot time penguin logo at no additional cost. - Please read Documentation/fb/vesafb.txt. If unsure, say Y. + This is the frame buffer device driver for generic VESA graphic cards. + Please read Documentation/fb/vesafb.txt. -MDA dual-headed support -CONFIG_FB_MDA +MDA text console (dual-headed) +CONFIG_MDA_CONSOLE Say Y here if you have an old MDA or monochrome Hercules graphics - adapter in your system acting as a second head ( = video card). You - will then be able to use two monitors with your Linux system. Do not - say Y here if your MDA card is the primary card in your system; the - normal VGA driver will handle it. + adapter in your system acting as a second head ( = video card). Do + not enable this driver if your MDA card is the primary card in your + system; the normal VGA driver will handle it. This driver is also available as a module ( = code which can be inserted and removed from the running kernel whenever you want). - The module will be called mdafb.o. If you want to compile it as + The module will be called mdacon.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. If unsure, say N. @@ -1674,14 +1686,13 @@ Virtual Frame Buffer support (ONLY FOR TESTING!) CONFIG_FB_VIRTUAL - This is a `virtual' frame buffer device. It operates on a chunk of - unswapable kernel memory instead of on the memory of a graphics - board. This means you cannot see any output sent to this frame - buffer device, while it does consume precious memory. The main use - of this frame buffer device is testing and debugging the frame - buffer subsystem. Do NOT enable it for normal systems! To protect - the innocent, it has to be enabled explicitly at boot time using the - kernel option `video=vfb:'. + This is a `virtual' frame buffer device. It operates on a chunk of + unswapable kernel memory instead of on the memory of a graphics board. + This means you cannot see any output sent to this frame buffer device, + while it does consume precious memory. The main use of this frame + buffer device is testing and debugging the frame buffer subsystem. Do + NOT enable it for normal systems! To protect the innocent, it has to + be enabled explicitly on boot time using the kernel option `video=vfb:'. This driver is also available as a module ( = code which can be inserted and removed from the running kernel whenever you want). @@ -1698,12 +1709,12 @@ drivers. Note that they are used for text console output only; they are NOT needed for graphical applications. - If you say N here, the needed low level drivers are automatically - enabled, depending on what frame buffer devices you selected above. - This is recommended for most users. + If you do not enable this option, the needed low level drivers are + automatically enabled, depending on what frame buffer devices you + selected. This is recommended for most users. - If you say Y here, you have more fine-grained control over which low - level drivers are enabled. You can e.g. leave out low level drivers + If you enable this option, you have more fine-grained control over which + low level drivers are enabled. You can e.g. leave out low level drivers for color depths you do not intend to use for text consoles. Low level frame buffer console drivers can be modules ( = code which @@ -1777,13 +1788,13 @@ Mac variable bpp packed pixels support CONFIG_FBCON_MAC This is the low level frame buffer console driver for 1/2/4/8/16/32 - bits per pixel packed pixels on Mac. It supports variable font widths + bits per pixel packed pixels on Mac. It supports variable fontwidths for low resolution screens. VGA characters/attributes support CONFIG_FBCON_VGA - This is the low level frame buffer console driver for VGA text mode; - it is used if you said Y to "VGA chipset support (text only)" above. + This is the low level frame buffer console driver for VGA text mode, as + used by vgafb. Parallel-port support CONFIG_PARPORT @@ -2236,6 +2247,9 @@ via FTP (user: anonymous) from ftp://ftp.netis.com/pub/members/rlynch/ + For 2.1 kernels, you will need "ipmasqadm" tool from + http://juanjox.home.ml.org + The ipautofw code is still under development and so is currently marked EXPERIMENTAL. If you want to try it, say Y. @@ -2244,6 +2258,22 @@ The module will be called ip_masq_autofw.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. +IP: masquerading special modules support +CONFIG_IP_MASQUERADE_MOD + This provides support for special modules that can modify rewriting + rules to achieve, for example, input port forwarding. + Beware that this feature adds a little overhead in the input packet + processing chain. + + You will need user space program "ipmasqadm" to use these + additional modules, you can download it from + http://juanjox.home.ml.org/ + + All this additional code is still under development and so is currently + marked EXPERIMENTAL. + + If you want to try, for example, PORT FORWARDING, say Y. + IP: ipportfw masquerade support CONFIG_IP_MASQUERADE_IPPORTFW Port Forwarding is an addition to IP Masquerading written by Steven @@ -2261,7 +2291,10 @@ http://www.monmouth.demon.co.uk/ipsubs/portforwarding.html (to browse the WWW, you need to have access to a machine on the Internet that has a program like lynx or netscape). You will need the user - space program ipportfw which can be downloaded from + space program "ipmasqadm" which can be downloaded from + http://juanjox.home.ml.org/ + + For general info, please see ftp://ftp.compsoc.net/users/steve/ipportfw/linux21/ The portfw code is still under development and so is currently @@ -2272,6 +2305,20 @@ The module will be called ip_masq_portfw.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. +IP: ipmarkfw masquerade support +CONFIG_IP_MASQUERADE_IPMARKFW + This provides functionally equivalent to port forwarding, the difference + is that Mark Forwarding uses "firewalling mark" to select which packets + must forward (see ipchains(8), "-m" argument). + + The markfw code is still under development and so is currently + marked EXPERIMENTAL. If you want to try it, say Y. + + This code is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called ip_masq_markfw.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + IP: always defragment CONFIG_IP_ALWAYS_DEFRAG This option means that all incoming fragments (= parts of IP packets @@ -8941,6 +8988,15 @@ and CD32. If you intend to run Linux on any of these systems, say Y; otherwise say N. +Amiga Cybervision support +CONFIG_FB_CYBER + This enables support for the Cybervision 64 graphics card from Phase5. + Please note that its use is not all that intuitive (i.e. if you have + any questions, be sure to ask!). Say N unless you have a Cybervision + 64 or plan to get one before you next recompile the kernel. + Please note that this driver DOES NOT support the Cybervision 64 3D + card at present, as they use incompatible video chips. + Amiga GSP (TMS340x0) support CONFIG_AMIGA_GSP Include support for Amiga graphics cards that use the Texas @@ -9306,17 +9362,6 @@ This option adds a device-tree directory under /proc which contains an image of the device tree that the kernel copies from Open Firmware. If unsure, say Y here. - -Support for ATI Mach64 display cards -CONFIG_ATY_VIDEO - Several of the newer Power Macintoshes and clones have a video - display interface based on the ATI Mach64 chipset. Say N here if - you are sure you don't need this functionality, otherwise Y. - -Support for IMS Twin Turbo display card -CONFIG_IMSTT_VIDEO - Some Power Macintosh clones have an IMS Twin Turbo video display - interface. Say Y to include support for this. MESH (Power Mac internal SCSI) support CONFIG_SCSI_MESH diff -u --recursive --new-file v2.1.123/linux/Documentation/fb/vesafb.txt linux/Documentation/fb/vesafb.txt --- v2.1.123/linux/Documentation/fb/vesafb.txt Thu Jul 16 18:09:22 1998 +++ linux/Documentation/fb/vesafb.txt Sun Oct 4 10:00:27 1998 @@ -30,37 +30,69 @@ ============== Switching modes is done using the vga=... boot parameter. Read -Documentation/svga.txt for details. With vesafb both text and -graphics modes work. Text modes are handled by vgafb, graphic modes -by the new vesafb.c. +Documentation/svga.txt for details. -The graphic modes are not in the list which you get if you boot with +You should compile in both vgacon (for text mode) and vesafb (for +graphics mode). Which of them takes over the console depends on +whenever the specified mode is text or graphics. + +The graphic modes are NOT in the list which you get if you boot with vga=ask and hit return. Here are some mode numbers: - | 640x480 800x600 1024x768 -----+--------------------------- -256 | 0x101 0x103 0x105 -32k | 0x110 0x113 0x116 -64k | 0x111 0x114 0x117 -16M | 0x112 0x115 0x118 - -Note 1: this are the VESA mode numbers. The video mode select code - expects 0x200 + VESA mode number. -Note 2: lilo can't handle hex, for booting with "vga=??" you have to - transform the numbers to decimal. - - -Speed it up! -============ - -Check /usr/src/linux/Documentation/mtrr.txt, enabling write-combining -for the framebuffer memory gives a performance boost. - -There are two ways to do console scrolling: redraw the screen -completely, or by copying around the video memory. You can select one -of them using the kernel command line: video=vesa:redraw or -video=vesa:memmove. redraw is the default, becauce this one works -faster on my box. + | 640x480 800x600 1024x768 1280x1024 +----+------------------------------------- +256 | 0x101 0x103 0x105 0x107 +32k | 0x110 0x113 0x116 0x119 +64k | 0x111 0x114 0x117 0x11A +16M | 0x112 0x115 0x118 0x11B + +This are the VESA mode numbers. The video mode select code expects +0x200 + VESA mode number. Therefore you have to enter "305" at the +"vga=ask" prompt to boot into 1024x768x8. + +If this does'nt work, this might be becauce your BIOS does not support +linear framebuffers or becauce it does'nt support this mode at all. +Even if your board does, it might be the BIOS does not. VESA BIOS +Extentions v2.0 are required, 1.2 is NOT sufficient. You'll get a +"bad mode number" message if something goes wrong. + +Note: LILO can't handle hex, for booting directly with "vga=mode-number" + you have to transform the numbers to decimal. + + +X11 +=== + +XF68_FBDev should work just fine, but it is non-accelerated. Running +another (accelerated) X-Server like XF86_SVGA might or might not work. +It depends on X-Server and graphics board. + +The X-Server must restore the video mode correctly, else you end up +with a broken console (and vesafb can't do anything about this). + + +Configuration +============= + +You can pass kernel command line options to vesafb with +"video=vesa:option1". Multiple options should be separated +by comma. Accepted options: + +invers - no comment... + +redraw - scroll by redrawing the affected part of the screen. + This is the default. +ypan - enable display panning using the VESA protected mode + interface. This enables the Shift-PgUp scrollback + thing and greatly speeds up fullscreen scrolling. + It is slower than "redraw" when scrolling only a halve + screen. Seems not to work with some BIOSes. +ywrap - If your gfx board supports wrap-around, use this one + instead of ypan. + +vgapal - Use the standard vga registers for palette changes. + This is the default. +pmipal - Use the protected mode interface for palette changes. Have fun! diff -u --recursive --new-file v2.1.123/linux/Documentation/networking/ip_masq/ip_masq-API-ex.c linux/Documentation/networking/ip_masq/ip_masq-API-ex.c --- v2.1.123/linux/Documentation/networking/ip_masq/ip_masq-API-ex.c Wed Dec 31 16:00:00 1969 +++ linux/Documentation/networking/ip_masq/ip_masq-API-ex.c Sun Oct 4 10:21:45 1998 @@ -0,0 +1,77 @@ +/* + There is only 1 optname (see setsockopt(2)), IP_FW_MASQ_CTL that + must be used. + Funcionality depends on your kernel CONFIG options, here is + an example you can use to create an ``incoming'' tunnel: + + See "user.c" module under ipmasqadm tree for a generic example + */ +#undef __KERNEL__ /* Makefile lazyness ;) */ +#include +#include +#include +#include +#include +#include + +#include /* For __uXX types */ +#include +#include +#include +#include +#include /* For IP_FW_MASQ_CTL */ +#include /* For specific masq defs */ + + +int create_listening_masq(struct ip_masq_ctl *masq, int proto, u_int32_t src_addr, u_int16_t src_port, u_int32_t dst_addr) +{ + int sockfd; + + sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); + + if (sockfd<0) { + perror("socket(RAW)"); + return -1; + } + + memset (masq, 0, sizeof (*masq)); + + /* + * Want user tunnel control + */ + masq->m_target = IP_MASQ_TARGET_USER; + + /* + * Want to insert new + */ + masq->m_cmd = IP_MASQ_CMD_INSERT; + + masq->u.user.protocol = proto; + masq->u.user.saddr = src_addr; + masq->u.user.sport = src_port; + masq->u.user.rt_daddr = inet_addr("192.168.21.239"); + + if (setsockopt(sockfd, IPPROTO_IP, + IP_FW_MASQ_CTL, (char *)masq, sizeof(*masq))) { + perror("setsockopt()"); + return -1; + } + /* masq struct now contains tunnel details */ + fprintf(stderr, "PROTO=%d SRC=0x%X:%x - MASQ=0x%X:%x - DST=0x%X:%x\n", + masq->u.user.protocol, + ntohl(masq->u.user.saddr), ntohs(masq->u.user.sport), + ntohl(masq->u.user.maddr), ntohs(masq->u.user.mport), + ntohl(masq->u.user.daddr), ntohs(masq->u.user.dport)); + return 0; +} + +int main(void) { + struct ip_masq_ctl masq_buf; + + return create_listening_masq(&masq_buf, + IPPROTO_TCP, + inet_addr("192.168.1.4"), + htons(23), + inet_addr("192.168.21.3")); +} + diff -u --recursive --new-file v2.1.123/linux/Documentation/paride.txt linux/Documentation/paride.txt --- v2.1.123/linux/Documentation/paride.txt Tue Jun 23 10:01:18 1998 +++ linux/Documentation/paride.txt Mon Sep 28 10:51:16 1998 @@ -1,7 +1,7 @@ Linux and parallel port IDE devices -PARIDE v1.02 (c) 1997-8 Grant Guenther +PARIDE v1.03 (c) 1997-8 Grant Guenther 1. Introduction @@ -42,8 +42,8 @@ SyQuest EZ-135, EZ-230 & SparQ drives Avatar Shark Imation Superdisk LS-120 - FreeCom Power CD - Hewlett-Packard 5GB tape drive + FreeCom Power CD + Hewlett-Packard 5GB and 8GB tape drives Hewlett-Packard 7100 and 7200 CD-RW drives as well as most of the clone and no-name products on the market. @@ -52,7 +52,7 @@ subsystem, is actually structured in three parts. There is a base paride module which provides a registry and some common methods for accessing the parallel ports. The second component is a set of -high-level drivers for each of the different type of supported device: +high-level drivers for each of the different types of supported devices: pd IDE disk pcd ATAPI CD-ROM @@ -176,7 +176,7 @@ if you use them as loadable kernel modules. Note 1: using these drivers with the "kerneld" automatic module loading -system is not recommended, and is not documented here. +system is not recommended for beginners, and is not documented here. Note 2: if you build PARPORT support as a loadable module, PARIDE must also be built as loadable modules, and PARPORT must be loaded before the @@ -290,13 +290,56 @@ mkdosfs /dev/pf0 mount /dev/pf0 /mnt -2.4 Using the pg driver + +2.4 The pf driver + +The pf driver is intended for use with parallel port ATAPI disk +devices. The most common devices in this category are PD drives +and LS-120 drives. Traditionally, media for these devices are not +partitioned. Consequently, the pf driver does not support partitioned +media. This may be changed in a future version of the driver. + + +2.5 Using the pt driver + +The pt driver for parallel port ATAPI tape drives is a minimal driver. +It does not yet support many of the standard tape ioctl operations. +For best performance, a block size of 32KB should be used. You will +probably want to set the parallel port delay to 0, if you can. + + +2.6 Using the pg driver The pg driver can be used in conjunction with the cdrecord program -to create CD-ROMs. For more information, and the required patches -to cdrecord, please visit http://www.torque.net/parport/cdr.html . +to create CD-ROMs. Please get cdrecord version 1.6.1a3 or later +from ftp://ftp.fokus.gmd.de/pub/unix/cdrecord/ (you may have to look +in the alpha subdirectory). To record CD-R media your parallel port +should ideally be set to EPP mode, and the "port delay" should be +set to 0. With those settings it is possible to record at 2x speed +without any buffer underruns. If you cannot get the driver to work +in EPP mode, try to use "bidirectional" or "PS/2" mode and 1x speeds only. + 3. Troubleshooting + +The most common problems that people report with the PARIDE drivers +concern the parallel port CMOS settings. At this time, none of the +PARIDE protocol modules support ECP mode, or any ECP combination modes. +If you are able to do so, please set your parallel port into EPP mode +using your CMOS setup procedure. + +Some parallel ports cannot reliably transfer data at full speed. To +offset the errors, the PARIDE protocol modules introduce a "port +delay" between each access to the i/o ports. Each protocol sets +a default value for this delay. In most cases, the user can override +the default and set it to 0 - resulting in somewhat higher transfer +rates. In some rare cases (especially with older 486 systems) the +default delays are not long enough. if you experience corrupt data +transfers, or unexpected failures, you may wish to increase the +port delay. The delay can be programmed using the "driveN" parameters +to each of the high-level drivers. Please see the notes above, or +read the comments at the beginning of the driver source files in +linux/drivers/block/paride. While a lot of testing has gone into these drivers to make them work as smoothly as possible, problems will arise. If you do have problems, diff -u --recursive --new-file v2.1.123/linux/Makefile linux/Makefile --- v2.1.123/linux/Makefile Mon Sep 28 10:51:32 1998 +++ linux/Makefile Sun Oct 4 12:23:12 1998 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 1 -SUBLEVEL = 123 +SUBLEVEL = 124 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) @@ -316,10 +316,11 @@ if [ -f VIDEO_MODULES ]; then inst_mod VIDEO_MODULES video; fi; \ if [ -f FC4_MODULES ]; then inst_mod FC4_MODULES fc4; fi; \ \ - ls *.o > .allmods; \ - echo $$MODULES | tr ' ' '\n' | sort | comm -23 .allmods - > .misc; \ - if [ -s .misc ]; then inst_mod .misc misc; fi; \ - rm -f .misc .allmods; \ + rm -f /tmp/.misc.$$$$ /tmp/.allmods.$$$$; \ + ls *.o > /tmp/.allmods.$$$$; \ + echo $$MODULES | tr ' ' '\n' | sort | comm -23 /tmp/.allmods.$$$$ - > /tmp/.misc.$$$$; \ + if [ -s /tmp/.misc.$$$$ ]; then inst_mod /tmp/.misc.$$$$ misc; fi; \ + rm -f /tmp/.misc.$$$$ /tmp/.allmods.$$$$; \ ) # modules disabled.... diff -u --recursive --new-file v2.1.123/linux/arch/i386/boot/video.S linux/arch/i386/boot/video.S --- v2.1.123/linux/arch/i386/boot/video.S Wed Jun 24 22:54:03 1998 +++ linux/arch/i386/boot/video.S Tue Sep 29 21:03:35 1998 @@ -24,7 +24,7 @@ #undef CONFIG_VIDEO_LOCAL ! Force 400 scan lines for standard modes (hack to fix bad behaviour -! of certain broken BIOS'es -- don't use unless needed) +! of certain broken BIOSes -- don't use unless needed) #undef CONFIG_VIDEO_400_HACK ! A special hack allowing to force specific BIOS mode ID along with specific @@ -85,6 +85,9 @@ #define PARAM_LFB_SIZE 0x1c #define PARAM_LFB_LINELENGTH 0x24 #define PARAM_LFB_COLORS 0x26 +#define PARAM_VESAPM_SEG 0x2e +#define PARAM_VESAPM_OFF 0x30 +#define PARAM_LFB_PAGES 0x32 ! Define DO_STORE according to CONFIG_VIDEO_RETAIN #ifdef CONFIG_VIDEO_RETAIN @@ -236,13 +239,14 @@ seg fs mov [PARAM_LFB_DEPTH],ax - mov eax,(di+40) + mov al,(di+29) + mov ah,#0 seg fs - mov [PARAM_LFB_BASE],eax + mov [PARAM_LFB_PAGES],ax - mov eax,(di+44) + mov eax,(di+40) seg fs - mov [PARAM_LFB_SIZE],eax + mov [PARAM_LFB_BASE],eax mov eax,(di+31) seg fs @@ -251,7 +255,30 @@ mov eax,(di+35) seg fs mov [PARAM_LFB_COLORS+4],eax - + + ! get video mem size + lea di,modelist+1024 + mov ax,#0x4f00 + int 0x10 + + xor eax,eax + mov ax,(di+18) + seg fs + mov [PARAM_LFB_SIZE],eax + + ! get protected mode interface informations + mov ax,#0x4f0a + xor bx,bx + xor di,di + int 0x10 + cmp ax,#0x004f + jnz no_pm + seg fs + mov [PARAM_VESAPM_SEG],es + seg fs + mov [PARAM_VESAPM_OFF],di + +no_pm: ret ! @@ -619,7 +646,7 @@ jz set80 seg gs ! This is EGA+ -- beware of 80x50 etc. mov al,[0x0484] - or al,al ! Some buggy BIOSs set 0 rows + or al,al ! Some buggy BIOSes set 0 rows jz set80 cmp al,#24 ! Let's hope this is correct jz set80 diff -u --recursive --new-file v2.1.123/linux/arch/i386/config.in linux/arch/i386/config.in --- v2.1.123/linux/arch/i386/config.in Thu Sep 17 17:53:34 1998 +++ linux/arch/i386/config.in Thu Oct 1 10:02:21 1998 @@ -135,8 +135,9 @@ mainmenu_option next_comment comment 'Console drivers' bool 'VGA text console' CONFIG_VGA_CONSOLE + bool 'Video mode selection support' CONFIG_VIDEO_SELECT if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - bool 'Video mode selection support' CONFIG_VIDEO_SELECT + tristate 'MDA text console (dual-headed) (EXPERIMENTAL)' CONFIG_MDA_CONSOLE bool 'Support for frame buffer devices (EXPERIMENTAL)' CONFIG_FB fi source drivers/video/Config.in diff -u --recursive --new-file v2.1.123/linux/arch/i386/defconfig linux/arch/i386/defconfig --- v2.1.123/linux/arch/i386/defconfig Mon Sep 28 10:51:32 1998 +++ linux/arch/i386/defconfig Thu Oct 1 23:20:41 1998 @@ -67,6 +67,7 @@ CONFIG_BLK_DEV_RZ1000=y CONFIG_BLK_DEV_IDEPCI=y CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_BLK_DEV_OFFBOARD is not set CONFIG_IDEDMA_AUTO=y # CONFIG_IDE_CHIPSETS is not set @@ -287,6 +288,7 @@ # Console drivers # CONFIG_VGA_CONSOLE=y +# CONFIG_VIDEO_SELECT is not set # # Sound diff -u --recursive --new-file v2.1.123/linux/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c --- v2.1.123/linux/arch/i386/kernel/io_apic.c Mon Sep 28 10:51:33 1998 +++ linux/arch/i386/kernel/io_apic.c Sun Oct 4 11:54:24 1998 @@ -129,7 +129,7 @@ /* * We disable IO-APIC IRQs by setting their 'destination CPU mask' to - * zero. Trick, trick. + * zero. Trick by Ramesh Nalluri. */ static inline void disable_IO_APIC_irq(unsigned int irq) { @@ -291,9 +291,22 @@ } /* + * Unclear documentation on what a "conforming ISA interrupt" means. + * + * Should we, or should we not, take the ELCR register into account? + * It's part of the EISA specification, but maybe it should only be + * used if the interrupt is actually marked as EISA? + * + * Oh, well. Don't do it until somebody tells us what the right thing + * to do is.. + */ +#undef USE_ELCR_TRIGGER_LEVEL +#ifdef USE_ELCR_TRIGGER_LEVEL + +/* * ISA Edge/Level control register, ELCR */ -static int __init ISA_ELCR(unsigned int irq) +static int __init EISA_ELCR(unsigned int irq) { if (irq < 16) { unsigned int port = 0x4d0 + (irq >> 3); @@ -303,37 +316,15 @@ return 0; } -/* - * ISA interrupts can be: - * - level triggered, active low (ELCR = 1) - * - edge triggered, active high (ELCR = 0) - * - edge triggered, active low (magic irq 8) - */ -static int __init default_ISA_trigger(int idx) -{ - unsigned int irq = mp_irqs[idx].mpc_dstirq; - - if (irq == 8) - return 0; - return ISA_ELCR(irq); -} +#define default_ISA_trigger(idx) (EISA_ELCR(mp_irqs[idx].mpc_dstirq)) +#define default_ISA_polarity(idx) (0) -static int __init default_ISA_polarity(int idx) -{ - unsigned int irq = mp_irqs[idx].mpc_dstirq; +#else - if (irq == 8) - return 1; - return ISA_ELCR(irq); -} +#define default_ISA_trigger(idx) (0) +#define default_ISA_polarity(idx) (0) -/* - * There are broken mptables which register ISA+high-active+level IRQs, - * these are illegal and are converted here to ISA+high-active+edge - * IRQ sources. Careful, ISA+low-active+level is another broken entry - * type, it represents PCI IRQs 'embedded into an ISA bus', they have - * to be accepted. Yes, ugh. - */ +#endif static int __init MPBIOS_polarity(int idx) { @@ -453,36 +444,14 @@ return trigger; } -static int __init trigger_flag_broken(int idx) -{ - int bus = mp_irqs[idx].mpc_srcbus; - int polarity = MPBIOS_polarity(idx); - int trigger = MPBIOS_trigger(idx); - - if ( (mp_bus_id_to_type[bus] == MP_BUS_ISA) && - (polarity == 0) /* active-high */ && - (trigger == 1) /* level */ ) - - return 1; /* broken */ - - return 0; -} - static inline int irq_polarity(int idx) { - /* - * There are no known BIOS bugs wrt polarity. yet. - */ return MPBIOS_polarity(idx); } static inline int irq_trigger(int idx) { - int trigger = MPBIOS_trigger(idx); - - if (trigger_flag_broken(idx)) - trigger = 0; - return trigger; + return MPBIOS_trigger(idx); } static int __init pin_2_irq(int idx, int pin) @@ -617,9 +586,6 @@ bus = mp_irqs[idx].mpc_srcbus; - if (trigger_flag_broken (idx)) - printk("broken BIOS, changing pin %d to edge\n", pin); - io_apic_write(0x11+2*pin, *(((int *)&entry)+1)); io_apic_write(0x10+2*pin, *(((int *)&entry)+0)); } @@ -882,9 +848,9 @@ if (!IO_APIC_IRQ(i)) continue; - mp_irqs[pos].mpc_irqtype = 0; - mp_irqs[pos].mpc_irqflag = 0; - mp_irqs[pos].mpc_srcbus = 0; + mp_irqs[pos].mpc_irqtype = mp_INT; + mp_irqs[pos].mpc_irqflag = 0; /* default */ + mp_irqs[pos].mpc_srcbus = MP_BUS_ISA; mp_irqs[pos].mpc_srcbusirq = i; mp_irqs[pos].mpc_dstapic = 0; mp_irqs[pos].mpc_dstirq = i; diff -u --recursive --new-file v2.1.123/linux/arch/i386/kernel/mtrr.c linux/arch/i386/kernel/mtrr.c --- v2.1.123/linux/arch/i386/kernel/mtrr.c Thu Sep 17 17:53:34 1998 +++ linux/arch/i386/kernel/mtrr.c Wed Sep 30 15:34:25 1998 @@ -122,9 +122,16 @@ Added sanity check for / before . Created addition queue for prior to SMP commence. v1.23 + 19980902 Richard Gooch + Ported patch to kernel 2.1.120-pre3. + v1.24 19980910 Richard Gooch Removed sanity checks and addition queue: Linus prefers an OOPS. - v1.24 + v1.25 + 19981001 Richard Gooch + Fixed harmless compiler warning in include/asm-i386/mtrr.h + Fixed version numbering and history for v1.23 -> v1.24. + v1.26 */ #include #include @@ -157,7 +164,7 @@ #include #include -#define MTRR_VERSION "1.24 (19980910)" +#define MTRR_VERSION "1.26 (19981001)" #define TRUE 1 #define FALSE 0 diff -u --recursive --new-file v2.1.123/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c --- v2.1.123/linux/arch/i386/kernel/process.c Mon Sep 28 10:51:33 1998 +++ linux/arch/i386/kernel/process.c Wed Sep 30 10:16:56 1998 @@ -519,34 +519,22 @@ void flush_thread(void) { int i; + struct task_struct *tsk = current; for (i=0 ; i<8 ; i++) - current->tss.debugreg[i] = 0; + tsk->tss.debugreg[i] = 0; /* * Forget coprocessor state.. */ - if (current->flags & PF_USEDFPU) { - current->flags &= ~PF_USEDFPU; - stts(); - } - current->used_math = 0; + clear_fpu(tsk); + tsk->used_math = 0; } void release_thread(struct task_struct *dead_task) { } -static inline void unlazy_fpu(struct task_struct *tsk) -{ - if (tsk->flags & PF_USEDFPU) { - __asm__("fnsave %0":"=m" (tsk->tss.i387)); - asm volatile("fwait"); - tsk->flags &= ~PF_USEDFPU; - stts(); - } -} - /* * If new_mm is NULL, we're being called to set up the LDT descriptor * for a clone task. Each clone must have a separate entry in the GDT. @@ -621,11 +609,12 @@ int dump_fpu (struct pt_regs * regs, struct user_i387_struct* fpu) { int fpvalid; + struct task_struct *tsk = current; - fpvalid = current->used_math; + fpvalid = tsk->used_math; if (fpvalid) { - unlazy_fpu(current); - memcpy(fpu,¤t->tss.i387.hard,sizeof(*fpu)); + unlazy_fpu(tsk); + memcpy(fpu,&tsk->tss.i387.hard,sizeof(*fpu)); } return fpvalid; @@ -793,6 +782,8 @@ if (IS_ERR(filename)) goto out; error = do_execve(filename, (char **) regs.ecx, (char **) regs.edx, ®s); + if (error == 0) + current->flags &= ~PF_DTRACE; putname(filename); out: unlock_kernel(); diff -u --recursive --new-file v2.1.123/linux/arch/i386/kernel/ptrace.c linux/arch/i386/kernel/ptrace.c --- v2.1.123/linux/arch/i386/kernel/ptrace.c Thu Sep 17 17:53:34 1998 +++ linux/arch/i386/kernel/ptrace.c Wed Sep 30 10:16:56 1998 @@ -541,6 +541,10 @@ if ((unsigned long) data > _NSIG) goto out; child->flags &= ~PF_TRACESYS; + if ((child->flags & PF_DTRACE) == 0) { + /* Spurious delayed TF traps may occur */ + child->flags |= PF_DTRACE; + } tmp = get_stack_long(child, EFL_OFFSET) | TRAP_FLAG; put_stack_long(child, EFL_OFFSET, tmp); child->exit_code = data; @@ -647,8 +651,6 @@ #endif __copy_from_user(&child->tss.i387.hard, (void *)data, sizeof(struct user_i387_struct)); - child->flags &= ~PF_USEDFPU; - stts(); #ifdef CONFIG_MATH_EMULATION } else { restore_i387_soft(&child->tss.i387.soft, diff -u --recursive --new-file v2.1.123/linux/arch/i386/kernel/signal.c linux/arch/i386/kernel/signal.c --- v2.1.123/linux/arch/i386/kernel/signal.c Thu Sep 17 17:53:34 1998 +++ linux/arch/i386/kernel/signal.c Tue Sep 29 11:39:28 1998 @@ -153,11 +153,9 @@ static inline int restore_i387_hard(struct _fpstate *buf) { - if (current->flags & PF_USEDFPU) { - current->flags &= ~PF_USEDFPU; - stts(); - } - return __copy_from_user(¤t->tss.i387.hard, buf, sizeof(*buf)); + struct task_struct *tsk = current; + clear_fpu(tsk); + return __copy_from_user(&tsk->tss.i387.hard, buf, sizeof(*buf)); } static inline int restore_i387(struct _fpstate *buf) @@ -307,14 +305,11 @@ static inline int save_i387_hard(struct _fpstate * buf) { - if (current->flags & PF_USEDFPU) { - current->flags &= ~PF_USEDFPU; - __asm__ __volatile__("fnsave %0":"=m"(current->tss.i387.hard)); - stts(); - } - asm volatile("fwait"); - current->tss.i387.hard.status = current->tss.i387.hard.swd; - if (__copy_to_user(buf, ¤t->tss.i387.hard, sizeof(*buf))) + struct task_struct *tsk = current; + + unlazy_fpu(tsk); + tsk->tss.i387.hard.status = tsk->tss.i387.hard.swd; + if (__copy_to_user(buf, &tsk->tss.i387.hard, sizeof(*buf))) return -1; return 1; } diff -u --recursive --new-file v2.1.123/linux/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c --- v2.1.123/linux/arch/i386/kernel/smp.c Wed Sep 9 14:51:05 1998 +++ linux/arch/i386/kernel/smp.c Thu Oct 1 17:41:44 1998 @@ -736,6 +736,7 @@ /* Must be done before calibration delay is computed */ mtrr_init_secondary_cpu (); #endif + stts(); smp_callin(); while (!smp_commenced) barrier(); @@ -1751,8 +1752,8 @@ static volatile int calibration_lock; - save_flags(flags); - cli(); + __save_flags(flags); + __cli(); SMP_PRINTK(("setup_APIC_clock() called.\n")); @@ -1790,8 +1791,7 @@ ack_APIC_irq (); - - restore_flags(flags); + __restore_flags(flags); } /* diff -u --recursive --new-file v2.1.123/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c --- v2.1.123/linux/arch/i386/kernel/traps.c Thu Sep 17 17:53:34 1998 +++ linux/arch/i386/kernel/traps.c Thu Oct 1 19:06:44 1998 @@ -191,7 +191,7 @@ do_exit(SIGSEGV); } -static void die_if_kernel(const char * str, struct pt_regs * regs, long err) +static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err) { if (!(regs->eflags & VM_MASK) && !(3 & regs->xcs)) die(str, regs, err); @@ -339,7 +339,16 @@ /* Mask out spurious TF errors due to lazy TF clearing */ if (condition & DR_STEP) { - if ((tsk->flags & PF_PTRACED) == 0) + /* + * The TF error should be masked out only if the current + * process is not traced and if the TRAP flag has been set + * previously by a tracing process (condition detected by + * the PF_DTRACE flag); remember that the i386 TRAP flag + * can be modified by the process itself in user mode, + * allowing programs to debug themselves without the ptrace() + * interface. + */ + if ((tsk->flags & (PF_DTRACE|PF_PTRACED)) == PF_DTRACE) goto clear_TF; } @@ -385,20 +394,15 @@ { struct task_struct * task; - lock_kernel(); - clts(); - task = current; /* - * Save the info for the exception handler + * Save the info for the exception handler + * (this will also clear the error) */ - __asm__ __volatile__("fnsave %0":"=m" (task->tss.i387.hard)); - task->flags&=~PF_USEDFPU; - stts(); - + task = current; + save_fpu(task); task->tss.trap_no = 16; task->tss.error_code = 0; force_sig(SIGFPE, task); - unlock_kernel(); } asmlinkage void do_coprocessor_error(struct pt_regs * regs, long error_code) @@ -423,19 +427,9 @@ * Careful.. There are problems with IBM-designed IRQ13 behaviour. * Don't touch unless you *really* know how it works. */ -asmlinkage void math_state_restore(void) +asmlinkage void math_state_restore(struct pt_regs regs) { __asm__ __volatile__("clts"); /* Allow maths ops (or we recurse) */ - -/* - * SMP is actually simpler than uniprocessor for once. Because - * we can't pull the delayed FPU switching trick Linus does - * we simply have to do the restore each context switch and - * set the flag. switch_to() will always save the state in - * case we swap processors. We also don't use the coprocessor - * timer - IRQ 13 mode isn't used with SMP machines (thank god). - */ - if(current->used_math) __asm__("frstor %0": :"m" (current->tss.i387)); else diff -u --recursive --new-file v2.1.123/linux/arch/ppc/8xx_io/Makefile linux/arch/ppc/8xx_io/Makefile --- v2.1.123/linux/arch/ppc/8xx_io/Makefile Thu Apr 23 20:21:28 1998 +++ linux/arch/ppc/8xx_io/Makefile Wed Sep 30 10:14:16 1998 @@ -8,6 +8,12 @@ # Note 2! The CFLAGS definition is now in the main makefile... O_TARGET := 8xx_io.a -O_OBJS = commproc.o uart.o enet.o +O_OBJS = commproc.o uart.o +ifdef CONFIG_MBX +O_OBJS += enet.o +endif +ifdef CONFIG_FADS +O_OBJS += fec.o +endif include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.123/linux/arch/ppc/8xx_io/commproc.c linux/arch/ppc/8xx_io/commproc.c --- v2.1.123/linux/arch/ppc/8xx_io/commproc.c Fri May 8 23:14:44 1998 +++ linux/arch/ppc/8xx_io/commproc.c Thu Oct 1 09:55:12 1998 @@ -21,6 +21,7 @@ * applications that require more DP ram, we can expand the boundaries * but then we have to be careful of any downloaded microcode. */ +#include #include #include #include @@ -29,7 +30,12 @@ #include #include #include +#ifdef CONFIG_MBX #include +#endif +#ifdef CONFIG_FADS +#include +#endif #include #include #include @@ -52,13 +58,13 @@ static void cpm_error_interrupt(void *); void -mbx_cpm_reset(uint host_page_addr) +m8xx_cpm_reset(uint host_page_addr) { volatile immap_t *imp; volatile cpm8xx_t *commproc; pte_t *pte; - imp = (immap_t *)MBX_IMAP_ADDR; + imp = (immap_t *)IMAP_ADDR; commproc = (cpm8xx_t *)&imp->im_cpm; #ifdef notdef @@ -78,6 +84,10 @@ #endif /* Set SDMA Bus Request priority 5. + * On 860T, this also enables FEC priority 6. I am not sure + * this is what we realy want for some applications, but the + * manual recommends it. + * Bit 25, FAM can also be set to use FEC aggressive mode (860T). */ imp->im_siu_conf.sc_sdcr = 1; @@ -99,10 +109,10 @@ /* Initialize the CPM interrupt controller. */ - ((immap_t *)MBX_IMAP_ADDR)->im_cpic.cpic_cicr = + ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr = (CICR_SCD_SCC4 | CICR_SCC_SCC3 | CICR_SCB_SCC2 | CICR_SCA_SCC1) | ((CPM_INTERRUPT/2) << 13) | CICR_HP_MASK; - ((immap_t *)MBX_IMAP_ADDR)->im_cpic.cpic_cimr = 0; + ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr = 0; /* Set our interrupt handler with the core CPU. */ if (request_irq(CPM_INTERRUPT, cpm_interrupt, 0, "cpm", NULL) != 0) @@ -111,7 +121,7 @@ /* Install our own error handler. */ cpm_install_handler(CPMVEC_ERROR, cpm_error_interrupt, NULL); - ((immap_t *)MBX_IMAP_ADDR)->im_cpic.cpic_cicr |= CICR_IEN; + ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr |= CICR_IEN; } /* CPM interrupt controller interrupt. @@ -124,19 +134,19 @@ /* Get the vector by setting the ACK bit and then reading * the register. */ - ((volatile immap_t *)MBX_IMAP_ADDR)->im_cpic.cpic_civr = 1; - vec = ((volatile immap_t *)MBX_IMAP_ADDR)->im_cpic.cpic_civr; + ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr = 1; + vec = ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr; vec >>= 11; if (cpm_vecs[vec].handler != 0) (*cpm_vecs[vec].handler)(cpm_vecs[vec].dev_id); else - ((immap_t *)MBX_IMAP_ADDR)->im_cpic.cpic_cimr &= ~(1 << vec); + ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr &= ~(1 << vec); /* After servicing the interrupt, we have to remove the status * indicator. */ - ((immap_t *)MBX_IMAP_ADDR)->im_cpic.cpic_cisr |= (1 << vec); + ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cisr |= (1 << vec); } @@ -160,7 +170,7 @@ (uint)handler, (uint)cpm_vecs[vec].handler); cpm_vecs[vec].handler = handler; cpm_vecs[vec].dev_id = dev_id; - ((immap_t *)MBX_IMAP_ADDR)->im_cpic.cpic_cimr |= (1 << vec); + ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr |= (1 << vec); } /* Allocate some memory from the dual ported ram. We may want to @@ -168,7 +178,7 @@ * citizen. */ uint -mbx_cpm_dpalloc(uint size) +m8xx_cpm_dpalloc(uint size) { uint retloc; @@ -185,7 +195,7 @@ * UART "fifos" and the like. */ uint -mbx_cpm_hostalloc(uint size) +m8xx_cpm_hostalloc(uint size) { uint retloc; @@ -201,13 +211,13 @@ /* Set a baud rate generator. This needs lots of work. There are * four BRGs, any of which can be wired to any channel. * The internal baud rate clock is the system clock divided by 16. - * I need to find a way to get this system clock frequency, which is - * part of the VPD....... + * This assumes the baudrate is 16x oversampled by the uart. */ -#define BRG_INT_CLK (40000000/16) +#define BRG_INT_CLK (((bd_t *)res)->bi_intfreq * 1000000) +#define BRG_UART_CLK (BRG_INT_CLK/16) void -mbx_cpm_setbrg(uint brg, uint rate) +m8xx_cpm_setbrg(uint brg, uint rate) { volatile uint *bp; @@ -215,5 +225,6 @@ */ bp = (uint *)&cpmp->cp_brgc1; bp += brg; - *bp = ((BRG_INT_CLK / rate) << 1) | CPM_BRG_EN; + *bp = ((BRG_UART_CLK / rate) << 1) | CPM_BRG_EN; } + diff -u --recursive --new-file v2.1.123/linux/arch/ppc/8xx_io/commproc.h linux/arch/ppc/8xx_io/commproc.h --- v2.1.123/linux/arch/ppc/8xx_io/commproc.h Thu Apr 23 20:21:28 1998 +++ linux/arch/ppc/8xx_io/commproc.h Wed Sep 30 10:14:16 1998 @@ -62,9 +62,9 @@ * and dual port ram. */ extern cpm8xx_t *cpmp; /* Pointer to comm processor */ -uint mbx_cpm_dpalloc(uint size); -uint mbx_cpm_hostalloc(uint size); -void mbx_cpm_setbrg(uint brg, uint rate); +uint m8xx_cpm_dpalloc(uint size); +uint m8xx_cpm_hostalloc(uint size); +void m8xx_cpm_setbrg(uint brg, uint rate); /* Buffer descriptors used by many of the CPM protocols. */ @@ -87,8 +87,16 @@ #define BD_SC_OV ((ushort)0x0002) /* Overrun */ #define BD_SC_CD ((ushort)0x0001) /* ?? */ -/* Define enough so I can at least use the MBX serial port as a UART. - * The MBX uses SMC1 as the host serial port. +/* Parameter RAM offsets. +*/ +#define PROFF_SCC1 ((uint)0x0000) +#define PROFF_SCC2 ((uint)0x0100) +#define PROFF_SCC3 ((uint)0x0200) +#define PROFF_SMC1 ((uint)0x0280) +#define PROFF_SCC4 ((uint)0x0300) +#define PROFF_SMC2 ((uint)0x0380) + +/* Define enough so I can at least use the serial port as a UART. */ typedef struct smc_uart { ushort smc_rbase; /* Rx Buffer descriptor base address */ @@ -114,9 +122,6 @@ ushort smc_rmask; /* Temporary bit mask */ } smc_uart_t; -#define PROFF_SMC1 ((uint)0x0280) /* Offset in Parameter RAM */ -#define PROFF_SMC2 ((uint)0x0380) - /* Function code bits. */ #define SMC_EB ((u_char)0x10) /* Set big endian byte order */ @@ -139,7 +144,7 @@ /* SMC Event and Mask register. */ #define SMCM_TXE ((unsigned char)0x10) -#define SMCM_BSY ((unsigned char)0x14) +#define SMCM_BSY ((unsigned char)0x04) #define SMCM_TX ((unsigned char)0x02) #define SMCM_RX ((unsigned char)0x01) @@ -238,6 +243,13 @@ #define SCC_TODR_TOD ((ushort)0x8000) +/* SCC Event and Mask register. +*/ +#define SCCM_TXE ((unsigned char)0x10) +#define SCCM_BSY ((unsigned char)0x04) +#define SCCM_TX ((unsigned char)0x02) +#define SCCM_RX ((unsigned char)0x01) + typedef struct scc_param { ushort scc_rbase; /* Rx Buffer descriptor base address */ ushort scc_tbase; /* Tx Buffer descriptor base address */ @@ -317,8 +329,6 @@ ushort sen_taddrl; /* temp address (LSB) */ } scc_enet_t; -#define PROFF_SCC1 ((uint)0x0000) /* Offset in Parameter RAM */ - /* Bits in parallel I/O port registers that have to be set/cleared * to configure the pins for SCC1 use. The TCLK and RCLK seem unique * to the MBX860 board. Any two of the four available clocks could be @@ -397,6 +407,37 @@ #define BD_ENET_TX_CSL ((ushort)0x0001) #define BD_ENET_TX_STATS ((ushort)0x03ff) /* All status bits */ +/* SCC as UART +*/ +typedef struct scc_uart { + sccp_t scc_genscc; + uint scc_res1; /* Reserved */ + uint scc_res2; /* Reserved */ + ushort scc_maxidl; /* Maximum idle chars */ + ushort scc_idlc; /* temp idle counter */ + ushort scc_brkcr; /* Break count register */ + ushort scc_parec; /* receive parity error counter */ + ushort scc_frmec; /* receive framing error counter */ + ushort scc_nosec; /* receive noise counter */ + ushort scc_brkec; /* receive break condition counter */ + ushort scc_brkln; /* last received break length */ + ushort scc_uaddr1; /* UART address character 1 */ + ushort scc_uaddr2; /* UART address character 2 */ + ushort scc_rtemp; /* Temp storage */ + ushort scc_toseq; /* Transmit out of sequence char */ + ushort scc_char1; /* control character 1 */ + ushort scc_char2; /* control character 2 */ + ushort scc_char3; /* control character 3 */ + ushort scc_char4; /* control character 4 */ + ushort scc_char5; /* control character 5 */ + ushort scc_char6; /* control character 6 */ + ushort scc_char7; /* control character 7 */ + ushort scc_char8; /* control character 8 */ + ushort scc_rccm; /* receive control character mask */ + ushort scc_rccr; /* receive control character register */ + ushort scc_rlbc; /* receive last break character */ +} scc_uart_t; + /* SCC Event and Mask registers when it is used as a UART. */ #define UART_SCCM_GLR ((ushort)0x1000) @@ -410,6 +451,30 @@ #define UART_SCCM_BSY ((ushort)0x0004) #define UART_SCCM_TX ((ushort)0x0002) #define UART_SCCM_RX ((ushort)0x0001) + +/* The SCC PMSR when used as a UART. +*/ +#define SCU_PMSR_FLC ((ushort)0x8000) +#define SCU_PMSR_SL ((ushort)0x4000) +#define SCU_PMSR_CL ((ushort)0x3000) +#define SCU_PMSR_UM ((ushort)0x0c00) +#define SCU_PMSR_FRZ ((ushort)0x0200) +#define SCU_PMSR_RZS ((ushort)0x0100) +#define SCU_PMSR_SYN ((ushort)0x0080) +#define SCU_PMSR_DRT ((ushort)0x0040) +#define SCU_PMSR_PEN ((ushort)0x0010) +#define SCU_PMSR_RPM ((ushort)0x000c) +#define SCU_PMSR_REVP ((ushort)0x0008) +#define SCU_PMSR_TPM ((ushort)0x0003) +#define SCU_PMSR_TEVP ((ushort)0x0003) + +/* CPM Transparent mode SCC. + */ +typedef struct scc_trans { + sccp_t st_genscc; + uint st_cpres; /* Preset CRC */ + uint st_cmask; /* Constant mask for CRC */ +} scc_trans_t; /* CPM interrupts. There are nearly 32 interrupts generated by CPM * channels or devices. All of these are presented to the PPC core diff -u --recursive --new-file v2.1.123/linux/arch/ppc/8xx_io/enet.c linux/arch/ppc/8xx_io/enet.c --- v2.1.123/linux/arch/ppc/8xx_io/enet.c Fri May 8 23:14:44 1998 +++ linux/arch/ppc/8xx_io/enet.c Wed Sep 30 10:14:16 1998 @@ -96,7 +96,7 @@ */ /* The number of Tx and Rx buffers. These are allocated from the page - * pool. The code may assume these are power of two, so it it best + * pool. The code may assume these are power of two, so it is best * to keep them that size. * We don't need to allocate pages for the transmitter. We just use * the skbuffer directly. diff -u --recursive --new-file v2.1.123/linux/arch/ppc/8xx_io/fec.c linux/arch/ppc/8xx_io/fec.c --- v2.1.123/linux/arch/ppc/8xx_io/fec.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/8xx_io/fec.c Wed Sep 30 10:14:16 1998 @@ -0,0 +1,985 @@ +/* + * Fast Ethernet Controller (FECC) driver for Motorola MPC8xx. + * Copyright (c) 1997 Dan Malek (dmalek@jlc.net) + * + * This version of the driver is specific to the FADS implementation, + * since the board contains control registers external to the processor + * for the control of the LevelOne LXT970 transceiver. The MPC860T manual + * describes connections using the internal parallel port I/O, which + * is basically all of Port D. + * + * Right now, I am very watseful with the buffers. I allocate memory + * pages and then divide them into 2K frame buffers. This way I know I + * have buffers large enough to hold one frame within one buffer descriptor. + * Once I get this working, I will use 64 or 128 byte CPM buffers, which + * will be much more memory efficient and will easily handle lots of + * small packets. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "commproc.h" + +/* The number of Tx and Rx buffers. These are allocated from the page + * pool. The code may assume these are power of two, so it it best + * to keep them that size. + * We don't need to allocate pages for the transmitter. We just use + * the skbuffer directly. + */ +#if 1 +#define FEC_ENET_RX_PAGES 4 +#define FEC_ENET_RX_FRSIZE 2048 +#define FEC_ENET_RX_FRPPG (PAGE_SIZE / FEC_ENET_RX_FRSIZE) +#define RX_RING_SIZE (FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES) +#define TX_RING_SIZE 8 /* Must be power of two */ +#define TX_RING_MOD_MASK 7 /* for this to work */ +#else +#define FEC_ENET_RX_PAGES 16 +#define FEC_ENET_RX_FRSIZE 2048 +#define FEC_ENET_RX_FRPPG (PAGE_SIZE / FEC_ENET_RX_FRSIZE) +#define RX_RING_SIZE (FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES) +#define TX_RING_SIZE 16 /* Must be power of two */ +#define TX_RING_MOD_MASK 15 /* for this to work */ +#endif + +/* Interrupt events/masks. +*/ +#define FEC_ENET_HBERR ((uint)0x80000000) /* Heartbeat error */ +#define FEC_ENET_BABR ((uint)0x40000000) /* Babbling receiver */ +#define FEC_ENET_BABT ((uint)0x20000000) /* Babbling transmitter */ +#define FEC_ENET_GRA ((uint)0x10000000) /* Graceful stop complete */ +#define FEC_ENET_TXF ((uint)0x08000000) /* Full frame transmitted */ +#define FEC_ENET_TXB ((uint)0x04000000) /* A buffer was transmitted */ +#define FEC_ENET_RXF ((uint)0x02000000) /* Full frame received */ +#define FEC_ENET_RXB ((uint)0x01000000) /* A buffer was received */ +#define FEC_ENET_MII ((uint)0x00800000) /* MII interrupt */ +#define FEC_ENET_EBERR ((uint)0x00400000) /* SDMA bus error */ + +/* The FEC stores dest/src/type, data, and checksum for receive packets. + */ +#define PKT_MAXBUF_SIZE 1518 +#define PKT_MINBUF_SIZE 64 +#define PKT_MAXBLR_SIZE 1520 + +/* The FEC buffer descriptors track the ring buffers. The rx_bd_base and + * tx_bd_base always point to the base of the buffer descriptors. The + * cur_rx and cur_tx point to the currently available buffer. + * The dirty_tx tracks the current buffer that is being sent by the + * controller. The cur_tx and dirty_tx are equal under both completely + * empty and completely full conditions. The empty/ready indicator in + * the buffer descriptor determines the actual condition. + */ +struct fec_enet_private { + /* The saved address of a sent-in-place packet/buffer, for skfree(). */ + struct sk_buff* tx_skbuff[TX_RING_SIZE]; + ushort skb_cur; + ushort skb_dirty; + + /* CPM dual port RAM relative addresses. + */ + cbd_t *rx_bd_base; /* Address of Rx and Tx buffers. */ + cbd_t *tx_bd_base; + cbd_t *cur_rx, *cur_tx; /* The next free ring entry */ + cbd_t *dirty_tx; /* The ring entries to be free()ed. */ + scc_t *sccp; + struct net_device_stats stats; + char tx_full; + unsigned long lock; +}; + +static int fec_enet_open(struct device *dev); +static int fec_enet_start_xmit(struct sk_buff *skb, struct device *dev); +static int fec_enet_rx(struct device *dev); +static void fec_enet_mii(struct device *dev); +static void fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs); +static int fec_enet_close(struct device *dev); +static struct net_device_stats *fec_enet_get_stats(struct device *dev); +static void set_multicast_list(struct device *dev); + +static ushort my_enet_addr[] = { 0x0800, 0x3e26, 0x1559 }; + +/* MII processing. We keep this as simple as possible. Requests are + * placed on the list (if there is room). When the request is finished + * by the MII, an optional function may be called. + */ +typedef struct mii_list { + uint mii_regval; + void (*mii_func)(uint val); + struct mii_list *mii_next; +} mii_list_t; + +#define NMII 10 +mii_list_t mii_cmds[NMII]; +mii_list_t *mii_free; +mii_list_t *mii_head; +mii_list_t *mii_tail; + +static int mii_queue(int request, void (*func)(int)); + +/* Make MII read/write commands for the FEC. +*/ +#define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18)) +#define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | \ + (VAL & 0xffff)) + +static int +fec_enet_open(struct device *dev) +{ + + /* I should reset the ring buffers here, but I don't yet know + * a simple way to do that. + */ + + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + + return 0; /* Always succeed */ +} + +static int +fec_enet_start_xmit(struct sk_buff *skb, struct device *dev) +{ + struct fec_enet_private *fep = (struct fec_enet_private *)dev->priv; + volatile cbd_t *bdp; + unsigned long flags; + + /* Transmitter timeout, serious problems. */ + if (dev->tbusy) { + int tickssofar = jiffies - dev->trans_start; + if (tickssofar < 20) + return 1; + printk("%s: transmit timed out.\n", dev->name); + fep->stats.tx_errors++; +#ifndef final_version + { + int i; + cbd_t *bdp; + printk(" Ring data dump: cur_tx %x%s cur_rx %x.\n", + fep->cur_tx, fep->tx_full ? " (full)" : "", + fep->cur_rx); + bdp = fep->tx_bd_base; + for (i = 0 ; i < TX_RING_SIZE; i++) + printk("%04x %04x %08x\n", + bdp->cbd_sc, + bdp->cbd_datlen, + bdp->cbd_bufaddr); + bdp = fep->rx_bd_base; + for (i = 0 ; i < RX_RING_SIZE; i++) + printk("%04x %04x %08x\n", + bdp->cbd_sc, + bdp->cbd_datlen, + bdp->cbd_bufaddr); + } +#endif + + dev->tbusy=0; + dev->trans_start = jiffies; + + return 0; + } + + /* Block a timer-based transmit from overlapping. This could better be + done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ + if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { + printk("%s: Transmitter access conflict.\n", dev->name); + return 1; + } + + if (test_and_set_bit(0, (void*)&fep->lock) != 0) { + printk("%s: tx queue lock!.\n", dev->name); + /* don't clear dev->tbusy flag. */ + return 1; + } + + /* Fill in a Tx ring entry */ + bdp = fep->cur_tx; + +#ifndef final_version + if (bdp->cbd_sc & BD_ENET_TX_READY) { + /* Ooops. All transmit buffers are full. Bail out. + * This should not happen, since dev->tbusy should be set. + */ + printk("%s: tx queue full!.\n", dev->name); + fep->lock = 0; + return 1; + } +#endif + + /* Clear all of the status flags. + */ + bdp->cbd_sc &= ~BD_ENET_TX_STATS; + + /* Set buffer length and buffer pointer. + */ + bdp->cbd_bufaddr = __pa(skb->data); + bdp->cbd_datlen = skb->len; + + /* Save skb pointer. + */ + fep->tx_skbuff[fep->skb_cur] = skb; + + fep->stats.tx_bytes += skb->len; + fep->skb_cur = (fep->skb_cur+1) & TX_RING_MOD_MASK; + + /* Push the data cache so the CPM does not get stale memory + * data. + */ + /*flush_dcache_range(skb->data, skb->data + skb->len);*/ + + /* Send it on its way. Tell CPM its ready, interrupt when done, + * its the last BD of the frame, and to put the CRC on the end. + */ + save_flags(flags); + cli(); + + bdp->cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_INTR | BD_ENET_TX_LAST | BD_ENET_TX_TC); + + dev->trans_start = jiffies; + (&(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec))->fec_x_des_active = 0x01000000; + + /* If this was the last BD in the ring, start at the beginning again. + */ + if (bdp->cbd_sc & BD_ENET_TX_WRAP) + bdp = fep->tx_bd_base; + else + bdp++; + + fep->lock = 0; + if (bdp->cbd_sc & BD_ENET_TX_READY) + fep->tx_full = 1; + else + dev->tbusy=0; + restore_flags(flags); + + fep->cur_tx = (cbd_t *)bdp; + + return 0; +} + +/* The interrupt handler. + * This is called from the MPC core interrupt. + */ +static void +fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs) +{ + struct device *dev = dev_id; + struct fec_enet_private *fep; + volatile cbd_t *bdp; + volatile fec_t *ep; + uint int_events; + int c=0; + + fep = (struct fec_enet_private *)dev->priv; + ep = &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec); + if (dev->interrupt) + printk("%s: Re-entering the interrupt handler.\n", dev->name); + dev->interrupt = 1; + + /* Get the interrupt events that caused us to be here. + */ + while ((int_events = ep->fec_ievent) != 0) { + ep->fec_ievent = int_events; + if ((int_events & + (FEC_ENET_HBERR | FEC_ENET_BABR | + FEC_ENET_BABT | FEC_ENET_EBERR)) != 0) + printk("FEC ERROR %x\n", int_events); + + /* Handle receive event in its own function. + */ + if (int_events & (FEC_ENET_RXF | FEC_ENET_RXB)) + fec_enet_rx(dev_id); + + /* Transmit OK, or non-fatal error. Update the buffer descriptors. + * FEC handles all errors, we just discover them as part of the + * transmit process. + */ + if (int_events & (FEC_ENET_TXF | FEC_ENET_TXB)) { + bdp = fep->dirty_tx; + while ((bdp->cbd_sc&BD_ENET_TX_READY)==0) { +#if 1 + if (bdp==fep->cur_tx) + break; +#endif + if (++c>1) {/*we go here when an it has been lost*/}; + + + if (bdp->cbd_sc & BD_ENET_TX_HB) /* No heartbeat */ + fep->stats.tx_heartbeat_errors++; + if (bdp->cbd_sc & BD_ENET_TX_LC) /* Late collision */ + fep->stats.tx_window_errors++; + if (bdp->cbd_sc & BD_ENET_TX_RL) /* Retrans limit */ + fep->stats.tx_aborted_errors++; + if (bdp->cbd_sc & BD_ENET_TX_UN) /* Underrun */ + fep->stats.tx_fifo_errors++; + if (bdp->cbd_sc & BD_ENET_TX_CSL) /* Carrier lost */ + fep->stats.tx_carrier_errors++; + + fep->stats.tx_errors++; + + fep->stats.tx_packets++; + +#ifndef final_version + if (bdp->cbd_sc & BD_ENET_TX_READY) + printk("HEY! Enet xmit interrupt and TX_READY.\n"); +#endif + /* Deferred means some collisions occurred during transmit, + * but we eventually sent the packet OK. + */ + if (bdp->cbd_sc & BD_ENET_TX_DEF) + fep->stats.collisions++; + + /* Free the sk buffer associated with this last transmit. + */ + dev_kfree_skb(fep->tx_skbuff[fep->skb_dirty]/*, FREE_WRITE*/); + fep->skb_dirty = (fep->skb_dirty + 1) & TX_RING_MOD_MASK; + + /* Update pointer to next buffer descriptor to be transmitted. + */ + if (bdp->cbd_sc & BD_ENET_TX_WRAP) + bdp = fep->tx_bd_base; + else + bdp++; + + /* Since we have freed up a buffer, the ring is no longer + * full. + */ + if (fep->tx_full && dev->tbusy) { + fep->tx_full = 0; + dev->tbusy = 0; + mark_bh(NET_BH); + } + + fep->dirty_tx = (cbd_t *)bdp; +#if 0 + if (bdp==fep->cur_tx) + break; +#endif + }/*while (bdp->cbd_sc&BD_ENET_TX_READY)==0*/ + } /* if tx events */ + + if (int_events & FEC_ENET_MII) + fec_enet_mii(dev_id); + + } /* while any events */ + + dev->interrupt = 0; + + return; +} + +/* During a receive, the cur_rx points to the current incoming buffer. + * When we update through the ring, if the next incoming buffer has + * not been given to the system, we just set the empty indicator, + * effectively tossing the packet. + */ +static int +fec_enet_rx(struct device *dev) +{ + struct fec_enet_private *fep; + volatile cbd_t *bdp; + struct sk_buff *skb; + ushort pkt_len; + volatile fec_t *ep; + + fep = (struct fec_enet_private *)dev->priv; + ep = &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec); + + /* First, grab all of the stats for the incoming packet. + * These get messed up if we get called due to a busy condition. + */ + bdp = fep->cur_rx; + +for (;;) { + if (bdp->cbd_sc & BD_ENET_RX_EMPTY) + break; + +#ifndef final_version + /* Since we have allocated space to hold a complete frame, + * the last indicator should be set. + */ + if ((bdp->cbd_sc & BD_ENET_RX_LAST) == 0) + printk("FEC ENET: rcv is not +last\n"); +#endif + + /* Frame too long or too short. + */ + if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH)) + fep->stats.rx_length_errors++; + if (bdp->cbd_sc & BD_ENET_RX_NO) /* Frame alignment */ + fep->stats.rx_frame_errors++; + if (bdp->cbd_sc & BD_ENET_RX_CR) /* CRC Error */ + fep->stats.rx_crc_errors++; + if (bdp->cbd_sc & BD_ENET_RX_OV) /* FIFO overrun */ + fep->stats.rx_crc_errors++; + + /* Report late collisions as a frame error. + * On this error, the BD is closed, but we don't know what we + * have in the buffer. So, just drop this frame on the floor. + */ + if (bdp->cbd_sc & BD_ENET_RX_CL) { + fep->stats.rx_frame_errors++; + } + else { + + /* Process the incoming frame. + */ + fep->stats.rx_packets++; + pkt_len = bdp->cbd_datlen; + fep->stats.rx_bytes += pkt_len; + + /* This does 16 byte alignment, exactly what we need. + */ + skb = dev_alloc_skb(pkt_len); + + if (skb == NULL) { + printk("%s: Memory squeeze, dropping packet.\n", dev->name); + fep->stats.rx_dropped++; + } + else { + skb->dev = dev; + skb_put(skb,pkt_len); /* Make room */ + eth_copy_and_sum(skb, + (unsigned char *)__va(bdp->cbd_bufaddr), + pkt_len, 0); + skb->protocol=eth_type_trans(skb,dev); + netif_rx(skb); + } + } + + /* Clear the status flags for this buffer. + */ + bdp->cbd_sc &= ~BD_ENET_RX_STATS; + + /* Mark the buffer empty. + */ + bdp->cbd_sc |= BD_ENET_RX_EMPTY; + + /* Update BD pointer to next entry. + */ + if (bdp->cbd_sc & BD_ENET_RX_WRAP) + bdp = fep->rx_bd_base; + else + bdp++; + +#if 1 + /* Doing this here will keep the FEC running while we process + * incoming frames. On a heavily loaded network, we should be + * able to keep up at the expense of system resources. + */ + ep->fec_r_des_active = 0x01000000; +#endif + } + fep->cur_rx = (cbd_t *)bdp; + +#if 0 + /* Doing this here will allow us to process all frames in the + * ring before the FEC is allowed to put more there. On a heavily + * loaded network, some frames may be lost. Unfortunately, this + * increases the interrupt overhead since we can potentially work + * our way back to the interrupt return only to come right back + * here. + */ + ep->fec_r_des_active = 0x01000000; +#endif + + return 0; +} + +static void +fec_enet_mii(struct device *dev) +{ + struct fec_enet_private *fep; + volatile fec_t *ep; + mii_list_t *mip; + uint mii_reg; + + fep = (struct fec_enet_private *)dev->priv; + ep = &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec); + mii_reg = ep->fec_mii_data; + + if ((mip = mii_head) == NULL) { + printk("MII and no head!\n"); + return; + } + + if (mip->mii_func != NULL) + (*(mip->mii_func))(mii_reg); + + mii_head = mip->mii_next; + mip->mii_next = mii_free; + mii_free = mip; + + if ((mip = mii_head) != NULL) + ep->fec_mii_data = mip->mii_regval; +} + +static int +mii_queue(int regval, void (*func)(int)) +{ + unsigned long flags; + mii_list_t *mip; + int retval; + + retval = 0; + + save_flags(flags); + cli(); + + if ((mip = mii_free) != NULL) { + mii_free = mip->mii_next; + mip->mii_regval = regval; + mip->mii_func = func; + mip->mii_next = NULL; + if (mii_head) { + mii_tail->mii_next = mip; + mii_tail = mip; + } + else { + mii_head = mii_tail = mip; + (&(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec))->fec_mii_data = regval; + } + } + else { + retval = 1; + } + + restore_flags(flags); + + return(retval); +} + +static void +mii_status(uint mii_reg) +{ + if (((mii_reg >> 18) & 0x1f) == 1) { + /* status register. + */ + printk("fec: "); + if (mii_reg & 0x0004) + printk("link up"); + else + printk("link down"); + + if (mii_reg & 0x0010) + printk(",remote fault"); + if (mii_reg & 0x0020) + printk(",auto complete"); + printk("\n"); + } + if (((mii_reg >> 18) & 0x1f) == 0x14) { + /* Extended chip status register. + */ + printk("fec: "); + if (mii_reg & 0x0800) + printk("100 Mbps"); + else + printk("10 Mbps"); + + if (mii_reg & 0x1000) + printk(", Full-Duplex\n"); + else + printk(", Half-Duplex\n"); + } +} + +static void +mii_startup_cmds(void) +{ + + /* Read status registers to clear any pending interrupt. + */ + mii_queue(mk_mii_read(1), mii_status); + mii_queue(mk_mii_read(18), mii_status); + + /* Read extended chip status register. + */ + mii_queue(mk_mii_read(0x14), mii_status); + + /* Enable Link status change interrupts. + mii_queue(mk_mii_write(0x11, 0x0002), NULL); + */ +} + +/* This supports the mii_link interrupt below. + * We should get called three times. Once for register 1, once for + * register 18, and once for register 20. + */ +static uint mii_saved_reg1; + +static void +mii_relink(uint mii_reg) +{ + if (((mii_reg >> 18) & 0x1f) == 1) { + /* Just save the status register and get out. + */ + mii_saved_reg1 = mii_reg; + return; + } + if (((mii_reg >> 18) & 0x1f) == 18) { + /* Not much here, but has to be read to clear the + * interrupt condition. + */ + if ((mii_reg & 0x8000) == 0) + printk("fec: re-link and no IRQ?\n"); + if ((mii_reg & 0x4000) == 0) + printk("fec: no PHY power?\n"); + } + if (((mii_reg >> 18) & 0x1f) == 20) { + /* Extended chip status register. + * OK, now we have it all, so figure out what is going on. + */ + printk("fec: "); + if (mii_saved_reg1 & 0x0004) + printk("link up"); + else + printk("link down"); + + if (mii_saved_reg1 & 0x0010) + printk(", remote fault"); + if (mii_saved_reg1 & 0x0020) + printk(", auto complete"); + + if (mii_reg & 0x0800) + printk(", 100 Mbps"); + else + printk(", 10 Mbps"); + + if (mii_reg & 0x1000) + printk(", Full-Duplex\n"); + else + printk(", Half-Duplex\n"); + } +} + +/* This interrupt occurs when the LTX970 detects a link change. +*/ +static void +mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs) +{ + struct device *dev = dev_id; + struct fec_enet_private *fep; + volatile fec_t *ep; + + fep = (struct fec_enet_private *)dev->priv; + ep = &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec); + + /* We need to sequentially read registers 1 and 18 to clear + * the interrupt. We don't need to do that here because this + * is an edge triggered interrupt that has already been acknowledged + * by the top level handler. We also read the extended status + * register 20. We just queue the commands and let them happen + * as part of the "normal" processing. + */ + mii_queue(mk_mii_read(1), mii_relink); + mii_queue(mk_mii_read(18), mii_relink); + mii_queue(mk_mii_read(20), mii_relink); +} + +static int +fec_enet_close(struct device *dev) +{ + /* Don't know what to do yet. + */ + + return 0; +} + +static struct net_device_stats *fec_enet_get_stats(struct device *dev) +{ + struct fec_enet_private *fep = (struct fec_enet_private *)dev->priv; + + return &fep->stats; +} + +/* Set or clear the multicast filter for this adaptor. + * Skeleton taken from sunlance driver. + * The CPM Ethernet implementation allows Multicast as well as individual + * MAC address filtering. Some of the drivers check to make sure it is + * a group multicast address, and discard those that are not. I guess I + * will do the same for now, but just remove the test if you want + * individual filtering as well (do the upper net layers want or support + * this kind of feature?). + */ + +static void set_multicast_list(struct device *dev) +{ + struct fec_enet_private *fep; + struct dev_mc_list *dmi; + u_char *mcptr, *tdptr; + volatile fec_t *ep; + int i, j; + + fep = (struct fec_enet_private *)dev->priv; + ep = &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec); + + if (dev->flags&IFF_PROMISC) { + + /* Log any net taps. */ + printk("%s: Promiscuous mode enabled.\n", dev->name); + ep->fec_r_cntrl |= 0x0008; + } else { + + ep->fec_r_cntrl &= ~0x0008; + + if (dev->flags & IFF_ALLMULTI) { + /* Catch all multicast addresses, so set the + * filter to all 1's. + */ + ep->fec_hash_table_high = 0xffffffff; + ep->fec_hash_table_low = 0xffffffff; + } +#if 0 + else { + /* Clear filter and add the addresses in the list. + */ + ep->sen_gaddr1 = 0; + ep->sen_gaddr2 = 0; + ep->sen_gaddr3 = 0; + ep->sen_gaddr4 = 0; + + dmi = dev->mc_list; + + for (i=0; imc_count; i++) { + + /* Only support group multicast for now. + */ + if (!(dmi->dmi_addr[0] & 1)) + continue; + + /* The address in dmi_addr is LSB first, + * and taddr is MSB first. We have to + * copy bytes MSB first from dmi_addr. + */ + mcptr = (u_char *)dmi->dmi_addr + 5; + tdptr = (u_char *)&ep->sen_taddrh; + for (j=0; j<6; j++) + *tdptr++ = *mcptr--; + + /* Ask CPM to run CRC and set bit in + * filter mask. + */ + cpmp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SCC1, CPM_CR_SET_GADDR) | CPM_CR_FLG; + /* this delay is necessary here -- Cort */ + udelay(10); + while (cpmp->cp_cpcr & CPM_CR_FLG); + } + } +#endif + } +} + +/* Initialize the FECC Ethernet on 860T. + */ +__initfunc(int m8xx_enet_init(void)) +{ + struct device *dev; + struct fec_enet_private *fep; + int i, j; + unsigned char *eap; + unsigned long mem_addr; + pte_t *pte; + volatile cbd_t *bdp; + cbd_t *cbd_base; + volatile immap_t *immap; + volatile fec_t *fecp; + unsigned char rtc_save_cfg, rtc_val; + + immap = (immap_t *)IMAP_ADDR; /* pointer to internal registers */ + + /* Allocate some private information. + */ + fep = (struct fec_enet_private *)kmalloc(sizeof(*fep), GFP_KERNEL); + __clear_user(fep,sizeof(*fep)); + + /* Create an Ethernet device instance. + */ + dev = init_etherdev(0, 0); + + fecp = &(immap->im_cpm.cp_fec); + + /* Whack a reset. We should wait for this. + */ + fecp->fec_ecntrl = 1; + udelay(10); + + /* Enable interrupts we wish to service. + */ + fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB | + FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII); + + /* Clear any outstanding interrupt. + */ + fecp->fec_ievent = 0xffc0; + + fecp->fec_ivec = (FEC_INTERRUPT/2) << 29; + + /* Set station address. + */ + fecp->fec_addr_low = (my_enet_addr[0] << 16) | my_enet_addr[1]; + fecp->fec_addr_high = my_enet_addr[2]; + + eap = (unsigned char *)&my_enet_addr[0]; + for (i=0; i<6; i++) + dev->dev_addr[i] = *eap++; + + /* Reset all multicast. + */ + fecp->fec_hash_table_high = 0; + fecp->fec_hash_table_low = 0; + + /* Set maximum receive buffer size. + */ + fecp->fec_r_buff_size = PKT_MAXBLR_SIZE; + fecp->fec_r_hash = PKT_MAXBUF_SIZE; + + /* Allocate memory for buffer descriptors. + */ + if (((RX_RING_SIZE + TX_RING_SIZE) * sizeof(cbd_t)) > PAGE_SIZE) { + printk("FECC init error. Need more space.\n"); + printk("FECC initialization failed.\n"); + return 1; + } + mem_addr = __get_free_page(GFP_KERNEL); + cbd_base = (cbd_t *)mem_addr; + + /* Make it uncached. + */ + pte = va_to_pte(&init_task, (int)mem_addr); + pte_val(*pte) |= _PAGE_NO_CACHE; + flush_tlb_page(current->mm->mmap, mem_addr); + + /* Set receive and transmit descriptor base. + */ + fecp->fec_r_des_start = __pa(mem_addr); + fep->rx_bd_base = cbd_base; + fecp->fec_x_des_start = __pa((unsigned long)(cbd_base + RX_RING_SIZE)); + fep->tx_bd_base = cbd_base + RX_RING_SIZE; + + fep->dirty_tx = fep->cur_tx = fep->tx_bd_base; + fep->cur_rx = fep->rx_bd_base; + + fep->skb_cur = fep->skb_dirty = 0; + + /* Initialize the receive buffer descriptors. + */ + bdp = fep->rx_bd_base; + for (i=0; imm->mmap, mem_addr); + + /* Initialize the BD for every fragment in the page. + */ + for (j=0; jcbd_sc = BD_ENET_RX_EMPTY; + bdp->cbd_bufaddr = __pa(mem_addr); + mem_addr += FEC_ENET_RX_FRSIZE; + bdp++; + } + } + + /* Set the last buffer to wrap. + */ + bdp--; + bdp->cbd_sc |= BD_SC_WRAP; + + /* ...and the same for transmmit. + */ + bdp = fep->tx_bd_base; + for (i=0; icbd_sc = 0; + bdp->cbd_bufaddr = 0; + bdp++; + } + + /* Set the last buffer to wrap. + */ + bdp--; + bdp->cbd_sc |= BD_SC_WRAP; + + /* Enable MII mode, half-duplex until we know better.. + */ + fecp->fec_r_cntrl = 0x0c; + fecp->fec_x_cntrl = 0x00; + + /* Enable big endian and don't care about SDMA FC. + */ + fecp->fec_fun_code = 0x78000000; + + /* Set MII speed (50 MHz core). + */ + fecp->fec_mii_speed = 0x14; + + /* Configure all of port D for MII. + */ + immap->im_ioport.iop_pdpar = 0x1fff; + immap->im_ioport.iop_pddir = 0x1c58; + + /* Install our interrupt handlers. The 860T FADS board uses + * IRQ2 for the MII interrupt. + */ + if (request_irq(FEC_INTERRUPT, fec_enet_interrupt, 0, "fec", dev) != 0) + panic("Could not allocate FEC IRQ!"); + if (request_irq(SIU_IRQ2, mii_link_interrupt, 0, "mii", dev) != 0) + panic("Could not allocate MII IRQ!"); + + dev->base_addr = (unsigned long)fecp; + dev->priv = fep; + dev->name = "fec"; + + /* The FEC Ethernet specific entries in the device structure. */ + dev->open = fec_enet_open; + dev->hard_start_xmit = fec_enet_start_xmit; + dev->stop = fec_enet_close; + dev->get_stats = fec_enet_get_stats; + dev->set_multicast_list = set_multicast_list; + + /* And last, enable the transmit and receive processing. + */ + fecp->fec_ecntrl = 2; + fecp->fec_r_des_active = 0x01000000; + + printk("FEC ENET Version 0.1, "); + for (i=0; i<5; i++) + printk("%02x:", dev->dev_addr[i]); + printk("%02x\n", dev->dev_addr[5]); + + for (i=0; i #include #include +#include +#ifdef CONFIG_MBX +#include +#endif +#ifdef CONFIG_FADS +#include +#endif #include "commproc.h" #ifdef CONFIG_SERIAL_CONSOLE @@ -53,7 +60,7 @@ #define TX_WAKEUP ASYNC_SHARE_IRQ static char *serial_name = "CPM UART driver"; -static char *serial_version = "0.01"; +static char *serial_version = "0.02"; static DECLARE_TASK_QUEUE(tq_serial); @@ -96,10 +103,16 @@ #define smc_scc_num hub6 #define SCC_NUM_BASE 2 +/* The index into the CPM registers for the first SCC in the table. +*/ +#define SCC_IDX_BASE 1 + static struct serial_state rs_table[] = { /* UART CLK PORT IRQ FLAGS NUM */ { 0, 0, PROFF_SMC1, CPMVEC_SMC1, 0, 0 }, /* SMC1 ttyS0 */ { 0, 0, PROFF_SMC2, CPMVEC_SMC2, 0, 1 }, /* SMC1 ttyS0 */ + { 0, 0, PROFF_SCC2, CPMVEC_SCC2, 0, 2 }, /* SCC2 ttyS2 */ + { 0, 0, PROFF_SCC3, CPMVEC_SCC3, 0, 3 }, /* SCC3 ttyS3 */ }; #define NR_PORTS (sizeof(rs_table)/sizeof(struct serial_state)) @@ -212,7 +225,7 @@ smcp->smc_smcm &= ~SMCM_TX; } else { - sccp = &cpmp->cp_scc[idx - SCC_NUM_BASE]; + sccp = &cpmp->cp_scc[idx - SCC_IDX_BASE]; sccp->scc_sccm &= ~UART_SCCM_TX; } restore_flags(flags); @@ -235,7 +248,7 @@ smcp->smc_smcm |= SMCM_TX; } else { - sccp = &cpmp->cp_scc[idx - SCC_NUM_BASE]; + sccp = &cpmp->cp_scc[idx - SCC_IDX_BASE]; sccp->scc_sccm |= UART_SCCM_TX; } restore_flags(flags); @@ -507,26 +520,33 @@ int idx; ser_info_t *info; volatile smc_t *smcp; + volatile scc_t *sccp; info = (ser_info_t *)dev_id; if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) { smcp = &cpmp->cp_smc[idx]; + events = smcp->smc_smce; + if (events & SMCM_RX) + receive_chars(info); + if (events & SMCM_TX) + transmit_chars(info); + smcp->smc_smce = events; } else { - panic("SCC UART Interrupt....not ready"); + sccp = &cpmp->cp_scc[idx - SCC_IDX_BASE]; + events = sccp->scc_scce; + if (events & SCCM_RX) + receive_chars(info); + if (events & SCCM_TX) + transmit_chars(info); + sccp->scc_scce = events; } - events = smcp->smc_smce; #ifdef SERIAL_DEBUG_INTR printk("rs_interrupt_single(%d, %x)...", info->state->smc_scc_num, events); #endif - if (events & SMCM_RX) - receive_chars(info); - if (events & SMCM_TX) - transmit_chars(info); - smcp->smc_smce = events; #ifdef modem_control check_modem_status(info); #endif @@ -610,6 +630,7 @@ volatile smc_t *smcp; volatile scc_t *sccp; volatile smc_uart_t *up; + volatile scc_uart_t *scup; save_flags(flags); cli(); @@ -662,13 +683,28 @@ * are coming. */ up = (smc_uart_t *)&cpmp->cp_dparam[state->port]; +#if 0 up->smc_mrblr = 1; /* receive buffer length */ up->smc_maxidl = 0; /* wait forever for next char */ +#else + up->smc_mrblr = RX_BUF_SIZE; + up->smc_maxidl = RX_BUF_SIZE; +#endif up->smc_brkcr = 1; /* number of break chars */ } else { - sccp = &cpmp->cp_scc[idx - SCC_NUM_BASE]; - sccp->scc_sccm |= UART_SCCM_RX; + sccp = &cpmp->cp_scc[idx - SCC_IDX_BASE]; + scup = (scc_uart_t *)&cpmp->cp_dparam[state->port]; +#if 0 + scup->scc_genscc.scc_mrblr = 1; /* receive buffer length */ + scup->scc_maxidl = 0; /* wait forever for next char */ +#else + scup->scc_genscc.scc_mrblr = RX_BUF_SIZE; + scup->scc_maxidl = RX_BUF_SIZE; +#endif + + sccp->scc_sccm |= (UART_SCCM_TX | UART_SCCM_RX); + sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT); } info->flags |= ASYNC_INITIALIZED; @@ -719,10 +755,10 @@ smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); } else { - sccp = &cpmp->cp_scc[idx - SCC_NUM_BASE]; - sccp->scc_sccm &= ~UART_SCCM_RX; + sccp = &cpmp->cp_scc[idx - SCC_IDX_BASE]; + sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX); + sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT); } - if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags); @@ -738,8 +774,8 @@ static void change_speed(ser_info_t *info) { int baud_rate; - unsigned cflag, cval, prev_mode; - int i, bits, idx; + unsigned cflag, cval, scval, prev_mode; + int i, bits, sbits, idx; unsigned long flags; volatile smc_t *smcp; volatile scc_t *sccp; @@ -754,6 +790,7 @@ * The value 'bits' counts this for us. */ cval = 0; + scval = 0; /* byte size and parity */ switch (cflag & CSIZE) { @@ -764,16 +801,22 @@ /* Never happens, but GCC is too dumb to figure it out */ default: bits = 8; break; } + sbits = bits - 5; + if (cflag & CSTOPB) { cval |= SMCMR_SL; /* Two stops */ + scval |= SCU_PMSR_SL; bits++; } if (cflag & PARENB) { cval |= SMCMR_PEN; + scval |= SCU_PMSR_PEN; bits++; } - if (!(cflag & PARODD)) + if (!(cflag & PARODD)) { cval |= SMCMR_PM_EVEN; + scval |= (SCU_PMSR_REVP | SCU_PMSR_TEVP); + } /* Determine divisor based on baud rate */ i = cflag & CBAUD; @@ -859,11 +902,11 @@ smcp->smc_smcmr |= (prev_mode & (SMCMR_REN | SMCMR_TEN)); } else { - sccp = &cpmp->cp_scc[idx - SCC_NUM_BASE]; - sccp->scc_sccm &= ~UART_SCCM_RX; + sccp = &cpmp->cp_scc[idx - SCC_IDX_BASE]; + sccp->scc_pmsr = (sbits << 12) | scval; } - mbx_cpm_setbrg(info->state->smc_scc_num, baud_rate); + m8xx_cpm_setbrg(info->state->smc_scc_num, baud_rate); restore_flags(flags); } @@ -1568,8 +1611,9 @@ smcp->smc_smcmr &= ~SMCMR_REN; } else { - sccp = &cpmp->cp_scc[idx - SCC_NUM_BASE]; + sccp = &cpmp->cp_scc[idx - SCC_IDX_BASE]; sccp->scc_sccm &= ~UART_SCCM_RX; + sccp->scc_gsmrl &= ~SCC_GSMRL_ENR; } /* * Before we drop DTR, make sure the UART transmitter @@ -2218,12 +2262,15 @@ struct serial_state * state; ser_info_t *info; uint mem_addr, dp_addr; - int i, j; + int i, j, idx; ushort chan; volatile cbd_t *bdp; volatile cpm8xx_t *cp; volatile smc_t *sp; volatile smc_uart_t *up; + volatile scc_t *scp; + volatile scc_uart_t *sup; + volatile immap_t *immap; init_bh(SERIAL_BH, do_serial_bh); #if 0 @@ -2289,6 +2336,7 @@ panic("Couldn't register callout driver\n"); cp = cpmp; /* Get pointer to Communication Processor */ + immap = (immap_t *)IMAP_ADDR; /* and to internal registers */ /* Configure SMCs Tx/Rx instead of port B parallel I/O. */ @@ -2296,10 +2344,41 @@ cp->cp_pbdir &= ~0x00000cc0; cp->cp_pbodr &= ~0x00000cc0; + /* Configure SCC2 and SCC3 instead of port A parallel I/O. + */ +#ifndef CONFIG_MBX + /* The "standard" configuration through the 860. + */ + immap->im_ioport.iop_papar |= 0x003c; + immap->im_ioport.iop_padir &= ~0x003c; + immap->im_ioport.iop_paodr &= ~0x003c; +#else + /* On the MBX, SCC3 is through Port D. + */ + immap->im_ioport.iop_papar |= 0x000c; /* SCC2 on port A */ + immap->im_ioport.iop_padir &= ~0x000c; + immap->im_ioport.iop_paodr &= ~0x000c; + + immap->im_ioport.iop_pdpar |= 0x0030; /* SCC3 on port D */ +#endif + + /* Since we don't yet do modem control, connect the port C pins + * as general purpose I/O. This will assert CTS and CD for the + * SCC ports. + */ + immap->im_ioport.iop_pcdir |= 0x03c6; + immap->im_ioport.iop_pcpar &= ~0x03c6; + /* Wire BRG1 to SMC1 and BRG2 to SMC2. */ cp->cp_simode = 0x10000000; + /* Connect SCC2 and SCC3 to NMSI. Connect BRG3 to SCC2 and + * BRG4 to SCC3. + */ + cp->cp_sicr &= ~0x00ffff00; + cp->cp_sicr |= 0x001b1200; + for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) { state->magic = SSTATE_MAGIC; state->line = i; @@ -2340,28 +2419,21 @@ info->state = state; state->info = (struct async_struct *)info; - /* Right now, assume we are using SMCs. - */ - sp = &cp->cp_smc[state->smc_scc_num]; - - up = (smc_uart_t *)&cp->cp_dparam[state->port]; - /* We need to allocate a transmit and receive buffer * descriptors from dual port ram, and a character * buffer area from host mem. */ - dp_addr = mbx_cpm_dpalloc(sizeof(cbd_t) * RX_NUM_FIFO); + dp_addr = m8xx_cpm_dpalloc(sizeof(cbd_t) * RX_NUM_FIFO); /* Allocate space for FIFOs in the host memory. */ - mem_addr = mbx_cpm_hostalloc(RX_NUM_FIFO * RX_BUF_SIZE); + mem_addr = m8xx_cpm_hostalloc(RX_NUM_FIFO * RX_BUF_SIZE); /* Set the physical address of the host memory * buffers in the buffer descriptors, and the * virtual address for us to work with. */ bdp = (cbd_t *)&cp->cp_dpmem[dp_addr]; - up->smc_rbase = dp_addr; info->rx_cur = info->rx_bd_base = (cbd_t *)bdp; for (j=0; j<(RX_NUM_FIFO-1); j++) { @@ -2373,18 +2445,28 @@ bdp->cbd_bufaddr = __pa(mem_addr); bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT; - dp_addr = mbx_cpm_dpalloc(sizeof(cbd_t) * TX_NUM_FIFO); + if ((idx = state->smc_scc_num) < SCC_NUM_BASE) { + sp = &cp->cp_smc[idx]; + up = (smc_uart_t *)&cp->cp_dparam[state->port]; + up->smc_rbase = dp_addr; + } + else { + scp = &cp->cp_scc[idx - SCC_IDX_BASE]; + sup = (scc_uart_t *)&cp->cp_dparam[state->port]; + sup->scc_genscc.scc_rbase = dp_addr; + } + + dp_addr = m8xx_cpm_dpalloc(sizeof(cbd_t) * TX_NUM_FIFO); /* Allocate space for FIFOs in the host memory. */ - mem_addr = mbx_cpm_hostalloc(TX_NUM_FIFO * TX_BUF_SIZE); + mem_addr = m8xx_cpm_hostalloc(TX_NUM_FIFO * TX_BUF_SIZE); /* Set the physical address of the host memory * buffers in the buffer descriptors, and the * virtual address for us to work with. */ bdp = (cbd_t *)&cp->cp_dpmem[dp_addr]; - up->smc_tbase = dp_addr; info->tx_cur = info->tx_bd_base = (cbd_t *)bdp; for (j=0; j<(TX_NUM_FIFO-1); j++) { @@ -2396,39 +2478,104 @@ bdp->cbd_bufaddr = __pa(mem_addr); bdp->cbd_sc = (BD_SC_WRAP | BD_SC_INTRPT); - /* Set up the uart parameters in the parameter ram. - */ - up->smc_rfcr = SMC_EB; - up->smc_tfcr = SMC_EB; + if (idx < SCC_NUM_BASE) { + up->smc_tbase = dp_addr; - /* Set this to 1 for now, so we get single character - * interrupts. Using idle charater time requires - * some additional tuning. - */ - up->smc_mrblr = 1; /* receive buffer length */ - up->smc_maxidl = 0; /* wait forever for next char */ - up->smc_brkcr = 1; /* number of break chars */ + /* Set up the uart parameters in the + * parameter ram. + */ + up->smc_rfcr = SMC_EB; + up->smc_tfcr = SMC_EB; - /* Send the CPM an initialize command. - */ - if (state->smc_scc_num == 0) - chan = CPM_CR_CH_SMC1; - else - chan = CPM_CR_CH_SMC2; - cp->cp_cpcr = mk_cr_cmd(chan, + /* Set this to 1 for now, so we get single + * character interrupts. Using idle charater + * time requires some additional tuning. + */ + up->smc_mrblr = 1; + up->smc_maxidl = 0; + up->smc_brkcr = 1; + + /* Send the CPM an initialize command. + */ + if (state->smc_scc_num == 0) + chan = CPM_CR_CH_SMC1; + else + chan = CPM_CR_CH_SMC2; + + cp->cp_cpcr = mk_cr_cmd(chan, CPM_CR_INIT_TRX) | CPM_CR_FLG; - while (cp->cp_cpcr & CPM_CR_FLG); + while (cp->cp_cpcr & CPM_CR_FLG); - /* Set UART mode, 8 bit, no parity, one stop. - * Enable receive and transmit. - */ - sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART; + /* Set UART mode, 8 bit, no parity, one stop. + * Enable receive and transmit. + */ + sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART; - /* Disable all interrupts and clear all pending - * events. - */ - sp->smc_smcm = 0; - sp->smc_smce = 0xff; + /* Disable all interrupts and clear all pending + * events. + */ + sp->smc_smcm = 0; + sp->smc_smce = 0xff; + } + else { + sup->scc_genscc.scc_tbase = dp_addr; + + /* Set up the uart parameters in the + * parameter ram. + */ + sup->scc_genscc.scc_rfcr = SMC_EB; + sup->scc_genscc.scc_tfcr = SMC_EB; + + /* Set this to 1 for now, so we get single + * character interrupts. Using idle charater + * time requires some additional tuning. + */ + sup->scc_genscc.scc_mrblr = 1; + sup->scc_maxidl = 0; + sup->scc_brkcr = 1; + sup->scc_parec = 0; + sup->scc_frmec = 0; + sup->scc_nosec = 0; + sup->scc_brkec = 0; + sup->scc_uaddr1 = 0; + sup->scc_uaddr2 = 0; + sup->scc_toseq = 0; + sup->scc_char1 = 0x8000; + sup->scc_char2 = 0x8000; + sup->scc_char3 = 0x8000; + sup->scc_char4 = 0x8000; + sup->scc_char5 = 0x8000; + sup->scc_char6 = 0x8000; + sup->scc_char7 = 0x8000; + sup->scc_char8 = 0x8000; + sup->scc_rccm = 0xc0ff; + + /* Send the CPM an initialize command. + */ + if (state->smc_scc_num == 2) + chan = CPM_CR_CH_SCC2; + else + chan = CPM_CR_CH_SCC3; + + cp->cp_cpcr = mk_cr_cmd(chan, + CPM_CR_INIT_TRX) | CPM_CR_FLG; + while (cp->cp_cpcr & CPM_CR_FLG); + + /* Set UART mode, 8 bit, no parity, one stop. + * Enable receive and transmit. + */ + scp->scc_gsmrh = 0; + scp->scc_gsmrl = + (SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16); + + /* Disable all interrupts and clear all pending + * events. + */ + scp->scc_sccm = 0; + scp->scc_scce = 0xffff; + scp->scc_dsr = 0x7e7e; + scp->scc_pmsr = 0x3000; + } /* Install interrupt handler. */ @@ -2436,7 +2583,7 @@ /* Set up the baud rate generator. */ - mbx_cpm_setbrg(state->smc_scc_num, 9600); + m8xx_cpm_setbrg(state->smc_scc_num, 9600); /* If the port is the console, enable Rx and Tx. */ @@ -2479,11 +2626,11 @@ /* Allocate space for two buffer descriptors in the DP ram. */ - dp_addr = mbx_cpm_dpalloc(sizeof(cbd_t) * 2); + dp_addr = m8xx_cpm_dpalloc(sizeof(cbd_t) * 2); /* Allocate space for two 2 byte FIFOs in the host memory. */ - mem_addr = mbx_cpm_hostalloc(4); + mem_addr = m8xx_cpm_hostalloc(4); /* Set the physical address of the host memory buffers in * the buffer descriptors. @@ -2526,7 +2673,7 @@ /* Set up the baud rate generator. */ - mbx_cpm_setbrg(ser->smc_scc_num, 9600); + m8xx_cpm_setbrg(ser->smc_scc_num, 9600); /* And finally, enable Rx and Tx. */ diff -u --recursive --new-file v2.1.123/linux/arch/ppc/Makefile linux/arch/ppc/Makefile --- v2.1.123/linux/arch/ppc/Makefile Thu Aug 6 14:06:29 1998 +++ linux/arch/ppc/Makefile Wed Sep 30 10:14:16 1998 @@ -14,10 +14,7 @@ KERNELLOAD =0xc0000000 -# PowerPC (cross) tools -ifneq ($(shell uname -m),ppc) -CROSS_COMPILE = ppc-linux-elf- -else +ifeq ($(shell uname -m),ppc) CHECKS = checks endif diff -u --recursive --new-file v2.1.123/linux/arch/ppc/amiga/amiints.c linux/arch/ppc/amiga/amiints.c --- v2.1.123/linux/arch/ppc/amiga/amiints.c Thu Aug 6 14:06:29 1998 +++ linux/arch/ppc/amiga/amiints.c Thu Oct 1 09:55:13 1998 @@ -2,4 +2,544 @@ #define amiga_request_irq request_irq #define amiga_free_irq free_irq -#include "../../m68k/amiga/amiints.c" +/* + * linux/arch/m68k/amiga/amiints.c -- Amiga Linux interrupt handling code + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + * + * 11/07/96: rewritten interrupt handling, irq lists are exists now only for + * this sources where it makes sense (VERTB/PORTS/EXTER) and you must + * be careful that dev_id for this sources is unique since this the + * only possibility to distinguish between different handlers for + * free_irq. irq lists also have different irq flags: + * - IRQ_FLG_FAST: handler is inserted at top of list (after other + * fast handlers) + * - IRQ_FLG_SLOW: handler is inserted at bottom of list and before + * they're executed irq level is set to the previous + * one, but handlers don't need to be reentrant, if + * reentrance occured, slow handlers will be just + * called again. + * The whole interrupt handling for CIAs is moved to cia.c + * /Roman Zippel + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_APUS +#include +#endif + +extern int cia_request_irq(struct ciabase *base,int irq, + void (*handler)(int, void *, struct pt_regs *), + unsigned long flags, const char *devname, void *dev_id); +extern void cia_free_irq(struct ciabase *base, unsigned int irq, void *dev_id); +extern void cia_init_IRQ(struct ciabase *base); +extern int cia_get_irq_list(struct ciabase *base, char *buf); + +/* irq node variables for amiga interrupt sources */ +static irq_node_t *ami_irq_list[AMI_STD_IRQS]; + +unsigned short ami_intena_vals[AMI_STD_IRQS] = { + IF_VERTB, IF_COPER, IF_AUD0, IF_AUD1, IF_AUD2, IF_AUD3, IF_BLIT, + IF_DSKSYN, IF_DSKBLK, IF_RBF, IF_TBE, IF_SOFT, IF_PORTS, IF_EXTER +}; +static const unsigned char ami_servers[AMI_STD_IRQS] = { + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 +}; + +static short ami_ablecount[AMI_IRQS]; + +static void ami_badint(int irq, void *dev_id, struct pt_regs *fp) +{ + num_spurious += 1; +} + +/* + * void amiga_init_IRQ(void) + * + * Parameters: None + * + * Returns: Nothing + * + * This function should be called during kernel startup to initialize + * the amiga IRQ handling routines. + */ + +__initfunc(void amiga_init_IRQ(void)) +{ + int i; + + /* initialize handlers */ + for (i = 0; i < AMI_STD_IRQS; i++) { + if (ami_servers[i]) { + ami_irq_list[i] = NULL; + } else { + ami_irq_list[i] = new_irq_node(); + ami_irq_list[i]->handler = ami_badint; + ami_irq_list[i]->flags = IRQ_FLG_STD; + ami_irq_list[i]->dev_id = NULL; + ami_irq_list[i]->devname = NULL; + ami_irq_list[i]->next = NULL; + } + } + for (i = 0; i < AMI_IRQS; i++) + ami_ablecount[i] = 0; + + /* turn off PCMCIA interrupts */ + if (AMIGAHW_PRESENT(PCMCIA)) + pcmcia_disable_irq(); + + /* turn off all interrupts... */ + custom.intena = 0x7fff; + custom.intreq = 0x7fff; + +#ifdef CONFIG_APUS + APUS_WRITE(APUS_REG_INT, REGINT_INTMASTER | REGINT_ENABLEIPL); + APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT); + APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET | IPLEMU_IPLMASK); +#endif + /* ... and enable the master interrupt bit */ + custom.intena = IF_SETCLR | IF_INTEN; + + cia_init_IRQ(&ciaa_base); + cia_init_IRQ(&ciab_base); +} + +static inline void amiga_insert_irq(irq_node_t **list, irq_node_t *node) +{ + unsigned long flags; + irq_node_t *cur; + + if (!node->dev_id) + printk("%s: Warning: dev_id of %s is zero\n", + __FUNCTION__, node->devname); + + save_flags(flags); + cli(); + + cur = *list; + + if (node->flags & IRQ_FLG_FAST) { + node->flags &= ~IRQ_FLG_SLOW; + while (cur && cur->flags & IRQ_FLG_FAST) { + list = &cur->next; + cur = cur->next; + } + } else if (node->flags & IRQ_FLG_SLOW) { + while (cur) { + list = &cur->next; + cur = cur->next; + } + } else { + while (cur && !(cur->flags & IRQ_FLG_SLOW)) { + list = &cur->next; + cur = cur->next; + } + } + + node->next = cur; + *list = node; + + restore_flags(flags); +} + +static inline void amiga_delete_irq(irq_node_t **list, void *dev_id) +{ + unsigned long flags; + irq_node_t *node; + + save_flags(flags); + cli(); + + for (node = *list; node; list = &node->next, node = *list) { + if (node->dev_id == dev_id) { + *list = node->next; + /* Mark it as free. */ + node->handler = NULL; + restore_flags(flags); + return; + } + } + restore_flags(flags); + printk ("%s: tried to remove invalid irq\n", __FUNCTION__); +} + +/* + * amiga_request_irq : add an interrupt service routine for a particular + * machine specific interrupt source. + * If the addition was successful, it returns 0. + */ + +int amiga_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), + unsigned long flags, const char *devname, void *dev_id) +{ + irq_node_t *node; + + if (irq >= AMI_IRQS) { + printk ("%s: Unknown IRQ %d from %s\n", __FUNCTION__, irq, devname); + return -ENXIO; + } + + if (irq >= IRQ_AMIGA_AUTO) + return sys_request_irq(irq - IRQ_AMIGA_AUTO, handler, + flags, devname, dev_id); + + if (irq >= IRQ_AMIGA_CIAB) + return cia_request_irq(&ciab_base, irq - IRQ_AMIGA_CIAB, + handler, flags, devname, dev_id); + + if (irq >= IRQ_AMIGA_CIAA) + return cia_request_irq(&ciaa_base, irq - IRQ_AMIGA_CIAA, + handler, flags, devname, dev_id); + + if (ami_servers[irq]) { + if (!(node = new_irq_node())) + return -ENOMEM; + node->handler = handler; + node->flags = flags; + node->dev_id = dev_id; + node->devname = devname; + node->next = NULL; + amiga_insert_irq(&ami_irq_list[irq], node); + } else { + if (!(ami_irq_list[irq]->flags & IRQ_FLG_STD)) { + if (ami_irq_list[irq]->flags & IRQ_FLG_LOCK) { + printk("%s: IRQ %d from %s is not replaceable\n", + __FUNCTION__, irq, ami_irq_list[irq]->devname); + return -EBUSY; + } + if (!(flags & IRQ_FLG_REPLACE)) { + printk("%s: %s can't replace IRQ %d from %s\n", + __FUNCTION__, devname, irq, ami_irq_list[irq]->devname); + return -EBUSY; + } + } + ami_irq_list[irq]->handler = handler; + ami_irq_list[irq]->flags = flags; + ami_irq_list[irq]->dev_id = dev_id; + ami_irq_list[irq]->devname = devname; + } + + /* enable the interrupt */ + if (irq < IRQ_AMIGA_PORTS && !ami_ablecount[irq]) + custom.intena = IF_SETCLR | ami_intena_vals[irq]; + + return 0; +} + +void amiga_free_irq(unsigned int irq, void *dev_id) +{ + if (irq >= AMI_IRQS) { + printk ("%s: Unknown IRQ %d\n", __FUNCTION__, irq); + return; + } + + if (irq >= IRQ_AMIGA_AUTO) + sys_free_irq(irq - IRQ_AMIGA_AUTO, dev_id); + + if (irq >= IRQ_AMIGA_CIAB) { + cia_free_irq(&ciab_base, irq - IRQ_AMIGA_CIAB, dev_id); + return; + } + + if (irq >= IRQ_AMIGA_CIAA) { + cia_free_irq(&ciaa_base, irq - IRQ_AMIGA_CIAA, dev_id); + return; + } + + if (ami_servers[irq]) { + amiga_delete_irq(&ami_irq_list[irq], dev_id); + /* if server list empty, disable the interrupt */ + if (!ami_irq_list[irq] && irq < IRQ_AMIGA_PORTS) + custom.intena = ami_intena_vals[irq]; + } else { + if (ami_irq_list[irq]->dev_id != dev_id) + printk("%s: removing probably wrong IRQ %d from %s\n", + __FUNCTION__, irq, ami_irq_list[irq]->devname); + ami_irq_list[irq]->handler = ami_badint; + ami_irq_list[irq]->flags = IRQ_FLG_STD; + ami_irq_list[irq]->dev_id = NULL; + ami_irq_list[irq]->devname = NULL; + custom.intena = ami_intena_vals[irq]; + } +} + +/* + * Enable/disable a particular machine specific interrupt source. + * Note that this may affect other interrupts in case of a shared interrupt. + * This function should only be called for a _very_ short time to change some + * internal data, that may not be changed by the interrupt at the same time. + * ami_(enable|disable)_irq calls may also be nested. + */ + +void amiga_enable_irq(unsigned int irq) +{ + if (irq >= AMI_IRQS) { + printk("%s: Unknown IRQ %d\n", __FUNCTION__, irq); + return; + } + + if (--ami_ablecount[irq]) + return; + + /* No action for auto-vector interrupts */ + if (irq >= IRQ_AMIGA_AUTO){ + printk("%s: Trying to enable auto-vector IRQ %i\n", + __FUNCTION__, irq - IRQ_AMIGA_AUTO); + return; + } + + if (irq >= IRQ_AMIGA_CIAB) { + cia_able_irq(&ciab_base, CIA_ICR_SETCLR | + (1 << (irq - IRQ_AMIGA_CIAB))); + return; + } + + if (irq >= IRQ_AMIGA_CIAA) { + cia_able_irq(&ciaa_base, CIA_ICR_SETCLR | + (1 << (irq - IRQ_AMIGA_CIAA))); + return; + } + + /* enable the interrupt */ + custom.intena = IF_SETCLR | ami_intena_vals[irq]; +} + +void amiga_disable_irq(unsigned int irq) +{ + if (irq >= AMI_IRQS) { + printk("%s: Unknown IRQ %d\n", __FUNCTION__, irq); + return; + } + + if (ami_ablecount[irq]++) + return; + + /* No action for auto-vector interrupts */ + if (irq >= IRQ_AMIGA_AUTO) { + printk("%s: Trying to disable auto-vector IRQ %i\n", + __FUNCTION__, irq - IRQ_AMIGA_AUTO); + return; + } + + if (irq >= IRQ_AMIGA_CIAB) { + cia_able_irq(&ciab_base, 1 << (irq - IRQ_AMIGA_CIAB)); + return; + } + + if (irq >= IRQ_AMIGA_CIAA) { + cia_able_irq(&ciaa_base, 1 << (irq - IRQ_AMIGA_CIAA)); + return; + } + + /* disable the interrupt */ + custom.intena = ami_intena_vals[irq]; +} + +inline void amiga_do_irq(int irq, struct pt_regs *fp) +{ + kstat.irqs[0][SYS_IRQS + irq]++; + ami_irq_list[irq]->handler(irq, ami_irq_list[irq]->dev_id, fp); +} + +void amiga_do_irq_list(int irq, struct pt_regs *fp, struct irq_server *server) +{ + irq_node_t *node, *slow_nodes; + unsigned short flags; + + kstat.irqs[0][SYS_IRQS + irq]++; + if (server->count++) + server->reentrance = 1; + /* serve first fast and normal handlers */ + for (node = ami_irq_list[irq]; + node && (!(node->flags & IRQ_FLG_SLOW)); + node = node->next) + node->handler(irq, node->dev_id, fp); + custom.intreq = ami_intena_vals[irq]; + if (!node) { + server->count--; + return; + } +#ifdef CONFIG_APUS + APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET | IPLEMU_DISABLEINT); + APUS_WRITE(APUS_IPL_EMU, IPLEMU_IPLMASK); + APUS_WRITE(APUS_IPL_EMU, (IPLEMU_SETRESET + | (~(fp->mq) & IPLEMU_IPLMASK))); + APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT); +#else + save_flags(flags); + restore_flags((flags & ~0x0700) | (fp->sr & 0x0700)); +#endif + /* if slow handlers exists, serve them now */ + slow_nodes = node; + for (;;) { + for (; node; node = node->next) + node->handler(irq, node->dev_id, fp); + /* if reentrance occured, serve slow handlers again */ + custom.intena = ami_intena_vals[irq]; + if (!server->reentrance) { + server->count--; + custom.intena = IF_SETCLR | ami_intena_vals[irq]; + return; + } + server->reentrance = 0; + custom.intena = IF_SETCLR | ami_intena_vals[irq]; + node = slow_nodes; + } +} + +/* + * The builtin Amiga hardware interrupt handlers. + */ + +static void ami_int1(int irq, void *dev_id, struct pt_regs *fp) +{ + unsigned short ints = custom.intreqr & custom.intenar; + + /* if serial transmit buffer empty, interrupt */ + if (ints & IF_TBE) { + custom.intreq = IF_TBE; + amiga_do_irq(IRQ_AMIGA_TBE, fp); + } + + /* if floppy disk transfer complete, interrupt */ + if (ints & IF_DSKBLK) { + custom.intreq = IF_DSKBLK; + amiga_do_irq(IRQ_AMIGA_DSKBLK, fp); + } + + /* if software interrupt set, interrupt */ + if (ints & IF_SOFT) { + custom.intreq = IF_SOFT; + amiga_do_irq(IRQ_AMIGA_SOFT, fp); + } +} + +static void ami_int3(int irq, void *dev_id, struct pt_regs *fp) +{ + unsigned short ints = custom.intreqr & custom.intenar; + static struct irq_server server = {0, 0}; + + /* if a blitter interrupt */ + if (ints & IF_BLIT) { + custom.intreq = IF_BLIT; + amiga_do_irq(IRQ_AMIGA_BLIT, fp); + } + + /* if a copper interrupt */ + if (ints & IF_COPER) { + custom.intreq = IF_COPER; + amiga_do_irq(IRQ_AMIGA_COPPER, fp); + } + + /* if a vertical blank interrupt */ + if (ints & IF_VERTB) + amiga_do_irq_list(IRQ_AMIGA_VERTB, fp, &server); +} + +static void ami_int4(int irq, void *dev_id, struct pt_regs *fp) +{ + unsigned short ints = custom.intreqr & custom.intenar; + + /* if audio 0 interrupt */ + if (ints & IF_AUD0) { + custom.intreq = IF_AUD0; + amiga_do_irq(IRQ_AMIGA_AUD0, fp); + } + + /* if audio 1 interrupt */ + if (ints & IF_AUD1) { + custom.intreq = IF_AUD1; + amiga_do_irq(IRQ_AMIGA_AUD1, fp); + } + + /* if audio 2 interrupt */ + if (ints & IF_AUD2) { + custom.intreq = IF_AUD2; + amiga_do_irq(IRQ_AMIGA_AUD2, fp); + } + + /* if audio 3 interrupt */ + if (ints & IF_AUD3) { + custom.intreq = IF_AUD3; + amiga_do_irq(IRQ_AMIGA_AUD3, fp); + } +} + +static void ami_int5(int irq, void *dev_id, struct pt_regs *fp) +{ + unsigned short ints = custom.intreqr & custom.intenar; + + /* if serial receive buffer full interrupt */ + if (ints & IF_RBF) { + /* acknowledge of IF_RBF must be done by the serial interrupt */ + amiga_do_irq(IRQ_AMIGA_RBF, fp); + } + + /* if a disk sync interrupt */ + if (ints & IF_DSKSYN) { + custom.intreq = IF_DSKSYN; + amiga_do_irq(IRQ_AMIGA_DSKSYN, fp); + } +} + +static void ami_int7(int irq, void *dev_id, struct pt_regs *fp) +{ + panic ("level 7 interrupt received\n"); +} + +void (*amiga_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = { + ami_badint, ami_int1, ami_badint, ami_int3, + ami_int4, ami_int5, ami_badint, ami_int7 +}; + +int amiga_get_irq_list(char *buf) +{ + int i, len = 0; + irq_node_t *node; + + for (i = 0; i < AMI_STD_IRQS; i++) { + if (!(node = ami_irq_list[i])) + continue; + if (node->flags & IRQ_FLG_STD) + continue; + len += sprintf(buf+len, "ami %2d: %10u ", i, + kstat.irqs[0][SYS_IRQS + i]); + do { + if (ami_servers[i]) { + if (node->flags & IRQ_FLG_FAST) + len += sprintf(buf+len, "F "); + else if (node->flags & IRQ_FLG_SLOW) + len += sprintf(buf+len, "S "); + else + len += sprintf(buf+len, " "); + } else { + if (node->flags & IRQ_FLG_LOCK) + len += sprintf(buf+len, "L "); + else + len += sprintf(buf+len, " "); + } + len += sprintf(buf+len, "%s\n", node->devname); + if ((node = node->next)) + len += sprintf(buf+len, " "); + } while (node); + } + + len += cia_get_irq_list(&ciaa_base, buf+len); + len += cia_get_irq_list(&ciab_base, buf+len); + return len; +} diff -u --recursive --new-file v2.1.123/linux/arch/ppc/amiga/config.c linux/arch/ppc/amiga/config.c --- v2.1.123/linux/arch/ppc/amiga/config.c Thu Aug 6 14:06:29 1998 +++ linux/arch/ppc/amiga/config.c Wed Sep 30 10:14:16 1998 @@ -2,6 +2,928 @@ #define m68k_num_memory num_memory #define m68k_memory memory +#include + +/* machine dependent "kbd-reset" setup function */ +void (*kbd_reset_setup) (char *, int) __initdata = 0; + #include -#include "../../m68k/amiga/config.c" +/* + * linux/arch/m68k/amiga/config.c + * + * Copyright (C) 1993 Hamish Macdonald + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ + +/* + * Miscellaneous Amiga stuff + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +unsigned long amiga_model; +unsigned long amiga_eclock; +unsigned long amiga_masterclock; +unsigned long amiga_colorclock; +unsigned long amiga_chipset; +unsigned char amiga_vblank; +unsigned char amiga_psfreq; +struct amiga_hw_present amiga_hw_present; + +static const char *amiga_models[] = { + "A500", "A500+", "A600", "A1000", "A1200", "A2000", "A2500", "A3000", + "A3000T", "A3000+", "A4000", "A4000T", "CDTV", "CD32", "Draco" +}; + +extern char m68k_debug_device[]; + +static void amiga_sched_init(void (*handler)(int, void *, struct pt_regs *)); +/* amiga specific keyboard functions */ +extern int amiga_keyb_init(void); +extern int amiga_kbdrate (struct kbd_repeat *); +extern void amiga_kbd_reset_setup(char*, int); +/* amiga specific irq functions */ +extern void amiga_init_IRQ (void); +extern void (*amiga_default_handler[]) (int, void *, struct pt_regs *); +extern int amiga_request_irq (unsigned int irq, + void (*handler)(int, void *, struct pt_regs *), + unsigned long flags, const char *devname, + void *dev_id); +extern void amiga_free_irq (unsigned int irq, void *dev_id); +extern void amiga_enable_irq (unsigned int); +extern void amiga_disable_irq (unsigned int); +static void amiga_get_model(char *model); +static int amiga_get_hardware_list(char *buffer); +extern int amiga_get_irq_list (char *); +/* amiga specific timer functions */ +static unsigned long amiga_gettimeoffset (void); +static void a3000_gettod (int *, int *, int *, int *, int *, int *); +static void a2000_gettod (int *, int *, int *, int *, int *, int *); +static int amiga_hwclk (int, struct hwclk_time *); +static int amiga_set_clock_mmss (unsigned long); +extern void amiga_mksound( unsigned int count, unsigned int ticks ); +#ifdef CONFIG_AMIGA_FLOPPY +extern void amiga_floppy_setup(char *, int *); +#endif +static void amiga_reset (void); +static int amiga_wait_key (struct console *co); +extern void amiga_init_sound(void); +static void amiga_savekmsg_init(void); +static void amiga_mem_console_write(struct console *co, const char *b, + unsigned int count); +void amiga_serial_console_write(struct console *co, const char *s, + unsigned int count); +static void amiga_debug_init(void); +#ifdef CONFIG_HEARTBEAT +static void amiga_heartbeat(int on); +#endif + +static struct console amiga_console_driver = { + "debug", + NULL, /* write */ + NULL, /* read */ + NULL, /* device */ + amiga_wait_key, /* wait_key */ + NULL, /* unblank */ + NULL, /* setup */ + CON_PRINTBUFFER, + -1, + 0, + NULL +}; + +#ifdef CONFIG_MAGIC_SYSRQ +static char amiga_sysrq_xlate[128] = + "\0001234567890-=\\\000\000" /* 0x00 - 0x0f */ + "qwertyuiop[]\000123" /* 0x10 - 0x1f */ + "asdfghjkl;'\000\000456" /* 0x20 - 0x2f */ + "\000zxcvbnm,./\000+789" /* 0x30 - 0x3f */ + " \177\t\r\r\000\177\000\000\000-\000\000\000\000\000" /* 0x40 - 0x4f */ + "\000\201\202\203\204\205\206\207\210\211()/*+\000" /* 0x50 - 0x5f */ + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" /* 0x60 - 0x6f */ + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"; /* 0x70 - 0x7f */ +#endif + +extern void (*kd_mksound)(unsigned int, unsigned int); + + /* + * Parse an Amiga-specific record in the bootinfo + */ + +int amiga_parse_bootinfo(const struct bi_record *record) +{ + int unknown = 0; + const unsigned long *data = record->data; + + switch (record->tag) { + case BI_AMIGA_MODEL: + amiga_model = *data; + break; + + case BI_AMIGA_ECLOCK: + amiga_eclock = *data; + break; + + case BI_AMIGA_CHIPSET: + amiga_chipset = *data; + break; + + case BI_AMIGA_CHIP_SIZE: + amiga_chip_size = *(const int *)data; + break; + + case BI_AMIGA_VBLANK: + amiga_vblank = *(const unsigned char *)data; + break; + + case BI_AMIGA_PSFREQ: + amiga_psfreq = *(const unsigned char *)data; + break; + + case BI_AMIGA_AUTOCON: + if (zorro_num_autocon < ZORRO_NUM_AUTO) + memcpy(&zorro_autocon[zorro_num_autocon++], + (const struct ConfigDev *)data, + sizeof(struct ConfigDev)); + else + printk("amiga_parse_bootinfo: too many AutoConfig devices\n"); + break; + + case BI_AMIGA_SERPER: + /* serial port period: ignored here */ + break; + + default: + unknown = 1; + } + return(unknown); +} + + /* + * Identify builtin hardware + */ + +__initfunc(static void amiga_identify(void)) +{ + /* Fill in some default values, if necessary */ + if (amiga_eclock == 0) + amiga_eclock = 709379; + + memset(&amiga_hw_present, 0, sizeof(amiga_hw_present)); + + printk("Amiga hardware found: "); + if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO) + printk("[%s] ", amiga_models[amiga_model-AMI_500]); + + switch(amiga_model) { + case AMI_UNKNOWN: + goto Generic; + + case AMI_600: + case AMI_1200: + AMIGAHW_SET(A1200_IDE); + AMIGAHW_SET(PCMCIA); + case AMI_500: + case AMI_500PLUS: + case AMI_1000: + case AMI_2000: + case AMI_2500: + AMIGAHW_SET(A2000_CLK); /* Is this correct for all models? */ + goto Generic; + + case AMI_3000: + case AMI_3000T: + AMIGAHW_SET(AMBER_FF); + AMIGAHW_SET(MAGIC_REKICK); + /* fall through */ + case AMI_3000PLUS: + AMIGAHW_SET(A3000_SCSI); + AMIGAHW_SET(A3000_CLK); + AMIGAHW_SET(ZORRO3); + goto Generic; + + case AMI_4000T: + AMIGAHW_SET(A4000_SCSI); + /* fall through */ + case AMI_4000: + AMIGAHW_SET(A4000_IDE); + AMIGAHW_SET(A3000_CLK); + AMIGAHW_SET(ZORRO3); + goto Generic; + + case AMI_CDTV: + case AMI_CD32: + AMIGAHW_SET(CD_ROM); + AMIGAHW_SET(A2000_CLK); /* Is this correct? */ + goto Generic; + + Generic: + AMIGAHW_SET(AMI_VIDEO); + AMIGAHW_SET(AMI_BLITTER); + AMIGAHW_SET(AMI_AUDIO); + AMIGAHW_SET(AMI_FLOPPY); + AMIGAHW_SET(AMI_KEYBOARD); + AMIGAHW_SET(AMI_MOUSE); + AMIGAHW_SET(AMI_SERIAL); + AMIGAHW_SET(AMI_PARALLEL); + AMIGAHW_SET(CHIP_RAM); + AMIGAHW_SET(PAULA); + + switch(amiga_chipset) { + case CS_OCS: + case CS_ECS: + case CS_AGA: + switch (custom.deniseid & 0xf) { + case 0x0c: + AMIGAHW_SET(DENISE_HR); + break; + case 0x08: + AMIGAHW_SET(LISA); + break; + } + break; + default: + AMIGAHW_SET(DENISE); + break; + } + switch ((custom.vposr>>8) & 0x7f) { + case 0x00: + AMIGAHW_SET(AGNUS_PAL); + break; + case 0x10: + AMIGAHW_SET(AGNUS_NTSC); + break; + case 0x20: + case 0x21: + AMIGAHW_SET(AGNUS_HR_PAL); + break; + case 0x30: + case 0x31: + AMIGAHW_SET(AGNUS_HR_NTSC); + break; + case 0x22: + case 0x23: + AMIGAHW_SET(ALICE_PAL); + break; + case 0x32: + case 0x33: + AMIGAHW_SET(ALICE_NTSC); + break; + } + AMIGAHW_SET(ZORRO); + break; + + case AMI_DRACO: + panic("No support for Draco yet"); + + default: + panic("Unknown Amiga Model"); + } + +#define AMIGAHW_ANNOUNCE(name, str) \ + if (AMIGAHW_PRESENT(name)) \ + printk(str) + + AMIGAHW_ANNOUNCE(AMI_VIDEO, "VIDEO "); + AMIGAHW_ANNOUNCE(AMI_BLITTER, "BLITTER "); + AMIGAHW_ANNOUNCE(AMBER_FF, "AMBER_FF "); + AMIGAHW_ANNOUNCE(AMI_AUDIO, "AUDIO "); + AMIGAHW_ANNOUNCE(AMI_FLOPPY, "FLOPPY "); + AMIGAHW_ANNOUNCE(A3000_SCSI, "A3000_SCSI "); + AMIGAHW_ANNOUNCE(A4000_SCSI, "A4000_SCSI "); + AMIGAHW_ANNOUNCE(A1200_IDE, "A1200_IDE "); + AMIGAHW_ANNOUNCE(A4000_IDE, "A4000_IDE "); + AMIGAHW_ANNOUNCE(CD_ROM, "CD_ROM "); + AMIGAHW_ANNOUNCE(AMI_KEYBOARD, "KEYBOARD "); + AMIGAHW_ANNOUNCE(AMI_MOUSE, "MOUSE "); + AMIGAHW_ANNOUNCE(AMI_SERIAL, "SERIAL "); + AMIGAHW_ANNOUNCE(AMI_PARALLEL, "PARALLEL "); + AMIGAHW_ANNOUNCE(A2000_CLK, "A2000_CLK "); + AMIGAHW_ANNOUNCE(A3000_CLK, "A3000_CLK "); + AMIGAHW_ANNOUNCE(CHIP_RAM, "CHIP_RAM "); + AMIGAHW_ANNOUNCE(PAULA, "PAULA "); + AMIGAHW_ANNOUNCE(DENISE, "DENISE "); + AMIGAHW_ANNOUNCE(DENISE_HR, "DENISE_HR "); + AMIGAHW_ANNOUNCE(LISA, "LISA "); + AMIGAHW_ANNOUNCE(AGNUS_PAL, "AGNUS_PAL "); + AMIGAHW_ANNOUNCE(AGNUS_NTSC, "AGNUS_NTSC "); + AMIGAHW_ANNOUNCE(AGNUS_HR_PAL, "AGNUS_HR_PAL "); + AMIGAHW_ANNOUNCE(AGNUS_HR_NTSC, "AGNUS_HR_NTSC "); + AMIGAHW_ANNOUNCE(ALICE_PAL, "ALICE_PAL "); + AMIGAHW_ANNOUNCE(ALICE_NTSC, "ALICE_NTSC "); + AMIGAHW_ANNOUNCE(MAGIC_REKICK, "MAGIC_REKICK "); + AMIGAHW_ANNOUNCE(PCMCIA, "PCMCIA "); + if (AMIGAHW_PRESENT(ZORRO)) + printk("ZORRO%s ", AMIGAHW_PRESENT(ZORRO3) ? "3" : ""); + printk("\n"); + +#undef AMIGAHW_ANNOUNCE +} + + /* + * Setup the Amiga configuration info + */ + +__initfunc(void config_amiga(void)) +{ + amiga_debug_init(); + amiga_identify(); + + mach_sched_init = amiga_sched_init; + mach_keyb_init = amiga_keyb_init; + mach_kbdrate = amiga_kbdrate; + kbd_reset_setup = amiga_kbd_reset_setup; + mach_init_IRQ = amiga_init_IRQ; + mach_default_handler = &amiga_default_handler; +#ifndef CONFIG_APUS + mach_request_irq = amiga_request_irq; + mach_free_irq = amiga_free_irq; + enable_irq = amiga_enable_irq; + disable_irq = amiga_disable_irq; +#endif + mach_get_model = amiga_get_model; + mach_get_hardware_list = amiga_get_hardware_list; + mach_get_irq_list = amiga_get_irq_list; + mach_gettimeoffset = amiga_gettimeoffset; + if (AMIGAHW_PRESENT(A3000_CLK)){ + mach_gettod = a3000_gettod; + } + else{ /* if (AMIGAHW_PRESENT(A2000_CLK)) */ + mach_gettod = a2000_gettod; + } + + mach_max_dma_address = 0xffffffff; /* + * default MAX_DMA=0xffffffff + * on all machines. If we don't + * do so, the SCSI code will not + * be able to allocate any mem + * for transfers, unless we are + * dealing with a Z2 mem only + * system. /Jes + */ + + mach_hwclk = amiga_hwclk; + mach_set_clock_mmss = amiga_set_clock_mmss; +#ifdef CONFIG_AMIGA_FLOPPY + mach_floppy_setup = amiga_floppy_setup; +#endif + mach_reset = amiga_reset; + conswitchp = &dummy_con; + kd_mksound = amiga_mksound; +#ifdef CONFIG_MAGIC_SYSRQ + mach_sysrq_key = 0x5f; /* HELP */ + mach_sysrq_shift_state = 0x03; /* SHIFT+ALTGR */ + mach_sysrq_shift_mask = 0xff; /* all modifiers except CapsLock */ + mach_sysrq_xlate = amiga_sysrq_xlate; +#endif +#ifdef CONFIG_HEARTBEAT + mach_heartbeat = amiga_heartbeat; +#endif + + /* Fill in the clock values (based on the 700 kHz E-Clock) */ + amiga_masterclock = 40*amiga_eclock; /* 28 MHz */ + amiga_colorclock = 5*amiga_eclock; /* 3.5 MHz */ + + /* clear all DMA bits */ + custom.dmacon = DMAF_ALL; + /* ensure that the DMA master bit is set */ + custom.dmacon = DMAF_SETCLR | DMAF_MASTER; + + /* initialize chipram allocator */ + amiga_chip_init (); + + /* debugging using chipram */ + if (!strcmp( m68k_debug_device, "mem" )){ + if (!AMIGAHW_PRESENT(CHIP_RAM)) + printk("Warning: no chipram present for debugging\n"); + else { + amiga_savekmsg_init(); + amiga_console_driver.write = amiga_mem_console_write; + register_console(&amiga_console_driver); + } + } + + /* our beloved beeper */ + if (AMIGAHW_PRESENT(AMI_AUDIO)) + amiga_init_sound(); + + /* + * if it is an A3000, set the magic bit that forces + * a hard rekick + */ + if (AMIGAHW_PRESENT(MAGIC_REKICK)) + *(unsigned char *)ZTWO_VADDR(0xde0002) |= 0x80; + +#ifdef CONFIG_ZORRO + zorro_init(); +#endif +} + +static unsigned short jiffy_ticks; + +__initfunc(static void amiga_sched_init(void (*timer_routine)(int, void *, + struct pt_regs *))) +{ + jiffy_ticks = (amiga_eclock+HZ/2)/HZ; + + ciab.cra &= 0xC0; /* turn off timer A, continuous mode, from Eclk */ + ciab.talo = jiffy_ticks % 256; + ciab.tahi = jiffy_ticks / 256; + + /* install interrupt service routine for CIAB Timer A + * + * Please don't change this to use ciaa, as it interferes with the + * SCSI code. We'll have to take a look at this later + */ + request_irq(IRQ_AMIGA_CIAB_TA, timer_routine, IRQ_FLG_LOCK, + "timer", NULL); + /* start timer */ + ciab.cra |= 0x11; +} + +#define TICK_SIZE 10000 + +/* This is always executed with interrupts disabled. */ +static unsigned long amiga_gettimeoffset (void) +{ + unsigned short hi, lo, hi2; + unsigned long ticks, offset = 0; + + /* read CIA B timer A current value */ + hi = ciab.tahi; + lo = ciab.talo; + hi2 = ciab.tahi; + + if (hi != hi2) { + lo = ciab.talo; + hi = hi2; + } + + ticks = hi << 8 | lo; + + if (ticks > jiffy_ticks / 2) + /* check for pending interrupt */ + if (cia_set_irq(&ciab_base, 0) & CIA_ICR_TA) + offset = 10000; + + ticks = jiffy_ticks - ticks; + ticks = (10000 * ticks) / jiffy_ticks; + + return ticks + offset; +} + +static void a3000_gettod (int *yearp, int *monp, int *dayp, + int *hourp, int *minp, int *secp) +{ + volatile struct tod3000 *tod = TOD_3000; + + tod->cntrl1 = TOD3000_CNTRL1_HOLD; + + *secp = tod->second1 * 10 + tod->second2; + *minp = tod->minute1 * 10 + tod->minute2; + *hourp = tod->hour1 * 10 + tod->hour2; + *dayp = tod->day1 * 10 + tod->day2; + *monp = tod->month1 * 10 + tod->month2; + *yearp = tod->year1 * 10 + tod->year2; + + tod->cntrl1 = TOD3000_CNTRL1_FREE; +} + +static void a2000_gettod (int *yearp, int *monp, int *dayp, + int *hourp, int *minp, int *secp) +{ + volatile struct tod2000 *tod = TOD_2000; + + tod->cntrl1 = TOD2000_CNTRL1_HOLD; + + while (tod->cntrl1 & TOD2000_CNTRL1_BUSY) + ; + + *secp = tod->second1 * 10 + tod->second2; + *minp = tod->minute1 * 10 + tod->minute2; + *hourp = (tod->hour1 & 3) * 10 + tod->hour2; + *dayp = tod->day1 * 10 + tod->day2; + *monp = tod->month1 * 10 + tod->month2; + *yearp = tod->year1 * 10 + tod->year2; + + if (!(tod->cntrl3 & TOD2000_CNTRL3_24HMODE)){ + if (!(tod->hour1 & TOD2000_HOUR1_PM) && *hourp == 12) + *hourp = 0; + else if ((tod->hour1 & TOD2000_HOUR1_PM) && *hourp != 12) + *hourp += 12; + } + + tod->cntrl1 &= ~TOD2000_CNTRL1_HOLD; +} + +static int amiga_hwclk(int op, struct hwclk_time *t) +{ + if (AMIGAHW_PRESENT(A3000_CLK)) { + volatile struct tod3000 *tod = TOD_3000; + + tod->cntrl1 = TOD3000_CNTRL1_HOLD; + + if (!op) { /* read */ + t->sec = tod->second1 * 10 + tod->second2; + t->min = tod->minute1 * 10 + tod->minute2; + t->hour = tod->hour1 * 10 + tod->hour2; + t->day = tod->day1 * 10 + tod->day2; + t->wday = tod->weekday; + t->mon = tod->month1 * 10 + tod->month2 - 1; + t->year = tod->year1 * 10 + tod->year2; + } else { + tod->second1 = t->sec / 10; + tod->second2 = t->sec % 10; + tod->minute1 = t->min / 10; + tod->minute2 = t->min % 10; + tod->hour1 = t->hour / 10; + tod->hour2 = t->hour % 10; + tod->day1 = t->day / 10; + tod->day2 = t->day % 10; + if (t->wday != -1) + tod->weekday = t->wday; + tod->month1 = (t->mon + 1) / 10; + tod->month2 = (t->mon + 1) % 10; + tod->year1 = t->year / 10; + tod->year2 = t->year % 10; + } + + tod->cntrl1 = TOD3000_CNTRL1_FREE; + } else /* if (AMIGAHW_PRESENT(A2000_CLK)) */ { + volatile struct tod2000 *tod = TOD_2000; + + tod->cntrl1 = TOD2000_CNTRL1_HOLD; + + while (tod->cntrl1 & TOD2000_CNTRL1_BUSY) + ; + + if (!op) { /* read */ + t->sec = tod->second1 * 10 + tod->second2; + t->min = tod->minute1 * 10 + tod->minute2; + t->hour = (tod->hour1 & 3) * 10 + tod->hour2; + t->day = tod->day1 * 10 + tod->day2; + t->wday = tod->weekday; + t->mon = tod->month1 * 10 + tod->month2 - 1; + t->year = tod->year1 * 10 + tod->year2; + + if (!(tod->cntrl3 & TOD2000_CNTRL3_24HMODE)){ + if (!(tod->hour1 & TOD2000_HOUR1_PM) && t->hour == 12) + t->hour = 0; + else if ((tod->hour1 & TOD2000_HOUR1_PM) && t->hour != 12) + t->hour += 12; + } + } else { + tod->second1 = t->sec / 10; + tod->second2 = t->sec % 10; + tod->minute1 = t->min / 10; + tod->minute2 = t->min % 10; + if (tod->cntrl3 & TOD2000_CNTRL3_24HMODE) + tod->hour1 = t->hour / 10; + else if (t->hour >= 12) + tod->hour1 = TOD2000_HOUR1_PM + + (t->hour - 12) / 10; + else + tod->hour1 = t->hour / 10; + tod->hour2 = t->hour % 10; + tod->day1 = t->day / 10; + tod->day2 = t->day % 10; + if (t->wday != -1) + tod->weekday = t->wday; + tod->month1 = (t->mon + 1) / 10; + tod->month2 = (t->mon + 1) % 10; + tod->year1 = t->year / 10; + tod->year2 = t->year % 10; + } + + tod->cntrl1 &= ~TOD2000_CNTRL1_HOLD; + } + + return 0; +} + +static int amiga_set_clock_mmss (unsigned long nowtime) +{ + short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60; + + if (AMIGAHW_PRESENT(A3000_CLK)) { + volatile struct tod3000 *tod = TOD_3000; + + tod->cntrl1 = TOD3000_CNTRL1_HOLD; + + tod->second1 = real_seconds / 10; + tod->second2 = real_seconds % 10; + tod->minute1 = real_minutes / 10; + tod->minute2 = real_minutes % 10; + + tod->cntrl1 = TOD3000_CNTRL1_FREE; + } else /* if (AMIGAHW_PRESENT(A2000_CLK)) */ { + volatile struct tod2000 *tod = TOD_2000; + + tod->cntrl1 = TOD2000_CNTRL1_HOLD; + + while (tod->cntrl1 & TOD2000_CNTRL1_BUSY) + ; + + tod->second1 = real_seconds / 10; + tod->second2 = real_seconds % 10; + tod->minute1 = real_minutes / 10; + tod->minute2 = real_minutes % 10; + + tod->cntrl1 &= ~TOD2000_CNTRL1_HOLD; + } + + return 0; +} + +static int amiga_wait_key (struct console *co) +{ + int i; + + while (1) { + while (ciaa.pra & 0x40); + + /* debounce */ + for (i = 0; i < 1000; i++); + + if (!(ciaa.pra & 0x40)) + break; + } + + /* wait for button up */ + while (1) { + while (!(ciaa.pra & 0x40)); + + /* debounce */ + for (i = 0; i < 1000; i++); + + if (ciaa.pra & 0x40) + break; + } + return 0; +} + +void dbprintf(const char *fmt , ...) +{ + static char buf[1024]; + va_list args; + extern void console_print (const char *str); + extern int vsprintf(char * buf, const char * fmt, va_list args); + + va_start(args, fmt); + vsprintf(buf, fmt, args); + va_end(args); + + console_print (buf); +} + +static NORET_TYPE void amiga_reset( void ) + ATTRIB_NORET; + +static void amiga_reset (void) +{ + for (;;); +} + + + /* + * Debugging + */ + +#define SAVEKMSG_MAXMEM 128*1024 + +#define SAVEKMSG_MAGIC1 0x53415645 /* 'SAVE' */ +#define SAVEKMSG_MAGIC2 0x4B4D5347 /* 'KMSG' */ + +struct savekmsg { + unsigned long magic1; /* SAVEKMSG_MAGIC1 */ + unsigned long magic2; /* SAVEKMSG_MAGIC2 */ + unsigned long magicptr; /* address of magic1 */ + unsigned long size; + char data[0]; +}; + +static struct savekmsg *savekmsg = NULL; + +static void amiga_mem_console_write(struct console *co, const char *s, + unsigned int count) +{ + if (savekmsg->size+count <= SAVEKMSG_MAXMEM-sizeof(struct savekmsg)) { + memcpy(savekmsg->data+savekmsg->size, s, count); + savekmsg->size += count; + } +} + +static void amiga_savekmsg_init(void) +{ + savekmsg = (struct savekmsg *)amiga_chip_alloc(SAVEKMSG_MAXMEM); + savekmsg->magic1 = SAVEKMSG_MAGIC1; + savekmsg->magic2 = SAVEKMSG_MAGIC2; + savekmsg->magicptr = VTOP(savekmsg); + savekmsg->size = 0; +} + +static void amiga_serial_putc(char c) +{ + custom.serdat = (unsigned char)c | 0x100; + +#ifdef CONFIG_APUS + /* I'm sure this should not be necessary since the address is + marked non-cachable and coherent. Still, without it the + serial output is not usable. -jskov */ + eieio (); +#endif + + while (!(custom.serdatr & 0x2000)) + ; +} + +void amiga_serial_console_write(struct console *co, const char *s, + unsigned int count) +{ + while (count--) { + if (*s == '\n') + amiga_serial_putc('\r'); + amiga_serial_putc(*s++); + } +} + +#ifdef CONFIG_SERIAL_CONSOLE +void amiga_serial_puts(const char *s) +{ + amiga_serial_console_write(NULL, s, strlen(s)); +} + +int amiga_serial_console_wait_key(struct console *co) +{ + int ch; + + while (!(custom.intreqr & IF_RBF)) + barrier(); + ch = custom.serdatr & 0xff; + /* clear the interrupt, so that another character can be read */ + custom.intreq = IF_RBF; + return ch; +} + +void amiga_serial_gets(struct console *co, char *s, int len) +{ + int ch, cnt = 0; + + while (1) { + ch = amiga_serial_console_wait_key(co); + + /* Check for backspace. */ + if (ch == 8 || ch == 127) { + if (cnt == 0) { + amiga_serial_putc('\007'); + continue; + } + cnt--; + amiga_serial_puts("\010 \010"); + continue; + } + + /* Check for enter. */ + if (ch == 10 || ch == 13) + break; + + /* See if line is too long. */ + if (cnt >= len + 1) { + amiga_serial_putc(7); + cnt--; + continue; + } + + /* Store and echo character. */ + s[cnt++] = ch; + amiga_serial_putc(ch); + } + /* Print enter. */ + amiga_serial_puts("\r\n"); + s[cnt] = 0; +} +#endif + +__initfunc(static void amiga_debug_init(void)) +{ + if (!strcmp( m68k_debug_device, "ser" )) { + /* no initialization required (?) */ + amiga_console_driver.write = amiga_serial_console_write; + register_console(&amiga_console_driver); + } +} + +#ifdef CONFIG_HEARTBEAT +static void amiga_heartbeat(int on) +{ + if (on) + ciaa.pra &= ~2; + else + ciaa.pra |= 2; +} +#endif + + /* + * Amiga specific parts of /proc + */ + +static void amiga_get_model(char *model) +{ + strcpy(model, "Amiga "); + if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO) + strcat(model, amiga_models[amiga_model-AMI_500]); +} + + +static int amiga_get_hardware_list(char *buffer) +{ + int len = 0; + + if (AMIGAHW_PRESENT(CHIP_RAM)) + len += sprintf(buffer+len, "Chip RAM:\t%ldK\n", amiga_chip_size>>10); + len += sprintf(buffer+len, "PS Freq:\t%dHz\nEClock Freq:\t%ldHz\n", + amiga_psfreq, amiga_eclock); + if (AMIGAHW_PRESENT(AMI_VIDEO)) { + char *type; + switch(amiga_chipset) { + case CS_OCS: + type = "OCS"; + break; + case CS_ECS: + type = "ECS"; + break; + case CS_AGA: + type = "AGA"; + break; + default: + type = "Old or Unknown"; + break; + } + len += sprintf(buffer+len, "Graphics:\t%s\n", type); + } + +#define AMIGAHW_ANNOUNCE(name, str) \ + if (AMIGAHW_PRESENT(name)) \ + len += sprintf (buffer+len, "\t%s\n", str) + + len += sprintf (buffer + len, "Detected hardware:\n"); + + AMIGAHW_ANNOUNCE(AMI_VIDEO, "Amiga Video"); + AMIGAHW_ANNOUNCE(AMI_BLITTER, "Blitter"); + AMIGAHW_ANNOUNCE(AMBER_FF, "Amber Flicker Fixer"); + AMIGAHW_ANNOUNCE(AMI_AUDIO, "Amiga Audio"); + AMIGAHW_ANNOUNCE(AMI_FLOPPY, "Floppy Controller"); + AMIGAHW_ANNOUNCE(A3000_SCSI, "SCSI Controller WD33C93 (A3000 style)"); + AMIGAHW_ANNOUNCE(A4000_SCSI, "SCSI Controller NCR53C710 (A4000T style)"); + AMIGAHW_ANNOUNCE(A1200_IDE, "IDE Interface (A1200 style)"); + AMIGAHW_ANNOUNCE(A4000_IDE, "IDE Interface (A4000 style)"); + AMIGAHW_ANNOUNCE(CD_ROM, "Internal CD ROM drive"); + AMIGAHW_ANNOUNCE(AMI_KEYBOARD, "Keyboard"); + AMIGAHW_ANNOUNCE(AMI_MOUSE, "Mouse Port"); + AMIGAHW_ANNOUNCE(AMI_SERIAL, "Serial Port"); + AMIGAHW_ANNOUNCE(AMI_PARALLEL, "Parallel Port"); + AMIGAHW_ANNOUNCE(A2000_CLK, "Hardware Clock (A2000 style)"); + AMIGAHW_ANNOUNCE(A3000_CLK, "Hardware Clock (A3000 style)"); + AMIGAHW_ANNOUNCE(CHIP_RAM, "Chip RAM"); + AMIGAHW_ANNOUNCE(PAULA, "Paula 8364"); + AMIGAHW_ANNOUNCE(DENISE, "Denise 8362"); + AMIGAHW_ANNOUNCE(DENISE_HR, "Denise 8373"); + AMIGAHW_ANNOUNCE(LISA, "Lisa 8375"); + AMIGAHW_ANNOUNCE(AGNUS_PAL, "Normal/Fat PAL Agnus 8367/8371"); + AMIGAHW_ANNOUNCE(AGNUS_NTSC, "Normal/Fat NTSC Agnus 8361/8370"); + AMIGAHW_ANNOUNCE(AGNUS_HR_PAL, "Fat Hires PAL Agnus 8372"); + AMIGAHW_ANNOUNCE(AGNUS_HR_NTSC, "Fat Hires NTSC Agnus 8372"); + AMIGAHW_ANNOUNCE(ALICE_PAL, "PAL Alice 8374"); + AMIGAHW_ANNOUNCE(ALICE_NTSC, "NTSC Alice 8374"); + AMIGAHW_ANNOUNCE(MAGIC_REKICK, "Magic Hard Rekick"); + AMIGAHW_ANNOUNCE(PCMCIA, "PCMCIA Slot"); + if (AMIGAHW_PRESENT(ZORRO)) + len += sprintf(buffer+len, "\tZorro%s AutoConfig: %d Expansion Device%s\n", + AMIGAHW_PRESENT(ZORRO3) ? " III" : "", + zorro_num_autocon, zorro_num_autocon == 1 ? "" : "s"); + +#undef AMIGAHW_ANNOUNCE + + return(len); +} diff -u --recursive --new-file v2.1.123/linux/arch/ppc/apus_defconfig linux/arch/ppc/apus_defconfig --- v2.1.123/linux/arch/ppc/apus_defconfig Thu Aug 6 14:06:29 1998 +++ linux/arch/ppc/apus_defconfig Wed Sep 30 10:14:16 1998 @@ -22,6 +22,7 @@ CONFIG_EXPERIMENTAL=y # CONFIG_MODULES is not set # CONFIG_PCI is not set +# CONFIG_PCI_QUIRKS is not set # CONFIG_PCI_OLD_PROC is not set CONFIG_NET=y # CONFIG_SYSCTL is not set @@ -32,12 +33,12 @@ # CONFIG_BINFMT_MISC is not set # CONFIG_BINFMT_JAVA is not set # CONFIG_PARPORT is not set -CONFIG_ABSTRACT_CONSOLE=y CONFIG_FB=y -# CONFIG_VGA_CONSOLE is not set # CONFIG_FB_COMPAT_XPMAC is not set +# CONFIG_PMAC_PBOOK is not set # CONFIG_MAC_KEYBOARD is not set # CONFIG_MAC_FLOPPY is not set +# CONFIG_MAC_SERIAL is not set # CONFIG_MACMOUSE is not set # CONFIG_PROC_DEVICETREE is not set # CONFIG_KGDB is not set @@ -48,7 +49,6 @@ CONFIG_AMIGAMOUSE=y CONFIG_ABSTRACT_CONSOLE=y CONFIG_FB=y -CONFIG_AMIGA_FLOPPY=y CONFIG_AMIGA_BUILTIN_SERIAL=y CONFIG_GVPIOEXT=y # CONFIG_GVPIOEXT_LP is not set @@ -63,28 +63,34 @@ # CONFIG_PNP is not set # -# Floppy, IDE, and other block devices +# Block devices # # CONFIG_BLK_DEV_FD is not set +CONFIG_AMIGA_FLOPPY=y CONFIG_BLK_DEV_IDE=y # # Please see Documentation/ide.txt for help/info on IDE drives # -CONFIG_BLK_DEV_GAYLE=y # CONFIG_BLK_DEV_HD_IDE is not set CONFIG_BLK_DEV_IDEDISK=y CONFIG_BLK_DEV_IDECD=y # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_BLK_DEV_PCIDE is not set +CONFIG_BLK_DEV_GAYLE=y +# CONFIG_BLK_DEV_IDEDOUBLER is not set +CONFIG_BLK_DEV_BUDDHA=y # CONFIG_BLK_DEV_CMD640 is not set # CONFIG_IDE_CHIPSETS is not set +# CONFIG_AMIGA_Z2RAM is not set # # Additional Block Devices # # CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_MD is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_INITRD=y @@ -105,10 +111,7 @@ CONFIG_INET=y # CONFIG_IP_MULTICAST is not set # CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -CONFIG_IP_PNP_BOOTP=y -CONFIG_IP_PNP_RARP=y -# CONFIG_IP_ACCT is not set +# CONFIG_IP_PNP is not set # CONFIG_IP_ROUTER is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set @@ -138,7 +141,6 @@ # CONFIG_NET_HW_FLOWCONTROL is not set # CONFIG_CPU_IS_SLOW is not set # CONFIG_NET_SCHED is not set -# CONFIG_NET_PROFILE is not set # # SCSI support @@ -191,14 +193,13 @@ # CONFIG_SCSI_U14_34F is not set # CONFIG_SCSI_ULTRASTOR is not set # CONFIG_SCSI_DEBUG is not set -# CONFIG_SCSI_MESH is not set CONFIG_A3000_SCSI=y CONFIG_A2091_SCSI=y CONFIG_GVP11_SCSI=y CONFIG_FASTLANE_SCSI=y -# CONFIG_A4000T_SCSI is not set -# CONFIG_A4091_SCSI is not set -# CONFIG_SCSI_MAC53C94 is not set +CONFIG_A4000T_SCSI=y +CONFIG_A4091_SCSI=y +CONFIG_BLZ603EPLUS_SCSI=y # # Network device support @@ -208,6 +209,8 @@ # CONFIG_DUMMY is not set # CONFIG_EQUALIZER is not set CONFIG_NET_ETHERNET=y +# CONFIG_MACE is not set +# CONFIG_BMAC is not set CONFIG_ARIADNE=y CONFIG_A2065=y CONFIG_HYDRA=y @@ -215,6 +218,8 @@ # CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_RTL8139 is not set +# CONFIG_YELLOWFIN is not set # CONFIG_NET_ISA is not set # CONFIG_NET_EISA is not set # CONFIG_NET_POCKET is not set @@ -249,6 +254,62 @@ # CONFIG_CD_NO_IDESCSI is not set # +# Console drivers +# +CONFIG_DUMMY_CONSOLE=y +CONFIG_FB_AMIGA=y +CONFIG_FB_AMIGA_OCS=y +CONFIG_FB_AMIGA_ECS=y +CONFIG_FB_AMIGA_AGA=y +CONFIG_FB_CYBER=y +CONFIG_FB_VIRGE=y +CONFIG_FB_RETINAZ3=y +CONFIG_FB_CLGEN=y +# CONFIG_FB_OF is not set +# CONFIG_FB_VGA is not set +CONFIG_FB_VIRTUAL=y +# CONFIG_FBCON_ADVANCED is not set +CONFIG_FBCON_MFB=y +CONFIG_FBCON_CFB2=y +CONFIG_FBCON_CFB4=y +CONFIG_FBCON_CFB8=y +CONFIG_FBCON_CFB16=y +CONFIG_FBCON_CFB24=y +CONFIG_FBCON_CFB32=y +CONFIG_FBCON_AFB=y +CONFIG_FBCON_ILBM=y +CONFIG_FBCON_MAC=y +# CONFIG_FBCON_FONTWIDTH8_ONLY is not set +# CONFIG_FBCON_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +CONFIG_FONT_PEARL_8x8=y + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_SERIAL=y +# CONFIG_SERIAL_CONSOLE is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_UNIX98_PTYS is not set +# CONFIG_MOUSE is not set +# CONFIG_QIC02_TAPE is not set +# CONFIG_APM is not set +# CONFIG_WATCHDOG is not set +# CONFIG_RTC is not set +# CONFIG_VIDEO_DEV is not set +# CONFIG_NVRAM is not set +# CONFIG_JOYSTICK is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set + +# # Filesystems # # CONFIG_QUOTA is not set @@ -262,7 +323,6 @@ CONFIG_VFAT_FS=y CONFIG_PROC_FS=y CONFIG_NFS_FS=y -# CONFIG_ROOT_NFS is not set # CONFIG_NFSD is not set CONFIG_SUNRPC=y CONFIG_LOCKD=y @@ -281,11 +341,15 @@ # Partition Tables # CONFIG_AMIGA_PARTITION=y -# CONFIG_FOREIGN_PARTITIONS is not set +CONFIG_FOREIGN_PARTITIONS=y +CONFIG_MSDOS_PARTITION=y +# CONFIG_OSF_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set # CONFIG_BSD_DISKLABEL is not set # CONFIG_SOLARIS_X86_PARTITION is not set # CONFIG_ADFS_FS is not set -# CONFIG_DEVPTS_FS is not set CONFIG_NLS=y # @@ -317,55 +381,6 @@ # CONFIG_NLS_ISO8859_8 is not set # CONFIG_NLS_ISO8859_9 is not set # CONFIG_NLS_KOI8_R is not set - -# -# Frame buffer devices -# -CONFIG_FB_AMIGA=y -CONFIG_FB_AMIGA_OCS=y -CONFIG_FB_AMIGA_ECS=y -CONFIG_FB_AMIGA_AGA=y -CONFIG_FB_CYBER=y -CONFIG_FB_VIRGE=y -CONFIG_FB_RETINAZ3=y -# CONFIG_FB_OF is not set -# CONFIG_FB_S3TRIO is not set -CONFIG_FB_VIRTUAL=y -# CONFIG_FBCON_ADVANCED is not set -CONFIG_FBCON_MFB=y -CONFIG_FBCON_ILBM=y -CONFIG_FBCON_AFB=y -CONFIG_FBCON_MAC=y -CONFIG_FBCON_CFB2=y -CONFIG_FBCON_CFB4=y -CONFIG_FBCON_CFB8=y -CONFIG_FBCON_CFB16=y -CONFIG_FBCON_CFB24=y -CONFIG_FBCON_CFB32=y - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=y -# CONFIG_SERIAL_CONSOLE is not set -# CONFIG_SERIAL_EXTENDED is not set -# CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_MOUSE is not set -# CONFIG_QIC02_TAPE is not set -# CONFIG_APM is not set -# CONFIG_WATCHDOG is not set -# CONFIG_RTC is not set -# CONFIG_VIDEO_DEV is not set -# CONFIG_NVRAM is not set -# CONFIG_JOYSTICK is not set -# CONFIG_MISC_RADIO is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set # # Sound diff -u --recursive --new-file v2.1.123/linux/arch/ppc/boot/Makefile linux/arch/ppc/boot/Makefile --- v2.1.123/linux/arch/ppc/boot/Makefile Fri May 8 23:14:44 1998 +++ linux/arch/ppc/boot/Makefile Wed Sep 30 10:14:16 1998 @@ -20,7 +20,6 @@ .S.o: $(CC) -D__ASSEMBLY__ -traditional -c -o $*.o $< - ZOFF = 0 ZSZ = 0 IOFF = 0 @@ -58,10 +57,10 @@ --add-section=initrd=ramdisk.image.gz \ --add-section=image=../coffboot/vmlinux.gz \ zvmlinux.initrd.tmp zvmlinux.initrd - $(CC) $(CFLAGS) -DINITRD_OFFSET=`sh offset zvmlinux.initrd initrd` \ - -DINITRD_SIZE=`sh size zvmlinux.initrd initrd` \ - -DZIMAGE_OFFSET=`sh offset zvmlinux.initrd image` \ - -DZIMAGE_SIZE=`sh size zvmlinux.initrd image` \ + $(CC) $(CFLAGS) -DINITRD_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd initrd` \ + -DINITRD_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd initrd` \ + -DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd image` \ + -DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd image` \ -DKERNELBASE=$(KERNELBASE) -c -o misc.o misc.c $(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS) $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ @@ -77,10 +76,10 @@ --add-section=initrd=ramdisk.image.gz \ --add-section=image=../coffboot/vmlinux.gz \ zvmlinux.initrd.tmp zvmlinux.initrd - $(CC) $(CFLAGS) -DINITRD_OFFSET=`sh offset zvmlinux.initrd initrd` \ - -DINITRD_SIZE=`sh size zvmlinux.initrd initrd` \ - -DZIMAGE_OFFSET=`sh offset zvmlinux.initrd image` \ - -DZIMAGE_SIZE=`sh size zvmlinux.initrd image` \ + $(CC) $(CFLAGS) -DINITRD_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd initrd` \ + -DINITRD_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd initrd` \ + -DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd image` \ + -DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd image` \ -DKERNELBASE=$(KERNELBASE) -c -o misc.o misc.c $(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS) $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ @@ -90,19 +89,26 @@ rm zvmlinux.initrd.tmp endif -zImage: zvmlinux mkprep ifeq ($(CONFIG_PREP),y) +zImage: zvmlinux mkprep ./mkprep -pbp zvmlinux zImage -endif +else + ifeq ($(CONFIG_MBX),y) +zImage: zvmlinux ln -sf zvmlinux zImage +else +zImage: +endif + endif -zImage.initrd: zvmlinux.initrd mkprep ifeq ($(CONFIG_PREP),y) +zImage.initrd: zvmlinux.initrd mkprep ./mkprep -pbp zvmlinux.initrd zImage.initrd endif ifeq ($(CONFIG_MBX),y) +zImage.initrd: zvmlinux.initrd ln -sf zvmlinux.initrd zImage.initrd endif @@ -118,8 +124,8 @@ # then with the offset rebuild the bootloader so we know where the kernel is # $(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 \ - -DZIMAGE_OFFSET=`sh offset zvmlinux image` \ - -DZIMAGE_SIZE=`sh size zvmlinux image` -DKERNELBASE=$(KERNELBASE) \ + -DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux image` \ + -DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux image` -DKERNELBASE=$(KERNELBASE) \ -c -o misc.o misc.c $(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS) $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment --add-section=image=../coffboot/vmlinux.gz \ @@ -131,17 +137,21 @@ dd if=zImage of=/dev/fd0H1440 bs=64b endif -mkprep : mkprep.c ifeq ($(CONFIG_PREP),y) +mkprep : mkprep.c $(HOSTCC) -DKERNELBASE=$(KERNELBASE) -o mkprep mkprep.c endif -znetboot : zImage ifeq ($(CONFIG_PREP),y) +znetboot : zImage cp zImage /tftpboot/zImage.prep -endif +else ifeq ($(CONFIG_MBX),y) +znetboot : zImage cp zImage /tftpboot/zImage.mbx +else +znetboot : +endif endif znetboot.initrd : zImage.initrd diff -u --recursive --new-file v2.1.123/linux/arch/ppc/boot/head.S linux/arch/ppc/boot/head.S --- v2.1.123/linux/arch/ppc/boot/head.S Thu Aug 6 14:06:29 1998 +++ linux/arch/ppc/boot/head.S Wed Sep 30 10:14:16 1998 @@ -7,7 +7,7 @@ .text /* - * $Id: head.S,v 1.24 1998/07/21 02:43:50 cort Exp $ + * $Id: head.S,v 1.26 1998/09/19 01:21:20 cort Exp $ * * This code is loaded by the ROM loader at some arbitrary location. * Move it to high memory so that it can load the kernel at 0x0000. @@ -144,6 +144,11 @@ mr r3, r11 mr r21, r11 bl serial_init /* Init MBX serial port */ + + lis r8, 0xfa200000@h /* Disable Ethernet SCC */ + li r0, 0 + stw r0, 0x0a00(r8) + mr r11, r21 lis r8,start@h ori r8,r8,start@l @@ -166,6 +171,7 @@ as ptr to residual -- Cort*/ lis r6,cmd_line@h ori r6,r6,cmd_line@l + lwz r6, 0(r6) subi r7,r6,1 00: lbzu r2,1(r7) cmpi 0,r2,0 diff -u --recursive --new-file v2.1.123/linux/arch/ppc/boot/mbxtty.c linux/arch/ppc/boot/mbxtty.c --- v2.1.123/linux/arch/ppc/boot/mbxtty.c Thu Aug 6 14:06:29 1998 +++ linux/arch/ppc/boot/mbxtty.c Thu Oct 1 09:55:13 1998 @@ -12,14 +12,22 @@ * I f**ked around for a day trying to figure out how to make EPPC-Bug * use SMC1, but gave up and decided to fix it here. */ +#include #include +#ifdef CONFIG_MBX #include +#endif +#ifdef CONFIG_FADS +#include +#endif #include "../8xx_io/commproc.h" +#ifdef CONFIG_MBX #define MBX_CSR1 ((volatile u_char *)0xfa100000) #define CSR1_COMEN (u_char)0x02 +#endif -static cpm8xx_t *cpmp = (cpm8xx_t *)&(((immap_t *)MBX_IMAP_ADDR)->im_cpm); +static cpm8xx_t *cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm); void serial_init(bd_t *bd) @@ -38,6 +46,7 @@ */ sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); +#ifdef CONFIG_MBX if (*MBX_CSR1 & CSR1_COMEN) { /* COM1 is enabled. Initialize SMC1 and use it for * the console port. @@ -45,7 +54,7 @@ /* Enable SDMA. */ - ((immap_t *)MBX_IMAP_ADDR)->im_siu_conf.sc_sdcr = 1; + ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sdcr = 1; /* Use Port B for SMCs instead of other functions. */ @@ -103,6 +112,7 @@ *MBX_CSR1 &= ~CSR1_COMEN; } else { +#endif /* SMC1 is used as console port. */ tbdf = (cbd_t *)&cp->cp_dpmem[up->smc_tbase]; @@ -113,7 +123,9 @@ cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC1, CPM_CR_STOP_TX) | CPM_CR_FLG; while (cp->cp_cpcr & CPM_CR_FLG); +#ifdef CONFIG_MBX } +#endif /* Make the first buffer the only buffer. */ diff -u --recursive --new-file v2.1.123/linux/arch/ppc/boot/misc.c linux/arch/ppc/boot/misc.c --- v2.1.123/linux/arch/ppc/boot/misc.c Thu Aug 6 14:06:29 1998 +++ linux/arch/ppc/boot/misc.c Wed Sep 30 10:14:16 1998 @@ -1,7 +1,7 @@ /* * misc.c * - * $Id: misc.c,v 1.49 1998/07/26 21:29:15 geert Exp $ + * $Id: misc.c,v 1.52 1998/09/19 01:21:24 cort Exp $ * * Adapted for PowerPC by Gary Thomas * @@ -9,6 +9,7 @@ * One day to be replaced by a single bootloader for chrp/prep/pmac. -- Cort */ +#include #include "../coffboot/zlib.h" #include "asm/residual.h" #include @@ -18,7 +19,9 @@ #include #ifdef CONFIG_MBX #include -bd_t hold_board_info; +#endif +#ifdef CONFIG_FADS +#include #endif /* @@ -31,8 +34,30 @@ char *avail_ram; char *end_avail; -char cmd_line[256]; -RESIDUAL hold_residual; +/* Because of the limited amount of memory on the MBX, it presents + * loading problems. The biggest is that we load this boot program + * into a relatively low memory address, and the Linux kernel Bss often + * extends into this space when it get loaded. When the kernel starts + * and zeros the BSS space, it also writes over the information we + * save here and pass to the kernel (command line and board info). + * On the MBX we grab some known memory holes to hold this information. + */ +char cmd_buf[256]; +char *cmd_line = cmd_buf; + +#if defined(CONFIG_MBX) || defined(CONFIG_FADS) +char *root_string = "root=/dev/nfs"; +char *nfsaddrs_string = "nfsaddrs="; +char *nfsroot_string = "nfsroot="; +char *defroot_string = "/sys/mbxroot"; +int do_ipaddrs(char **cmd_cp, int echo); +void do_nfsroot(char **cmd_cp, char *dp); +int strncmp(const char * cs,const char * ct,size_t count); +char *strrchr(const char * s, int c); +#endif + +RESIDUAL hold_resid_buf; +RESIDUAL *hold_residual = &hold_resid_buf; unsigned long initrd_start = 0, initrd_end = 0; char *zimage_start; int zimage_size; @@ -60,7 +85,7 @@ while(1); } -#ifndef CONFIG_MBX +#if !defined(CONFIG_MBX) && !defined(CONFIG_FADS) static void clear_screen() { int i, j; @@ -311,6 +336,9 @@ unsigned long i; BATU *u; BATL *l; +#if defined(CONFIG_MBX) || defined(CONFIG_KB) + char *dp; +#endif lines = 25; cols = 80; @@ -318,7 +346,7 @@ orig_y = 24; -#ifndef CONFIG_MBX +#if !defined(CONFIG_MBX) && !defined(CONFIG_FADS) /* * IBM's have the MMU on, so we have to disable it or * things get really unhappy in the kernel when @@ -331,18 +359,30 @@ vga_init(0xC0000000); if (residual) - memcpy(&hold_residual,residual,sizeof(RESIDUAL)); + memcpy(hold_residual,residual,sizeof(RESIDUAL)); #else /* CONFIG_MBX */ + + /* Grab some space for the command line and board info. Since + * we no longer use the ELF header, but it was loaded, grab + * that space. + */ + cmd_line = (char *)(load_addr - 0x10000); + hold_residual = (RESIDUAL *)(cmd_line + sizeof(cmd_buf)); /* copy board data */ if (residual) - _bcopy((char *)residual, (char *)&hold_board_info, - sizeof(hold_board_info)); + memcpy(hold_residual,residual,sizeof(bd_t)); #endif /* CONFIG_MBX */ /* MBX/prep sometimes put the residual/board info at the end of mem * assume 16M for now -- Cort + * To boot on standard MBX boards with 4M, we can't use initrd, + * and we have to assume less memory. -- Dan */ - end_avail = (char *)0x01000000; + if ( INITRD_OFFSET ) + end_avail = (char *)0x01000000; + else + end_avail = (char *)0x00400000; + /* let residual data tell us it's higher */ if ( (unsigned long)residual > 0x00800000 ) end_avail = (char *)PAGE_ALIGN((unsigned long)residual); @@ -361,23 +401,19 @@ { puts("board data at: "); puthex((unsigned long)residual); puts(" "); -#ifdef CONFIG_MBX +#if defined(CONFIG_MBX) || defined(CONFIG_FADS) puthex((unsigned long)((unsigned long)residual + sizeof(bd_t))); #else puthex((unsigned long)((unsigned long)residual + sizeof(RESIDUAL))); #endif puts("\n"); puts("relocated to: "); -#ifdef CONFIG_MBX - puthex((unsigned long)&hold_board_info); -#else - puthex((unsigned long)&hold_residual); -#endif + puthex((unsigned long)hold_residual); puts(" "); -#ifdef CONFIG_MBX - puthex((unsigned long)((unsigned long)&hold_board_info + sizeof(bd_t))); +#if defined(CONFIG_MBX) || defined(CONFIG_FADS) + puthex((unsigned long)((unsigned long)hold_residual + sizeof(bd_t))); #else - puthex((unsigned long)((unsigned long)&hold_residual + sizeof(RESIDUAL))); + puthex((unsigned long)((unsigned long)hold_residual + sizeof(RESIDUAL))); #endif puts("\n"); } @@ -411,8 +447,11 @@ /* * don't relocate the zimage if it was loaded above 16M since * things get weird if we try to relocate -- Cort + * We don't relocate zimage on a base MBX board because of + * insufficient memory. In this case we don't have initrd either, + * so use that as an indicator. -- Dan */ - if ( (unsigned long)zimage_start <= 0x01000000 ) + if (( (unsigned long)zimage_start <= 0x01000000 ) && initrd_start) { memcpy ((void *)PAGE_ALIGN(-PAGE_SIZE+(unsigned long)end_avail-zimage_size), (void *)zimage_start, zimage_size ); @@ -439,6 +478,7 @@ * max ram is. * -- Cort */ +#if 0 memcpy ((void *)PAGE_ALIGN(-PAGE_SIZE+(unsigned long)end_avail-INITRD_SIZE), (void *)initrd_start, INITRD_SIZE ); @@ -447,20 +487,26 @@ end_avail = (char *)initrd_start; puts("relocated to: "); puthex(initrd_start); puts(" "); puthex(initrd_end); puts("\n"); +#endif } +#ifndef CONFIG_MBX /* this is safe, just use it */ + /* I don't know why it didn't work for me on the MBX with 20 MB + * memory. I guess something was saved up there, but I can't + * figure it out......we are running on luck. -- Dan. + */ avail_ram = (char *)0x00400000; end_avail = (char *)0x00600000; +#endif puts("avail ram: "); puthex((unsigned long)avail_ram); puts(" "); puthex((unsigned long)end_avail); puts("\n"); -#ifndef CONFIG_MBX +#if !defined(CONFIG_MBX) && !defined(CONFIG_FADS) CRT_tstc(); /* Forces keyboard to be initialized */ #endif -#ifdef CONFIG_PREP -/* I need to fix this for mbx -- Cort */ + puts("\nLinux/PPC load: "); timer = 0; cp = cmd_line; @@ -472,6 +518,13 @@ cp--; puts("\b \b"); } +#ifdef CONFIG_MBX + } else if (ch == '?') { + if (!do_ipaddrs(&cp, 1)) { + *cp++ = ch; + putc(ch); + } +#endif } else { *cp++ = ch; putc(ch); @@ -482,12 +535,38 @@ udelay(1000); /* 1 msec */ } *cp = 0; +#ifdef CONFIG_MBX + /* The MBX does not currently have any default boot strategy. + * If the command line is not filled in, we will automatically + * create the default network boot. + */ + if (cmd_line[0] == 0) { + dp = root_string; + while (*dp != 0) + *cp++ = *dp++; + *cp++ = ' '; + + dp = nfsaddrs_string; + while (*dp != 0) + *cp++ = *dp++; + dp = cp; + do_ipaddrs(&cp, 0); + *cp++ = ' '; + + /* Add the server address to the root file system path. + */ + dp = strrchr(dp, ':'); + dp++; + do_nfsroot(&cp, dp); + *cp = 0; + } +#endif puts("\n"); -#endif /* CONFIG_PREP */ + /* mappings on early boot can only handle 16M */ - if ( (int)(&cmd_line[0]) > (16<<20)) + if ( (int)(cmd_line[0]) > (16<<20)) puts("cmd_line located > 16M\n"); - if ( (int)&hold_residual > (16<<20)) + if ( (int)hold_residual > (16<<20)) puts("hold_residual located > 16M\n"); if ( initrd_start > (16<<20)) puts("initrd_start located > 16M\n"); @@ -497,12 +576,152 @@ gunzip(0, 0x400000, zimage_start, &zimage_size); puts("done.\n"); puts("Now booting the kernel\n"); -#ifndef CONFIG_MBX - return (unsigned long)&hold_residual; -#else - return (unsigned long)&hold_board_info; -#endif + return (unsigned long)hold_residual; } + +#ifdef CONFIG_MBX +int +do_ipaddrs(char **cmd_cp, int echo) +{ + char *cp, *ip, ch; + unsigned char ipd; + int i, j, retval; + + /* We need to create the string: + * : + */ + cp = *cmd_cp; + retval = 0; + + if ((cp - 9) >= cmd_line) { + if (strncmp(cp - 9, "nfsaddrs=", 9) == 0) { + ip = (char *)0xfa000060; + retval = 1; + for (j=0; j<2; j++) { + for (i=0; i<4; i++) { + ipd = *ip++; + + ch = ipd/100; + if (ch) { + ch += '0'; + if (echo) + putc(ch); + *cp++ = ch; + ipd -= 100 * (ch - '0'); + } + + ch = ipd/10; + if (ch) { + ch += '0'; + if (echo) + putc(ch); + *cp++ = ch; + ipd -= 10 * (ch - '0'); + } + + ch = ipd + '0'; + if (echo) + putc(ch); + *cp++ = ch; + + ch = '.'; + if (echo) + putc(ch); + *cp++ = ch; + } + + /* At the end of the string, remove the + * '.' and replace it with a ':'. + */ + *(cp - 1) = ':'; + if (echo) { + putc('\b'); putc(':'); + } + } + + /* At the end of the second string, remove the + * '.' from both the command line and the + * screen. + */ + --cp; + putc('\b'); putc(' '); putc('\b'); + } + } + *cmd_cp = cp; + return(retval); +} + +void +do_nfsroot(char **cmd_cp, char *dp) +{ + char *cp, *rp, *ep; + + /* The boot argument (i.e /sys/mbxroot/zImage) is stored + * at offset 0x0078 in NVRAM. We use this path name to + * construct the root file system path. + */ + cp = *cmd_cp; + + /* build command string. + */ + rp = nfsroot_string; + while (*rp != 0) + *cp++ = *rp++; + + /* Add the server address to the path. + */ + while (*dp != ' ') + *cp++ = *dp++; + *cp++ = ':'; + + rp = (char *)0xfa000078; + ep = strrchr(rp, '/'); + + if (ep != 0) { + while (rp < ep) + *cp++ = *rp++; + } + else { + rp = defroot_string; + while (*rp != 0) + *cp++ = *rp++; + } + + *cmd_cp = cp; +} + +size_t strlen(const char * s) +{ + const char *sc; + + for (sc = s; *sc != '\0'; ++sc) + /* nothing */; + return sc - s; +} + +int strncmp(const char * cs,const char * ct,size_t count) +{ + register signed char __res = 0; + + while (count) { + if ((__res = *cs - *ct++) != 0 || !*cs++) + break; + count--; + } + + return __res; +} + +char * strrchr(const char * s, int c) +{ + const char *p = s + strlen(s); + do { + if (*p == (char)c) + return (char *)p; + } while (--p >= s); + return NULL; +} +#endif void puthex(unsigned long val) { diff -u --recursive --new-file v2.1.123/linux/arch/ppc/boot/mkprep.c linux/arch/ppc/boot/mkprep.c --- v2.1.123/linux/arch/ppc/boot/mkprep.c Mon Jan 12 15:18:13 1998 +++ linux/arch/ppc/boot/mkprep.c Wed Sep 30 10:14:16 1998 @@ -10,16 +10,18 @@ * 3) -asm - strips elf header and writes out as asm data * useful for generating data for a compressed image * -- Cort + * + * Modified for x86 hosted builds by Matt Porter */ #ifdef linux #include -#include +/*#include */ /*#include */ /* the byte swap funcs don't work here -- Cort */ #else #include -#include #endif +#include #include #include @@ -164,8 +166,13 @@ bzero( block, sizeof block ); /* set entry point and boot image size skipping over elf header */ +#ifdef __i386__ + *entry = 0x400/*+65536*/; + *length = info.st_size+0x400; +#else *entry = cpu_to_le32(0x400/*+65536*/); *length = cpu_to_le32(info.st_size+0x400); +#endif /* __i386__ */ /* sets magic number for msdos partition (used by linux) */ block[510] = 0x55; @@ -202,9 +209,18 @@ pe->beginning_sector = cpu_to_le32(1); #else /* This has to be 0 on the PowerStack? */ +#ifdef __i386__ + pe->beginning_sector = 0; +#else pe->beginning_sector = cpu_to_le32(0); +#endif /* __i386__ */ #endif + +#ifdef __i386__ + pe->number_of_sectors = 2*18*80-1; +#else pe->number_of_sectors = cpu_to_le32(2*18*80-1); +#endif /* __i386__ */ write( out, block, sizeof(block) ); write( out, entry, sizeof(*entry) ); diff -u --recursive --new-file v2.1.123/linux/arch/ppc/boot/offset linux/arch/ppc/boot/offset --- v2.1.123/linux/arch/ppc/boot/offset Mon Jan 12 15:18:13 1998 +++ linux/arch/ppc/boot/offset Wed Sep 30 10:14:16 1998 @@ -1,4 +1,4 @@ #!/bin/bash -OFFSET=`objdump -h $1 | grep $2 | grep -v zvmlinux| awk '{print $6}'` +OFFSET=`$1 -h $2 | grep $3 | grep -v zvmlinux| awk '{print $6}'` echo "0x"$OFFSET diff -u --recursive --new-file v2.1.123/linux/arch/ppc/boot/size linux/arch/ppc/boot/size --- v2.1.123/linux/arch/ppc/boot/size Mon Jan 12 15:18:13 1998 +++ linux/arch/ppc/boot/size Wed Sep 30 10:14:16 1998 @@ -1,4 +1,4 @@ #!/bin/bash -OFFSET=`objdump -h $1 | grep $2 | grep -v zvmlinux | awk '{print $3}'` +OFFSET=`$1 -h $2 | grep $3 | grep -v zvmlinux | awk '{print $3}'` echo "0x"$OFFSET diff -u --recursive --new-file v2.1.123/linux/arch/ppc/chrp_defconfig linux/arch/ppc/chrp_defconfig --- v2.1.123/linux/arch/ppc/chrp_defconfig Thu Aug 6 14:06:29 1998 +++ linux/arch/ppc/chrp_defconfig Wed Sep 30 10:14:16 1998 @@ -41,10 +41,11 @@ CONFIG_MAC_KEYBOARD=y # CONFIG_MAC_FLOPPY is not set # CONFIG_MAC_SERIAL is not set -CONFIG_MACMOUSE=y +# CONFIG_ADBMOUSE is not set CONFIG_PROC_DEVICETREE=y # CONFIG_KGDB is not set # CONFIG_XMON is not set +# CONFIG_TOTALMP is not set # # Plug and Play support @@ -148,12 +149,11 @@ # CONFIG_SCSI_NCR53C406A is not set # CONFIG_SCSI_NCR53C7xx is not set CONFIG_SCSI_NCR53C8XX=y -# CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT is not set -# CONFIG_SCSI_NCR53C8XX_TAGGED_QUEUE is not set -# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set +CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 CONFIG_SCSI_NCR53C8XX_MAX_TAGS=4 CONFIG_SCSI_NCR53C8XX_SYNC=5 -# CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT is not set +# CONFIG_SCSI_NCR53C8XX_PROFILE is not set +# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set # CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set # CONFIG_SCSI_PAS16 is not set # CONFIG_SCSI_PCI2000 is not set @@ -199,9 +199,9 @@ # CONFIG_EEXPRESS_PRO100 is not set # CONFIG_LNE390 is not set # CONFIG_NE2K_PCI is not set +# CONFIG_TLAN is not set # CONFIG_ES3210 is not set # CONFIG_EPIC100 is not set -# CONFIG_TLAN is not set # CONFIG_ZNET is not set # CONFIG_NET_POCKET is not set # CONFIG_FDDI is not set @@ -228,50 +228,29 @@ # CONFIG_CD_NO_IDESCSI is not set # -# Filesystems -# -# CONFIG_QUOTA is not set -# CONFIG_MINIX_FS is not set -CONFIG_EXT2_FS=y -CONFIG_ISO9660_FS=y -# CONFIG_JOLIET is not set -# CONFIG_FAT_FS is not set -# CONFIG_MSDOS_FS is not set -# CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set -CONFIG_PROC_FS=y -CONFIG_NFS_FS=y -# CONFIG_NFSD is not set -CONFIG_SUNRPC=y -CONFIG_LOCKD=y -# CONFIG_CODA_FS is not set -# CONFIG_SMB_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_AFFS_FS is not set -CONFIG_HFS_FS=y -# CONFIG_ROMFS_FS is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_UFS_FS is not set -# CONFIG_ADFS_FS is not set -# CONFIG_DEVPTS_FS is not set -CONFIG_MAC_PARTITION=y -# CONFIG_NLS is not set - -# # Console drivers # +CONFIG_DUMMY_CONSOLE=y CONFIG_FB_OF=y -CONFIG_FB_S3TRIO=y +# CONFIG_FB_CONTROL is not set +# CONFIG_FB_PLATINUM is not set +# CONFIG_FB_VALKYRIE is not set CONFIG_FB_ATY=y +CONFIG_FB_IMSTT=y +# CONFIG_FB_CT65550 is not set +# CONFIG_FB_S3TRIO is not set CONFIG_FB_VGA=y # CONFIG_FB_VIRTUAL is not set # CONFIG_FBCON_ADVANCED is not set CONFIG_FBCON_CFB8=y CONFIG_FBCON_CFB16=y +CONFIG_FBCON_CFB24=y CONFIG_FBCON_CFB32=y CONFIG_FBCON_VGA=y +# CONFIG_FBCON_FONTWIDTH8_ONLY is not set +# CONFIG_FBCON_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y # # Character devices @@ -282,6 +261,7 @@ # CONFIG_SERIAL_CONSOLE is not set # CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_UNIX98_PTYS is not set # CONFIG_MOUSE is not set # CONFIG_UMISC is not set # CONFIG_QIC02_TAPE is not set @@ -291,7 +271,6 @@ # CONFIG_VIDEO_DEV is not set CONFIG_NVRAM=y # CONFIG_JOYSTICK is not set -# CONFIG_MISC_RADIO is not set # # Ftape, the floppy tape device driver @@ -299,7 +278,43 @@ # CONFIG_FTAPE is not set # +# Filesystems +# +# CONFIG_QUOTA is not set +# CONFIG_MINIX_FS is not set +CONFIG_EXT2_FS=y +CONFIG_ISO9660_FS=y +# CONFIG_JOLIET is not set +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +CONFIG_PROC_FS=y +CONFIG_NFS_FS=y +# CONFIG_NFSD is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +# CONFIG_CODA_FS is not set +# CONFIG_SMB_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_AFFS_FS is not set +CONFIG_HFS_FS=y +# CONFIG_ROMFS_FS is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_UFS_FS is not set +# CONFIG_ADFS_FS is not set +CONFIG_MAC_PARTITION=y +# CONFIG_NLS is not set + +# # Sound # CONFIG_SOUND=y +# CONFIG_SOUND_ES1370 is not set +# CONFIG_SOUND_ES1371 is not set +# CONFIG_SOUND_SONICVIBES is not set +# CONFIG_SOUND_MSNDCLAS is not set +# CONFIG_SOUND_MSNDPIN is not set # CONFIG_SOUND_OSS is not set diff -u --recursive --new-file v2.1.123/linux/arch/ppc/chrpboot/Makefile linux/arch/ppc/chrpboot/Makefile --- v2.1.123/linux/arch/ppc/chrpboot/Makefile Thu Aug 6 14:06:29 1998 +++ linux/arch/ppc/chrpboot/Makefile Wed Sep 30 10:14:16 1998 @@ -20,7 +20,7 @@ LD_ARGS = -T ../vmlinux.lds -Ttext 0x00800000 OBJCOPY = $(CROSS_COMPILE)objcopy -OBJS = crt0.o start.o main.o misc.o string.o zlib.o image.o # initrd.o +OBJS = crt0.o start.o main.o misc.o ../coffboot/string.o ../coffboot/zlib.o image.o # initrd.o LIBS = $(TOPDIR)/lib/lib.a diff -u --recursive --new-file v2.1.123/linux/arch/ppc/chrpboot/main.c linux/arch/ppc/chrpboot/main.c --- v2.1.123/linux/arch/ppc/chrpboot/main.c Thu Apr 23 20:21:28 1998 +++ linux/arch/ppc/chrpboot/main.c Wed Sep 30 10:14:16 1998 @@ -6,8 +6,8 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ -#include "nonstdio.h" -#include "zlib.h" +#include "../coffboot/nonstdio.h" +#include "../coffboot/zlib.h" extern void *finddevice(const char *); extern int getprop(void *, const char *, void *, int); diff -u --recursive --new-file v2.1.123/linux/arch/ppc/chrpboot/nonstdio.h linux/arch/ppc/chrpboot/nonstdio.h --- v2.1.123/linux/arch/ppc/chrpboot/nonstdio.h Mon Jan 12 15:18:13 1998 +++ linux/arch/ppc/chrpboot/nonstdio.h Wed Dec 31 16:00:00 1969 @@ -1,18 +0,0 @@ -/* - * Copyright (C) Paul Mackerras 1997. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ -typedef int FILE; -extern FILE *stdin, *stdout; -#define NULL ((void *)0) -#define EOF (-1) -#define fopen(n, m) NULL -#define fflush(f) 0 -#define fclose(f) 0 -extern char *fgets(); - -#define perror(s) printf("%s: no files!\n", (s)) diff -u --recursive --new-file v2.1.123/linux/arch/ppc/chrpboot/zlib.c linux/arch/ppc/chrpboot/zlib.c --- v2.1.123/linux/arch/ppc/chrpboot/zlib.c Mon Jan 12 15:18:13 1998 +++ linux/arch/ppc/chrpboot/zlib.c Wed Dec 31 16:00:00 1969 @@ -1,2143 +0,0 @@ -/* - * This file is derived from various .h and .c files from the zlib-0.95 - * distribution by Jean-loup Gailly and Mark Adler, with some additions - * by Paul Mackerras to aid in implementing Deflate compression and - * decompression for PPP packets. See zlib.h for conditions of - * distribution and use. - * - * Changes that have been made include: - * - changed functions not used outside this file to "local" - * - added minCompression parameter to deflateInit2 - * - added Z_PACKET_FLUSH (see zlib.h for details) - * - added inflateIncomp - * - * $Id: zlib.c,v 1.1 1997/09/19 07:03:44 paulus Exp $ - */ - -/*+++++*/ -/* zutil.h -- internal interface and configuration of the compression library - * Copyright (C) 1995 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* From: zutil.h,v 1.9 1995/05/03 17:27:12 jloup Exp */ - -#define _Z_UTIL_H - -#include "zlib.h" - -#ifndef local -# define local static -#endif -/* compile with -Dlocal if your debugger can't find static symbols */ - -#define FAR - -typedef unsigned char uch; -typedef uch FAR uchf; -typedef unsigned short ush; -typedef ush FAR ushf; -typedef unsigned long ulg; - -extern char *z_errmsg[]; /* indexed by 1-zlib_error */ - -#define ERR_RETURN(strm,err) return (strm->msg=z_errmsg[1-err], err) -/* To be used only when the state is known to be valid */ - -#ifndef NULL -#define NULL ((void *) 0) -#endif - - /* common constants */ - -#define DEFLATED 8 - -#ifndef DEF_WBITS -# define DEF_WBITS MAX_WBITS -#endif -/* default windowBits for decompression. MAX_WBITS is for compression only */ - -#if MAX_MEM_LEVEL >= 8 -# define DEF_MEM_LEVEL 8 -#else -# define DEF_MEM_LEVEL MAX_MEM_LEVEL -#endif -/* default memLevel */ - -#define STORED_BLOCK 0 -#define STATIC_TREES 1 -#define DYN_TREES 2 -/* The three kinds of block type */ - -#define MIN_MATCH 3 -#define MAX_MATCH 258 -/* The minimum and maximum match lengths */ - - /* functions */ - -#include -#define zmemcpy memcpy -#define zmemzero(dest, len) memset(dest, 0, len) - -/* Diagnostic functions */ -#ifdef DEBUG_ZLIB -# include -# ifndef verbose -# define verbose 0 -# endif -# define Assert(cond,msg) {if(!(cond)) z_error(msg);} -# define Trace(x) fprintf x -# define Tracev(x) {if (verbose) fprintf x ;} -# define Tracevv(x) {if (verbose>1) fprintf x ;} -# define Tracec(c,x) {if (verbose && (c)) fprintf x ;} -# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} -#else -# define Assert(cond,msg) -# define Trace(x) -# define Tracev(x) -# define Tracevv(x) -# define Tracec(c,x) -# define Tracecv(c,x) -#endif - - -typedef uLong (*check_func) OF((uLong check, Bytef *buf, uInt len)); - -/* voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); */ -/* void zcfree OF((voidpf opaque, voidpf ptr)); */ - -#define ZALLOC(strm, items, size) \ - (*((strm)->zalloc))((strm)->opaque, (items), (size)) -#define ZFREE(strm, addr, size) \ - (*((strm)->zfree))((strm)->opaque, (voidpf)(addr), (size)) -#define TRY_FREE(s, p, n) {if (p) ZFREE(s, p, n);} - -/* deflate.h -- internal compression state - * Copyright (C) 1995 Jean-loup Gailly - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/*+++++*/ -/* infblock.h -- header to use infblock.c - * Copyright (C) 1995 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -struct inflate_blocks_state; -typedef struct inflate_blocks_state FAR inflate_blocks_statef; - -local inflate_blocks_statef * inflate_blocks_new OF(( - z_stream *z, - check_func c, /* check function */ - uInt w)); /* window size */ - -local int inflate_blocks OF(( - inflate_blocks_statef *, - z_stream *, - int)); /* initial return code */ - -local void inflate_blocks_reset OF(( - inflate_blocks_statef *, - z_stream *, - uLongf *)); /* check value on output */ - -local int inflate_blocks_free OF(( - inflate_blocks_statef *, - z_stream *, - uLongf *)); /* check value on output */ - -local int inflate_addhistory OF(( - inflate_blocks_statef *, - z_stream *)); - -local int inflate_packet_flush OF(( - inflate_blocks_statef *)); - -/*+++++*/ -/* inftrees.h -- header to use inftrees.c - * Copyright (C) 1995 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* Huffman code lookup table entry--this entry is four bytes for machines - that have 16-bit pointers (e.g. PC's in the small or medium model). */ - -typedef struct inflate_huft_s FAR inflate_huft; - -struct inflate_huft_s { - union { - struct { - Byte Exop; /* number of extra bits or operation */ - Byte Bits; /* number of bits in this code or subcode */ - } what; - uInt Nalloc; /* number of these allocated here */ - Bytef *pad; /* pad structure to a power of 2 (4 bytes for */ - } word; /* 16-bit, 8 bytes for 32-bit machines) */ - union { - uInt Base; /* literal, length base, or distance base */ - inflate_huft *Next; /* pointer to next level of table */ - } more; -}; - -#ifdef DEBUG_ZLIB - local uInt inflate_hufts; -#endif - -local int inflate_trees_bits OF(( - uIntf *, /* 19 code lengths */ - uIntf *, /* bits tree desired/actual depth */ - inflate_huft * FAR *, /* bits tree result */ - z_stream *)); /* for zalloc, zfree functions */ - -local int inflate_trees_dynamic OF(( - uInt, /* number of literal/length codes */ - uInt, /* number of distance codes */ - uIntf *, /* that many (total) code lengths */ - uIntf *, /* literal desired/actual bit depth */ - uIntf *, /* distance desired/actual bit depth */ - inflate_huft * FAR *, /* literal/length tree result */ - inflate_huft * FAR *, /* distance tree result */ - z_stream *)); /* for zalloc, zfree functions */ - -local int inflate_trees_fixed OF(( - uIntf *, /* literal desired/actual bit depth */ - uIntf *, /* distance desired/actual bit depth */ - inflate_huft * FAR *, /* literal/length tree result */ - inflate_huft * FAR *)); /* distance tree result */ - -local int inflate_trees_free OF(( - inflate_huft *, /* tables to free */ - z_stream *)); /* for zfree function */ - - -/*+++++*/ -/* infcodes.h -- header to use infcodes.c - * Copyright (C) 1995 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -struct inflate_codes_state; -typedef struct inflate_codes_state FAR inflate_codes_statef; - -local inflate_codes_statef *inflate_codes_new OF(( - uInt, uInt, - inflate_huft *, inflate_huft *, - z_stream *)); - -local int inflate_codes OF(( - inflate_blocks_statef *, - z_stream *, - int)); - -local void inflate_codes_free OF(( - inflate_codes_statef *, - z_stream *)); - - -/*+++++*/ -/* inflate.c -- zlib interface to inflate modules - * Copyright (C) 1995 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* inflate private state */ -struct internal_state { - - /* mode */ - enum { - METHOD, /* waiting for method byte */ - FLAG, /* waiting for flag byte */ - BLOCKS, /* decompressing blocks */ - CHECK4, /* four check bytes to go */ - CHECK3, /* three check bytes to go */ - CHECK2, /* two check bytes to go */ - CHECK1, /* one check byte to go */ - DONE, /* finished check, done */ - BAD} /* got an error--stay here */ - mode; /* current inflate mode */ - - /* mode dependent information */ - union { - uInt method; /* if FLAGS, method byte */ - struct { - uLong was; /* computed check value */ - uLong need; /* stream check value */ - } check; /* if CHECK, check values to compare */ - uInt marker; /* if BAD, inflateSync's marker bytes count */ - } sub; /* submode */ - - /* mode independent information */ - int nowrap; /* flag for no wrapper */ - uInt wbits; /* log2(window size) (8..15, defaults to 15) */ - inflate_blocks_statef - *blocks; /* current inflate_blocks state */ - -}; - - -int inflateReset(z) -z_stream *z; -{ - uLong c; - - if (z == Z_NULL || z->state == Z_NULL) - return Z_STREAM_ERROR; - z->total_in = z->total_out = 0; - z->msg = Z_NULL; - z->state->mode = z->state->nowrap ? BLOCKS : METHOD; - inflate_blocks_reset(z->state->blocks, z, &c); - Trace((stderr, "inflate: reset\n")); - return Z_OK; -} - - -int inflateEnd(z) -z_stream *z; -{ - uLong c; - - if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL) - return Z_STREAM_ERROR; - if (z->state->blocks != Z_NULL) - inflate_blocks_free(z->state->blocks, z, &c); - ZFREE(z, z->state, sizeof(struct internal_state)); - z->state = Z_NULL; - Trace((stderr, "inflate: end\n")); - return Z_OK; -} - - -int inflateInit2(z, w) -z_stream *z; -int w; -{ - /* initialize state */ - if (z == Z_NULL) - return Z_STREAM_ERROR; -/* if (z->zalloc == Z_NULL) z->zalloc = zcalloc; */ -/* if (z->zfree == Z_NULL) z->zfree = zcfree; */ - if ((z->state = (struct internal_state FAR *) - ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL) - return Z_MEM_ERROR; - z->state->blocks = Z_NULL; - - /* handle undocumented nowrap option (no zlib header or check) */ - z->state->nowrap = 0; - if (w < 0) - { - w = - w; - z->state->nowrap = 1; - } - - /* set window size */ - if (w < 8 || w > 15) - { - inflateEnd(z); - return Z_STREAM_ERROR; - } - z->state->wbits = (uInt)w; - - /* create inflate_blocks state */ - if ((z->state->blocks = - inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, 1 << w)) - == Z_NULL) - { - inflateEnd(z); - return Z_MEM_ERROR; - } - Trace((stderr, "inflate: allocated\n")); - - /* reset state */ - inflateReset(z); - return Z_OK; -} - - -int inflateInit(z) -z_stream *z; -{ - return inflateInit2(z, DEF_WBITS); -} - - -#define NEEDBYTE {if(z->avail_in==0)goto empty;r=Z_OK;} -#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++) - -int inflate(z, f) -z_stream *z; -int f; -{ - int r; - uInt b; - - if (z == Z_NULL || z->next_in == Z_NULL) - return Z_STREAM_ERROR; - r = Z_BUF_ERROR; - while (1) switch (z->state->mode) - { - case METHOD: - NEEDBYTE - if (((z->state->sub.method = NEXTBYTE) & 0xf) != DEFLATED) - { - z->state->mode = BAD; - z->msg = "unknown compression method"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - if ((z->state->sub.method >> 4) + 8 > z->state->wbits) - { - z->state->mode = BAD; - z->msg = "invalid window size"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - z->state->mode = FLAG; - case FLAG: - NEEDBYTE - if ((b = NEXTBYTE) & 0x20) - { - z->state->mode = BAD; - z->msg = "invalid reserved bit"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - if (((z->state->sub.method << 8) + b) % 31) - { - z->state->mode = BAD; - z->msg = "incorrect header check"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - Trace((stderr, "inflate: zlib header ok\n")); - z->state->mode = BLOCKS; - case BLOCKS: - r = inflate_blocks(z->state->blocks, z, r); - if (f == Z_PACKET_FLUSH && z->avail_in == 0 && z->avail_out != 0) - r = inflate_packet_flush(z->state->blocks); - if (r == Z_DATA_ERROR) - { - z->state->mode = BAD; - z->state->sub.marker = 0; /* can try inflateSync */ - break; - } - if (r != Z_STREAM_END) - return r; - r = Z_OK; - inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was); - if (z->state->nowrap) - { - z->state->mode = DONE; - break; - } - z->state->mode = CHECK4; - case CHECK4: - NEEDBYTE - z->state->sub.check.need = (uLong)NEXTBYTE << 24; - z->state->mode = CHECK3; - case CHECK3: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE << 16; - z->state->mode = CHECK2; - case CHECK2: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE << 8; - z->state->mode = CHECK1; - case CHECK1: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE; - - if (z->state->sub.check.was != z->state->sub.check.need) - { - z->state->mode = BAD; - z->msg = "incorrect data check"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - Trace((stderr, "inflate: zlib check ok\n")); - z->state->mode = DONE; - case DONE: - return Z_STREAM_END; - case BAD: - return Z_DATA_ERROR; - default: - return Z_STREAM_ERROR; - } - - empty: - if (f != Z_PACKET_FLUSH) - return r; - z->state->mode = BAD; - z->state->sub.marker = 0; /* can try inflateSync */ - return Z_DATA_ERROR; -} - -/* - * This subroutine adds the data at next_in/avail_in to the output history - * without performing any output. The output buffer must be "caught up"; - * i.e. no pending output (hence s->read equals s->write), and the state must - * be BLOCKS (i.e. we should be willing to see the start of a series of - * BLOCKS). On exit, the output will also be caught up, and the checksum - * will have been updated if need be. - */ - -int inflateIncomp(z) -z_stream *z; -{ - if (z->state->mode != BLOCKS) - return Z_DATA_ERROR; - return inflate_addhistory(z->state->blocks, z); -} - - -int inflateSync(z) -z_stream *z; -{ - uInt n; /* number of bytes to look at */ - Bytef *p; /* pointer to bytes */ - uInt m; /* number of marker bytes found in a row */ - uLong r, w; /* temporaries to save total_in and total_out */ - - /* set up */ - if (z == Z_NULL || z->state == Z_NULL) - return Z_STREAM_ERROR; - if (z->state->mode != BAD) - { - z->state->mode = BAD; - z->state->sub.marker = 0; - } - if ((n = z->avail_in) == 0) - return Z_BUF_ERROR; - p = z->next_in; - m = z->state->sub.marker; - - /* search */ - while (n && m < 4) - { - if (*p == (Byte)(m < 2 ? 0 : 0xff)) - m++; - else if (*p) - m = 0; - else - m = 4 - m; - p++, n--; - } - - /* restore */ - z->total_in += p - z->next_in; - z->next_in = p; - z->avail_in = n; - z->state->sub.marker = m; - - /* return no joy or set up to restart on a new block */ - if (m != 4) - return Z_DATA_ERROR; - r = z->total_in; w = z->total_out; - inflateReset(z); - z->total_in = r; z->total_out = w; - z->state->mode = BLOCKS; - return Z_OK; -} - -#undef NEEDBYTE -#undef NEXTBYTE - -/*+++++*/ -/* infutil.h -- types and macros common to blocks and codes - * Copyright (C) 1995 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* inflate blocks semi-private state */ -struct inflate_blocks_state { - - /* mode */ - enum { - TYPE, /* get type bits (3, including end bit) */ - LENS, /* get lengths for stored */ - STORED, /* processing stored block */ - TABLE, /* get table lengths */ - BTREE, /* get bit lengths tree for a dynamic block */ - DTREE, /* get length, distance trees for a dynamic block */ - CODES, /* processing fixed or dynamic block */ - DRY, /* output remaining window bytes */ - DONEB, /* finished last block, done */ - BADB} /* got a data error--stuck here */ - mode; /* current inflate_block mode */ - - /* mode dependent information */ - union { - uInt left; /* if STORED, bytes left to copy */ - struct { - uInt table; /* table lengths (14 bits) */ - uInt index; /* index into blens (or border) */ - uIntf *blens; /* bit lengths of codes */ - uInt bb; /* bit length tree depth */ - inflate_huft *tb; /* bit length decoding tree */ - int nblens; /* # elements allocated at blens */ - } trees; /* if DTREE, decoding info for trees */ - struct { - inflate_huft *tl, *td; /* trees to free */ - inflate_codes_statef - *codes; - } decode; /* if CODES, current state */ - } sub; /* submode */ - uInt last; /* true if this block is the last block */ - - /* mode independent information */ - uInt bitk; /* bits in bit buffer */ - uLong bitb; /* bit buffer */ - Bytef *window; /* sliding window */ - Bytef *end; /* one byte after sliding window */ - Bytef *read; /* window read pointer */ - Bytef *write; /* window write pointer */ - check_func checkfn; /* check function */ - uLong check; /* check on output */ - -}; - - -/* defines for inflate input/output */ -/* update pointers and return */ -#define UPDBITS {s->bitb=b;s->bitk=k;} -#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;} -#define UPDOUT {s->write=q;} -#define UPDATE {UPDBITS UPDIN UPDOUT} -#define LEAVE {UPDATE return inflate_flush(s,z,r);} -/* get bytes and bits */ -#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;} -#define NEEDBYTE {if(n)r=Z_OK;else LEAVE} -#define NEXTBYTE (n--,*p++) -#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<>=(j);k-=(j);} -/* output bytes */ -#define WAVAIL (qread?s->read-q-1:s->end-q) -#define LOADOUT {q=s->write;m=WAVAIL;} -#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=WAVAIL;}} -#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT} -#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;} -#define OUTBYTE(a) {*q++=(Byte)(a);m--;} -/* load local pointers */ -#define LOAD {LOADIN LOADOUT} - -/* And'ing with mask[n] masks the lower n bits */ -local uInt inflate_mask[] = { - 0x0000, - 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, - 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff -}; - -/* copy as much as possible from the sliding window to the output area */ -local int inflate_flush OF(( - inflate_blocks_statef *, - z_stream *, - int)); - -/*+++++*/ -/* inffast.h -- header to use inffast.c - * Copyright (C) 1995 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -local int inflate_fast OF(( - uInt, - uInt, - inflate_huft *, - inflate_huft *, - inflate_blocks_statef *, - z_stream *)); - - -/*+++++*/ -/* infblock.c -- interpret and process block types to last block - * Copyright (C) 1995 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* Table for deflate from PKZIP's appnote.txt. */ -local uInt border[] = { /* Order of the bit length code lengths */ - 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - -/* - Notes beyond the 1.93a appnote.txt: - - 1. Distance pointers never point before the beginning of the output - stream. - 2. Distance pointers can point back across blocks, up to 32k away. - 3. There is an implied maximum of 7 bits for the bit length table and - 15 bits for the actual data. - 4. If only one code exists, then it is encoded using one bit. (Zero - would be more efficient, but perhaps a little confusing.) If two - codes exist, they are coded using one bit each (0 and 1). - 5. There is no way of sending zero distance codes--a dummy must be - sent if there are none. (History: a pre 2.0 version of PKZIP would - store blocks with no distance codes, but this was discovered to be - too harsh a criterion.) Valid only for 1.93a. 2.04c does allow - zero distance codes, which is sent as one code of zero bits in - length. - 6. There are up to 286 literal/length codes. Code 256 represents the - end-of-block. Note however that the static length tree defines - 288 codes just to fill out the Huffman codes. Codes 286 and 287 - cannot be used though, since there is no length base or extra bits - defined for them. Similarily, there are up to 30 distance codes. - However, static trees define 32 codes (all 5 bits) to fill out the - Huffman codes, but the last two had better not show up in the data. - 7. Unzip can check dynamic Huffman blocks for complete code sets. - The exception is that a single code would not be complete (see #4). - 8. The five bits following the block type is really the number of - literal codes sent minus 257. - 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits - (1+6+6). Therefore, to output three times the length, you output - three codes (1+1+1), whereas to output four times the same length, - you only need two codes (1+3). Hmm. - 10. In the tree reconstruction algorithm, Code = Code + Increment - only if BitLength(i) is not zero. (Pretty obvious.) - 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) - 12. Note: length code 284 can represent 227-258, but length code 285 - really is 258. The last length deserves its own, short code - since it gets used a lot in very redundant files. The length - 258 is special since 258 - 3 (the min match length) is 255. - 13. The literal/length and distance code bit lengths are read as a - single stream of lengths. It is possible (and advantageous) for - a repeat code (16, 17, or 18) to go across the boundary between - the two sets of lengths. - */ - - -local void inflate_blocks_reset(s, z, c) -inflate_blocks_statef *s; -z_stream *z; -uLongf *c; -{ - if (s->checkfn != Z_NULL) - *c = s->check; - if (s->mode == BTREE || s->mode == DTREE) - ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt)); - if (s->mode == CODES) - { - inflate_codes_free(s->sub.decode.codes, z); - inflate_trees_free(s->sub.decode.td, z); - inflate_trees_free(s->sub.decode.tl, z); - } - s->mode = TYPE; - s->bitk = 0; - s->bitb = 0; - s->read = s->write = s->window; - if (s->checkfn != Z_NULL) - s->check = (*s->checkfn)(0L, Z_NULL, 0); - Trace((stderr, "inflate: blocks reset\n")); -} - - -local inflate_blocks_statef *inflate_blocks_new(z, c, w) -z_stream *z; -check_func c; -uInt w; -{ - inflate_blocks_statef *s; - - if ((s = (inflate_blocks_statef *)ZALLOC - (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL) - return s; - if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL) - { - ZFREE(z, s, sizeof(struct inflate_blocks_state)); - return Z_NULL; - } - s->end = s->window + w; - s->checkfn = c; - s->mode = TYPE; - Trace((stderr, "inflate: blocks allocated\n")); - inflate_blocks_reset(s, z, &s->check); - return s; -} - - -local int inflate_blocks(s, z, r) -inflate_blocks_statef *s; -z_stream *z; -int r; -{ - uInt t; /* temporary storage */ - uLong b; /* bit buffer */ - uInt k; /* bits in bit buffer */ - Bytef *p; /* input data pointer */ - uInt n; /* bytes available there */ - Bytef *q; /* output window write pointer */ - uInt m; /* bytes to end of window or read pointer */ - - /* copy input/output information to locals (UPDATE macro restores) */ - LOAD - - /* process input based on current state */ - while (1) switch (s->mode) - { - case TYPE: - NEEDBITS(3) - t = (uInt)b & 7; - s->last = t & 1; - switch (t >> 1) - { - case 0: /* stored */ - Trace((stderr, "inflate: stored block%s\n", - s->last ? " (last)" : "")); - DUMPBITS(3) - t = k & 7; /* go to byte boundary */ - DUMPBITS(t) - s->mode = LENS; /* get length of stored block */ - break; - case 1: /* fixed */ - Trace((stderr, "inflate: fixed codes block%s\n", - s->last ? " (last)" : "")); - { - uInt bl, bd; - inflate_huft *tl, *td; - - inflate_trees_fixed(&bl, &bd, &tl, &td); - s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z); - if (s->sub.decode.codes == Z_NULL) - { - r = Z_MEM_ERROR; - LEAVE - } - s->sub.decode.tl = Z_NULL; /* don't try to free these */ - s->sub.decode.td = Z_NULL; - } - DUMPBITS(3) - s->mode = CODES; - break; - case 2: /* dynamic */ - Trace((stderr, "inflate: dynamic codes block%s\n", - s->last ? " (last)" : "")); - DUMPBITS(3) - s->mode = TABLE; - break; - case 3: /* illegal */ - DUMPBITS(3) - s->mode = BADB; - z->msg = "invalid block type"; - r = Z_DATA_ERROR; - LEAVE - } - break; - case LENS: - NEEDBITS(32) - if (((~b) >> 16) != (b & 0xffff)) - { - s->mode = BADB; - z->msg = "invalid stored block lengths"; - r = Z_DATA_ERROR; - LEAVE - } - s->sub.left = (uInt)b & 0xffff; - b = k = 0; /* dump bits */ - Tracev((stderr, "inflate: stored length %u\n", s->sub.left)); - s->mode = s->sub.left ? STORED : TYPE; - break; - case STORED: - if (n == 0) - LEAVE - NEEDOUT - t = s->sub.left; - if (t > n) t = n; - if (t > m) t = m; - zmemcpy(q, p, t); - p += t; n -= t; - q += t; m -= t; - if ((s->sub.left -= t) != 0) - break; - Tracev((stderr, "inflate: stored end, %lu total out\n", - z->total_out + (q >= s->read ? q - s->read : - (s->end - s->read) + (q - s->window)))); - s->mode = s->last ? DRY : TYPE; - break; - case TABLE: - NEEDBITS(14) - s->sub.trees.table = t = (uInt)b & 0x3fff; -#ifndef PKZIP_BUG_WORKAROUND - if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) - { - s->mode = BADB; - z->msg = "too many length or distance symbols"; - r = Z_DATA_ERROR; - LEAVE - } -#endif - t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); - if (t < 19) - t = 19; - if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL) - { - r = Z_MEM_ERROR; - LEAVE - } - s->sub.trees.nblens = t; - DUMPBITS(14) - s->sub.trees.index = 0; - Tracev((stderr, "inflate: table sizes ok\n")); - s->mode = BTREE; - case BTREE: - while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10)) - { - NEEDBITS(3) - s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7; - DUMPBITS(3) - } - while (s->sub.trees.index < 19) - s->sub.trees.blens[border[s->sub.trees.index++]] = 0; - s->sub.trees.bb = 7; - t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb, - &s->sub.trees.tb, z); - if (t != Z_OK) - { - r = t; - if (r == Z_DATA_ERROR) - s->mode = BADB; - LEAVE - } - s->sub.trees.index = 0; - Tracev((stderr, "inflate: bits tree ok\n")); - s->mode = DTREE; - case DTREE: - while (t = s->sub.trees.table, - s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)) - { - inflate_huft *h; - uInt i, j, c; - - t = s->sub.trees.bb; - NEEDBITS(t) - h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]); - t = h->word.what.Bits; - c = h->more.Base; - if (c < 16) - { - DUMPBITS(t) - s->sub.trees.blens[s->sub.trees.index++] = c; - } - else /* c == 16..18 */ - { - i = c == 18 ? 7 : c - 14; - j = c == 18 ? 11 : 3; - NEEDBITS(t + i) - DUMPBITS(t) - j += (uInt)b & inflate_mask[i]; - DUMPBITS(i) - i = s->sub.trees.index; - t = s->sub.trees.table; - if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || - (c == 16 && i < 1)) - { - s->mode = BADB; - z->msg = "invalid bit length repeat"; - r = Z_DATA_ERROR; - LEAVE - } - c = c == 16 ? s->sub.trees.blens[i - 1] : 0; - do { - s->sub.trees.blens[i++] = c; - } while (--j); - s->sub.trees.index = i; - } - } - inflate_trees_free(s->sub.trees.tb, z); - s->sub.trees.tb = Z_NULL; - { - uInt bl, bd; - inflate_huft *tl, *td; - inflate_codes_statef *c; - - bl = 9; /* must be <= 9 for lookahead assumptions */ - bd = 6; /* must be <= 9 for lookahead assumptions */ - t = s->sub.trees.table; - t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), - s->sub.trees.blens, &bl, &bd, &tl, &td, z); - if (t != Z_OK) - { - if (t == (uInt)Z_DATA_ERROR) - s->mode = BADB; - r = t; - LEAVE - } - Tracev((stderr, "inflate: trees ok\n")); - if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL) - { - inflate_trees_free(td, z); - inflate_trees_free(tl, z); - r = Z_MEM_ERROR; - LEAVE - } - ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt)); - s->sub.decode.codes = c; - s->sub.decode.tl = tl; - s->sub.decode.td = td; - } - s->mode = CODES; - case CODES: - UPDATE - if ((r = inflate_codes(s, z, r)) != Z_STREAM_END) - return inflate_flush(s, z, r); - r = Z_OK; - inflate_codes_free(s->sub.decode.codes, z); - inflate_trees_free(s->sub.decode.td, z); - inflate_trees_free(s->sub.decode.tl, z); - LOAD - Tracev((stderr, "inflate: codes end, %lu total out\n", - z->total_out + (q >= s->read ? q - s->read : - (s->end - s->read) + (q - s->window)))); - if (!s->last) - { - s->mode = TYPE; - break; - } - if (k > 7) /* return unused byte, if any */ - { - Assert(k < 16, "inflate_codes grabbed too many bytes") - k -= 8; - n++; - p--; /* can always return one */ - } - s->mode = DRY; - case DRY: - FLUSH - if (s->read != s->write) - LEAVE - s->mode = DONEB; - case DONEB: - r = Z_STREAM_END; - LEAVE - case BADB: - r = Z_DATA_ERROR; - LEAVE - default: - r = Z_STREAM_ERROR; - LEAVE - } -} - - -local int inflate_blocks_free(s, z, c) -inflate_blocks_statef *s; -z_stream *z; -uLongf *c; -{ - inflate_blocks_reset(s, z, c); - ZFREE(z, s->window, s->end - s->window); - ZFREE(z, s, sizeof(struct inflate_blocks_state)); - Trace((stderr, "inflate: blocks freed\n")); - return Z_OK; -} - -/* - * This subroutine adds the data at next_in/avail_in to the output history - * without performing any output. The output buffer must be "caught up"; - * i.e. no pending output (hence s->read equals s->write), and the state must - * be BLOCKS (i.e. we should be willing to see the start of a series of - * BLOCKS). On exit, the output will also be caught up, and the checksum - * will have been updated if need be. - */ -local int inflate_addhistory(s, z) -inflate_blocks_statef *s; -z_stream *z; -{ - uLong b; /* bit buffer */ /* NOT USED HERE */ - uInt k; /* bits in bit buffer */ /* NOT USED HERE */ - uInt t; /* temporary storage */ - Bytef *p; /* input data pointer */ - uInt n; /* bytes available there */ - Bytef *q; /* output window write pointer */ - uInt m; /* bytes to end of window or read pointer */ - - if (s->read != s->write) - return Z_STREAM_ERROR; - if (s->mode != TYPE) - return Z_DATA_ERROR; - - /* we're ready to rock */ - LOAD - /* while there is input ready, copy to output buffer, moving - * pointers as needed. - */ - while (n) { - t = n; /* how many to do */ - /* is there room until end of buffer? */ - if (t > m) t = m; - /* update check information */ - if (s->checkfn != Z_NULL) - s->check = (*s->checkfn)(s->check, q, t); - zmemcpy(q, p, t); - q += t; - p += t; - n -= t; - z->total_out += t; - s->read = q; /* drag read pointer forward */ -/* WRAP */ /* expand WRAP macro by hand to handle s->read */ - if (q == s->end) { - s->read = q = s->window; - m = WAVAIL; - } - } - UPDATE - return Z_OK; -} - - -/* - * At the end of a Deflate-compressed PPP packet, we expect to have seen - * a `stored' block type value but not the (zero) length bytes. - */ -local int inflate_packet_flush(s) - inflate_blocks_statef *s; -{ - if (s->mode != LENS) - return Z_DATA_ERROR; - s->mode = TYPE; - return Z_OK; -} - - -/*+++++*/ -/* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* simplify the use of the inflate_huft type with some defines */ -#define base more.Base -#define next more.Next -#define exop word.what.Exop -#define bits word.what.Bits - - -local int huft_build OF(( - uIntf *, /* code lengths in bits */ - uInt, /* number of codes */ - uInt, /* number of "simple" codes */ - uIntf *, /* list of base values for non-simple codes */ - uIntf *, /* list of extra bits for non-simple codes */ - inflate_huft * FAR*,/* result: starting table */ - uIntf *, /* maximum lookup bits (returns actual) */ - z_stream *)); /* for zalloc function */ - -local voidpf falloc OF(( - voidpf, /* opaque pointer (not used) */ - uInt, /* number of items */ - uInt)); /* size of item */ - -local void ffree OF(( - voidpf q, /* opaque pointer (not used) */ - voidpf p, /* what to free (not used) */ - uInt n)); /* number of bytes (not used) */ - -/* Tables for deflate from PKZIP's appnote.txt. */ -local uInt cplens[] = { /* Copy lengths for literal codes 257..285 */ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; - /* actually lengths - 2; also see note #13 above about 258 */ -local uInt cplext[] = { /* Extra bits for literal codes 257..285 */ - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, - 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 192, 192}; /* 192==invalid */ -local uInt cpdist[] = { /* Copy offsets for distance codes 0..29 */ - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577}; -local uInt cpdext[] = { /* Extra bits for distance codes */ - 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, - 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, - 12, 12, 13, 13}; - -/* - Huffman code decoding is performed using a multi-level table lookup. - The fastest way to decode is to simply build a lookup table whose - size is determined by the longest code. However, the time it takes - to build this table can also be a factor if the data being decoded - is not very long. The most common codes are necessarily the - shortest codes, so those codes dominate the decoding time, and hence - the speed. The idea is you can have a shorter table that decodes the - shorter, more probable codes, and then point to subsidiary tables for - the longer codes. The time it costs to decode the longer codes is - then traded against the time it takes to make longer tables. - - This results of this trade are in the variables lbits and dbits - below. lbits is the number of bits the first level table for literal/ - length codes can decode in one step, and dbits is the same thing for - the distance codes. Subsequent tables are also less than or equal to - those sizes. These values may be adjusted either when all of the - codes are shorter than that, in which case the longest code length in - bits is used, or when the shortest code is *longer* than the requested - table size, in which case the length of the shortest code in bits is - used. - - There are two different values for the two tables, since they code a - different number of possibilities each. The literal/length table - codes 286 possible values, or in a flat code, a little over eight - bits. The distance table codes 30 possible values, or a little less - than five bits, flat. The optimum values for speed end up being - about one bit more than those, so lbits is 8+1 and dbits is 5+1. - The optimum values may differ though from machine to machine, and - possibly even between compilers. Your mileage may vary. - */ - - -/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */ -#define BMAX 15 /* maximum bit length of any code */ -#define N_MAX 288 /* maximum number of codes in any set */ - -#ifdef DEBUG_ZLIB - uInt inflate_hufts; -#endif - -local int huft_build(b, n, s, d, e, t, m, zs) -uIntf *b; /* code lengths in bits (all assumed <= BMAX) */ -uInt n; /* number of codes (assumed <= N_MAX) */ -uInt s; /* number of simple-valued codes (0..s-1) */ -uIntf *d; /* list of base values for non-simple codes */ -uIntf *e; /* list of extra bits for non-simple codes */ -inflate_huft * FAR *t; /* result: starting table */ -uIntf *m; /* maximum lookup bits, returns actual */ -z_stream *zs; /* for zalloc function */ -/* Given a list of code lengths and a maximum table size, make a set of - tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR - if the given code set is incomplete (the tables are still built in this - case), Z_DATA_ERROR if the input is invalid (all zero length codes or an - over-subscribed set of lengths), or Z_MEM_ERROR if not enough memory. */ -{ - - uInt a; /* counter for codes of length k */ - uInt c[BMAX+1]; /* bit length count table */ - uInt f; /* i repeats in table every f entries */ - int g; /* maximum code length */ - int h; /* table level */ - register uInt i; /* counter, current code */ - register uInt j; /* counter */ - register int k; /* number of bits in current code */ - int l; /* bits per table (returned in m) */ - register uIntf *p; /* pointer into c[], b[], or v[] */ - inflate_huft *q; /* points to current table */ - struct inflate_huft_s r; /* table entry for structure assignment */ - inflate_huft *u[BMAX]; /* table stack */ - uInt v[N_MAX]; /* values in order of bit length */ - register int w; /* bits before this table == (l * h) */ - uInt x[BMAX+1]; /* bit offsets, then code stack */ - uIntf *xp; /* pointer into x */ - int y; /* number of dummy codes added */ - uInt z; /* number of entries in current table */ - - - /* Generate counts for each bit length */ - p = c; -#define C0 *p++ = 0; -#define C2 C0 C0 C0 C0 -#define C4 C2 C2 C2 C2 - C4 /* clear c[]--assume BMAX+1 is 16 */ - p = b; i = n; - do { - c[*p++]++; /* assume all entries <= BMAX */ - } while (--i); - if (c[0] == n) /* null input--all zero length codes */ - { - *t = (inflate_huft *)Z_NULL; - *m = 0; - return Z_OK; - } - - - /* Find minimum and maximum length, bound *m by those */ - l = *m; - for (j = 1; j <= BMAX; j++) - if (c[j]) - break; - k = j; /* minimum code length */ - if ((uInt)l < j) - l = j; - for (i = BMAX; i; i--) - if (c[i]) - break; - g = i; /* maximum code length */ - if ((uInt)l > i) - l = i; - *m = l; - - - /* Adjust last length count to fill out codes, if needed */ - for (y = 1 << j; j < i; j++, y <<= 1) - if ((y -= c[j]) < 0) - return Z_DATA_ERROR; - if ((y -= c[i]) < 0) - return Z_DATA_ERROR; - c[i] += y; - - - /* Generate starting offsets into the value table for each length */ - x[1] = j = 0; - p = c + 1; xp = x + 2; - while (--i) { /* note that i == g from above */ - *xp++ = (j += *p++); - } - - - /* Make a table of values in order of bit lengths */ - p = b; i = 0; - do { - if ((j = *p++) != 0) - v[x[j]++] = i; - } while (++i < n); - - - /* Generate the Huffman codes and for each, make the table entries */ - x[0] = i = 0; /* first Huffman code is zero */ - p = v; /* grab values in bit order */ - h = -1; /* no tables yet--level -1 */ - w = -l; /* bits decoded == (l * h) */ - u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */ - q = (inflate_huft *)Z_NULL; /* ditto */ - z = 0; /* ditto */ - - /* go through the bit lengths (k already is bits in shortest code) */ - for (; k <= g; k++) - { - a = c[k]; - while (a--) - { - /* here i is the Huffman code of length k bits for value *p */ - /* make tables up to required level */ - while (k > w + l) - { - h++; - w += l; /* previous table always l bits */ - - /* compute minimum size table less than or equal to l bits */ - z = (z = g - w) > (uInt)l ? l : z; /* table size upper limit */ - if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ - { /* too few codes for k-w bit table */ - f -= a + 1; /* deduct codes from patterns left */ - xp = c + k; - if (j < z) - while (++j < z) /* try smaller tables up to z bits */ - { - if ((f <<= 1) <= *++xp) - break; /* enough codes to use up j bits */ - f -= *xp; /* else deduct codes from patterns */ - } - } - z = 1 << j; /* table entries for j-bit table */ - - /* allocate and link in new table */ - if ((q = (inflate_huft *)ZALLOC - (zs,z + 1,sizeof(inflate_huft))) == Z_NULL) - { - if (h) - inflate_trees_free(u[0], zs); - return Z_MEM_ERROR; /* not enough memory */ - } - q->word.Nalloc = z + 1; -#ifdef DEBUG_ZLIB - inflate_hufts += z + 1; -#endif - *t = q + 1; /* link to list for huft_free() */ - *(t = &(q->next)) = Z_NULL; - u[h] = ++q; /* table starts after link */ - - /* connect to last table, if there is one */ - if (h) - { - x[h] = i; /* save pattern for backing up */ - r.bits = (Byte)l; /* bits to dump before this table */ - r.exop = (Byte)j; /* bits in this table */ - r.next = q; /* pointer to this table */ - j = i >> (w - l); /* (get around Turbo C bug) */ - u[h-1][j] = r; /* connect to last table */ - } - } - - /* set up table entry in r */ - r.bits = (Byte)(k - w); - if (p >= v + n) - r.exop = 128 + 64; /* out of values--invalid code */ - else if (*p < s) - { - r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */ - r.base = *p++; /* simple code is just the value */ - } - else - { - r.exop = (Byte)e[*p - s] + 16 + 64; /* non-simple--look up in lists */ - r.base = d[*p++ - s]; - } - - /* fill code-like entries with r */ - f = 1 << (k - w); - for (j = i >> w; j < z; j += f) - q[j] = r; - - /* backwards increment the k-bit code i */ - for (j = 1 << (k - 1); i & j; j >>= 1) - i ^= j; - i ^= j; - - /* backup over finished tables */ - while ((i & ((1 << w) - 1)) != x[h]) - { - h--; /* don't need to update q */ - w -= l; - } - } - } - - - /* Return Z_BUF_ERROR if we were given an incomplete table */ - return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK; -} - - -local int inflate_trees_bits(c, bb, tb, z) -uIntf *c; /* 19 code lengths */ -uIntf *bb; /* bits tree desired/actual depth */ -inflate_huft * FAR *tb; /* bits tree result */ -z_stream *z; /* for zfree function */ -{ - int r; - - r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, tb, bb, z); - if (r == Z_DATA_ERROR) - z->msg = "oversubscribed dynamic bit lengths tree"; - else if (r == Z_BUF_ERROR) - { - inflate_trees_free(*tb, z); - z->msg = "incomplete dynamic bit lengths tree"; - r = Z_DATA_ERROR; - } - return r; -} - - -local int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, z) -uInt nl; /* number of literal/length codes */ -uInt nd; /* number of distance codes */ -uIntf *c; /* that many (total) code lengths */ -uIntf *bl; /* literal desired/actual bit depth */ -uIntf *bd; /* distance desired/actual bit depth */ -inflate_huft * FAR *tl; /* literal/length tree result */ -inflate_huft * FAR *td; /* distance tree result */ -z_stream *z; /* for zfree function */ -{ - int r; - - /* build literal/length tree */ - if ((r = huft_build(c, nl, 257, cplens, cplext, tl, bl, z)) != Z_OK) - { - if (r == Z_DATA_ERROR) - z->msg = "oversubscribed literal/length tree"; - else if (r == Z_BUF_ERROR) - { - inflate_trees_free(*tl, z); - z->msg = "incomplete literal/length tree"; - r = Z_DATA_ERROR; - } - return r; - } - - /* build distance tree */ - if ((r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, z)) != Z_OK) - { - if (r == Z_DATA_ERROR) - z->msg = "oversubscribed literal/length tree"; - else if (r == Z_BUF_ERROR) { -#ifdef PKZIP_BUG_WORKAROUND - r = Z_OK; - } -#else - inflate_trees_free(*td, z); - z->msg = "incomplete literal/length tree"; - r = Z_DATA_ERROR; - } - inflate_trees_free(*tl, z); - return r; -#endif - } - - /* done */ - return Z_OK; -} - - -/* build fixed tables only once--keep them here */ -local int fixed_lock = 0; -local int fixed_built = 0; -#define FIXEDH 530 /* number of hufts used by fixed tables */ -local uInt fixed_left = FIXEDH; -local inflate_huft fixed_mem[FIXEDH]; -local uInt fixed_bl; -local uInt fixed_bd; -local inflate_huft *fixed_tl; -local inflate_huft *fixed_td; - - -local voidpf falloc(q, n, s) -voidpf q; /* opaque pointer (not used) */ -uInt n; /* number of items */ -uInt s; /* size of item */ -{ - Assert(s == sizeof(inflate_huft) && n <= fixed_left, - "inflate_trees falloc overflow"); - if (q) s++; /* to make some compilers happy */ - fixed_left -= n; - return (voidpf)(fixed_mem + fixed_left); -} - - -local void ffree(q, p, n) -voidpf q; -voidpf p; -uInt n; -{ - Assert(0, "inflate_trees ffree called!"); - if (q) q = p; /* to make some compilers happy */ -} - - -local int inflate_trees_fixed(bl, bd, tl, td) -uIntf *bl; /* literal desired/actual bit depth */ -uIntf *bd; /* distance desired/actual bit depth */ -inflate_huft * FAR *tl; /* literal/length tree result */ -inflate_huft * FAR *td; /* distance tree result */ -{ - /* build fixed tables if not built already--lock out other instances */ - while (++fixed_lock > 1) - fixed_lock--; - if (!fixed_built) - { - int k; /* temporary variable */ - unsigned c[288]; /* length list for huft_build */ - z_stream z; /* for falloc function */ - - /* set up fake z_stream for memory routines */ - z.zalloc = falloc; - z.zfree = ffree; - z.opaque = Z_NULL; - - /* literal table */ - for (k = 0; k < 144; k++) - c[k] = 8; - for (; k < 256; k++) - c[k] = 9; - for (; k < 280; k++) - c[k] = 7; - for (; k < 288; k++) - c[k] = 8; - fixed_bl = 7; - huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, &z); - - /* distance table */ - for (k = 0; k < 30; k++) - c[k] = 5; - fixed_bd = 5; - huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, &z); - - /* done */ - fixed_built = 1; - } - fixed_lock--; - *bl = fixed_bl; - *bd = fixed_bd; - *tl = fixed_tl; - *td = fixed_td; - return Z_OK; -} - - -local int inflate_trees_free(t, z) -inflate_huft *t; /* table to free */ -z_stream *z; /* for zfree function */ -/* Free the malloc'ed tables built by huft_build(), which makes a linked - list of the tables it made, with the links in a dummy first entry of - each table. */ -{ - register inflate_huft *p, *q; - - /* Go through linked list, freeing from the malloced (t[-1]) address. */ - p = t; - while (p != Z_NULL) - { - q = (--p)->next; - ZFREE(z, p, p->word.Nalloc * sizeof(inflate_huft)); - p = q; - } - return Z_OK; -} - -/*+++++*/ -/* infcodes.c -- process literals and length/distance pairs - * Copyright (C) 1995 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* simplify the use of the inflate_huft type with some defines */ -#define base more.Base -#define next more.Next -#define exop word.what.Exop -#define bits word.what.Bits - -/* inflate codes private state */ -struct inflate_codes_state { - - /* mode */ - enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ - START, /* x: set up for LEN */ - LEN, /* i: get length/literal/eob next */ - LENEXT, /* i: getting length extra (have base) */ - DIST, /* i: get distance next */ - DISTEXT, /* i: getting distance extra */ - COPY, /* o: copying bytes in window, waiting for space */ - LIT, /* o: got literal, waiting for output space */ - WASH, /* o: got eob, possibly still output waiting */ - END, /* x: got eob and all data flushed */ - BADCODE} /* x: got error */ - mode; /* current inflate_codes mode */ - - /* mode dependent information */ - uInt len; - union { - struct { - inflate_huft *tree; /* pointer into tree */ - uInt need; /* bits needed */ - } code; /* if LEN or DIST, where in tree */ - uInt lit; /* if LIT, literal */ - struct { - uInt get; /* bits to get for extra */ - uInt dist; /* distance back to copy from */ - } copy; /* if EXT or COPY, where and how much */ - } sub; /* submode */ - - /* mode independent information */ - Byte lbits; /* ltree bits decoded per branch */ - Byte dbits; /* dtree bits decoder per branch */ - inflate_huft *ltree; /* literal/length/eob tree */ - inflate_huft *dtree; /* distance tree */ - -}; - - -local inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z) -uInt bl, bd; -inflate_huft *tl, *td; -z_stream *z; -{ - inflate_codes_statef *c; - - if ((c = (inflate_codes_statef *) - ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL) - { - c->mode = START; - c->lbits = (Byte)bl; - c->dbits = (Byte)bd; - c->ltree = tl; - c->dtree = td; - Tracev((stderr, "inflate: codes new\n")); - } - return c; -} - - -local int inflate_codes(s, z, r) -inflate_blocks_statef *s; -z_stream *z; -int r; -{ - uInt j; /* temporary storage */ - inflate_huft *t; /* temporary pointer */ - uInt e; /* extra bits or operation */ - uLong b; /* bit buffer */ - uInt k; /* bits in bit buffer */ - Bytef *p; /* input data pointer */ - uInt n; /* bytes available there */ - Bytef *q; /* output window write pointer */ - uInt m; /* bytes to end of window or read pointer */ - Bytef *f; /* pointer to copy strings from */ - inflate_codes_statef *c = s->sub.decode.codes; /* codes state */ - - /* copy input/output information to locals (UPDATE macro restores) */ - LOAD - - /* process input and output based on current state */ - while (1) switch (c->mode) - { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ - case START: /* x: set up for LEN */ -#ifndef SLOW - if (m >= 258 && n >= 10) - { - UPDATE - r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z); - LOAD - if (r != Z_OK) - { - c->mode = r == Z_STREAM_END ? WASH : BADCODE; - break; - } - } -#endif /* !SLOW */ - c->sub.code.need = c->lbits; - c->sub.code.tree = c->ltree; - c->mode = LEN; - case LEN: /* i: get length/literal/eob next */ - j = c->sub.code.need; - NEEDBITS(j) - t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); - DUMPBITS(t->bits) - e = (uInt)(t->exop); - if (e == 0) /* literal */ - { - c->sub.lit = t->base; - Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", t->base)); - c->mode = LIT; - break; - } - if (e & 16) /* length */ - { - c->sub.copy.get = e & 15; - c->len = t->base; - c->mode = LENEXT; - break; - } - if ((e & 64) == 0) /* next table */ - { - c->sub.code.need = e; - c->sub.code.tree = t->next; - break; - } - if (e & 32) /* end of block */ - { - Tracevv((stderr, "inflate: end of block\n")); - c->mode = WASH; - break; - } - c->mode = BADCODE; /* invalid code */ - z->msg = "invalid literal/length code"; - r = Z_DATA_ERROR; - LEAVE - case LENEXT: /* i: getting length extra (have base) */ - j = c->sub.copy.get; - NEEDBITS(j) - c->len += (uInt)b & inflate_mask[j]; - DUMPBITS(j) - c->sub.code.need = c->dbits; - c->sub.code.tree = c->dtree; - Tracevv((stderr, "inflate: length %u\n", c->len)); - c->mode = DIST; - case DIST: /* i: get distance next */ - j = c->sub.code.need; - NEEDBITS(j) - t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); - DUMPBITS(t->bits) - e = (uInt)(t->exop); - if (e & 16) /* distance */ - { - c->sub.copy.get = e & 15; - c->sub.copy.dist = t->base; - c->mode = DISTEXT; - break; - } - if ((e & 64) == 0) /* next table */ - { - c->sub.code.need = e; - c->sub.code.tree = t->next; - break; - } - c->mode = BADCODE; /* invalid code */ - z->msg = "invalid distance code"; - r = Z_DATA_ERROR; - LEAVE - case DISTEXT: /* i: getting distance extra */ - j = c->sub.copy.get; - NEEDBITS(j) - c->sub.copy.dist += (uInt)b & inflate_mask[j]; - DUMPBITS(j) - Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist)); - c->mode = COPY; - case COPY: /* o: copying bytes in window, waiting for space */ -#ifndef __TURBOC__ /* Turbo C bug for following expression */ - f = (uInt)(q - s->window) < c->sub.copy.dist ? - s->end - (c->sub.copy.dist - (q - s->window)) : - q - c->sub.copy.dist; -#else - f = q - c->sub.copy.dist; - if ((uInt)(q - s->window) < c->sub.copy.dist) - f = s->end - (c->sub.copy.dist - (q - s->window)); -#endif - while (c->len) - { - NEEDOUT - OUTBYTE(*f++) - if (f == s->end) - f = s->window; - c->len--; - } - c->mode = START; - break; - case LIT: /* o: got literal, waiting for output space */ - NEEDOUT - OUTBYTE(c->sub.lit) - c->mode = START; - break; - case WASH: /* o: got eob, possibly more output */ - FLUSH - if (s->read != s->write) - LEAVE - c->mode = END; - case END: - r = Z_STREAM_END; - LEAVE - case BADCODE: /* x: got error */ - r = Z_DATA_ERROR; - LEAVE - default: - r = Z_STREAM_ERROR; - LEAVE - } -} - - -local void inflate_codes_free(c, z) -inflate_codes_statef *c; -z_stream *z; -{ - ZFREE(z, c, sizeof(struct inflate_codes_state)); - Tracev((stderr, "inflate: codes free\n")); -} - -/*+++++*/ -/* inflate_util.c -- data and routines common to blocks and codes - * Copyright (C) 1995 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* copy as much as possible from the sliding window to the output area */ -local int inflate_flush(s, z, r) -inflate_blocks_statef *s; -z_stream *z; -int r; -{ - uInt n; - Bytef *p, *q; - - /* local copies of source and destination pointers */ - p = z->next_out; - q = s->read; - - /* compute number of bytes to copy as far as end of window */ - n = (uInt)((q <= s->write ? s->write : s->end) - q); - if (n > z->avail_out) n = z->avail_out; - if (n && r == Z_BUF_ERROR) r = Z_OK; - - /* update counters */ - z->avail_out -= n; - z->total_out += n; - - /* update check information */ - if (s->checkfn != Z_NULL) - s->check = (*s->checkfn)(s->check, q, n); - - /* copy as far as end of window */ - zmemcpy(p, q, n); - p += n; - q += n; - - /* see if more to copy at beginning of window */ - if (q == s->end) - { - /* wrap pointers */ - q = s->window; - if (s->write == s->end) - s->write = s->window; - - /* compute bytes to copy */ - n = (uInt)(s->write - q); - if (n > z->avail_out) n = z->avail_out; - if (n && r == Z_BUF_ERROR) r = Z_OK; - - /* update counters */ - z->avail_out -= n; - z->total_out += n; - - /* update check information */ - if (s->checkfn != Z_NULL) - s->check = (*s->checkfn)(s->check, q, n); - - /* copy */ - zmemcpy(p, q, n); - p += n; - q += n; - } - - /* update pointers */ - z->next_out = p; - s->read = q; - - /* done */ - return r; -} - - -/*+++++*/ -/* inffast.c -- process literals and length/distance pairs fast - * Copyright (C) 1995 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* simplify the use of the inflate_huft type with some defines */ -#define base more.Base -#define next more.Next -#define exop word.what.Exop -#define bits word.what.Bits - -/* macros for bit input with no checking and for returning unused bytes */ -#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<>3);p-=c;k&=7;} - -/* Called with number of bytes left to write in window at least 258 - (the maximum string length) and number of input bytes available - at least ten. The ten bytes are six bytes for the longest length/ - distance pair plus four bytes for overloading the bit buffer. */ - -local int inflate_fast(bl, bd, tl, td, s, z) -uInt bl, bd; -inflate_huft *tl, *td; -inflate_blocks_statef *s; -z_stream *z; -{ - inflate_huft *t; /* temporary pointer */ - uInt e; /* extra bits or operation */ - uLong b; /* bit buffer */ - uInt k; /* bits in bit buffer */ - Bytef *p; /* input data pointer */ - uInt n; /* bytes available there */ - Bytef *q; /* output window write pointer */ - uInt m; /* bytes to end of window or read pointer */ - uInt ml; /* mask for literal/length tree */ - uInt md; /* mask for distance tree */ - uInt c; /* bytes to copy */ - uInt d; /* distance back to copy from */ - Bytef *r; /* copy source pointer */ - - /* load input, output, bit values */ - LOAD - - /* initialize masks */ - ml = inflate_mask[bl]; - md = inflate_mask[bd]; - - /* do until not enough input or output space for fast loop */ - do { /* assume called with m >= 258 && n >= 10 */ - /* get literal/length code */ - GRABBITS(20) /* max bits for literal/length code */ - if ((e = (t = tl + ((uInt)b & ml))->exop) == 0) - { - DUMPBITS(t->bits) - Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? - "inflate: * literal '%c'\n" : - "inflate: * literal 0x%02x\n", t->base)); - *q++ = (Byte)t->base; - m--; - continue; - } - do { - DUMPBITS(t->bits) - if (e & 16) - { - /* get extra bits for length */ - e &= 15; - c = t->base + ((uInt)b & inflate_mask[e]); - DUMPBITS(e) - Tracevv((stderr, "inflate: * length %u\n", c)); - - /* decode distance base of block to copy */ - GRABBITS(15); /* max bits for distance code */ - e = (t = td + ((uInt)b & md))->exop; - do { - DUMPBITS(t->bits) - if (e & 16) - { - /* get extra bits to add to distance base */ - e &= 15; - GRABBITS(e) /* get extra bits (up to 13) */ - d = t->base + ((uInt)b & inflate_mask[e]); - DUMPBITS(e) - Tracevv((stderr, "inflate: * distance %u\n", d)); - - /* do the copy */ - m -= c; - if ((uInt)(q - s->window) >= d) /* offset before dest */ - { /* just copy */ - r = q - d; - *q++ = *r++; c--; /* minimum count is three, */ - *q++ = *r++; c--; /* so unroll loop a little */ - } - else /* else offset after destination */ - { - e = d - (q - s->window); /* bytes from offset to end */ - r = s->end - e; /* pointer to offset */ - if (c > e) /* if source crosses, */ - { - c -= e; /* copy to end of window */ - do { - *q++ = *r++; - } while (--e); - r = s->window; /* copy rest from start of window */ - } - } - do { /* copy all or what's left */ - *q++ = *r++; - } while (--c); - break; - } - else if ((e & 64) == 0) - e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop; - else - { - z->msg = "invalid distance code"; - UNGRAB - UPDATE - return Z_DATA_ERROR; - } - } while (1); - break; - } - if ((e & 64) == 0) - { - if ((e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop) == 0) - { - DUMPBITS(t->bits) - Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? - "inflate: * literal '%c'\n" : - "inflate: * literal 0x%02x\n", t->base)); - *q++ = (Byte)t->base; - m--; - break; - } - } - else if (e & 32) - { - Tracevv((stderr, "inflate: * end of block\n")); - UNGRAB - UPDATE - return Z_STREAM_END; - } - else - { - z->msg = "invalid literal/length code"; - UNGRAB - UPDATE - return Z_DATA_ERROR; - } - } while (1); - } while (m >= 258 && n >= 10); - - /* not enough input or output--restore pointers and return */ - UNGRAB - UPDATE - return Z_OK; -} - - -/*+++++*/ -/* zutil.c -- target dependent utility functions for the compression library - * Copyright (C) 1995 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* From: zutil.c,v 1.8 1995/05/03 17:27:12 jloup Exp */ - -char *zlib_version = ZLIB_VERSION; - -char *z_errmsg[] = { -"stream end", /* Z_STREAM_END 1 */ -"", /* Z_OK 0 */ -"file error", /* Z_ERRNO (-1) */ -"stream error", /* Z_STREAM_ERROR (-2) */ -"data error", /* Z_DATA_ERROR (-3) */ -"insufficient memory", /* Z_MEM_ERROR (-4) */ -"buffer error", /* Z_BUF_ERROR (-5) */ -""}; - - -/*+++++*/ -/* adler32.c -- compute the Adler-32 checksum of a data stream - * Copyright (C) 1995 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* From: adler32.c,v 1.6 1995/05/03 17:27:08 jloup Exp */ - -#define BASE 65521L /* largest prime smaller than 65536 */ -#define NMAX 5552 -/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ - -#define DO1(buf) {s1 += *buf++; s2 += s1;} -#define DO2(buf) DO1(buf); DO1(buf); -#define DO4(buf) DO2(buf); DO2(buf); -#define DO8(buf) DO4(buf); DO4(buf); -#define DO16(buf) DO8(buf); DO8(buf); - -/* ========================================================================= */ -uLong adler32(adler, buf, len) - uLong adler; - Bytef *buf; - uInt len; -{ - unsigned long s1 = adler & 0xffff; - unsigned long s2 = (adler >> 16) & 0xffff; - int k; - - if (buf == Z_NULL) return 1L; - - while (len > 0) { - k = len < NMAX ? len : NMAX; - len -= k; - while (k >= 16) { - DO16(buf); - k -= 16; - } - if (k != 0) do { - DO1(buf); - } while (--k); - s1 %= BASE; - s2 %= BASE; - } - return (s2 << 16) | s1; -} diff -u --recursive --new-file v2.1.123/linux/arch/ppc/chrpboot/zlib.h linux/arch/ppc/chrpboot/zlib.h --- v2.1.123/linux/arch/ppc/chrpboot/zlib.h Mon Jan 12 15:18:13 1998 +++ linux/arch/ppc/chrpboot/zlib.h Wed Dec 31 16:00:00 1969 @@ -1,432 +0,0 @@ -/* $Id: zlib.h,v 1.1 1997/09/19 07:03:47 paulus Exp $ */ - -/* - * This file is derived from zlib.h and zconf.h from the zlib-0.95 - * distribution by Jean-loup Gailly and Mark Adler, with some additions - * by Paul Mackerras to aid in implementing Deflate compression and - * decompression for PPP packets. - */ - -/* - * ==FILEVERSION 960122== - * - * This marker is used by the Linux installation script to determine - * whether an up-to-date version of this file is already installed. - */ - -/* zlib.h -- interface of the 'zlib' general purpose compression library - version 0.95, Aug 16th, 1995. - - Copyright (C) 1995 Jean-loup Gailly and Mark Adler - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jean-loup Gailly Mark Adler - gzip@prep.ai.mit.edu madler@alumni.caltech.edu - */ - -#ifndef _ZLIB_H -#define _ZLIB_H - -/* #include "zconf.h" */ /* included directly here */ - -/* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* From: zconf.h,v 1.12 1995/05/03 17:27:12 jloup Exp */ - -/* - The library does not install any signal handler. It is recommended to - add at least a handler for SIGSEGV when decompressing; the library checks - the consistency of the input data whenever possible but may go nuts - for some forms of corrupted input. - */ - -/* - * Compile with -DMAXSEG_64K if the alloc function cannot allocate more - * than 64k bytes at a time (needed on systems with 16-bit int). - * Compile with -DUNALIGNED_OK if it is OK to access shorts or ints - * at addresses which are not a multiple of their size. - * Under DOS, -DFAR=far or -DFAR=__far may be needed. - */ - -#ifndef STDC -# if defined(MSDOS) || defined(__STDC__) || defined(__cplusplus) -# define STDC -# endif -#endif - -#ifdef __MWERKS__ /* Metrowerks CodeWarrior declares fileno() in unix.h */ -# include -#endif - -/* Maximum value for memLevel in deflateInit2 */ -#ifndef MAX_MEM_LEVEL -# ifdef MAXSEG_64K -# define MAX_MEM_LEVEL 8 -# else -# define MAX_MEM_LEVEL 9 -# endif -#endif - -#ifndef FAR -# define FAR -#endif - -/* Maximum value for windowBits in deflateInit2 and inflateInit2 */ -#ifndef MAX_WBITS -# define MAX_WBITS 15 /* 32K LZ77 window */ -#endif - -/* The memory requirements for deflate are (in bytes): - 1 << (windowBits+2) + 1 << (memLevel+9) - that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) - plus a few kilobytes for small objects. For example, if you want to reduce - the default memory requirements from 256K to 128K, compile with - make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" - Of course this will generally degrade compression (there's no free lunch). - - The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus a few kilobytes - for small objects. -*/ - - /* Type declarations */ - -#ifndef OF /* function prototypes */ -# ifdef STDC -# define OF(args) args -# else -# define OF(args) () -# endif -#endif - -typedef unsigned char Byte; /* 8 bits */ -typedef unsigned int uInt; /* 16 bits or more */ -typedef unsigned long uLong; /* 32 bits or more */ - -typedef Byte FAR Bytef; -typedef char FAR charf; -typedef int FAR intf; -typedef uInt FAR uIntf; -typedef uLong FAR uLongf; - -#ifdef STDC - typedef void FAR *voidpf; - typedef void *voidp; -#else - typedef Byte FAR *voidpf; - typedef Byte *voidp; -#endif - -/* end of original zconf.h */ - -#define ZLIB_VERSION "0.95P" - -/* - The 'zlib' compression library provides in-memory compression and - decompression functions, including integrity checks of the uncompressed - data. This version of the library supports only one compression method - (deflation) but other algorithms may be added later and will have the same - stream interface. - - For compression the application must provide the output buffer and - may optionally provide the input buffer for optimization. For decompression, - the application must provide the input buffer and may optionally provide - the output buffer for optimization. - - Compression can be done in a single step if the buffers are large - enough (for example if an input file is mmap'ed), or can be done by - repeated calls of the compression function. In the latter case, the - application must provide more input and/or consume the output - (providing more output space) before each call. -*/ - -typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); -typedef void (*free_func) OF((voidpf opaque, voidpf address, uInt nbytes)); - -struct internal_state; - -typedef struct z_stream_s { - Bytef *next_in; /* next input byte */ - uInt avail_in; /* number of bytes available at next_in */ - uLong total_in; /* total nb of input bytes read so far */ - - Bytef *next_out; /* next output byte should be put there */ - uInt avail_out; /* remaining free space at next_out */ - uLong total_out; /* total nb of bytes output so far */ - - char *msg; /* last error message, NULL if no error */ - struct internal_state FAR *state; /* not visible by applications */ - - alloc_func zalloc; /* used to allocate the internal state */ - free_func zfree; /* used to free the internal state */ - voidp opaque; /* private data object passed to zalloc and zfree */ - - Byte data_type; /* best guess about the data type: ascii or binary */ - -} z_stream; - -/* - The application must update next_in and avail_in when avail_in has - dropped to zero. It must update next_out and avail_out when avail_out - has dropped to zero. The application must initialize zalloc, zfree and - opaque before calling the init function. All other fields are set by the - compression library and must not be updated by the application. - - The opaque value provided by the application will be passed as the first - parameter for calls of zalloc and zfree. This can be useful for custom - memory management. The compression library attaches no meaning to the - opaque value. - - zalloc must return Z_NULL if there is not enough memory for the object. - On 16-bit systems, the functions zalloc and zfree must be able to allocate - exactly 65536 bytes, but will not be required to allocate more than this - if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, - pointers returned by zalloc for objects of exactly 65536 bytes *must* - have their offset normalized to zero. The default allocation function - provided by this library ensures this (see zutil.c). To reduce memory - requirements and avoid any allocation of 64K objects, at the expense of - compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). - - The fields total_in and total_out can be used for statistics or - progress reports. After compression, total_in holds the total size of - the uncompressed data and may be saved for use in the decompressor - (particularly if the decompressor wants to decompress everything in - a single step). -*/ - - /* constants */ - -#define Z_NO_FLUSH 0 -#define Z_PARTIAL_FLUSH 1 -#define Z_FULL_FLUSH 2 -#define Z_SYNC_FLUSH 3 /* experimental: partial_flush + byte align */ -#define Z_FINISH 4 -#define Z_PACKET_FLUSH 5 -/* See deflate() below for the usage of these constants */ - -#define Z_OK 0 -#define Z_STREAM_END 1 -#define Z_ERRNO (-1) -#define Z_STREAM_ERROR (-2) -#define Z_DATA_ERROR (-3) -#define Z_MEM_ERROR (-4) -#define Z_BUF_ERROR (-5) -/* error codes for the compression/decompression functions */ - -#define Z_BEST_SPEED 1 -#define Z_BEST_COMPRESSION 9 -#define Z_DEFAULT_COMPRESSION (-1) -/* compression levels */ - -#define Z_FILTERED 1 -#define Z_HUFFMAN_ONLY 2 -#define Z_DEFAULT_STRATEGY 0 - -#define Z_BINARY 0 -#define Z_ASCII 1 -#define Z_UNKNOWN 2 -/* Used to set the data_type field */ - -#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ - -extern char *zlib_version; -/* The application can compare zlib_version and ZLIB_VERSION for consistency. - If the first character differs, the library code actually used is - not compatible with the zlib.h header file used by the application. - */ - - /* basic functions */ - -extern int inflateInit OF((z_stream *strm)); -/* - Initializes the internal stream state for decompression. The fields - zalloc and zfree must be initialized before by the caller. If zalloc and - zfree are set to Z_NULL, inflateInit updates them to use default allocation - functions. - - inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory. msg is set to null if there is no error message. - inflateInit does not perform any decompression: this will be done by - inflate(). -*/ - - -extern int inflate OF((z_stream *strm, int flush)); -/* - Performs one or both of the following actions: - - - Decompress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in is updated and processing - will resume at this point for the next call of inflate(). - - - Provide more output starting at next_out and update next_out and avail_out - accordingly. inflate() always provides as much output as possible - (until there is no more input data or no more space in the output buffer). - - Before the call of inflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming - more output, and updating the next_* and avail_* values accordingly. - The application can consume the uncompressed output when it wants, for - example when the output buffer is full (avail_out == 0), or after each - call of inflate(). - - If the parameter flush is set to Z_PARTIAL_FLUSH or Z_PACKET_FLUSH, - inflate flushes as much output as possible to the output buffer. The - flushing behavior of inflate is not specified for values of the flush - parameter other than Z_PARTIAL_FLUSH, Z_PACKET_FLUSH or Z_FINISH, but the - current implementation actually flushes as much output as possible - anyway. For Z_PACKET_FLUSH, inflate checks that once all the input data - has been consumed, it is expecting to see the length field of a stored - block; if not, it returns Z_DATA_ERROR. - - inflate() should normally be called until it returns Z_STREAM_END or an - error. However if all decompression is to be performed in a single step - (a single call of inflate), the parameter flush should be set to - Z_FINISH. In this case all pending input is processed and all pending - output is flushed; avail_out must be large enough to hold all the - uncompressed data. (The size of the uncompressed data may have been saved - by the compressor for this purpose.) The next operation on this stream must - be inflateEnd to deallocate the decompression state. The use of Z_FINISH - is never required, but can be used to inform inflate that a faster routine - may be used for the single inflate() call. - - inflate() returns Z_OK if some progress has been made (more input - processed or more output produced), Z_STREAM_END if the end of the - compressed data has been reached and all uncompressed output has been - produced, Z_DATA_ERROR if the input data was corrupted, Z_STREAM_ERROR if - the stream structure was inconsistent (for example if next_in or next_out - was NULL), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if no - progress is possible or if there was not enough room in the output buffer - when Z_FINISH is used. In the Z_DATA_ERROR case, the application may then - call inflateSync to look for a good compression block. */ - - -extern int inflateEnd OF((z_stream *strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any - pending output. - - inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state - was inconsistent. In the error case, msg may be set but then points to a - static string (which must not be deallocated). -*/ - - /* advanced functions */ - -extern int inflateInit2 OF((z_stream *strm, - int windowBits)); -/* - This is another version of inflateInit with more compression options. The - fields next_out, zalloc and zfree must be initialized before by the caller. - - The windowBits parameter is the base two logarithm of the maximum window - size (the size of the history buffer). It should be in the range 8..15 for - this version of the library (the value 16 will be allowed soon). The - default value is 15 if inflateInit is used instead. If a compressed stream - with a larger window size is given as input, inflate() will return with - the error code Z_DATA_ERROR instead of trying to allocate a larger window. - - If next_out is not null, the library will use this buffer for the history - buffer; the buffer must either be large enough to hold the entire output - data, or have at least 1< +#include #define zmemcpy memcpy #define zmemzero(dest, len) memset(dest, 0, len) diff -u --recursive --new-file v2.1.123/linux/arch/ppc/config.in linux/arch/ppc/config.in --- v2.1.123/linux/arch/ppc/config.in Thu Aug 6 14:06:29 1998 +++ linux/arch/ppc/config.in Wed Sep 30 10:14:16 1998 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.65 1998/07/20 18:42:27 geert Exp $ +# $Id: config.in,v 1.71 1998/09/18 13:25:17 cort Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -7,21 +7,23 @@ mainmenu_option next_comment +comment 'Cross development support' + bool 'Build using cross development tools' CONFIG_CROSSCOMPILE +if [ "$CONFIG_CROSSCOMPILE" = "y" ]; then + string ' Prefix for cross devel tools' CROSS_COMPILE "ppc-linux-elf-" +fi +endmenu + +mainmenu_option next_comment comment 'Platform support' define_bool CONFIG_PPC y -#if [ "`uname`" != "Linux" -o "`uname -m`" != "ppc" ]; then -# define_bool CONFIG_CROSSCOMPILE y -#else -# define_bool CONFIG_NATIVE y -#fi - choice 'Processor type' \ "6xx/7xx CONFIG_6xx \ 860/821 CONFIG_8xx" 6xx/7xx choice 'Machine Type' \ "PowerMac CONFIG_PMAC \ - PReP CONFIG_PREP \ + PReP/MTX CONFIG_PREP \ CHRP CONFIG_CHRP \ PowerMac/PReP/CHRP CONFIG_ALL_PPC \ APUS CONFIG_APUS \ @@ -89,12 +91,11 @@ bool 'Support for PowerMac keyboard' CONFIG_MAC_KEYBOARD bool 'Support for PowerMac floppy' CONFIG_MAC_FLOPPY bool 'Support for PowerMac serial ports' CONFIG_MAC_SERIAL -if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - bool 'Support for PowerMac mouse (EXPERIMENTAL)' CONFIG_MACMOUSE -fi +bool 'Support for PowerMac ADB mouse' CONFIG_ADBMOUSE bool 'Support for Open Firmware device tree in /proc' CONFIG_PROC_DEVICETREE bool 'Include kgdb kernel debugger' CONFIG_KGDB bool 'Include xmon kernel debugger' CONFIG_XMON +bool 'Support for TotalImpact TotalMP' CONFIG_TOTALMP if [ "$CONFIG_APUS" = "y" ]; then define_bool CONFIG_FB_CONSOLE y @@ -103,8 +104,6 @@ define_bool CONFIG_AMIGAMOUSE y define_bool CONFIG_ABSTRACT_CONSOLE y define_bool CONFIG_FB y - tristate 'Amiga floppy support' CONFIG_AMIGA_FLOPPY - bool 'Amiga Gayle IDE interface support' CONFIG_BLK_DEV_GAYLE tristate 'Amiga builtin serial support' CONFIG_AMIGA_BUILTIN_SERIAL tristate 'GVP IO-Extender support' CONFIG_GVPIOEXT dep_tristate 'GVP IO-Extender parallel printer support' CONFIG_GVPIOEXT_LP $CONFIG_GVPIOEXT diff -u --recursive --new-file v2.1.123/linux/arch/ppc/defconfig linux/arch/ppc/defconfig --- v2.1.123/linux/arch/ppc/defconfig Thu Aug 6 14:06:29 1998 +++ linux/arch/ppc/defconfig Wed Sep 30 10:14:16 1998 @@ -35,16 +35,16 @@ CONFIG_BINFMT_MISC=m # CONFIG_BINFMT_JAVA is not set # CONFIG_PARPORT is not set -# CONFIG_FB is not set -# CONFIG_VGA_CONSOLE is not set -# CONFIG_PMAC_PBOOK is not set +CONFIG_FB=y +CONFIG_FB_COMPAT_XPMAC=y +CONFIG_PMAC_PBOOK=y CONFIG_MAC_KEYBOARD=y CONFIG_MAC_FLOPPY=y CONFIG_MAC_SERIAL=y CONFIG_MACMOUSE=y CONFIG_PROC_DEVICETREE=y # CONFIG_KGDB is not set -# CONFIG_XMON is not set +CONFIG_XMON=y # # Plug and Play support @@ -64,7 +64,7 @@ CONFIG_BLK_DEV_IDEDISK=y CONFIG_BLK_DEV_IDECD=y # CONFIG_BLK_DEV_IDETAPE is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set +CONFIG_BLK_DEV_IDEFLOPPY=y # CONFIG_BLK_DEV_IDESCSI is not set # CONFIG_BLK_DEV_CMD640 is not set # CONFIG_BLK_DEV_RZ1000 is not set @@ -260,17 +260,39 @@ # # Console drivers # +CONFIG_DUMMY_CONSOLE=y +CONFIG_FB_OF=y +CONFIG_FB_CONTROL=y +CONFIG_FB_PLATINUM=y +CONFIG_FB_ATY=y +CONFIG_FB_IMSTT=y +CONFIG_FB_CT65550=y +# CONFIG_FB_S3TRIO is not set +# CONFIG_FB_VGA is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FBCON_ADVANCED is not set +CONFIG_FBCON_CFB8=y +CONFIG_FBCON_CFB16=y +CONFIG_FBCON_CFB24=y +CONFIG_FBCON_CFB32=y +# CONFIG_FBCON_FONTWIDTH8_ONLY is not set +CONFIG_FBCON_FONTS=y +# CONFIG_FONT_8x8 is not set +CONFIG_FONT_8x16=y +CONFIG_FONT_SUN8x16=y +CONFIG_FONT_SUN12x22=y +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set # # Character devices # CONFIG_VT=y CONFIG_VT_CONSOLE=y -# CONFIG_SERIAL is not set +CONFIG_SERIAL=m # CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 # CONFIG_MOUSE is not set # CONFIG_UMISC is not set # CONFIG_QIC02_TAPE is not set @@ -313,8 +335,8 @@ # CONFIG_ROMFS_FS is not set CONFIG_AUTOFS_FS=y # CONFIG_UFS_FS is not set -CONFIG_DEVPTS_FS=y # CONFIG_ADFS_FS is not set +CONFIG_DEVPTS_FS=y CONFIG_MAC_PARTITION=y CONFIG_NLS=y @@ -351,4 +373,5 @@ # # Sound # -# CONFIG_SOUND is not set +CONFIG_SOUND=y +CONFIG_DMASOUND=y diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/Makefile linux/arch/ppc/kernel/Makefile --- v2.1.123/linux/arch/ppc/kernel/Makefile Thu Aug 6 14:06:29 1998 +++ linux/arch/ppc/kernel/Makefile Wed Sep 30 10:14:17 1998 @@ -11,11 +11,11 @@ $(CC) $(CFLAGS) -D__ASSEMBLY__ -c $< -o $*.o O_TARGET := kernel.o -OX_OBJS := ppc_ksyms.o +OX_OBJS := ppc_ksyms.o setup.o O_OBJS := traps.o irq.o idle.o time.o process.o signal.o syscalls.o misc.o \ - bitops.o setup.o ptrace.o align.o ppc_htab.o + bitops.o ptrace.o align.o ppc_htab.o ifdef CONFIG_PCI O_OBJS += pci.o @@ -23,6 +23,9 @@ ifdef CONFIG_KGDB O_OBJS += ppc-stub.o endif +ifdef CONFIG_TOTALMP +O_OBJS += totalmp.o +endif ifeq ($(CONFIG_MBX),y) O_OBJS += mbx_setup.o mbx_pci.o softemu8xx.o @@ -31,10 +34,10 @@ O_OBJS += apus_setup.o prom.o openpic.o else O_OBJS += prep_time.o pmac_time.o chrp_time.o \ - pmac_setup.o pmac_support.o chrp_setup.o \ + pmac_setup.o pmac_support.o \ prep_pci.o pmac_pci.o chrp_pci.o \ residual.o prom.o openpic.o -OX_OBJS += prep_setup.o +OX_OBJS += chrp_setup.o prep_setup.o endif endif diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/align.c linux/arch/ppc/kernel/align.c --- v2.1.123/linux/arch/ppc/kernel/align.c Thu Apr 23 20:21:28 1998 +++ linux/arch/ppc/kernel/align.c Wed Sep 30 10:14:17 1998 @@ -265,7 +265,7 @@ #else giveup_fpu(); #endif - cvt_fd(&data.f, ¤t->tss.fpr[reg]); + cvt_fd(&data.f, ¤t->tss.fpr[reg], ¤t->tss.fpscr); /* current->tss.fpr[reg] = data.f; */ break; case ST+F+S: @@ -275,7 +275,7 @@ #else giveup_fpu(); #endif - cvt_df(¤t->tss.fpr[reg], &data.f); + cvt_df(¤t->tss.fpr[reg], &data.f, ¤t->tss.fpscr); /* data.f = current->tss.fpr[reg]; */ break; default: diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/apus_setup.c linux/arch/ppc/kernel/apus_setup.c --- v2.1.123/linux/arch/ppc/kernel/apus_setup.c Thu Aug 6 14:06:29 1998 +++ linux/arch/ppc/kernel/apus_setup.c Wed Sep 30 10:14:17 1998 @@ -19,6 +19,7 @@ #include #include #include +#include unsigned long m68k_machtype; char debug_device[6] = ""; @@ -99,6 +100,7 @@ { int freq, divisor; unsigned char c = *(unsigned char*)ZTWO_VADDR(0xf00011); + printk ("CPU speed ID ('%c') ", c); switch (c) { @@ -122,7 +124,7 @@ break; default: freq = 0; - printk (" *Unknown CPU speed ID ('%c')* ", c); + printk (" *Unknown* "); break; } @@ -133,24 +135,27 @@ case 0: freq = 15000000; speed = 60; - - /* Use status of left mouse button to select - RAM speed. */ - if (!(ciaa.pra & 0x40)) - { - APUS_WRITE (APUS_REG_WAITSTATE, - REGWAITSTATE_SETRESET - |REGWAITSTATE_PPCR - |REGWAITSTATE_PPCW); - printk (" [RAM R/W waitstate removed. " - "(expecting 60ns RAM).] "); - } break; + case 1: freq = 16500000; - speed = 66; + speed =66; break; } + + /* Use status of left mouse button to select + RAM speed. */ + if (!(ciaa.pra & 0x40)) + { + APUS_WRITE (APUS_REG_WAITSTATE, + REGWAITSTATE_SETRESET + |REGWAITSTATE_PPCR + |REGWAITSTATE_PPCW); + printk (" [RAM R/W waitstate removed. " + "(expecting 60ns RAM).] "); + } + + printk ("PowerUp Bus Speed: %dMHz\n", speed); } @@ -222,7 +227,72 @@ } return v_ret; } - + +/* From pgtable.h */ +extern __inline__ pte_t *my_find_pte(struct mm_struct *mm,unsigned long va) +{ + pgd_t *dir = 0; + pmd_t *pmd = 0; + pte_t *pte = 0; + + va &= PAGE_MASK; + + dir = pgd_offset( mm, va ); + if (dir) + { + pmd = pmd_offset(dir, va & PAGE_MASK); + if (pmd && pmd_present(*pmd)) + { + pte = pte_offset(pmd, va); + } + } + return pte; +} + + +/* Again simulating an m68k/mm/kmap.c function. */ +void kernel_set_cachemode( unsigned long address, unsigned long size, + unsigned int cmode ) +{ + int mask, flags; + + switch (cmode) + { + case KERNELMAP_FULL_CACHING: + mask = ~(_PAGE_NO_CACHE | _PAGE_GUARDED); + flags = 0; + break; + case KERNELMAP_NOCACHE_SER: + mask = ~0; + flags = (_PAGE_NO_CACHE | _PAGE_GUARDED); + break; + default: + panic ("kernel_set_cachemode() doesn't support mode %d\n", + cmode); + break; + } + + size /= PAGE_SIZE; + address &= PAGE_MASK; + while (size--) + { + pte_t *pte; + + pte = my_find_pte(init_task.mm, address); + if ( !pte ) + { + printk("pte NULL in kernel_set_cachemode()\n"); + return; + } + + pte_val (*pte) &= mask; + pte_val (*pte) |= flags; + flush_tlb_page(find_vma(init_task.mm,address),address); + + address += PAGE_SIZE; + } +} + unsigned long mm_ptov (unsigned long paddr) { unsigned long ret; diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c --- v2.1.123/linux/arch/ppc/kernel/chrp_setup.c Thu Aug 6 14:06:29 1998 +++ linux/arch/ppc/kernel/chrp_setup.c Wed Sep 30 10:14:17 1998 @@ -11,6 +11,7 @@ */ #include +#include #include #include #include @@ -29,6 +30,7 @@ #include #include #include +#include #include #include @@ -220,3 +222,46 @@ conswitchp = &dummy_con; #endif } + +#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) + +unsigned int chrp_ide_irq = 0; +int chrp_ide_ports_known = 0; +ide_ioreg_t chrp_ide_regbase[MAX_HWIFS]; +ide_ioreg_t chrp_idedma_regbase; + +void chrp_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq) +{ + ide_ioreg_t port = base; + int i = 8; + + while (i--) + *p++ = port++; + *p++ = port; + if (irq != NULL) + *irq = chrp_ide_irq; +} + +void chrp_ide_probe(void) { + + struct pci_dev *pdev = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, NULL); + + chrp_ide_ports_known = 1; + + if(pdev) { + chrp_ide_regbase[0]=pdev->base_address[0] & + PCI_BASE_ADDRESS_IO_MASK; + chrp_ide_regbase[1]=pdev->base_address[2] & + PCI_BASE_ADDRESS_IO_MASK; + chrp_idedma_regbase=pdev->base_address[4] & + PCI_BASE_ADDRESS_IO_MASK; + chrp_ide_irq=pdev->irq; + } +} + +EXPORT_SYMBOL(chrp_ide_irq); +EXPORT_SYMBOL(chrp_ide_ports_known); +EXPORT_SYMBOL(chrp_ide_regbase); +EXPORT_SYMBOL(chrp_ide_probe); + +#endif diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/find_name.c linux/arch/ppc/kernel/find_name.c --- v2.1.123/linux/arch/ppc/kernel/find_name.c Fri May 8 23:14:44 1998 +++ linux/arch/ppc/kernel/find_name.c Wed Sep 30 10:14:17 1998 @@ -16,7 +16,7 @@ if ( argc < 2 ) { fprintf(stderr, "Usage: %s
\n", argv[0]); - exit(-1); + return -1; } for ( i = 1 ; argv[i] ; i++ ) @@ -41,7 +41,7 @@ strcpy( last, s); } - printf( "%s", last); + printf( "%s%s", last, s ); } fclose(f); return 0; diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/head.S linux/arch/ppc/kernel/head.S --- v2.1.123/linux/arch/ppc/kernel/head.S Thu Aug 6 14:06:29 1998 +++ linux/arch/ppc/kernel/head.S Wed Sep 30 10:14:17 1998 @@ -1,7 +1,7 @@ /* * arch/ppc/kernel/head.S * - * $Id: head.S,v 1.98 1998/07/26 21:28:48 geert Exp $ + * $Id: head.S,v 1.107 1998/09/25 19:48:52 paulus Exp $ * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) @@ -93,15 +93,18 @@ bdnz 0b #endif +/* 601 only have IBAT cr0.eq is set on 601 when using this macro */ #define LOAD_BAT(n, offset, reg, RA, RB) \ lwz RA,offset+0(reg); \ lwz RB,offset+4(reg); \ mtspr IBAT##n##U,RA; \ mtspr IBAT##n##L,RB; \ + beq 1f; \ lwz RA,offset+8(reg); \ lwz RB,offset+12(reg); \ mtspr DBAT##n##U,RA; \ - mtspr DBAT##n##L,RB + mtspr DBAT##n##L,RB; \ +1: #ifndef CONFIG_APUS #define tophys(rd,rs,rt) addis rd,rs,-KERNELBASE@h @@ -139,6 +142,12 @@ * pointer (r1) points to just below the end of the half-meg region * from 0x380000 - 0x400000, which is mapped in already. * + * If we are booted from MacOS via BootX, we enter with the kernel + * image loaded somewhere, and the following values in registers: + * r3: 'BooX' (0x426f6f58) + * r4: virtual address of boot_infos_t + * r5: 0 + * * PREP * This is jumped to on prep systems right after the kernel is relocated * to its proper place in memory by the boot loader. The expected layout @@ -213,33 +222,45 @@ lis r11,KERNELBASE@h bne 4f ori r11,r11,4 /* set up BAT registers for 601 */ - li r8,0x7f + li r8,0x7f /* valid, block length = 8MB */ oris r9,r11,0x800000@h /* set up BAT reg for 2nd 8M */ oris r10,r8,0x800000@h /* set up BAT reg for 2nd 8M */ + mtspr IBAT0U,r11 /* N.B. 601 has valid bit in */ + mtspr IBAT0L,r8 /* lower BAT register */ mtspr IBAT1U,r9 mtspr IBAT1L,r10 b 5f 4: #ifndef CONFIG_APUS - ori r11,r11,0x1ff /* set up BAT registers for 604 */ - li r8,2 + ori r11,r11,0x1fe /* set up BAT registers for 604 */ + li r8,2 /* R/W access */ #else - ori r11,r11,0xff /* set up an 8MB mapping */ + ori r11,r11,0xfe /* set up an 8MB mapping */ lis r8,CYBERBASEp@h lwz r8,0(r8) addis r8,r8,KERNELBASE@h addi r8,r8,2 #endif -5: mtspr DBAT0U,r11 - mtspr DBAT0L,r8 - mtspr IBAT0U,r11 + mtspr DBAT0L,r8 /* N.B. 6xx (not 601) have valid */ + mtspr DBAT0U,r11 /* bit in upper BAT register */ mtspr IBAT0L,r8 - isync + mtspr IBAT0U,r11 +5: isync #ifdef CONFIG_APUS /* Unfortunately the APUS specific instructions bloat the * code so it cannot fit in the 0x100 bytes available. We have * to do it the crude way. */ + + /* Map 0xfff00000 so we can access VTOP/PTOV constant when + MMU is enabled. */ + lis r8,0xfff0 + ori r11,r8,0x2 /* r/w */ + ori r8,r8,0x2 /* 128KB, supervisor */ + mtspr DBAT3U,r8 + mtspr DBAT3L,r11 + + /* Copy exception code to exception vector base. */ lis r3,KERNELBASE@h tophys(r4,r3,r5) lis r3,0xfff0 /* Copy to 0xfff00000 on APUS */ @@ -263,23 +284,10 @@ li r3,0 mfmsr r0 andi. r0,r0,MSR_DR /* MMU enabled? */ - beq 7f + beq relocate_kernel lis r3,KERNELBASE@h /* if so, are we */ cmpw 0,r4,r3 /* already running at KERNELBASE? */ - beq 2f - rlwinm r4,r4,0,8,31 /* translate source address */ - add r4,r4,r3 /* to region mapped with BATs */ -7: addis r9,r26,klimit@ha /* fetch klimit */ - lwz r25,klimit@l(r9) - addis r25,r25,-KERNELBASE@h - li r6,0 /* Destination */ - li r5,0x4000 /* # bytes of memory to copy */ - bl copy_and_flush /* copy the first 0x4000 bytes */ - addi r0,r3,4f@l /* jump to the address of 4f */ - mtctr r0 /* in copy and do the rest. */ - bctr /* jump to the copy */ -4: mr r5,r25 - bl copy_and_flush /* copy the rest */ + bne relocate_kernel 2: #endif /* CONFIG_APUS */ /* @@ -356,6 +364,7 @@ */ #endif /* CONFIG_8xx */ +turn_on_mmu: mfmsr r0 ori r0,r0,MSR_DR|MSR_IR mtspr SRR1,r0 @@ -364,7 +373,7 @@ mtspr SRR0,r0 SYNC rfi /* enables MMU */ - + /* * GCC sometimes accesses words at negative offsets from the stack * pointer, although the SysV ABI says it shouldn't. To cope with @@ -506,7 +515,7 @@ li r20,(IPLEMU_SETRESET|IPLEMU_DISABLEINT) stb r20,APUS_IPL_EMU@l(r3) - sync + eieio lbz r3,APUS_IPL_EMU@l(r3) @@ -1418,7 +1427,7 @@ * by a switch_to() call to smp_giveup_fpu() in SMP so * last_task_used_math is not used. * - * We should never be herre on SMP anyway, sinc ethe fpu should + * We should never be here on SMP anyway, since the fpu should * always be on. * -- Cort */ @@ -1432,11 +1441,11 @@ lwz r5,PT_REGS(r4) add r5,r5,r6 lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5) - li r20,MSR_FP + li r20,MSR_FP|MSR_FE0|MSR_FE1 andc r4,r4,r20 /* disable FP for previous task */ stw r4,_MSR-STACK_FRAME_OVERHEAD(r5) -1: ori r23,r23,MSR_FP /* enable use of FP after return */ +1: ori r23,r23,MSR_FP|MSR_FE0|MSR_FE1 /* enable use of FP after return */ mfspr r5,SPRG3 /* current task's TSS (phys) */ lfd fr0,TSS_FPSCR-4(r5) mtfsf 0xff,fr0 @@ -1514,7 +1523,7 @@ stfd fr0,TSS_FPSCR-4(r4) lwz r5,PT_REGS(r4) lwz r3,_MSR-STACK_FRAME_OVERHEAD(r5) - li r4,MSR_FP + li r4,MSR_FP|MSR_FE0|MSR_FE1 andc r3,r3,r4 /* disable FP for previous task */ stw r3,_MSR-STACK_FRAME_OVERHEAD(r5) #else /* CONFIG_8xx */ @@ -1522,7 +1531,31 @@ giveup_fpu: #endif /* CONFIG_8xx */ blr - + +/* + * This code is jumped to from the startup code to copy + * the kernel image to physical address 0. + */ +relocate_kernel: + lis r9,0x426f /* if booted from BootX, don't */ + addi r9,r9,0x6f58 /* translate source addr */ + cmpw r31,r9 /* (we have to on chrp) */ + beq 7f + rlwinm r4,r4,0,8,31 /* translate source address */ + add r4,r4,r3 /* to region mapped with BATs */ +7: addis r9,r26,klimit@ha /* fetch klimit */ + lwz r25,klimit@l(r9) + addis r25,r25,-KERNELBASE@h + li r6,0 /* Destination offset */ + li r5,0x4000 /* # bytes of memory to copy */ + bl copy_and_flush /* copy the first 0x4000 bytes */ + addi r0,r3,4f@l /* jump to the address of 4f */ + mtctr r0 /* in copy and do the rest. */ + bctr /* jump to the copy */ +4: mr r5,r25 + bl copy_and_flush /* copy the rest */ + b turn_on_mmu + /* * Copy routine used to copy the kernel to start at physical address 0 * and flush and invalidate the caches as needed. @@ -1577,11 +1610,6 @@ bne 3f /* don't invalidate the D-cache */ ori r8,r8,HID0_DCI /* unless it wasn't enabled */ 3: - /* turn on dpm for 603 */ - cmpi 0,r9,3 - bne 10f - oris r11,r11,HID0_DPM@h -10: sync mtspr HID0,r8 /* enable and invalidate caches */ sync @@ -1633,6 +1661,7 @@ mr r7,r27 bl identify_machine bl MMU_init + /* * Go back to running unmapped so we can load up new values * for SDR1 (hash table pointer) and the segment registers @@ -1674,9 +1703,11 @@ addi r3,r3,1 /* increment VSID */ addis r4,r4,0x1000 /* address of next segment */ bdnz 3b - /* Load the BAT registers with the values set up by MMU_init. MMU_init takes care of whether we're on a 601 or not. */ + mfpvr r3 + srwi r3,r3,16 + cmpwi r3,1 lis r3,BATS@ha addi r3,r3,BATS@l tophys(r3,r3,r4) @@ -1696,6 +1727,20 @@ li r4,MSR_KERNEL lis r3,start_kernel@h ori r3,r3,start_kernel@l +#ifdef __SMP__ + /* the second time through here we go to + * start_secondary(). -- Cort + */ + lis r5,first_cpu_booted@h + ori r5,r5,first_cpu_booted@l + tophys(r5,r5,r3) + lwz r5,0(r5) + cmpi 0,r5,0 + beq 10f + lis r3,start_secondary@h + ori r3,r3,start_secondary@l +10: +#endif /* __SMP__ */ mtspr SRR0,r3 mtspr SRR1,r4 rfi /* enable MMU and jump to start_kernel */ @@ -2220,173 +2265,6 @@ */ _GLOBAL(__main) blr - -#ifdef __SMP__ -/* - * Secondary processor begins executing here. - */ - .globl secondary_entry -secondary_entry: - /* just like __start() with a few changes -- Cort */ - mfspr r9,PVR - rlwinm r9,r9,16,16,31 /* r9 = 1 for 601, 4 for 604 */ - cmpi 0,r9,1 - lis r11,KERNELBASE@h - bne 4f - ori r11,r11,4 /* set up BAT registers for 601 */ - li r8,0x7f - oris r9,r11,0x800000@h /* set up BAT reg for 2nd 8M */ - oris r10,r8,0x800000@h /* set up BAT reg for 2nd 8M */ - mtspr IBAT1U,r9 - mtspr IBAT1L,r10 - b 5f -4: ori r11,r11,0x1ff /* set up BAT registers for 604 */ - li r8,2 - mtspr DBAT0U,r11 - mtspr DBAT0L,r8 -5: mtspr IBAT0U,r11 - mtspr IBAT0L,r8 - isync -/* - * we now have the 1st 16M of ram mapped with the bats. - * prep needs the mmu to be turned on here, but pmac already has it on. - * this shouldn't bother the pmac since it just gets turned on again - * as we jump to our code at KERNELBASE. -- Cort - */ - mfmsr r0 - ori r0,r0,MSR_DR|MSR_IR - mtspr SRR1,r0 - lis r0,100f@h - ori r0,r0,100f@l - mtspr SRR0,r0 - SYNC - rfi /* enables MMU */ -100: - /* - * Enable caches and 604-specific features if necessary. - */ - mfspr r9,PVR - rlwinm r9,r9,16,16,31 - cmpi 0,r9,1 - beq 4f /* not needed for 601 */ - mfspr r11,HID0 - andi. r0,r11,HID0_DCE - ori r11,r11,HID0_ICE|HID0_DCE - ori r8,r11,HID0_ICFI - bne 3f /* don't invalidate the D-cache */ - ori r8,r8,HID0_DCI /* unless it wasn't enabled */ -3: - /* turn on dpm for 603 */ - cmpi 0,r9,3 - bne 10f - oris r11,r11,HID0_DPM@h -10: - sync - mtspr HID0,r8 /* enable and invalidate caches */ - sync - mtspr HID0,r11 /* enable caches */ - sync - isync - cmpi 0,r9,4 /* check for 604 */ - cmpi 1,r9,9 /* or 604e */ - cmpi 2,r9,10 /* or mach5 */ - cror 2,2,6 - cror 2,2,10 - bne 4f - ori r11,r11,HID0_SIED|HID0_BHTE /* for 604[e], enable */ - bne 2,5f - ori r11,r11,HID0_BTCD -5: mtspr HID0,r11 /* superscalar exec & br history tbl */ -4: -/* - * init_MMU on the first processor has setup the variables - * for us - all we need to do is load them -- Cort - */ - -/* - * Go back to running unmapped so we can load up new values - * for SDR1 (hash table pointer) and the segment registers - * and change to using our exception vectors. - */ - lis r6,_SDR1@ha - lwz r6,_SDR1@l(r6) - lis r4,2f@h - ori r4,r4,2f@l - tophys(r4,r4,r3) - li r3,MSR_KERNEL & ~(MSR_IR|MSR_DR) - mtspr SRR0,r4 - mtspr SRR1,r3 - rfi -/* Load up the kernel context */ -2: - /* get ptr to current */ - lis r2,current_set@h - ori r2,r2,current_set@l - /* assume we're second processor for now */ - tophys(r2,r2,r10) - lwz r2,4(r2) - /* stack */ - addi r1,r2,TASK_UNION_SIZE - li r0,0 - tophys(r3,r1,r10) - stwu r0,-STACK_FRAME_OVERHEAD(r3) - - SYNC /* Force all PTE updates to finish */ - tlbia /* Clear all TLB entries */ - mtspr SDR1,r6 - li r0,16 /* load up segment register values */ - mtctr r0 /* for context 0 */ - lis r3,0x2000 /* Ku = 1, VSID = 0 */ - li r4,0 -3: mtsrin r3,r4 - addi r3,r3,1 /* increment VSID */ - addis r4,r4,0x1000 /* address of next segment */ - bdnz 3b - -/* Load the BAT registers with the values set up by MMU_init. - MMU_init takes care of whether we're on a 601 or not. */ - lis r3,BATS@ha - addi r3,r3,BATS@l - tophys(r3,r3,r4) - LOAD_BAT(0,0,r3,r4,r5) - LOAD_BAT(1,16,r3,r4,r5) - LOAD_BAT(2,32,r3,r4,r5) - LOAD_BAT(3,48,r3,r4,r5) - -/* Set up for using our exception vectors */ - /* ptr to phys current tss */ - tophys(r4,r2,r4) - addi r4,r4,TSS /* init task's TSS */ - mtspr SPRG3,r4 - li r3,0 - mtspr SPRG2,r3 /* 0 => r1 has kernel sp */ - - /* need to flush/invalidate caches too */ - li r3,0x4000/CACHE_LINE_SIZE - li r4,0 - mtctr r3 -73: dcbst 0,r4 - addi r4,r4,CACHE_LINE_SIZE - bdnz 73b - sync - li r4,0 - mtctr r3 -72: icbi 0,r4 - addi r4,r4,CACHE_LINE_SIZE - bdnz 72b - sync - isync -77: -/* Now turn on the MMU for real! */ - li r4,MSR_KERNEL - lis r3,start_secondary@h - ori r3,r3,start_secondary@l - mtspr SRR0,r3 - mtspr SRR1,r4 - rfi /* enable MMU and jump to start_kernel */ -/* should never return */ - .long 0 -#endif /* __SMP__ */ /* * PROM code for specific machines follows. Put it diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/idle.c linux/arch/ppc/kernel/idle.c --- v2.1.123/linux/arch/ppc/kernel/idle.c Thu Aug 6 14:06:29 1998 +++ linux/arch/ppc/kernel/idle.c Wed Sep 30 10:14:17 1998 @@ -1,5 +1,5 @@ /* - * $Id: idle.c,v 1.48 1998/07/30 11:29:22 davem Exp $ + * $Id: idle.c,v 1.50 1998/08/18 16:19:25 cort Exp $ * * Idle daemon for PowerPC. Idle daemon will handle any action * that needs to be taken when the system becomes idle. @@ -53,8 +53,8 @@ __sti(); /* endless loop with no priority at all */ - current->priority = -100; - current->counter = -100; + current->priority = 0; + current->counter = 0; check_pgt_cache(); @@ -69,6 +69,7 @@ #ifndef __SMP__ if ( !current->need_resched ) power_save(); #endif /* __SMP__ */ + run_task_queue(&tq_scheduler); schedule(); } ret = 0; diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c --- v2.1.123/linux/arch/ppc/kernel/irq.c Thu Aug 6 14:06:29 1998 +++ linux/arch/ppc/kernel/irq.c Wed Sep 30 10:14:17 1998 @@ -50,55 +50,28 @@ #include #include #include +#include +#include +#include #ifdef CONFIG_8xx #include #include #endif -#include -#include -#include -#define VEC_SPUR (24) extern void process_int(unsigned long vec, struct pt_regs *fp); extern void apus_init_IRQ(void); extern void amiga_disable_irq(unsigned int irq); extern void amiga_enable_irq(unsigned int irq); +static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { } +static volatile unsigned char *gg2_int_ack_special; +extern volatile unsigned long ipi_count; + #ifdef CONFIG_APUS /* Rename a few functions. Requires the CONFIG_APUS protection. */ #define request_irq nop_ppc_request_irq #define free_irq nop_ppc_free_irq #define get_irq_list nop_get_irq_list #endif - -#undef SHOW_IRQ - -#define NR_MASK_WORDS ((NR_IRQS + 31) / 32) - -int max_irqs; -unsigned int local_irq_count[NR_CPUS]; -static struct irqaction *irq_action[NR_IRQS]; -static int spurious_interrupts = 0; -static unsigned int cached_irq_mask[NR_MASK_WORDS]; -unsigned int lost_interrupts[NR_MASK_WORDS]; -atomic_t n_lost_interrupts; - -static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { } - -/*spinlock_t irq_controller_lock = SPIN_LOCK_UNLOCKED;*/ -#ifdef __SMP__ -atomic_t __ppc_bh_counter = ATOMIC_INIT(0); -#else -int __ppc_bh_counter = 0; -#endif -static volatile unsigned char *gg2_int_ack_special; -extern volatile unsigned long ipi_count; - -#define cached_21 (((char *)(cached_irq_mask))[3]) -#define cached_A1 (((char *)(cached_irq_mask))[2]) - -/* - * These are set to the appropriate functions by init_IRQ() - */ #ifndef CONFIG_8xx void (*mask_and_ack_irq)(int irq_nr); void (*mask_irq)(unsigned int irq_nr); @@ -113,10 +86,22 @@ #define unmask_irq(irq) mbx_unmask_irq(irq) #endif /* CONFIG_8xx */ - -/* prep */ +#define VEC_SPUR (24) +#undef SHOW_IRQ +#define NR_MASK_WORDS ((NR_IRQS + 31) / 32) +#define cached_21 (((char *)(cached_irq_mask))[3]) +#define cached_A1 (((char *)(cached_irq_mask))[2]) #define PREP_IRQ_MASK (((unsigned int)cached_A1)<<8) | (unsigned int)cached_21 +unsigned int local_bh_count[NR_CPUS]; +unsigned int local_irq_count[NR_CPUS]; +int max_irqs; +static struct irqaction *irq_action[NR_IRQS]; +static int spurious_interrupts = 0; +static unsigned int cached_irq_mask[NR_MASK_WORDS]; +unsigned int lost_interrupts[NR_MASK_WORDS]; +atomic_t n_lost_interrupts; + /* pmac */ struct pmac_irq_hw { unsigned int flag; @@ -131,8 +116,6 @@ (struct pmac_irq_hw *) 0xf3000010, }; -#define KEYBOARD_IRQ 20 /* irq number for command-power interrupt */ - /* nasty hack for shared irq's since we need to do kmalloc calls but * can't very very early in the boot when we need to do a request irq. @@ -392,62 +375,108 @@ } +/* + * Global interrupt locks for SMP. Allow interrupts to come in on any + * CPU, yet make cli/sti act globally to protect critical regions.. + */ #ifdef __SMP__ -/* Who has global_irq_lock. */ unsigned char global_irq_holder = NO_PROC_ID; +unsigned volatile int global_irq_lock; +atomic_t global_irq_count; -/* This protects IRQ's. */ -spinlock_t global_irq_lock = SPIN_LOCK_UNLOCKED; -unsigned long previous_irqholder; +atomic_t global_bh_count; +atomic_t global_bh_lock; -/* This protects BH software state (masks, things like that). */ -spinlock_t global_bh_lock = SPIN_LOCK_UNLOCKED; +static void show(char * str) +{ + int i; + unsigned long *stack; + int cpu = smp_processor_id(); -/* Global IRQ locking depth. */ -atomic_t global_irq_count = ATOMIC_INIT(0); + printk("\n%s, CPU %d:\n", str, cpu); + printk("irq: %d [%d %d]\n", + atomic_read(&global_irq_count), local_irq_count[0], local_irq_count[1]); + printk("bh: %d [%d %d]\n", + atomic_read(&global_bh_count), local_bh_count[0], local_bh_count[1]); + stack = (unsigned long *) &str; + for (i = 40; i ; i--) { + unsigned long x = *++stack; + if (x > (unsigned long) &init_task_union && x < (unsigned long) &vsprintf) { + printk("<[%08lx]> ", x); + } + } +} -#undef INIT_STUCK -#define INIT_STUCK 100000000 +#define MAXCOUNT 100000000 +static inline void wait_on_bh(void) +{ + int count = MAXCOUNT; + do { + if (!--count) { + show("wait_on_bh"); + count = ~0; + } + /* nothing .. wait for the other bh's to go away */ + } while (atomic_read(&global_bh_count) != 0); +} -#undef STUCK -#define STUCK \ -if (!--stuck) {printk("wait_on_irq CPU#%d stuck at %08lx, waiting for %08lx (local=%d, global=%d)\n", cpu, where, previous_irqholder, local_count, atomic_read(&global_irq_count)); stuck = INIT_STUCK; } -void wait_on_irq(int cpu, unsigned long where) +#define MAXCOUNT 100000000 +static inline void wait_on_irq(int cpu) { - int stuck = INIT_STUCK; - int local_count = local_irq_count[cpu]; + int count = MAXCOUNT; - /* Are we the only one in an interrupt context? */ - while (local_count != atomic_read(&global_irq_count)) { - /* - * No such luck. Now we need to release the lock, - * _and_ release our interrupt context, because - * otherwise we'd have dead-locks and live-locks - * and other fun things. - */ - atomic_sub(local_count, &global_irq_count); - spin_unlock(&global_irq_lock); + for (;;) { /* - * Wait for everybody else to go away and release - * their things before trying to get the lock again. + * Wait until all interrupts are gone. Wait + * for bottom half handlers unless we're + * already executing in one.. */ + if (!atomic_read(&global_irq_count)) { + if (local_bh_count[cpu] || !atomic_read(&global_bh_count)) + break; + } + + /* Duh, we have to loop. Release the lock to avoid deadlocks */ + clear_bit(0,&global_irq_lock); + for (;;) { - STUCK; + if (!--count) { + show("wait_on_irq"); + count = ~0; + } + __sti(); + /* don't worry about the lock race Linus found + * on intel here. -- Cort + */ + __cli(); if (atomic_read(&global_irq_count)) continue; - if (*((unsigned char *)&global_irq_lock)) + if (global_irq_lock) continue; - if (spin_trylock(&global_irq_lock)) + if (!local_bh_count[cpu] && atomic_read(&global_bh_count)) + continue; + if (!test_and_set_bit(0,&global_irq_lock)) break; } - atomic_add(local_count, &global_irq_count); } } -#define irq_active(cpu) \ - (global_irq_count != local_irq_count[cpu]) +/* + * This is called when we want to synchronize with + * bottom half handlers. We need to wait until + * no other CPU is executing any bottom half handler. + * + * Don't wait if we're already running in an interrupt + * context or are inside a bh handler. + */ +void synchronize_bh(void) +{ + if (atomic_read(&global_bh_count) && !in_interrupt()) + wait_on_bh(); +} + /* * This is called when we want to synchronize with @@ -455,95 +484,124 @@ * stop sending interrupts: but to make sure there * are no interrupts that are executing on another * CPU we need to call this function. - * - * On UP this is a no-op. */ void synchronize_irq(void) { - int cpu = smp_processor_id(); - int local_count = local_irq_count[cpu]; - - /* Do we need to wait? */ - if (local_count != atomic_read(&global_irq_count)) { - /* The stupid way to do this */ + if (atomic_read(&global_irq_count)) { + /* Stupid approach */ cli(); sti(); } } -#undef INIT_STUCK -#define INIT_STUCK 10000000 - -#undef STUCK -#define STUCK \ -if (!--stuck) {\ -ll_printk("get_irqlock stuck at %08lx, waiting for %08lx\n", where, previous_irqholder); stuck = INIT_STUCK;} - -void get_irqlock(int cpu, unsigned long where) +static inline void get_irqlock(int cpu) { - int stuck = INIT_STUCK; - if (!spin_trylock(&global_irq_lock)) { + if (test_and_set_bit(0,&global_irq_lock)) { /* do we already hold the lock? */ if ((unsigned char) cpu == global_irq_holder) return; /* Uhhuh.. Somebody else got it. Wait.. */ do { do { - STUCK; - barrier(); - } while (*((unsigned char *)&global_irq_lock)); - } while (!spin_trylock(&global_irq_lock)); + + } while (test_bit(0,&global_irq_lock)); + } while (test_and_set_bit(0,&global_irq_lock)); } - - /* - * Ok, we got the lock bit. - * But that's actually just the easy part.. Now - * we need to make sure that nobody else is running + /* + * We also to make sure that nobody else is running * in an interrupt context. */ - wait_on_irq(cpu, where); + wait_on_irq(cpu); + /* - * Finally. + * Ok, finally.. */ global_irq_holder = cpu; - previous_irqholder = where; } +/* + * A global "cli()" while in an interrupt context + * turns into just a local cli(). Interrupts + * should use spinlocks for the (very unlikely) + * case that they ever want to protect against + * each other. + * + * If we already have local interrupts disabled, + * this will not turn a local disable into a + * global one (problems with spinlocks: this makes + * save_flags+cli+sti usable inside a spinlock). + */ void __global_cli(void) { - int cpu = smp_processor_id(); - unsigned long where; - __asm__("mr %0,31" : "=r" (where)); /* get lr */ - __cli(); - get_irqlock(cpu, where); + unsigned int flags; + + __save_flags(flags); + if (flags & (1 << 15)) { + int cpu = smp_processor_id(); + __cli(); + if (!local_irq_count[cpu]) + get_irqlock(cpu); + } } void __global_sti(void) { - release_irqlock(smp_processor_id()); + int cpu = smp_processor_id(); + + if (!local_irq_count[cpu]) + release_irqlock(cpu); __sti(); } +/* + * SMP flags value to restore to: + * 0 - global cli + * 1 - global sti + * 2 - local cli + * 3 - local sti + */ unsigned long __global_save_flags(void) { - return global_irq_holder == (unsigned char) smp_processor_id(); + int retval; + int local_enabled; + unsigned long flags; + + __save_flags(flags); + local_enabled = (flags >> 15) & 1; + /* default to local */ + retval = 2 + local_enabled; + + /* check for global flags if we're not in an interrupt */ + if (!local_irq_count[smp_processor_id()]) { + if (local_enabled) + retval = 1; + if (global_irq_holder == (unsigned char) smp_processor_id()) + retval = 0; + } + return retval; } void __global_restore_flags(unsigned long flags) { switch (flags) { case 0: - release_irqlock(smp_processor_id()); - __sti(); + __global_cli(); break; case 1: - __global_cli(); + __global_sti(); + break; + case 2: + __cli(); + break; + case 3: + __sti(); break; default: printk("global_restore_flags: %08lx (%08lx)\n", flags, (&flags)[-1]); } } + #endif /* __SMP__ */ @@ -867,7 +925,7 @@ for (i = 0; i * 32 < max_irqs; ++i) out_le32(&pmac_irq_hw[i]->enable, 0); #ifdef CONFIG_XMON - request_irq(KEYBOARD_IRQ, xmon_irq, 0, "NMI", 0); + request_irq(20, xmon_irq, 0, "NMI", 0); #endif /* CONFIG_XMON */ break; case _MACH_chrp: @@ -876,7 +934,7 @@ unmask_irq = chrp_unmask_irq; gg2_int_ack_special = (volatile unsigned char *) ioremap(GG2_INT_ACK_SPECIAL, 1); - openpic_init(); + openpic_init(1); i8259_init(); cached_irq_mask[0] = cached_irq_mask[1] = ~0UL; #ifdef CONFIG_XMON diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/misc.S linux/arch/ppc/kernel/misc.S --- v2.1.123/linux/arch/ppc/kernel/misc.S Thu Aug 6 14:06:29 1998 +++ linux/arch/ppc/kernel/misc.S Wed Sep 30 10:14:17 1998 @@ -370,15 +370,39 @@ _GLOBAL(_get_L2CR) mfspr r3,L2CR blr - + +_GLOBAL(_set_L2CR) + mtspr L2CR,r3 + blr + _GLOBAL(_get_PVR) mfspr r3,PVR blr +/* + * These are used in the alignment trap handler when emulating + * single-precision loads and stores. + * We restore and save the fpscr so the task gets the same result + * and exceptions as if the cpu had performed the load or store. + */ _GLOBAL(cvt_fd) cvt_fd: + lfd 0,-4(r5) /* load up fpscr value */ + mtfsf 0xff,0 lfs 0,0(r3) stfd 0,0(r4) + mffs 0 /* save new fpscr value */ + stfd 0,-4(r5) + blr + +_GLOBAL(cvt_df) +cvt_df: + lfd 0,-4(r5) /* load up fpscr value */ + mtfsf 0xff,0 + lfd 0,0(r3) + stfs 0,0(r4) + mffs 0 /* save new fpscr value */ + stfd 0,-4(r5) blr /* @@ -390,12 +414,6 @@ mr r3,r4 blr -_GLOBAL(cvt_df) -cvt_df: - lfd 0,0(r3) - stfs 0,0(r4) - blr - /* * Create a kernel thread * __kernel_thread(flags, fn, arg) @@ -455,7 +473,7 @@ .align 4 .globl sys_call_table sys_call_table: - .long sys_setup /* 0 */ + .long sys_ni_syscall /* 0 - old "setup()" system call */ .long sys_exit .long sys_fork .long sys_read @@ -638,4 +656,10 @@ .long sys_pwrite /* 180 */ .long sys_chown .long sys_getcwd + .long sys_capget + .long sys_capset + .long sys_sigaltstack /* 185 */ + .long sys_sendfile + .long sys_ni_syscall + .long sys_ni_syscall .space (NR_syscalls-183)*4 diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/openpic.c linux/arch/ppc/kernel/openpic.c --- v2.1.123/linux/arch/ppc/kernel/openpic.c Fri May 8 23:14:45 1998 +++ linux/arch/ppc/kernel/openpic.c Wed Sep 30 10:14:17 1998 @@ -133,7 +133,7 @@ return val & mask; } -static inline void openpic_writefield(volatile u_int *addr, u_int mask, +inline void openpic_writefield(volatile u_int *addr, u_int mask, u_int field) { u_int val = openpic_read(addr); @@ -173,7 +173,7 @@ * Initialize the OpenPIC */ -__initfunc(void openpic_init(void)) +__initfunc(void openpic_init(int main_pic)) { u_int t, i; u_int vendorid, devid, stepping, timerfreq; @@ -233,41 +233,44 @@ else printk("not set\n"); - /* Initialize timer interrupts */ - for (i = 0; i < OPENPIC_NUM_TIMERS; i++) { - /* Disabled, Priority 0 */ - openpic_inittimer(i, 0, OPENPIC_VEC_TIMER+i); - /* No processor */ - openpic_maptimer(i, 0); + if ( main_pic ) + { + /* Initialize timer interrupts */ + for (i = 0; i < OPENPIC_NUM_TIMERS; i++) { + /* Disabled, Priority 0 */ + openpic_inittimer(i, 0, OPENPIC_VEC_TIMER+i); + /* No processor */ + openpic_maptimer(i, 0); + } + + /* Initialize IPI interrupts */ + for (i = 0; i < OPENPIC_NUM_IPI; i++) { + /* Disabled, Priority 0 */ + openpic_initipi(i, 0, OPENPIC_VEC_IPI+i); + } + + /* Initialize external interrupts */ + /* SIOint (8259 cascade) is special */ + openpic_initirq(0, 8, OPENPIC_VEC_SOURCE, 1, 1); + /* Processor 0 */ + openpic_mapirq(0, 1<<0); + for (i = 1; i < NumSources; i++) { + /* Enabled, Priority 8 */ + openpic_initirq(i, 8, OPENPIC_VEC_SOURCE+i, 0, + i < OpenPIC_NumInitSenses ? OpenPIC_InitSenses[i] : 1); + /* Processor 0 */ + openpic_mapirq(i, 1<<0); + } + + /* Initialize the spurious interrupt */ + openpic_set_spurious(OPENPIC_VEC_SPURIOUS); + + if (request_irq(IRQ_8259_CASCADE, no_action, SA_INTERRUPT, + "82c59 cascade", NULL)) + printk("Unable to get OpenPIC IRQ 0 for cascade\n"); + openpic_set_priority(0, 0); + openpic_disable_8259_pass_through(); } - - /* Initialize IPI interrupts */ - for (i = 0; i < OPENPIC_NUM_IPI; i++) { - /* Disabled, Priority 0 */ - openpic_initipi(i, 0, OPENPIC_VEC_IPI+i); - } - - /* Initialize external interrupts */ - /* SIOint (8259 cascade) is special */ - openpic_initirq(0, 8, OPENPIC_VEC_SOURCE, 1, 1); - /* Processor 0 */ - openpic_mapirq(0, 1<<0); - for (i = 1; i < NumSources; i++) { - /* Enabled, Priority 8 */ - openpic_initirq(i, 8, OPENPIC_VEC_SOURCE+i, 0, - i < OpenPIC_NumInitSenses ? OpenPIC_InitSenses[i] : 1); - /* Processor 0 */ - openpic_mapirq(i, 1<<0); - } - - /* Initialize the spurious interrupt */ - openpic_set_spurious(OPENPIC_VEC_SPURIOUS); - - if (request_irq(IRQ_8259_CASCADE, no_action, SA_INTERRUPT, - "82c59 cascade", NULL)) - printk("Unable to get OpenPIC IRQ 0 for cascade\n"); - openpic_set_priority(0, 0); - openpic_disable_8259_pass_through(); } @@ -529,5 +532,3 @@ OPENPIC_SENSE_LEVEL, (sense ? OPENPIC_SENSE_LEVEL : 0)); } - - diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/pci.c linux/arch/ppc/kernel/pci.c --- v2.1.123/linux/arch/ppc/kernel/pci.c Thu Aug 6 14:06:29 1998 +++ linux/arch/ppc/kernel/pci.c Wed Sep 30 10:14:17 1998 @@ -1,5 +1,5 @@ /* - * $Id: pci.c,v 1.36 1998/08/02 23:22:11 paulus Exp $ + * $Id: pci.c,v 1.38 1998/08/31 06:28:02 cort Exp $ * Common pmac/prep/chrp pci routines. -- Cort */ @@ -201,8 +201,22 @@ route_pci_interrupts(); for(dev=pci_devices; dev; dev=dev->next) { + /* + * Use our old hard-coded kludge to figure out what + * irq this device uses. This is necessary on things + * without residual data. -- Cort + */ unsigned char d = PCI_SLOT(dev->devfn); dev->irq = Motherboard_routes[Motherboard_map[d]]; +#if 0 + /* + * If we have residual data and if it knows about this + * device ask it what the irq is. + * -- Cort + */ + ppcd = residual_find_device_id( ~0L, dev->device, + -1,-1,-1, 0); +#endif } break; case _MACH_chrp: diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/pmac_setup.c linux/arch/ppc/kernel/pmac_setup.c --- v2.1.123/linux/arch/ppc/kernel/pmac_setup.c Thu Aug 27 19:56:29 1998 +++ linux/arch/ppc/kernel/pmac_setup.c Wed Sep 30 10:14:17 1998 @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -53,10 +54,10 @@ #include #include "time.h" -extern int root_mountflags; - unsigned char drive_info; +extern char saved_command_line[]; + #define DEFAULT_ROOT_DEVICE 0x0801 /* sda1 - slightly silly choice */ extern void zs_kgdb_hook(int tty_num); @@ -68,8 +69,70 @@ pmac_get_cpuinfo(char *buffer) { int len; - /* should find motherboard type here as well */ - len = sprintf(buffer,"machine\t\t: PowerMac\n"); + struct device_node *np; + char *pp; + int plen; + + /* find motherboard type */ + len = sprintf(buffer, "machine\t\t: "); + np = find_devices("device-tree"); + if (np != NULL) { + pp = (char *) get_property(np, "model", NULL); + if (pp != NULL) + len += sprintf(buffer+len, "%s\n", pp); + else + len += sprintf(buffer+len, "PowerMac\n"); + pp = (char *) get_property(np, "compatible", &plen); + if (pp != NULL) { + len += sprintf(buffer+len, "motherboard\t:"); + while (plen > 0) { + int l = strlen(pp) + 1; + len += sprintf(buffer+len, " %s", pp); + plen -= l; + pp += l; + } + buffer[len++] = '\n'; + } + } else + len += sprintf(buffer+len, "PowerMac\n"); + + /* find l2 cache info */ + np = find_devices("l2-cache"); + if (np == 0) + np = find_type_devices("cache"); + if (np != 0) { + unsigned int *ic = (unsigned int *) + get_property(np, "i-cache-size", NULL); + unsigned int *dc = (unsigned int *) + get_property(np, "d-cache-size", NULL); + len += sprintf(buffer+len, "L2 cache\t:"); + if (get_property(np, "cache-unified", NULL) != 0 && dc) { + len += sprintf(buffer+len, " %dK unified", *dc / 1024); + } else { + if (ic) + len += sprintf(buffer+len, " %dK instruction", + *ic / 1024); + if (dc) + len += sprintf(buffer+len, "%s %dK data", + (ic? " +": ""), *dc / 1024); + } + pp = get_property(np, "ram-type", NULL); + if (pp) + len += sprintf(buffer+len, " %s", pp); + buffer[len++] = '\n'; + } + + /* find ram info */ + np = find_devices("memory"); + if (np != 0) { + struct reg_property *reg = (struct reg_property *) + get_property(np, "reg", NULL); + if (reg != 0) { + len += sprintf(buffer+len, "memory\t\t: %dMB\n", + reg->size >> 20); + } + } + return len; } @@ -154,6 +217,13 @@ #endif kd_mksound = pmac_mksound; + +#ifdef CONFIG_BLK_DEV_INITRD + if (initrd_start) + ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); + else +#endif + ROOT_DEV = to_kdev_t(DEFAULT_ROOT_DEVICE); } __initfunc(static void ohare_init(void)) @@ -210,6 +280,7 @@ } } +#ifdef CONFIG_SCSI __initfunc(void note_scsi_host(struct device_node *node, void *host)) { @@ -238,28 +309,65 @@ } } } +#endif -__initfunc(void find_boot_device(void)) +#ifdef CONFIG_BLK_DEV_IDE_PMAC +extern int pmac_ide_count; +extern struct device_node *pmac_ide_node[]; +static int ide_majors[] = { 3, 22, 33, 34, 56, 57 }; + +__initfunc(kdev_t find_ide_boot(void)) { - kdev_t dev; + char *p; + int i, n; - if (kdev_t_to_nr(ROOT_DEV) != 0) - return; - ROOT_DEV = to_kdev_t(DEFAULT_ROOT_DEVICE); - if (boot_host == NULL) - return; + if (bootdevice == NULL) + return 0; + p = strrchr(bootdevice, '/'); + if (p == NULL) + return 0; + n = p - bootdevice; + + /* + * Look through the list of IDE interfaces for this one. + */ + for (i = 0; i < pmac_ide_count; ++i) { + char *name = pmac_ide_node[i]->full_name; + if (memcmp(name, bootdevice, n) == 0 && name[n] == 0) { + /* XXX should cope with the 2nd drive as well... */ + return MKDEV(ide_majors[i], 0); + } + } + + return 0; +} +#endif /* CONFIG_BLK_DEV_IDE_PMAC */ + +__initfunc(void find_boot_device(void)) +{ #ifdef CONFIG_SCSI - dev = sd_find_target(boot_host, boot_target); - if (dev == 0) - return; - boot_dev = MKDEV(MAJOR(dev), MINOR(dev) + boot_part); + if (boot_host != NULL) { + boot_dev = sd_find_target(boot_host, boot_target); + if (boot_dev != 0) + return; + } +#endif +#ifdef CONFIG_BLK_DEV_IDE_PMAC + boot_dev = find_ide_boot(); #endif - /* XXX should cope with booting from IDE also */ } __initfunc(void note_bootable_part(kdev_t dev, int part)) { static int found_boot = 0; + char *p; + + /* Do nothing if the root has been set already. */ + if (ROOT_DEV != to_kdev_t(DEFAULT_ROOT_DEVICE)) + return; + p = strstr(saved_command_line, "root="); + if (p != NULL && (p == saved_command_line || p[-1] == ' ')) + return; if (!found_boot) { find_boot_device(); diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/ppc_defs.h linux/arch/ppc/kernel/ppc_defs.h --- v2.1.123/linux/arch/ppc/kernel/ppc_defs.h Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/kernel/ppc_defs.h Wed Sep 30 10:14:17 1998 @@ -0,0 +1,69 @@ +/* + * WARNING! This file is automatically generated - DO NOT EDIT! + */ +#define KERNELBASE -1073741824 +#define STATE 0 +#define NEXT_TASK 48 +#define COUNTER 24 +#define PROCESSOR 36 +#define SIGPENDING 8 +#define TSS 568 +#define MM 872 +#define TASK_STRUCT_SIZE 912 +#define KSP 0 +#define PG_TABLES 4 +#define PGD 8 +#define LAST_SYSCALL 20 +#define PT_REGS 12 +#define PF_TRACESYS 32 +#define TASK_FLAGS 4 +#define NEED_RESCHED 20 +#define TSS_FPR0 24 +#define TSS_FPSCR 284 +#define TSS_SMP_FORK_RET 288 +#define TASK_UNION_SIZE 8192 +#define STACK_FRAME_OVERHEAD 16 +#define INT_FRAME_SIZE 192 +#define GPR0 16 +#define GPR1 20 +#define GPR2 24 +#define GPR3 28 +#define GPR4 32 +#define GPR5 36 +#define GPR6 40 +#define GPR7 44 +#define GPR8 48 +#define GPR9 52 +#define GPR10 56 +#define GPR11 60 +#define GPR12 64 +#define GPR13 68 +#define GPR14 72 +#define GPR15 76 +#define GPR16 80 +#define GPR17 84 +#define GPR18 88 +#define GPR19 92 +#define GPR20 96 +#define GPR21 100 +#define GPR22 104 +#define GPR23 108 +#define GPR24 112 +#define GPR25 116 +#define GPR26 120 +#define GPR27 124 +#define GPR28 128 +#define GPR29 132 +#define GPR30 136 +#define GPR31 140 +#define _NIP 144 +#define _MSR 148 +#define _CTR 156 +#define _LINK 160 +#define _CCR 168 +#define _XER 164 +#define _DAR 180 +#define _DSISR 184 +#define ORIG_GPR3 152 +#define RESULT 188 +#define TRAP 176 diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/ppc_htab.c linux/arch/ppc/kernel/ppc_htab.c --- v2.1.123/linux/arch/ppc/kernel/ppc_htab.c Wed Aug 26 11:37:34 1998 +++ linux/arch/ppc/kernel/ppc_htab.c Wed Sep 30 10:14:17 1998 @@ -1,5 +1,5 @@ /* - * $Id: ppc_htab.c,v 1.21 1998/05/13 22:34:55 cort Exp $ + * $Id: ppc_htab.c,v 1.25 1998/08/26 10:28:26 davem Exp $ * * PowerPC hash table management proc entry. Will show information * about the current hash table and will allow changes to it. @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include #include @@ -31,6 +33,8 @@ static ssize_t ppc_htab_write(struct file * file, const char * buffer, size_t count, loff_t *ppos); static long long ppc_htab_lseek(struct file * file, loff_t offset, int orig); +int proc_dol2crvec(ctl_table *table, int write, struct file *filp, + void *buffer, size_t *lenp); extern PTE *Hash, *Hash_end; extern unsigned long Hash_size, Hash_mask; @@ -518,4 +522,148 @@ default: return(-EINVAL); } +} + +int proc_dol2crvec(ctl_table *table, int write, struct file *filp, + void *buffer, size_t *lenp) +{ + int vleft, first=1, len, left, val; + #define TMPBUFLEN 256 + char buf[TMPBUFLEN], *p; + + if ( (_get_PVR() >> 16) != 8) return -EFAULT; + + if ( /*!table->maxlen ||*/ (filp->f_pos && !write)) { + *lenp = 0; + return 0; + } + + vleft = table->maxlen / sizeof(int); + left = *lenp; + + for (; left /*&& vleft--*/; first=0) { + if (write) { + while (left) { + char c; + if(get_user(c,(char *) buffer)) + return -EFAULT; + if (!isspace(c)) + break; + left--; + ((char *) buffer)++; + } + if (!left) + break; + len = left; + if (len > TMPBUFLEN-1) + len = TMPBUFLEN-1; + if(copy_from_user(buf, buffer, len)) + return -EFAULT; + buf[len] = 0; + p = buf; + if (*p < '0' || *p > '9') + break; + val = simple_strtoul(p, &p, 0); + len = p-buf; + if ((len < left) && *p && !isspace(*p)) + break; + buffer += len; + left -= len; + _set_L2CR(val); + while ( _get_L2CR() & 0x1 ) + /* wait for invalidate to finish */; + + } else { + p = buf; + if (!first) + *p++ = '\t'; + val = _get_L2CR(); + p += sprintf(p, "%08x: ", val); + p += sprintf(p, " %s", + (val&0x80000000)?"enabled":"disabled"); + p += sprintf(p,",%sparity",(val&0x40000000)?"":"no "); + + switch( (val >> 28) & 0x3 ) + { + case 1: p += sprintf(p,",256Kb"); + break; + case 2: p += sprintf(p,",512Kb"); + break; + case 3: p += sprintf(p,",1M"); + break; + default: p += sprintf(p,",unknown size"); + break; + } + + + switch( (val >> 25) & 0x7 ) + { + case 0: p += sprintf(p,",clock disabled"); + break; + case 1: p += sprintf(p,",+1 clock"); + break; + case 2: p += sprintf(p,",+1.5 clock"); + break; + case 7: + case 3: p += sprintf(p,",reserved clock"); + break; + case 4: p += sprintf(p,",+2 clock"); + break; + case 5: p += sprintf(p,",+2.5 clock"); + break; + case 6: p += sprintf(p,",+3 clock"); + break; + } + + switch( (val >> 23) & 0x2 ) + { + case 0: p += sprintf(p,",flow-through burst SRAM"); + break; + case 1: p += sprintf(p,",reserved SRAM"); + break; + case 2: p += sprintf(p,",pipelined burst SRAM"); + break; + case 3: p += sprintf(p,",pipelined late-write SRAM"); + break; + } + + p += sprintf(p,"%s",(val>>22)?"":",data only"); + p += sprintf(p,"%s",(val>>20)?",ZZ enabled":""); + p += sprintf(p,",%s",(val>>19)?"write-through":"copy-back"); + p += sprintf(p,",%sns hold",(val>>16)?"1.0":"0.5"); + + p += sprintf(p,"\n"); + + len = strlen(buf); + if (len > left) + len = left; + if(copy_to_user(buffer, buf, len)) + return -EFAULT; + left -= len; + buffer += len; + break; + } + } + + if (!write && !first && left) { + if(put_user('\n', (char *) buffer)) + return -EFAULT; + left--, buffer++; + } + if (write) { + p = (char *) buffer; + while (left) { + char c; + if(get_user(c, p++)) + return -EFAULT; + if (!isspace(c)) + break; + left--; + } + } + if (write && first) + return -EINVAL; + *lenp -= left; + filp->f_pos += *lenp; + return 0; } diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/ppc_ksyms.c linux/arch/ppc/kernel/ppc_ksyms.c --- v2.1.123/linux/arch/ppc/kernel/ppc_ksyms.c Thu Aug 6 14:06:29 1998 +++ linux/arch/ppc/kernel/ppc_ksyms.c Wed Sep 30 10:14:17 1998 @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -56,10 +57,10 @@ EXPORT_SYMBOL(sys_sigreturn); EXPORT_SYMBOL(n_lost_interrupts); EXPORT_SYMBOL(do_lost_interrupts); -EXPORT_SYMBOL(__ppc_bh_counter); EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL(local_irq_count); +EXPORT_SYMBOL(local_bh_count); EXPORT_SYMBOL(isa_io_base); EXPORT_SYMBOL(isa_mem_base); @@ -99,6 +100,7 @@ EXPORT_SYMBOL(strspn); EXPORT_SYMBOL(strcmp); EXPORT_SYMBOL(strncmp); +EXPORT_SYMBOL(strnicmp); EXPORT_SYMBOL(memset); EXPORT_SYMBOL(memcpy); EXPORT_SYMBOL(memmove); @@ -137,6 +139,9 @@ EXPORT_SYMBOL(ioremap); EXPORT_SYMBOL(__ioremap); EXPORT_SYMBOL(iounmap); + +EXPORT_SYMBOL(ide_insw); +EXPORT_SYMBOL(ide_outsw); EXPORT_SYMBOL(start_thread); EXPORT_SYMBOL(__kernel_thread); diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/prep_pci.c linux/arch/ppc/kernel/prep_pci.c --- v2.1.123/linux/arch/ppc/kernel/prep_pci.c Thu Aug 6 14:06:29 1998 +++ linux/arch/ppc/kernel/prep_pci.c Wed Sep 30 10:14:17 1998 @@ -1,5 +1,5 @@ /* - * $Id: prep_pci.c,v 1.20 1998/06/19 16:48:45 cort Exp $ + * $Id: prep_pci.c,v 1.22 1998/08/05 20:11:15 cort Exp $ * PReP pci functions. * Originally by Gary Thomas * rewritten and updated by Cort Dougan (cort@cs.nmt.edu) @@ -234,6 +234,44 @@ 15, /* Line 4 */ }; +/* + * a 6015 ibm board + * -- Cort + */ +static char ibm6015_pci_IRQ_map[23] __prepdata = { + 0, /* Slot 0 - unused */ + 0, /* Slot 1 - unused */ + 0, /* Slot 2 - unused */ + 0, /* Slot 3 - unused */ + 0, /* Slot 4 - unused */ + 0, /* Slot 5 - unused */ + 0, /* Slot 6 - unused */ + 0, /* Slot 7 - unused */ + 0, /* Slot 8 - unused */ + 0, /* Slot 9 - unused */ + 0, /* Slot 10 - unused */ + 0, /* Slot 11 - */ + 1, /* Slot 12 - SCSI */ + 2, /* Slot 13 - */ + 2, /* Slot 14 - */ + 1, /* Slot 15 - */ + 1, /* Slot 16 - */ + 0, /* Slot 17 - */ + 2, /* Slot 18 - */ + 0, /* Slot 19 - */ + 0, /* Slot 20 - */ + 0, /* Slot 21 - */ + 2, /* Slot 22 - */ +}; +static char ibm6015_pci_IRQ_routes[] __prepdata = { + 0, /* Line 0 - unused */ + 13, /* Line 1 */ + 10, /* Line 2 */ + 15, /* Line 3 */ + 15, /* Line 4 */ +}; + + /* IBM Nobis and 850 */ static char Nobis_pci_IRQ_map[23] __prepdata ={ 0, /* Slot 0 - unused */ @@ -434,16 +472,31 @@ } else if ( _prep_type == _PREP_IBM ) { unsigned char pl_id; - - if (inb(0x0852) == 0xFF) { + /* + * my carolina is 0xf0 + * 6015 has 0xfc + * -- Cort + */ + printk("IBM ID: %08x\n", inb(0x0852)); + switch(inb(0x0852)) + { + case 0xff: Motherboard_map_name = "IBM 850/860 Portable\n"; Motherboard_map = Nobis_pci_IRQ_map; Motherboard_routes = Nobis_pci_IRQ_routes; - } else { + break; + case 0xfc: + Motherboard_map_name = "IBM 6015"; + Motherboard_map = ibm6015_pci_IRQ_map; + Motherboard_routes = ibm6015_pci_IRQ_routes; + break; + default: Motherboard_map_name = "IBM 8xx (Carolina)"; Motherboard_map = ibm8xx_pci_IRQ_map; Motherboard_routes = ibm8xx_pci_IRQ_routes; + break; } + /*printk("Changing IRQ mode\n");*/ pl_id=inb(0x04d0); /*printk("Low mask is %#0x\n", pl_id);*/ diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/prep_setup.c linux/arch/ppc/kernel/prep_setup.c --- v2.1.123/linux/arch/ppc/kernel/prep_setup.c Thu Aug 6 14:06:29 1998 +++ linux/arch/ppc/kernel/prep_setup.c Wed Sep 30 10:14:17 1998 @@ -76,26 +76,70 @@ #endif len = sprintf(buffer,"machine\t\t: PReP %s\n",Motherboard_map_name); + - len += sprintf(buffer+len,"L2\t\t: "); - switch(*((unsigned char *)CACHECRBA) & L2CACHE_MASK) + switch ( _prep_type ) { - case L2CACHE_512KB: - len += sprintf(buffer+len,"512Kb\n"); - break; - case L2CACHE_256KB: - len += sprintf(buffer+len,"256Kb\n"); - break; - case L2CACHE_1MB: - len += sprintf(buffer+len,"1MB\n"); + case _PREP_IBM: + if ((*(unsigned char *)0x8000080c) & (1<<6)) + len += sprintf(buffer+len,"Upgrade CPU\n"); + len += sprintf(buffer+len,"L2\t\t: "); + if ((*(unsigned char *)0x8000080c) & (1<<7)) + { + len += sprintf(buffer+len,"not present\n"); + goto no_l2; + } + len += sprintf(buffer+len,"%sKb,", + (((*(unsigned char *)0x8000080d)>>2)&1)?"512":"256"); + len += sprintf(buffer+len,"%sync\n", + ((*(unsigned char *)0x8000080d)>>7) ? "":"a"); break; - case L2CACHE_NONE: - len += sprintf(buffer+len,"none\n"); + case _PREP_Motorola: + len += sprintf(buffer+len,"L2\t\t: "); + switch(*((unsigned char *)CACHECRBA) & L2CACHE_MASK) + { + case L2CACHE_512KB: + len += sprintf(buffer+len,"512Kb"); + break; + case L2CACHE_256KB: + len += sprintf(buffer+len,"256Kb"); + break; + case L2CACHE_1MB: + len += sprintf(buffer+len,"1MB"); + break; + case L2CACHE_NONE: + len += sprintf(buffer+len,"none\n"); + goto no_l2; + break; + default: + len += sprintf(buffer+len, "%x\n", + *((unsigned char *)CACHECRBA)); + } + + len += sprintf(buffer+len,",parity %s", + (*((unsigned char *)CACHECRBA) & L2CACHE_PARITY) ? + "enabled" : "disabled"); + + len += sprintf(buffer+len, " SRAM:"); + + switch ( ((*((unsigned char *)CACHECRBA) & 0xf0) >> 4) & ~(0x3) ) + { + case 1: len += sprintf(buffer+len, + "synchronous,parity,flow-through\n"); + break; + case 2: len += sprintf(buffer+len,"asynchronous,no parity\n"); + break; + case 3: len += sprintf(buffer+len,"asynchronous,parity\n"); + break; + default:len += sprintf(buffer+len, + "synchronous,pipelined,no parity\n"); + break; + } break; - default: - len += sprintf(buffer+len,"%x\n", *((unsigned char *)CACHECRBA)); } - + + +no_l2: if ( res->ResidualLength == 0 ) return len; @@ -111,20 +155,6 @@ } len += sprintf(buffer+len,"\n"); -#if 0 - /* L2 */ - if ( (inb(IBM_EQUIP_PRESENT) & 1) == 0) /* l2 present */ - { - len += sprintf(buffer+len,"l2\t\t: %dkB %s\n", - ((inb(IBM_L2_STATUS) >> 5) & 1) ? 512 : 256, - (inb(IBM_SYS_CTL) & 64) ? "enabled" : "disabled"); - } - else - { - len += sprintf(buffer+len,"l2\t\t: not present\n"); - } -#endif - return len; } @@ -155,6 +185,9 @@ ROOT_DEV = to_kdev_t(0x0801); /* sda1 */ break; } + + /* Enable L2. Assume we don't need to flush -- Cort*/ + *(unsigned char *)(0x8000081c) = *(unsigned char *)(0x8000081c)|3; /* make the serial port the console */ /* strcat(cmd_line,"console=ttyS0,9600n8"); */ diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/process.c linux/arch/ppc/kernel/process.c --- v2.1.123/linux/arch/ppc/kernel/process.c Thu Aug 6 14:06:29 1998 +++ linux/arch/ppc/kernel/process.c Wed Sep 30 10:14:17 1998 @@ -349,6 +349,9 @@ regs->gpr[1] = sp; regs->msr = MSR_USER; shove_aux_table(sp); + if (last_task_used_math == current) + last_task_used_math = 0; + current->tss.fpscr = 0; } asmlinkage int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6, @@ -446,7 +449,7 @@ int i; va_start(args, fmt); - i=sprintf(buf,fmt,args); + i=vsprintf(buf,fmt,args); ll_puts(buf); va_end(args); return i; @@ -454,6 +457,19 @@ int lines = 24, cols = 80; int orig_x = 0, orig_y = 0; + +void puthex(unsigned long val) +{ + unsigned char buf[10]; + int i; + for (i = 7; i >= 0; i--) + { + buf[i] = "0123456789ABCDEF"[val & 0x0F]; + val >>= 4; + } + buf[8] = '\0'; + prom_print(buf); +} __initfunc(void ll_puts(const char *s)) { diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/prom.c linux/arch/ppc/kernel/prom.c --- v2.1.123/linux/arch/ppc/kernel/prom.c Thu Aug 6 14:06:29 1998 +++ linux/arch/ppc/kernel/prom.c Wed Sep 30 10:14:17 1998 @@ -1,5 +1,5 @@ /* - * $Id: prom.c,v 1.32 1998/07/28 20:28:46 geert Exp $ + * $Id: prom.c,v 1.39 1998/09/18 09:14:52 paulus Exp $ * * Procedures for interfacing to the Open Firmware PROM on * Power Macintosh computers. @@ -20,6 +20,8 @@ #include #include #include +#include +#include /* * Properties whose value is longer than this get excluded from our @@ -67,8 +69,12 @@ static interpret_func interpret_macio_props; static interpret_func interpret_root_props; +#ifndef FB_MAX /* avoid pulling in all of the fb stuff */ +#define FB_MAX 8 +#endif char *prom_display_paths[FB_MAX] __initdata = { 0, }; unsigned int prom_num_displays = 0; +char *of_stdout_device = 0; prom_entry prom = 0; ihandle prom_chosen = 0, prom_stdout = 0; @@ -85,19 +91,22 @@ static struct device_node *allnodes = 0; static void *call_prom(const char *service, int nargs, int nret, ...); - void prom_print(const char *msg); static void prom_exit(void); static unsigned long copy_device_tree(unsigned long, unsigned long); static unsigned long inspect_node(phandle, struct device_node *, unsigned long, unsigned long, struct device_node ***); static unsigned long finish_node(struct device_node *, unsigned long, interpret_func *); +static void relocate_nodes(void); static unsigned long check_display(unsigned long); static int prom_next_node(phandle *); extern void enter_rtas(void *); extern unsigned long reloc_offset(void); +extern char cmd_line[512]; /* XXX */ +boot_infos_t *boot_infos = 0; /* init it so it's in data segment not bss */ + /* * prom_init() is called very early on, before the kernel text * and data have been mapped to KERNELBASE. At this point the code @@ -208,15 +217,44 @@ unsigned long offset = reloc_offset(); int l; char *p, *d; - - /* check if we're prep, return if we are */ - if ( *(unsigned long *)(0) == 0xdeadc0de ) +#ifdef __SMP__ + if ( RELOC(first_cpu_booted) ) return; - +#endif /* __SMP__ */ + /* check if we're apus, return if we are */ if ( r3 == 0x61707573 ) return; + /* If we came here from BootX, clear the screen, + * set up some pointers and return. */ + if (r3 == 0x426f6f58 && pp == NULL) { + boot_infos_t *bi = (boot_infos_t *) r4; + unsigned int *screen; + int nw, ln; + unsigned long space; + + /* first clear the screen */ + for (ln = 0; ln < bi->dispDeviceRect[3]; ++ln) { + screen = (unsigned int *) (bi->dispDeviceBase + + ln * bi->dispDeviceRowBytes); + nw = bi->dispDeviceRect[2] * bi->dispDeviceDepth / 32; + for (; nw > 0; --nw) + *screen++ = 0; + } + + RELOC(boot_infos) = PTRUNRELOC(bi); + space = bi->deviceTreeOffset + bi->deviceTreeSize; + if (bi->ramDisk) + space = bi->ramDisk + bi->ramDiskSize; + RELOC(klimit) = PTRUNRELOC((char *) bi + space); + return; + } + + /* check if we're prep, return if we are */ + if ( *(unsigned long *)(0) == 0xdeadc0de ) + return; + /* First get a handle for the stdout device */ RELOC(prom) = pp; RELOC(prom_chosen) = call_prom(RELOC("finddevice"), 1, 1, @@ -228,9 +266,16 @@ sizeof(prom_stdout)) <= 0) prom_exit(); - /* Get the boot device and translate it to a full OF pathname. */ + /* Get the full OF pathname of the stdout device */ mem = (unsigned long) RELOC(klimit) + offset; p = (char *) mem; + memset(p, 0, 256); + call_prom(RELOC("instance-to-path"), 3, 1, RELOC(prom_stdout), p, 255); + RELOC(of_stdout_device) = PTRUNRELOC(p); + mem += strlen(p) + 1; + + /* Get the boot device and translate it to a full OF pathname. */ + p = (char *) mem; l = (int) call_prom(RELOC("getprop"), 4, 1, RELOC(prom_chosen), RELOC("bootpath"), p, 1<<20); if (l > 0) { @@ -303,8 +348,9 @@ { phandle node; ihandle ih; + int i; unsigned long offset = reloc_offset(); - char type[16], name[16], *path; + char type[16], *path; for (node = 0; prom_next_node(&node); ) { type[0] = 0; @@ -323,20 +369,23 @@ ih = call_prom(RELOC("open"), 1, 1, path); if (ih == 0 || ih == (ihandle) -1) { prom_print(RELOC("... failed\n")); - /* platinum kludge. platinum is a valid display, - * but not handled by OF. Make sure prom_num_display - * is incremented anyway - */ - call_prom(RELOC("getprop"), 4, 1, node, RELOC("name"), - name, sizeof(name)); - if (strncmp(name, RELOC("platinum"), 8)) - continue; - } else { - prom_print(RELOC("... ok\n")); + continue; } + prom_print(RELOC("... ok\n")); + + /* + * If this display is the device that OF is using for stdout, + * move it to the front of the list. + */ mem += strlen(path) + 1; - RELOC(prom_display_paths[RELOC(prom_num_displays)++]) - = PTRUNRELOC(path); + i = RELOC(prom_num_displays)++; + if (RELOC(of_stdout_device) != 0 && i > 0 + && strcmp(PTRRELOC(RELOC(of_stdout_device)), path) == 0) { + for (; i > 0; --i) + RELOC(prom_display_paths[i]) + = RELOC(prom_display_paths[i-1]); + } + RELOC(prom_display_paths[i]) = PTRUNRELOC(path); if (RELOC(prom_num_displays) >= FB_MAX) break; } @@ -478,6 +527,8 @@ { unsigned long mem = (unsigned long) klimit; + if (boot_infos) + relocate_nodes(); mem = finish_node(allnodes, mem, NULL); printk(KERN_INFO "device tree used %lu bytes\n", mem - (unsigned long) allnodes); @@ -517,10 +568,56 @@ else ifunc = NULL; + /* if we were booted from BootX, convert the full name */ + if (boot_infos + && strncmp(np->full_name, "Devices:device-tree", 19) == 0) { + if (np->full_name[19] == 0) { + strcpy(np->full_name, "/"); + } else if (np->full_name[19] == ':') { + char *p = np->full_name + 19; + np->full_name = p; + for (; *p; ++p) + if (*p == ':') + *p = '/'; + } + } + for (child = np->child; child != NULL; child = child->sibling) mem_start = finish_node(child, mem_start, ifunc); return mem_start; +} + +/* + * When BootX makes a copy of the device tree from the MacOS + * Name Registry, it is in the format we use but all of the pointers + * are offsets from the start of the tree. + * This procedure updates the pointers. + */ +__openfirmware +static void relocate_nodes(void) +{ + unsigned long base; + struct device_node *np; + struct property *pp; + +#define ADDBASE(x) (x = (x)? ((typeof (x))((unsigned long)(x) + base)): 0) + + base = (unsigned long) boot_infos + boot_infos->deviceTreeOffset; + allnodes = (struct device_node *)(base + 4); + for (np = allnodes; np != 0; np = np->allnext) { + ADDBASE(np->full_name); + ADDBASE(np->properties); + ADDBASE(np->parent); + ADDBASE(np->child); + ADDBASE(np->sibling); + ADDBASE(np->allnext); + for (pp = np->properties; pp != 0; pp = pp->next) { + ADDBASE(pp->name); + ADDBASE(pp->value); + ADDBASE(pp->next); + } + } } __openfirmware diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/residual.c linux/arch/ppc/kernel/residual.c --- v2.1.123/linux/arch/ppc/kernel/residual.c Thu Aug 6 14:06:29 1998 +++ linux/arch/ppc/kernel/residual.c Thu Oct 1 09:55:13 1998 @@ -1,5 +1,5 @@ /* - * $Id: residual.c,v 1.10 1998/07/09 22:23:18 cort Exp $ + * $Id: residual.c,v 1.12 1998/08/27 23:15:56 paulus Exp $ * * Code to deal with the PReP residual data. * @@ -23,7 +23,6 @@ #include #include -#if 0 #include #include #include @@ -464,8 +463,6 @@ } static void printlargepacket(PnP_TAG_PACKET * pkt, int size) { - int i; - switch (tag_large_item_name(pkt->S1_Pack.Tag)) { case LargeVendorItem: printlargevendor(pkt, size); @@ -477,7 +474,6 @@ } } static void printpackets(PnP_TAG_PACKET * pkt, const char * cat) { - PnP_TAG_PACKET tmp; if (pkt->S1_Pack.Tag== END_TAG) { printk(" No packets describing %s resources.\n", cat); return; @@ -501,10 +497,8 @@ void print_residual_device_info(void) { int i; - union _PnP_TAG_PACKET *pkt; PPC_DEVICE *dev; #define did dev->DeviceId -return; /* make sure we have residual data first */ if ( res->ResidualLength == 0 ) @@ -552,12 +546,18 @@ PnP_BASE_TYPES[did.BaseType], PnP_SUB_TYPE_STR(did.BaseType,did.SubType), s); - printpackets( (union _PnP_TAG_PACKET *) - &res->DevicePnPHeap[dev->AllocatedOffset], "allocated"); - printpackets( (union _PnP_TAG_PACKET *) - &res->DevicePnPHeap[dev->PossibleOffset], "possible"); - printpackets( (union _PnP_TAG_PACKET *) - &res->DevicePnPHeap[dev->CompatibleOffset], "compatible"); + if ( dev->AllocatedOffset ) + printpackets( (union _PnP_TAG_PACKET *) + &res->DevicePnPHeap[dev->AllocatedOffset], + "allocated"); + if ( dev->PossibleOffset ) + printpackets( (union _PnP_TAG_PACKET *) + &res->DevicePnPHeap[dev->PossibleOffset], + "possible"); + if ( dev->CompatibleOffset ) + printpackets( (union _PnP_TAG_PACKET *) + &res->DevicePnPHeap[dev->CompatibleOffset], + "compatible"); } } @@ -728,7 +728,6 @@ } #endif -#endif /* 0 */ /* Returns the device index in the residual data, any of the search items may be set as -1 for wildcard, DevID number field (second halfword) is big endian ! @@ -804,6 +803,28 @@ return 0; } +PPC_DEVICE *residual_find_device_id(unsigned long BusMask, + unsigned short DevID, + int BaseType, + int SubType, + int Interface, + int n) +{ + int i; + if ( !res->ResidualLength ) return NULL; + for (i=0; iActualNumDevices; i++) { +#define Dev res->Devices[i].DeviceId + if ( (Dev.BusId&BusMask) && + (BaseType==-1 || Dev.BaseType==BaseType) && + (SubType==-1 || Dev.SubType==SubType) && + (Interface==-1 || Dev.Interface==Interface) && + (DevID==0xffff || (Dev.DevId&0xffff) == DevID) && + !(n--) ) return res->Devices+i; +#undef Dev + } + return 0; +} + PnP_TAG_PACKET *PnP_find_packet(unsigned char *p, unsigned packet_tag, int n) @@ -850,4 +871,3 @@ }; return 0; /* not found */ } - diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c --- v2.1.123/linux/arch/ppc/kernel/setup.c Thu Aug 6 14:06:29 1998 +++ linux/arch/ppc/kernel/setup.c Wed Sep 30 10:14:17 1998 @@ -1,9 +1,10 @@ /* - * $Id: setup.c,v 1.95 1998/07/20 19:03:47 geert Exp $ + * $Id: setup.c,v 1.103 1998/09/18 09:14:56 paulus Exp $ * Common prep/pmac/chrp boot and setup code. */ #include +#include #include #include #include @@ -26,12 +27,18 @@ #ifdef CONFIG_MBX #include #endif +#include /* APUS defs */ extern unsigned long m68k_machtype; -extern struct mem_info ramdisk; extern int parse_bootinfo(const struct bi_record *); extern char _end[]; +#ifdef CONFIG_APUS +struct mem_info ramdisk; +unsigned long isa_io_base; +unsigned long isa_mem_base; +unsigned long pci_dram_offset; +#endif /* END APUS defs */ extern char cmd_line[512]; @@ -52,6 +59,8 @@ int _prep_type; +extern boot_infos_t *boot_infos; + /* * Perhaps we can put the pmac screen_info[] here * on pmac as well so we don't need the ifdef's. @@ -239,7 +248,7 @@ } -#ifdef CONFIG_BLK_DEV_IDE +#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) void ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq) { #if !defined(CONFIG_MBX) && !defined(CONFIG_APUS) @@ -256,6 +265,7 @@ } #endif } +EXPORT_SYMBOL(ide_init_hwif_ports); #endif unsigned long cpu_temp(void) @@ -333,7 +343,7 @@ unsigned long len = 0; unsigned long bogosum = 0; unsigned long i; - unsigned long cr; + #ifdef __SMP__ extern unsigned long cpu_present_map; extern struct cpuinfo_PPC cpu_data[NR_CPUS]; @@ -374,14 +384,6 @@ break; case 8: len += sprintf(len+buffer, "750\n"); - cr = _get_L2CR(); - if ( cr & (0x1<<28)) cr = 256; - else if ( cr & (0x2<<28)) cr = 512; - else if ( cr & (0x3<<28)) cr = 1024; - else cr = 0; - len += sprintf(len+buffer, "on-chip l2\t: " - "%ld KB (%s)\n", - cr,(_get_L2CR()&0x80000000) ? "on" : "off"); len += sprintf(len+buffer, "temperature \t: %lu C\n", cpu_temp()); break; @@ -436,9 +438,9 @@ #else /* CONFIG_MBX */ { bd_t *bp; - extern RESIDUAL res; + extern RESIDUAL *res; - bp = (bd_t *)&res; + bp = (bd_t *)res; len += sprintf(len+buffer,"clock\t\t: %dMHz\n" "bus clock\t: %dMHz\n", @@ -513,20 +515,18 @@ #ifndef CONFIG_MBX #ifndef CONFIG_MACH_SPECIFIC char *model; - /* prep boot loader tells us if we're prep or not */ - if ( *(unsigned long *)(KERNELBASE) == (0xdeadc0de) ) - { - _machine = _MACH_prep; - have_of = 0; - } /* boot loader will tell us if we're APUS */ - else if ( r3 == 0x61707573 ) + if ( r3 == 0x61707573 ) { _machine = _MACH_apus; have_of = 0; r3 = 0; - } else - { + } + /* prep boot loader tells us if we're prep or not */ + else if ( *(unsigned long *)(KERNELBASE) == (0xdeadc0de) ) { + _machine = _MACH_prep; + have_of = 0; + } else { have_of = 1; /* ask the OF info if we're a chrp or pmac */ model = get_property(find_path_device("/"), "type", NULL); @@ -556,6 +556,20 @@ if (r3 >= 0x4000 && r3 < 0x800000 && r4 == 0) { strncpy(cmd_line, (char *)r3 + KERNELBASE, sizeof(cmd_line)); + } else if (boot_infos != 0) { + /* booted by BootX - check for ramdisk */ + if (boot_infos->kernelParamsOffset != 0) + strncpy(cmd_line, (char *) boot_infos + + boot_infos->kernelParamsOffset, + sizeof(cmd_line)); +#ifdef CONFIG_BLK_DEV_INITRD + if (boot_infos->ramDisk) { + initrd_start = (unsigned long) boot_infos + + boot_infos->ramDisk; + initrd_end = initrd_start + boot_infos->ramDiskSize; + initrd_below_start_ok = 1; + } +#endif } else { struct device_node *chosen; char *p; @@ -568,6 +582,7 @@ ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); } #endif + cmd_line[0] = 0; chosen = find_devices("chosen"); if (chosen != NULL) { p = get_property(chosen, "bootargs", NULL); @@ -652,7 +667,6 @@ break; #ifdef CONFIG_APUS case _MACH_apus: - setup_pci_ptrs(); /* Parse bootinfo. The bootinfo is located right after the kernel bss */ parse_bootinfo((const struct bi_record *)&_end); @@ -677,6 +691,7 @@ default: printk("Unknown machine type in identify_machine!\n"); } + #else /* CONFIG_MBX */ if ( r3 ) @@ -722,6 +737,8 @@ #ifdef CONFIG_XMON extern void xmon_map_scc(void); xmon_map_scc(); + if (strstr(cmd_line, "xmon")) + xmon(0); #endif /* CONFIG_XMON */ /* reboot on panic */ @@ -771,7 +788,7 @@ m68k_machtype = MACH_AMIGA; apus_setup_arch(memory_start_p,memory_end_p); break; -#endif +#endif default: printk("Unknown machine %d in setup_arch()\n", _machine); } diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/signal.c linux/arch/ppc/kernel/signal.c --- v2.1.123/linux/arch/ppc/kernel/signal.c Thu Aug 6 14:06:29 1998 +++ linux/arch/ppc/kernel/signal.c Wed Sep 30 10:14:17 1998 @@ -1,7 +1,7 @@ /* * linux/arch/ppc/kernel/signal.c * - * $Id: signal.c,v 1.16 1998/06/16 23:34:10 cort Exp $ + * $Id: signal.c,v 1.20 1998/09/28 16:47:09 cort Exp $ * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) @@ -128,6 +128,13 @@ do_exit(SIGSEGV); } +asmlinkage int +sys_sigaltstack(const stack_t *uss, stack_t *uoss) +{ + struct pt_regs *regs = (struct pt_regs *) &uss; + return do_sigaltstack(uss, uoss, regs->gpr[1]); +} + int sys_sigaction(int sig, const struct old_sigaction *act, struct old_sigaction *oact) @@ -483,3 +490,4 @@ setup_frame(regs, (struct sigregs *) frame, newsp); return 1; } + diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/smp.c linux/arch/ppc/kernel/smp.c --- v2.1.123/linux/arch/ppc/kernel/smp.c Thu Aug 6 14:06:29 1998 +++ linux/arch/ppc/kernel/smp.c Wed Sep 30 10:14:17 1998 @@ -1,5 +1,5 @@ /* - * $Id: smp.c,v 1.28 1998/08/04 04:47:45 cort Exp $ + * $Id: smp.c,v 1.33 1998/09/25 04:32:30 cort Exp $ * * Smp support for ppc. * @@ -49,6 +49,8 @@ unsigned int prof_multiplier[NR_CPUS]; unsigned int prof_counter[NR_CPUS]; +int first_cpu_booted = 0; + int start_secondary(void *); extern int cpu_idle(void *unused); @@ -119,7 +121,7 @@ /* make sure msg is for us */ if ( msg == -1 ) return; -printk("recv after msg check\n"); + switch( msg ) { case MSG_STOP_CPU: @@ -177,12 +179,14 @@ __initfunc(void smp_boot_cpus(void)) { - extern unsigned long secondary_entry[]; extern struct task_struct *current_set[NR_CPUS]; - int i, timeout; + int i; struct task_struct *p; printk("Entering SMP Mode...\n"); + + first_cpu_booted = 1; + dcbf(&first_cpu_booted); for (i = 0; i < NR_CPUS; i++) { cpu_number_map[i] = -1; @@ -219,11 +223,12 @@ p->processor = 1; current_set[1] = p; /* need to flush here since secondary bat's aren't setup */ - dcbf((volatile unsigned long *)¤t_set[1]); + dcbf((void *)¤t_set[1]); /* setup entry point of secondary processor */ - *(volatile unsigned long *)(0xf2800000) - = (unsigned long)secondary_entry-KERNELBASE; + /* *(volatile unsigned long *)(0xf2800000) + = (unsigned long)secondary_entry-KERNELBASE;*/ + *(volatile unsigned long *)(0xf2800000) = 0x100; eieio(); /* interrupt secondary to begin executing code */ *(volatile unsigned long *)(0xf80000c0) = 0L; @@ -234,7 +239,9 @@ * calibrate_delay() so use this value that I found through * experimentation. -- Cort */ - udelay(1); + for ( i = 1000; i && !cpu_callin_map[1] ; i-- ) + udelay(100); + if(cpu_callin_map[1]) { cpu_number_map[1] = 1; __cpu_logical_map[i] = 1; @@ -243,7 +250,7 @@ #if 0 /* this sync's the decr's, but we don't want this now -- Cort */ set_dec(decrementer_count); #endif - /* interrupt secondary to start decr's again */ + /* interrupt secondary to start decr's on both cpus */ smp_message_pass(1,0xf0f0, 0, 0); /* interrupt secondary to begin executing code */ /**(volatile unsigned long *)(0xf80000c0) = 0L; diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/syscalls.c linux/arch/ppc/kernel/syscalls.c --- v2.1.123/linux/arch/ppc/kernel/syscalls.c Mon Jan 12 15:18:13 1998 +++ linux/arch/ppc/kernel/syscalls.c Wed Sep 30 10:14:17 1998 @@ -209,7 +209,7 @@ goto out; } - /*flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);*/ + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); ret = do_mmap(file, addr, len, prot, flags, offset); out: unlock_kernel(); diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/totalmp.c linux/arch/ppc/kernel/totalmp.c --- v2.1.123/linux/arch/ppc/kernel/totalmp.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/kernel/totalmp.c Wed Sep 30 10:14:17 1998 @@ -0,0 +1,109 @@ +/* + * $Id: totalmp.c,v 1.5 1998/08/26 13:58:50 cort Exp $ + * + * Support for Total Impact's TotalMP PowerPC accelerator board. + * + * Written by Cort Dougan (cort@cs.nmt.edu) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +extern void totalmp_init(void); + +extern inline void openpic_writefield(volatile u_int *addr, u_int mask, + u_int field); +__initfunc(void totalmp_init(void)) +{ + struct pci_dev *dev; + u32 val; + unsigned long ctl_area, ctl_area_phys; + + /* it's a pci card */ + if ( !pci_present() ) return; + + /* search for a MPIC. For now, we assume + * only one TotalMP card installed. -- Cort + */ + for(dev=pci_devices; dev; dev=dev->next) + { + if ( (dev->vendor == PCI_VENDOR_ID_IBM) + && ((dev->device == PCI_DEVICE_ID_IBM_MPIC) + || (dev->device==PCI_DEVICE_ID_IBM_MPIC_2)) ) + { + break; + } + } + + if ( !dev ) return; + + OpenPIC = (struct OpenPIC *)bus_to_virt(dev->base_address[0]); +#if 0 + if ( (ulong)OpenPIC > 0x10000000 ) + { + printk("TotalMP: relocating base %lx -> %lx\n", + (ulong)OpenPIC, ((ulong)OpenPIC & 0x00FFFFFF) | 0x01000000); + OpenPIC = (struct OpenPIC *)(((ulong)OpenPIC & 0x00FFFFFF) | 0x01000000); + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, (ulong)OpenPIC); + }*/ +#endif + OpenPIC = (struct OpenPIC *)((ulong)OpenPIC + _IO_BASE); + + openpic_init(0); + + /* put openpic in 8259-cascade mode */ + openpic_writefield(&OpenPIC->Global.Global_Configuration0, 0, 0x20000000); + /* set ipi to highest priority */ + openpic_writefield(&OpenPIC->Global._IPI_Vector_Priority[0].Reg, 0, 0x000f0000); + + /* allocate and remap the control area to be no-cache */ + ctl_area = __get_free_pages(GFP_ATOMIC, 3); + ctl_area_phys = (unsigned long) virt_to_phys((void *)ctl_area); + ctl_area = (unsigned long)ioremap(ctl_area, 0x8000); + + /* soft reset cpu 0 */ + pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &val); + openpic_writefield(&OpenPIC->Global._Processor_Initialization.Reg, 0, 0x1); + + /* wait for base address reg to change, signaling that cpu 0 is done */ +#define wait_for(where) { \ + udelay(100); \ + pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &val); \ + if ( val != 0x77700000 ) \ + { \ + printk("TotalMP: CPU0 did not respond: val %x %d\n", val, where); \ + /*free_pages((ulong)phys_to_virt(ctl_area_phys),1);*/ \ + return; \ + } } + + /* tell cpu0 where the control area is */ + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,(~val) >> 16); + wait_for(0); + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, + ((ulong)ctl_area & 0xff000000)>>20); + wait_for(1); + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, + ((ulong)ctl_area & 0x00ff0000)>>12); + wait_for(2); + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, + ((ulong)ctl_area & 0x0000ff00)>>4); + wait_for(3); + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, + ((ulong)ctl_area & 0x000000ff)<<4); + wait_for(4); +#undef wait_for + /* wait for cpu0 to "sign-on" */ +} + diff -u --recursive --new-file v2.1.123/linux/arch/ppc/lib/string.S linux/arch/ppc/lib/string.S --- v2.1.123/linux/arch/ppc/lib/string.S Thu May 14 19:47:38 1998 +++ linux/arch/ppc/lib/string.S Wed Sep 30 10:14:17 1998 @@ -219,12 +219,12 @@ .globl __copy_tofrom_user __copy_tofrom_user: - rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */ + srwi. r7,r5,3 addi r6,r3,-4 addi r4,r4,-4 - li r3,0 /* success return value */ - beq 2f /* if less than 8 bytes to do */ - andi. r0,r6,3 /* get dest word aligned */ + li r3,0 /* success return value */ + beq 2f /* if less than 8 bytes to do */ + andi. r0,r6,3 /* get dest word aligned */ mtctr r7 bne 5f 1: lwz r7,4(r4) @@ -238,7 +238,7 @@ 14: lwzu r0,4(r4) addi r5,r5,-4 15: stwu r0,4(r6) -3: cmpwi 0,r5,0 +3: cmpwi 0,r5,0 /* do 1 byte at a time for the remainder */ beqlr mtctr r5 addi r4,r4,3 @@ -247,32 +247,78 @@ 16: stbu r0,1(r6) bdnz 4b blr -5: subfic r0,r0,4 - mtctr r0 +5: subfic r0,r0,4 /* copy bytes until we have the */ + mtctr r0 /* destination 4-byte aligned */ + subf r5,r0,r5 6: lbz r7,4(r4) addi r4,r4,1 17: stb r7,4(r6) addi r6,r6,1 bdnz 6b - subf r5,r0,r5 - rlwinm. r7,r5,32-3,3,31 + srwi. r7,r5,3 beq 2b mtctr r7 b 1b -99: li r3,-EFAULT +/* we come here on a fault in the 8-byte-at-a-time loop */ +88: subi r4,r4,8 /* compensate for the lwzu */ +98: mfctr r0 + rlwimi r5,r0,3,0,28 /* use the byte-at-a-time loop to */ + b 3b /* copy up to the byte at fault */ +/* here on a write fault in the single-word copy */ +96: subi r4,r4,4 + b 3b +/* here on a read fault in the initial single-byte copy */ +90: mfctr r3 + add r3,r3,r5 + b 70f +/* here on a read fault in the final single-byte copy */ +99: mfctr r3 + subi r6,r6,3 +/* clear out the rest of the destination: r3 bytes starting at 4(r6) */ +70: li r0,0 + mr. r5,r3 + beq 76f +71: andi. r4,r6,3 + beq 72f +77: stb r0,4(r6) + addi r6,r6,1 + addic. r5,r5,-1 + bne 71b +72: srwi. r7,r5,2 + beq 73f + mtctr r7 +74: stwu r0,4(r6) + bdnz 74b +73: andi. r5,r5,3 + beq 76f + mtctr r5 + addi r6,r6,3 +75: stbu r0,1(r6) + bdnz 75b +76: blr +/* here on a write fault in the initial single-byte copy */ +80: mfctr r3 + add r3,r3,r5 + blr +/* here on a write fault in the final single-byte copy */ +81: mfctr r3 blr + .section __ex_table,"a" .align 2 - .long 1b,99b - .long 11b,99b - .long 12b,99b - .long 13b,99b - .long 14b,99b - .long 15b,99b + .long 1b,98b + .long 11b,98b + .long 12b,88b + .long 13b,88b + .long 14b,3b + .long 15b,96b .long 4b,99b - .long 16b,99b - .long 6b,99b - .long 17b,99b + .long 16b,81b + .long 6b,90b + .long 17b,80b + .long 77b,76b + .long 74b,76b + .long 75b,76b .text #undef CLEAR_USE_DCBZ 1 diff -u --recursive --new-file v2.1.123/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c --- v2.1.123/linux/arch/ppc/mm/init.c Wed Sep 9 14:51:06 1998 +++ linux/arch/ppc/mm/init.c Wed Sep 30 10:14:17 1998 @@ -1,5 +1,5 @@ /* - * $Id: init.c,v 1.115 1998/08/04 20:48:38 davem Exp $ + * $Id: init.c,v 1.123 1998/09/19 19:03:55 geert Exp $ * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) @@ -33,6 +33,7 @@ #include #include #include +#include #ifdef CONFIG_BLK_DEV_INITRD #include /* for initrd_* */ #endif @@ -46,6 +47,8 @@ #include #include #include +#include +#include /* APUS includes */ #include #include @@ -69,6 +72,7 @@ unsigned long avail_start; struct pgtable_cache_struct quicklists; struct mem_info memory[NUM_MEMINFO]; +extern boot_infos_t *boot_infos; void MMU_init(void); static void *MMU_get_page(void); @@ -229,7 +233,7 @@ { printk("%-8.8s %3d %3d %8ld %8ld %8ld %c%08lx %08lx ", p->comm,p->pid, - p->mm->count,p->mm->context, + atomic_read(&p->mm->count),p->mm->context, p->mm->context<<4, p->tss.last_syscall, user_mode(p->tss.regs) ? 'u' : 'k', p->tss.regs->nip, (ulong)p); @@ -805,11 +809,6 @@ for (bl = 128<<10; bl < 256<<20; bl <<= 1) { if (bl * 2 > tot) break; - /* On some APUS systems, memory grows downwards, i.e., - 24MB will be 8MB aligned. Handle that properly by - mapping first 8MB, then 16MB. */ - if (((bl * 2) - 1) & mem_base) - break; } setbat(2, KERNELBASE, mem_base, bl, RAM_PAGE); @@ -884,7 +883,6 @@ unsigned long a; unsigned long num_freed_pages = 0, num_prep_pages = 0, num_pmac_pages = 0, num_openfirmware_pages = 0; - #define FREESEC(START,END,CNT) do { \ a = (unsigned long)(&START); \ for (; a < (unsigned long)(&END); a += PAGE_SIZE) { \ @@ -933,6 +931,11 @@ */ __initfunc(void MMU_init(void)) { + +#ifdef __SMP__ + if ( first_cpu_booted ) return; +#endif /* __SMP__ */ + #ifndef CONFIG_8xx if (have_of) end_of_DRAM = pmac_find_end_of_memory(); @@ -967,7 +970,7 @@ break; case _MACH_apus: /* Map PPC exception vectors. */ - setbat(0, 0xfff00000, 0xfff00000, 0x00010000, RAM_PAGE); + setbat(0, 0xfff00000, 0xfff00000, 0x00020000, RAM_PAGE); /* Map chip and ZorroII memory */ setbat(1, zTwoBase, 0x00000000, 0x01000000, IO_PAGE); /* Note: a temporary hack in arch/ppc/amiga/setup.c @@ -997,17 +1000,16 @@ /* * Find some memory for setup_arch to return. - * We use the last chunk of available memory as the area + * We use the largest chunk of available memory as the area * that setup_arch returns, making sure that there are at * least 32 pages unused before this for MMU_get_page to use. */ __initfunc(unsigned long find_available_memory(void)) { - int i; + int i, rn; unsigned long a, free; unsigned long start, end; - free = 0; if (_machine == _MACH_mbx) { /* Return the first, not the last region, because we * may not yet have properly initialized the additonal @@ -1018,12 +1020,17 @@ return avail_start; } - for (i = 0; i < phys_avail.n_regions - 1; ++i) { + rn = 0; + for (i = 1; i < phys_avail.n_regions; ++i) + if (phys_avail.regions[i].size > phys_avail.regions[rn].size) + rn = i; + free = 0; + for (i = 0; i < rn; ++i) { start = phys_avail.regions[i].address; end = start + phys_avail.regions[i].size; free += (end & PAGE_MASK) - PAGE_ALIGN(start); } - a = PAGE_ALIGN(phys_avail.regions[i].address); + a = PAGE_ALIGN(phys_avail.regions[rn].address); if (free < 32 * PAGE_SIZE) a += 32 * PAGE_SIZE - free; avail_start = (unsigned long) __va(a); @@ -1082,6 +1089,15 @@ } phys_avail.n_regions = 0; +#ifdef CONFIG_BLK_DEV_INITRD + /* if we are booted from BootX with an initial ramdisk, + make sure the ramdisk pages aren't reserved. */ + if (initrd_start) { + for (a = initrd_start; a < initrd_end; a += PAGE_SIZE) + clear_bit(PG_reserved, &mem_map[MAP_NR(a)].flags); + } +#endif /* CONFIG_BLK_DEV_INITRD */ + /* free the prom's memory - no-op on prep */ for (i = 0; i < prom_mem.n_regions; ++i) { a = (unsigned long) __va(prom_mem.regions[i].address); @@ -1216,8 +1232,13 @@ phys_mem.n_regions = 1; } - /* record which bits the prom is using */ - get_mem_prop("available", &phys_avail); + if (boot_infos == 0) { + /* record which bits the prom is using */ + get_mem_prop("available", &phys_avail); + } else { + /* booted from BootX - it's all available (after klimit) */ + phys_avail = phys_mem; + } prom_mem = phys_mem; for (i = 0; i < phys_avail.n_regions; ++i) remove_mem_piece(&prom_mem, phys_avail.regions[i].address, @@ -1274,36 +1295,69 @@ #define HARDWARE_MAPPED_SIZE (512*1024) __initfunc(unsigned long *apus_find_end_of_memory(void)) { - unsigned long kstart, ksize; + int shadow = 0; - /* Add the chunk that ADOS does not see. This may also - * include a ROM mapping which we reclaim. The top 512KB is - * removed again below. - * Do it by aligning the size to the nearest 2MB limit upwards. - */ - memory[0].size = ((memory[0].size+0x001fffff) & 0xffe00000); + /* The memory size reported by ADOS excludes the 512KB + reserved for PPC exception registers and possibly 512KB + containing a shadow of the ADOS ROM. */ + { + unsigned long size = memory[0].size; - append_mem_piece(&phys_mem, memory[0].addr, memory[0].size); + /* If 2MB aligned, size was probably user + specified. We can't tell anything about shadowing + in this case so skip shadow assignment. */ + if (0 != (size & 0x1fffff)){ + /* Align to 512KB to ensure correct handling + of both memfile and system specified + sizes. */ + size = ((size+0x0007ffff) & 0xfff80000); + /* If memory is 1MB aligned, assume + shadowing. */ + shadow = !(size & 0x80000); + } - phys_avail = phys_mem; - kstart = __pa(_stext); - ksize = PAGE_ALIGN(klimit - _stext); - remove_mem_piece(&phys_avail, kstart, ksize, 1); + /* Add the chunk that ADOS does not see. by aligning + the size to the nearest 2MB limit upwards. */ + memory[0].size = ((size+0x001fffff) & 0xffe00000); + } - /* Remove the upper HARDWARE_MAPPED_SIZE bytes where the address - * range 0xfff00000-0xfffx0000 is mapped to. - * We do it this way to ensure that the memory registered in the - * system has a power-of-two size. - */ - remove_mem_piece(&phys_avail, - (memory[0].addr + memory[0].size - - HARDWARE_MAPPED_SIZE), - HARDWARE_MAPPED_SIZE, 1); + /* Now register the memory block. */ + { + unsigned long kstart, ksize; + + append_mem_piece(&phys_mem, memory[0].addr, memory[0].size); + phys_avail = phys_mem; + kstart = __pa(_stext); + ksize = PAGE_ALIGN(klimit - _stext); + remove_mem_piece(&phys_avail, kstart, ksize, 0); + } + + /* Remove the memory chunks that are controlled by special + Phase5 hardware. */ + { + unsigned long top = memory[0].addr + memory[0].size; + + /* Remove the upper 512KB if it contains a shadow of + the ADOS ROM. FIXME: It might be possible to + disable this shadow HW. Check the booter + (ppc_boot.c) */ + if (shadow) + { + top -= HARDWARE_MAPPED_SIZE; + remove_mem_piece(&phys_avail, top, + HARDWARE_MAPPED_SIZE, 0); + } + + /* Remove the upper 512KB where the PPC exception + vectors are mapped. */ + top -= HARDWARE_MAPPED_SIZE; + remove_mem_piece(&phys_avail, top, + HARDWARE_MAPPED_SIZE, 0); + } /* FIXME:APUS: Only handles one block of memory! Problem is - * that the VTOP/PTOV code in head.S would be a mess if it had - * to handle more than one block. - */ + that the VTOP/PTOV code in head.S would be a mess if it had + to handle more than one block. */ return __va(memory[0].addr + memory[0].size); } @@ -1393,6 +1447,5 @@ } else Hash_end = 0; - } #endif /* ndef CONFIG_8xx */ diff -u --recursive --new-file v2.1.123/linux/arch/ppc/pmac_defconfig linux/arch/ppc/pmac_defconfig --- v2.1.123/linux/arch/ppc/pmac_defconfig Thu Aug 6 14:06:29 1998 +++ linux/arch/ppc/pmac_defconfig Wed Sep 30 10:14:17 1998 @@ -1,5 +1,5 @@ # -# Automatically generated by make menuconfig: don't edit +# Automatically generated make config: don't edit # # @@ -35,16 +35,16 @@ CONFIG_BINFMT_MISC=m # CONFIG_BINFMT_JAVA is not set # CONFIG_PARPORT is not set -# CONFIG_FB is not set -# CONFIG_VGA_CONSOLE is not set -# CONFIG_PMAC_PBOOK is not set +CONFIG_FB=y +CONFIG_FB_COMPAT_XPMAC=y +CONFIG_PMAC_PBOOK=y CONFIG_MAC_KEYBOARD=y CONFIG_MAC_FLOPPY=y CONFIG_MAC_SERIAL=y CONFIG_MACMOUSE=y CONFIG_PROC_DEVICETREE=y # CONFIG_KGDB is not set -# CONFIG_XMON is not set +CONFIG_XMON=y # # Plug and Play support @@ -56,17 +56,25 @@ # # CONFIG_BLK_DEV_FD is not set CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# # CONFIG_BLK_DEV_HD_IDE is not set CONFIG_BLK_DEV_IDEDISK=y CONFIG_BLK_DEV_IDECD=y # CONFIG_BLK_DEV_IDETAPE is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set +CONFIG_BLK_DEV_IDEFLOPPY=y # CONFIG_BLK_DEV_IDESCSI is not set # CONFIG_BLK_DEV_CMD640 is not set # CONFIG_BLK_DEV_RZ1000 is not set # CONFIG_BLK_DEV_IDEPCI is not set # CONFIG_BLK_DEV_SL82C105 is not set # CONFIG_IDE_CHIPSETS is not set + +# +# Additional Block Devices +# # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_MD is not set @@ -98,10 +106,18 @@ # CONFIG_IP_MROUTE is not set CONFIG_IP_ALIAS=y # CONFIG_SYN_COOKIES is not set + +# +# (it is safe to leave these untouched) +# CONFIG_INET_RARP=y CONFIG_IP_NOSR=y CONFIG_SKB_LARGE=y # CONFIG_IPV6 is not set + +# +# +# # CONFIG_IPX is not set CONFIG_ATALK=m # CONFIG_X25 is not set @@ -119,11 +135,19 @@ # SCSI support # CONFIG_SCSI=y + +# +# SCSI support type (disk, tape, CD-ROM) +# CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=y CONFIG_BLK_DEV_SR=y CONFIG_BLK_DEV_SR_VENDOR=y # CONFIG_CHR_DEV_SG is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# # CONFIG_SCSI_MULTI_LUN is not set CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_LOGGING is not set @@ -209,6 +233,10 @@ # CONFIG_COPS is not set # CONFIG_IPDDP is not set CONFIG_PPP=m + +# +# CCP compressors for PPP are only built as modules. +# # CONFIG_SLIP is not set # CONFIG_NET_RADIO is not set # CONFIG_TR is not set @@ -230,6 +258,57 @@ # CONFIG_CD_NO_IDESCSI is not set # +# Console drivers +# +CONFIG_DUMMY_CONSOLE=y +CONFIG_FB_OF=y +CONFIG_FB_CONTROL=y +CONFIG_FB_PLATINUM=y +CONFIG_FB_ATY=y +CONFIG_FB_IMSTT=y +CONFIG_FB_CT65550=y +# CONFIG_FB_S3TRIO is not set +# CONFIG_FB_VGA is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FBCON_ADVANCED is not set +CONFIG_FBCON_CFB8=y +CONFIG_FBCON_CFB16=y +CONFIG_FBCON_CFB24=y +CONFIG_FBCON_CFB32=y +# CONFIG_FBCON_FONTWIDTH8_ONLY is not set +CONFIG_FBCON_FONTS=y +# CONFIG_FONT_8x8 is not set +CONFIG_FONT_8x16=y +CONFIG_FONT_SUN8x16=y +CONFIG_FONT_SUN12x22=y +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_SERIAL=m +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_MOUSE is not set +# CONFIG_UMISC is not set +# CONFIG_QIC02_TAPE is not set +# CONFIG_APM is not set +# CONFIG_WATCHDOG is not set +# CONFIG_RTC is not set +# CONFIG_VIDEO_DEV is not set +CONFIG_NVRAM=y +# CONFIG_JOYSTICK is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set + +# # Filesystems # # CONFIG_QUOTA is not set @@ -292,33 +371,7 @@ # CONFIG_NLS_KOI8_R is not set # -# Console drivers -# - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -# CONFIG_SERIAL is not set -# CONFIG_SERIAL_EXTENDED is not set -# CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_MOUSE is not set -# CONFIG_UMISC is not set -# CONFIG_QIC02_TAPE is not set -# CONFIG_APM is not set -# CONFIG_WATCHDOG is not set -# CONFIG_RTC is not set -# CONFIG_VIDEO_DEV is not set -CONFIG_NVRAM=y -# CONFIG_JOYSTICK is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set - -# # Sound # -# CONFIG_SOUND is not set +CONFIG_SOUND=y +CONFIG_DMASOUND=y diff -u --recursive --new-file v2.1.123/linux/arch/ppc/prep_defconfig linux/arch/ppc/prep_defconfig --- v2.1.123/linux/arch/ppc/prep_defconfig Thu Aug 6 14:06:29 1998 +++ linux/arch/ppc/prep_defconfig Wed Sep 30 10:14:17 1998 @@ -196,9 +196,9 @@ # CONFIG_EEXPRESS_PRO100 is not set # CONFIG_LNE390 is not set # CONFIG_NE2K_PCI is not set +# CONFIG_TLAN is not set # CONFIG_ES3210 is not set # CONFIG_EPIC100 is not set -# CONFIG_TLAN is not set # CONFIG_ZNET is not set # CONFIG_NET_POCKET is not set # CONFIG_FDDI is not set @@ -225,6 +225,40 @@ # CONFIG_CD_NO_IDESCSI is not set # +# Console drivers +# + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_SERIAL_CONSOLE=y +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +CONFIG_MOUSE=y +# CONFIG_ATIXL_BUSMOUSE is not set +# CONFIG_BUSMOUSE is not set +# CONFIG_MS_BUSMOUSE is not set +CONFIG_PSMOUSE=y +# CONFIG_82C710_MOUSE is not set +# CONFIG_PC110_PAD is not set +# CONFIG_UMISC is not set +# CONFIG_QIC02_TAPE is not set +# CONFIG_APM is not set +# CONFIG_WATCHDOG is not set +# CONFIG_RTC is not set +# CONFIG_VIDEO_DEV is not set +# CONFIG_NVRAM is not set +# CONFIG_JOYSTICK is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set + +# # Filesystems # # CONFIG_QUOTA is not set @@ -287,41 +321,42 @@ # CONFIG_NLS_KOI8_R is not set # -# Console drivers -# - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -# CONFIG_SERIAL_EXTENDED is not set -# CONFIG_SERIAL_NONSTANDARD is not set -CONFIG_MOUSE=y -# CONFIG_ATIXL_BUSMOUSE is not set -# CONFIG_BUSMOUSE is not set -# CONFIG_MS_BUSMOUSE is not set -CONFIG_PSMOUSE=y -# CONFIG_82C710_MOUSE is not set -# CONFIG_PC110_PAD is not set -# CONFIG_UMISC is not set -# CONFIG_QIC02_TAPE is not set -# CONFIG_APM is not set -# CONFIG_WATCHDOG is not set -# CONFIG_RTC is not set -# CONFIG_VIDEO_DEV is not set -# CONFIG_NVRAM is not set -# CONFIG_JOYSTICK is not set -# CONFIG_MISC_RADIO is not set - -# -# Ftape, the floppy tape device driver +# Sound # -# CONFIG_FTAPE is not set +CONFIG_SOUND=y +# CONFIG_SOUND_ES1370 is not set +# CONFIG_SOUND_ES1371 is not set +# CONFIG_SOUND_SONICVIBES is not set +# CONFIG_SOUND_MSNDCLAS is not set +# CONFIG_SOUND_MSNDPIN is not set +CONFIG_SOUND_OSS=y +# CONFIG_SOUND_PAS is not set +# CONFIG_SOUND_SB is not set +# CONFIG_SOUND_ADLIB is not set +# CONFIG_SOUND_GUS is not set +# CONFIG_SOUND_MPU401 is not set +# CONFIG_SOUND_PSS is not set +# CONFIG_SOUND_MSS is not set +# CONFIG_SOUND_SSCAPE is not set +# CONFIG_SOUND_TRIX is not set +# CONFIG_SOUND_MAD16 is not set +# CONFIG_SOUND_WAVEFRONT is not set +CONFIG_SOUND_CS4232=y +CONFIG_CS4232_BASE=530 +CONFIG_CS4232_IRQ=11 +CONFIG_CS4232_DMA=0 +CONFIG_CS4232_DMA2=3 +CONFIG_CS4232_MPU_BASE=330 +CONFIG_CS4232_MPU_IRQ=9 +# CONFIG_SOUND_MAUI is not set +# CONFIG_SOUND_SGALAXY is not set +# CONFIG_SOUND_OPL3SA1 is not set +# CONFIG_SOUND_SOFTOSS is not set +# CONFIG_SOUND_YM3812 is not set +# CONFIG_SOUND_VMIDI is not set +# CONFIG_SOUND_UART6850 is not set # -# Sound +# Additional low level sound drivers # -# CONFIG_SOUND is not set +# CONFIG_LOWLEVEL_SOUND is not set diff -u --recursive --new-file v2.1.123/linux/arch/sparc/Makefile linux/arch/sparc/Makefile --- v2.1.123/linux/arch/sparc/Makefile Thu Aug 6 14:06:29 1998 +++ linux/arch/sparc/Makefile Sun Oct 4 10:22:42 1998 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.36 1998/06/02 00:36:40 davem Exp $ +# $Id: Makefile,v 1.39 1998/09/16 12:31:31 jj Exp $ # sparc/Makefile # # Makefile for the architecture dependent flags and dependencies on the @@ -15,26 +15,35 @@ # Uncomment the first CFLAGS if you are doing kgdb source level # debugging of the kernel to get the proper debugging information. +IS_EGCS := $(shell if $(CC) --version 2>&1 | grep 'egcs' > /dev/null; then echo y; else echo n; fi) +NEW_GAS := $(shell if $(LD) --version 2>&1 | grep 'elf64_sparc' > /dev/null; then echo y; else echo n; fi) + +ifeq ($(NEW_GAS),y) +AS := $(AS) -32 +LD := $(LD) -m elf32_sparc +endif + #CFLAGS := $(CFLAGS) -g -pipe -fcall-used-g5 -fcall-used-g7 +ifneq ($(IS_EGCS),y) CFLAGS := $(CFLAGS) -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7 +else +CFLAGS := $(CFLAGS) -m32 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7 +endif #LINKFLAGS = -N -Ttext 0xf0004000 LINKFLAGS = -T arch/sparc/vmlinux.lds HEAD := arch/sparc/kernel/head.o arch/sparc/kernel/init_task.o -# Note arch/sparc/mm has to be the last subdir SUBDIRS := $(SUBDIRS) arch/sparc/kernel arch/sparc/lib arch/sparc/prom \ - arch/sparc/mm + arch/sparc/mm arch/sparc/math-emu -CORE_FILES := arch/sparc/kernel/kernel.o arch/sparc/mm/mm.o $(CORE_FILES) +CORE_FILES := arch/sparc/kernel/kernel.o arch/sparc/mm/mm.o $(CORE_FILES) \ + arch/sparc/math-emu/math-emu.o LIBS := $(TOPDIR)/lib/lib.a $(LIBS) $(TOPDIR)/arch/sparc/prom/promlib.a \ $(TOPDIR)/arch/sparc/lib/lib.a -SUBDIRS += arch/sparc/math-emu -CORE_FILES += arch/sparc/math-emu/math-emu.o - ifdef CONFIG_AP1000 SUBDIRS := $(SUBDIRS) arch/sparc/ap1000 mpp CORE_FILES := $(TOPDIR)/arch/sparc/ap1000/ap1000lib.o \ @@ -43,8 +52,14 @@ CFLAGS := $(CFLAGS) -D__MPP__=1 endif +# This one has to come last +SUBDIRS += arch/sparc/boot +CORE_FILES_NO_BTFIX := $(CORE_FILES) +CORE_FILES += arch/sparc/boot/btfix.o + archclean: - -$(MAKE) -C arch/sparc/boot archclean + rm -f $(TOPDIR)/vmlinux.aout + -$(MAKE) -C arch/sparc/boot clean archmrproper: -$(MAKE) -C arch/sparc/math-emu cleansymlinks @@ -57,19 +72,3 @@ tftpboot.img: $(MAKE) -C arch/sparc/boot tftpboot.img - -vmlinux.o: $(CONFIGURATION) init/main.o init/version.o linuxsubdirs - $(LD) -r $(VMLINUX.OBJS) -o vmlinux.o - -arch/sparc/boot/btfix.s: arch/sparc/boot/btfixupprep vmlinux.o - $(OBJDUMP) -x vmlinux.o | arch/sparc/boot/btfixupprep > arch/sparc/boot/btfix.s - -arch/sparc/boot/btfix.o: arch/sparc/boot/btfix.s - $(CC) -c -o arch/sparc/boot/btfix.o arch/sparc/boot/btfix.s - -arch/sparc/boot/btfixupprep: arch/sparc/boot/btfixupprep.c - $(MAKE) -C arch/sparc/boot btfixupprep - -vmlinux: arch/sparc/boot/btfix.o - $(LD) $(LINKFLAGS) vmlinux.o arch/sparc/boot/btfix.o -o vmlinux - $(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aU] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map diff -u --recursive --new-file v2.1.123/linux/arch/sparc/boot/Makefile linux/arch/sparc/boot/Makefile --- v2.1.123/linux/arch/sparc/boot/Makefile Thu Apr 23 20:21:30 1998 +++ linux/arch/sparc/boot/Makefile Sun Oct 4 10:22:42 1998 @@ -1,16 +1,13 @@ -# $Id: Makefile,v 1.6 1998/02/23 01:44:39 rth Exp $ +# $Id: Makefile,v 1.8 1998/09/16 12:24:51 jj Exp $ # Makefile for the Sparc boot stuff. # # Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) -# Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) +# Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz) ROOT_IMG =/usr/src/root.img ELFTOAOUT =elftoaout -all: boot - -boot: - @echo "Nothing special to be done for 'boot' on Linux/SPARC." +all: btfix.o tftpboot.img: piggyback $(ELFTOAOUT) $(TOPDIR)/vmlinux -o tftpboot.img @@ -22,8 +19,20 @@ btfixupprep: btfixupprep.c $(HOSTCC) $(HOSTCFLAGS) -o btfixupprep btfixupprep.c -archclean: - rm -f btfixupprep piggyback tftpboot.img +clean: + rm -f btfixupprep piggyback tftpboot.img btfix.o btfix.s + +BTOBJS := $(HEAD) init/main.o init/version.o \ + $(CORE_FILES_NO_BTFIX) $(FILESYSTEMS) \ + $(NETWORKS) $(DRIVERS) + +vmlinux.o: dummy + $(LD) -r $(patsubst %,$(TOPDIR)/%,$(BTOBJS)) $(LIBS) -o vmlinux.o + +btfix.s: btfixupprep vmlinux.o + $(OBJDUMP) -x vmlinux.o | ./btfixupprep > btfix.s -dep: +btfix.o: btfix.s + $(CC) -c -o btfix.o btfix.s +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.123/linux/arch/sparc/boot/btfixupprep.c linux/arch/sparc/boot/btfixupprep.c --- v2.1.123/linux/arch/sparc/boot/btfixupprep.c Thu Apr 23 20:21:30 1998 +++ linux/arch/sparc/boot/btfixupprep.c Sun Oct 4 10:22:42 1998 @@ -1,4 +1,4 @@ -/* $Id: btfixupprep.c,v 1.3 1998/03/09 14:03:10 jj Exp $ +/* $Id: btfixupprep.c,v 1.5 1998/09/16 12:24:55 jj Exp $ Simple utility to prepare vmlinux image for sparc. Resolves all BTFIXUP uses and settings and creates a special .s object to link to the image. @@ -29,8 +29,11 @@ #define MAXSYMS 1024 +static char *symtab = "SYMBOL TABLE:"; static char *relrec = "RELOCATION RECORDS FOR ["; static int rellen; +static int symlen; +int mode; struct _btfixup; @@ -97,6 +100,20 @@ unsigned long offset; char *initvalstr; + symlen = strlen(symtab); + while (fgets (buffer, 1024, stdin) != NULL) + if (!strncmp (buffer, symtab, symlen)) + goto main0; + fatal(); +main0: + if (fgets (buffer, 1024, stdin) == NULL || buffer[0] < '0' || buffer[0] > '9') + fatal(); + for (mode = 0;; mode++) + if (buffer[mode] < '0' || buffer[mode] > '9') + break; + if (mode != 8 && mode != 16) + fatal(); + rellen = strlen(relrec); while (fgets (buffer, 1024, stdin) != NULL) if (!strncmp (buffer, relrec, rellen)) @@ -112,17 +129,19 @@ if (fgets (buffer, 1024, stdin) == NULL) fatal(); while (fgets (buffer, 1024, stdin) != NULL) { + int nbase; if (!strncmp (buffer, relrec, rellen)) goto main1; p = strchr (buffer, '\n'); if (p) *p = 0; - if (strlen (buffer) < 30) + if (strlen (buffer) < 22+mode) continue; - if (strncmp (buffer + 8, " R_SPARC_", 9)) + if (strncmp (buffer + mode, " R_SPARC_", 9)) continue; - if (buffer[27] != '_' || buffer[28] != '_' || buffer[29] != '_') + nbase = 27 - 8 + mode; + if (buffer[nbase] != '_' || buffer[nbase+1] != '_' || buffer[nbase+2] != '_') continue; - switch (buffer[30]) { + switch (buffer[nbase+3]) { case 'f': /* CALL */ case 'b': /* BLACKBOX */ case 's': /* SIMM13 */ @@ -133,26 +152,26 @@ default: continue; } - p = strchr (buffer + 32, '+'); + p = strchr (buffer + nbase+5, '+'); if (p) *p = 0; - shift = 32; - if (buffer[31] == 's' && buffer[32] == '_') { - shift = 33; + shift = nbase + 5; + if (buffer[nbase+4] == 's' && buffer[nbase+5] == '_') { + shift = nbase + 6; if (strcmp (sect, ".text.init")) { fprintf(stderr, "Wrong use of '%s' BTFIXUPSET.\nBTFIXUPSET_CALL can be used only in __init sections\n", buffer+shift); exit(1); } - } else if (buffer[31] != '_') + } else if (buffer[nbase+4] != '_') continue; - if (strcmp (sect, ".text") && strcmp (sect, ".text.init") && (strcmp (sect, "__ksymtab") || buffer[30] != 'f')) { - if (buffer[30] == 'f') - fprintf(stderr, "Wrong use of '%s' in '%s' section. It can be only used in .text, .text.init and __ksymtab\n", buffer + shift, sect); + if (strcmp (sect, ".text") && strcmp (sect, ".text.init") && strcmp (sect, ".fixup") && (strcmp (sect, "__ksymtab") || buffer[nbase+3] != 'f')) { + if (buffer[nbase+3] == 'f') + fprintf(stderr, "Wrong use of '%s' in '%s' section. It can be only used in .text, .text.init, .fixup and __ksymtab\n", buffer + shift, sect); else - fprintf(stderr, "Wrong use of '%s' in '%s' section. It can be only used in .text and .text.init\n", buffer + shift, sect); + fprintf(stderr, "Wrong use of '%s' in '%s' section. It can be only used in .text, .fixup and .text.init\n", buffer + shift, sect); exit(1); } p = strstr (buffer + shift, "__btset_"); - if (p && buffer[31] == 's') { + if (p && buffer[nbase+4] == 's') { fprintf(stderr, "__btset_ in BTFIXUP name can only be used when defining the variable, not for setting\n%s\n", buffer); exit(1); } @@ -171,23 +190,23 @@ initvalstr = p + 10; *p = 0; } - f = find(buffer[30], buffer + shift); - if (buffer[31] == 's') + f = find(buffer[nbase+3], buffer + shift); + if (buffer[nbase+4] == 's') continue; - switch (buffer[30]) { + switch (buffer[nbase+3]) { case 'f': if (initval) { fprintf(stderr, "Cannot use pre-initalized fixups for calls\n%s\n", buffer); exit(1); } if (!strcmp (sect, "__ksymtab")) { - if (strncmp (buffer + 17, "32 ", 10)) { + if (strncmp (buffer + mode+9, "32 ", 10)) { fprintf(stderr, "BTFIXUP_CALL in EXPORT_SYMBOL results in relocation other than R_SPARC_32\n\%s\n", buffer); exit(1); } - } else if (strncmp (buffer + 17, "WDISP30 ", 10) && - strncmp (buffer + 17, "HI22 ", 10) && - strncmp (buffer + 17, "LO10 ", 10)) { + } else if (strncmp (buffer + mode+9, "WDISP30 ", 10) && + strncmp (buffer + mode+9, "HI22 ", 10) && + strncmp (buffer + mode+9, "LO10 ", 10)) { fprintf(stderr, "BTFIXUP_CALL results in relocation other than R_SPARC_WDISP30, R_SPARC_HI22 or R_SPARC_LO10\n%s\n", buffer); exit(1); } @@ -197,7 +216,7 @@ fprintf(stderr, "Cannot use pre-initialized fixups for blackboxes\n%s\n", buffer); exit(1); } - if (strncmp (buffer + 17, "HI22 ", 10)) { + if (strncmp (buffer + mode+9, "HI22 ", 10)) { fprintf(stderr, "BTFIXUP_BLACKBOX results in relocation other than R_SPARC_HI22\n%s\n", buffer); exit(1); } @@ -207,7 +226,7 @@ fprintf(stderr, "Wrong initializer for SIMM13. Has to be from $fffff000 to $00000fff\n%s\n", buffer); exit(1); } - if (strncmp (buffer + 17, "13 ", 10)) { + if (strncmp (buffer + mode+9, "13 ", 10)) { fprintf(stderr, "BTFIXUP_SIMM13 results in relocation other than R_SPARC_13\n%s\n", buffer); exit(1); } @@ -217,7 +236,7 @@ fprintf(stderr, "Wrong initializer for HALF.\n%s\n", buffer); exit(1); } - if (strncmp (buffer + 17, "13 ", 10)) { + if (strncmp (buffer + mode+9, "13 ", 10)) { fprintf(stderr, "BTFIXUP_HALF results in relocation other than R_SPARC_13\n%s\n", buffer); exit(1); } @@ -227,7 +246,7 @@ fprintf(stderr, "Wrong initializer for SETHI. Cannot have set low 10 bits\n%s\n", buffer); exit(1); } - if (strncmp (buffer + 17, "HI22 ", 10)) { + if (strncmp (buffer + mode+9, "HI22 ", 10)) { fprintf(stderr, "BTFIXUP_SETHI results in relocation other than R_SPARC_HI22\n%s\n", buffer); exit(1); } @@ -237,7 +256,7 @@ fprintf(stderr, "Cannot use pre-initalized fixups for INT\n%s\n", buffer); exit(1); } - if (strncmp (buffer + 17, "HI22 ", 10) && strncmp (buffer + 17, "LO10 ", 10)) { + if (strncmp (buffer + mode+9, "HI22 ", 10) && strncmp (buffer + mode+9, "LO10 ", 10)) { fprintf(stderr, "BTFIXUP_INT results in relocation other than R_SPARC_HI22 and R_SPARC_LO10\n%s\n", buffer); exit(1); } @@ -261,7 +280,7 @@ exit(1); } offset = strtoul(buffer, &q, 16); - if (q != buffer + 8 || (!offset && strncmp (buffer, "00000000 ", 9))) { + if (q != buffer + mode || (!offset && (mode == 8 ? strncmp (buffer, "00000000 ", 9) : strncmp (buffer, "0000000000000000 ", 17)))) { fprintf(stderr, "Malformed relocation address in\n%s\n", buffer); exit(1); } @@ -274,7 +293,7 @@ if (!*rr) fatal(); (*rr)->offset = offset; (*rr)->f = NULL; - if (buffer[30] == 'f') { + if (buffer[nbase+3] == 'f') { lastf = f; lastfoffset = offset; lastfrelno = k; @@ -302,11 +321,13 @@ printf("0\n"); for (r = f->rel, j--; r != NULL; j--, r = r->next) { if (!strcmp (r->sect, ".text")) - printf ("_stext+0x%08x", r->offset); + printf ("_stext+0x%08lx", r->offset); else if (!strcmp (r->sect, ".text.init")) - printf ("__init_begin+0x%08x", r->offset); + printf ("__init_begin+0x%08lx", r->offset); else if (!strcmp (r->sect, "__ksymtab")) - printf ("__start___ksymtab+0x%08x", r->offset); + printf ("__start___ksymtab+0x%08lx", r->offset); + else if (!strcmp (r->sect, ".fixup")) + printf ("__start___fixup+0x%08lx", r->offset); else fatal(); if (f->type == 'f' || !r->f) diff -u --recursive --new-file v2.1.123/linux/arch/sparc/config.in linux/arch/sparc/config.in --- v2.1.123/linux/arch/sparc/config.in Thu Aug 6 14:06:30 1998 +++ linux/arch/sparc/config.in Sun Oct 4 10:22:42 1998 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.58 1998/07/29 05:06:41 davem Exp $ +# $Id: config.in,v 1.63 1998/09/21 05:05:56 jj Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -35,6 +35,9 @@ tristate 'OPIU DDV Driver' CONFIG_DDV else bool 'Support for SUN4 machines (disables SUN4[CDM] support)' CONFIG_SUN4 + if [ "$CONFIG_SUN4" != "y" ]; then + bool 'Support for PCI and PS/2 keyboard/mouse' CONFIG_PCI + fi mainmenu_option next_comment comment 'Console drivers' @@ -54,9 +57,7 @@ define_bool CONFIG_SUN_CONSOLE y define_bool CONFIG_SUN_AUXIO y define_bool CONFIG_SUN_IO y - if [ "$CONFIG_SUN4" = "y" ]; then - bool 'Force early PROM Console' CONFIG_SUN4_FORCECONSOLE - else + if [ "$CONFIG_SUN4" != "y" ]; then source drivers/sbus/char/Config.in source drivers/sbus/audio/Config.in fi diff -u --recursive --new-file v2.1.123/linux/arch/sparc/defconfig linux/arch/sparc/defconfig --- v2.1.123/linux/arch/sparc/defconfig Thu Aug 6 14:06:30 1998 +++ linux/arch/sparc/defconfig Sun Oct 4 10:22:42 1998 @@ -120,8 +120,7 @@ # # Protocol-specific masquerading support will be built as modules. # -# CONFIG_IP_MASQUERADE_IPAUTOFW is not set -# CONFIG_IP_MASQUERADE_IPPORTFW is not set +# CONFIG_IP_MASQUERADE_MOD is not set # CONFIG_IP_ROUTER is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set @@ -136,7 +135,7 @@ CONFIG_INET_RARP=m CONFIG_IP_NOSR=y CONFIG_SKB_LARGE=y -CONFIG_IPV6=m +CONFIG_IPV6=y # CONFIG_IPV6_EUI64 is not set # @@ -273,7 +272,8 @@ CONFIG_SMD_DISKLABEL=y # CONFIG_SOLARIS_X86_PARTITION is not set # CONFIG_ADFS_FS is not set -CONFIG_DEVPTS_FS=y +CONFIG_QNX4FS_FS=m +# CONFIG_QNX4FS_RW is not set # CONFIG_MAC_PARTITION is not set CONFIG_NLS=y diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/Makefile linux/arch/sparc/kernel/Makefile --- v2.1.123/linux/arch/sparc/kernel/Makefile Thu Aug 6 14:06:30 1998 +++ linux/arch/sparc/kernel/Makefile Sun Oct 4 10:22:42 1998 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.45 1998/07/28 16:52:42 jj Exp $ +# $Id: Makefile,v 1.48 1998/09/21 05:04:46 jj Exp $ # Makefile for the linux kernel. # # Note! Dependencies are done automagically by 'make dep', which also @@ -22,7 +22,7 @@ sys_sparc.o sunos_asm.o sparc-stub.o systbls.o sys_sunos.o \ sunos_ioctl.o time.o windows.o cpu.o devices.o \ sclow.o solaris.o tadpole.o tick14.o ptrace.o sys_solaris.o \ - unaligned.o muldiv.o + unaligned.o muldiv.o pcic.o OX_OBJS := sparc_ksyms.o @@ -36,6 +36,10 @@ ifdef CONFIG_SUN_AUXIO O_OBJS += auxio.o +endif + +ifdef CONFIG_PCI +O_OBJS += ebus.o endif head.o: head.S diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/auxio.c linux/arch/sparc/kernel/auxio.c --- v2.1.123/linux/arch/sparc/kernel/auxio.c Thu Apr 23 20:21:30 1998 +++ linux/arch/sparc/kernel/auxio.c Sun Oct 4 10:22:42 1998 @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -32,6 +33,11 @@ node = prom_getchild(node); auxio_nd = prom_searchsiblings(node, "auxio"); if(!auxio_nd) { +#ifdef CONFIG_PCI + /* There may be auxio on Ebus */ + auxio_register = 0; + return; +#else if(prom_searchsiblings(node, "leds")) { /* VME chassis sun4m machine, no auxio exists. */ auxio_register = 0; @@ -39,6 +45,7 @@ } prom_printf("Cannot find auxio node, cannot continue...\n"); prom_halt(); +#endif } } prom_getproperty(auxio_nd, "reg", (char *) auxregs, sizeof(auxregs)); diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/ebus.c linux/arch/sparc/kernel/ebus.c --- v2.1.123/linux/arch/sparc/kernel/ebus.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sparc/kernel/ebus.c Sun Oct 4 10:22:42 1998 @@ -0,0 +1,328 @@ +/* $Id: ebus.c,v 1.1 1998/09/18 10:43:43 jj Exp $ + * ebus.c: PCI to EBus bridge device. + * + * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) + * + * Adopted for sparc by V. Roganov and G. Raiko. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#undef PROM_DEBUG +#undef DEBUG_FILL_EBUS_DEV + +#ifdef PROM_DEBUG +#define dprintf prom_printf +#else +#define dprintf printk +#endif + +struct linux_ebus *ebus_chain = 0; + +#ifdef CONFIG_SUN_OPENPROMIO +extern int openprom_init(void); +#endif +#ifdef CONFIG_SPARCAUDIO +extern int sparcaudio_init(void); +#endif +#ifdef CONFIG_SUN_AUXIO +extern void auxio_probe(void); +#endif +#ifdef CONFIG_OBP_FLASH +extern int flash_init(void); +#endif +#ifdef CONFIG_ENVCTRL +extern int envctrl_init(void); +#endif + +static inline unsigned long ebus_alloc(size_t size) +{ + return (unsigned long)kmalloc(size, GFP_ATOMIC); +} + +__initfunc(void fill_ebus_child(int node, struct linux_prom_registers *preg, + struct linux_ebus_child *dev)) +{ + int regs[PROMREG_MAX]; + int irqs[PROMREG_MAX]; + char lbuf[128]; + int i, len; + + dev->prom_node = node; + prom_getstring(node, "name", lbuf, sizeof(lbuf)); + strcpy(dev->prom_name, lbuf); + + len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs)); + dev->num_addrs = len / sizeof(regs[0]); + + for (i = 0; i < dev->num_addrs; i++) { + if (regs[i] >= dev->parent->num_addrs) { + prom_printf("UGH: property for %s was %d, need < %d\n", + dev->prom_name, len, dev->parent->num_addrs); + panic(__FUNCTION__); + } + dev->base_address[i] = dev->parent->base_address[regs[i]]; + } + + len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs)); + if ((len == -1) || (len == 0)) { + dev->num_irqs = 0; + /* + * Oh, well, some PROMs don't export interrupts + * property to children of EBus devices... + * + * Be smart about PS/2 keyboard and mouse. + */ + if (!strcmp(dev->parent->prom_name, "8042")) { + dev->num_irqs = 1; + dev->irqs[0] = dev->parent->irqs[0]; + } + } else { + dev->num_irqs = len / sizeof(irqs[0]); + printk("FIXME: %s irq(%d)\n", dev->prom_name, irqs[0]); + } + +#ifdef DEBUG_FILL_EBUS_DEV + dprintk("child '%s': address%s\n", dev->prom_name, + dev->num_addrs > 1 ? "es" : ""); + for (i = 0; i < dev->num_addrs; i++) + dprintk(" %016lx\n", dev->base_address[i]); + if (dev->num_irqs) { + dprintk(" IRQ%s", dev->num_irqs > 1 ? "s" : ""); + for (i = 0; i < dev->num_irqs; i++) + dprintk(" %08x", dev->irqs[i]); + dprintk("\n"); + } +#endif +} + +__initfunc(void fill_ebus_device(int node, struct linux_ebus_device *dev)) +{ + struct linux_prom_registers regs[PROMREG_MAX]; + struct linux_ebus_child *child; + int irqs[PROMINTR_MAX]; + char lbuf[128]; + int i, n, len; + + dev->prom_node = node; + prom_getstring(node, "name", lbuf, sizeof(lbuf)); + strcpy(dev->prom_name, lbuf); + + len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs)); + if (len % sizeof(struct linux_prom_registers)) { + prom_printf("UGH: proplen for %s was %d, need multiple of %d\n", + dev->prom_name, len, + (int)sizeof(struct linux_prom_registers)); + panic(__FUNCTION__); + } + dev->num_addrs = len / sizeof(struct linux_prom_registers); + + for (i = 0; i < dev->num_addrs; i++) { + n = (regs[i].which_io - 0x10) >> 2; + + dev->base_address[i] = dev->bus->self->base_address[n]; + dev->base_address[i] += regs[i].phys_addr; + + if (dev->base_address[i]) { + dev->base_address[i] = + (unsigned long)sparc_alloc_io (dev->base_address[i], 0, + regs[i].reg_size, + dev->prom_name, 0, 0); + if (dev->base_address[i] == 0 ) { + panic("ebus: unable sparc_alloc_io for dev %s", + dev->prom_name); + } + } + } + + len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs)); + if ((len == -1) || (len == 0)) { + dev->num_irqs = 0; + } else { + dev->num_irqs = len / sizeof(irqs[0]); + +#define IRQ_8042 7 + if (irqs[0] == 4) dev->irqs[0] = IRQ_8042; + printk("FIXME: %s irq(%d)\n", dev->prom_name, irqs[0]); + } + +#ifdef DEBUG_FILL_EBUS_DEV + dprintk("'%s': address%s\n", dev->prom_name, + dev->num_addrs > 1 ? "es" : ""); + for (i = 0; i < dev->num_addrs; i++) + dprintk(" %016lx\n", dev->base_address[i]); + if (dev->num_irqs) { + dprintk(" IRQ%s", dev->num_irqs > 1 ? "s" : ""); + for (i = 0; i < dev->num_irqs; i++) + dprintk(" %08x", dev->irqs[i]); + dprintk("\n"); + } +#endif + if ((node = prom_getchild(node))) { + dev->children = (struct linux_ebus_child *) + ebus_alloc(sizeof(struct linux_ebus_child)); + + child = dev->children; + child->next = 0; + child->parent = dev; + child->bus = dev->bus; + fill_ebus_child(node, ®s[0], child); + + while ((node = prom_getsibling(node))) { + child->next = (struct linux_ebus_child *) + ebus_alloc(sizeof(struct linux_ebus_child)); + + child = child->next; + child->next = 0; + child->parent = dev; + child->bus = dev->bus; + fill_ebus_child(node, ®s[0], child); + } + } +} + +__initfunc(void ebus_init(void)) +{ + struct linux_prom_pci_registers regs[PROMREG_MAX]; + struct linux_pbm_info *pbm; + struct linux_ebus_device *dev; + struct linux_ebus *ebus; + struct pci_dev *pdev; + struct pcidev_cookie *cookie; + char lbuf[128]; + unsigned long addr, *base; + unsigned short pci_command; + int nd, len, ebusnd; + int reg, nreg; + int num_ebus = 0; + + if (!pci_present()) + return; + + pdev = pci_find_device(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_EBUS, 0); + if (!pdev) { +#ifdef PROM_DEBUG + dprintk("ebus: No EBus's found.\n"); +#endif + return; + } + cookie = pdev->sysdata; + ebusnd = cookie->prom_node; + + ebus_chain = ebus = (struct linux_ebus *) + ebus_alloc(sizeof(struct linux_ebus)); + ebus->next = 0; + + while (ebusnd) { +#ifdef PROM_DEBUG + dprintk("ebus%d:", num_ebus); +#endif + + prom_getstring(ebusnd, "name", lbuf, sizeof(lbuf)); + ebus->prom_node = ebusnd; + strcpy(ebus->prom_name, lbuf); + ebus->self = pdev; + ebus->parent = pbm = cookie->pbm; + + /* Enable BUS Master. */ + pci_read_config_word(pdev, PCI_COMMAND, &pci_command); + pci_command |= PCI_COMMAND_MASTER; + pci_write_config_word(pdev, PCI_COMMAND, pci_command); + + len = prom_getproperty(ebusnd, "reg", (void *)regs, + sizeof(regs)); + if (len == 0 || len == -1) { + prom_printf("%s: can't find reg property\n", + __FUNCTION__); + prom_halt(); + } + nreg = len / sizeof(struct linux_prom_pci_registers); + + base = &ebus->self->base_address[0]; + for (reg = 0; reg < nreg; reg++) { + if (!(regs[reg].which_io & 0x03000000)) + continue; + + addr = regs[reg].phys_lo; + *base++ = addr; +#ifdef PROM_DEBUG + dprintk(" %lx[%x]", addr, regs[reg].size_lo); +#endif + } +#ifdef PROM_DEBUG + dprintk("\n"); +#endif + + nd = prom_getchild(ebusnd); + if (!nd) + goto next_ebus; + + ebus->devices = (struct linux_ebus_device *) + ebus_alloc(sizeof(struct linux_ebus_device)); + + dev = ebus->devices; + dev->next = 0; + dev->children = 0; + dev->bus = ebus; + fill_ebus_device(nd, dev); + + while ((nd = prom_getsibling(nd))) { + dev->next = (struct linux_ebus_device *) + ebus_alloc(sizeof(struct linux_ebus_device)); + + dev = dev->next; + dev->next = 0; + dev->children = 0; + dev->bus = ebus; + fill_ebus_device(nd, dev); + } + + next_ebus: + pdev = pci_find_device(PCI_VENDOR_ID_SUN, + PCI_DEVICE_ID_SUN_EBUS, pdev); + if (!pdev) + break; + + cookie = pdev->sysdata; + ebusnd = cookie->prom_node; + + ebus->next = (struct linux_ebus *) + ebus_alloc(sizeof(struct linux_ebus)); + ebus = ebus->next; + ebus->next = 0; + ++num_ebus; + } + +#ifdef CONFIG_SUN_OPENPROMIO + openprom_init(); +#endif + +#ifdef CONFIG_SPARCAUDIO + sparcaudio_init(); +#endif +#ifdef CONFIG_SUN_BPP + bpp_init(); +#endif +#ifdef CONFIG_SUN_AUXIO + auxio_probe(); +#endif +#ifdef CONFIG_ENVCTRL + envctrl_init(); +#endif +#ifdef CONFIG_OBP_FLASH + flash_init(); +#endif +} diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/irq.c linux/arch/sparc/kernel/irq.c --- v2.1.123/linux/arch/sparc/kernel/irq.c Thu Aug 6 14:06:30 1998 +++ linux/arch/sparc/kernel/irq.c Sun Oct 4 10:22:42 1998 @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.86 1998/06/04 09:54:49 jj Exp $ +/* $Id: irq.c,v 1.89 1998/09/21 05:05:12 jj Exp $ * arch/sparc/kernel/irq.c: Interrupt request handling routines. On the * Sparc the IRQ's are basically 'cast in stone' * and you are supposed to probe the prom's device @@ -6,7 +6,7 @@ * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx) - * Copyright (C) 1995 Pete A. Zaitcev (zaitcev@ipmce.su) + * Copyright (C) 1995 Pete A. Zaitcev (zaitcev@metabyte.com) * Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk) */ @@ -40,6 +40,7 @@ #include #include #include +#include /* * Dave Redman (djhr@tadpole.co.uk) @@ -669,6 +670,13 @@ break; case sun4m: +#ifdef CONFIG_PCI + pcic_probe(); + if (pci_present()) { + sun4m_pci_init_IRQ(); + break; + } +#endif sun4m_init_IRQ(); break; diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/pcic.c linux/arch/sparc/kernel/pcic.c --- v2.1.123/linux/arch/sparc/kernel/pcic.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sparc/kernel/pcic.c Sun Oct 4 10:22:42 1998 @@ -0,0 +1,762 @@ +/* $Id: pcic.c,v 1.2 1998/09/29 03:21:56 jj Exp $ + * pcic.c: Sparc/PCI controller support + * + * Copyright (C) 1998 V. Roganov and G. Raiko + * + * Code is derived from Ultra/PCI PSYCHO controller support, see that + * for author info. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include /* for sanity check... */ + +#include + +#undef PROM_DEBUG +#undef FIXUP_REGS_DEBUG +#undef FIXUP_IRQ_DEBUG +#undef FIXUP_VMA_DEBUG + +#ifdef PROM_DEBUG +#define dprintf prom_printf +#else +#define dprintf printk +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifndef CONFIG_PCI + +int pcibios_present(void) +{ + return 0; +} + +asmlinkage int sys_pciconfig_read(unsigned long bus, + unsigned long dfn, + unsigned long off, + unsigned long len, + unsigned char *buf) +{ + return 0; +} + +asmlinkage int sys_pciconfig_write(unsigned long bus, + unsigned long dfn, + unsigned long off, + unsigned long len, + unsigned char *buf) +{ + return 0; +} + +#else + +static struct linux_pcic PCIC; +static struct linux_pcic *pcic = NULL; + +static void pci_do_gettimeofday(struct timeval *tv); +static void pci_do_settimeofday(struct timeval *tv); + +__initfunc(void pcic_probe(void)) +{ + struct linux_prom_registers regs[PROMREG_MAX]; + struct linux_pbm_info* pbm; + char namebuf[64]; + int node; + int err; + + if (pci_present()) { + prom_printf("PCIC: called twice!\n"); + prom_halt(); + } + + node = prom_getchild (prom_root_node); + node = prom_searchsiblings (node, "pci"); + if (node == 0) + return; + /* + * Map in PCIC register set, config space, and IO base + */ + err = prom_getproperty(node, "reg", (char*)regs, sizeof(regs)); + if (err == 0 || err == -1) { + prom_printf("PCIC: Error, cannot get PCIC registers " + "from PROM.\n"); + prom_halt(); + } + + pcic = &PCIC; + + pcic->pcic_regs = (unsigned long)sparc_alloc_io(regs[0].phys_addr, NULL, + regs[0].reg_size, + "PCIC Registers", 0, 0); + if (!pcic->pcic_regs) { + prom_printf("PCIC: Error, cannot map PCIC registers.\n"); + prom_halt(); + } + + pcic->pcic_io_phys = regs[1].phys_addr; + pcic->pcic_io = (unsigned long)sparc_alloc_io(regs[1].phys_addr, NULL, + regs[1].reg_size, + "PCIC IO Base", 0, 0); + if (pcic->pcic_io == 0UL) { + prom_printf("PCIC: Error, cannot map PCIC IO Base.\n"); + prom_halt(); + } + + pcic->pcic_config_space_addr = + (unsigned long)sparc_alloc_io (regs[2].phys_addr, NULL, + regs[2].reg_size * 2, + "PCI Config Space Address", 0, 0); + if (pcic->pcic_config_space_addr == 0UL) { + prom_printf("PCIC: Error, cannot map" + "PCI Configuration Space Address.\n"); + prom_halt(); + } + + /* + * Docs say three least significant bits in address and data + * must be the same. Thus, we need adjust size of data. + */ + pcic->pcic_config_space_data = + (unsigned long)sparc_alloc_io (regs[3].phys_addr, NULL, + regs[3].reg_size * 2, + "PCI Config Space Data", 0, 0); + if (pcic->pcic_config_space_data == 0UL) { + prom_printf("PCIC: Error, cannot map" + "PCI Configuration Space Data.\n"); + prom_halt(); + } + + pbm = &pcic->pbm; + pbm->prom_node = node; + prom_getstring(node, "name", namebuf, sizeof(namebuf)); + strcpy(pbm->prom_name, namebuf); +} + +__initfunc(void pcibios_init(void)) +{ + /* + * PCIC should be initialized at start of the timer. + * So, here we report the presence of PCIC and do some magic passes. + */ + if(!pcic) + return; + + printk("PCIC MAP: config addr=0x%lx; config data=0x%lx, " + "regs=0x%lx io=0x%lx\n", + pcic->pcic_config_space_addr, pcic->pcic_config_space_data, + pcic->pcic_regs, pcic->pcic_io); + + /* + * FIXME: + * Switch off IOTLB translation. + * It'll be great to use IOMMU to handle HME's rings + * but we couldn't. Thus, we have to flush CPU cache + * in HME. + */ + writeb(PCI_DVMA_CONTROL_IOTLB_DISABLE, + pcic->pcic_regs+PCI_DVMA_CONTROL); + + /* + * FIXME: + * Increase mapped size for PCI memory space (DMA access). + * Should be done in that order (size first, address second). + * Why we couldn't set up 4GB and forget about it ? + */ + writel(0xF0000000UL, pcic->pcic_regs+PCI_SIZE_0); + writel(0+PCI_BASE_ADDRESS_SPACE_MEMORY, + pcic->pcic_regs+PCI_BASE_ADDRESS_0); +} + +int pcibios_present(void) +{ + return pcic != NULL; +} + +__initfunc(static int pdev_to_pnode(struct linux_pbm_info *pbm, + struct pci_dev *pdev)) +{ + struct linux_prom_pci_registers regs[PROMREG_MAX]; + int err; + int node = prom_getchild(pbm->prom_node); + + while(node) { + err = prom_getproperty(node, "reg", + (char *)®s[0], sizeof(regs)); + if(err != 0 && err != -1) { + unsigned long devfn = (regs[0].which_io >> 8) & 0xff; + if(devfn == pdev->devfn) + return node; /* Match */ + } + node = prom_getsibling(node); + } + return 0; +} + +static inline struct pcidev_cookie *pci_devcookie_alloc(void) +{ + return kmalloc(sizeof(struct pcidev_cookie), GFP_ATOMIC); +} + + +static void pcic_map_pci_device (struct pci_dev *dev) { + int node, pcinode; + int i, j; + + /* Is any valid address present ? */ + i = 0; + for(j = 0; j < 6; j++) + if (dev->base_address[j]) i++; + if (!i) return; /* nothing to do */ + + /* + * find related address and get it's window length + */ + pcinode = prom_getchild(prom_root_node); + pcinode = prom_searchsiblings(pcinode, "pci"); + if (!pcinode) + panic("PCIC: failed to locate 'pci' node"); + + + for (node = prom_getchild(pcinode); node; + node = prom_getsibling(node)) { + struct linux_prom_pci_assigned_addresses addrs[6]; + int addrlen = prom_getproperty(node,"assigned-addresses", + (char*)addrs, sizeof(addrs)); + if (addrlen == -1) + continue; + + addrlen /= sizeof(struct linux_prom_pci_assigned_addresses); + for (i = 0; i < addrlen; i++ ) + for (j = 0; j < 6; j++) { + if (!dev->base_address[j] || !addrs[i].phys_lo) + continue; + if (addrs[i].phys_lo == dev->base_address[j]) { + unsigned long address = dev->base_address[j]; + int length = addrs[i].size_lo; + char namebuf[128] = { 0, }; + unsigned long mapaddr, addrflags; + + prom_getstring(node, "name", + namebuf, sizeof(namebuf)); + + /* FIXME: + * failure in allocation too large space + */ + if (length > 0x200000) { + length = 0x200000; + prom_printf("PCIC: map window for device '%s' " + "reduced to 2MB !\n", namebuf); + } + + /* + * Be careful with MEM/IO address flags + */ + if ((address & PCI_BASE_ADDRESS_SPACE) == + PCI_BASE_ADDRESS_SPACE_IO) { + mapaddr = address & PCI_BASE_ADDRESS_IO_MASK; + } else { + mapaddr = address & PCI_BASE_ADDRESS_MEM_MASK; + } + addrflags = address ^ mapaddr; + + dev->base_address[j] = + (unsigned long)sparc_alloc_io(address, 0, + length, + namebuf, 0, 0); + if ( dev->base_address[j] == 0 ) + panic("PCIC: failed make mapping for " + "pci device '%s' with address %lx\n", + namebuf, address); + + dev->base_address[j] ^= addrflags; + return; + } + } + } + + panic("PCIC: unable to locate prom node for pci device (%x,%x) \n", + dev->device, dev->vendor); +} + +/* + * Assign IO space for a device. + * This is a chance for devices which have the same IO and Mem Space to + * fork access to IO and Mem. + * + * Now, we assume there is one such device only (IGA 1682) but code below + * should work in cases when space of all such devices is less then 16MB. + */ +unsigned long pcic_alloc_io( unsigned long* addr ) +{ + unsigned long paddr = *addr; + unsigned long offset; + + if(pcic->pcic_mapped_io == 0) { + pcic->pcic_mapped_io = paddr & ~(PCI_SPACE_SIZE-1) ; + writeb((pcic->pcic_mapped_io>>24) & 0xff, + pcic->pcic_regs+PCI_PIBAR); + writeb((pcic->pcic_io_phys>>24) & PCI_SIBAR_ADDRESS_MASK, + pcic->pcic_regs+PCI_SIBAR); + writeb(PCI_ISIZE_16M, pcic->pcic_regs+PCI_ISIZE); + } + if(paddr < pcic->pcic_mapped_io || + paddr > pcic->pcic_mapped_io + PCI_SPACE_SIZE) + return 0; + offset = paddr - pcic->pcic_mapped_io; + *addr = pcic->pcic_io_phys + offset; + return pcic->pcic_io + offset; +} + +/* + * Stolen from both i386 and sparc64 branch + */ +__initfunc(void pcibios_fixup(void)) +{ + struct pci_dev *dev; + int i, has_io, has_mem; + unsigned short cmd; + + if(pcic == NULL) { + prom_printf("PCI: Error, PCIC not found.\n"); + prom_halt(); + } + + for (dev = pci_devices; dev; dev=dev->next) { + /* + * Comment from i386 branch: + * There are buggy BIOSes that forget to enable I/O and memory + * access to PCI devices. We try to fix this, but we need to + * be sure that the BIOS didn't forget to assign an address + * to the device. [mj] + * OBP is a case of such BIOS :-) + */ + has_io = has_mem = 0; + for(i=0; i<6; i++) { + unsigned long a = dev->base_address[i]; + if (a & PCI_BASE_ADDRESS_SPACE_IO) { + has_io = 1; + } else if (a & PCI_BASE_ADDRESS_MEM_MASK) + has_mem = 1; + } + pci_read_config_word(dev, PCI_COMMAND, &cmd); + if (has_io && !(cmd & PCI_COMMAND_IO)) { + printk("PCI: Enabling I/O for device %02x:%02x\n", + dev->bus->number, dev->devfn); + cmd |= PCI_COMMAND_IO; + pci_write_config_word(dev, PCI_COMMAND, cmd); + } + if (has_mem && !(cmd & PCI_COMMAND_MEMORY)) { + printk("PCI: Enabling memory for device %02x:%02x\n", + dev->bus->number, dev->devfn); + cmd |= PCI_COMMAND_MEMORY; + pci_write_config_word(dev, PCI_COMMAND, cmd); + } + + /* cookies */ + { + struct pcidev_cookie *pcp; + struct linux_pbm_info* pbm = &pcic->pbm; + int node = pdev_to_pnode(pbm, dev); + + if(node == 0) + node = -1; + pcp = pci_devcookie_alloc(); + pcp->pbm = pbm; + pcp->prom_node = node; + dev->sysdata = pcp; + } + + /* memory mapping */ + if (!(dev->vendor == PCI_VENDOR_ID_SUN && + dev->device == PCI_DEVICE_ID_SUN_EBUS)) { + pcic_map_pci_device(dev); + } + + /* irq */ +#define SETIRQ(vend,devid,irqn) \ + if (dev->vendor==vend && dev->device==devid) dev->irq = irqn; + + SETIRQ(PCI_VENDOR_ID_SUN,PCI_DEVICE_ID_SUN_HAPPYMEAL,3); + } + ebus_init(); +} + +/* Makes compiler happy */ +static volatile int pcic_timer_dummy; + +static void pcic_clear_clock_irq(void) +{ + pcic_timer_dummy = readl(pcic->pcic_regs+PCI_SYS_LIMIT); +} + +static void pcic_timer_handler (int irq, void *h, struct pt_regs *regs) +{ + pcic_clear_clock_irq(); + do_timer(regs); +} + +#define USECS_PER_JIFFY 10000 /* We have 100HZ "standard" timer for sparc */ +#define TICK_TIMER_LIMIT ((100*1000000/4)/100) + +__initfunc(void pci_time_init(void)) +{ + unsigned long v; + int timer_irq, irq; + + do_get_fast_time = pci_do_gettimeofday; + /* A hack until do_gettimeofday prototype is moved to arch specific headers + and btfixupped. Patch do_gettimeofday with ba pci_do_gettimeofday; nop */ + ((unsigned int *)do_gettimeofday)[0] = + 0x10800000 | (((unsigned long)pci_do_gettimeofday - (unsigned long)do_gettimeofday) & 0x003fffff); + ((unsigned int *)do_gettimeofday)[1] = + 0x01000000; + BTFIXUPSET_CALL(bus_do_settimeofday, pci_do_settimeofday, BTFIXUPCALL_NORM); + btfixup(); + + writel (TICK_TIMER_LIMIT, pcic->pcic_regs+PCI_SYS_LIMIT); + /* PROM should set appropriate irq */ + v = readb(pcic->pcic_regs+PCI_COUNTER_IRQ); + timer_irq = PCI_COUNTER_IRQ_SYS(v); + writel (PCI_COUNTER_IRQ_SET(timer_irq, 0), + pcic->pcic_regs+PCI_COUNTER_IRQ); + irq = request_irq(timer_irq, pcic_timer_handler, + (SA_INTERRUPT | SA_STATIC_ALLOC), "timer", NULL); + if (irq) { + prom_printf("time_init: unable to attach IRQ%d\n", timer_irq); + prom_halt(); + } + __sti(); +} + +static __inline__ unsigned long do_gettimeoffset(void) +{ + unsigned long offset = 0; + + /* + * We devide all to 100 + * to have microsecond resolution and to avoid overflow + */ + unsigned long count = + readl(pcic->pcic_regs+PCI_SYS_COUNTER) & ~PCI_SYS_COUNTER_OVERFLOW; + count = ((count/100)*USECS_PER_JIFFY) / (TICK_TIMER_LIMIT/100); + + if(test_bit(TIMER_BH, &bh_active)) + offset = 1000000; + return offset + count; +} + +extern volatile unsigned long lost_ticks; + +static void pci_do_gettimeofday(struct timeval *tv) +{ + unsigned long flags; + + save_and_cli(flags); + *tv = xtime; + tv->tv_usec += do_gettimeoffset(); + + /* + * xtime is atomically updated in timer_bh. lost_ticks is + * nonzero if the timer bottom half hasnt executed yet. + */ + if (lost_ticks) + tv->tv_usec += USECS_PER_JIFFY; + + restore_flags(flags); + + if (tv->tv_usec >= 1000000) { + tv->tv_usec -= 1000000; + tv->tv_sec++; + } +} + +static void pci_do_settimeofday(struct timeval *tv) +{ + cli(); + tv->tv_usec -= do_gettimeoffset(); + if(tv->tv_usec < 0) { + tv->tv_usec += 1000000; + tv->tv_sec--; + } + xtime = *tv; + time_state = TIME_BAD; + time_maxerror = 0x70000000; + time_esterror = 0x70000000; + sti(); +} + +#if 0 +static void watchdog_reset() { + writeb(0, pcic->pcic_regs+PCI_SYS_STATUS); +} +#endif + +#define CONFIG_CMD(bus, device_fn, where) (0x80000000 | (((unsigned int)bus) << 16) | (((unsigned int)device_fn) << 8) | (where & ~3)) + +int pcibios_read_config_byte(unsigned char bus, unsigned char device_fn, + unsigned char where, unsigned char *value) +{ + unsigned int v; + + pcibios_read_config_dword (bus, device_fn, where&~3, &v); + *value = 0xff & (v >> (8*(where & 3))); + return PCIBIOS_SUCCESSFUL; +} + +int pcibios_read_config_word (unsigned char bus, + unsigned char device_fn, + unsigned char where, unsigned short *value) +{ + unsigned int v; + if (where&1) return PCIBIOS_BAD_REGISTER_NUMBER; + + pcibios_read_config_dword (bus, device_fn, where&~3, &v); + *value = 0xffff & (v >> (8*(where & 3))); + return PCIBIOS_SUCCESSFUL; +} + +int pcibios_read_config_dword (unsigned char bus, unsigned char device_fn, + unsigned char where, unsigned int *value) +{ + unsigned long flags; + if (where&3) return PCIBIOS_BAD_REGISTER_NUMBER; + if (bus != 0 || + (device_fn != 0 && device_fn != 1 && device_fn != 0x80)) { + *value = 0xffffffff; + return PCIBIOS_SUCCESSFUL; + } + + /* FIXME: IGA haven't got high config memory addresses !!! */ + if (device_fn == 0x80 && where > PCI_INTERRUPT_LINE) { + *value = 0xffffffff; + return PCIBIOS_SUCCESSFUL; + } + + save_and_cli(flags); + writel(CONFIG_CMD(bus,device_fn,where), pcic->pcic_config_space_addr); + *value = readl(pcic->pcic_config_space_data + (where&4)); + restore_flags(flags); + return PCIBIOS_SUCCESSFUL; +} + +int pcibios_write_config_byte (unsigned char bus, unsigned char devfn, + unsigned char where, unsigned char value) +{ + unsigned int v; + + pcibios_read_config_dword (bus, devfn, where&~3, &v); + v = (v & ~(0xff << (8*(where&3)))) | + ((0xff&(unsigned)value) << (8*(where&3))); + return pcibios_write_config_dword (bus, devfn, where&~3, v); +} + +int pcibios_write_config_word (unsigned char bus, unsigned char devfn, + unsigned char where, unsigned short value) +{ + unsigned int v; + if (where&1) return PCIBIOS_BAD_REGISTER_NUMBER; + + pcibios_read_config_dword (bus, devfn, where&~3, &v); + v = (v & ~(0xffff << (8*(where&3)))) | + ((0xffff&(unsigned)value) << (8*(where&3))); + return pcibios_write_config_dword (bus, devfn, where&~3, v); +} + +int pcibios_write_config_dword (unsigned char bus, unsigned char devfn, + unsigned char where, unsigned int value) +{ + unsigned long flags; + if ((where&3) || bus != 0 || (devfn != 0 && devfn != 1 && devfn != 0x80)) + return PCIBIOS_BAD_REGISTER_NUMBER; + + save_and_cli(flags); + writel(CONFIG_CMD(bus,devfn,where),pcic->pcic_config_space_addr); + writel(value, pcic->pcic_config_space_data + (where&4)); + restore_flags(flags); + return PCIBIOS_SUCCESSFUL; +} + +__initfunc(char *pcibios_setup(char *str)) +{ + return str; +} + +/* + * Following code added to handle extra PCI-related system calls + */ +asmlinkage int sys_pciconfig_read(unsigned long bus, + unsigned long dfn, + unsigned long off, + unsigned long len, + unsigned char *buf) +{ + unsigned char ubyte; + unsigned short ushort; + unsigned int uint; + int err = 0; + + if(!suser()) + return -EPERM; + + lock_kernel(); + switch(len) { + case 1: + pcibios_read_config_byte(bus, dfn, off, &ubyte); + put_user(ubyte, (unsigned char *)buf); + break; + case 2: + pcibios_read_config_word(bus, dfn, off, &ushort); + put_user(ushort, (unsigned short *)buf); + break; + case 4: + pcibios_read_config_dword(bus, dfn, off, &uint); + put_user(uint, (unsigned int *)buf); + break; + + default: + err = -EINVAL; + break; + }; + unlock_kernel(); + + return err; +} + +asmlinkage int sys_pciconfig_write(unsigned long bus, + unsigned long dfn, + unsigned long off, + unsigned long len, + unsigned char *buf) +{ + unsigned char ubyte; + unsigned short ushort; + unsigned int uint; + int err = 0; + + if(!suser()) + return -EPERM; + + lock_kernel(); + switch(len) { + case 1: + err = get_user(ubyte, (unsigned char *)buf); + if(err) + break; + pcibios_write_config_byte(bus, dfn, off, ubyte); + break; + + case 2: + err = get_user(ushort, (unsigned short *)buf); + if(err) + break; + pcibios_write_config_byte(bus, dfn, off, ushort); + break; + + case 4: + err = get_user(uint, (unsigned int *)buf); + if(err) + break; + pcibios_write_config_byte(bus, dfn, off, uint); + break; + + default: + err = -EINVAL; + break; + + }; + unlock_kernel(); + + return err; +} + +static inline unsigned long get_irqmask(int irq_nr) +{ + return 1 << irq_nr; +} + +static inline char *pcic_irq_itoa(unsigned int irq) +{ + static char buff[16]; + sprintf(buff, "%d", irq); + return buff; +} + +static void pcic_disable_irq(unsigned int irq_nr) +{ + unsigned long mask, flags; + + mask = get_irqmask(irq_nr); + save_and_cli(flags); + writel(mask, pcic->pcic_regs+PCI_SYS_INT_TARGET_MASK_SET); + restore_flags(flags); +} + +static void pcic_enable_irq(unsigned int irq_nr) +{ + unsigned long mask, flags; + + mask = get_irqmask(irq_nr); + save_and_cli(flags); + writel(mask, pcic->pcic_regs+PCI_SYS_INT_TARGET_MASK_CLEAR); + restore_flags(flags); +} + +static void pcic_clear_profile_irq(int cpu) +{ + printk("PCIC: unimplemented code: FILE=%s LINE=%d", __FILE__, __LINE__); +} + +static void pcic_load_profile_irq(int cpu, unsigned int limit) +{ + printk("PCIC: unimplemented code: FILE=%s LINE=%d", __FILE__, __LINE__); +} + +/* We assume the caller is local cli()'d when these are called, or else + * very bizarre behavior will result. + */ +static void pcic_disable_pil_irq(unsigned int pil) +{ + writel(get_irqmask(pil), pcic->pcic_regs+PCI_SYS_INT_TARGET_MASK_SET); +} + +static void pcic_enable_pil_irq(unsigned int pil) +{ + writel(get_irqmask(pil), pcic->pcic_regs+PCI_SYS_INT_TARGET_MASK_CLEAR); +} + +__initfunc(void sun4m_pci_init_IRQ(void)) +{ + BTFIXUPSET_CALL(enable_irq, pcic_enable_irq, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(disable_irq, pcic_disable_irq, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(enable_pil_irq, pcic_enable_pil_irq, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(disable_pil_irq, pcic_disable_pil_irq, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(clear_clock_irq, pcic_clear_clock_irq, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(clear_profile_irq, pcic_clear_profile_irq, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(load_profile_irq, pcic_load_profile_irq, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(__irq_itoa, pcic_irq_itoa, BTFIXUPCALL_NORM); +} + +__initfunc(void pcibios_fixup_bus(struct pci_bus *bus)) +{ +} + +#endif diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/process.c linux/arch/sparc/kernel/process.c --- v2.1.123/linux/arch/sparc/kernel/process.c Thu Aug 6 14:06:30 1998 +++ linux/arch/sparc/kernel/process.c Sun Oct 4 10:22:42 1998 @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.118 1998/08/04 20:48:47 davem Exp $ +/* $Id: process.c,v 1.126 1998/09/21 05:05:18 jj Exp $ * linux/arch/sparc/kernel/process.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -61,8 +61,8 @@ goto out; /* endless idle loop with no priority at all */ - current->priority = -100; - current->counter = -100; + current->priority = 0; + current->counter = 0; for (;;) { if (ARCH_SUN4C_SUN4) { static int count = HZ; @@ -108,16 +108,13 @@ /* This is being executed in task 0 'user space'. */ int cpu_idle(void *unused) { - extern volatile int smp_commenced; - - current->priority = -100; + current->priority = 0; while(1) { - srmmu_check_pgt_cache(); - run_task_queue(&tq_scheduler); - /* endless idle loop with no priority at all */ - current->counter = -100; - if(!smp_commenced || current->need_resched) - schedule(); + check_pgt_cache(); + run_task_queue(&tq_scheduler); + /* endless idle loop with no priority at all */ + current->counter = 0; + schedule(); } } @@ -176,8 +173,10 @@ void machine_power_off(void) { +#ifdef CONFIG_SUN_AUXIO if (auxio_power_register) *auxio_power_register |= AUXIO_POWER_OFF; +#endif machine_halt(); } @@ -594,8 +593,44 @@ */ int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs) { - /* Currently we report that we couldn't dump the fpu structure */ - return 0; + if (current->used_math == 0) { + memset(fpregs, 0, sizeof(*fpregs)); + fpregs->pr_q_entrysize = 8; + return 1; + } +#ifdef __SMP__ + if (current->flags & PF_USEDFPU) { + put_psr(get_psr() | PSR_EF); + fpsave(¤t->tss.float_regs[0], ¤t->tss.fsr, + ¤t->tss.fpqueue[0], ¤t->tss.fpqdepth); + regs->psr &= ~(PSR_EF); + current->flags &= ~(PF_USEDFPU); + } +#else + if (current == last_task_used_math) { + put_psr(get_psr() | PSR_EF); + fpsave(¤t->tss.float_regs[0], ¤t->tss.fsr, + ¤t->tss.fpqueue[0], ¤t->tss.fpqdepth); + last_task_used_math = 0; + regs->psr &= ~(PSR_EF); + } +#endif + memcpy(&fpregs->pr_fr.pr_regs[0], + ¤t->tss.float_regs[0], + (sizeof(unsigned long) * 32)); + fpregs->pr_fsr = current->tss.fsr; + fpregs->pr_qcnt = current->tss.fpqdepth; + fpregs->pr_q_entrysize = 8; + fpregs->pr_en = 1; + if(fpregs->pr_qcnt != 0) { + memcpy(&fpregs->pr_q[0], + ¤t->tss.fpqueue[0], + sizeof(struct fpq) * fpregs->pr_qcnt); + } + /* Zero out the rest. */ + memset(&fpregs->pr_q[fpregs->pr_qcnt], 0, + sizeof(struct fpq) * (32 - fpregs->pr_qcnt)); + return 1; } /* diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/setup.c linux/arch/sparc/kernel/setup.c --- v2.1.123/linux/arch/sparc/kernel/setup.c Thu Aug 6 14:06:30 1998 +++ linux/arch/sparc/kernel/setup.c Sun Oct 4 10:22:42 1998 @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.99 1998/07/28 16:52:45 jj Exp $ +/* $Id: setup.c,v 1.103 1998/09/21 05:05:23 jj Exp $ * linux/arch/sparc/kernel/setup.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -332,9 +332,6 @@ switch(sparc_cpu_model) { case sun4: printk("SUN4\n"); -#ifdef CONFIG_SUN4_FORCECONSOLE - register_console(&prom_console); -#endif packed = 0; break; case sun4c: @@ -443,8 +440,14 @@ serial_console = 1; } else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) { serial_console = 2; + } else if (idev == PROMDEV_I_UNK && odev == PROMDEV_OTTYA) { + prom_printf("MrCoffee ttya\n"); + serial_console = 1; + } else if (idev == PROMDEV_I_UNK && odev == PROMDEV_OSCREEN) { + serial_console = 0; + prom_printf("MrCoffee keyboard\n"); } else { - prom_printf("Inconsistent console\n"); + prom_printf("Inconsistent or unknown console\n"); prom_halt(); } } diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/signal.c linux/arch/sparc/kernel/signal.c --- v2.1.123/linux/arch/sparc/kernel/signal.c Thu Aug 6 14:06:30 1998 +++ linux/arch/sparc/kernel/signal.c Sun Oct 4 10:22:42 1998 @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.82 1998/07/31 05:18:51 jj Exp $ +/* $Id: signal.c,v 1.86 1998/09/29 09:46:04 davem Exp $ * linux/arch/sparc/kernel/signal.c * * Copyright (C) 1991, 1992 Linus Torvalds @@ -423,7 +423,7 @@ { struct signal_sframe *sframep; struct sigcontext *sc; - int window = 0; + int window = 0, err; synchronize_user_stack(); sframep = (struct signal_sframe *)get_sigframe(sa, regs, SF_ALIGNEDSZ); @@ -443,43 +443,47 @@ sc = &sframep->sig_context; /* We've already made sure frame pointer isn't in kernel space... */ - __put_user((sas_ss_flags(regs->u_regs[UREG_FP]) == SS_ONSTACK), &sc->sigc_onstack); - __put_user(oldset->sig[0], &sc->sigc_mask); - __copy_to_user(sframep->extramask, &oldset->sig[1], - (_NSIG_WORDS - 1) * sizeof(unsigned int)); - __put_user(regs->u_regs[UREG_FP], &sc->sigc_sp); - __put_user(pc, &sc->sigc_pc); - __put_user(npc, &sc->sigc_npc); - __put_user(regs->psr, &sc->sigc_psr); - __put_user(regs->u_regs[UREG_G1], &sc->sigc_g1); - __put_user(regs->u_regs[UREG_I0], &sc->sigc_o0); - __put_user(current->tss.w_saved, &sc->sigc_oswins); + err = __put_user((sas_ss_flags(regs->u_regs[UREG_FP]) == SS_ONSTACK), + &sc->sigc_onstack); + err |= __put_user(oldset->sig[0], &sc->sigc_mask); + err |= __copy_to_user(sframep->extramask, &oldset->sig[1], + (_NSIG_WORDS - 1) * sizeof(unsigned int)); + err |= __put_user(regs->u_regs[UREG_FP], &sc->sigc_sp); + err |= __put_user(pc, &sc->sigc_pc); + err |= __put_user(npc, &sc->sigc_npc); + err |= __put_user(regs->psr, &sc->sigc_psr); + err |= __put_user(regs->u_regs[UREG_G1], &sc->sigc_g1); + err |= __put_user(regs->u_regs[UREG_I0], &sc->sigc_o0); + err |= __put_user(current->tss.w_saved, &sc->sigc_oswins); if(current->tss.w_saved) for(window = 0; window < current->tss.w_saved; window++) { sc->sigc_spbuf[window] = (char *)current->tss.rwbuf_stkptrs[window]; - copy_to_user(&sc->sigc_wbuf[window], - ¤t->tss.reg_window[window], - sizeof(struct reg_window)); + err |= copy_to_user(&sc->sigc_wbuf[window], + ¤t->tss.reg_window[window], + sizeof(struct reg_window)); } else - copy_to_user(sframep, (char *)regs->u_regs[UREG_FP], - sizeof(struct reg_window)); + err |= copy_to_user(sframep, (char *)regs->u_regs[UREG_FP], + sizeof(struct reg_window)); current->tss.w_saved = 0; /* So process is allowed to execute. */ - __put_user(signr, &sframep->sig_num); + err |= __put_user(signr, &sframep->sig_num); if(signr == SIGSEGV || signr == SIGILL || signr == SIGFPE || signr == SIGBUS || signr == SIGEMT) { - __put_user(current->tss.sig_desc, &sframep->sig_code); - __put_user(current->tss.sig_address, &sframep->sig_address); + err |= __put_user(current->tss.sig_desc, &sframep->sig_code); + err |= __put_user(current->tss.sig_address, &sframep->sig_address); } else { - __put_user(0, &sframep->sig_code); - __put_user(0, &sframep->sig_address); + err |= __put_user(0, &sframep->sig_code); + err |= __put_user(0, &sframep->sig_address); } - __put_user(sc, &sframep->sig_scptr); + err |= __put_user(sc, &sframep->sig_scptr); + if (err) + goto sigsegv; + regs->u_regs[UREG_FP] = (unsigned long) sframep; regs->pc = (unsigned long) sa->sa_handler; regs->npc = (regs->pc + 4); @@ -489,12 +493,16 @@ /* Ugh, we need to grab master lock in these rare cases ;-( */ lock_kernel(); do_exit(SIGILL); +sigsegv: + lock_kernel(); + do_exit(SIGSEGV); } -static inline void +static inline int save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t *fpu) { + int err = 0; #ifdef __SMP__ if (current->flags & PF_USEDFPU) { put_psr(get_psr() | PSR_EF); @@ -512,15 +520,16 @@ regs->psr &= ~(PSR_EF); } #endif - copy_to_user(&fpu->si_float_regs[0], ¤t->tss.float_regs[0], - (sizeof(unsigned long) * 32)); - __put_user(current->tss.fsr, &fpu->si_fsr); - __put_user(current->tss.fpqdepth, &fpu->si_fpqdepth); + err |= copy_to_user(&fpu->si_float_regs[0], ¤t->tss.float_regs[0], + (sizeof(unsigned long) * 32)); + err |= __put_user(current->tss.fsr, &fpu->si_fsr); + err |= __put_user(current->tss.fpqdepth, &fpu->si_fpqdepth); if (current->tss.fpqdepth != 0) - copy_to_user(&fpu->si_fpqueue[0], ¤t->tss.fpqueue[0], - ((sizeof(unsigned long) + - (sizeof(unsigned long *)))*16)); + err |= copy_to_user(&fpu->si_fpqueue[0], ¤t->tss.fpqueue[0], + ((sizeof(unsigned long) + + (sizeof(unsigned long *)))*16)); current->used_math = 0; + return err; } static inline void @@ -528,7 +537,7 @@ int signo, sigset_t *oldset) { struct new_signal_frame *sf; - int sigframe_size; + int sigframe_size, err; /* 1. Make sure everything is clean */ synchronize_user_stack(); @@ -551,20 +560,22 @@ } /* 2. Save the current process state */ - copy_to_user(&sf->info.si_regs, regs, sizeof (struct pt_regs)); + err = copy_to_user(&sf->info.si_regs, regs, sizeof (struct pt_regs)); if (current->used_math) { - save_fpu_state(regs, &sf->fpu_state); - __put_user(&sf->fpu_state, &sf->fpu_save); + err |= save_fpu_state(regs, &sf->fpu_state); + err |= __put_user(&sf->fpu_state, &sf->fpu_save); } else { - __put_user(0, &sf->fpu_save); + err |= __put_user(0, &sf->fpu_save); } - __put_user(oldset->sig[0], &sf->info.si_mask); - __copy_to_user(sf->extramask, &oldset->sig[1], - (_NSIG_WORDS - 1) * sizeof(unsigned int)); - copy_to_user(sf, (char *) regs->u_regs [UREG_FP], - sizeof (struct reg_window)); + err |= __put_user(oldset->sig[0], &sf->info.si_mask); + err |= __copy_to_user(sf->extramask, &oldset->sig[1], + (_NSIG_WORDS - 1) * sizeof(unsigned int)); + err |= copy_to_user(sf, (char *) regs->u_regs [UREG_FP], + sizeof (struct reg_window)); + if (err) + goto sigsegv; /* 3. signal handler back-trampoline and parameters */ regs->u_regs[UREG_FP] = (unsigned long) sf; @@ -581,8 +592,13 @@ else { regs->u_regs[UREG_I7] = (unsigned long)(&(sf->insns[0]) - 2); - __put_user(0x821020d8, &sf->insns[0]); /* mov __NR_sigreturn, %g1 */ - __put_user(0x91d02010, &sf->insns[1]); /* t 0x10 */ + /* mov __NR_sigreturn, %g1 */ + err |= __put_user(0x821020d8, &sf->insns[0]); + + /* t 0x10 */ + err |= __put_user(0x91d02010, &sf->insns[1]); + if (err) + goto sigsegv; /* Flush instruction space. */ flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0])); @@ -592,6 +608,9 @@ sigill_and_return: lock_kernel(); do_exit(SIGILL); +sigsegv: + lock_kernel(); + do_exit(SIGSEGV); } static inline void @@ -601,7 +620,7 @@ struct rt_signal_frame *sf; int sigframe_size; unsigned int psr; - int i; + int i, err; synchronize_user_stack(); sigframe_size = RT_ALIGNEDSZ; @@ -613,30 +632,32 @@ if(current->tss.w_saved != 0) goto sigill; - put_user(regs->pc, &sf->regs.pc); - __put_user(regs->npc, &sf->regs.npc); - __put_user(regs->y, &sf->regs.y); + err = put_user(regs->pc, &sf->regs.pc); + err |= __put_user(regs->npc, &sf->regs.npc); + err |= __put_user(regs->y, &sf->regs.y); psr = regs->psr; if(current->used_math) psr |= PSR_EF; - __put_user(psr, &sf->regs.psr); + err |= __put_user(psr, &sf->regs.psr); for(i = 0; i < 16; i++) - __put_user(regs->u_regs[i], &sf->regs.u_regs[i]); + err |= __put_user(regs->u_regs[i], &sf->regs.u_regs[i]); if(psr & PSR_EF) { - save_fpu_state(regs, &sf->fpu_state); - __put_user(&sf->fpu_state, &sf->fpu_save); + err |= save_fpu_state(regs, &sf->fpu_state); + err |= __put_user(&sf->fpu_state, &sf->fpu_save); } else { - __put_user(0, &sf->fpu_save); + err |= __put_user(0, &sf->fpu_save); } - __copy_to_user(&sf->mask, &oldset->sig[0], sizeof(sigset_t)); + err |= __copy_to_user(&sf->mask, &oldset->sig[0], sizeof(sigset_t)); /* Setup sigaltstack */ - __put_user(current->sas_ss_sp, &sf->stack.ss_sp); - __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags); - __put_user(current->sas_ss_size, &sf->stack.ss_size); + err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp); + err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags); + err |= __put_user(current->sas_ss_size, &sf->stack.ss_size); - copy_to_user(sf, (char *) regs->u_regs [UREG_FP], - sizeof (struct reg_window)); + err |= copy_to_user(sf, (char *) regs->u_regs [UREG_FP], + sizeof (struct reg_window)); + if (err) + goto sigsegv; regs->u_regs[UREG_FP] = (unsigned long) sf; regs->u_regs[UREG_I0] = signo; @@ -650,8 +671,13 @@ else { regs->u_regs[UREG_I7] = (unsigned long)(&(sf->insns[0]) - 2); - __put_user(0x821020d8, &sf->insns[0]); /* mov __NR_sigreturn, %g1 */ - __put_user(0x91d02010, &sf->insns[1]); /* t 0x10 */ + /* mov __NR_sigreturn, %g1 */ + err |= __put_user(0x821020d8, &sf->insns[0]); + + /* t 0x10 */ + err |= __put_user(0x91d02010, &sf->insns[1]); + if (err) + goto sigsegv; /* Flush instruction space. */ flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0])); @@ -661,6 +687,9 @@ sigill: lock_kernel(); do_exit(SIGILL); +sigsegv: + lock_kernel(); + do_exit(SIGSEGV); } /* Setup a Solaris stack frame */ @@ -675,7 +704,7 @@ svr4_gwindows_t *gw; svr4_ucontext_t *uc; svr4_sigset_t setv; - int window = 0; + int window = 0, err; synchronize_user_stack(); sfp = (svr4_signal_frame_t *) get_sigframe(sa, regs, SVR4_SF_ALIGNED + REGWIN_SZ); @@ -688,7 +717,7 @@ } /* Start with a clean frame pointer and fill it */ - clear_user(sfp, sizeof (*sfp)); + err = clear_user(sfp, sizeof (*sfp)); /* Setup convenience variables */ si = &sfp->si; @@ -706,32 +735,32 @@ if (_NSIG_WORDS >= 4) { setv.sigbits[2] = oldset->sig[2]; setv.sigbits[3] = oldset->sig[3]; - __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t)); + err |= __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t)); } else - __copy_to_user(&uc->sigmask, &setv, 2 * sizeof(unsigned int)); + err |= __copy_to_user(&uc->sigmask, &setv, 2 * sizeof(unsigned int)); /* Store registers */ - __put_user(regs->pc, &((*gr) [SVR4_PC])); - __put_user(regs->npc, &((*gr) [SVR4_NPC])); - __put_user(regs->psr, &((*gr) [SVR4_PSR])); - __put_user(regs->y, &((*gr) [SVR4_Y])); + err |= __put_user(regs->pc, &((*gr) [SVR4_PC])); + err |= __put_user(regs->npc, &((*gr) [SVR4_NPC])); + err |= __put_user(regs->psr, &((*gr) [SVR4_PSR])); + err |= __put_user(regs->y, &((*gr) [SVR4_Y])); /* Copy g [1..7] and o [0..7] registers */ - copy_to_user(&(*gr)[SVR4_G1], ®s->u_regs [UREG_G1], sizeof (long) * 7); - copy_to_user(&(*gr)[SVR4_O0], ®s->u_regs [UREG_I0], sizeof (long) * 8); + err |= copy_to_user(&(*gr)[SVR4_G1], ®s->u_regs [UREG_G1], sizeof (long) * 7); + err |= copy_to_user(&(*gr)[SVR4_O0], ®s->u_regs [UREG_I0], sizeof (long) * 8); /* Setup sigaltstack */ - __put_user(current->sas_ss_sp, &uc->stack.sp); - __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags); - __put_user(current->sas_ss_size, &uc->stack.size); + err |= __put_user(current->sas_ss_sp, &uc->stack.sp); + err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags); + err |= __put_user(current->sas_ss_size, &uc->stack.size); /* Save the currently window file: */ /* 1. Link sfp->uc->gwins to our windows */ - __put_user(gw, &mc->gwin); + err |= __put_user(gw, &mc->gwin); /* 2. Number of windows to restore at setcontext (): */ - __put_user(current->tss.w_saved, &gw->count); + err |= __put_user(current->tss.w_saved, &gw->count); /* 3. Save each valid window * Currently, it makes a copy of the windows from the kernel copy. @@ -745,9 +774,11 @@ * to flush the user windows. */ for(window = 0; window < current->tss.w_saved; window++) { - __put_user((int *) &(gw->win [window]), &gw->winptr [window]); - copy_to_user(&gw->win [window], ¤t->tss.reg_window [window], sizeof (svr4_rwindow_t)); - __put_user(0, gw->winptr [window]); + err |= __put_user((int *) &(gw->win [window]), &gw->winptr [window]); + err |= copy_to_user(&gw->win [window], + ¤t->tss.reg_window [window], + sizeof (svr4_rwindow_t)); + err |= __put_user(0, gw->winptr [window]); } /* 4. We just pay attention to the gw->count field on setcontext */ @@ -758,8 +789,10 @@ * that much currently, should use those that David already * is providing with tss.sig_desc */ - __put_user(signr, &si->siginfo.signo); - __put_user(SVR4_SINOINFO, &si->siginfo.code); + err |= __put_user(signr, &si->siginfo.signo); + err |= __put_user(SVR4_SINOINFO, &si->siginfo.code); + if (err) + goto sigsegv; regs->u_regs[UREG_FP] = (unsigned long) sfp; regs->pc = (unsigned long) sa->sa_handler; @@ -772,10 +805,13 @@ if (regs->u_regs [14]){ struct reg_window *rw = (struct reg_window *) regs->u_regs [14]; - __put_user(signr, &rw->ins [0]); - __put_user(si, &rw->ins [1]); - __put_user(uc, &rw->ins [2]); - __put_user(sfp, &rw->ins [6]); /* frame pointer */ + err |= __put_user(signr, &rw->ins [0]); + err |= __put_user(si, &rw->ins [1]); + err |= __put_user(uc, &rw->ins [2]); + err |= __put_user(sfp, &rw->ins [6]); /* frame pointer */ + if (err) + goto sigsegv; + regs->u_regs[UREG_I0] = signr; regs->u_regs[UREG_I1] = (uint) si; regs->u_regs[UREG_I2] = (uint) uc; @@ -785,6 +821,9 @@ sigill_and_return: lock_kernel(); do_exit(SIGILL); +sigsegv: + lock_kernel(); + do_exit(SIGSEGV); } asmlinkage int svr4_getcontext (svr4_ucontext_t *uc, struct pt_regs *regs) @@ -792,14 +831,14 @@ svr4_gregset_t *gr; svr4_mcontext_t *mc; svr4_sigset_t setv; + int err = 0; synchronize_user_stack(); if (current->tss.w_saved) goto sigsegv_and_return; - if(clear_user(uc, sizeof (*uc))) - return -EFAULT; + err = clear_user(uc, sizeof (*uc)); /* Setup convenience variables */ mc = &uc->mcontext; @@ -810,29 +849,29 @@ if (_NSIG_WORDS >= 4) { setv.sigbits[2] = current->blocked.sig[2]; setv.sigbits[3] = current->blocked.sig[3]; - __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t)); + err |= __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t)); } else - __copy_to_user(&uc->sigmask, &setv, 2 * sizeof(unsigned int)); + err |= __copy_to_user(&uc->sigmask, &setv, 2 * sizeof(unsigned int)); /* Store registers */ - __put_user(regs->pc, &uc->mcontext.greg [SVR4_PC]); - __put_user(regs->npc, &uc->mcontext.greg [SVR4_NPC]); - __put_user(regs->psr, &uc->mcontext.greg [SVR4_PSR]); - __put_user(regs->y, &uc->mcontext.greg [SVR4_Y]); + err |= __put_user(regs->pc, &uc->mcontext.greg [SVR4_PC]); + err |= __put_user(regs->npc, &uc->mcontext.greg [SVR4_NPC]); + err |= __put_user(regs->psr, &uc->mcontext.greg [SVR4_PSR]); + err |= __put_user(regs->y, &uc->mcontext.greg [SVR4_Y]); /* Copy g [1..7] and o [0..7] registers */ - copy_to_user(&(*gr)[SVR4_G1], ®s->u_regs [UREG_G1], sizeof (uint) * 7); - copy_to_user(&(*gr)[SVR4_O0], ®s->u_regs [UREG_I0], sizeof (uint) * 8); + err |= copy_to_user(&(*gr)[SVR4_G1], ®s->u_regs [UREG_G1], sizeof (uint) * 7); + err |= copy_to_user(&(*gr)[SVR4_O0], ®s->u_regs [UREG_I0], sizeof (uint) * 8); /* Setup sigaltstack */ - __put_user(current->sas_ss_sp, &uc->stack.sp); - __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags); - __put_user(current->sas_ss_size, &uc->stack.size); + err |= __put_user(current->sas_ss_sp, &uc->stack.sp); + err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags); + err |= __put_user(current->sas_ss_size, &uc->stack.size); /* The register file is not saved * we have already stuffed all of it with sync_user_stack */ - return 0; + return (err ? -EFAULT : 0); sigsegv_and_return: lock_kernel(); @@ -905,15 +944,17 @@ spin_unlock_irq(¤t->sigmask_lock); regs->pc = pc; regs->npc = npc | 1; - __get_user(regs->y, &((*gr) [SVR4_Y])); - __get_user(psr, &((*gr) [SVR4_PSR])); + err |= __get_user(regs->y, &((*gr) [SVR4_Y])); + err |= __get_user(psr, &((*gr) [SVR4_PSR])); regs->psr &= ~(PSR_ICC); regs->psr |= (psr & PSR_ICC); /* Restore g[1..7] and o[0..7] registers */ - copy_from_user(®s->u_regs [UREG_G1], &(*gr)[SVR4_G1], sizeof (long) * 7); - copy_from_user(®s->u_regs [UREG_I0], &(*gr)[SVR4_O0], sizeof (long) * 8); - return 0; + err |= copy_from_user(®s->u_regs [UREG_G1], &(*gr)[SVR4_G1], + sizeof (long) * 7); + err |= copy_from_user(®s->u_regs [UREG_I0], &(*gr)[SVR4_O0], + sizeof (long) * 8); + return (err ? -EFAULT : 0); sigsegv_and_return: lock_kernel(); diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/smp.c linux/arch/sparc/kernel/smp.c --- v2.1.123/linux/arch/sparc/kernel/smp.c Thu Aug 6 14:06:30 1998 +++ linux/arch/sparc/kernel/smp.c Sun Oct 4 10:22:42 1998 @@ -159,7 +159,7 @@ local_flush_tlb_mm(mm); } else { xc1((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_mm), (unsigned long) mm); - if(mm->count == 1 && current->mm == mm) + if(atomic_read(&mm->count) == 1 && current->mm == mm) mm->cpu_vm_mask = (1 << smp_processor_id()); } } @@ -274,4 +274,27 @@ restore_flags(flags); return 0; +} + +int smp_bogo_info(char *buf) +{ + int len = 0, i; + + for (i = 0; i < NR_CPUS; i++) + if (cpu_present_map & (1 << i)) + len += sprintf(buf + len, "Cpu%dBogo\t: %lu.%02lu\n", + i, + cpu_data[i].udelay_val/500000, + (cpu_data[i].udelay_val/5000)%100); + return len; +} + +int smp_info(char *buf) +{ + int len = 0, i; + + for (i = 0; i < NR_CPUS; i++) + if (cpu_present_map & (1 << i)) + len += sprintf(buf + len, "CPU%d\t\t: online\n", i); + return len; } diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/sparc_ksyms.c linux/arch/sparc/kernel/sparc_ksyms.c --- v2.1.123/linux/arch/sparc/kernel/sparc_ksyms.c Thu Aug 6 14:06:30 1998 +++ linux/arch/sparc/kernel/sparc_ksyms.c Sun Oct 4 10:22:42 1998 @@ -1,4 +1,4 @@ -/* $Id: sparc_ksyms.c,v 1.65 1998/06/04 09:54:50 jj Exp $ +/* $Id: sparc_ksyms.c,v 1.70 1998/09/17 11:04:55 jj Exp $ * arch/sparc/kernel/ksyms.c: Sparc specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -85,11 +85,6 @@ /* used by various drivers */ EXPORT_SYMBOL(sparc_cpu_model); -#ifdef __SMP__ -EXPORT_SYMBOL(klock_info); -#endif -EXPORT_SYMBOL_PRIVATE(_lock_kernel); -EXPORT_SYMBOL_PRIVATE(_unlock_kernel); EXPORT_SYMBOL_PRIVATE(_spinlock_waitfor); #ifdef SPIN_LOCK_DEBUG EXPORT_SYMBOL(_spin_lock); @@ -119,14 +114,10 @@ EXPORT_SYMBOL(__sparc_bh_counter); #ifdef __SMP__ #ifdef DEBUG_IRQLOCK -EXPORT_SYMBOL(irq_enter); -EXPORT_SYMBOL(irq_exit); EXPORT_SYMBOL(__global_restore_flags); EXPORT_SYMBOL(__global_sti); EXPORT_SYMBOL(__global_cli); #else -EXPORT_SYMBOL_PRIVATE(_irq_enter); -EXPORT_SYMBOL_PRIVATE(_irq_exit); EXPORT_SYMBOL_PRIVATE(_global_restore_flags); EXPORT_SYMBOL_PRIVATE(_global_sti); EXPORT_SYMBOL_PRIVATE(_global_cli); @@ -134,7 +125,10 @@ #endif EXPORT_SYMBOL(page_offset); + +#ifndef CONFIG_SUN4 EXPORT_SYMBOL(stack_top); +#endif /* Atomic operations. */ EXPORT_SYMBOL_PRIVATE(_atomic_add); @@ -227,7 +221,7 @@ /* sparc library symbols */ EXPORT_SYMBOL(bcopy); -EXPORT_SYMBOL(memscan); +EXPORT_SYMBOL_NOVERS(memscan); EXPORT_SYMBOL(strlen); EXPORT_SYMBOL(strnlen); EXPORT_SYMBOL(strcpy); @@ -235,7 +229,7 @@ EXPORT_SYMBOL(strcat); EXPORT_SYMBOL(strncat); EXPORT_SYMBOL(strcmp); -EXPORT_SYMBOL(strncmp); +EXPORT_SYMBOL_NOVERS(strncmp); EXPORT_SYMBOL(strchr); EXPORT_SYMBOL(strrchr); EXPORT_SYMBOL(strpbrk); diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/sun4c_irq.c linux/arch/sparc/kernel/sun4c_irq.c --- v2.1.123/linux/arch/sparc/kernel/sun4c_irq.c Thu Aug 6 14:06:30 1998 +++ linux/arch/sparc/kernel/sun4c_irq.c Sun Oct 4 10:22:42 1998 @@ -121,7 +121,7 @@ { volatile unsigned int clear_intr; #ifdef CONFIG_SUN4 - if( idprom->id_machtype == SM_SUN4 | SM_4_260 ) + if (idprom->id_machtype == (SM_SUN4 | SM_4_260)) clear_intr = sun4_timer.timer_limit10; else #endif @@ -146,7 +146,7 @@ * the cache chip on the sun4c. */ #ifdef CONFIG_SUN4 - if (idprom->id_machtype == SM_SUN4 | SM_4_260) + if (idprom->id_machtype == (SM_SUN4 | SM_4_260)) sun4c_timers = &sun4_timer; else #endif @@ -171,7 +171,10 @@ prom_halt(); } +#if 0 + /* This does not work on 4/330 */ sun4c_enable_irq(10); +#endif claim_ticker14(NULL, PROFILE_IRQ, 0); } diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/sun4d_irq.c linux/arch/sparc/kernel/sun4d_irq.c --- v2.1.123/linux/arch/sparc/kernel/sun4d_irq.c Thu Aug 6 14:06:30 1998 +++ linux/arch/sparc/kernel/sun4d_irq.c Sun Oct 4 10:22:42 1998 @@ -1,4 +1,4 @@ -/* $Id: sun4d_irq.c,v 1.14 1998/06/04 09:54:47 jj Exp $ +/* $Id: sun4d_irq.c,v 1.15 1998/09/29 09:46:12 davem Exp $ * arch/sparc/kernel/sun4d_irq.c: * SS1000/SC2000 interrupt handling. * @@ -284,11 +284,12 @@ /* If this is flagged as statically allocated then we use our * private struct which is never freed. */ - if (irqflags & SA_STATIC_ALLOC) + if (irqflags & SA_STATIC_ALLOC) { if (static_irq_count < MAX_STATIC_ALLOC) action = &static_irqaction[static_irq_count++]; else printk("Request for IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n",irq, devname); + } if (action == NULL) action = (struct irqaction *)kmalloc(sizeof(struct irqaction), diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/sun4d_smp.c linux/arch/sparc/kernel/sun4d_smp.c --- v2.1.123/linux/arch/sparc/kernel/sun4d_smp.c Thu Aug 6 14:06:30 1998 +++ linux/arch/sparc/kernel/sun4d_smp.c Sun Oct 4 10:22:42 1998 @@ -57,7 +57,6 @@ extern int smp_activated; extern volatile int cpu_number_map[NR_CPUS]; extern volatile int __cpu_logical_map[NR_CPUS]; -extern struct klock_info klock_info; extern volatile unsigned long ipi_count; extern volatile int smp_process_available; extern volatile int smp_commenced; @@ -71,31 +70,6 @@ #define SMP_PRINTK(x) #endif -int smp4d_bogo_info(char *buf) -{ - int len = 0, i; - - for (i = 0; i < NR_CPUS; i++) - if (cpu_present_map & (1 << i)) - len += sprintf(buf + len, "Cpu%dBogo\t: %lu.%02lu\n", - i, - cpu_data[i].udelay_val/500000, - (cpu_data[i].udelay_val/5000)%100); - return len; -} - -int smp4d_info(char *buf) -{ - int len = 0, i; - - for (i = 0; i < NR_CPUS; i++) - if (cpu_present_map & (1 << i)) - len += sprintf(buf + len, "CPU%d\t\t: %s\n", - i, - (klock_info.akp == i) ? "akp" : "online"); - return len; -} - static inline unsigned long swap(volatile unsigned long *ptr, unsigned long val) { __asm__ __volatile__("swap [%1], %0\n\t" : @@ -216,7 +190,6 @@ mid_xlate[i] = i; cpu_number_map[boot_cpu_id] = 0; __cpu_logical_map[0] = boot_cpu_id; - klock_info.akp = boot_cpu_id; current->processor = boot_cpu_id; smp_store_cpu_info(boot_cpu_id); smp_setup_percpu_timer(); @@ -436,6 +409,8 @@ /* Protects counters touched during level14 ticker */ static spinlock_t ticker_lock = SPIN_LOCK_UNLOCKED; +#ifdef CONFIG_PROFILE + /* 32-bit Sparc specific profiling function. */ static inline void sparc_do_profile(unsigned long pc) { @@ -454,6 +429,8 @@ } } +#endif + extern unsigned int prof_multiplier[NR_CPUS]; extern unsigned int prof_counter[NR_CPUS]; @@ -479,9 +456,10 @@ show_leds(cpu); } +#ifdef CONFIG_PROFILE if(!user_mode(regs)) sparc_do_profile(regs->pc); - +#endif if(!--prof_counter[cpu]) { int user = user_mode(regs); if(current->pid) { @@ -559,8 +537,6 @@ BTFIXUPSET_BLACKBOX(load_current, smp4d_blackbox_current); BTFIXUPSET_CALL(smp_cross_call, smp4d_cross_call, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(smp_message_pass, smp4d_message_pass, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(smp_bogo_info, smp4d_bogo_info, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(smp_info, smp4d_info, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(__smp_processor_id, __smp4d_processor_id, BTFIXUPCALL_NORM); for (i = 0; i < NR_CPUS; i++) { diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/sun4m_irq.c linux/arch/sparc/kernel/sun4m_irq.c --- v2.1.123/linux/arch/sparc/kernel/sun4m_irq.c Thu Aug 6 14:06:30 1998 +++ linux/arch/sparc/kernel/sun4m_irq.c Sun Oct 4 10:22:42 1998 @@ -47,10 +47,12 @@ * * take an encoded intr value and lookup if it's valid * then get the mask bits that match from irq_mask + * + * P3: Translation from irq 0x0d to mask 0x2000 is for MrCoffee. */ static unsigned char irq_xlate[32] = { /* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f */ - 0, 0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 5, 6, 0, 0, 7, + 0, 0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 5, 6, 14, 0, 7, 0, 0, 8, 9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 0 }; diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/sun4m_smp.c linux/arch/sparc/kernel/sun4m_smp.c --- v2.1.123/linux/arch/sparc/kernel/sun4m_smp.c Thu Aug 6 14:06:30 1998 +++ linux/arch/sparc/kernel/sun4m_smp.c Sun Oct 4 10:22:42 1998 @@ -53,7 +53,6 @@ extern int smp_activated; extern volatile int cpu_number_map[NR_CPUS]; extern volatile int __cpu_logical_map[NR_CPUS]; -extern struct klock_info klock_info; extern volatile unsigned long ipi_count; extern volatile int smp_process_available; extern volatile int smp_commenced; @@ -67,30 +66,6 @@ #define SMP_PRINTK(x) #endif -int smp4m_bogo_info(char *buf) -{ - return sprintf(buf, - "Cpu0Bogo\t: %lu.%02lu\n" - "Cpu1Bogo\t: %lu.%02lu\n" - "Cpu2Bogo\t: %lu.%02lu\n" - "Cpu3Bogo\t: %lu.%02lu\n", - cpu_data[0].udelay_val/500000, (cpu_data[0].udelay_val/5000)%100, - cpu_data[1].udelay_val/500000, (cpu_data[1].udelay_val/5000)%100, - cpu_data[2].udelay_val/500000, (cpu_data[2].udelay_val/5000)%100, - cpu_data[3].udelay_val/500000, (cpu_data[3].udelay_val/5000)%100); -} - -int smp4m_info(char *buf) -{ - return sprintf(buf, -" CPU0\t\tCPU1\t\tCPU2\t\tCPU3\n" -"State: %s\t\t%s\t\t%s\t\t%s\n", -(cpu_present_map & 1) ? ((klock_info.akp == 0) ? "akp" : "online") : "offline", -(cpu_present_map & 2) ? ((klock_info.akp == 1) ? "akp" : "online") : "offline", -(cpu_present_map & 4) ? ((klock_info.akp == 2) ? "akp" : "online") : "offline", -(cpu_present_map & 8) ? ((klock_info.akp == 3) ? "akp" : "online") : "offline"); -} - static inline unsigned long swap(volatile unsigned long *ptr, unsigned long val) { __asm__ __volatile__("swap [%1], %0\n\t" : @@ -186,7 +161,6 @@ mid_xlate[boot_cpu_id] = (linux_cpus[boot_cpu_id].mid & ~8); cpu_number_map[boot_cpu_id] = 0; __cpu_logical_map[0] = boot_cpu_id; - klock_info.akp = boot_cpu_id; current->processor = boot_cpu_id; smp_store_cpu_info(boot_cpu_id); set_irq_udt(mid_xlate[boot_cpu_id]); @@ -468,6 +442,7 @@ if(!--prof_counter[cpu]) { int user = user_mode(regs); + if(current->pid) { update_one_process(current, 1, user, !user, cpu); @@ -534,7 +509,5 @@ BTFIXUPSET_BLACKBOX(load_current, smp4m_blackbox_current); BTFIXUPSET_CALL(smp_cross_call, smp4m_cross_call, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(smp_message_pass, smp4m_message_pass, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(smp_bogo_info, smp4m_bogo_info, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(smp_info, smp4m_info, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(__smp_processor_id, __smp4m_processor_id, BTFIXUPCALL_NORM); } diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/sys_sparc.c linux/arch/sparc/kernel/sys_sparc.c --- v2.1.123/linux/arch/sparc/kernel/sys_sparc.c Thu Aug 6 14:06:30 1998 +++ linux/arch/sparc/kernel/sys_sparc.c Sun Oct 4 10:22:42 1998 @@ -1,4 +1,4 @@ -/* $Id: sys_sparc.c,v 1.46 1998/08/03 23:58:01 davem Exp $ +/* $Id: sys_sparc.c,v 1.48 1998/09/07 09:19:34 davem Exp $ * linux/arch/sparc/kernel/sys_sparc.c * * This file contains various random system calls that @@ -206,6 +206,7 @@ } } + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); retval = do_mmap(file, addr, len, prot, flags, off); out_putf: @@ -297,6 +298,11 @@ /* XXX: Don't preclude handling different sized sigset_t's. */ if (sigsetsize != sizeof(sigset_t)) return -EINVAL; + + /* All tasks which use RT signals (effectively) use + * new style signals. + */ + current->tss.new_signal = 1; if (act) { new_ka.ka_restorer = restorer; diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/sys_sunos.c linux/arch/sparc/kernel/sys_sunos.c --- v2.1.123/linux/arch/sparc/kernel/sys_sunos.c Thu Aug 6 14:06:30 1998 +++ linux/arch/sparc/kernel/sys_sunos.c Sun Oct 4 10:22:42 1998 @@ -1,4 +1,4 @@ -/* $Id: sys_sunos.c,v 1.91 1998/06/16 04:37:04 davem Exp $ +/* $Id: sys_sunos.c,v 1.92 1998/08/31 03:40:53 davem Exp $ * sys_sunos.c: SunOS specific syscall compatibility support. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -118,6 +118,7 @@ } } + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); retval = do_mmap(file, addr, len, prot, flags, off); if(!ret_type) retval = ((retval < PAGE_OFFSET) ? 0 : retval); diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/systbls.S linux/arch/sparc/kernel/systbls.S --- v2.1.123/linux/arch/sparc/kernel/systbls.S Thu Aug 6 14:06:30 1998 +++ linux/arch/sparc/kernel/systbls.S Sun Oct 4 10:22:42 1998 @@ -1,4 +1,4 @@ -/* $Id: systbls.S,v 1.75 1998/07/28 13:07:48 jj Exp $ +/* $Id: systbls.S,v 1.80 1998/09/21 05:04:59 jj Exp $ * systbls.S: System call entry point tables for OS compatibility. * The native Linux system call table lives here also. * @@ -9,212 +9,156 @@ * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu) */ -#include - .data .align 4 /* First, the Linux native syscall table. */ - .globl C_LABEL(sys_call_table) -C_LABEL(sys_call_table): -/*0*/ .long C_LABEL(sys_setup), C_LABEL(sys_exit), C_LABEL(sys_fork) - .long C_LABEL(sys_read), C_LABEL(sys_write) -/*5*/ .long C_LABEL(sys_open), C_LABEL(sys_close), C_LABEL(sys_wait4) - .long C_LABEL(sys_creat), C_LABEL(sys_link) -/*10*/ .long C_LABEL(sys_unlink), C_LABEL(sunos_execv), C_LABEL(sys_chdir) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_mknod) -/*15*/ .long C_LABEL(sys_chmod), C_LABEL(sys_lchown), C_LABEL(sparc_brk) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_lseek) -/*20*/ .long C_LABEL(sys_getpid), C_LABEL(sys_capget), C_LABEL(sys_capset) - .long C_LABEL(sys_setuid), C_LABEL(sys_getuid) -/*25*/ .long C_LABEL(sys_time), C_LABEL(sys_ptrace), C_LABEL(sys_alarm) - .long C_LABEL(sys_sigaltstack), C_LABEL(sys_pause) -/*30*/ .long C_LABEL(sys_utime), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_access), C_LABEL(sys_nice), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_sync), C_LABEL(sys_kill), C_LABEL(sys_newstat) - .long C_LABEL(sys_sendfile), C_LABEL(sys_newlstat), C_LABEL(sys_dup) - .long C_LABEL(sys_pipe), C_LABEL(sys_times), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_setgid), C_LABEL(sys_getgid) - .long C_LABEL(sys_signal), C_LABEL(sys_geteuid) -/*50*/ .long C_LABEL(sys_getegid), C_LABEL(sys_acct), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_ioctl), C_LABEL(sys_reboot) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_symlink), C_LABEL(sys_readlink) - .long C_LABEL(sys_execve), C_LABEL(sys_umask), C_LABEL(sys_chroot) - .long C_LABEL(sys_newfstat), C_LABEL(sys_nis_syscall), C_LABEL(sys_getpagesize) - .long C_LABEL(sys_msync), C_LABEL(sys_vfork), C_LABEL(sys_pread) - .long C_LABEL(sys_pwrite), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_mmap), C_LABEL(sys_nis_syscall), C_LABEL(sys_munmap) - .long C_LABEL(sys_mprotect), C_LABEL(sys_nis_syscall), C_LABEL(sys_vhangup) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall), C_LABEL(sys_getgroups) - .long C_LABEL(sys_setgroups), C_LABEL(sys_getpgrp), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_setitimer), C_LABEL(sys_nis_syscall), C_LABEL(sys_swapon) - .long C_LABEL(sys_getitimer), C_LABEL(sys_nis_syscall), C_LABEL(sys_sethostname) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_dup2), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_fcntl), C_LABEL(sys_select), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_fsync), C_LABEL(sys_setpriority), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) -/*100*/ .long C_LABEL(sys_getpriority), C_LABEL(sys_rt_sigreturn) - .long C_LABEL(sys_rt_sigaction), C_LABEL(sys_rt_sigprocmask) - .long C_LABEL(sys_rt_sigpending), C_LABEL(sys_rt_sigtimedwait) - .long C_LABEL(sys_rt_sigqueueinfo), C_LABEL(sys_rt_sigsuspend) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_gettimeofday), C_LABEL(sys_getrusage) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_getcwd), C_LABEL(sys_readv) - .long C_LABEL(sys_writev), C_LABEL(sys_settimeofday), C_LABEL(sys_fchown) - .long C_LABEL(sys_fchmod), C_LABEL(sys_nis_syscall), C_LABEL(sys_setreuid) - .long C_LABEL(sys_setregid), C_LABEL(sys_rename), C_LABEL(sys_truncate) - .long C_LABEL(sys_ftruncate), C_LABEL(sys_flock), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_mkdir), C_LABEL(sys_rmdir), C_LABEL(sys_utimes) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall), C_LABEL(sys_getrlimit) - .long C_LABEL(sys_setrlimit), C_LABEL(sys_nis_syscall), C_LABEL(sys_prctl) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) -/*150*/ .long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_poll), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_statfs), C_LABEL(sys_fstatfs) - .long C_LABEL(sys_umount), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_getdomainname), C_LABEL(sys_setdomainname) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_quotactl), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_mount), C_LABEL(sys_ustat), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_getdents), C_LABEL(sys_setsid) - .long C_LABEL(sys_fchdir), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_sigpending), C_LABEL(sys_query_module) - .long C_LABEL(sys_setpgid), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_newuname), C_LABEL(sys_init_module) - .long C_LABEL(sys_personality), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_getppid), C_LABEL(sparc_sigaction), C_LABEL(sys_sgetmask) -/*200*/ .long C_LABEL(sys_ssetmask), C_LABEL(sys_sigsuspend), C_LABEL(sys_newlstat) - .long C_LABEL(sys_uselib), C_LABEL(old_readdir), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_socketcall), C_LABEL(sys_syslog), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_idle), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_waitpid), C_LABEL(sys_swapoff), C_LABEL(sys_sysinfo) - .long C_LABEL(sys_ipc), C_LABEL(sys_sigreturn), C_LABEL(sys_clone) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_adjtimex), C_LABEL(sys_sigprocmask) - .long C_LABEL(sys_create_module), C_LABEL(sys_delete_module) - .long C_LABEL(sys_get_kernel_syms), C_LABEL(sys_getpgid), C_LABEL(sys_bdflush) - .long C_LABEL(sys_sysfs), C_LABEL(sys_nis_syscall), C_LABEL(sys_setfsuid) - .long C_LABEL(sys_setfsgid), C_LABEL(sys_select), C_LABEL(sys_time) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_stime), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_llseek) - /* "We are the Knights of the Forest of Ni!!" */ - .long C_LABEL(sys_mlock) - .long C_LABEL(sys_munlock) - .long C_LABEL(sys_mlockall) -/*240*/ .long C_LABEL(sys_munlockall) - .long C_LABEL(sys_sched_setparam) - .long C_LABEL(sys_sched_getparam) - .long C_LABEL(sys_sched_setscheduler) - .long C_LABEL(sys_sched_getscheduler) -/*245*/ .long C_LABEL(sys_sched_yield) - .long C_LABEL(sys_sched_get_priority_max) - .long C_LABEL(sys_sched_get_priority_min) - .long C_LABEL(sys_sched_rr_get_interval) - .long C_LABEL(sys_nanosleep) -/*250*/ .long C_LABEL(sys_mremap) - .long C_LABEL(sys_sysctl) - .long C_LABEL(sys_getsid) - .long C_LABEL(sys_fdatasync) - .long C_LABEL(sys_nfsservctl) -/*255*/ .long C_LABEL(sys_aplib) - .long C_LABEL(sys_nis_syscall) + .globl sys_call_table +sys_call_table: +/*0*/ .long sys_nis_syscall, sys_exit, sys_fork, sys_read, sys_write +/*5*/ .long sys_open, sys_close, sys_wait4, sys_creat, sys_link +/*10*/ .long sys_unlink, sunos_execv, sys_chdir, sys_chown, sys_mknod +/*15*/ .long sys_chmod, sys_lchown, sparc_brk, sys_nis_syscall, sys_lseek +/*20*/ .long sys_getpid, sys_capget, sys_capset, sys_setuid, sys_getuid +/*25*/ .long sys_time, sys_ptrace, sys_alarm, sys_sigaltstack, sys_pause +/*30*/ .long sys_utime, sys_nis_syscall, sys_nis_syscall, sys_access, sys_nice +/*35*/ .long sys_nis_syscall, sys_sync, sys_kill, sys_newstat, sys_sendfile +/*40*/ .long sys_newlstat, sys_dup, sys_pipe, sys_times, sys_nis_syscall +/*45*/ .long sys_nis_syscall, sys_setgid, sys_getgid, sys_signal, sys_geteuid +/*50*/ .long sys_getegid, sys_acct, sys_nis_syscall, sys_nis_syscall, sys_ioctl +/*55*/ .long sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys_execve +/*60*/ .long sys_umask, sys_chroot, sys_newfstat, sys_nis_syscall, sys_getpagesize +/*65*/ .long sys_msync, sys_vfork, sys_pread, sys_pwrite, sys_nis_syscall +/*70*/ .long sys_nis_syscall, sys_mmap, sys_nis_syscall, sys_munmap, sys_mprotect +/*75*/ .long sys_nis_syscall, sys_vhangup, sys_nis_syscall, sys_nis_syscall, sys_getgroups +/*80*/ .long sys_setgroups, sys_getpgrp, sys_nis_syscall, sys_setitimer, sys_nis_syscall +/*85*/ .long sys_swapon, sys_getitimer, sys_nis_syscall, sys_sethostname, sys_nis_syscall +/*90*/ .long sys_dup2, sys_nis_syscall, sys_fcntl, sys_select, sys_nis_syscall +/*95*/ .long sys_fsync, sys_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall +/*100*/ .long sys_getpriority, sys_rt_sigreturn, sys_rt_sigaction, sys_rt_sigprocmask, sys_rt_sigpending +/*105*/ .long sys_rt_sigtimedwait, sys_rt_sigqueueinfo, sys_rt_sigsuspend, sys_nis_syscall, sys_nis_syscall +/*110*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall +/*115*/ .long sys_nis_syscall, sys_gettimeofday, sys_getrusage, sys_nis_syscall, sys_getcwd +/*120*/ .long sys_readv, sys_writev, sys_settimeofday, sys_fchown, sys_fchmod +/*125*/ .long sys_nis_syscall, sys_setreuid, sys_setregid, sys_rename, sys_truncate +/*130*/ .long sys_ftruncate, sys_flock, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall +/*135*/ .long sys_nis_syscall, sys_mkdir, sys_rmdir, sys_utimes, sys_nis_syscall +/*140*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getrlimit +/*145*/ .long sys_setrlimit, sys_nis_syscall, sys_prctl, sys_pciconfig_read, sys_pciconfig_write +/*150*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_nis_syscall +/*155*/ .long sys_nis_syscall, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_umount +/*160*/ .long sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_nis_syscall +/*165*/ .long sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall +/*170*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents +/*175*/ .long sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall +/*180*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_sigpending, sys_query_module +/*185*/ .long sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_newuname +/*190*/ .long sys_init_module, sys_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall +/*195*/ .long sys_nis_syscall, sys_nis_syscall, sys_getppid, sparc_sigaction, sys_sgetmask +/*200*/ .long sys_ssetmask, sys_sigsuspend, sys_newlstat, sys_uselib, old_readdir +/*205*/ .long sys_nis_syscall, sys_socketcall, sys_syslog, sys_nis_syscall, sys_nis_syscall +/*210*/ .long sys_idle, sys_nis_syscall, sys_waitpid, sys_swapoff, sys_sysinfo +/*215*/ .long sys_ipc, sys_sigreturn, sys_clone, sys_nis_syscall, sys_adjtimex +/*220*/ .long sys_sigprocmask, sys_create_module, sys_delete_module, sys_get_kernel_syms, sys_getpgid +/*225*/ .long sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid +/*230*/ .long sys_select, sys_time, sys_nis_syscall, sys_stime, sys_nis_syscall + /* "We are the Knights of the Forest of Ni!!" */ +/*235*/ .long sys_nis_syscall, sys_llseek, sys_mlock, sys_munlock, sys_mlockall +/*240*/ .long sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler +/*245*/ .long sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep +/*250*/ .long sys_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl +/*255*/ .long sys_aplib, sys_nis_syscall /* Now the SunOS syscall table. */ .align 4 - .globl C_LABEL(sunos_sys_table) -C_LABEL(sunos_sys_table): -/*0*/ .long C_LABEL(sunos_indir), C_LABEL(sys_exit), C_LABEL(sys_fork) - .long C_LABEL(sunos_read), C_LABEL(sunos_write), C_LABEL(sunos_open) - .long C_LABEL(sys_close), C_LABEL(sunos_wait4), C_LABEL(sys_creat) - .long C_LABEL(sys_link), C_LABEL(sys_unlink), C_LABEL(sunos_execv) - .long C_LABEL(sys_chdir), C_LABEL(sunos_nosys), C_LABEL(sys_mknod) - .long C_LABEL(sys_chmod), C_LABEL(sys_lchown), C_LABEL(sunos_brk) - .long C_LABEL(sunos_nosys), C_LABEL(sys_lseek), C_LABEL(sunos_getpid) - .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) - .long C_LABEL(sunos_getuid), C_LABEL(sunos_nosys), C_LABEL(sys_ptrace) - .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) - .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) - .long C_LABEL(sys_access), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) - .long C_LABEL(sys_sync), C_LABEL(sys_kill), C_LABEL(sys_newstat) - .long C_LABEL(sunos_nosys), C_LABEL(sys_newlstat), C_LABEL(sys_dup) - .long C_LABEL(sys_pipe), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) - .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_getgid) - .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) -/*50*/ .long C_LABEL(sunos_nosys), C_LABEL(sys_acct), C_LABEL(sunos_nosys) - .long C_LABEL(sunos_mctl), C_LABEL(sunos_ioctl), C_LABEL(sys_reboot) - .long C_LABEL(sunos_nosys), C_LABEL(sys_symlink), C_LABEL(sys_readlink) - .long C_LABEL(sys_execve), C_LABEL(sys_umask), C_LABEL(sys_chroot) - .long C_LABEL(sys_newfstat), C_LABEL(sunos_nosys), C_LABEL(sys_getpagesize) - .long C_LABEL(sys_msync), C_LABEL(sys_vfork), C_LABEL(sunos_nosys) - .long C_LABEL(sunos_nosys), C_LABEL(sunos_sbrk), C_LABEL(sunos_sstk) - .long C_LABEL(sunos_mmap), C_LABEL(sunos_vadvise), C_LABEL(sys_munmap) - .long C_LABEL(sys_mprotect), C_LABEL(sunos_madvise), C_LABEL(sys_vhangup) - .long C_LABEL(sunos_nosys), C_LABEL(sunos_mincore), C_LABEL(sys_getgroups) - .long C_LABEL(sys_setgroups), C_LABEL(sys_getpgrp), C_LABEL(sunos_setpgrp) - .long C_LABEL(sys_setitimer), C_LABEL(sunos_nosys), C_LABEL(sys_swapon) - .long C_LABEL(sys_getitimer), C_LABEL(sys_gethostname), C_LABEL(sys_sethostname) - .long C_LABEL(sunos_getdtablesize), C_LABEL(sys_dup2), C_LABEL(sunos_nop) - .long C_LABEL(sys_fcntl), C_LABEL(sunos_select), C_LABEL(sunos_nop) - .long C_LABEL(sys_fsync), C_LABEL(sys_setpriority), C_LABEL(sunos_socket) - .long C_LABEL(sys_connect), C_LABEL(sunos_accept) -/*100*/ .long C_LABEL(sys_getpriority), C_LABEL(sunos_send), C_LABEL(sunos_recv) - .long C_LABEL(sunos_nosys), C_LABEL(sys_bind), C_LABEL(sunos_setsockopt) - .long C_LABEL(sys_listen), C_LABEL(sunos_nosys), C_LABEL(sunos_sigaction) - .long C_LABEL(sunos_sigblock), C_LABEL(sunos_sigsetmask), C_LABEL(sys_sigpause) - .long C_LABEL(sys_sigstack), C_LABEL(sys_recvmsg), C_LABEL(sys_sendmsg) - .long C_LABEL(sunos_nosys), C_LABEL(sys_gettimeofday), C_LABEL(sys_getrusage) - .long C_LABEL(sunos_getsockopt), C_LABEL(sunos_nosys), C_LABEL(sunos_readv) - .long C_LABEL(sunos_writev), C_LABEL(sys_settimeofday), C_LABEL(sys_fchown) - .long C_LABEL(sys_fchmod), C_LABEL(sys_recvfrom), C_LABEL(sys_setreuid) - .long C_LABEL(sys_setregid), C_LABEL(sys_rename), C_LABEL(sys_truncate) - .long C_LABEL(sys_ftruncate), C_LABEL(sys_flock), C_LABEL(sunos_nosys) - .long C_LABEL(sys_sendto), C_LABEL(sys_shutdown), C_LABEL(sys_socketpair) - .long C_LABEL(sys_mkdir), C_LABEL(sys_rmdir), C_LABEL(sys_utimes) - .long C_LABEL(sys_sigreturn), C_LABEL(sunos_nosys), C_LABEL(sys_getpeername) - .long C_LABEL(sunos_gethostid), C_LABEL(sunos_nosys), C_LABEL(sys_getrlimit) - .long C_LABEL(sys_setrlimit), C_LABEL(sunos_killpg), C_LABEL(sunos_nosys) - .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) -/*150*/ .long C_LABEL(sys_getsockname), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) - .long C_LABEL(sys_poll), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) - .long C_LABEL(sunos_getdirentries), C_LABEL(sys_statfs), C_LABEL(sys_fstatfs) - .long C_LABEL(sys_umount), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) - .long C_LABEL(sys_getdomainname), C_LABEL(sys_setdomainname) - .long C_LABEL(sunos_nosys), C_LABEL(sys_quotactl), C_LABEL(sunos_nosys) - .long C_LABEL(sunos_mount), C_LABEL(sys_ustat), C_LABEL(sunos_semsys) - .long C_LABEL(sunos_msgsys), C_LABEL(sunos_shmsys), C_LABEL(sunos_audit) - .long C_LABEL(sunos_nosys), C_LABEL(sunos_getdents), C_LABEL(sys_setsid) - .long C_LABEL(sys_fchdir), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) - .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) - .long C_LABEL(sunos_nosys), C_LABEL(sys_sigpending), C_LABEL(sunos_nosys) - .long C_LABEL(sys_setpgid), C_LABEL(sunos_pathconf), C_LABEL(sunos_fpathconf) - .long C_LABEL(sunos_sysconf), C_LABEL(sunos_uname), C_LABEL(sunos_nosys) - .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) - .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) - .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) -/*200*/ .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) - .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) - .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) - .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) - .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) - .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) - .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) - .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) - .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) - .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) - .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) - .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) - .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) - .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) - .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) - .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) - .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) -/*250*/ .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) - .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sys_aplib) + .globl sunos_sys_table +sunos_sys_table: +/*0*/ .long sunos_indir, sys_exit, sys_fork + .long sunos_read, sunos_write, sunos_open + .long sys_close, sunos_wait4, sys_creat + .long sys_link, sys_unlink, sunos_execv + .long sys_chdir, sunos_nosys, sys_mknod + .long sys_chmod, sys_lchown, sunos_brk + .long sunos_nosys, sys_lseek, sunos_getpid + .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_getuid, sunos_nosys, sys_ptrace + .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_nosys, sunos_nosys, sunos_nosys + .long sys_access, sunos_nosys, sunos_nosys + .long sys_sync, sys_kill, sys_newstat + .long sunos_nosys, sys_newlstat, sys_dup + .long sys_pipe, sunos_nosys, sunos_nosys + .long sunos_nosys, sunos_nosys, sunos_getgid + .long sunos_nosys, sunos_nosys +/*50*/ .long sunos_nosys, sys_acct, sunos_nosys + .long sunos_mctl, sunos_ioctl, sys_reboot + .long sunos_nosys, sys_symlink, sys_readlink + .long sys_execve, sys_umask, sys_chroot + .long sys_newfstat, sunos_nosys, sys_getpagesize + .long sys_msync, sys_vfork, sunos_nosys + .long sunos_nosys, sunos_sbrk, sunos_sstk + .long sunos_mmap, sunos_vadvise, sys_munmap + .long sys_mprotect, sunos_madvise, sys_vhangup + .long sunos_nosys, sunos_mincore, sys_getgroups + .long sys_setgroups, sys_getpgrp, sunos_setpgrp + .long sys_setitimer, sunos_nosys, sys_swapon + .long sys_getitimer, sys_gethostname, sys_sethostname + .long sunos_getdtablesize, sys_dup2, sunos_nop + .long sys_fcntl, sunos_select, sunos_nop + .long sys_fsync, sys_setpriority, sunos_socket + .long sys_connect, sunos_accept +/*100*/ .long sys_getpriority, sunos_send, sunos_recv + .long sunos_nosys, sys_bind, sunos_setsockopt + .long sys_listen, sunos_nosys, sunos_sigaction + .long sunos_sigblock, sunos_sigsetmask, sys_sigpause + .long sys_sigstack, sys_recvmsg, sys_sendmsg + .long sunos_nosys, sys_gettimeofday, sys_getrusage + .long sunos_getsockopt, sunos_nosys, sunos_readv + .long sunos_writev, sys_settimeofday, sys_fchown + .long sys_fchmod, sys_recvfrom, sys_setreuid + .long sys_setregid, sys_rename, sys_truncate + .long sys_ftruncate, sys_flock, sunos_nosys + .long sys_sendto, sys_shutdown, sys_socketpair + .long sys_mkdir, sys_rmdir, sys_utimes + .long sys_sigreturn, sunos_nosys, sys_getpeername + .long sunos_gethostid, sunos_nosys, sys_getrlimit + .long sys_setrlimit, sunos_killpg, sunos_nosys + .long sunos_nosys, sunos_nosys +/*150*/ .long sys_getsockname, sunos_nosys, sunos_nosys + .long sys_poll, sunos_nosys, sunos_nosys + .long sunos_getdirentries, sys_statfs, sys_fstatfs + .long sys_umount, sunos_nosys, sunos_nosys + .long sys_getdomainname, sys_setdomainname + .long sunos_nosys, sys_quotactl, sunos_nosys + .long sunos_mount, sys_ustat, sunos_semsys + .long sunos_msgsys, sunos_shmsys, sunos_audit + .long sunos_nosys, sunos_getdents, sys_setsid + .long sys_fchdir, sunos_nosys, sunos_nosys + .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_nosys, sys_sigpending, sunos_nosys + .long sys_setpgid, sunos_pathconf, sunos_fpathconf + .long sunos_sysconf, sunos_uname, sunos_nosys + .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_nosys, sunos_nosys, sunos_nosys +/*200*/ .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_nosys, sunos_nosys +/*250*/ .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_nosys, sunos_nosys, sys_aplib diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/time.c linux/arch/sparc/kernel/time.c --- v2.1.123/linux/arch/sparc/kernel/time.c Thu Aug 6 14:06:30 1998 +++ linux/arch/sparc/kernel/time.c Sun Oct 4 10:22:42 1998 @@ -1,4 +1,4 @@ -/* $Id: time.c,v 1.33 1998/07/28 16:52:48 jj Exp $ +/* $Id: time.c,v 1.39 1998/09/29 09:46:15 davem Exp $ * linux/arch/sparc/kernel/time.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -7,6 +7,9 @@ * Chris Davis (cdavis@cois.on.ca) 03/27/1998 * Added support for the intersil on the sun4/4200 * + * Gleb Raiko (rajko@mech.math.msu.su) 08/18/1998 + * Support for MicroSPARC-IIep, PCI CPU. + * * This file handles the Sparc specific time handling details. */ #include @@ -19,6 +22,7 @@ #include #include #include +#include #include #include @@ -36,6 +40,7 @@ struct mostek48t02 *mstk48t02_regs = 0; struct mostek48t08 *mstk48t08_regs = 0; static int set_rtc_mmss(unsigned long); +static void sbus_do_settimeofday(struct timeval *tv); #ifdef CONFIG_SUN4 struct intersil *intersil_clock; @@ -71,10 +76,13 @@ static long last_rtc_update=0; #ifdef CONFIG_SUN4 - int temp; - intersil_read_intr(intersil_clock, temp); - /* re-enable the irq */ - enable_pil_irq(10); + if((idprom->id_machtype == (SM_SUN4 | SM_4_260)) || + (idprom->id_machtype == (SM_SUN4 | SM_4_110))) { + int temp; + intersil_read_intr(intersil_clock, temp); + /* re-enable the irq */ + enable_pil_irq(10); + } #endif clear_clock_irq(); @@ -83,11 +91,12 @@ /* Determine when to update the Mostek clock. */ if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 && xtime.tv_usec > 500000 - (tick >> 1) && - xtime.tv_usec < 500000 + (tick >> 1)) + xtime.tv_usec < 500000 + (tick >> 1)) { if (set_rtc_mmss(xtime.tv_sec) == 0) last_rtc_update = xtime.tv_sec; else last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ + } } /* Converts Gregorian date to seconds since 1970-01-01 00:00:00. @@ -316,7 +325,7 @@ kick_start_clock(); } -__initfunc(void time_init(void)) +__initfunc(void sbus_time_init(void)) { unsigned int year, mon, day, hour, min, sec; struct mostek48t02 *mregs; @@ -327,6 +336,8 @@ #endif do_get_fast_time = do_gettimeofday; + BTFIXUPSET_CALL(bus_do_settimeofday, sbus_do_settimeofday, BTFIXUPCALL_NORM); + btfixup(); #if CONFIG_AP1000 init_timers(timer_interrupt); @@ -344,7 +355,6 @@ #ifdef CONFIG_SUN4 if(idprom->id_machtype == (SM_SUN4 | SM_4_330)) { #endif - mregs = mstk48t02_regs; if(!mregs) { prom_printf("Something wrong, clock regs not mapped yet.\n"); @@ -397,7 +407,19 @@ __sti(); } -static __inline__ unsigned long do_gettimeoffset(void) +__initfunc(void time_init(void)) +{ +#ifdef CONFIG_PCI + extern void pci_time_init(void); + if (pci_present()) { + pci_time_init(); + return; + } +#endif + sbus_time_init(); +} + +extern __inline__ unsigned long do_gettimeoffset(void) { unsigned long offset = 0; unsigned int count; @@ -458,6 +480,11 @@ } void do_settimeofday(struct timeval *tv) +{ + bus_do_settimeofday(tv); +} + +static void sbus_do_settimeofday(struct timeval *tv) { cli(); #if !CONFIG_AP1000 diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/traps.c linux/arch/sparc/kernel/traps.c --- v2.1.123/linux/arch/sparc/kernel/traps.c Thu Apr 23 20:21:30 1998 +++ linux/arch/sparc/kernel/traps.c Sun Oct 4 10:22:42 1998 @@ -1,4 +1,4 @@ -/* $Id: traps.c,v 1.56 1998/04/06 16:08:32 jj Exp $ +/* $Id: traps.c,v 1.57 1998/09/17 11:04:51 jj Exp $ * arch/sparc/kernel/traps.c * * Copyright 1995 David S. Miller (davem@caip.rutgers.edu) @@ -242,8 +242,8 @@ void do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc, unsigned long psr) { - static calls = 0; - int ret; + static int calls = 0; + int ret = 0; #ifndef __SMP__ struct task_struct *fpt = last_task_used_math; #else diff -u --recursive --new-file v2.1.123/linux/arch/sparc/lib/copy_user.S linux/arch/sparc/lib/copy_user.S --- v2.1.123/linux/arch/sparc/lib/copy_user.S Fri Dec 13 01:37:31 1996 +++ linux/arch/sparc/lib/copy_user.S Sun Oct 4 10:22:42 1998 @@ -3,7 +3,7 @@ * Copyright(C) 1995 Linus Torvalds * Copyright(C) 1996 David S. Miller * Copyright(C) 1996 Eddie C. Dost - * Copyright(C) 1996 Jakub Jelinek + * Copyright(C) 1996,1998 Jakub Jelinek * * derived from: * e-mail between David and Eddie. @@ -13,13 +13,14 @@ #include #include +#include #define EX(x,y,a,b,z) \ 98: x,y; \ .section .fixup,z##alloc,z##execinstr; \ .align 4; \ -99: retl; \ - a, b, %o0; \ +99: ba fixupretl; \ + a, b, %g3; \ .section __ex_table,z##alloc; \ .align 4; \ .word 98b, 99b; \ @@ -31,8 +32,8 @@ .section .fixup,z##alloc,z##execinstr; \ .align 4; \ 99: c, d, e; \ - retl; \ - a, b, %o0; \ + ba fixupretl; \ + a, b, %g3; \ .section __ex_table,z##alloc; \ .align 4; \ .word 98b, 99b; \ @@ -340,7 +341,7 @@ andcc %o2, 4, %g0 EXO2(ld [%o1 + 0x00], %g2,#) - EX(ld [%o1 + 0x04], %g3, sub %o2, 4,#) + EXO2(ld [%o1 + 0x04], %g3,#) add %o1, 8, %o1 EXO2(st %g2, [%o0 + 0x00],#) EX(st %g3, [%o0 + 0x04], sub %o2, 4,#) @@ -352,16 +353,32 @@ .section .fixup,#alloc,#execinstr .align 4 97: - retl - mov %o2, %o0 + mov %o2, %g3 +fixupretl: + GET_PAGE_OFFSET(g1) + cmp %o0, %g1 + blu 1f + cmp %o1, %g1 + bgeu 1f + nop + save %sp, -64, %sp + mov %i0, %o0 + call __bzero + mov %g3, %o1 + restore +1: retl + mov %g3, %o0 + /* exception routine sets %g2 to (broken_insn - first_insn)>>2 */ 50: /* This magic counts how many bytes are left when crash in MOVE_BIGCHUNK * happens. This is derived from the amount ldd reads, st stores, etc. * x = g2 % 12; - * o0 = g1 + g7 - ((g2 / 12) * 32 + (x < 4) ? x * 8 : (x - 4) * 4) + * g3 = g1 + g7 - ((g2 / 12) * 32 + (x < 4) ? 0 : (x - 4) * 4); + * o0 += (g2 / 12) * 32; */ cmp %g2, 12 + add %o0, %g7, %o0 bcs 1f cmp %g2, 24 bcs 2f @@ -370,84 +387,97 @@ nop sub %g2, 12, %g2 sub %g7, 32, %g7 -3: - sub %g2, 12, %g2 +3: sub %g2, 12, %g2 sub %g7, 32, %g7 -2: - sub %g2, 12, %g2 +2: sub %g2, 12, %g2 sub %g7, 32, %g7 -1: - cmp %g2, 4 - bcs,a 1f - sll %g2, 3, %g2 +1: cmp %g2, 4 + bcs,a 60f + clr %g2 sub %g2, 4, %g2 sll %g2, 2, %g2 -1: - and %g1, 0x7f, %o0 - add %o0, %g7, %o0 - retl - sub %o0, %g2, %o0 +60: and %g1, 0x7f, %g3 + sub %o0, %g7, %o0 + add %g3, %g7, %g3 + ba fixupretl + sub %g3, %g2, %g3 51: /* i = 41 - g2; j = i % 6; - * o0 = (g1 & 15) + (i / 6) * 16 + (j < 4) ? (j + 1) * 4 : (j - 3) * 8; + * g3 = (g1 & 15) + (i / 6) * 16 + (j < 4) ? (j + 1) * 4 : 16; + * o0 -= (i / 6) * 16 + 16; */ neg %g2 and %g1, 0xf, %g1 add %g2, 41, %g2 -1: - cmp %g2, 6 + add %o0, %g1, %o0 +1: cmp %g2, 6 bcs,a 2f cmp %g2, 4 add %g1, 16, %g1 b 1b sub %g2, 6, %g2 -2: - bcs,a 3f - inc %g2 - sub %g2, 3, %g2 - b 2f - sll %g2, 3, %g2 -3: +2: bcc,a 2f + mov 16, %g2 + inc %g2 sll %g2, 2, %g2 -2: - retl - add %g1, %g2, %o0 +2: add %g1, %g2, %g3 + ba fixupretl + sub %o0, %g3, %o0 52: -/* o0 = g1 + g7 - (g2 / 8) * 32 + (x & 3) * 8 */ - and %g2, 0xfffffff8, %g4 +/* g3 = g1 + g7 - (g2 / 8) * 32 + (g2 & 4) ? (g2 & 3) * 8 : 0; + o0 += (g2 / 8) * 32 */ + andn %g2, 7, %g4 + add %o0, %g7, %o0 + andcc %g2, 4, %g0 and %g2, 3, %g2 sll %g4, 2, %g4 sll %g2, 3, %g2 - add %g2, %g4, %g2 - b,a 1b + bne 60b + sub %g7, %g4, %g7 + ba 60b + clr %g2 53: -/* o0 = o3 + (o2 & 15) - (g2 & 8) - (g2 & 3) * 2 */ +/* g3 = o3 + (o2 & 15) - (g2 & 8) - (g2 & 4) ? (g2 & 3) * 2 : 0; + o0 += (g2 & 8) */ and %g2, 3, %g4 - and %g2, 0xfffffff8, %g2 + andcc %g2, 4, %g0 + and %g2, 8, %g2 sll %g4, 1, %g4 + be 1f + add %o0, %g2, %o0 add %g2, %g4, %g2 - and %o2, 0xf, %o0 - add %o0, %o3, %o0 - retl - sub %o0, %g2, %o0 +1: and %o2, 0xf, %g3 + add %g3, %o3, %g3 + ba fixupretl + sub %g3, %g2, %g3 54: -/* o0 = o3 + (o2 & 15) - (g2 / 4) * 2 - (g2 & 1) */ +/* g3 = o3 + (o2 & 15) - (g2 / 4) * 2 - (g2 & 2) ? (g2 & 1) : 0; + o0 += (g2 / 4) * 2 */ srl %g2, 2, %o4 - and %g2, 1, %o1 - sll %o4, 1, %o4 + and %g2, 1, %o5 + srl %g2, 1, %g2 + add %o4, %o4, %o4 + and %o5, %g2, %o5 and %o2, 0xf, %o2 - sub %o3, %o1, %o3 + add %o0, %o4, %o0 + sub %o3, %o5, %o3 sub %o2, %o4, %o2 - retl - add %o2, %o3, %o0 + ba fixupretl + add %o2, %o3, %g3 55: -/* o0 = (o2 & 1) + (27 - g2)/4 * 2 + ((27 - g2) & 1) */ +/* i = 27 - g2; + g3 = (o2 & 1) + i / 4 * 2 + !(i & 3); + o0 -= i / 4 * 2 + 1 */ neg %g2 and %o2, 1, %o2 add %g2, 27, %g2 - srl %g2, 2, %o1 - and %g2, 1, %g2 - sll %o1, 1, %o1 - add %o2, %g2, %o0 - retl - add %o0, %o1, %o0 + srl %g2, 2, %o5 + andcc %g2, 3, %g0 + mov 1, %g2 + add %o5, %o5, %o5 + be,a 1f + clr %g2 +1: add %g2, %o5, %g3 + sub %o0, %g3, %o0 + ba fixupretl + add %g3, %o2, %g3 diff -u --recursive --new-file v2.1.123/linux/arch/sparc/lib/debuglocks.c linux/arch/sparc/lib/debuglocks.c --- v2.1.123/linux/arch/sparc/lib/debuglocks.c Thu May 15 16:48:01 1997 +++ linux/arch/sparc/lib/debuglocks.c Sun Oct 4 10:22:42 1998 @@ -1,7 +1,8 @@ -/* $Id: debuglocks.c,v 1.1 1997/05/08 18:13:34 davem Exp $ +/* $Id: debuglocks.c,v 1.3 1998/09/29 09:46:22 davem Exp $ * debuglocks.c: Debugging versions of SMP locking primitives. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1998 Anton Blanchard (anton@progsoc.uts.edu.au) */ #include @@ -22,75 +23,56 @@ * number of the owner in the lowest two bits. */ -#undef INIT_STUCK -#define INIT_STUCK 100000000 +#define STORE_CALLER(A) __asm__ __volatile__("mov %%i7, %0" : "=r" (A)); -#undef STUCK -#define STUCK \ -if(!--stuck) { printk("spin_lock(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3); stuck = INIT_STUCK; } - -void _spin_lock(spinlock_t *lock) +static inline void show(char *str, spinlock_t *lock, unsigned long caller) { - unsigned long caller; - unsigned long val; int cpu = smp_processor_id(); - int stuck = INIT_STUCK; - __asm__ __volatile__("mov %%i7, %0" : "=r" (caller)); -again: - __asm__ __volatile__("ldstub [%1], %0" : "=r" (val) : "r" (&(lock->lock))); - if(val) { - while(lock->lock) { - STUCK; - barrier(); - } - goto again; - } - lock->owner_pc = (cpu & 3) | (caller & ~3); + printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n",str, + lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3); } -int _spin_trylock(spinlock_t *lock) +static inline void show_read(char *str, rwlock_t *lock, unsigned long caller) { - unsigned long val; - unsigned long caller; int cpu = smp_processor_id(); - __asm__ __volatile__("mov %%i7, %0" : "=r" (caller)); - __asm__ __volatile__("ldstub [%1], %0" : "=r" (val) : "r" (&(lock->lock))); - if(!val) { - /* We got it, record our identity for debugging. */ - lock->owner_pc = (cpu & 3) | (caller & ~3); - } - return val == 0; + printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n",str, + lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3); } -void _spin_unlock(spinlock_t *lock) +static inline void show_write(char *str, rwlock_t *lock, unsigned long caller) { - lock->owner_pc = 0; - __asm__ __volatile__("stb %%g0, [%0]" : : "r" (&(lock->lock)) : "memory"); + int cpu = smp_processor_id(); + + printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx) reader[0]=%08lx reader[1]=%08lx reader[2]=%08lx reader[3]=%08lx\n", + str, lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3, + lock->reader_pc[0], + lock->reader_pc[1], + lock->reader_pc[2], + lock->reader_pc[3]); } #undef INIT_STUCK #define INIT_STUCK 100000000 -#undef STUCK -#define STUCK \ -if(!--stuck) { printk("spin_lock_irq(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3); stuck = INIT_STUCK; } - -void _spin_lock_irq(spinlock_t *lock) +void _do_spin_lock(spinlock_t *lock, char *str) { unsigned long caller; unsigned long val; int cpu = smp_processor_id(); int stuck = INIT_STUCK; - __cli(); - __asm__ __volatile__("mov %%i7, %0" : "=r" (caller)); + STORE_CALLER(caller); + again: __asm__ __volatile__("ldstub [%1], %0" : "=r" (val) : "r" (&(lock->lock))); if(val) { while(lock->lock) { - STUCK; + if (!--stuck) { + show(str, lock, caller); + stuck = INIT_STUCK; + } barrier(); } goto again; @@ -98,69 +80,49 @@ lock->owner_pc = (cpu & 3) | (caller & ~3); } -void _spin_unlock_irq(spinlock_t *lock) -{ - lock->owner_pc = 0; - __asm__ __volatile__("stb %%g0, [%0]" : : "r" (&(lock->lock)) : "memory"); - __sti(); -} - -#undef INIT_STUCK -#define INIT_STUCK 100000000 - -#undef STUCK -#define STUCK \ -if(!--stuck) { printk("spin_lock_irq(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3); stuck = INIT_STUCK; } - -/* Caller macro does __save_and_cli(flags) for us. */ -void _spin_lock_irqsave(spinlock_t *lock) +int _spin_trylock(spinlock_t *lock) { - unsigned long caller; unsigned long val; + unsigned long caller; int cpu = smp_processor_id(); - int stuck = INIT_STUCK; - __asm__ __volatile__("mov %%i7, %0" : "=r" (caller)); -again: + STORE_CALLER(caller); + __asm__ __volatile__("ldstub [%1], %0" : "=r" (val) : "r" (&(lock->lock))); - if(val) { - while(lock->lock) { - STUCK; - barrier(); - } - goto again; + if(!val) { + /* We got it, record our identity for debugging. */ + lock->owner_pc = (cpu & 3) | (caller & ~3); } - lock->owner_pc = (cpu & 3) | (caller & ~3); + return val == 0; } -void _spin_unlock_irqrestore(spinlock_t *lock) +void _do_spin_unlock(spinlock_t *lock) { lock->owner_pc = 0; - __asm__ __volatile__("stb %%g0, [%0]" : : "r" (&(lock->lock)) : "memory"); + barrier(); + lock->lock = 0; } #undef INIT_STUCK #define INIT_STUCK 100000000 -#undef STUCK -#define STUCK \ -if(!--stuck) { printk("read_lock(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; } - -void _read_lock(rwlock_t *rw) +void _do_read_lock(rwlock_t *rw, char *str) { - unsigned long flags; unsigned long caller; unsigned long val; int cpu = smp_processor_id(); int stuck = INIT_STUCK; - __asm__ __volatile__("mov %%i7, %0" : "=r" (caller)); - __save_and_cli(flags); + STORE_CALLER(caller); + wlock_again: __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock))); if(val) { while(rw->lock & 0xff) { - STUCK; + if (!--stuck) { + show(str, (spinlock_t *)rw, caller); + stuck = INIT_STUCK; + } barrier(); } goto wlock_again; @@ -169,291 +131,85 @@ __asm__ __volatile__("ldstub [%1 + 2], %0" : "=r" (val) : "r" (&(rw->lock))); if(val) { while(rw->lock & 0xff00) { - STUCK; + if (!--stuck) { + show_read(str, rw, caller); + stuck = INIT_STUCK; + } barrier(); } goto clock_again; } (*((unsigned short *)&rw->lock))++; + rw->reader_pc[cpu] = caller; barrier(); (*(((unsigned short *)&rw->lock)+1)) = 0; - __restore_flags(flags); -} - -#undef INIT_STUCK -#define INIT_STUCK 100000000 - -#undef STUCK -#define STUCK \ -if(!--stuck) { printk("read_unlock(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; } - -void _read_unlock(rwlock_t *rw) -{ - unsigned long flags, val, caller; - int cpu = smp_processor_id(); - int stuck = INIT_STUCK; - - __asm__ __volatile__("mov %%i7, %0" : "=r" (caller)); - __save_and_cli(flags); -clock_again: - __asm__ __volatile__("ldstub [%1 + 2], %0" : "=r" (val) : "r" (&(rw->lock))); - if(val) { - while(rw->lock & 0xff00) { - STUCK; - barrier(); - } - goto clock_again; - } - (*((unsigned short *)&rw->lock))--; - barrier(); - (*(((unsigned char *)&rw->lock)+2))=0; - __restore_flags(flags); -} - -#undef INIT_STUCK -#define INIT_STUCK 100000000 - -#undef STUCK -#define STUCK \ -if(!--stuck) { printk("write_lock(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; } - -void _write_lock(rwlock_t *rw) -{ - unsigned long flags, val, caller; - int cpu = smp_processor_id(); - int stuck = INIT_STUCK; - - __asm__ __volatile__("mov %%i7, %0" : "=r" (caller)); - __save_and_cli(flags); -wlock_again: - __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock))); - if(val) { - while(rw->lock & 0xff) { - STUCK; - barrier(); - } - goto wlock_again; - } - rw->owner_pc = (cpu & 3) | (caller & ~3); - while(rw->lock & ~0xff) { - STUCK; - barrier(); - } -} - -void _write_unlock(rwlock_t *rw) -{ - rw->owner_pc = 0; - barrier(); - rw->lock = 0; } #undef INIT_STUCK #define INIT_STUCK 100000000 -#undef STUCK -#define STUCK \ -if(!--stuck) { printk("read_lock_irq(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; } - -void _read_lock_irq(rwlock_t *rw) +void _do_read_unlock(rwlock_t *rw, char *str) { unsigned long caller; unsigned long val; int cpu = smp_processor_id(); int stuck = INIT_STUCK; - __asm__ __volatile__("mov %%i7, %0" : "=r" (caller)); - __cli(); -wlock_again: - __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock))); - if(val) { - while(rw->lock & 0xff) { - STUCK; - barrier(); - } - goto wlock_again; - } -clock_again: - __asm__ __volatile__("ldstub [%1 + 2], %0" : "=r" (val) : "r" (&(rw->lock))); - if(val) { - while(rw->lock & 0xff00) { - STUCK; - barrier(); - } - goto clock_again; - } - (*((unsigned short *)&rw->lock))++; - barrier(); - (*(((unsigned short *)&rw->lock)+1)) = 0; -} - -#undef INIT_STUCK -#define INIT_STUCK 100000000 - -#undef STUCK -#define STUCK \ -if(!--stuck) { printk("read_unlock_irq(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; } - -void _read_unlock_irq(rwlock_t *rw) -{ - unsigned long val, caller; - int stuck = INIT_STUCK; - int cpu = smp_processor_id(); + STORE_CALLER(caller); - __asm__ __volatile__("mov %%i7, %0" : "=r" (caller)); clock_again: __asm__ __volatile__("ldstub [%1 + 2], %0" : "=r" (val) : "r" (&(rw->lock))); if(val) { while(rw->lock & 0xff00) { - STUCK; + if (!--stuck) { + show_read(str, rw, caller); + stuck = INIT_STUCK; + } barrier(); } goto clock_again; } (*((unsigned short *)&rw->lock))--; + rw->reader_pc[cpu] = 0; barrier(); (*(((unsigned char *)&rw->lock)+2))=0; - __sti(); -} - -#undef INIT_STUCK -#define INIT_STUCK 100000000 - -#undef STUCK -#define STUCK \ -if(!--stuck) { printk("write_lock_irq(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; } - -void _write_lock_irq(rwlock_t *rw) -{ - unsigned long val, caller; - int cpu = smp_processor_id(); - int stuck = INIT_STUCK; - - __asm__ __volatile__("mov %%i7, %0" : "=r" (caller)); - __cli(); -wlock_again: - __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock))); - if(val) { - while(rw->lock & 0xff) { - STUCK; - barrier(); - } - goto wlock_again; - } - rw->owner_pc = (cpu & 3) | (caller & ~3); - while(rw->lock & ~0xff) { - STUCK; - barrier(); - } -} - -void _write_unlock_irq(rwlock_t *rw) -{ - rw->owner_pc = 0; - barrier(); - rw->lock = 0; - __sti(); } #undef INIT_STUCK #define INIT_STUCK 100000000 -#undef STUCK -#define STUCK \ -if(!--stuck) { printk("read_lock_irqsave(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; } - -/* Caller does __save_and_cli(flags) for us. */ -void _read_lock_irqsave(rwlock_t *rw) +void _do_write_lock(rwlock_t *rw, char *str) { unsigned long caller; unsigned long val; int cpu = smp_processor_id(); int stuck = INIT_STUCK; - __asm__ __volatile__("mov %%i7, %0" : "=r" (caller)); -wlock_again: - __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock))); - if(val) { - while(rw->lock & 0xff) { - STUCK; - barrier(); - } - goto wlock_again; - } -clock_again: - __asm__ __volatile__("ldstub [%1 + 2], %0" : "=r" (val) : "r" (&(rw->lock))); - if(val) { - while(rw->lock & 0xff00) { - STUCK; - barrier(); - } - goto clock_again; - } - (*((unsigned short *)&rw->lock))++; - barrier(); - (*(((unsigned short *)&rw->lock)+1)) = 0; -} - -#undef INIT_STUCK -#define INIT_STUCK 100000000 - -#undef STUCK -#define STUCK \ -if(!--stuck) { printk("read_unlock_irqrestore(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; } - -void _read_unlock_irqrestore(rwlock_t *rw) -{ - unsigned long val, caller; - int cpu = smp_processor_id(); - int stuck = INIT_STUCK; - - __asm__ __volatile__("mov %%i7, %0" : "=r" (caller)); -clock_again: - __asm__ __volatile__("ldstub [%1 + 2], %0" : "=r" (val) : "r" (&(rw->lock))); - if(val) { - while(rw->lock & 0xff00) { - STUCK; - barrier(); - } - goto clock_again; - } - (*((unsigned short *)&rw->lock))--; - barrier(); - (*(((unsigned char *)&rw->lock)+2))=0; -} - -#undef INIT_STUCK -#define INIT_STUCK 100000000 + STORE_CALLER(caller); -#undef STUCK -#define STUCK \ -if(!--stuck) { printk("write_lock_irqsave(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; } - -/* Caller does __save_and_cli(flags) for us. */ -void _write_lock_irqsave(rwlock_t *rw) -{ - unsigned long val, caller; - int cpu = smp_processor_id(); - int stuck = INIT_STUCK; - - __asm__ __volatile__("mov %%i7, %0" : "=r" (caller)); wlock_again: __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock))); if(val) { while(rw->lock & 0xff) { - STUCK; + if (!--stuck) { + show_write(str, rw, caller); + stuck = INIT_STUCK; + } barrier(); } goto wlock_again; } rw->owner_pc = (cpu & 3) | (caller & ~3); while(rw->lock & ~0xff) { - STUCK; + if (!--stuck) { + show_write(str, rw, caller); + stuck = INIT_STUCK; + } barrier(); } } -void _write_unlock_irqrestore(rwlock_t *rw) +void _do_write_unlock(rwlock_t *rw) { rw->owner_pc = 0; barrier(); diff -u --recursive --new-file v2.1.123/linux/arch/sparc/mm/Makefile linux/arch/sparc/mm/Makefile --- v2.1.123/linux/arch/sparc/mm/Makefile Thu Aug 6 14:06:30 1998 +++ linux/arch/sparc/mm/Makefile Sun Oct 4 10:22:42 1998 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.31 1998/07/26 03:02:45 davem Exp $ +# $Id: Makefile,v 1.32 1998/08/16 16:02:25 ecd Exp $ # Makefile for the linux Sparc-specific parts of the memory manager. # # Note! Dependencies are done automagically by 'make dep', which also @@ -12,7 +12,7 @@ ifeq ($(CONFIG_SUN4),y) O_OBJS += nosrmmu.o else -O_OBJS += srmmu.o iommu.o io-unit.o hypersparc.o viking.o tsunami.o turbosparc.o +O_OBJS += srmmu.o iommu.o io-unit.o hypersparc.o viking.o tsunami.o endif ifdef SMP O_OBJS += nosun4c.o @@ -24,9 +24,6 @@ hypersparc.o: hypersparc.S $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o hypersparc.o hypersparc.S - -turbosparc.o: turbosparc.S - $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o turbosparc.o turbosparc.S viking.o: viking.S $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o viking.o viking.S diff -u --recursive --new-file v2.1.123/linux/arch/sparc/mm/asyncd.c linux/arch/sparc/mm/asyncd.c --- v2.1.123/linux/arch/sparc/mm/asyncd.c Wed Sep 9 14:51:06 1998 +++ linux/arch/sparc/mm/asyncd.c Sun Oct 4 10:22:42 1998 @@ -1,4 +1,4 @@ -/* $Id: asyncd.c,v 1.11 1997/12/14 23:24:34 ecd Exp $ +/* $Id: asyncd.c,v 1.12 1998/09/13 04:30:30 davem Exp $ * The asyncd kernel daemon. This handles paging on behalf of * processes that receive page faults due to remote (async) memory * accesses. diff -u --recursive --new-file v2.1.123/linux/arch/sparc/mm/fault.c linux/arch/sparc/mm/fault.c --- v2.1.123/linux/arch/sparc/mm/fault.c Fri May 8 23:14:46 1998 +++ linux/arch/sparc/mm/fault.c Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -/* $Id: fault.c,v 1.94 1998/05/01 16:00:27 jj Exp $ +/* $Id: fault.c,v 1.95 1998/09/18 19:50:32 davem Exp $ * fault.c: Page fault handlers for the Sparc. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -149,7 +149,9 @@ (unsigned long) tsk->mm->context); printk(KERN_ALERT "tsk->mm->pgd = %08lx\n", (unsigned long) tsk->mm->pgd); + lock_kernel(); die_if_kernel("Oops", regs); + unlock_kernel(); } asmlinkage int lookup_fault(unsigned long pc, unsigned long ret_pc, @@ -196,11 +198,11 @@ unsigned int fixup; unsigned long g2; int from_user = !(regs->psr & PSR_PS); - lock_kernel(); - down(&mm->mmap_sem); + if(text_fault) address = regs->pc; + down(&mm->mmap_sem); /* The kernel referencing a bad kernel pointer can lock up * a sun4c machine completely, so we must attempt recovery. */ @@ -231,7 +233,7 @@ } handle_mm_fault(current, vma, address, write); up(&mm->mmap_sem); - goto out; + return; /* * Something tried to access memory that isn't in our memory map.. * Fix it, but check if it's kernel or user first.. @@ -263,7 +265,7 @@ regs->u_regs[UREG_G2] = g2; regs->pc = fixup; regs->npc = regs->pc + 4; - goto out; + return; } } if(from_user) { @@ -274,11 +276,9 @@ tsk->tss.sig_address = address; tsk->tss.sig_desc = SUBSIG_NOMAPPING; force_sig(SIGSEGV, tsk); - goto out; + return; } unhandled_fault (address, tsk, regs); -out: - unlock_kernel(); } asmlinkage void do_sun4c_fault(struct pt_regs *regs, int text_fault, int write, diff -u --recursive --new-file v2.1.123/linux/arch/sparc/mm/init.c linux/arch/sparc/mm/init.c --- v2.1.123/linux/arch/sparc/mm/init.c Wed Sep 9 14:51:06 1998 +++ linux/arch/sparc/mm/init.c Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.59 1998/03/27 06:59:57 davem Exp $ +/* $Id: init.c,v 1.60 1998/09/13 04:30:31 davem Exp $ * linux/arch/sparc/mm/init.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.1.123/linux/arch/sparc/mm/srmmu.c linux/arch/sparc/mm/srmmu.c --- v2.1.123/linux/arch/sparc/mm/srmmu.c Thu Aug 6 14:06:30 1998 +++ linux/arch/sparc/mm/srmmu.c Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -/* $Id: srmmu.c,v 1.173 1998/08/04 20:48:57 davem Exp $ +/* $Id: srmmu.c,v 1.175 1998/08/28 18:57:31 zaitcev Exp $ * srmmu.c: SRMMU specific routines for memory management. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -1997,7 +1997,7 @@ static void srmmu_destroy_context(struct mm_struct *mm) { - if(mm->context != NO_CONTEXT && mm->count == 1) { + if(mm->context != NO_CONTEXT && atomic_read(&mm->count) == 1) { flush_cache_mm(mm); ctxd_set(&srmmu_context_table[mm->context], swapper_pg_dir); flush_tlb_mm(mm); @@ -2071,7 +2071,7 @@ static void hypersparc_destroy_context(struct mm_struct *mm) { - if(mm->context != NO_CONTEXT && mm->count == 1) { + if(mm->context != NO_CONTEXT && atomic_read(&mm->count) == 1) { ctxd_t *ctxp; /* HyperSparc is copy-back, any data for this @@ -2399,10 +2399,93 @@ poke_srmmu = poke_swift; } -/* turbosparc.S */ -extern void turbosparc_flush_cache_all(void); -extern void turbosparc_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr); -extern void turbosparc_flush_page_for_dma(unsigned long page); +static void turbosparc_flush_cache_all(void) +{ + flush_user_windows(); + turbosparc_idflash_clear(); +} + +static void turbosparc_flush_cache_mm(struct mm_struct *mm) +{ + FLUSH_BEGIN(mm) + flush_user_windows(); + turbosparc_idflash_clear(); + FLUSH_END +} + +static void turbosparc_flush_cache_range(struct mm_struct *mm, unsigned long start, unsigned long end) +{ + FLUSH_BEGIN(mm) + flush_user_windows(); + turbosparc_idflash_clear(); + FLUSH_END +} + +static void turbosparc_flush_cache_page(struct vm_area_struct *vma, unsigned long page) +{ + FLUSH_BEGIN(vma->vm_mm) + flush_user_windows(); + if (vma->vm_flags & VM_EXEC) + turbosparc_flush_icache(); + turbosparc_flush_dcache(); + FLUSH_END +} + +/* TurboSparc is copy-back, if we turn it on, but this does not work. */ +static void turbosparc_flush_page_to_ram(unsigned long page) +{ +#ifdef TURBOSPARC_WRITEBACK + volatile unsigned long clear; + + if (srmmu_hwprobe(page)) + turbosparc_flush_page_cache(page); + clear = srmmu_get_fstatus(); +#endif +} + +static void turbosparc_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr) +{ +} + +static void turbosparc_flush_page_for_dma(unsigned long page) +{ + turbosparc_flush_dcache(); +} + +static void turbosparc_flush_chunk(unsigned long chunk) +{ +} + +static void turbosparc_flush_tlb_all(void) +{ + srmmu_flush_whole_tlb(); + module_stats.invall++; +} + +static void turbosparc_flush_tlb_mm(struct mm_struct *mm) +{ + FLUSH_BEGIN(mm) + srmmu_flush_whole_tlb(); + module_stats.invmm++; + FLUSH_END +} + +static void turbosparc_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) +{ + FLUSH_BEGIN(mm) + srmmu_flush_whole_tlb(); + module_stats.invrnge++; + FLUSH_END +} + +static void turbosparc_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) +{ + FLUSH_BEGIN(vma->vm_mm) + srmmu_flush_whole_tlb(); + module_stats.invpg++; + FLUSH_END +} + __initfunc(static void poke_turbosparc(void)) { @@ -2420,7 +2503,7 @@ #ifdef TURBOSPARC_WRITEBACK ccreg |= (TURBOSPARC_SNENABLE); /* Do DVMA snooping in Dcache */ ccreg &= ~(TURBOSPARC_uS2 | TURBOSPARC_WTENABLE); - /* Write-back D-cache, emulate VLSI + /* Write-back D-cache, emulate VLSI * abortion number three, not number one */ #else /* For now let's play safe, optimize later */ @@ -2428,7 +2511,8 @@ /* Do DVMA snooping in Dcache, Write-thru D-cache */ ccreg &= ~(TURBOSPARC_uS2); /* Emulate VLSI abortion number three, not number one */ -#endif +#endif + switch (ccreg & 7) { case 0: /* No SE cache */ case 7: /* Test mode */ @@ -2449,22 +2533,17 @@ srmmu_modtype = TurboSparc; BTFIXUPSET_CALL(flush_cache_all, turbosparc_flush_cache_all, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_cache_mm, hypersparc_flush_cache_mm, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_cache_page, hypersparc_flush_cache_page, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_cache_range, hypersparc_flush_cache_range, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(flush_cache_mm, turbosparc_flush_cache_mm, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(flush_cache_page, turbosparc_flush_cache_page, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(flush_cache_range, turbosparc_flush_cache_range, BTFIXUPCALL_NORM); + + BTFIXUPSET_CALL(flush_tlb_all, turbosparc_flush_tlb_all, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(flush_tlb_mm, turbosparc_flush_tlb_mm, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(flush_tlb_page, turbosparc_flush_tlb_page, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(flush_tlb_range, turbosparc_flush_tlb_range, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_tlb_all, hypersparc_flush_tlb_all, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_tlb_mm, hypersparc_flush_tlb_mm, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_tlb_page, hypersparc_flush_tlb_page, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_tlb_range, hypersparc_flush_tlb_range, BTFIXUPCALL_NORM); - -#ifdef TURBOSPARC_WRITEBACK - BTFIXUPSET_CALL(flush_page_to_ram, hypersparc_flush_page_to_ram, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_chunk, hypersparc_flush_chunk, BTFIXUPCALL_NORM); -#else - BTFIXUPSET_CALL(flush_page_to_ram, swift_flush_page_to_ram, BTFIXUPCALL_NOP); - BTFIXUPSET_CALL(flush_chunk, swift_flush_chunk, BTFIXUPCALL_NOP); -#endif + BTFIXUPSET_CALL(flush_page_to_ram, turbosparc_flush_page_to_ram, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(flush_chunk, turbosparc_flush_chunk, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_sig_insns, turbosparc_flush_sig_insns, BTFIXUPCALL_NOP); BTFIXUPSET_CALL(flush_page_for_dma, turbosparc_flush_page_for_dma, BTFIXUPCALL_NOP); diff -u --recursive --new-file v2.1.123/linux/arch/sparc/mm/sun4c.c linux/arch/sparc/mm/sun4c.c --- v2.1.123/linux/arch/sparc/mm/sun4c.c Thu Aug 6 14:06:30 1998 +++ linux/arch/sparc/mm/sun4c.c Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -/* $Id: sun4c.c,v 1.166 1998/08/04 20:49:05 davem Exp $ +/* $Id: sun4c.c,v 1.171 1998/09/21 05:05:41 jj Exp $ * sun4c.c: Doing in software what should be done in hardware. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -400,7 +400,9 @@ _unused = sun4c_get_context(); sun4c_set_context(_unused); +#ifdef CONFIG_SUN_AUXIO _unused = *AUXREG; +#endif } /* Bootup utility functions. */ @@ -622,9 +624,8 @@ break; case (SM_SUN4|SM_4_470): - prom_printf("No support for 4400 yet\n"); - prom_halt(); - num_segmaps = 1024; + /* should be 1024 segmaps. when it get fixed */ + num_segmaps = 256; num_contexts = 64; break; default: @@ -755,13 +756,15 @@ ~bits_off); } -/* the 4/260 dies real hard on the prom_putsegment line. - not sure why, but it seems to work without it cgd */ static inline void sun4c_init_map_kernelprom(unsigned long kernel_end) { unsigned long vaddr; unsigned char pseg, ctx; -#ifndef CONFIG_SUN4 +#ifdef CONFIG_SUN4 + /* sun4/110 and 260 have no kadb. */ + if((idprom->id_machtype != (SM_SUN4 | SM_4_260)) && + (idprom->id_machtype != (SM_SUN4 | SM_4_110))) { +#endif for(vaddr = KADB_DEBUGGER_BEGVM; vaddr < LINUX_OPPROM_ENDVM; vaddr += SUN4C_REAL_PGDIR_SIZE) { @@ -773,6 +776,8 @@ fix_permissions(vaddr, _SUN4C_PAGE_PRIV, 0); } } +#ifdef CONFIG_SUN4 + } #endif for(vaddr = KERNBASE; vaddr < kernel_end; vaddr += SUN4C_REAL_PGDIR_SIZE) { pseg = sun4c_get_segmap(vaddr); @@ -2142,7 +2147,7 @@ { struct ctx_list *ctx_old; - if(mm->context != NO_CONTEXT && mm->count == 1) { + if(mm->context != NO_CONTEXT && atomic_read(&mm->count) == 1) { sun4c_demap_context_hw(&sun4c_context_ring[mm->context], mm->context); ctx_old = ctx_list_pool + mm->context; remove_from_ctx_list(ctx_old); @@ -2205,7 +2210,7 @@ { struct ctx_list *ctx_old; - if(mm->context != NO_CONTEXT && mm->count == 1) { + if(mm->context != NO_CONTEXT && atomic_read(&mm->count) == 1) { sun4c_demap_context_sw(&sun4c_context_ring[mm->context], mm->context); ctx_old = ctx_list_pool + mm->context; remove_from_ctx_list(ctx_old); diff -u --recursive --new-file v2.1.123/linux/arch/sparc/mm/turbosparc.S linux/arch/sparc/mm/turbosparc.S --- v2.1.123/linux/arch/sparc/mm/turbosparc.S Thu Apr 23 20:21:31 1998 +++ linux/arch/sparc/mm/turbosparc.S Wed Dec 31 16:00:00 1969 @@ -1,48 +0,0 @@ -/* $Id: turbosparc.S,v 1.3 1998/02/05 14:19:04 jj Exp $ - * turbosparc.S: High speed TurboSparc mmu/cache operations. - * - * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - -#include -#include -#include -#include -#include - -#define WINDOW_FLUSH(tmp1, tmp2) \ - mov 0, tmp1; \ -98: ld [%g6 + AOFF_task_tss + AOFF_thread_uwinmask], tmp2; \ - orcc %g0, tmp2, %g0; \ - add tmp1, 1, tmp1; \ - bne 98b; \ - save %sp, -64, %sp; \ -99: subcc tmp1, 1, tmp1; \ - bne 99b; \ - restore %g0, %g0, %g0; - - .text - .align 4 - - .globl turbosparc_flush_cache_all - .globl turbosparc_flush_sig_insns - .globl turbosparc_flush_page_for_dma - -turbosparc_flush_cache_all: - WINDOW_FLUSH(%g4, %g5) - sethi %hi(vac_cache_size), %g4 - ld [%g4 + %lo(vac_cache_size)], %g5 - sethi %hi(vac_line_size), %g1 - ld [%g1 + %lo(vac_line_size)], %g2 -1: - subcc %g5, %g2, %g5 - bne 1b - sta %g0, [%g5] ASI_M_DATAC_TAG - retl - sta %g0, [%g0] ASI_M_IC_FLCLEAR - -turbosparc_flush_sig_insns: -turbosparc_flush_page_for_dma: - retl - nop diff -u --recursive --new-file v2.1.123/linux/arch/sparc/prom/console.c linux/arch/sparc/prom/console.c --- v2.1.123/linux/arch/sparc/prom/console.c Thu Apr 23 20:21:31 1998 +++ linux/arch/sparc/prom/console.c Sun Oct 4 10:22:43 1998 @@ -1,8 +1,9 @@ -/* $Id: console.c,v 1.17 1998/03/09 14:04:21 jj Exp $ +/* $Id: console.c,v 1.20 1998/09/21 05:05:50 jj Exp $ * console.c: Routines that deal with sending and receiving IO * to/from the current console device using the PROM. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1998 Pete Zaitcev */ #include @@ -17,6 +18,9 @@ extern void restore_current(void); +static char con_name_jmc[] = "/obio/su@"; /* "/obio/su@0,3002f8"; */ +#define CON_SIZE_JMC (sizeof(con_name_jmc)) + /* Non blocking get character from console input device, returns -1 * if no input was taken. This can be used for polling. */ @@ -83,7 +87,6 @@ i = 0; } #endif - break; default: i = -1; @@ -139,9 +142,14 @@ restore_flags(flags); if(prom_node_has_property(st_p, "keyboard")) return PROMDEV_IKBD; - prom_getproperty(st_p, "device_type", propb, sizeof(propb)); + if (prom_getproperty(st_p, "name", propb, sizeof(propb)) != -1) { + if(strncmp(propb, "keyboard", sizeof("serial")) == 0) + return PROMDEV_IKBD; + } + if (prom_getproperty(st_p, "device_type", propb, sizeof(propb)) != -1) { if(strncmp(propb, "serial", sizeof("serial"))) return PROMDEV_I_UNK; + } prom_getproperty(prom_root_node, "stdin-path", propb, sizeof(propb)); p = propb; while(*p) p++; p -= 2; @@ -154,7 +162,7 @@ return PROMDEV_I_UNK; case PROM_AP1000: return PROMDEV_I_UNK; - }; + } } /* Query for output device type */ @@ -190,9 +198,12 @@ return PROMDEV_OSCREEN; } if(prom_vers == PROM_V3) { - if(strncmp("serial", propb, sizeof("serial"))) + if(propl >= 0 && + strncmp("serial", propb, sizeof("serial")) != 0) return PROMDEV_O_UNK; prom_getproperty(prom_root_node, "stdout-path", propb, sizeof(propb)); + if(strncmp(propb, con_name_jmc, CON_SIZE_JMC) == 0) + return PROMDEV_OTTYA; p = propb; while(*p) p++; p -= 2; if(p[0]==':') { @@ -201,9 +212,7 @@ else if(p[1] == 'b') return PROMDEV_OTTYB; } - return PROMDEV_O_UNK; } else { - /* This works on SS-2 (an early OpenFirmware) still. */ switch(*romvec->pv_stdin) { case PROMDEV_TTYA: return PROMDEV_OTTYA; case PROMDEV_TTYB: return PROMDEV_OTTYB; @@ -212,7 +221,6 @@ break; case PROM_AP1000: default: - return PROMDEV_I_UNK; - }; + } return PROMDEV_O_UNK; } diff -u --recursive --new-file v2.1.123/linux/arch/sparc/prom/tree.c linux/arch/sparc/prom/tree.c --- v2.1.123/linux/arch/sparc/prom/tree.c Thu Apr 23 20:21:31 1998 +++ linux/arch/sparc/prom/tree.c Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -/* $Id: tree.c,v 1.24 1998/03/09 14:04:29 jj Exp $ +/* $Id: tree.c,v 1.25 1998/09/17 11:04:58 jj Exp $ * tree.c: Basic device tree traversal/scanning for the Linux * prom library. * @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -257,29 +258,49 @@ int prom_finddevice(char *name) { - int topnd = prom_getchild(prom_root_node); - int srch; + char nbuf[128]; + char *s = name, *d; + int node = prom_root_node, node2; + unsigned int which_io, phys_addr; + struct linux_prom_registers reg[PROMREG_MAX]; - if(name[0] == '/') - name++; - if(sparc_cpu_model == sun4d) { - if(!strcmp(name, "sbus")) - name = "sbi"; - if((srch = prom_searchsiblings(topnd, "io-unit")) == 0 || - (srch = prom_getchild(srch)) == 0 || - (srch = prom_searchsiblings(srch, name)) == 0) { - prom_printf("%s prom node not found.\n", name); - prom_halt(); - } - } else if((srch = prom_searchsiblings(topnd, name)) == 0) { - if((srch = prom_searchsiblings(topnd, "iommu")) == 0 || - (srch = prom_getchild(srch)) == 0 || - (srch = prom_searchsiblings(srch, name)) == 0) { - prom_printf("Cannot find node %s\n", name); - prom_halt(); + while (*s++) { + if (!*s) return node; /* path '.../' is legal */ + node = prom_getchild(node); + + for (d = nbuf; *s != 0 && *s != '@' && *s != '/';) + *d++ = *s++; + *d = 0; + + node = prom_searchsiblings(node, nbuf); + if (!node) + return 0; + + if (*s == '@') { + if (isxdigit(s[1]) && s[2] == ',') { + which_io = simple_strtoul(s+1, NULL, 16); + phys_addr = simple_strtoul(s+3, &d, 16); + if (d != s + 3 && (!*d || *d == '/') + && d <= s + 3 + 8) { + node2 = node; + while (node2 && node2 != -1) { + if (prom_getproperty (node2, "reg", (char *)reg, sizeof (reg)) > 0) { + if (which_io == reg[0].which_io && phys_addr == reg[0].phys_addr) { + node = node2; + break; + } + } + node2 = prom_getsibling(node2); + if (!node2 || node2 == -1) + break; + node2 = prom_searchsiblings(prom_getsibling(node2), nbuf); + } + } + } + while (*s != 0 && *s != '/') s++; } } - return srch; + return node; } int prom_node_has_property(int node, char *prop) diff -u --recursive --new-file v2.1.123/linux/arch/sparc/vmlinux.lds linux/arch/sparc/vmlinux.lds --- v2.1.123/linux/arch/sparc/vmlinux.lds Thu Apr 23 20:21:31 1998 +++ linux/arch/sparc/vmlinux.lds Sun Oct 4 10:22:43 1998 @@ -22,7 +22,9 @@ .data1 : { *(.data1) } _edata = .; PROVIDE (edata = .); + __start___fixup = .; .fixup : { *(.fixup) } + __stop___fixup = .; __start___ex_table = .; __ex_table : { *(__ex_table) } __stop___ex_table = .; diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/Makefile linux/arch/sparc64/Makefile --- v2.1.123/linux/arch/sparc64/Makefile Thu Aug 6 14:06:30 1998 +++ linux/arch/sparc64/Makefile Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.27 1998/07/27 07:36:16 davem Exp $ +# $Id: Makefile,v 1.29 1998/09/16 12:25:20 jj Exp $ # sparc64/Makefile # # Makefile for the architecture dependent flags and dependencies on the @@ -12,14 +12,22 @@ SHELL =/bin/bash CC = sparc64-linux-gcc -D__KERNEL__ -I$(TOPDIR)/include + +IS_EGCS := $(shell if $(CC) --version 2>&1 | grep 'egcs' > /dev/null; then echo y; else echo n; fi) +NEW_GAS := $(shell if $(LD) --version 2>&1 | grep 'elf64_sparc' > /dev/null; then echo y; else echo n; fi) + +ifneq ($(NEW_GAS),y) AS = sparc64-linux-as LD = sparc64-linux-ld NM = sparc64-linux-nm AR = sparc64-linux-ar RANLIB = sparc64-linux-ranlib +else +AS := $(AS) -64 +LD := $(LD) -m elf64_sparc +endif ELFTOAOUT = elftoaout -IS_EGCS := $(shell if $(CC) --version 2>&1 | grep 'egcs' > /dev/null; then echo y; else echo n; fi) # # Uncomment the first CFLAGS if you are doing kgdb source level @@ -30,7 +38,7 @@ CFLAGS := $(CFLAGS) -pipe -mno-fpu -mtune=ultrasparc -mmedlow \ -ffixed-g4 -fcall-used-g5 -fcall-used-g7 -Wno-sign-compare else - CFLAGS := $(CFLAGS) -pipe -mno-fpu -mtune=ultrasparc -mcmodel=medlow \ + CFLAGS := $(CFLAGS) -m64 -pipe -mno-fpu -mcpu=ultrasparc -mcmodel=medlow \ -ffixed-g4 -fcall-used-g5 -fcall-used-g7 -Wno-sign-compare endif diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/config.in linux/arch/sparc64/config.in --- v2.1.123/linux/arch/sparc64/config.in Thu Aug 6 14:06:30 1998 +++ linux/arch/sparc64/config.in Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.55 1998/08/03 15:28:38 davem Exp $ +# $Id: config.in,v 1.57 1998/09/17 11:05:14 jj Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -51,14 +51,15 @@ define_bool CONFIG_SUN_CONSOLE y define_bool CONFIG_SUN_AUXIO y define_bool CONFIG_SUN_IO y - define_bool CONFIG_PCI y - define_bool CONFIG_PCI_CONSOLE y + bool 'PCI support' CONFIG_PCI source drivers/sbus/char/Config.in source drivers/sbus/audio/Config.in fi tristate 'Openprom tree appears in /proc/openprom (EXPERIMENTAL)' CONFIG_SUN_OPENPROMFS -bool 'Backward-compatible /proc/pci' CONFIG_PCI_OLD_PROC +if [ "$CONFIG_PCI" = "y" ]; then + bool 'Backward-compatible /proc/pci' CONFIG_PCI_OLD_PROC +fi bool 'Networking support' CONFIG_NET bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT @@ -246,5 +247,5 @@ comment 'Kernel hacking' bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ -bool 'ECache flush trap support at ta 0x72' CONFIG_EC_FLUSH_TRAP +#bool 'ECache flush trap support at ta 0x72' CONFIG_EC_FLUSH_TRAP endmenu diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig --- v2.1.123/linux/arch/sparc64/defconfig Thu Aug 6 14:06:30 1998 +++ linux/arch/sparc64/defconfig Sun Oct 4 10:22:43 1998 @@ -55,7 +55,6 @@ CONFIG_SUN_AUXIO=y CONFIG_SUN_IO=y CONFIG_PCI=y -CONFIG_PCI_CONSOLE=y # # Misc Linux/SPARC drivers @@ -73,6 +72,7 @@ # CONFIG_SPARCAUDIO is not set # CONFIG_SPARCAUDIO_AMD7930 is not set # CONFIG_SPARCAUDIO_CS4231 is not set +# CONFIG_SPARCAUDIO_DBRI is not set CONFIG_SUN_OPENPROMFS=m CONFIG_PCI_OLD_PROC=y CONFIG_NET=y @@ -91,7 +91,7 @@ # CONFIG_PARPORT_OTHER is not set CONFIG_PRINTER=y CONFIG_PRINTER_READBACK=y -CONFIG_ENVCTRL=y +CONFIG_ENVCTRL=m # # Floppy, IDE, and other block devices @@ -105,7 +105,7 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_INITRD=y CONFIG_BLK_DEV_LOOP=m -# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_IDE=y CONFIG_BLK_DEV_IDEDISK=y CONFIG_BLK_DEV_IDECD=y @@ -292,7 +292,8 @@ CONFIG_SMD_DISKLABEL=y CONFIG_SOLARIS_X86_PARTITION=y # CONFIG_ADFS_FS is not set -# CONFIG_DEVPTS_FS is not set +CONFIG_QNX4FS_FS=m +# CONFIG_QNX4FS_RW is not set # CONFIG_MAC_PARTITION is not set CONFIG_NLS=y @@ -335,4 +336,3 @@ # Kernel hacking # # CONFIG_MAGIC_SYSRQ is not set -# CONFIG_EC_FLUSH_TRAP is not set diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/Makefile linux/arch/sparc64/kernel/Makefile --- v2.1.123/linux/arch/sparc64/kernel/Makefile Thu Aug 6 14:06:30 1998 +++ linux/arch/sparc64/kernel/Makefile Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.38 1998/07/26 03:02:47 davem Exp $ +# $Id: Makefile,v 1.40 1998/09/17 11:05:03 jj Exp $ # Makefile for the linux kernel. # # Note! Dependencies are done automagically by 'make dep', which also @@ -20,9 +20,13 @@ traps.o devices.o auxio.o ioport.o \ irq.o ptrace.o time.o sys_sparc.o signal.o \ unaligned.o sys_sunos32.o sunos_ioctl32.o \ - central.o psycho.o ebus.o + central.o psycho.o OX_OBJS := sparc64_ksyms.o +ifdef CONFIG_PCI + O_OBJS += ebus.o +endif + ifdef SMP O_OBJS += smp.o trampoline.o endif @@ -48,6 +52,12 @@ # binfmt_elf32.o: $(TOPDIR)/fs/binfmt_elf.c +ifneq ($(IS_EGCS),y) + CMODEL_CFLAG := -mmedlow +else + CMODEL_CFLAG := -mcmodel=medlow +endif + check_asm: dummy @echo "/* Automatically generated. Do not edit. */" > asm_offsets.h @echo "#ifndef __ASM_OFFSETS_H__" >> asm_offsets.h @@ -70,7 +80,7 @@ @rm -f tmp.[ci] #$(CC) -o check_asm check_asm.c # Until we can do this natively, a hack has to take place - $(CC) -mmedlow -ffixed-g4 -S -o check_asm.s check_asm.c + $(CC) $(CMODEL_CFLAG) -ffixed-g4 -S -o check_asm.s check_asm.c $(HOSTCC) -Wa,-Av9a -o check_asm check_asm.s @rm -f check_asm.s # @@ -94,7 +104,7 @@ @rm -f tmp.[ci] #$(CC) -D__SMP__ -o check_asm check_asm.c # Until we can do this natively, a hack has to take place - $(CC) -D__SMP__ -mmedlow -ffixed-g4 -S -o check_asm.s check_asm.c + $(CC) -D__SMP__ $(CMODEL_CFLAG) -ffixed-g4 -S -o check_asm.s check_asm.c $(HOSTCC) -Wa,-Av9a -o check_asm check_asm.s @rm -f check_asm.s # diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/binfmt_aout32.c linux/arch/sparc64/kernel/binfmt_aout32.c --- v2.1.123/linux/arch/sparc64/kernel/binfmt_aout32.c Thu Apr 23 20:21:31 1998 +++ linux/arch/sparc64/kernel/binfmt_aout32.c Sun Oct 4 10:22:43 1998 @@ -91,7 +91,7 @@ # define START_DATA(u) (u.u_tsize) # define START_STACK(u) ((regs->u_regs[UREG_FP]) & ~(PAGE_SIZE - 1)) - if (!current->dumpable || current->mm->count != 1) + if (!current->dumpable || atomic_read(¤t->mm->count) != 1) return 0; current->dumpable = 0; @@ -201,7 +201,8 @@ * memory and creates the pointer tables from them, and puts their * addresses on the "stack", returning the new stack pointer value. */ -#define A(x) ((unsigned long)x) +#define A(__x) ((unsigned long)(__x)) + static u32 *create_aout32_tables(char * p, struct linux_binprm * bprm) { u32 *argv, *envp; diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/binfmt_elf32.c linux/arch/sparc64/kernel/binfmt_elf32.c --- v2.1.123/linux/arch/sparc64/kernel/binfmt_elf32.c Sun Sep 21 12:55:02 1997 +++ linux/arch/sparc64/kernel/binfmt_elf32.c Sun Oct 4 10:22:43 1998 @@ -1,19 +1,133 @@ -/* binfmt_elf32.c: Support 32-bit Sparc ELF binaries on Ultra. +/* + * binfmt_elf32.c: Support 32-bit Sparc ELF binaries on Ultra. * + * Copyright (C) 1995, 1996, 1997, 1998 David S. Miller (davem@dm.cobaltmicro.com) + * Copyright (C) 1995, 1996, 1997, 1998 Jakub Jelinek (jj@ultra.linux.cz) */ #define ELF_ARCH EM_SPARC #define ELF_CLASS ELFCLASS32 #define ELF_DATA ELFDATA2MSB; +/* For the most part we present code dumps in the format + * Solaris does. + */ +typedef unsigned int elf_greg_t; +#define ELF_NGREG 38 +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +/* Format is: + * G0 --> G7 + * O0 --> O7 + * L0 --> L7 + * I0 --> I7 + * PSR, PC, nPC, Y, WIM, TBR + */ +#include +#define ELF_CORE_COPY_REGS(__elf_regs, __pt_regs) \ +do { unsigned int *dest = &(__elf_regs[0]); \ + struct pt_regs *src = (__pt_regs); \ + unsigned int *sp; \ + int i; \ + for(i = 0; i < 16; i++) \ + dest[i] = (unsigned int) src->u_regs[i];\ + /* Don't try this at home kids... */ \ + set_fs(USER_DS); \ + sp = (unsigned int *) (src->u_regs[14] & \ + 0x00000000fffffffc); \ + for(i = 0; i < 16; i++) \ + __get_user(dest[i+16], &sp[i]); \ + set_fs(KERNEL_DS); \ + dest[32] = tstate_to_psr(src->tstate); \ + dest[33] = (unsigned int) src->tpc; \ + dest[34] = (unsigned int) src->tnpc; \ + dest[35] = src->y; \ + dest[36] = dest[37] = 0; /* XXX */ \ +} while(0); + +typedef struct { + union { + unsigned int pr_regs[32]; + unsigned long pr_dregs[16]; + } pr_fr; + unsigned int __unused; + unsigned int pr_fsr; + unsigned char pr_qcnt; + unsigned char pr_q_entrysize; + unsigned char pr_en; + unsigned int pr_q[64]; +} elf_fpregset_t; + +/* UltraSparc extensions. Still unused, but will be eventually. */ +typedef struct { + unsigned int pr_type; + unsigned int pr_align; + union { + struct { + union { + unsigned int pr_regs[32]; + unsigned long pr_dregs[16]; + long double pr_qregs[8]; + } pr_xfr; + } pr_v8p; + unsigned int pr_xfsr; + unsigned int pr_fprs; + unsigned int pr_xg[8]; + unsigned int pr_xo[8]; + unsigned long pr_tstate; + unsigned int pr_filler[8]; + } pr_un; +} elf_xregset_t; + #define elf_check_arch(x) (((x) == EM_SPARC) || ((x) == EM_SPARC32PLUS)) -#define ELF_ET_DYN_BASE 0x60000000 +#define ELF_ET_DYN_BASE 0x08000000 #include #include #include +#include + +struct timeval32 +{ + int tv_sec, tv_usec; +}; + +#define elf_prstatus elf_prstatus32 +struct elf_prstatus32 +{ + struct elf_siginfo pr_info; /* Info associated with signal */ + short pr_cursig; /* Current signal */ + unsigned int pr_sigpend; /* Set of pending signals */ + unsigned int pr_sighold; /* Set of held signals */ + pid_t pr_pid; + pid_t pr_ppid; + pid_t pr_pgrp; + pid_t pr_sid; + struct timeval32 pr_utime; /* User time */ + struct timeval32 pr_stime; /* System time */ + struct timeval32 pr_cutime; /* Cumulative user time */ + struct timeval32 pr_cstime; /* Cumulative system time */ + elf_gregset_t pr_reg; /* GP registers */ + int pr_fpvalid; /* True if math co-processor being used. */ +}; + +#define elf_prpsinfo elf_prpsinfo32 +struct elf_prpsinfo32 +{ + char pr_state; /* numeric process state */ + char pr_sname; /* char for pr_state */ + char pr_zomb; /* zombie */ + char pr_nice; /* nice val */ + unsigned int pr_flag; /* flags */ + u16 pr_uid; + u16 pr_gid; + pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* filename of executable */ + char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */ +}; #define elf_addr_t u32 #define elf_caddr_t u32 diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/check_asm.sh linux/arch/sparc64/kernel/check_asm.sh --- v2.1.123/linux/arch/sparc64/kernel/check_asm.sh Mon Mar 17 14:54:23 1997 +++ linux/arch/sparc64/kernel/check_asm.sh Sun Oct 4 10:22:43 1998 @@ -1,3 +1,4 @@ #!/bin/sh sed -n -e '/struct[ ]*'$1'_struct[ ]*{/,/};/p' < $2 | sed '/struct[ ]*'$1'_struct[ ]*{/d;/:[0-9]*[ ]*;/d;/^[ ]*$/d;/};/d;s/^[ ]*//;s/volatile[ ]*//;s/\(unsigned\|signed\|struct\)[ ]*//;s/\(\[\|__attribute__\).*;[ ]*$//;s/;[ ]*$//;s/^[^ ]*[ ]*//;s/,/\ /g' | sed 's/^[ *]*//;s/[ ]*$//;s/^.*$/printf ("#define AOFF_'$1'_\0 0x%08x\\n#define ASIZ_'$1'_\0 0x%08x\\n", ((char *)\&_'$1'.\0) - ((char *)\&_'$1'), sizeof(_'$1'.\0));/' >> $3 +echo "printf (\"#define ASIZ_$1\\t0x%08x\\n\", sizeof(_$1));" >> $3 diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/dtlb_backend.S linux/arch/sparc64/kernel/dtlb_backend.S --- v2.1.123/linux/arch/sparc64/kernel/dtlb_backend.S Thu Aug 6 14:06:30 1998 +++ linux/arch/sparc64/kernel/dtlb_backend.S Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -/* $Id: dtlb_backend.S,v 1.4 1998/06/15 16:59:34 jj Exp $ +/* $Id: dtlb_backend.S,v 1.6 1998/09/24 03:21:32 davem Exp $ * dtlb_backend.S: Back end to DTLB miss replacement strategy. * This is included directly into the trap table. * diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/ebus.c linux/arch/sparc64/kernel/ebus.c --- v2.1.123/linux/arch/sparc64/kernel/ebus.c Thu Aug 6 14:06:30 1998 +++ linux/arch/sparc64/kernel/ebus.c Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -/* $Id: ebus.c,v 1.29 1998/07/01 15:39:44 jj Exp $ +/* $Id: ebus.c,v 1.33 1998/09/21 05:06:03 jj Exp $ * ebus.c: PCI to EBus bridge device. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -31,7 +31,6 @@ extern void prom_ebus_ranges_init(struct linux_ebus *); extern void prom_ebus_intmap_init(struct linux_ebus *); -extern void pci_console_init(void); #ifdef CONFIG_SUN_OPENPROMIO extern int openprom_init(void); @@ -227,7 +226,6 @@ } } -extern void sun4u_start_timers(void); extern void clock_probe(void); __initfunc(void ebus_init(void)) @@ -367,10 +365,6 @@ ++num_ebus; } -#ifndef CONFIG_FB - pci_console_init(); -#endif - #ifdef CONFIG_SUN_OPENPROMIO openprom_init(); #endif @@ -389,6 +383,5 @@ #ifdef CONFIG_OBP_FLASH flash_init(); #endif - sun4u_start_timers(); clock_probe(); } diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/entry.S linux/arch/sparc64/kernel/entry.S --- v2.1.123/linux/arch/sparc64/kernel/entry.S Thu Aug 6 14:06:30 1998 +++ linux/arch/sparc64/kernel/entry.S Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -/* $Id: entry.S,v 1.87 1998/07/29 16:32:28 jj Exp $ +/* $Id: entry.S,v 1.90 1998/09/25 01:09:05 davem Exp $ * arch/sparc64/kernel/entry.S: Sparc64 trap low-level entry points. * * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) @@ -373,17 +373,112 @@ retl nop + /* These next few routines must be sure to clear the + * SFSR FaultValid bit so that the fast tlb data protection + * handler does not flush the wrong context and lock up the + * box. + */ + .globl __do_data_access_exception + .globl __do_data_access_exception_tl1 +__do_data_access_exception_tl1: + rdpr %pstate, %g4 + wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate + rdpr %tl, %g3 + cmp %g3, 1 + mov TLB_SFSR, %g3 + mov DMMU_SFAR, %g5 + ldxa [%g3] ASI_DMMU, %g4 ! Get SFSR + ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR + stxa %g0, [%g3] ASI_DMMU ! Clear SFSR.FaultValid bit + membar #Sync + bgu,pn %icc, winfix_dax + rdpr %tpc, %g3 + sethi %hi(109f), %g7 + ba,pt %xcc, etraptl1 + or %g7, %lo(109f), %g7 ! Merge in below +__do_data_access_exception: + rdpr %pstate, %g4 + wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate + mov TLB_SFSR, %g3 + mov DMMU_SFAR, %g5 + ldxa [%g3] ASI_DMMU, %g4 ! Get SFSR + ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR + stxa %g0, [%g3] ASI_DMMU ! Clear SFSR.FaultValid bit + membar #Sync + sethi %hi(109f), %g7 + ba,pt %xcc, etrap +109: or %g7, %lo(109b), %g7 + mov %l4, %o1 + mov %l5, %o2 + call data_access_exception + add %sp, STACK_BIAS + REGWIN_SZ, %o0 + ba,pt %xcc, rtrap + clr %l6 + + .globl __do_instruction_access_exception + .globl __do_instruction_access_exception_tl1 +__do_instruction_access_exception_tl1: + rdpr %pstate, %g4 + wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate + mov TLB_SFSR, %g3 + mov DMMU_SFAR, %g5 + ldxa [%g3] ASI_DMMU, %g4 ! Get SFSR + ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR + stxa %g0, [%g3] ASI_IMMU ! Clear FaultValid bit + membar #Sync + sethi %hi(109f), %g7 + ba,pt %xcc, etraptl1 + or %g7, %lo(109f), %g7 ! Merge in below +__do_instruction_access_exception: + rdpr %pstate, %g4 + wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate + mov TLB_SFSR, %g3 + mov DMMU_SFAR, %g5 + ldxa [%g3] ASI_DMMU, %g4 ! Get SFSR + ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR + stxa %g0, [%g3] ASI_IMMU ! Clear FaultValid bit + membar #Sync + sethi %hi(109f), %g7 + ba,pt %xcc, etrap +109: or %g7, %lo(109b), %g7 + mov %l4, %o1 + mov %l5, %o2 + call instruction_access_exception + add %sp, STACK_BIAS + REGWIN_SZ, %o0 + ba,pt %xcc, rtrap + clr %l6 + + .globl __do_privact +__do_privact: + mov TLB_SFSR, %g3 + stxa %g0, [%g3] ASI_DMMU ! Clear FaultValid bit + membar #Sync + sethi %hi(109f), %g7 + ba,pt %xcc, etrap +109: or %g7, %lo(109b), %g7 + call do_privact + add %sp, STACK_BIAS + REGWIN_SZ, %o0 + ba,pt %xcc, rtrap + clr %l6 + .globl do_mna do_mna: rdpr %tl, %g3 cmp %g3, 1 - bgu,a,pn %icc, winfix_mna - rdpr %tpc, %g3 + + /* Setup %g4/%g5 now as they are used in the + * winfixup code. + */ + mov TLB_SFSR, %g3 mov DMMU_SFAR, %g4 - mov TLB_SFSR, %g5 - sethi %hi(109f), %g7 ldxa [%g4] ASI_DMMU, %g4 - ldxa [%g5] ASI_DMMU, %g5 + ldxa [%g3] ASI_DMMU, %g5 + stxa %g0, [%g3] ASI_DMMU ! Clear FaultValid bit + membar #Sync + bgu,pn %icc, winfix_dax + rdpr %tpc, %g3 + +1: sethi %hi(109f), %g7 ba,pt %xcc, etrap 109: or %g7, %lo(109b), %g7 mov %l4, %o1 @@ -395,11 +490,13 @@ .globl do_lddfmna do_lddfmna: - mov DMMU_SFAR, %g4 - mov TLB_SFSR, %g5 sethi %hi(109f), %g7 + mov TLB_SFSR, %g4 + ldxa [%g4] ASI_DMMU, %g5 + stxa %g0, [%g4] ASI_DMMU ! Clear FaultValid bit + membar #Sync + mov DMMU_SFAR, %g4 ldxa [%g4] ASI_DMMU, %g4 - ldxa [%g5] ASI_DMMU, %g5 ba,pt %xcc, etrap 109: or %g7, %lo(109b), %g7 mov %l4, %o1 @@ -411,11 +508,13 @@ .globl do_stdfmna do_stdfmna: - mov DMMU_SFAR, %g4 - mov TLB_SFSR, %g5 sethi %hi(109f), %g7 + mov TLB_SFSR, %g4 + ldxa [%g4] ASI_DMMU, %g5 + stxa %g0, [%g4] ASI_DMMU ! Clear FaultValid bit + membar #Sync + mov DMMU_SFAR, %g4 ldxa [%g4] ASI_DMMU, %g4 - ldxa [%g5] ASI_DMMU, %g5 ba,pt %xcc, etrap 109: or %g7, %lo(109b), %g7 mov %l4, %o1 diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c --- v2.1.123/linux/arch/sparc64/kernel/ioctl32.c Thu Aug 6 14:06:30 1998 +++ linux/arch/sparc64/kernel/ioctl32.c Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -/* $Id: ioctl32.c,v 1.48 1998/08/03 23:58:04 davem Exp $ +/* $Id: ioctl32.c,v 1.52 1998/09/25 17:09:22 jj Exp $ * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -40,6 +40,7 @@ #undef __KERNEL__ #include #define __KERNEL__ +#include #include #include @@ -51,16 +52,20 @@ #include #include -/* As gcc will warn about casting u32 to some ptr, we have to cast it to - * unsigned long first, and that's what is A() for. - * You just do (void *)A(x), instead of having to type (void *)((unsigned long)x) - * or instead of just (void *)x, which will produce warnings. - */ -#define A(x) ((unsigned long)x) +/* Use this to get at 32-bit user passed pointers. + See sys_sparc32.c for description about these. */ +#define A(__x) ((unsigned long)(__x)) +#define AA(__x) \ +({ unsigned long __ret; \ + __asm__ ("srl %0, 0, %0" \ + : "=r" (__ret) \ + : "0" (__x)); \ + __ret; \ +}) extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); -static int w_long(unsigned int fd, unsigned int cmd, u32 arg) +static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg) { mm_segment_t old_fs = get_fs(); int err; @@ -69,23 +74,23 @@ set_fs (KERNEL_DS); err = sys_ioctl(fd, cmd, (unsigned long)&val); set_fs (old_fs); - if (!err && put_user(val, (u32 *)A(arg))) + if (!err && put_user(val, (u32 *)arg)) return -EFAULT; return err; } -static int rw_long(unsigned int fd, unsigned int cmd, u32 arg) +static int rw_long(unsigned int fd, unsigned int cmd, unsigned long arg) { mm_segment_t old_fs = get_fs(); int err; unsigned long val; - if(get_user(val, (u32 *)A(arg))) + if(get_user(val, (u32 *)arg)) return -EFAULT; set_fs (KERNEL_DS); err = sys_ioctl(fd, cmd, (unsigned long)&val); set_fs (old_fs); - if (!err && put_user(val, (u32 *)A(arg))) + if (!err && put_user(val, (u32 *)arg)) return -EFAULT; return err; } @@ -95,9 +100,9 @@ int tv_usec; }; -static int do_siocgstamp(unsigned int fd, unsigned int cmd, u32 arg) +static int do_siocgstamp(unsigned int fd, unsigned int cmd, unsigned long arg) { - struct timeval32 *up = (struct timeval32 *)A(arg); + struct timeval32 *up = (struct timeval32 *)arg; struct timeval ktv; mm_segment_t old_fs = get_fs(); int err; @@ -106,10 +111,8 @@ err = sys_ioctl(fd, cmd, (unsigned long)&ktv); set_fs(old_fs); if(!err) { - if(!access_ok(VERIFY_WRITE, up, sizeof(*up)) || - __put_user(ktv.tv_sec, &up->tv_sec) || - __put_user(ktv.tv_usec, &up->tv_usec)) - err = -EFAULT; + err = put_user(ktv.tv_sec, &up->tv_sec); + err |= __put_user(ktv.tv_usec, &up->tv_usec); } return err; } @@ -149,7 +152,7 @@ __kernel_caddr_t32 ifcbuf; }; -static inline int dev_ifconf(unsigned int fd, u32 arg) +static inline int dev_ifconf(unsigned int fd, unsigned long arg) { struct ifconf32 ifc32; struct ifconf ifc; @@ -159,7 +162,7 @@ unsigned int i, j; int err; - if (copy_from_user(&ifc32, (struct ifconf32 *)A(arg), sizeof(struct ifconf32))) + if (copy_from_user(&ifc32, (struct ifconf32 *)arg, sizeof(struct ifconf32))) return -EFAULT; if(ifc32.ifcbuf == 0) { @@ -199,7 +202,7 @@ ifc32.ifc_len = i; else ifc32.ifc_len = i - sizeof (struct ifreq32); - if (copy_to_user((struct ifconf32 *)A(arg), &ifc32, sizeof(struct ifconf32))) + if (copy_to_user((struct ifconf32 *)arg, &ifc32, sizeof(struct ifconf32))) err = -EFAULT; } } @@ -208,7 +211,7 @@ return err; } -static inline int dev_ifsioc(unsigned int fd, unsigned int cmd, u32 arg) +static inline int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long arg) { struct ifreq ifr; mm_segment_t old_fs; @@ -216,26 +219,27 @@ switch (cmd) { case SIOCSIFMAP: - if (copy_from_user(&ifr, (struct ifreq32 *)A(arg), sizeof(ifr.ifr_name)) || - __get_user(ifr.ifr_map.mem_start, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.mem_start)) || - __get_user(ifr.ifr_map.mem_end, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.mem_end)) || - __get_user(ifr.ifr_map.base_addr, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.base_addr)) || - __get_user(ifr.ifr_map.irq, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.irq)) || - __get_user(ifr.ifr_map.dma, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.dma)) || - __get_user(ifr.ifr_map.port, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.port))) + err = copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(ifr.ifr_name)); + err |= __get_user(ifr.ifr_map.mem_start, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_start)); + err |= __get_user(ifr.ifr_map.mem_end, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_end)); + err |= __get_user(ifr.ifr_map.base_addr, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.base_addr)); + err |= __get_user(ifr.ifr_map.irq, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.irq)); + err |= __get_user(ifr.ifr_map.dma, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.dma)); + err |= __get_user(ifr.ifr_map.port, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.port)); + if (err) return -EFAULT; break; case SIOCGPPPSTATS: case SIOCGPPPCSTATS: case SIOCGPPPVER: - if (copy_from_user(&ifr, (struct ifreq32 *)A(arg), sizeof(struct ifreq32))) + if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32))) return -EFAULT; ifr.ifr_data = (__kernel_caddr_t)get_free_page(GFP_KERNEL); if (!ifr.ifr_data) return -EAGAIN; break; default: - if (copy_from_user(&ifr, (struct ifreq32 *)A(arg), sizeof(struct ifreq32))) + if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32))) return -EFAULT; break; } @@ -255,7 +259,7 @@ case SIOCGIFBRDADDR: case SIOCGIFDSTADDR: case SIOCGIFNETMASK: - if (copy_to_user((struct ifreq32 *)A(arg), &ifr, sizeof(struct ifreq32))) + if (copy_to_user((struct ifreq32 *)arg, &ifr, sizeof(struct ifreq32))) return -EFAULT; break; case SIOCGPPPSTATS: @@ -265,7 +269,7 @@ u32 data; int len; - __get_user(data, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_data)); + __get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data)); if(cmd == SIOCGPPPVER) len = strlen(PPP_VERSION) + 1; else if(cmd == SIOCGPPPCSTATS) @@ -278,14 +282,13 @@ break; } case SIOCGIFMAP: - if (copy_to_user((struct ifreq32 *)A(arg), &ifr, sizeof(ifr.ifr_name)) || - __put_user(ifr.ifr_map.mem_start, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.mem_start)) || - __put_user(ifr.ifr_map.mem_end, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.mem_end)) || - __put_user(ifr.ifr_map.base_addr, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.base_addr)) || - __put_user(ifr.ifr_map.irq, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.irq)) || - __put_user(ifr.ifr_map.dma, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.dma)) || - __put_user(ifr.ifr_map.port, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.port))) - return -EFAULT; + err = copy_to_user((struct ifreq32 *)arg, &ifr, sizeof(ifr.ifr_name)); + err |= __put_user(ifr.ifr_map.mem_start, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_start)); + err |= __put_user(ifr.ifr_map.mem_end, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_end)); + err |= __put_user(ifr.ifr_map.base_addr, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.base_addr)); + err |= __put_user(ifr.ifr_map.irq, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.irq)); + err |= __put_user(ifr.ifr_map.dma, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.dma)); + err |= __put_user(ifr.ifr_map.port, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.port)); break; } } @@ -311,7 +314,7 @@ }; -static inline int routing_ioctl(unsigned int fd, unsigned int cmd, u32 arg) +static inline int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) { struct rtentry r; char devname[16]; @@ -319,19 +322,20 @@ int ret; mm_segment_t old_fs = get_fs(); - if (copy_from_user (&r.rt_dst, &(((struct rtentry32 *)A(arg))->rt_dst), 3 * sizeof(struct sockaddr)) || - __get_user (r.rt_flags, &(((struct rtentry32 *)A(arg))->rt_flags)) || - __get_user (r.rt_metric, &(((struct rtentry32 *)A(arg))->rt_metric)) || - __get_user (r.rt_mtu, &(((struct rtentry32 *)A(arg))->rt_mtu)) || - __get_user (r.rt_window, &(((struct rtentry32 *)A(arg))->rt_window)) || - __get_user (r.rt_irtt, &(((struct rtentry32 *)A(arg))->rt_irtt)) || - __get_user (rtdev, &(((struct rtentry32 *)A(arg))->rt_dev)) || - (rtdev && copy_from_user (devname, (char *)A(rtdev), 15))) - return -EFAULT; + ret = copy_from_user (&r.rt_dst, &(((struct rtentry32 *)arg)->rt_dst), 3 * sizeof(struct sockaddr)); + ret |= __get_user (r.rt_flags, &(((struct rtentry32 *)arg)->rt_flags)); + ret |= __get_user (r.rt_metric, &(((struct rtentry32 *)arg)->rt_metric)); + ret |= __get_user (r.rt_mtu, &(((struct rtentry32 *)arg)->rt_mtu)); + ret |= __get_user (r.rt_window, &(((struct rtentry32 *)arg)->rt_window)); + ret |= __get_user (r.rt_irtt, &(((struct rtentry32 *)arg)->rt_irtt)); + ret |= __get_user (rtdev, &(((struct rtentry32 *)arg)->rt_dev)); if (rtdev) { + ret |= copy_from_user (devname, (char *)A(rtdev), 15); r.rt_dev = devname; devname[15] = 0; } else r.rt_dev = 0; + if (ret) + return -EFAULT; set_fs (KERNEL_DS); ret = sys_ioctl (fd, cmd, (long)&r); set_fs (old_fs); @@ -345,7 +349,7 @@ u32 start; }; -static inline int hdio_getgeo(unsigned int fd, u32 arg) +static inline int hdio_getgeo(unsigned int fd, unsigned long arg) { mm_segment_t old_fs = get_fs(); struct hd_geometry geo; @@ -355,9 +359,8 @@ err = sys_ioctl(fd, HDIO_GETGEO, (unsigned long)&geo); set_fs (old_fs); if (!err) { - if (copy_to_user ((struct hd_geometry32 *)A(arg), &geo, 4) || - __put_user (geo.start, &(((struct hd_geometry32 *)A(arg))->start))) - return -EFAULT; + err = copy_to_user ((struct hd_geometry32 *)arg, &geo, 4); + err |= __put_user (geo.start, &(((struct hd_geometry32 *)arg)->start)); } return err; } @@ -373,7 +376,7 @@ #define FBIOPUTCMAP32 _IOW('F', 3, struct fbcmap32) #define FBIOGETCMAP32 _IOW('F', 4, struct fbcmap32) -static inline int fbiogetputcmap(unsigned int fd, unsigned int cmd, u32 arg) +static inline int fbiogetputcmap(unsigned int fd, unsigned int cmd, unsigned long arg) { struct fbcmap f; int ret; @@ -381,19 +384,21 @@ u32 r, g, b; mm_segment_t old_fs = get_fs(); - if (get_user(f.index, &(((struct fbcmap32 *)A(arg))->index)) || - __get_user(f.count, &(((struct fbcmap32 *)A(arg))->count)) || - __get_user(r, &(((struct fbcmap32 *)A(arg))->red)) || - __get_user(g, &(((struct fbcmap32 *)A(arg))->green)) || - __get_user(b, &(((struct fbcmap32 *)A(arg))->blue))) + ret = get_user(f.index, &(((struct fbcmap32 *)arg)->index)); + ret |= __get_user(f.count, &(((struct fbcmap32 *)arg)->count)); + ret |= __get_user(r, &(((struct fbcmap32 *)arg)->red)); + ret |= __get_user(g, &(((struct fbcmap32 *)arg)->green)); + ret |= __get_user(b, &(((struct fbcmap32 *)arg)->blue)); + if (ret) return -EFAULT; if ((f.index < 0) || (f.index > 255)) return -EINVAL; if (f.index + f.count > 256) f.count = 256 - f.index; if (cmd == FBIOPUTCMAP32) { - if (copy_from_user (red, (char *)A(r), f.count) || - copy_from_user (green, (char *)A(g), f.count) || - copy_from_user (blue, (char *)A(b), f.count)) + ret = copy_from_user (red, (char *)A(r), f.count); + ret |= copy_from_user (green, (char *)A(g), f.count); + ret |= copy_from_user (blue, (char *)A(b), f.count); + if (ret) return -EFAULT; } f.red = red; f.green = green; f.blue = blue; @@ -401,10 +406,9 @@ ret = sys_ioctl (fd, (cmd == FBIOPUTCMAP32) ? FBIOPUTCMAP_SPARC : FBIOGETCMAP_SPARC, (long)&f); set_fs (old_fs); if (!ret && cmd == FBIOGETCMAP32) { - if (copy_to_user ((char *)A(r), red, f.count) || - copy_to_user ((char *)A(g), green, f.count) || - copy_to_user ((char *)A(b), blue, f.count)) - return -EFAULT; + ret = copy_to_user ((char *)A(r), red, f.count); + ret |= copy_to_user ((char *)A(g), green, f.count); + ret |= copy_to_user ((char *)A(b), blue, f.count); } return ret; } @@ -423,7 +427,7 @@ #define FBIOSCURSOR32 _IOW('F', 24, struct fbcursor32) #define FBIOGCURSOR32 _IOW('F', 25, struct fbcursor32) -static inline int fbiogscursor(unsigned int fd, unsigned int cmd, u32 arg) +static inline int fbiogscursor(unsigned int fd, unsigned int cmd, unsigned long arg) { struct fbcursor f; int ret; @@ -433,29 +437,32 @@ u32 m, i; mm_segment_t old_fs = get_fs(); - if (copy_from_user (&f, (struct fbcursor32 *)A(arg), 2 * sizeof (short) + 2 * sizeof(struct fbcurpos)) || - __get_user(f.size.fbx, &(((struct fbcursor32 *)A(arg))->size.fbx)) || - __get_user(f.size.fby, &(((struct fbcursor32 *)A(arg))->size.fby)) || - __get_user(f.cmap.index, &(((struct fbcursor32 *)A(arg))->cmap.index)) || - __get_user(f.cmap.count, &(((struct fbcursor32 *)A(arg))->cmap.count)) || - __get_user(r, &(((struct fbcursor32 *)A(arg))->cmap.red)) || - __get_user(g, &(((struct fbcursor32 *)A(arg))->cmap.green)) || - __get_user(b, &(((struct fbcursor32 *)A(arg))->cmap.blue)) || - __get_user(m, &(((struct fbcursor32 *)A(arg))->mask)) || - __get_user(i, &(((struct fbcursor32 *)A(arg))->image))) + ret = copy_from_user (&f, (struct fbcursor32 *)arg, 2 * sizeof (short) + 2 * sizeof(struct fbcurpos)); + ret |= __get_user(f.size.fbx, &(((struct fbcursor32 *)arg)->size.fbx)); + ret |= __get_user(f.size.fby, &(((struct fbcursor32 *)arg)->size.fby)); + ret |= __get_user(f.cmap.index, &(((struct fbcursor32 *)arg)->cmap.index)); + ret |= __get_user(f.cmap.count, &(((struct fbcursor32 *)arg)->cmap.count)); + ret |= __get_user(r, &(((struct fbcursor32 *)arg)->cmap.red)); + ret |= __get_user(g, &(((struct fbcursor32 *)arg)->cmap.green)); + ret |= __get_user(b, &(((struct fbcursor32 *)arg)->cmap.blue)); + ret |= __get_user(m, &(((struct fbcursor32 *)arg)->mask)); + ret |= __get_user(i, &(((struct fbcursor32 *)arg)->image)); + if (ret) return -EFAULT; if (f.set & FB_CUR_SETCMAP) { if ((uint) f.size.fby > 32) return -EINVAL; - if (copy_from_user (mask, (char *)A(m), f.size.fby * 4) || - copy_from_user (image, (char *)A(i), f.size.fby * 4)) + ret = copy_from_user (mask, (char *)A(m), f.size.fby * 4); + ret |= copy_from_user (image, (char *)A(i), f.size.fby * 4); + if (ret) return -EFAULT; f.image = image; f.mask = mask; } if (f.set & FB_CUR_SETCMAP) { - if (copy_from_user (red, (char *)A(r), 2) || - copy_from_user (green, (char *)A(g), 2) || - copy_from_user (blue, (char *)A(b), 2)) + ret = copy_from_user (red, (char *)A(r), 2); + ret |= copy_from_user (green, (char *)A(g), 2); + ret |= copy_from_user (blue, (char *)A(b), 2); + if (ret) return -EFAULT; f.cmap.red = red; f.cmap.green = green; f.cmap.blue = blue; } @@ -491,7 +498,7 @@ __kernel_caddr_t32 transp; }; -static int fb_ioctl_trans(unsigned int fd, unsigned int cmd, u32 arg) +static int fb_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) { mm_segment_t old_fs = get_fs(); u32 red = 0, green = 0, blue = 0, transp = 0; @@ -500,6 +507,7 @@ void *karg; int err = 0; + memset(&cmap, 0, sizeof(cmap)); switch (cmd) { case FBIOGET_FSCREENINFO: karg = &fix; @@ -507,120 +515,91 @@ case FBIOGETCMAP: case FBIOPUTCMAP: karg = &cmap; - if (__get_user(cmap.start, &((struct fb_cmap32 *)A(arg))->start) || - __get_user(cmap.len, &((struct fb_cmap32 *)A(arg))->len) || - __get_user(red, &((struct fb_cmap32 *)A(arg))->red) || - __get_user(green, &((struct fb_cmap32 *)A(arg))->green) || - __get_user(blue, &((struct fb_cmap32 *)A(arg))->blue) || - __get_user(transp, &((struct fb_cmap32 *)A(arg))->transp)) - return -EFAULT; + err = __get_user(cmap.start, &((struct fb_cmap32 *)arg)->start); + err |= __get_user(cmap.len, &((struct fb_cmap32 *)arg)->len); + err |= __get_user(red, &((struct fb_cmap32 *)arg)->red); + err |= __get_user(green, &((struct fb_cmap32 *)arg)->green); + err |= __get_user(blue, &((struct fb_cmap32 *)arg)->blue); + err |= __get_user(transp, &((struct fb_cmap32 *)arg)->transp); + if (err) + goto out; + err = -ENOMEM; cmap.red = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL); if (!cmap.red) - return -ENOMEM; + goto out; cmap.green = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL); - if (!cmap.green) { - kfree(cmap.red); - return -ENOMEM; - } + if (!cmap.green) + goto out; cmap.blue = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL); - if (!cmap.blue) { - kfree(cmap.red); - kfree(cmap.green); - return -ENOMEM; - } + if (!cmap.blue) + goto out; if (transp) { cmap.transp = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL); - if (!cmap.transp) { - kfree(cmap.red); - kfree(cmap.green); - kfree(cmap.blue); - return -ENOMEM; - } - } else { + if (!cmap.transp) + goto out; + } else cmap.transp = NULL; - } + if (cmd == FBIOGETCMAP) break; - if (__copy_from_user(cmap.red, (char *)A(((struct fb_cmap32 *)A(arg))->red), - cmap.len * sizeof(__u16)) || - __copy_from_user(cmap.green, (char *)A(((struct fb_cmap32 *)A(arg))->green), - cmap.len * sizeof(__u16)) || - __copy_from_user(cmap.blue, (char *)A(((struct fb_cmap32 *)A(arg))->blue), - cmap.len * sizeof(__u16)) || - (cmap.transp && - __copy_from_user(cmap.transp, (char *)A(((struct fb_cmap32 *)A(arg))->transp), - cmap.len * sizeof(__u16)))) { - kfree(cmap.red); - kfree(cmap.green); - kfree(cmap.blue); - if (cmap.transp) - kfree(cmap.transp); - return -EFAULT; - } + err = __copy_from_user(cmap.red, (char *)A(red), cmap.len * sizeof(__u16)); + err |= __copy_from_user(cmap.green, (char *)A(green), cmap.len * sizeof(__u16)); + err |= __copy_from_user(cmap.blue, (char *)A(blue), cmap.len * sizeof(__u16)); + if (cmap.transp) err |= __copy_from_user(cmap.transp, (char *)A(transp), cmap.len * sizeof(__u16)); + if (err) + goto out; break; default: - printk("%s: Unknown fb ioctl cmd fd(%d) cmd(%08x) arg(%08x)\n", - __FUNCTION__, fd, cmd, arg); + do { + static int count = 0; + if (++count <= 20) + printk("%s: Unknown fb ioctl cmd fd(%d) " + "cmd(%08x) arg(%08lx)\n", + __FUNCTION__, fd, cmd, arg); + } while(0); return -ENOSYS; } set_fs(KERNEL_DS); err = sys_ioctl(fd, cmd, (unsigned long)karg); set_fs(old_fs); if (err) - return err; + goto out; switch (cmd) { case FBIOGET_FSCREENINFO: - if (__copy_to_user((char *)((struct fb_fix_screeninfo32 *)A(arg))->id, - (char *)fix.id, sizeof(fix.id)) || - __put_user((__u32)(unsigned long)fix.smem_start, - &((struct fb_fix_screeninfo32 *)A(arg))->smem_start) || - __put_user(fix.smem_len, &((struct fb_fix_screeninfo32 *)A(arg))->smem_len) || - __put_user(fix.type, &((struct fb_fix_screeninfo32 *)A(arg))->type) || - __put_user(fix.type_aux, &((struct fb_fix_screeninfo32 *)A(arg))->type_aux) || - __put_user(fix.visual, &((struct fb_fix_screeninfo32 *)A(arg))->visual) || - __put_user(fix.xpanstep, &((struct fb_fix_screeninfo32 *)A(arg))->xpanstep) || - __put_user(fix.ypanstep, &((struct fb_fix_screeninfo32 *)A(arg))->ypanstep) || - __put_user(fix.ywrapstep, &((struct fb_fix_screeninfo32 *)A(arg))->ywrapstep) || - __put_user(fix.line_length, &((struct fb_fix_screeninfo32 *)A(arg))->line_length) || - __put_user((__u32)(unsigned long)fix.mmio_start, - &((struct fb_fix_screeninfo32 *)A(arg))->mmio_start) || - __put_user(fix.mmio_len, &((struct fb_fix_screeninfo32 *)A(arg))->mmio_len) || - __put_user(fix.accel, &((struct fb_fix_screeninfo32 *)A(arg))->accel) || - __copy_to_user((char *)((struct fb_fix_screeninfo32 *)A(arg))->reserved, - (char *)fix.reserved, sizeof(fix.reserved))) - return -EFAULT; + err = __copy_to_user((char *)((struct fb_fix_screeninfo32 *)arg)->id, (char *)fix.id, sizeof(fix.id)); + err |= __put_user((__u32)(unsigned long)fix.smem_start, &((struct fb_fix_screeninfo32 *)arg)->smem_start); + err |= __put_user(fix.smem_len, &((struct fb_fix_screeninfo32 *)arg)->smem_len); + err |= __put_user(fix.type, &((struct fb_fix_screeninfo32 *)arg)->type); + err |= __put_user(fix.type_aux, &((struct fb_fix_screeninfo32 *)arg)->type_aux); + err |= __put_user(fix.visual, &((struct fb_fix_screeninfo32 *)arg)->visual); + err |= __put_user(fix.xpanstep, &((struct fb_fix_screeninfo32 *)arg)->xpanstep); + err |= __put_user(fix.ypanstep, &((struct fb_fix_screeninfo32 *)arg)->ypanstep); + err |= __put_user(fix.ywrapstep, &((struct fb_fix_screeninfo32 *)arg)->ywrapstep); + err |= __put_user(fix.line_length, &((struct fb_fix_screeninfo32 *)arg)->line_length); + err |= __put_user((__u32)(unsigned long)fix.mmio_start, &((struct fb_fix_screeninfo32 *)arg)->mmio_start); + err |= __put_user(fix.mmio_len, &((struct fb_fix_screeninfo32 *)arg)->mmio_len); + err |= __put_user(fix.accel, &((struct fb_fix_screeninfo32 *)arg)->accel); + err |= __copy_to_user((char *)((struct fb_fix_screeninfo32 *)arg)->reserved, (char *)fix.reserved, sizeof(fix.reserved)); break; case FBIOGETCMAP: - if (__copy_to_user((char *)A(((struct fb_cmap32 *)A(arg))->red), cmap.red, - cmap.len * sizeof(__u16)) || - __copy_to_user((char *)A(((struct fb_cmap32 *)A(arg))->green), cmap.blue, - cmap.len * sizeof(__u16)) || - __copy_to_user((char *)A(((struct fb_cmap32 *)A(arg))->blue), cmap.blue, - cmap.len * sizeof(__u16)) || - (cmap.transp && - __copy_to_user((char *)A(((struct fb_cmap32 *)A(arg))->transp), cmap.transp, - cmap.len * sizeof(__u16)))) { - kfree(cmap.red); - kfree(cmap.green); - kfree(cmap.blue); - if (cmap.transp) - kfree(cmap.transp); - return -EFAULT; - } - /* fall through */ - case FBIOPUTCMAP: - kfree(cmap.red); - kfree(cmap.green); - kfree(cmap.blue); + err = __copy_to_user((char *)A(red), cmap.red, cmap.len * sizeof(__u16)); + err |= __copy_to_user((char *)A(green), cmap.blue, cmap.len * sizeof(__u16)); + err |= __copy_to_user((char *)A(blue), cmap.blue, cmap.len * sizeof(__u16)); if (cmap.transp) - kfree(cmap.transp); + err |= __copy_to_user((char *)A(transp), cmap.transp, cmap.len * sizeof(__u16)); + break; + case FBIOPUTCMAP: break; } - return 0; +out: if (cmap.red) kfree(cmap.red); + if (cmap.green) kfree(cmap.green); + if (cmap.blue) kfree(cmap.blue); + if (cmap.transp) kfree(cmap.transp); + return err; } -static int hdio_ioctl_trans(unsigned int fd, unsigned int cmd, u32 arg) +static int hdio_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) { mm_segment_t old_fs = get_fs(); unsigned long kval; @@ -632,7 +611,7 @@ set_fs(old_fs); if(error == 0) { - uvp = (unsigned int *)A(arg); + uvp = (unsigned int *)arg; if(put_user(kval, uvp)) error = -EFAULT; } @@ -744,10 +723,10 @@ #define NR_FD_IOCTL_TRANS (sizeof(fd_ioctl_trans_table)/sizeof(fd_ioctl_trans_table[0])) -static int fd_ioctl_trans(unsigned int fd, unsigned int cmd, u32 arg) +static int fd_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) { mm_segment_t old_fs = get_fs(); - void *karg; + void *karg = NULL; unsigned int kcmd = 0; int i, err; @@ -771,19 +750,18 @@ return -ENOMEM; if (cmd == FDGETPRM32) break; - if (__get_user(f->size, &((struct floppy_struct32 *)A(arg))->size) || - __get_user(f->sect, &((struct floppy_struct32 *)A(arg))->sect) || - __get_user(f->head, &((struct floppy_struct32 *)A(arg))->head) || - __get_user(f->track, &((struct floppy_struct32 *)A(arg))->track) || - __get_user(f->stretch, &((struct floppy_struct32 *)A(arg))->stretch) || - __get_user(f->gap, &((struct floppy_struct32 *)A(arg))->gap) || - __get_user(f->rate, &((struct floppy_struct32 *)A(arg))->rate) || - __get_user(f->spec1, &((struct floppy_struct32 *)A(arg))->spec1) || - __get_user(f->fmt_gap, &((struct floppy_struct32 *)A(arg))->fmt_gap) || - __get_user((u64)f->name, &((struct floppy_struct32 *)A(arg))->name)) { - kfree(karg); - return -EFAULT; - } + err = __get_user(f->size, &((struct floppy_struct32 *)arg)->size); + err |= __get_user(f->sect, &((struct floppy_struct32 *)arg)->sect); + err |= __get_user(f->head, &((struct floppy_struct32 *)arg)->head); + err |= __get_user(f->track, &((struct floppy_struct32 *)arg)->track); + err |= __get_user(f->stretch, &((struct floppy_struct32 *)arg)->stretch); + err |= __get_user(f->gap, &((struct floppy_struct32 *)arg)->gap); + err |= __get_user(f->rate, &((struct floppy_struct32 *)arg)->rate); + err |= __get_user(f->spec1, &((struct floppy_struct32 *)arg)->spec1); + err |= __get_user(f->fmt_gap, &((struct floppy_struct32 *)arg)->fmt_gap); + err |= __get_user((u64)f->name, &((struct floppy_struct32 *)arg)->name); + if (err) + goto out; break; } case FDSETDRVPRM32: @@ -796,28 +774,27 @@ return -ENOMEM; if (cmd == FDGETDRVPRM32) break; - if (__get_user(f->cmos, &((struct floppy_drive_params32 *)A(arg))->cmos) || - __get_user(f->max_dtr, &((struct floppy_drive_params32 *)A(arg))->max_dtr) || - __get_user(f->hlt, &((struct floppy_drive_params32 *)A(arg))->hlt) || - __get_user(f->hut, &((struct floppy_drive_params32 *)A(arg))->hut) || - __get_user(f->srt, &((struct floppy_drive_params32 *)A(arg))->srt) || - __get_user(f->spinup, &((struct floppy_drive_params32 *)A(arg))->spinup) || - __get_user(f->spindown, &((struct floppy_drive_params32 *)A(arg))->spindown) || - __get_user(f->spindown_offset, &((struct floppy_drive_params32 *)A(arg))->spindown_offset) || - __get_user(f->select_delay, &((struct floppy_drive_params32 *)A(arg))->select_delay) || - __get_user(f->rps, &((struct floppy_drive_params32 *)A(arg))->rps) || - __get_user(f->tracks, &((struct floppy_drive_params32 *)A(arg))->tracks) || - __get_user(f->timeout, &((struct floppy_drive_params32 *)A(arg))->timeout) || - __get_user(f->interleave_sect, &((struct floppy_drive_params32 *)A(arg))->interleave_sect) || - __copy_from_user(&f->max_errors, &((struct floppy_drive_params32 *)A(arg))->max_errors, sizeof(f->max_errors)) || - __get_user(f->flags, &((struct floppy_drive_params32 *)A(arg))->flags) || - __get_user(f->read_track, &((struct floppy_drive_params32 *)A(arg))->read_track) || - __copy_from_user(f->autodetect, ((struct floppy_drive_params32 *)A(arg))->autodetect, sizeof(f->autodetect)) || - __get_user(f->checkfreq, &((struct floppy_drive_params32 *)A(arg))->checkfreq) || - __get_user(f->native_format, &((struct floppy_drive_params32 *)A(arg))->native_format)) { - kfree(karg); - return -EFAULT; - } + err = __get_user(f->cmos, &((struct floppy_drive_params32 *)arg)->cmos); + err |= __get_user(f->max_dtr, &((struct floppy_drive_params32 *)arg)->max_dtr); + err |= __get_user(f->hlt, &((struct floppy_drive_params32 *)arg)->hlt); + err |= __get_user(f->hut, &((struct floppy_drive_params32 *)arg)->hut); + err |= __get_user(f->srt, &((struct floppy_drive_params32 *)arg)->srt); + err |= __get_user(f->spinup, &((struct floppy_drive_params32 *)arg)->spinup); + err |= __get_user(f->spindown, &((struct floppy_drive_params32 *)arg)->spindown); + err |= __get_user(f->spindown_offset, &((struct floppy_drive_params32 *)arg)->spindown_offset); + err |= __get_user(f->select_delay, &((struct floppy_drive_params32 *)arg)->select_delay); + err |= __get_user(f->rps, &((struct floppy_drive_params32 *)arg)->rps); + err |= __get_user(f->tracks, &((struct floppy_drive_params32 *)arg)->tracks); + err |= __get_user(f->timeout, &((struct floppy_drive_params32 *)arg)->timeout); + err |= __get_user(f->interleave_sect, &((struct floppy_drive_params32 *)arg)->interleave_sect); + err |= __copy_from_user(&f->max_errors, &((struct floppy_drive_params32 *)arg)->max_errors, sizeof(f->max_errors)); + err |= __get_user(f->flags, &((struct floppy_drive_params32 *)arg)->flags); + err |= __get_user(f->read_track, &((struct floppy_drive_params32 *)arg)->read_track); + err |= __copy_from_user(f->autodetect, ((struct floppy_drive_params32 *)arg)->autodetect, sizeof(f->autodetect)); + err |= __get_user(f->checkfreq, &((struct floppy_drive_params32 *)arg)->checkfreq); + err |= __get_user(f->native_format, &((struct floppy_drive_params32 *)arg)->native_format); + if (err) + goto out; break; } case FDGETDRVSTAT32: @@ -842,56 +819,48 @@ set_fs (KERNEL_DS); err = sys_ioctl (fd, kcmd, (unsigned long)karg); set_fs (old_fs); - if (err) { - kfree(karg); - return err; - } + if (err) + goto out; switch (cmd) { case FDGETPRM32: { struct floppy_struct *f = karg; - if (__put_user(f->size, &((struct floppy_struct32 *)A(arg))->size) || - __put_user(f->sect, &((struct floppy_struct32 *)A(arg))->sect) || - __put_user(f->head, &((struct floppy_struct32 *)A(arg))->head) || - __put_user(f->track, &((struct floppy_struct32 *)A(arg))->track) || - __put_user(f->stretch, &((struct floppy_struct32 *)A(arg))->stretch) || - __put_user(f->gap, &((struct floppy_struct32 *)A(arg))->gap) || - __put_user(f->rate, &((struct floppy_struct32 *)A(arg))->rate) || - __put_user(f->spec1, &((struct floppy_struct32 *)A(arg))->spec1) || - __put_user(f->fmt_gap, &((struct floppy_struct32 *)A(arg))->fmt_gap) || - __put_user((u64)f->name, &((struct floppy_struct32 *)A(arg))->name)) { - kfree(karg); - return -EFAULT; - } + err = __put_user(f->size, &((struct floppy_struct32 *)arg)->size); + err |= __put_user(f->sect, &((struct floppy_struct32 *)arg)->sect); + err |= __put_user(f->head, &((struct floppy_struct32 *)arg)->head); + err |= __put_user(f->track, &((struct floppy_struct32 *)arg)->track); + err |= __put_user(f->stretch, &((struct floppy_struct32 *)arg)->stretch); + err |= __put_user(f->gap, &((struct floppy_struct32 *)arg)->gap); + err |= __put_user(f->rate, &((struct floppy_struct32 *)arg)->rate); + err |= __put_user(f->spec1, &((struct floppy_struct32 *)arg)->spec1); + err |= __put_user(f->fmt_gap, &((struct floppy_struct32 *)arg)->fmt_gap); + err |= __put_user((u64)f->name, &((struct floppy_struct32 *)arg)->name); break; } case FDGETDRVPRM32: { struct floppy_drive_params *f = karg; - if (__put_user(f->cmos, &((struct floppy_drive_params32 *)A(arg))->cmos) || - __put_user(f->max_dtr, &((struct floppy_drive_params32 *)A(arg))->max_dtr) || - __put_user(f->hlt, &((struct floppy_drive_params32 *)A(arg))->hlt) || - __put_user(f->hut, &((struct floppy_drive_params32 *)A(arg))->hut) || - __put_user(f->srt, &((struct floppy_drive_params32 *)A(arg))->srt) || - __put_user(f->spinup, &((struct floppy_drive_params32 *)A(arg))->spinup) || - __put_user(f->spindown, &((struct floppy_drive_params32 *)A(arg))->spindown) || - __put_user(f->spindown_offset, &((struct floppy_drive_params32 *)A(arg))->spindown_offset) || - __put_user(f->select_delay, &((struct floppy_drive_params32 *)A(arg))->select_delay) || - __put_user(f->rps, &((struct floppy_drive_params32 *)A(arg))->rps) || - __put_user(f->tracks, &((struct floppy_drive_params32 *)A(arg))->tracks) || - __put_user(f->timeout, &((struct floppy_drive_params32 *)A(arg))->timeout) || - __put_user(f->interleave_sect, &((struct floppy_drive_params32 *)A(arg))->interleave_sect) || - __copy_to_user(&((struct floppy_drive_params32 *)A(arg))->max_errors, &f->max_errors, sizeof(f->max_errors)) || - __put_user(f->flags, &((struct floppy_drive_params32 *)A(arg))->flags) || - __put_user(f->read_track, &((struct floppy_drive_params32 *)A(arg))->read_track) || - __copy_to_user(((struct floppy_drive_params32 *)A(arg))->autodetect, f->autodetect, sizeof(f->autodetect)) || - __put_user(f->checkfreq, &((struct floppy_drive_params32 *)A(arg))->checkfreq) || - __put_user(f->native_format, &((struct floppy_drive_params32 *)A(arg))->native_format)) { - kfree(karg); - return -EFAULT; - } + err = __put_user(f->cmos, &((struct floppy_drive_params32 *)arg)->cmos); + err |= __put_user(f->max_dtr, &((struct floppy_drive_params32 *)arg)->max_dtr); + err |= __put_user(f->hlt, &((struct floppy_drive_params32 *)arg)->hlt); + err |= __put_user(f->hut, &((struct floppy_drive_params32 *)arg)->hut); + err |= __put_user(f->srt, &((struct floppy_drive_params32 *)arg)->srt); + err |= __put_user(f->spinup, &((struct floppy_drive_params32 *)arg)->spinup); + err |= __put_user(f->spindown, &((struct floppy_drive_params32 *)arg)->spindown); + err |= __put_user(f->spindown_offset, &((struct floppy_drive_params32 *)arg)->spindown_offset); + err |= __put_user(f->select_delay, &((struct floppy_drive_params32 *)arg)->select_delay); + err |= __put_user(f->rps, &((struct floppy_drive_params32 *)arg)->rps); + err |= __put_user(f->tracks, &((struct floppy_drive_params32 *)arg)->tracks); + err |= __put_user(f->timeout, &((struct floppy_drive_params32 *)arg)->timeout); + err |= __put_user(f->interleave_sect, &((struct floppy_drive_params32 *)arg)->interleave_sect); + err |= __copy_to_user(&((struct floppy_drive_params32 *)arg)->max_errors, &f->max_errors, sizeof(f->max_errors)); + err |= __put_user(f->flags, &((struct floppy_drive_params32 *)arg)->flags); + err |= __put_user(f->read_track, &((struct floppy_drive_params32 *)arg)->read_track); + err |= __copy_to_user(((struct floppy_drive_params32 *)arg)->autodetect, f->autodetect, sizeof(f->autodetect)); + err |= __put_user(f->checkfreq, &((struct floppy_drive_params32 *)arg)->checkfreq); + err |= __put_user(f->native_format, &((struct floppy_drive_params32 *)arg)->native_format); break; } case FDGETDRVSTAT32: @@ -899,66 +868,57 @@ { struct floppy_drive_struct *f = karg; - if (__put_user(f->flags, &((struct floppy_drive_struct32 *)A(arg))->flags) || - __put_user(f->spinup_date, &((struct floppy_drive_struct32 *)A(arg))->spinup_date) || - __put_user(f->select_date, &((struct floppy_drive_struct32 *)A(arg))->select_date) || - __put_user(f->first_read_date, &((struct floppy_drive_struct32 *)A(arg))->first_read_date) || - __put_user(f->probed_format, &((struct floppy_drive_struct32 *)A(arg))->probed_format) || - __put_user(f->track, &((struct floppy_drive_struct32 *)A(arg))->track) || - __put_user(f->maxblock, &((struct floppy_drive_struct32 *)A(arg))->maxblock) || - __put_user(f->maxtrack, &((struct floppy_drive_struct32 *)A(arg))->maxtrack) || - __put_user(f->generation, &((struct floppy_drive_struct32 *)A(arg))->generation) || - __put_user(f->keep_data, &((struct floppy_drive_struct32 *)A(arg))->keep_data) || - __put_user(f->fd_ref, &((struct floppy_drive_struct32 *)A(arg))->fd_ref) || - __put_user(f->fd_device, &((struct floppy_drive_struct32 *)A(arg))->fd_device) || - __put_user(f->last_checked, &((struct floppy_drive_struct32 *)A(arg))->last_checked) || - __put_user((u64)f->dmabuf, &((struct floppy_drive_struct32 *)A(arg))->dmabuf) || - __put_user((u64)f->bufblocks, &((struct floppy_drive_struct32 *)A(arg))->bufblocks)) { - kfree(karg); - return -EFAULT; - } + err = __put_user(f->flags, &((struct floppy_drive_struct32 *)arg)->flags); + err |= __put_user(f->spinup_date, &((struct floppy_drive_struct32 *)arg)->spinup_date); + err |= __put_user(f->select_date, &((struct floppy_drive_struct32 *)arg)->select_date); + err |= __put_user(f->first_read_date, &((struct floppy_drive_struct32 *)arg)->first_read_date); + err |= __put_user(f->probed_format, &((struct floppy_drive_struct32 *)arg)->probed_format); + err |= __put_user(f->track, &((struct floppy_drive_struct32 *)arg)->track); + err |= __put_user(f->maxblock, &((struct floppy_drive_struct32 *)arg)->maxblock); + err |= __put_user(f->maxtrack, &((struct floppy_drive_struct32 *)arg)->maxtrack); + err |= __put_user(f->generation, &((struct floppy_drive_struct32 *)arg)->generation); + err |= __put_user(f->keep_data, &((struct floppy_drive_struct32 *)arg)->keep_data); + err |= __put_user(f->fd_ref, &((struct floppy_drive_struct32 *)arg)->fd_ref); + err |= __put_user(f->fd_device, &((struct floppy_drive_struct32 *)arg)->fd_device); + err |= __put_user(f->last_checked, &((struct floppy_drive_struct32 *)arg)->last_checked); + err |= __put_user((u64)f->dmabuf, &((struct floppy_drive_struct32 *)arg)->dmabuf); + err |= __put_user((u64)f->bufblocks, &((struct floppy_drive_struct32 *)arg)->bufblocks); break; } case FDGETFDCSTAT32: { struct floppy_fdc_state *f = karg; - if (__put_user(f->spec1, &((struct floppy_fdc_state32 *)A(arg))->spec1) || - __put_user(f->spec2, &((struct floppy_fdc_state32 *)A(arg))->spec2) || - __put_user(f->dtr, &((struct floppy_fdc_state32 *)A(arg))->dtr) || - __put_user(f->version, &((struct floppy_fdc_state32 *)A(arg))->version) || - __put_user(f->dor, &((struct floppy_fdc_state32 *)A(arg))->dor) || - __put_user(f->address, &((struct floppy_fdc_state32 *)A(arg))->address) || - __copy_to_user((char *)&((struct floppy_fdc_state32 *)A(arg))->address - + sizeof(((struct floppy_fdc_state32 *)A(arg))->address), - (char *)&f->address + sizeof(f->address), sizeof(int)) || - __put_user(f->driver_version, &((struct floppy_fdc_state32 *)A(arg))->driver_version) || - __copy_to_user(((struct floppy_fdc_state32 *)A(arg))->track, f->track, sizeof(f->track))) { - kfree(karg); - return -EFAULT; - } + err = __put_user(f->spec1, &((struct floppy_fdc_state32 *)arg)->spec1); + err |= __put_user(f->spec2, &((struct floppy_fdc_state32 *)arg)->spec2); + err |= __put_user(f->dtr, &((struct floppy_fdc_state32 *)arg)->dtr); + err |= __put_user(f->version, &((struct floppy_fdc_state32 *)arg)->version); + err |= __put_user(f->dor, &((struct floppy_fdc_state32 *)arg)->dor); + err |= __put_user(f->address, &((struct floppy_fdc_state32 *)arg)->address); + err |= __copy_to_user((char *)&((struct floppy_fdc_state32 *)arg)->address + + sizeof(((struct floppy_fdc_state32 *)arg)->address), + (char *)&f->address + sizeof(f->address), sizeof(int)); + err |= __put_user(f->driver_version, &((struct floppy_fdc_state32 *)arg)->driver_version); + err |= __copy_to_user(((struct floppy_fdc_state32 *)arg)->track, f->track, sizeof(f->track)); break; } case FDWERRORGET32: { struct floppy_write_errors *f = karg; - if (__put_user(f->write_errors, &((struct floppy_write_errors32 *)A(arg))->write_errors) || - __put_user(f->first_error_sector, &((struct floppy_write_errors32 *)A(arg))->first_error_sector) || - __put_user(f->first_error_generation, &((struct floppy_write_errors32 *)A(arg))->first_error_generation) || - __put_user(f->last_error_sector, &((struct floppy_write_errors32 *)A(arg))->last_error_sector) || - __put_user(f->last_error_generation, &((struct floppy_write_errors32 *)A(arg))->last_error_generation) || - __put_user(f->badness, &((struct floppy_write_errors32 *)A(arg))->badness)) { - kfree(karg); - return -EFAULT; - } + err = __put_user(f->write_errors, &((struct floppy_write_errors32 *)arg)->write_errors); + err |= __put_user(f->first_error_sector, &((struct floppy_write_errors32 *)arg)->first_error_sector); + err |= __put_user(f->first_error_generation, &((struct floppy_write_errors32 *)arg)->first_error_generation); + err |= __put_user(f->last_error_sector, &((struct floppy_write_errors32 *)arg)->last_error_sector); + err |= __put_user(f->last_error_generation, &((struct floppy_write_errors32 *)arg)->last_error_generation); + err |= __put_user(f->badness, &((struct floppy_write_errors32 *)arg)->badness); break; } default: break; } - kfree(karg); - return 0; +out: if (karg) kfree(karg); + return err; } struct ppp_option_data32 { @@ -974,7 +934,7 @@ }; #define PPPIOCGIDLE32 _IOR('t', 63, struct ppp_idle32) -static int ppp_ioctl_trans(unsigned int fd, unsigned int cmd, u32 arg) +static int ppp_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) { mm_segment_t old_fs = get_fs(); struct ppp_option_data32 data32; @@ -991,7 +951,7 @@ karg = &idle; break; case PPPIOCSCOMPRESS32: - if (copy_from_user(&data32, (struct ppp_option_data32 *)A(arg), sizeof(struct ppp_option_data32))) + if (copy_from_user(&data32, (struct ppp_option_data32 *)arg, sizeof(struct ppp_option_data32))) return -EFAULT; data.ptr = kmalloc (data32.length, GFP_KERNEL); if (!data.ptr) @@ -1006,8 +966,13 @@ karg = &data; break; default: - printk("ppp_ioctl: Unknown cmd fd(%d) cmd(%08x) arg(%08x)\n", - (int)fd, (unsigned int)cmd, (unsigned int)arg); + do { + static int count = 0; + if (++count <= 20) + printk("ppp_ioctl: Unknown cmd fd(%d) " + "cmd(%08x) arg(%08x)\n", + (int)fd, (unsigned int)cmd, (unsigned int)arg); + } while(0); return -EINVAL; } set_fs (KERNEL_DS); @@ -1019,7 +984,7 @@ return err; idle32.xmit_idle = idle.xmit_idle; idle32.recv_idle = idle.recv_idle; - if (copy_to_user((struct ppp_idle32 *)A(arg), &idle32, sizeof(struct ppp_idle32))) + if (copy_to_user((struct ppp_idle32 *)arg, &idle32, sizeof(struct ppp_idle32))) return -EFAULT; break; case PPPIOCSCOMPRESS32: @@ -1072,7 +1037,7 @@ #define MTIOCGETCONFIG32 _IOR('m', 4, struct mtconfiginfo32) #define MTIOCSETCONFIG32 _IOW('m', 5, struct mtconfiginfo32) -static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, u32 arg) +static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) { mm_segment_t old_fs = get_fs(); struct mtconfiginfo info; @@ -1098,21 +1063,26 @@ case MTIOCSETCONFIG32: kcmd = MTIOCSETCONFIG; karg = &info; - if (__get_user(info.mt_type, &((struct mtconfiginfo32 *)A(arg))->mt_type) || - __get_user(info.ifc_type, &((struct mtconfiginfo32 *)A(arg))->ifc_type) || - __get_user(info.irqnr, &((struct mtconfiginfo32 *)A(arg))->irqnr) || - __get_user(info.dmanr, &((struct mtconfiginfo32 *)A(arg))->dmanr) || - __get_user(info.port, &((struct mtconfiginfo32 *)A(arg))->port) || - __get_user(info.debug, &((struct mtconfiginfo32 *)A(arg))->debug) || - __copy_from_user((char *)&info.debug + sizeof(info.debug), - (char *)&((struct mtconfiginfo32 *)A(arg))->debug - + sizeof(((struct mtconfiginfo32 *)A(arg))->debug), - sizeof(__u32))) + err = __get_user(info.mt_type, &((struct mtconfiginfo32 *)arg)->mt_type); + err |= __get_user(info.ifc_type, &((struct mtconfiginfo32 *)arg)->ifc_type); + err |= __get_user(info.irqnr, &((struct mtconfiginfo32 *)arg)->irqnr); + err |= __get_user(info.dmanr, &((struct mtconfiginfo32 *)arg)->dmanr); + err |= __get_user(info.port, &((struct mtconfiginfo32 *)arg)->port); + err |= __get_user(info.debug, &((struct mtconfiginfo32 *)arg)->debug); + err |= __copy_from_user((char *)&info.debug + sizeof(info.debug), + (char *)&((struct mtconfiginfo32 *)arg)->debug + + sizeof(((struct mtconfiginfo32 *)arg)->debug), sizeof(__u32)); + if (err) return -EFAULT; break; default: - printk("mt_ioctl: Unknown cmd fd(%d) cmd(%08x) arg(%08x)\n", - (int)fd, (unsigned int)cmd, (unsigned int)arg); + do { + static int count = 0; + if (++count <= 20) + printk("mt_ioctl: Unknown cmd fd(%d) " + "cmd(%08x) arg(%08x)\n", + (int)fd, (unsigned int)cmd, (unsigned int)arg); + } while(0); return -EINVAL; } set_fs (KERNEL_DS); @@ -1122,35 +1092,33 @@ return err; switch (cmd) { case MTIOCPOS32: - if (__put_user(pos.mt_blkno, &((struct mtpos32 *)A(arg))->mt_blkno)) + if (__put_user(pos.mt_blkno, &((struct mtpos32 *)arg)->mt_blkno)) return -EFAULT; break; case MTIOCGET32: - if (__put_user(get.mt_type, &((struct mtget32 *)A(arg))->mt_type) || - __put_user(get.mt_resid, &((struct mtget32 *)A(arg))->mt_resid) || - __put_user(get.mt_dsreg, &((struct mtget32 *)A(arg))->mt_dsreg) || - __put_user(get.mt_gstat, &((struct mtget32 *)A(arg))->mt_gstat) || - __put_user(get.mt_erreg, &((struct mtget32 *)A(arg))->mt_erreg) || - __put_user(get.mt_fileno, &((struct mtget32 *)A(arg))->mt_fileno) || - __put_user(get.mt_blkno, &((struct mtget32 *)A(arg))->mt_blkno)) - return -EFAULT; + err = __put_user(get.mt_type, &((struct mtget32 *)arg)->mt_type); + err |= __put_user(get.mt_resid, &((struct mtget32 *)arg)->mt_resid); + err |= __put_user(get.mt_dsreg, &((struct mtget32 *)arg)->mt_dsreg); + err |= __put_user(get.mt_gstat, &((struct mtget32 *)arg)->mt_gstat); + err |= __put_user(get.mt_erreg, &((struct mtget32 *)arg)->mt_erreg); + err |= __put_user(get.mt_fileno, &((struct mtget32 *)arg)->mt_fileno); + err |= __put_user(get.mt_blkno, &((struct mtget32 *)arg)->mt_blkno); break; case MTIOCGETCONFIG32: - if (__put_user(info.mt_type, &((struct mtconfiginfo32 *)A(arg))->mt_type) || - __put_user(info.ifc_type, &((struct mtconfiginfo32 *)A(arg))->ifc_type) || - __put_user(info.irqnr, &((struct mtconfiginfo32 *)A(arg))->irqnr) || - __put_user(info.dmanr, &((struct mtconfiginfo32 *)A(arg))->dmanr) || - __put_user(info.port, &((struct mtconfiginfo32 *)A(arg))->port) || - __put_user(info.debug, &((struct mtconfiginfo32 *)A(arg))->debug) || - __copy_to_user((char *)&((struct mtconfiginfo32 *)A(arg))->debug - + sizeof(((struct mtconfiginfo32 *)A(arg))->debug), - (char *)&info.debug + sizeof(info.debug), sizeof(__u32))) - return -EFAULT; + err = __put_user(info.mt_type, &((struct mtconfiginfo32 *)arg)->mt_type); + err |= __put_user(info.ifc_type, &((struct mtconfiginfo32 *)arg)->ifc_type); + err |= __put_user(info.irqnr, &((struct mtconfiginfo32 *)arg)->irqnr); + err |= __put_user(info.dmanr, &((struct mtconfiginfo32 *)arg)->dmanr); + err |= __put_user(info.port, &((struct mtconfiginfo32 *)arg)->port); + err |= __put_user(info.debug, &((struct mtconfiginfo32 *)arg)->debug); + err |= __copy_to_user((char *)&((struct mtconfiginfo32 *)arg)->debug + + sizeof(((struct mtconfiginfo32 *)arg)->debug), + (char *)&info.debug + sizeof(info.debug), sizeof(__u32)); break; case MTIOCSETCONFIG32: break; } - return 0; + return err; } struct cdrom_read32 { @@ -1166,7 +1134,7 @@ __kernel_caddr_t32 buf; }; -static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, u32 arg) +static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) { mm_segment_t old_fs = get_fs(); struct cdrom_read cdread; @@ -1182,9 +1150,10 @@ case CDROMREADRAW: case CDROMREADCOOKED: karg = &cdread; - if (__get_user(cdread.cdread_lba, &((struct cdrom_read32 *)A(arg))->cdread_lba) || - __get_user(addr, &((struct cdrom_read32 *)A(arg))->cdread_bufaddr) || - __get_user(cdread.cdread_buflen, &((struct cdrom_read32 *)A(arg))->cdread_buflen)) + err = __get_user(cdread.cdread_lba, &((struct cdrom_read32 *)arg)->cdread_lba); + err |= __get_user(addr, &((struct cdrom_read32 *)arg)->cdread_bufaddr); + err |= __get_user(cdread.cdread_buflen, &((struct cdrom_read32 *)arg)->cdread_buflen); + if (err) return -EFAULT; data = kmalloc(cdread.cdread_buflen, GFP_KERNEL); if (!data) @@ -1193,10 +1162,11 @@ break; case CDROMREADAUDIO: karg = &cdreadaudio; - if (copy_from_user(&cdreadaudio.addr, &((struct cdrom_read_audio32 *)A(arg))->addr, sizeof(cdreadaudio.addr)) || - __get_user(cdreadaudio.addr_format, &((struct cdrom_read_audio32 *)A(arg))->addr_format) || - __get_user(cdreadaudio.nframes, &((struct cdrom_read_audio32 *)A(arg))->nframes) || - __get_user(addr, &((struct cdrom_read_audio32 *)A(arg))->buf)) + err = copy_from_user(&cdreadaudio.addr, &((struct cdrom_read_audio32 *)arg)->addr, sizeof(cdreadaudio.addr)); + err |= __get_user(cdreadaudio.addr_format, &((struct cdrom_read_audio32 *)arg)->addr_format); + err |= __get_user(cdreadaudio.nframes, &((struct cdrom_read_audio32 *)arg)->nframes); + err |= __get_user(addr, &((struct cdrom_read_audio32 *)arg)->buf); + if (err) return -EFAULT; data = kmalloc(cdreadaudio.nframes * 2352, GFP_KERNEL); if (!data) @@ -1204,38 +1174,35 @@ cdreadaudio.buf = data; break; default: - printk("cdrom_ioctl: Unknown cmd fd(%d) cmd(%08x) arg(%08x)\n", - (int)fd, (unsigned int)cmd, (unsigned int)arg); + do { + static int count = 0; + if (++count <= 20) + printk("cdrom_ioctl: Unknown cmd fd(%d) " + "cmd(%08x) arg(%08x)\n", + (int)fd, (unsigned int)cmd, (unsigned int)arg); + } while(0); return -EINVAL; } set_fs (KERNEL_DS); err = sys_ioctl (fd, cmd, (unsigned long)karg); set_fs (old_fs); - if (err) { - if (data) kfree(data); - return err; - } + if (err) + goto out; switch (cmd) { case CDROMREADMODE2: case CDROMREADMODE1: case CDROMREADRAW: case CDROMREADCOOKED: - if (copy_to_user((char *)A(addr), data, cdread.cdread_buflen)) { - kfree(data); - return -EFAULT; - } + err = copy_to_user((char *)A(addr), data, cdread.cdread_buflen); break; case CDROMREADAUDIO: - if (copy_to_user((char *)A(addr), data, cdreadaudio.nframes * 2352)) { - kfree(data); - return -EFAULT; - } + err = copy_to_user((char *)A(addr), data, cdreadaudio.nframes * 2352); break; default: break; } - if (data) kfree(data); - return 0; +out: if (data) kfree(data); + return err; } struct loop_info32 { @@ -1253,7 +1220,7 @@ char reserved[4]; }; -static int loop_status(unsigned int fd, unsigned int cmd, u32 arg) +static int loop_status(unsigned int fd, unsigned int cmd, unsigned long arg) { mm_segment_t old_fs = get_fs(); struct loop_info l; @@ -1261,12 +1228,13 @@ switch(cmd) { case LOOP_SET_STATUS: - if ((get_user(l.lo_number, &((struct loop_info32 *)A(arg))->lo_number) || - __get_user(l.lo_device, &((struct loop_info32 *)A(arg))->lo_device) || - __get_user(l.lo_inode, &((struct loop_info32 *)A(arg))->lo_inode) || - __get_user(l.lo_rdevice, &((struct loop_info32 *)A(arg))->lo_rdevice) || - __copy_from_user((char *)&l.lo_offset, (char *)&((struct loop_info32 *)A(arg))->lo_offset, - 8 + (unsigned long)l.lo_init - (unsigned long)&l.lo_offset))) + err = get_user(l.lo_number, &((struct loop_info32 *)arg)->lo_number); + err |= __get_user(l.lo_device, &((struct loop_info32 *)arg)->lo_device); + err |= __get_user(l.lo_inode, &((struct loop_info32 *)arg)->lo_inode); + err |= __get_user(l.lo_rdevice, &((struct loop_info32 *)arg)->lo_rdevice); + err |= __copy_from_user((char *)&l.lo_offset, (char *)&((struct loop_info32 *)arg)->lo_offset, + 8 + (unsigned long)l.lo_init - (unsigned long)&l.lo_offset); + if (err) return -EFAULT; set_fs (KERNEL_DS); err = sys_ioctl (fd, cmd, (unsigned long)&l); @@ -1276,14 +1244,14 @@ set_fs (KERNEL_DS); err = sys_ioctl (fd, cmd, (unsigned long)&l); set_fs (old_fs); - if (!err && - (put_user(l.lo_number, &((struct loop_info32 *)A(arg))->lo_number) || - __put_user(l.lo_device, &((struct loop_info32 *)A(arg))->lo_device) || - __put_user(l.lo_inode, &((struct loop_info32 *)A(arg))->lo_inode) || - __put_user(l.lo_rdevice, &((struct loop_info32 *)A(arg))->lo_rdevice) || - __copy_to_user((char *)&((struct loop_info32 *)A(arg))->lo_offset, - (char *)&l.lo_offset, (unsigned long)l.lo_init - (unsigned long)&l.lo_offset))) - err = -EFAULT; + if (!err) { + err = put_user(l.lo_number, &((struct loop_info32 *)arg)->lo_number); + err |= __put_user(l.lo_device, &((struct loop_info32 *)arg)->lo_device); + err |= __put_user(l.lo_inode, &((struct loop_info32 *)arg)->lo_inode); + err |= __put_user(l.lo_rdevice, &((struct loop_info32 *)arg)->lo_rdevice); + err |= __copy_to_user((char *)&((struct loop_info32 *)arg)->lo_offset, + (char *)&l.lo_offset, (unsigned long)l.lo_init - (unsigned long)&l.lo_offset); + } break; } return err; @@ -1422,7 +1390,7 @@ return 0; } -asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, u32 arg) +asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) { struct file * filp; int error = -EBADF; @@ -1433,7 +1401,7 @@ goto out; if (!filp->f_op || !filp->f_op->ioctl) { - error = sys_ioctl (fd, cmd, (unsigned long)arg); + error = sys_ioctl (fd, cmd, arg); goto out; } switch (cmd) { @@ -1535,7 +1503,7 @@ case FDPOLLDRVSTAT32: case FDGETFDCSTAT32: case FDWERRORGET32: - error = fd_ioctl_trans(fd, cmd, (unsigned long)arg); + error = fd_ioctl_trans(fd, cmd, arg); goto out; case PPPIOCGIDLE32: @@ -1570,16 +1538,16 @@ case PIO_FONTX: case GIO_FONTX: - error = do_fontx_ioctl(filp, cmd, (struct consolefontdesc32 *)A(arg)); + error = do_fontx_ioctl(filp, cmd, (struct consolefontdesc32 *)arg); goto out; case PIO_UNIMAP: case GIO_UNIMAP: - error = do_unimap_ioctl(filp, cmd, (struct unimapdesc32 *)A(arg)); + error = do_unimap_ioctl(filp, cmd, (struct unimapdesc32 *)arg); goto out; case KDFONTOP: - error = do_kdfontop_ioctl(filp, (struct console_font_op32 *)A(arg)); + error = do_kdfontop_ioctl(filp, (struct console_font_op32 *)arg); goto out; /* List here exlicitly which ioctl's are known to have @@ -1822,6 +1790,13 @@ case SIOCDRARP: case SIOCADDDLCI: case SIOCDELDLCI: + + /* SG stuff */ + case SG_SET_TIMEOUT: + case SG_GET_TIMEOUT: + case SG_EMULATED_HOST: + case SG_SET_TRANSFORM: + case SG_GET_TRANSFORM: /* PPP stuff */ case PPPIOCGFLAGS: @@ -1890,12 +1865,17 @@ case AUTOFS_IOC_PROTOVER: case AUTOFS_IOC_EXPIRE: - error = sys_ioctl (fd, cmd, (unsigned long)arg); + error = sys_ioctl (fd, cmd, arg); goto out; default: - printk("sys32_ioctl: Unknown cmd fd(%d) cmd(%08x) arg(%08x)\n", - (int)fd, (unsigned int)cmd, (unsigned int)arg); + do { + static int count = 0; + if (++count <= 20) + printk("sys32_ioctl: Unknown cmd fd(%d) " + "cmd(%08x) arg(%08x)\n", + (int)fd, (unsigned int)cmd, (unsigned int)arg); + } while(0); error = -EINVAL; break; } diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c --- v2.1.123/linux/arch/sparc64/kernel/process.c Thu Aug 6 14:06:30 1998 +++ linux/arch/sparc64/kernel/process.c Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.70 1998/08/04 20:49:15 davem Exp $ +/* $Id: process.c,v 1.75 1998/09/23 02:05:15 davem Exp $ * arch/sparc64/kernel/process.c * * Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu) @@ -407,14 +407,20 @@ * where we grab a new one. */ spin_lock(&scheduler_lock); - get_mmu_context(current); + current->mm->cpu_vm_mask = 0; + activate_context(current); + current->mm->cpu_vm_mask = (1UL<tss.flags & SPARC_FLAG_32BIT) - __asm__ __volatile__("stxa %%g0, [%0] %1" : : "r"(TSB_REG), "i"(ASI_DMMU)); + __asm__ __volatile__("stxa %%g0, [%0] %1" + : /* no outputs */ + : "r"(TSB_REG), "i"(ASI_DMMU)); + __cli(); current->tss.ctx = current->mm->context & 0x3ff; spitfire_set_secondary_context (current->tss.ctx); __asm__ __volatile__("flush %g6"); + __sti(); } /* It's a bit more tricky when 64-bit tasks are involved... */ @@ -592,7 +598,13 @@ */ void dump_thread(struct pt_regs * regs, struct user * dump) { -#if 0 +#if 1 + /* Only should be used for SunOS and ancient a.out + * SparcLinux binaries... Fixme some day when bored. + * But for now at least plug the security hole :-) + */ + memset(dump, 0, sizeof(struct user)); +#else unsigned long first_stack_page; dump->magic = SUNOS_CORE_MAGIC; dump->len = sizeof(struct user); @@ -616,13 +628,69 @@ #endif } +typedef struct { + union { + unsigned int pr_regs[32]; + unsigned long pr_dregs[16]; + } pr_fr; + unsigned int __unused; + unsigned int pr_fsr; + unsigned char pr_qcnt; + unsigned char pr_q_entrysize; + unsigned char pr_en; + unsigned int pr_q[64]; +} elf_fpregset_t32; + /* * fill in the fpu structure for a core dump. */ int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs) { - /* Currently we report that we couldn't dump the fpu structure */ - return 0; + unsigned long *kfpregs = (unsigned long *)(((char *)current) + AOFF_task_fpregs); + unsigned long fprs = current->tss.fpsaved[0]; + + if ((current->tss.flags & SPARC_FLAG_32BIT) != 0) { + elf_fpregset_t32 *fpregs32 = (elf_fpregset_t32 *)fpregs; + + if (fprs & FPRS_DL) + memcpy(&fpregs32->pr_fr.pr_regs[0], kfpregs, + sizeof(unsigned int) * 32); + else + memset(&fpregs32->pr_fr.pr_regs[0], 0, + sizeof(unsigned int) * 32); + fpregs32->pr_qcnt = 0; + fpregs32->pr_q_entrysize = 8; + memset(&fpregs32->pr_q[0], 0, + (sizeof(unsigned int) * 64)); + if (fprs & FPRS_FEF) { + fpregs32->pr_fsr = (unsigned int) current->tss.xfsr[0]; + fpregs32->pr_en = 1; + } else { + fpregs32->pr_fsr = 0; + fpregs32->pr_en = 0; + } + } else { + if(fprs & FPRS_DL) + memcpy(&fpregs->pr_regs[0], kfpregs, + sizeof(unsigned int) * 32); + else + memset(&fpregs->pr_regs[0], 0, + sizeof(unsigned int) * 32); + if(fprs & FPRS_DU) + memcpy(&fpregs->pr_regs[16], kfpregs+16, + sizeof(unsigned int) * 32); + else + memset(&fpregs->pr_regs[16], 0, + sizeof(unsigned int) * 32); + if(fprs & FPRS_FEF) { + fpregs->pr_fsr = current->tss.xfsr[0]; + fpregs->pr_gsr = current->tss.gsr[0]; + } else { + fpregs->pr_fsr = fpregs->pr_gsr = 0; + } + fpregs->pr_fprs = fprs; + } + return 1; } /* diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/psycho.c linux/arch/sparc64/kernel/psycho.c --- v2.1.123/linux/arch/sparc64/kernel/psycho.c Thu Aug 6 14:06:30 1998 +++ linux/arch/sparc64/kernel/psycho.c Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -/* $Id: psycho.c,v 1.63 1998/08/02 05:55:42 ecd Exp $ +/* $Id: psycho.c,v 1.64 1998/09/01 07:24:24 jj Exp $ * psycho.c: Ultra/AX U2P PCI controller support. * * Copyright (C) 1997 David S. Miller (davem@caipfs.rutgers.edu) @@ -75,7 +75,6 @@ #include struct linux_psycho *psycho_root = NULL; -struct linux_psycho **psycho_index_map; int linux_num_psycho = 0; static struct linux_pbm_info *bus2pbm[256]; @@ -534,18 +533,6 @@ if(!node) break; } - - /* Last minute sanity check. */ - if(psycho_root == NULL && SBus_chain == NULL) { - prom_printf("Fatal error, neither SBUS nor PCI bus found.\n"); - prom_halt(); - } - - psycho_index_map = kmalloc(sizeof(struct linux_psycho *) * linux_num_psycho, - GFP_ATOMIC); - - for (psycho = psycho_root; psycho; psycho = psycho->next) - psycho_index_map[psycho->index] = psycho; } int pcibios_present(void) diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/rtrap.S linux/arch/sparc64/kernel/rtrap.S --- v2.1.123/linux/arch/sparc64/kernel/rtrap.S Thu Aug 6 14:06:30 1998 +++ linux/arch/sparc64/kernel/rtrap.S Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -/* $Id: rtrap.S,v 1.39 1998/07/26 03:02:49 davem Exp $ +/* $Id: rtrap.S,v 1.40 1998/09/23 02:05:18 davem Exp $ * rtrap.S: Preparing for return from trap on Sparc V9. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -144,7 +144,12 @@ call fault_in_user_windows add %sp, STACK_BIAS + REGWIN_SZ, %o0 -1: andcc %l1, %l6, %g0 +1: +#if 0 + call rtrap_check + add %sp, STACK_BIAS + REGWIN_SZ, %o0 +#endif + andcc %l1, %l6, %g0 be,pt %xcc, rt_continue stb %g0, [%g6 + AOFF_task_tss + AOFF_thread_fpdepth] ! This is neccessary for non-syscall rtraps only diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/setup.c linux/arch/sparc64/kernel/setup.c --- v2.1.123/linux/arch/sparc64/kernel/setup.c Thu Aug 6 14:06:30 1998 +++ linux/arch/sparc64/kernel/setup.c Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.30 1998/07/24 09:50:08 jj Exp $ +/* $Id: setup.c,v 1.32 1998/09/24 03:21:37 davem Exp $ * linux/arch/sparc64/kernel/setup.c * * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu) @@ -56,8 +56,6 @@ 16 /* orig-video-points */ }; -unsigned int phys_bytes_of_ram, end_of_phys_memory; - /* Typing sync at the prom prompt calls the function pointed to by * the sync callback which I set to the following function. * This should sync all filesystems and return, for now it just @@ -235,8 +233,8 @@ extern unsigned short root_flags; extern unsigned short root_dev; extern unsigned short ram_flags; -extern unsigned ramdisk_image; -extern unsigned ramdisk_size; +extern unsigned int ramdisk_image; +extern unsigned int ramdisk_size; #define RAMDISK_IMAGE_START_MASK 0x07FF #define RAMDISK_PROMPT_FLAG 0x8000 #define RAMDISK_LOAD_FLAG 0x4000 @@ -278,7 +276,7 @@ unsigned long * memory_start_p, unsigned long * memory_end_p)) { extern int serial_console; /* in console.c, of course */ - unsigned long lowest_paddr; + unsigned long lowest_paddr, end_of_phys_memory = 0; int total, i; #ifdef PROM_DEBUG_CONSOLE @@ -441,6 +439,8 @@ extern int smp_bogo(char *); extern int mmu_info(char *); +unsigned long dcache_aliases_found = 0; + int get_cpuinfo(char *buffer) { int cpuid=smp_processor_id(); @@ -454,6 +454,7 @@ "type\t\t: sun4u\n" "ncpus probed\t: %d\n" "ncpus active\t: %d\n" + "d-aliases\t: %lu\n" #ifndef __SMP__ "BogoMips\t: %lu.%02lu\n" #endif @@ -461,7 +462,7 @@ sparc_cpu_type[cpuid], sparc_fpu_type[cpuid], prom_rev, prom_prev >> 16, (prom_prev >> 8) & 0xff, prom_prev & 0xff, - linux_num_cpus, smp_num_cpus + linux_num_cpus, smp_num_cpus, dcache_aliases_found #ifndef __SMP__ , loops_per_sec/500000, (loops_per_sec/5000) % 100 #endif diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/signal.c linux/arch/sparc64/kernel/signal.c --- v2.1.123/linux/arch/sparc64/kernel/signal.c Thu Aug 6 14:06:31 1998 +++ linux/arch/sparc64/kernel/signal.c Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.30 1998/07/30 11:29:34 davem Exp $ +/* $Id: signal.c,v 1.37 1998/09/25 01:09:22 davem Exp $ * arch/sparc64/kernel/signal.c * * Copyright (C) 1991, 1992 Linus Torvalds @@ -39,6 +39,8 @@ /* This turned off for production... */ /* #define DEBUG_SIGNALS 1 */ +/* #define DEBUG_SIGNALS_TRACE 1 */ +/* #define DEBUG_SIGNALS_MAPS 1 */ /* {set, get}context() needed for 64-bit SparcLinux userland. */ asmlinkage void sparc64_set_context(struct pt_regs *regs) @@ -49,16 +51,17 @@ unsigned long pc, npc, tstate; unsigned long fp, i7; unsigned char fenab; + int err; __asm__ __volatile__("flushw"); if(tp->w_saved || (((unsigned long)ucp) & (sizeof(unsigned long)-1)) || (!__access_ok((unsigned long)ucp, sizeof(*ucp)))) goto do_sigsegv; - grp = &ucp->uc_mcontext.mc_gregs; - __get_user(pc, &((*grp)[MC_PC])); - __get_user(npc, &((*grp)[MC_NPC])); - if((pc | npc) & 3) + grp = &ucp->uc_mcontext.mc_gregs; + err = __get_user(pc, &((*grp)[MC_PC])); + err |= __get_user(npc, &((*grp)[MC_NPC])); + if(err || ((pc | npc) & 3)) goto do_sigsegv; if(regs->u_regs[UREG_I1]) { sigset_t set; @@ -78,48 +81,57 @@ } regs->tpc = pc; regs->tnpc = npc; - __get_user(regs->y, &((*grp)[MC_Y])); - __get_user(tstate, &((*grp)[MC_TSTATE])); + err |= __get_user(regs->y, &((*grp)[MC_Y])); + err |= __get_user(tstate, &((*grp)[MC_TSTATE])); regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC); regs->tstate |= (tstate & (TSTATE_ICC | TSTATE_XCC)); - __get_user(regs->u_regs[UREG_G1], (&(*grp)[MC_G1])); - __get_user(regs->u_regs[UREG_G2], (&(*grp)[MC_G2])); - __get_user(regs->u_regs[UREG_G3], (&(*grp)[MC_G3])); - __get_user(regs->u_regs[UREG_G4], (&(*grp)[MC_G4])); - __get_user(regs->u_regs[UREG_G5], (&(*grp)[MC_G5])); - __get_user(regs->u_regs[UREG_G6], (&(*grp)[MC_G6])); - __get_user(regs->u_regs[UREG_G7], (&(*grp)[MC_G7])); - __get_user(regs->u_regs[UREG_I0], (&(*grp)[MC_O0])); - __get_user(regs->u_regs[UREG_I1], (&(*grp)[MC_O1])); - __get_user(regs->u_regs[UREG_I2], (&(*grp)[MC_O2])); - __get_user(regs->u_regs[UREG_I3], (&(*grp)[MC_O3])); - __get_user(regs->u_regs[UREG_I4], (&(*grp)[MC_O4])); - __get_user(regs->u_regs[UREG_I5], (&(*grp)[MC_O5])); - __get_user(regs->u_regs[UREG_I6], (&(*grp)[MC_O6])); - __get_user(regs->u_regs[UREG_I7], (&(*grp)[MC_O7])); - - __get_user(fp, &(ucp->uc_mcontext.mc_fp)); - __get_user(i7, &(ucp->uc_mcontext.mc_i7)); - __put_user(fp, (&(((struct reg_window *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[6]))); - __put_user(i7, (&(((struct reg_window *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[7]))); + err |= __get_user(regs->u_regs[UREG_G1], (&(*grp)[MC_G1])); + err |= __get_user(regs->u_regs[UREG_G2], (&(*grp)[MC_G2])); + err |= __get_user(regs->u_regs[UREG_G3], (&(*grp)[MC_G3])); + err |= __get_user(regs->u_regs[UREG_G4], (&(*grp)[MC_G4])); + err |= __get_user(regs->u_regs[UREG_G5], (&(*grp)[MC_G5])); + err |= __get_user(regs->u_regs[UREG_G6], (&(*grp)[MC_G6])); + err |= __get_user(regs->u_regs[UREG_G7], (&(*grp)[MC_G7])); + err |= __get_user(regs->u_regs[UREG_I0], (&(*grp)[MC_O0])); + err |= __get_user(regs->u_regs[UREG_I1], (&(*grp)[MC_O1])); + err |= __get_user(regs->u_regs[UREG_I2], (&(*grp)[MC_O2])); + err |= __get_user(regs->u_regs[UREG_I3], (&(*grp)[MC_O3])); + err |= __get_user(regs->u_regs[UREG_I4], (&(*grp)[MC_O4])); + err |= __get_user(regs->u_regs[UREG_I5], (&(*grp)[MC_O5])); + err |= __get_user(regs->u_regs[UREG_I6], (&(*grp)[MC_O6])); + err |= __get_user(regs->u_regs[UREG_I7], (&(*grp)[MC_O7])); + + err |= __get_user(fp, &(ucp->uc_mcontext.mc_fp)); + err |= __get_user(i7, &(ucp->uc_mcontext.mc_i7)); + err |= __put_user(fp, + (&(((struct reg_window *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[6]))); + err |= __put_user(i7, + (&(((struct reg_window *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[7]))); - __get_user(fenab, &(ucp->uc_mcontext.mc_fpregs.mcfpu_enab)); + err |= __get_user(fenab, &(ucp->uc_mcontext.mc_fpregs.mcfpu_enab)); if(fenab) { unsigned long *fpregs = (unsigned long *)(((char *)current) + AOFF_task_fpregs); unsigned long fprs; fprs_write(0); - __get_user(fprs, &(ucp->uc_mcontext.mc_fpregs.mcfpu_fprs)); + err |= __get_user(fprs, &(ucp->uc_mcontext.mc_fpregs.mcfpu_fprs)); if (fprs & FPRS_DL) - copy_from_user(fpregs, &(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs), - (sizeof(unsigned int) * 32)); + err |= copy_from_user(fpregs, + &(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs), + (sizeof(unsigned int) * 32)); if (fprs & FPRS_DU) - copy_from_user(fpregs+16, ((unsigned long *)&(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs))+16, - (sizeof(unsigned int) * 32)); - __get_user(current->tss.xfsr[0], &(ucp->uc_mcontext.mc_fpregs.mcfpu_fsr)); - __get_user(current->tss.gsr[0], &(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr)); + err |= copy_from_user(fpregs+16, + ((unsigned long *)&(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs))+16, + (sizeof(unsigned int) * 32)); + err |= __get_user(current->tss.xfsr[0], + &(ucp->uc_mcontext.mc_fpregs.mcfpu_fsr)); + err |= __get_user(current->tss.gsr[0], + &(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr)); regs->tstate &= ~TSTATE_PEF; } + if (err) + goto do_sigsegv; + return; do_sigsegv: lock_kernel(); @@ -134,6 +146,7 @@ mcontext_t *mcp; unsigned long fp, i7; unsigned char fenab; + int err; synchronize_user_stack(); if(tp->w_saved || clear_user(ucp, sizeof(*ucp))) @@ -152,52 +165,61 @@ regs->tpc = regs->tnpc; regs->tnpc += 4; + err = 0; if (_NSIG_WORDS == 1) - __put_user(current->blocked.sig[0], (unsigned long *)&ucp->uc_sigmask); + err |= __put_user(current->blocked.sig[0], + (unsigned long *)&ucp->uc_sigmask); else - __copy_to_user(&ucp->uc_sigmask, ¤t->blocked, sizeof(sigset_t)); + err |= __copy_to_user(&ucp->uc_sigmask, ¤t->blocked, + sizeof(sigset_t)); - __put_user(regs->tstate, &((*grp)[MC_TSTATE])); - __put_user(regs->tpc, &((*grp)[MC_PC])); - __put_user(regs->tnpc, &((*grp)[MC_NPC])); - __put_user(regs->y, &((*grp)[MC_Y])); - __put_user(regs->u_regs[UREG_G1], &((*grp)[MC_G1])); - __put_user(regs->u_regs[UREG_G2], &((*grp)[MC_G2])); - __put_user(regs->u_regs[UREG_G3], &((*grp)[MC_G3])); - __put_user(regs->u_regs[UREG_G4], &((*grp)[MC_G4])); - __put_user(regs->u_regs[UREG_G5], &((*grp)[MC_G5])); - __put_user(regs->u_regs[UREG_G6], &((*grp)[MC_G6])); - __put_user(regs->u_regs[UREG_G6], &((*grp)[MC_G7])); - __put_user(regs->u_regs[UREG_I0], &((*grp)[MC_O0])); - __put_user(regs->u_regs[UREG_I1], &((*grp)[MC_O1])); - __put_user(regs->u_regs[UREG_I2], &((*grp)[MC_O2])); - __put_user(regs->u_regs[UREG_I3], &((*grp)[MC_O3])); - __put_user(regs->u_regs[UREG_I4], &((*grp)[MC_O4])); - __put_user(regs->u_regs[UREG_I5], &((*grp)[MC_O5])); - __put_user(regs->u_regs[UREG_I6], &((*grp)[MC_O6])); - __put_user(regs->u_regs[UREG_I7], &((*grp)[MC_O7])); - - __get_user(fp, (&(((struct reg_window *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[6]))); - __get_user(i7, (&(((struct reg_window *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[7]))); - __put_user(fp, &(mcp->mc_fp)); - __put_user(i7, &(mcp->mc_i7)); + err |= __put_user(regs->tstate, &((*grp)[MC_TSTATE])); + err |= __put_user(regs->tpc, &((*grp)[MC_PC])); + err |= __put_user(regs->tnpc, &((*grp)[MC_NPC])); + err |= __put_user(regs->y, &((*grp)[MC_Y])); + err |= __put_user(regs->u_regs[UREG_G1], &((*grp)[MC_G1])); + err |= __put_user(regs->u_regs[UREG_G2], &((*grp)[MC_G2])); + err |= __put_user(regs->u_regs[UREG_G3], &((*grp)[MC_G3])); + err |= __put_user(regs->u_regs[UREG_G4], &((*grp)[MC_G4])); + err |= __put_user(regs->u_regs[UREG_G5], &((*grp)[MC_G5])); + err |= __put_user(regs->u_regs[UREG_G6], &((*grp)[MC_G6])); + err |= __put_user(regs->u_regs[UREG_G6], &((*grp)[MC_G7])); + err |= __put_user(regs->u_regs[UREG_I0], &((*grp)[MC_O0])); + err |= __put_user(regs->u_regs[UREG_I1], &((*grp)[MC_O1])); + err |= __put_user(regs->u_regs[UREG_I2], &((*grp)[MC_O2])); + err |= __put_user(regs->u_regs[UREG_I3], &((*grp)[MC_O3])); + err |= __put_user(regs->u_regs[UREG_I4], &((*grp)[MC_O4])); + err |= __put_user(regs->u_regs[UREG_I5], &((*grp)[MC_O5])); + err |= __put_user(regs->u_regs[UREG_I6], &((*grp)[MC_O6])); + err |= __put_user(regs->u_regs[UREG_I7], &((*grp)[MC_O7])); + + err |= __get_user(fp, + (&(((struct reg_window *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[6]))); + err |= __get_user(i7, + (&(((struct reg_window *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[7]))); + err |= __put_user(fp, &(mcp->mc_fp)); + err |= __put_user(i7, &(mcp->mc_i7)); - __put_user(fenab, &(mcp->mc_fpregs.mcfpu_enab)); + err |= __put_user(fenab, &(mcp->mc_fpregs.mcfpu_enab)); if(fenab) { unsigned long *fpregs = (unsigned long *)(((char *)current) + AOFF_task_fpregs); unsigned long fprs; fprs = current->tss.fpsaved[0]; if (fprs & FPRS_DL) - copy_to_user(&(mcp->mc_fpregs.mcfpu_fregs), fpregs, - (sizeof(unsigned int) * 32)); + err |= copy_to_user(&(mcp->mc_fpregs.mcfpu_fregs), fpregs, + (sizeof(unsigned int) * 32)); if (fprs & FPRS_DU) - copy_to_user(((unsigned long *)&(mcp->mc_fpregs.mcfpu_fregs))+16, fpregs+16, - (sizeof(unsigned int) * 32)); - __put_user(current->tss.xfsr[0], &(mcp->mc_fpregs.mcfpu_fsr)); - __put_user(current->tss.gsr[0], &(mcp->mc_fpregs.mcfpu_gsr)); - __put_user(fprs, &(mcp->mc_fpregs.mcfpu_fprs)); + err |= copy_to_user( + ((unsigned long *)&(mcp->mc_fpregs.mcfpu_fregs))+16, fpregs+16, + (sizeof(unsigned int) * 32)); + err |= __put_user(current->tss.xfsr[0], &(mcp->mc_fpregs.mcfpu_fsr)); + err |= __put_user(current->tss.gsr[0], &(mcp->mc_fpregs.mcfpu_gsr)); + err |= __put_user(fprs, &(mcp->mc_fpregs.mcfpu_fprs)); } + if (err) + goto do_sigsegv; + return; do_sigsegv: lock_kernel(); @@ -474,22 +496,25 @@ return 0; } -static inline void +static inline int save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t *fpu) { unsigned long *fpregs = (unsigned long *)(regs+1); unsigned long fprs; + int err = 0; fprs = current->tss.fpsaved[0]; if (fprs & FPRS_DL) - copy_to_user(&fpu->si_float_regs[0], fpregs, - (sizeof(unsigned int) * 32)); + err |= copy_to_user(&fpu->si_float_regs[0], fpregs, + (sizeof(unsigned int) * 32)); if (fprs & FPRS_DU) - copy_to_user(&fpu->si_float_regs[32], fpregs+16, - (sizeof(unsigned int) * 32)); - __put_user(current->tss.xfsr[0], &fpu->si_fsr); - __put_user(current->tss.gsr[0], &fpu->si_gsr); - __put_user(fprs, &fpu->si_fprs); + err |= copy_to_user(&fpu->si_float_regs[32], fpregs+16, + (sizeof(unsigned int) * 32)); + err |= __put_user(current->tss.xfsr[0], &fpu->si_fsr); + err |= __put_user(current->tss.gsr[0], &fpu->si_gsr); + err |= __put_user(fprs, &fpu->si_fprs); + + return err; } static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, unsigned long framesize) @@ -500,7 +525,8 @@ /* This is the X/Open sanctioned signal stack switching. */ if (ka->sa.sa_flags & SA_ONSTACK) { - if (!on_sig_stack(sp) && !((current->sas_ss_sp + current->sas_ss_size) & 7)) + if (!on_sig_stack(sp) && + !((current->sas_ss_sp + current->sas_ss_size) & 7)) sp = current->sas_ss_sp + current->sas_ss_size; } return (void *)(sp - framesize); @@ -511,7 +537,7 @@ int signo, sigset_t *oldset) { struct new_signal_frame *sf; - int sigframe_size; + int sigframe_size, err; /* 1. Make sure everything is clean */ synchronize_user_stack(); @@ -534,22 +560,25 @@ } /* 2. Save the current process state */ - copy_to_user(&sf->info.si_regs, regs, sizeof (*regs)); + err = copy_to_user(&sf->info.si_regs, regs, sizeof (*regs)); if (current->tss.fpsaved[0] & FPRS_FEF) { - save_fpu_state(regs, &sf->fpu_state); - __put_user((u64)&sf->fpu_state, &sf->fpu_save); + err |= save_fpu_state(regs, &sf->fpu_state); + err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save); } else { - __put_user(0, &sf->fpu_save); + err |= __put_user(0, &sf->fpu_save); } - __put_user(oldset->sig[0], &sf->info.si_mask); + err |= __put_user(oldset->sig[0], &sf->info.si_mask); if (_NSIG_WORDS > 1) - __copy_to_user(sf->extramask, &oldset->sig[1], sizeof(sf->extramask)); + err |= __copy_to_user(sf->extramask, &oldset->sig[1], + sizeof(sf->extramask)); - copy_in_user((u64 *)sf, - (u64 *)(regs->u_regs[UREG_FP]+STACK_BIAS), - sizeof(struct reg_window)); + err |= copy_in_user((u64 *)sf, + (u64 *)(regs->u_regs[UREG_FP]+STACK_BIAS), + sizeof(struct reg_window)); + if (err) + goto sigsegv; /* 3. signal handler back-trampoline and parameters */ regs->u_regs[UREG_FP] = ((unsigned long) sf) - STACK_BIAS; @@ -572,8 +601,13 @@ regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2); - __put_user(0x821020d8, &sf->insns[0]); /* mov __NR_sigreturn, %g1 */ - __put_user(0x91d0206d, &sf->insns[1]); /* t 0x6d */ + /* mov __NR_sigreturn, %g1 */ + err |= __put_user(0x821020d8, &sf->insns[0]); + + /* t 0x6d */ + err |= __put_user(0x91d0206d, &sf->insns[1]); + if (err) + goto sigsegv; if(pte_present(*ptep)) { unsigned long page = pte_page(*ptep); @@ -590,6 +624,9 @@ sigill: lock_kernel(); do_exit(SIGILL); +sigsegv: + lock_kernel(); + do_exit(SIGSEGV); } static inline void @@ -597,7 +634,7 @@ int signo, sigset_t *oldset, siginfo_t *info) { struct rt_signal_frame *sf; - int sigframe_size; + int sigframe_size, err; /* 1. Make sure everything is clean */ synchronize_user_stack(); @@ -619,27 +656,29 @@ } /* 2. Save the current process state */ - copy_to_user(&sf->regs, regs, sizeof (*regs)); + err = copy_to_user(&sf->regs, regs, sizeof (*regs)); if (current->tss.fpsaved[0] & FPRS_FEF) { - save_fpu_state(regs, &sf->fpu_state); - __put_user((u64)&sf->fpu_state, &sf->fpu_save); + err |= save_fpu_state(regs, &sf->fpu_state); + err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save); } else { - __put_user(0, &sf->fpu_save); + err |= __put_user(0, &sf->fpu_save); } /* Setup sigaltstack */ - __put_user(current->sas_ss_sp, &sf->stack.ss_sp); - __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags); - __put_user(current->sas_ss_size, &sf->stack.ss_size); + err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp); + err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags); + err |= __put_user(current->sas_ss_size, &sf->stack.ss_size); - copy_to_user(&sf->mask, oldset, sizeof(sigset_t)); + err |= copy_to_user(&sf->mask, oldset, sizeof(sigset_t)); - copy_in_user((u64 *)sf, - (u64 *)(regs->u_regs[UREG_FP]+STACK_BIAS), - sizeof(struct reg_window)); + err |= copy_in_user((u64 *)sf, + (u64 *)(regs->u_regs[UREG_FP]+STACK_BIAS), + sizeof(struct reg_window)); - copy_to_user(&sf->info, info, sizeof(siginfo_t)); + err |= copy_to_user(&sf->info, info, sizeof(siginfo_t)); + if (err) + goto sigsegv; /* 3. signal handler back-trampoline and parameters */ regs->u_regs[UREG_FP] = ((unsigned long) sf) - STACK_BIAS; @@ -662,8 +701,13 @@ regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2); - __put_user(0x82102065, &sf->insns[0]); /* mov __NR_rt_sigreturn, %g1 */ - __put_user(0x91d0206d, &sf->insns[1]); /* t 0x6d */ + /* mov __NR_rt_sigreturn, %g1 */ + err |= __put_user(0x82102065, &sf->insns[0]); + + /* t 0x6d */ + err |= __put_user(0x91d0206d, &sf->insns[1]); + if (err) + goto sigsegv; if(pte_present(*ptep)) { unsigned long page = pte_page(*ptep); @@ -680,6 +724,9 @@ sigill: lock_kernel(); do_exit(SIGILL); +sigsegv: + lock_kernel(); + do_exit(SIGSEGV); } static inline void handle_signal(unsigned long signr, struct k_sigaction *ka, @@ -721,6 +768,60 @@ } } +#ifdef DEBUG_SIGNALS_MAPS + +#define MAPS_LINE_FORMAT "%016lx-%016lx %s %016lx %s %lu " + +static inline void read_maps (void) +{ + struct vm_area_struct * map, * next; + char * buffer; + ssize_t i; + + buffer = (char*)__get_free_page(GFP_KERNEL); + if (!buffer) + return; + + for (map = current->mm->mmap ; map ; map = next ) { + /* produce the next line */ + char *line; + char str[5], *cp = str; + int flags; + kdev_t dev; + unsigned long ino; + + /* + * Get the next vma now (but it won't be used if we sleep). + */ + next = map->vm_next; + flags = map->vm_flags; + + *cp++ = flags & VM_READ ? 'r' : '-'; + *cp++ = flags & VM_WRITE ? 'w' : '-'; + *cp++ = flags & VM_EXEC ? 'x' : '-'; + *cp++ = flags & VM_MAYSHARE ? 's' : 'p'; + *cp++ = 0; + + dev = 0; + ino = 0; + if (map->vm_file != NULL) { + dev = map->vm_file->f_dentry->d_inode->i_dev; + ino = map->vm_file->f_dentry->d_inode->i_ino; + line = d_path(map->vm_file->f_dentry, buffer, PAGE_SIZE); + } + printk(MAPS_LINE_FORMAT, map->vm_start, map->vm_end, str, map->vm_offset, + kdevname(dev), ino); + if (map->vm_file != NULL) + printk("%s\n", line); + else + printk("\n"); + } + free_page((unsigned long)buffer); + return; +} + +#endif + /* Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. @@ -824,9 +925,26 @@ unlock_kernel(); } #ifdef DEBUG_SIGNALS - /* Very useful to debug dynamic linker problems */ - printk ("Sig ILL going...\n"); + /* Very useful to debug the dynamic linker */ + printk ("Sig %d going...\n", (int)signr); show_regs (regs); +#ifdef DEBUG_SIGNALS_TRACE + { + struct reg_window *rw = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS); + unsigned long ins[8]; + + while(rw && + !(((unsigned long) rw) & 0x3)) { + copy_from_user(ins, &rw->ins[0], sizeof(ins)); + printk("Caller[%016lx](%016lx,%016lx,%016lx,%016lx,%016lx,%016lx)\n", ins[7], ins[0], ins[1], ins[2], ins[3], ins[4], ins[5]); + rw = (struct reg_window *)(unsigned long)(ins[6] + STACK_BIAS); + } + } +#endif +#ifdef DEBUG_SIGNALS_MAPS + printk("Maps:\n"); + read_maps(); +#endif #endif /* fall through */ default: diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/signal32.c linux/arch/sparc64/kernel/signal32.c --- v2.1.123/linux/arch/sparc64/kernel/signal32.c Thu Aug 6 14:06:31 1998 +++ linux/arch/sparc64/kernel/signal32.c Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -/* $Id: signal32.c,v 1.41 1998/07/30 11:29:32 davem Exp $ +/* $Id: signal32.c,v 1.44 1998/09/25 01:09:17 davem Exp $ * arch/sparc64/kernel/signal32.c * * Copyright (C) 1991, 1992 Linus Torvalds @@ -39,6 +39,7 @@ /* #define DEBUG_SIGNALS 1 */ /* #define DEBUG_SIGNALS_TRACE 1 */ /* #define DEBUG_SIGNALS_MAPS 1 */ +/* #define DEBUG_SIGNALS_TLB 1 */ /* Signal frames: the original one (compatible with SunOS): * @@ -270,8 +271,10 @@ recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); return; + segv: - send_sig(SIGSEGV, current, 1); + lock_kernel(); + do_exit(SIGSEGV); } asmlinkage void do_sigreturn32(struct pt_regs *regs) @@ -329,8 +332,10 @@ regs->tstate &= ~(TSTATE_ICC); regs->tstate |= psr_to_tstate_icc(psr); return; + segv: - send_sig(SIGSEGV, current, 1); + lock_kernel(); + do_exit(SIGSEGV); } asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) @@ -412,7 +417,8 @@ spin_unlock_irq(¤t->sigmask_lock); return; segv: - send_sig(SIGSEGV, current, 1); + lock_kernel(); + do_exit(SIGSEGV); } /* Checks if the fp is valid */ @@ -445,6 +451,7 @@ struct signal_sframe32 *sframep; struct sigcontext32 *sc; unsigned seta[_NSIG_WORDS32]; + int err = 0; #if 0 int window = 0; @@ -472,7 +479,8 @@ sc = &sframep->sig_context; /* We've already made sure frame pointer isn't in kernel space... */ - __put_user((sas_ss_flags(regs->u_regs[UREG_FP]) == SS_ONSTACK), &sc->sigc_onstack); + err = __put_user((sas_ss_flags(regs->u_regs[UREG_FP]) == SS_ONSTACK), + &sc->sigc_onstack); switch (_NSIG_WORDS) { case 4: seta[7] = (oldset->sig[3] >> 32); @@ -484,67 +492,81 @@ case 1: seta[1] = (oldset->sig[0] >> 32); seta[0] = oldset->sig[0]; } - __put_user(seta[0], &sc->sigc_mask); - __copy_to_user(sframep->extramask, seta + 1, (_NSIG_WORDS32 - 1) * sizeof(unsigned)); - __put_user(regs->u_regs[UREG_FP], &sc->sigc_sp); - __put_user(pc, &sc->sigc_pc); - __put_user(npc, &sc->sigc_npc); + err |= __put_user(seta[0], &sc->sigc_mask); + err |= __copy_to_user(sframep->extramask, seta + 1, + (_NSIG_WORDS32 - 1) * sizeof(unsigned)); + err |= __put_user(regs->u_regs[UREG_FP], &sc->sigc_sp); + err |= __put_user(pc, &sc->sigc_pc); + err |= __put_user(npc, &sc->sigc_npc); psr = tstate_to_psr (regs->tstate); if(current->tss.fpsaved[0] & FPRS_FEF) psr |= PSR_EF; - __put_user(psr, &sc->sigc_psr); - __put_user(regs->u_regs[UREG_G1], &sc->sigc_g1); - __put_user(regs->u_regs[UREG_I0], &sc->sigc_o0); - __put_user(current->tss.w_saved, &sc->sigc_oswins); + err |= __put_user(psr, &sc->sigc_psr); + err |= __put_user(regs->u_regs[UREG_G1], &sc->sigc_g1); + err |= __put_user(regs->u_regs[UREG_I0], &sc->sigc_o0); + err |= __put_user(current->tss.w_saved, &sc->sigc_oswins); #if 0 /* w_saved is not currently used... */ if(current->tss.w_saved) for(window = 0; window < current->tss.w_saved; window++) { sc->sigc_spbuf[window] = (char *)current->tss.rwbuf_stkptrs[window]; - copy_to_user(&sc->sigc_wbuf[window], - ¤t->tss.reg_window[window], - sizeof(struct reg_window)); + err |= copy_to_user(&sc->sigc_wbuf[window], + ¤t->tss.reg_window[window], + sizeof(struct reg_window)); } else #endif - copy_in_user((u32 *)sframep, - (u32 *)(regs->u_regs[UREG_FP]), - sizeof(struct reg_window32)); + err |= copy_in_user((u32 *)sframep, + (u32 *)(regs->u_regs[UREG_FP]), + sizeof(struct reg_window32)); current->tss.w_saved = 0; /* So process is allowed to execute. */ - __put_user(signr, &sframep->sig_num); + err |= __put_user(signr, &sframep->sig_num); if(signr == SIGSEGV || signr == SIGILL || signr == SIGFPE || signr == SIGBUS || signr == SIGEMT) { - __put_user(current->tss.sig_desc, &sframep->sig_code); - __put_user(current->tss.sig_address, &sframep->sig_address); + err |= __put_user(current->tss.sig_desc, &sframep->sig_code); + err |= __put_user(current->tss.sig_address, &sframep->sig_address); } else { - __put_user(0, &sframep->sig_code); - __put_user(0, &sframep->sig_address); + err |= __put_user(0, &sframep->sig_code); + err |= __put_user(0, &sframep->sig_address); } - __put_user((u64)sc, &sframep->sig_scptr); + err |= __put_user((u64)sc, &sframep->sig_scptr); + if (err) + goto sigsegv; + regs->u_regs[UREG_FP] = (unsigned long) sframep; regs->tpc = (unsigned long) sa->sa_handler; regs->tnpc = (regs->tpc + 4); + return; + +sigsegv: + lock_kernel(); + do_exit(SIGSEGV); } -static inline void save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t *fpu) +static inline int save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t *fpu) { unsigned long *fpregs = (unsigned long *)(((char *)current) + AOFF_task_fpregs); unsigned long fprs; + int err = 0; fprs = current->tss.fpsaved[0]; if (fprs & FPRS_DL) - copy_to_user(&fpu->si_float_regs[0], fpregs, (sizeof(unsigned int) * 32)); + err |= copy_to_user(&fpu->si_float_regs[0], fpregs, + (sizeof(unsigned int) * 32)); if (fprs & FPRS_DU) - copy_to_user(&fpu->si_float_regs[32], fpregs+16, (sizeof(unsigned int) * 32)); - __put_user(current->tss.xfsr[0], &fpu->si_fsr); - __put_user(current->tss.gsr[0], &fpu->si_gsr); - __put_user(fprs, &fpu->si_fprs); + err |= copy_to_user(&fpu->si_float_regs[32], fpregs+16, + (sizeof(unsigned int) * 32)); + err |= __put_user(current->tss.xfsr[0], &fpu->si_fsr); + err |= __put_user(current->tss.gsr[0], &fpu->si_gsr); + err |= __put_user(fprs, &fpu->si_fprs); + + return err; } static inline void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, @@ -553,7 +575,7 @@ struct new_signal_frame32 *sf; int sigframe_size; u32 psr; - int i; + int i, err; unsigned seta[_NSIG_WORDS32]; /* 1. Make sure everything is clean */ @@ -583,21 +605,21 @@ } /* 2. Save the current process state */ - put_user(regs->tpc, &sf->info.si_regs.pc); - __put_user(regs->tnpc, &sf->info.si_regs.npc); - __put_user(regs->y, &sf->info.si_regs.y); + err = put_user(regs->tpc, &sf->info.si_regs.pc); + err |= __put_user(regs->tnpc, &sf->info.si_regs.npc); + err |= __put_user(regs->y, &sf->info.si_regs.y); psr = tstate_to_psr (regs->tstate); if(current->tss.fpsaved[0] & FPRS_FEF) psr |= PSR_EF; - __put_user(psr, &sf->info.si_regs.psr); + err |= __put_user(psr, &sf->info.si_regs.psr); for (i = 0; i < 16; i++) - __put_user(regs->u_regs[i], &sf->info.si_regs.u_regs[i]); + err |= __put_user(regs->u_regs[i], &sf->info.si_regs.u_regs[i]); if (psr & PSR_EF) { - save_fpu_state32(regs, &sf->fpu_state); - __put_user((u64)&sf->fpu_state, &sf->fpu_save); + err |= save_fpu_state32(regs, &sf->fpu_state); + err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save); } else { - __put_user(0, &sf->fpu_save); + err |= __put_user(0, &sf->fpu_save); } switch (_NSIG_WORDS) { @@ -610,13 +632,17 @@ case 1: seta[1] = (oldset->sig[0] >> 32); seta[0] = oldset->sig[0]; } - __put_user(seta[0], &sf->info.si_mask); - __copy_to_user(sf->extramask, seta + 1, (_NSIG_WORDS32 - 1) * sizeof(unsigned)); - - copy_in_user((u32 *)sf, - (u32 *)(regs->u_regs[UREG_FP]), - sizeof(struct reg_window32)); + err |= __put_user(seta[0], &sf->info.si_mask); + err |= __copy_to_user(sf->extramask, seta + 1, + (_NSIG_WORDS32 - 1) * sizeof(unsigned)); + + err |= copy_in_user((u32 *)sf, + (u32 *)(regs->u_regs[UREG_FP]), + sizeof(struct reg_window32)); + if (err) + goto sigsegv; + /* 3. signal handler back-trampoline and parameters */ regs->u_regs[UREG_FP] = (unsigned long) sf; regs->u_regs[UREG_I0] = signo; @@ -638,8 +664,10 @@ regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2); - __put_user(0x821020d8, &sf->insns[0]); /* mov __NR_sigreturn, %g1 */ - __put_user(0x91d02010, &sf->insns[1]); /* t 0x10 */ + err = __put_user(0x821020d8, &sf->insns[0]); /*mov __NR_sigreturn, %g1*/ + err |= __put_user(0x91d02010, &sf->insns[1]); /*t 0x10*/ + if(err) + goto sigsegv; if(pte_present(*ptep)) { unsigned long page = pte_page(*ptep); @@ -656,6 +684,9 @@ sigill: lock_kernel(); do_exit(SIGILL); +sigsegv: + lock_kernel(); + do_exit(SIGSEGV); } /* Setup a Solaris stack frame */ @@ -674,7 +705,7 @@ int window = 0; #endif unsigned psr; - int i; + int i, err; synchronize_user_stack(); save_and_clear_fpu(); @@ -691,7 +722,7 @@ } /* Start with a clean frame pointer and fill it */ - clear_user(sfp, sizeof (*sfp)); + err = clear_user(sfp, sizeof (*sfp)); /* Setup convenience variables */ si = &sfp->si; @@ -709,37 +740,37 @@ if (_NSIG_WORDS >= 2) { setv.sigbits[2] = oldset->sig[1]; setv.sigbits[3] = (oldset->sig[1] >> 32); - __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t)); + err |= __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t)); } else - __copy_to_user(&uc->sigmask, &setv, 2 * sizeof(unsigned)); + err |= __copy_to_user(&uc->sigmask, &setv, 2 * sizeof(unsigned)); /* Store registers */ - __put_user(regs->tpc, &((*gr) [SVR4_PC])); - __put_user(regs->tnpc, &((*gr) [SVR4_NPC])); + err |= __put_user(regs->tpc, &((*gr) [SVR4_PC])); + err |= __put_user(regs->tnpc, &((*gr) [SVR4_NPC])); psr = tstate_to_psr (regs->tstate); if(current->tss.fpsaved[0] & FPRS_FEF) psr |= PSR_EF; - __put_user(psr, &((*gr) [SVR4_PSR])); - __put_user(regs->y, &((*gr) [SVR4_Y])); + err |= __put_user(psr, &((*gr) [SVR4_PSR])); + err |= __put_user(regs->y, &((*gr) [SVR4_Y])); /* Copy g [1..7] and o [0..7] registers */ for (i = 0; i < 7; i++) - __put_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i); + err |= __put_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i); for (i = 0; i < 8; i++) - __put_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i); + err |= __put_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i); /* Setup sigaltstack */ - __put_user(current->sas_ss_sp, &uc->stack.sp); - __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags); - __put_user(current->sas_ss_size, &uc->stack.size); + err |= __put_user(current->sas_ss_sp, &uc->stack.sp); + err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags); + err |= __put_user(current->sas_ss_size, &uc->stack.size); /* Save the currently window file: */ /* 1. Link sfp->uc->gwins to our windows */ - __put_user((u32)(long)gw, &mc->gwin); + err |= __put_user((u32)(long)gw, &mc->gwin); /* 2. Number of windows to restore at setcontext (): */ - __put_user(current->tss.w_saved, &gw->count); + err |= __put_user(current->tss.w_saved, &gw->count); /* 3. Save each valid window * Currently, it makes a copy of the windows from the kernel copy. @@ -754,9 +785,12 @@ */ #if 0 for(window = 0; window < current->tss.w_saved; window++) { - __put_user((int *) &(gw->win [window]), (int **)gw->winptr +window ); - copy_to_user(&gw->win [window], ¤t->tss.reg_window [window], sizeof (svr4_rwindow_t)); - __put_user(0, (int *)gw->winptr + window); + err |= __put_user((int *) &(gw->win [window]), + (int **)gw->winptr +window ); + err |= copy_to_user(&gw->win [window], + ¤t->tss.reg_window [window], + sizeof (svr4_rwindow_t)); + err |= __put_user(0, (int *)gw->winptr + window); } #endif @@ -768,8 +802,10 @@ * that much currently, should use those that David already * is providing with tss.sig_desc */ - __put_user(signr, &si->siginfo.signo); - __put_user(SVR4_SINOINFO, &si->siginfo.code); + err |= __put_user(signr, &si->siginfo.signo); + err |= __put_user(SVR4_SINOINFO, &si->siginfo.code); + if (err) + goto sigsegv; regs->u_regs[UREG_FP] = (unsigned long) sfp; regs->tpc = (unsigned long) sa->sa_handler; @@ -783,14 +819,22 @@ struct reg_window32 *rw = (struct reg_window32 *) (regs->u_regs [14] & 0x00000000ffffffffUL); - __put_user(signr, &rw->ins [0]); - __put_user((u64)si, &rw->ins [1]); - __put_user((u64)uc, &rw->ins [2]); - __put_user((u64)sfp, &rw->ins [6]); /* frame pointer */ + err |= __put_user(signr, &rw->ins [0]); + err |= __put_user((u64)si, &rw->ins [1]); + err |= __put_user((u64)uc, &rw->ins [2]); + err |= __put_user((u64)sfp, &rw->ins [6]); /* frame pointer */ + if (err) + goto sigsegv; + regs->u_regs[UREG_I0] = signr; regs->u_regs[UREG_I1] = (u32)(u64) si; regs->u_regs[UREG_I2] = (u32)(u64) uc; } + return; + +sigsegv: + lock_kernel(); + do_exit(SIGSEGV); } asmlinkage int @@ -799,7 +843,7 @@ svr4_gregset_t *gr; svr4_mcontext_t *mc; svr4_sigset_t setv; - int i; + int i, err; synchronize_user_stack(); save_and_clear_fpu(); @@ -809,8 +853,7 @@ lock_kernel(); do_exit (SIGSEGV); } - if(clear_user(uc, sizeof (*uc))) - return -EFAULT; + err = clear_user(uc, sizeof (*uc)); /* Setup convenience variables */ mc = &uc->mcontext; @@ -821,38 +864,38 @@ if (_NSIG_WORDS >= 2) { setv.sigbits[2] = current->blocked.sig[1]; setv.sigbits[3] = (current->blocked.sig[1] >> 32); - __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t)); + err |= __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t)); } else - __copy_to_user(&uc->sigmask, &setv, 2 * sizeof(unsigned)); + err |= __copy_to_user(&uc->sigmask, &setv, 2 * sizeof(unsigned)); /* Store registers */ - __put_user(regs->tpc, &uc->mcontext.greg [SVR4_PC]); - __put_user(regs->tnpc, &uc->mcontext.greg [SVR4_NPC]); + err |= __put_user(regs->tpc, &uc->mcontext.greg [SVR4_PC]); + err |= __put_user(regs->tnpc, &uc->mcontext.greg [SVR4_NPC]); #if 1 - __put_user(0, &uc->mcontext.greg [SVR4_PSR]); + err |= __put_user(0, &uc->mcontext.greg [SVR4_PSR]); #else i = tstate_to_psr(regs->tstate) & ~PSR_EF; if (current->tss.fpsaved[0] & FPRS_FEF) i |= PSR_EF; - __put_user(i, &uc->mcontext.greg [SVR4_PSR]); + err |= __put_user(i, &uc->mcontext.greg [SVR4_PSR]); #endif - __put_user(regs->y, &uc->mcontext.greg [SVR4_Y]); + err |= __put_user(regs->y, &uc->mcontext.greg [SVR4_Y]); /* Copy g [1..7] and o [0..7] registers */ for (i = 0; i < 7; i++) - __put_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i); + err |= __put_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i); for (i = 0; i < 8; i++) - __put_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i); + err |= __put_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i); /* Setup sigaltstack */ - __put_user(current->sas_ss_sp, &uc->stack.sp); - __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags); - __put_user(current->sas_ss_size, &uc->stack.size); + err |= __put_user(current->sas_ss_sp, &uc->stack.sp); + err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags); + err |= __put_user(current->sas_ss_size, &uc->stack.size); /* The register file is not saved * we have already stuffed all of it with sync_user_stack */ - return 0; + return (err ? -EFAULT : 0); } @@ -923,8 +966,8 @@ spin_unlock_irq(¤t->sigmask_lock); regs->tpc = pc; regs->tnpc = npc | 1; - __get_user(regs->y, &((*gr) [SVR4_Y])); - __get_user(psr, &((*gr) [SVR4_PSR])); + err |= __get_user(regs->y, &((*gr) [SVR4_Y])); + err |= __get_user(psr, &((*gr) [SVR4_PSR])); regs->tstate &= ~(TSTATE_ICC); regs->tstate |= psr_to_tstate_icc(psr); #if 0 @@ -933,9 +976,11 @@ #endif /* Restore g[1..7] and o[0..7] registers */ for (i = 0; i < 7; i++) - __get_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i); + err |= __get_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i); for (i = 0; i < 8; i++) - __get_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i); + err |= __get_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i); + if(err) + goto sigsegv; return -EINTR; sigsegv: @@ -950,7 +995,7 @@ struct rt_signal_frame32 *sf; int sigframe_size; u32 psr; - int i; + int i, err; sigset_t32 seta; /* 1. Make sure everything is clean */ @@ -980,27 +1025,27 @@ } /* 2. Save the current process state */ - put_user(regs->tpc, &sf->regs.pc); - __put_user(regs->tnpc, &sf->regs.npc); - __put_user(regs->y, &sf->regs.y); + err = put_user(regs->tpc, &sf->regs.pc); + err |= __put_user(regs->tnpc, &sf->regs.npc); + err |= __put_user(regs->y, &sf->regs.y); psr = tstate_to_psr (regs->tstate); if(current->tss.fpsaved[0] & FPRS_FEF) psr |= PSR_EF; - __put_user(psr, &sf->regs.psr); + err |= __put_user(psr, &sf->regs.psr); for (i = 0; i < 16; i++) - __put_user(regs->u_regs[i], &sf->regs.u_regs[i]); + err |= __put_user(regs->u_regs[i], &sf->regs.u_regs[i]); if (psr & PSR_EF) { - save_fpu_state32(regs, &sf->fpu_state); - __put_user((u64)&sf->fpu_state, &sf->fpu_save); + err |= save_fpu_state32(regs, &sf->fpu_state); + err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save); } else { - __put_user(0, &sf->fpu_save); + err |= __put_user(0, &sf->fpu_save); } /* Setup sigaltstack */ - __put_user(current->sas_ss_sp, &sf->stack.ss_sp); - __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags); - __put_user(current->sas_ss_size, &sf->stack.ss_size); + err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp); + err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags); + err |= __put_user(current->sas_ss_size, &sf->stack.ss_size); switch (_NSIG_WORDS) { case 4: seta.sig[7] = (oldset->sig[3] >> 32); @@ -1012,11 +1057,13 @@ case 1: seta.sig[1] = (oldset->sig[0] >> 32); seta.sig[0] = oldset->sig[0]; } - __copy_to_user(&sf->mask, &seta, sizeof(sigset_t)); + err |= __copy_to_user(&sf->mask, &seta, sizeof(sigset_t)); - copy_in_user((u32 *)sf, - (u32 *)(regs->u_regs[UREG_FP]), - sizeof(struct reg_window32)); + err |= copy_in_user((u32 *)sf, + (u32 *)(regs->u_regs[UREG_FP]), + sizeof(struct reg_window32)); + if (err) + goto sigsegv; /* 3. signal handler back-trampoline and parameters */ regs->u_regs[UREG_FP] = (unsigned long) sf; @@ -1039,8 +1086,13 @@ regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2); - __put_user(0x821020d8, &sf->insns[0]); /* mov __NR_sigreturn, %g1 */ - __put_user(0x91d02010, &sf->insns[1]); /* t 0x10 */ + /* mov __NR_rt_sigreturn, %g1 */ + err |= __put_user(0x82102065, &sf->insns[0]); + + /* t 0x10 */ + err |= __put_user(0x91d02010, &sf->insns[1]); + if (err) + goto sigsegv; if(pte_present(*ptep)) { unsigned long page = pte_page(*ptep); @@ -1057,6 +1109,9 @@ sigill: lock_kernel(); do_exit(SIGILL); +sigsegv: + lock_kernel(); + do_exit(SIGSEGV); } static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka, @@ -1257,6 +1312,14 @@ /* Very useful to debug dynamic linker problems */ printk ("Sig %ld going for %s[%d]...\n", signr, current->comm, current->pid); show_regs (regs); +#ifdef DEBUG_SIGNALS_TLB + do { + extern void sparc_ultra_dump_itlb(void); + extern void sparc_ultra_dump_dtlb(void); + sparc_ultra_dump_dtlb(); + sparc_ultra_dump_itlb(); + } while(0); +#endif #ifdef DEBUG_SIGNALS_TRACE { struct reg_window32 *rw = (struct reg_window32 *)(regs->u_regs[UREG_FP] & 0xffffffff); diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/smp.c linux/arch/sparc64/kernel/smp.c --- v2.1.123/linux/arch/sparc64/kernel/smp.c Thu Aug 6 14:06:31 1998 +++ linux/arch/sparc64/kernel/smp.c Sun Oct 4 10:22:43 1998 @@ -63,7 +63,7 @@ for (i = 0; i < NR_CPUS; i++) if(cpu_present_map & (1UL << i)) len += sprintf(buf + len, - "CPU%d:\t\tonline\n", i + "CPU%d:\t\tonline\n", i); return len; } @@ -380,7 +380,7 @@ { u32 ctx = mm->context & 0x3ff; - if(mm == current->mm && mm->count == 1) { + if(mm == current->mm && atomic_read(&mm->count) == 1) { if(mm->cpu_vm_mask == (1UL << smp_processor_id())) goto local_flush_and_out; return smp_cross_call_avoidance(mm); @@ -396,7 +396,7 @@ { u32 ctx = mm->context & 0x3ff; - if(mm == current->mm && mm->count == 1) { + if(mm == current->mm && atomic_read(&mm->count) == 1) { if(mm->cpu_vm_mask == (1UL << smp_processor_id())) goto local_flush_and_out; return smp_cross_call_avoidance(mm); @@ -413,13 +413,13 @@ { u32 ctx = mm->context & 0x3ff; - if(mm == current->mm && mm->count == 1) { + if(mm == current->mm && atomic_read(&mm->count) == 1) { if(mm->cpu_vm_mask == (1UL << smp_processor_id())) goto local_flush_and_out; return smp_cross_call_avoidance(mm); } #if 0 /* XXX Disabled until further notice... */ - else if(mm->count == 1) { + else if(atomic_read(&mm->count) == 1) { /* Try to handle two special cases to avoid cross calls * in common scenerios where we are swapping process * pages out. diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c --- v2.1.123/linux/arch/sparc64/kernel/sparc64_ksyms.c Thu Aug 6 14:06:31 1998 +++ linux/arch/sparc64/kernel/sparc64_ksyms.c Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -/* $Id: sparc64_ksyms.c,v 1.39 1998/07/04 12:35:59 ecd Exp $ +/* $Id: sparc64_ksyms.c,v 1.41 1998/10/04 08:44:16 davem Exp $ * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -103,7 +103,6 @@ #ifdef __SMP__ EXPORT_SYMBOL(scheduler_lock); EXPORT_SYMBOL(global_bh_lock); -EXPORT_SYMBOL(klock_info); EXPORT_SYMBOL(global_irq_holder); EXPORT_SYMBOL(synchronize_irq); EXPORT_SYMBOL(cpu_data); @@ -184,7 +183,7 @@ /* sparc library symbols */ EXPORT_SYMBOL(bcopy); -EXPORT_SYMBOL(strlen); +EXPORT_SYMBOL(__strlen); EXPORT_SYMBOL(strnlen); EXPORT_SYMBOL(strcpy); EXPORT_SYMBOL(strncpy); diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/sunos_ioctl32.c linux/arch/sparc64/kernel/sunos_ioctl32.c --- v2.1.123/linux/arch/sparc64/kernel/sunos_ioctl32.c Thu Apr 23 20:21:32 1998 +++ linux/arch/sparc64/kernel/sunos_ioctl32.c Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -/* $Id: sunos_ioctl32.c,v 1.9 1998/03/29 10:10:53 davem Exp $ +/* $Id: sunos_ioctl32.c,v 1.10 1998/08/15 20:42:46 davem Exp $ * sunos_ioctl32.c: SunOS ioctl compatability on sparc64. * * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx) @@ -24,7 +24,14 @@ #include #include -#define A(x) ((unsigned long)x) +/* Use this to get at 32-bit user passed pointers. */ +#define A(__x) \ +({ unsigned long __ret; \ + __asm__ ("srl %0, 0, %0" \ + : "=r" (__ret) \ + : "0" (__x)); \ + __ret; \ +}) #define SUNOS_NR_OPEN 256 diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/sys32.S linux/arch/sparc64/kernel/sys32.S --- v2.1.123/linux/arch/sparc64/kernel/sys32.S Thu Aug 6 14:06:31 1998 +++ linux/arch/sparc64/kernel/sys32.S Sun Oct 4 10:22:43 1998 @@ -1,10 +1,13 @@ -/* $Id: sys32.S,v 1.6 1998/06/28 08:28:22 ecd Exp $ +/* $Id: sys32.S,v 1.7 1998/09/11 10:39:46 jj Exp $ * sys32.S: I-cache tricks for 32-bit compatability layer simple * conversions. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) */ +/* NOTE: call as jump breaks return stack, we have to avoid that */ + .text .align 32 @@ -15,81 +18,74 @@ srl %o1, 0, %o1 ! IEU0 Group or %g2, %lo(0xffffffff), %g2 ! IEU1 srl %o2, 0, %o2 ! IEU0 Group - mov %o7, %g1 ! IEU1 + sethi %hi(sys_mmap), %g1 ! IEU1 and %o3, %g2, %o3 ! IEU0 Group and %o4, %g2, %o4 ! IEU1 - and %o5, %g2, %o5 ! IEU0 Group - call sys_mmap ! CTI Group brk forced - mov %g1, %o7 ! IEU0 Group (regdep) + jmpl %g1 + %lo(sys_mmap), %g0 ! CTI Group brk forced + and %o5, %g2, %o5 ! IEU0 .align 32 .globl sys32_lseek .globl sys32_chmod, sys32_chown, sys32_lchown, sys32_mknod sys32_lseek: sra %o1, 0, %o1 - mov %o7, %g1 - call sys_lseek - mov %g1, %o7 + sethi %hi(sys_lseek), %g1 + jmpl %g1 + %lo(sys_lseek), %g0 + nop sys32_chmod: - sll %o1, 16, %o1 - mov %o7, %g1 + sethi %hi(0xffff), %g2 + sethi %hi(sys_chmod), %g1 + orcc %g2, %lo(0xffff), %g2 srl %o0, 0, %o0 - srl %o1, 16, %o1 - call sys_chmod - mov %g1, %o7 + jmpl %g1 + %lo(sys_chmod), %g0 + and %o1, %g2, %o1 sys32_chown: - sll %o1, 16, %o1 - mov %o7, %g1 - sll %o2, 16, %o2 + sethi %hi(0xffff), %g2 + sethi %hi(sys_chown), %g1 + orcc %g2, %lo(0xffff), %g2 srl %o0, 0, %o0 - srl %o1, 16, %o1 - srl %o2, 16, %o2 - call sys_chown - mov %g1, %o7 + and %o1, %g2, %o1 + jmpl %g1 + %lo(sys_chown), %g0 + and %o2, %g2, %o2 sys32_lchown: - sll %o1, 16, %o1 - mov %o7, %g1 - sll %o2, 16, %o2 + sethi %hi(0xffff), %g2 + sethi %hi(sys_lchown), %g1 + orcc %g2, %lo(0xffff), %g2 srl %o0, 0, %o0 - srl %o1, 16, %o1 - srl %o2, 16, %o2 - call sys_lchown - mov %g1, %o7 + and %o1, %g2, %o1 + jmpl %g1 + %lo(sys_lchown), %g0 + and %o2, %g2, %o2 sys32_mknod: - sll %o2, 16, %o2 - mov %o7, %g1 + sethi %hi(0xffff), %g2 + sethi %hi(sys_mknod), %g1 + orcc %g2, %lo(0xffff), %g2 srl %o0, 0, %o0 - srl %o2, 16, %o2 - call sys_mknod - mov %g1, %o7 + jmpl %g1 + %lo(sys_mknod), %g0 + and %o2, %g2, %o2 .align 32 .globl sys32_sendto, sys32_recvfrom, sys32_getsockopt sys32_sendto: srl %o1, 0, %o1 - mov %o7, %g1 + sethi %hi(sys_sendto), %g1 srl %o2, 0, %o2 - srl %o4, 0, %o4 - call sys_sendto - mov %g1, %o7 + jmpl %g1 + %lo(sys_sendto), %g0 + srl %o4, 0, %o4 sys32_recvfrom: srl %o1, 0, %o1 - mov %o7, %g1 + sethi %hi(sys_recvfrom), %g1 srl %o2, 0, %o2 srl %o4, 0, %o4 - srl %o5, 0, %o5 - call sys_recvfrom - mov %g1, %o7 + jmpl %g1 + %lo(sys_recvfrom), %g0 + srl %o5, 0, %o5 sys32_getsockopt: srl %o3, 0, %o3 - mov %o7, %g1 - srl %o4, 0, %o4 - call sys_getsockopt - mov %g1, %o7 + sethi %hi(sys_getsockopt), %g1 + jmpl %g1 + %lo(sys_getsockopt), %g0 + srl %o4, 0, %o4 .globl sys32_bdflush sys32_bdflush: - sra %o1, 0, %o1 - mov %o7, %g1 - call sys_bdflush - mov %g1, %o7 + sethi %hi(sys_bdflush), %g1 + jmpl %g1 + %lo(sys_bdflush), %g0 + sra %o1, 0, %o1 diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/sys_sparc.c linux/arch/sparc64/kernel/sys_sparc.c --- v2.1.123/linux/arch/sparc64/kernel/sys_sparc.c Thu Aug 6 14:06:31 1998 +++ linux/arch/sparc64/kernel/sys_sparc.c Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -/* $Id: sys_sparc.c,v 1.20 1998/08/03 20:03:26 davem Exp $ +/* $Id: sys_sparc.c,v 1.22 1998/09/25 01:09:27 davem Exp $ * linux/arch/sparc64/kernel/sys_sparc.c * * This file contains various random system calls that @@ -181,6 +181,7 @@ } } + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); retval = do_mmap(file, addr, len, prot, flags, off); out_putf: @@ -252,17 +253,20 @@ asmlinkage int solaris_syscall(struct pt_regs *regs) { + static int count = 0; lock_kernel(); regs->tpc = regs->tnpc; regs->tnpc += 4; - printk ("For Solaris binary emulation you need solaris module loaded\n"); + if(++count <= 20) + printk ("For Solaris binary emulation you need solaris module loaded\n"); show_regs (regs); send_sig(SIGSEGV, current, 1); unlock_kernel(); - return 0; + return -ENOSYS; } -asmlinkage int sys_utrap_install(utrap_entry_t type, utrap_handler_t new_p, utrap_handler_t new_d, +asmlinkage int sys_utrap_install(utrap_entry_t type, utrap_handler_t new_p, + utrap_handler_t new_d, utrap_handler_t *old_p, utrap_handler_t *old_d) { if (type < UT_INSTRUCTION_EXCEPTION || type > UT_TRAP_INSTRUCTION_31) diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c --- v2.1.123/linux/arch/sparc64/kernel/sys_sparc32.c Thu Aug 6 14:06:31 1998 +++ linux/arch/sparc64/kernel/sys_sparc32.c Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -/* $Id: sys_sparc32.c,v 1.90 1998/07/29 16:32:30 jj Exp $ +/* $Id: sys_sparc32.c,v 1.95 1998/09/07 09:20:50 davem Exp $ * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -50,14 +50,30 @@ #include #include -/* As gcc will warn about casting u32 to some ptr, we have to cast it to - * unsigned long first, and that's what is A() for. - * You just do (void *)A(x), instead of having to - * type (void *)((unsigned long)x) or instead of just (void *)x, which will - * produce warnings. +/* Use this to get at 32-bit user passed pointers. */ +/* Things to consider: the low-level assembly stub does + srl x, 0, x for first four arguments, so if you have + pointer to something in the first four arguments, just + declare it as a pointer, not u32. On the other side, + arguments from 5th onwards should be declared as u32 + for pointers, and need AA() around each usage. + A() macro should be used for places where you e.g. + have some internal variable u32 and just want to get + rid of a compiler warning. AA() has to be used in + places where you want to convert a function argument + to 32bit pointer or when you e.g. access pt_regs + structure and want to consider 32bit registers only. + -jj */ -#define A(x) ((unsigned long)x) - +#define A(__x) ((unsigned long)(__x)) +#define AA(__x) \ +({ unsigned long __ret; \ + __asm__ ("srl %0, 0, %0" \ + : "=r" (__ret) \ + : "0" (__x)); \ + __ret; \ +}) + static inline char * get_page(void) { char * res; @@ -73,12 +89,12 @@ * * POSIX.1 2.4: an empty pathname is invalid (ENOENT). */ -static inline int do_getname32(u32 filename, char *page) +static inline int do_getname32(const char *filename, char *page) { int retval; /* 32bit pointer will be always far below TASK_SIZE :)) */ - retval = strncpy_from_user((char *)page, (char *)A(filename), PAGE_SIZE); + retval = strncpy_from_user((char *)page, (char *)filename, PAGE_SIZE); if (retval > 0) { if (retval < PAGE_SIZE) return 0; @@ -88,7 +104,7 @@ return retval; } -char * getname32(u32 filename) +char * getname32(const char *filename) { char *tmp, *result; @@ -218,6 +234,261 @@ * * This is really horribly ugly. */ +#define IPCOP_MASK(__x) (1UL << (__x)) +static int do_sys32_semctl(int first, int second, int third, void *uptr) +{ + union semun fourth; + u32 pad; + int err = -EINVAL; + + if (!uptr) + goto out; + err = -EFAULT; + if (get_user (pad, (u32 *)uptr)) + goto out; + fourth.__pad = (void *)A(pad); + if (IPCOP_MASK (third) & + (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (SEM_INFO) | IPCOP_MASK (GETVAL) | + IPCOP_MASK (GETPID) | IPCOP_MASK (GETNCNT) | IPCOP_MASK (GETZCNT) | + IPCOP_MASK (GETALL) | IPCOP_MASK (SETALL) | IPCOP_MASK (IPC_RMID))) { + err = sys_semctl (first, second, third, fourth); + } else { + struct semid_ds s; + struct semid_ds32 *usp = (struct semid_ds32 *)A(pad); + mm_segment_t old_fs; + int need_back_translation; + + if (third == IPC_SET) { + err = get_user (s.sem_perm.uid, &usp->sem_perm.uid); + err |= __get_user (s.sem_perm.gid, &usp->sem_perm.gid); + err |= __get_user (s.sem_perm.mode, &usp->sem_perm.mode); + if (err) + goto out; + fourth.__pad = &s; + } + need_back_translation = + (IPCOP_MASK (third) & + (IPCOP_MASK (SEM_STAT) | IPCOP_MASK (IPC_STAT))) != 0; + if (need_back_translation) + fourth.__pad = &s; + old_fs = get_fs (); + set_fs (KERNEL_DS); + err = sys_semctl (first, second, third, fourth); + set_fs (old_fs); + if (need_back_translation) { + int err2 = put_user (s.sem_perm.key, &usp->sem_perm.key); + err2 |= __put_user (s.sem_perm.uid, &usp->sem_perm.uid); + err2 |= __put_user (s.sem_perm.gid, &usp->sem_perm.gid); + err2 |= __put_user (s.sem_perm.cuid, &usp->sem_perm.cuid); + err2 |= __put_user (s.sem_perm.cgid, &usp->sem_perm.cgid); + err2 |= __put_user (s.sem_perm.mode, &usp->sem_perm.mode); + err2 |= __put_user (s.sem_perm.seq, &usp->sem_perm.seq); + err2 |= __put_user (s.sem_otime, &usp->sem_otime); + err2 |= __put_user (s.sem_ctime, &usp->sem_ctime); + err2 |= __put_user (s.sem_nsems, &usp->sem_nsems); + if (err2) err = -EFAULT; + } + } +out: + return err; +} + +static int do_sys32_msgsnd (int first, int second, int third, void *uptr) +{ + struct msgbuf *p = kmalloc (second + sizeof (struct msgbuf) + 4, GFP_USER); + struct msgbuf32 *up = (struct msgbuf32 *)uptr; + mm_segment_t old_fs; + int err; + + if (!p) + return -ENOMEM; + err = get_user (p->mtype, &up->mtype); + err |= __copy_from_user (p->mtext, &up->mtext, second); + if (err) + goto out; + old_fs = get_fs (); + set_fs (KERNEL_DS); + err = sys_msgsnd (first, p, second, third); + set_fs (old_fs); +out: + kfree (p); + return err; +} + +static int do_sys32_msgrcv (int first, int second, int msgtyp, int third, + int version, void *uptr) +{ + struct msgbuf32 *up; + struct msgbuf *p; + mm_segment_t old_fs; + int err; + + if (!version) { + struct ipc_kludge *uipck = (struct ipc_kludge *)uptr; + struct ipc_kludge ipck; + + err = -EINVAL; + if (!uptr) + goto out; + err = -EFAULT; + if (copy_from_user (&ipck, uipck, sizeof (struct ipc_kludge))) + goto out; + uptr = (void *)A(ipck.msgp); + msgtyp = ipck.msgtyp; + } + err = -ENOMEM; + p = kmalloc (second + sizeof (struct msgbuf) + 4, GFP_USER); + if (!p) + goto out; + old_fs = get_fs (); + set_fs (KERNEL_DS); + err = sys_msgrcv (first, p, second + 4, msgtyp, third); + set_fs (old_fs); + if (err < 0) + goto free_then_out; + up = (struct msgbuf32 *)uptr; + if (put_user (p->mtype, &up->mtype) || + __copy_to_user (&up->mtext, p->mtext, err)) + err = -EFAULT; +free_then_out: + kfree (p); +out: + return err; +} + +static int do_sys32_msgctl (int first, int second, void *uptr) +{ + int err; + + if (IPCOP_MASK (second) & + (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (MSG_INFO) | + IPCOP_MASK (IPC_RMID))) { + err = sys_msgctl (first, second, (struct msqid_ds *)uptr); + } else { + struct msqid_ds m; + struct msqid_ds32 *up = (struct msqid_ds32 *)uptr; + mm_segment_t old_fs; + + if (second == IPC_SET) { + err = get_user (m.msg_perm.uid, &up->msg_perm.uid); + err |= __get_user (m.msg_perm.gid, &up->msg_perm.gid); + err |= __get_user (m.msg_perm.mode, &up->msg_perm.mode); + err |= __get_user (m.msg_qbytes, &up->msg_qbytes); + if (err) + goto out; + } + old_fs = get_fs (); + set_fs (KERNEL_DS); + err = sys_msgctl (first, second, &m); + set_fs (old_fs); + if (IPCOP_MASK (second) & + (IPCOP_MASK (MSG_STAT) | IPCOP_MASK (IPC_STAT))) { + int err2 = put_user (m.msg_perm.key, &up->msg_perm.key); + err2 |= __put_user (m.msg_perm.uid, &up->msg_perm.uid); + err2 |= __put_user (m.msg_perm.gid, &up->msg_perm.gid); + err2 |= __put_user (m.msg_perm.cuid, &up->msg_perm.cuid); + err2 |= __put_user (m.msg_perm.cgid, &up->msg_perm.cgid); + err2 |= __put_user (m.msg_perm.mode, &up->msg_perm.mode); + err2 |= __put_user (m.msg_perm.seq, &up->msg_perm.seq); + err2 |= __put_user (m.msg_stime, &up->msg_stime); + err2 |= __put_user (m.msg_rtime, &up->msg_rtime); + err2 |= __put_user (m.msg_ctime, &up->msg_ctime); + err2 |= __put_user (m.msg_cbytes, &up->msg_cbytes); + err2 |= __put_user (m.msg_qnum, &up->msg_qnum); + err2 |= __put_user (m.msg_qbytes, &up->msg_qbytes); + err2 |= __put_user (m.msg_lspid, &up->msg_lspid); + err2 |= __put_user (m.msg_lrpid, &up->msg_lrpid); + if (err2) + err = -EFAULT; + } + } + +out: + return err; +} + +static int do_sys32_shmat (int first, int second, int third, int version, void *uptr) +{ + unsigned long raddr; + u32 *uaddr = (u32 *)A((u32)third); + int err = -EINVAL; + + if (version == 1) + goto out; + err = sys_shmat (first, uptr, second, &raddr); + if (err) + goto out; + err = put_user (raddr, uaddr); +out: + return err; +} + +static int do_sys32_shmctl (int first, int second, void *uptr) +{ + int err; + + if (IPCOP_MASK (second) & + (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (SHM_LOCK) | IPCOP_MASK (SHM_UNLOCK) | + IPCOP_MASK (IPC_RMID))) { + err = sys_shmctl (first, second, (struct shmid_ds *)uptr); + } else { + struct shmid_ds s; + struct shmid_ds32 *up = (struct shmid_ds32 *)uptr; + mm_segment_t old_fs; + + if (second == IPC_SET) { + err = get_user (s.shm_perm.uid, &up->shm_perm.uid); + err |= __get_user (s.shm_perm.gid, &up->shm_perm.gid); + err |= __get_user (s.shm_perm.mode, &up->shm_perm.mode); + if (err) + goto out; + } + old_fs = get_fs (); + set_fs (KERNEL_DS); + err = sys_shmctl (first, second, &s); + set_fs (old_fs); + if (err < 0) + goto out; + + /* Mask it even in this case so it becomes a CSE. */ + if (second == SHM_INFO) { + struct shm_info32 { + int used_ids; + u32 shm_tot, shm_rss, shm_swp; + u32 swap_attempts, swap_successes; + } *uip = (struct shm_info32 *)uptr; + struct shm_info *kp = (struct shm_info *)&s; + int err2 = put_user (kp->used_ids, &uip->used_ids); + err2 |= __put_user (kp->shm_tot, &uip->shm_tot); + err2 |= __put_user (kp->shm_rss, &uip->shm_rss); + err2 |= __put_user (kp->shm_swp, &uip->shm_swp); + err2 |= __put_user (kp->swap_attempts, &uip->swap_attempts); + err2 |= __put_user (kp->swap_successes, &uip->swap_successes); + if (err2) + err = -EFAULT; + } else if (IPCOP_MASK (second) & + (IPCOP_MASK (SHM_STAT) | IPCOP_MASK (IPC_STAT))) { + int err2 = put_user (s.shm_perm.key, &up->shm_perm.key); + err2 |= __put_user (s.shm_perm.uid, &up->shm_perm.uid); + err2 |= __put_user (s.shm_perm.gid, &up->shm_perm.gid); + err2 |= __put_user (s.shm_perm.cuid, &up->shm_perm.cuid); + err2 |= __put_user (s.shm_perm.cgid, &up->shm_perm.cgid); + err2 |= __put_user (s.shm_perm.mode, &up->shm_perm.mode); + err2 |= __put_user (s.shm_perm.seq, &up->shm_perm.seq); + err2 |= __put_user (s.shm_atime, &up->shm_atime); + err2 |= __put_user (s.shm_dtime, &up->shm_dtime); + err2 |= __put_user (s.shm_ctime, &up->shm_ctime); + err2 |= __put_user (s.shm_segsz, &up->shm_segsz); + err2 |= __put_user (s.shm_nattch, &up->shm_nattch); + err2 |= __put_user (s.shm_cpid, &up->shm_cpid); + err2 |= __put_user (s.shm_lpid, &up->shm_lpid); + if (err2) + err = -EFAULT; + } + } +out: + return err; +} asmlinkage int sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth) { @@ -231,190 +502,32 @@ switch (call) { case SEMOP: /* struct sembuf is the same on 32 and 64bit :)) */ - err = sys_semop (first, (struct sembuf *)A(ptr), second); + err = sys_semop (first, (struct sembuf *)AA(ptr), second); goto out; case SEMGET: err = sys_semget (first, second, third); goto out; - case SEMCTL: { - union semun fourth; - void *pad; - mm_segment_t old_fs; - struct semid_ds s; - - err = -EINVAL; - if (!ptr) - goto out; - err = -EFAULT; - if(get_user(pad, (void **)A(ptr))) - goto out; - fourth.__pad = pad; - switch (third) { - case IPC_INFO: - case SEM_INFO: - case GETVAL: - case GETPID: - case GETNCNT: - case GETZCNT: - case GETALL: - case SETALL: - case IPC_RMID: - err = sys_semctl (first, second, third, fourth); - goto out; - case IPC_SET: - if (get_user (s.sem_perm.uid, &(((struct semid_ds32 *)A(pad))->sem_perm.uid)) || - __get_user (s.sem_perm.gid, &(((struct semid_ds32 *)A(pad))->sem_perm.gid)) || - __get_user (s.sem_perm.mode, &(((struct semid_ds32 *)A(pad))->sem_perm.mode))) { - err = -EFAULT; - goto out; - } - /* Fall through */ - case SEM_STAT: - case IPC_STAT: - fourth.__pad = &s; - break; - } - old_fs = get_fs(); - set_fs (KERNEL_DS); - err = sys_semctl (first, second, third, fourth); - set_fs (old_fs); - switch (third) { - case SEM_STAT: - case IPC_STAT: - if (put_user (s.sem_perm.key, &(((struct semid_ds32 *)A(pad))->sem_perm.key)) || - __put_user (s.sem_perm.uid, &(((struct semid_ds32 *)A(pad))->sem_perm.uid)) || - __put_user (s.sem_perm.gid, &(((struct semid_ds32 *)A(pad))->sem_perm.gid)) || - __put_user (s.sem_perm.cuid, &(((struct semid_ds32 *)A(pad))->sem_perm.cuid)) || - __put_user (s.sem_perm.cgid, &(((struct semid_ds32 *)A(pad))->sem_perm.cgid)) || - __put_user (s.sem_perm.mode, &(((struct semid_ds32 *)A(pad))->sem_perm.mode)) || - __put_user (s.sem_perm.seq, &(((struct semid_ds32 *)A(pad))->sem_perm.seq)) || - __put_user (s.sem_otime, &(((struct semid_ds32 *)A(pad))->sem_otime)) || - __put_user (s.sem_ctime, &(((struct semid_ds32 *)A(pad))->sem_ctime)) || - __put_user (s.sem_nsems, &(((struct semid_ds32 *)A(pad))->sem_nsems))) - err = -EFAULT; - } + case SEMCTL: + err = do_sys32_semctl (first, second, third, (void *)AA(ptr)); goto out; - } default: err = -EINVAL; goto out; - } + }; if (call <= MSGCTL) switch (call) { case MSGSND: - { - struct msgbuf *p = kmalloc (second + sizeof (struct msgbuf) + 4, GFP_KERNEL); - - if (!p) err = -ENOMEM; - else { - err = 0; - if (get_user(p->mtype, &(((struct msgbuf32 *)A(ptr))->mtype)) || - __copy_from_user(p->mtext, &(((struct msgbuf32 *)A(ptr))->mtext), second)) - err = -EFAULT; - if (!err) { - mm_segment_t old_fs = get_fs(); - set_fs (KERNEL_DS); - err = sys_msgsnd (first, p, second, third); - set_fs (old_fs); - } - kfree (p); - } - } + err = do_sys32_msgsnd (first, second, third, (void *)AA(ptr)); goto out; case MSGRCV: - { - struct msgbuf *p; - mm_segment_t old_fs; - long msgtyp = fifth; - - if (!version) { - struct ipc_kludge tmp; - err = -EINVAL; - if (!ptr) - goto out; - err = -EFAULT; - if(copy_from_user(&tmp,(struct ipc_kludge *)A(ptr), sizeof (tmp))) - goto out; - ptr = tmp.msgp; - msgtyp = tmp.msgtyp; - } - - p = kmalloc (second + sizeof (struct msgbuf) + 4, GFP_KERNEL); - if (!p) { - err = -EFAULT; - goto out; - } - - old_fs = get_fs(); - set_fs (KERNEL_DS); - err = sys_msgrcv (first, p, second + 4, msgtyp, third); - set_fs (old_fs); - - if (err < 0) - goto out; - - if (put_user (p->mtype, &(((struct msgbuf32 *)A(ptr))->mtype)) || - __copy_to_user(&(((struct msgbuf32 *)A(ptr))->mtext), p->mtext, err)) - err = -EFAULT; - kfree (p); - goto out; - } + err = do_sys32_msgrcv (first, second, fifth, third, + version, (void *)AA(ptr)); + goto out; case MSGGET: err = sys_msgget ((key_t) first, second); goto out; case MSGCTL: - { - struct msqid_ds m; - mm_segment_t old_fs; - - switch (second) { - case IPC_INFO: - case MSG_INFO: - /* struct msginfo is the same */ - case IPC_RMID: - /* and this doesn't care about ptr */ - err = sys_msgctl (first, second, (struct msqid_ds *)A(ptr)); - goto out; - - case IPC_SET: - if (get_user (m.msg_perm.uid, &(((struct msqid_ds32 *)A(ptr))->msg_perm.uid)) || - __get_user (m.msg_perm.gid, &(((struct msqid_ds32 *)A(ptr))->msg_perm.gid)) || - __get_user (m.msg_perm.mode, &(((struct msqid_ds32 *)A(ptr))->msg_perm.mode)) || - __get_user (m.msg_qbytes, &(((struct msqid_ds32 *)A(ptr))->msg_qbytes))) { - err = -EFAULT; - goto out; - } - default: - break; - } - old_fs = get_fs(); - set_fs (KERNEL_DS); - err = sys_msgctl (first, second, &m); - set_fs (old_fs); - switch (second) { - case MSG_STAT: - case IPC_STAT: - if (put_user (m.msg_perm.key, &(((struct msqid_ds32 *)A(ptr))->msg_perm.key)) || - __put_user (m.msg_perm.uid, &(((struct msqid_ds32 *)A(ptr))->msg_perm.uid)) || - __put_user (m.msg_perm.gid, &(((struct msqid_ds32 *)A(ptr))->msg_perm.gid)) || - __put_user (m.msg_perm.cuid, &(((struct msqid_ds32 *)A(ptr))->msg_perm.cuid)) || - __put_user (m.msg_perm.cgid, &(((struct msqid_ds32 *)A(ptr))->msg_perm.cgid)) || - __put_user (m.msg_perm.mode, &(((struct msqid_ds32 *)A(ptr))->msg_perm.mode)) || - __put_user (m.msg_perm.seq, &(((struct msqid_ds32 *)A(ptr))->msg_perm.seq)) || - __put_user (m.msg_stime, &(((struct msqid_ds32 *)A(ptr))->msg_stime)) || - __put_user (m.msg_rtime, &(((struct msqid_ds32 *)A(ptr))->msg_rtime)) || - __put_user (m.msg_ctime, &(((struct msqid_ds32 *)A(ptr))->msg_ctime)) || - __put_user (m.msg_cbytes, &(((struct msqid_ds32 *)A(ptr))->msg_cbytes)) || - __put_user (m.msg_qnum, &(((struct msqid_ds32 *)A(ptr))->msg_qnum)) || - __put_user (m.msg_qbytes, &(((struct msqid_ds32 *)A(ptr))->msg_qbytes)) || - __put_user (m.msg_lspid, &(((struct msqid_ds32 *)A(ptr))->msg_lspid)) || - __put_user (m.msg_lrpid, &(((struct msqid_ds32 *)A(ptr))->msg_lrpid))) - err = -EFAULT; - break; - default: - break; - } - } + err = do_sys32_msgctl (first, second, (void *)AA(ptr)); goto out; default: err = -EINVAL; @@ -423,95 +536,17 @@ if (call <= SHMCTL) switch (call) { case SHMAT: - switch (version) { - case 0: default: { - unsigned long raddr; - u32 *uptr = (u32 *) A(((u32)third)); - err = sys_shmat (first, (char *)A(ptr), second, &raddr); - if (err) - goto out; - err = -EFAULT; - if(put_user (raddr, uptr)) - goto out; - err = 0; - goto out; - } - case 1: /* If iBCS2 should ever run, then for sure in 64bit mode, not 32bit... */ - err = -EINVAL; - goto out; - } + err = do_sys32_shmat (first, second, third, + version, (void *)AA(ptr)); + goto out; case SHMDT: - err = sys_shmdt ((char *)A(ptr)); + err = sys_shmdt ((char *)AA(ptr)); goto out; case SHMGET: err = sys_shmget (first, second, third); goto out; case SHMCTL: - { - struct shmid_ds s; - mm_segment_t old_fs; - - switch (second) { - case IPC_INFO: - /* struct shminfo is the same */ - case SHM_LOCK: - case SHM_UNLOCK: - case IPC_RMID: - /* and these three aren't using ptr at all */ - err = sys_shmctl (first, second, (struct shmid_ds *)A(ptr)); - goto out; - - case IPC_SET: - if (get_user (s.shm_perm.uid, &(((struct shmid_ds32 *)A(ptr))->shm_perm.uid)) || - __get_user (s.shm_perm.gid, &(((struct shmid_ds32 *)A(ptr))->shm_perm.gid)) || - __get_user (s.shm_perm.mode, &(((struct shmid_ds32 *)A(ptr))->shm_perm.mode))) { - err = -EFAULT; - goto out; - } - default: - break; - } - old_fs = get_fs(); - set_fs (KERNEL_DS); - err = sys_shmctl (first, second, &s); - set_fs (old_fs); - switch (second) { - case SHM_INFO: - { - struct shm_info32 { int used_ids; u32 shm_tot; u32 shm_rss; u32 shm_swp; u32 swap_attempts; u32 swap_successes; }; - struct shm_info *si = (struct shm_info *)&s; - - if (put_user (si->used_ids, &(((struct shm_info32 *)A(ptr))->used_ids)) || - __put_user (si->shm_tot, &(((struct shm_info32 *)A(ptr))->shm_tot)) || - __put_user (si->shm_rss, &(((struct shm_info32 *)A(ptr))->shm_rss)) || - __put_user (si->shm_swp, &(((struct shm_info32 *)A(ptr))->shm_swp)) || - __put_user (si->swap_attempts, &(((struct shm_info32 *)A(ptr))->swap_attempts)) || - __put_user (si->swap_successes, &(((struct shm_info32 *)A(ptr))->swap_successes))) - err = -EFAULT; - } - break; - case SHM_STAT: - case IPC_STAT: - if (put_user (s.shm_perm.key, &(((struct shmid_ds32 *)A(ptr))->shm_perm.key)) || - __put_user (s.shm_perm.uid, &(((struct shmid_ds32 *)A(ptr))->shm_perm.uid)) || - __put_user (s.shm_perm.gid, &(((struct shmid_ds32 *)A(ptr))->shm_perm.gid)) || - __put_user (s.shm_perm.cuid, &(((struct shmid_ds32 *)A(ptr))->shm_perm.cuid)) || - __put_user (s.shm_perm.cgid, &(((struct shmid_ds32 *)A(ptr))->shm_perm.cgid)) || - __put_user (s.shm_perm.mode, &(((struct shmid_ds32 *)A(ptr))->shm_perm.mode)) || - __put_user (s.shm_perm.seq, &(((struct shmid_ds32 *)A(ptr))->shm_perm.seq)) || - __put_user (s.shm_atime, &(((struct shmid_ds32 *)A(ptr))->shm_atime)) || - __put_user (s.shm_dtime, &(((struct shmid_ds32 *)A(ptr))->shm_dtime)) || - __put_user (s.shm_ctime, &(((struct shmid_ds32 *)A(ptr))->shm_ctime)) || - __put_user (s.shm_segsz, &(((struct shmid_ds32 *)A(ptr))->shm_segsz)) || - __put_user (s.shm_nattch, &(((struct shmid_ds32 *)A(ptr))->shm_nattch)) || - __put_user (s.shm_lpid, &(((struct shmid_ds32 *)A(ptr))->shm_cpid)) || - __put_user (s.shm_cpid, &(((struct shmid_ds32 *)A(ptr))->shm_lpid))) - err = -EFAULT; - break; - default: - break; - } - } + err = do_sys32_shmctl (first, second, (void *)AA(ptr)); goto out; default: err = -EINVAL; @@ -527,29 +562,31 @@ static inline int get_flock(struct flock *kfl, struct flock32 *ufl) { - if(get_user(kfl->l_type, &ufl->l_type) || - __get_user(kfl->l_whence, &ufl->l_whence) || - __get_user(kfl->l_start, &ufl->l_start) || - __get_user(kfl->l_len, &ufl->l_len) || - __get_user(kfl->l_pid, &ufl->l_pid)) - return -EFAULT; - return 0; + int err; + + err = get_user(kfl->l_type, &ufl->l_type); + err |= __get_user(kfl->l_whence, &ufl->l_whence); + err |= __get_user(kfl->l_start, &ufl->l_start); + err |= __get_user(kfl->l_len, &ufl->l_len); + err |= __get_user(kfl->l_pid, &ufl->l_pid); + return err; } static inline int put_flock(struct flock *kfl, struct flock32 *ufl) { - if(__put_user(kfl->l_type, &ufl->l_type) || - __put_user(kfl->l_whence, &ufl->l_whence) || - __put_user(kfl->l_start, &ufl->l_start) || - __put_user(kfl->l_len, &ufl->l_len) || - __put_user(kfl->l_pid, &ufl->l_pid)) - return -EFAULT; - return 0; + int err; + + err = __put_user(kfl->l_type, &ufl->l_type); + err |= __put_user(kfl->l_whence, &ufl->l_whence); + err |= __put_user(kfl->l_start, &ufl->l_start); + err |= __put_user(kfl->l_len, &ufl->l_len); + err |= __put_user(kfl->l_pid, &ufl->l_pid); + return err; } extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg); -asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, u32 arg) +asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) { switch (cmd) { case F_GETLK: @@ -560,12 +597,12 @@ mm_segment_t old_fs; long ret; - if(get_flock(&f, (struct flock32 *)A(arg))) + if(get_flock(&f, (struct flock32 *)arg)) return -EFAULT; old_fs = get_fs(); set_fs (KERNEL_DS); ret = sys_fcntl(fd, cmd, (unsigned long)&f); set_fs (old_fs); - if(put_flock(&f, (struct flock32 *)A(arg))) + if(put_flock(&f, (struct flock32 *)arg)) return -EFAULT; return ret; } @@ -587,7 +624,7 @@ extern asmlinkage int sys_quotactl(int cmd, const char *special, int id, caddr_t addr); -asmlinkage int sys32_quotactl(int cmd, u32 special, int id, u32 addr) +asmlinkage int sys32_quotactl(int cmd, const char *special, int id, unsigned long addr) { int cmds = cmd >> SUBCMDSHIFT; int err; @@ -601,29 +638,29 @@ case Q_SETQUOTA: case Q_SETUSE: case Q_SETQLIM: - if (copy_from_user (&d, (struct dqblk32 *)A(addr), + if (copy_from_user (&d, (struct dqblk32 *)addr, sizeof (struct dqblk32))) return -EFAULT; d.dqb_itime = ((struct dqblk32 *)&d)->dqb_itime; d.dqb_btime = ((struct dqblk32 *)&d)->dqb_btime; break; default: - return sys_quotactl(cmd, (const char *)A(special), - id, (caddr_t)A(addr)); + return sys_quotactl(cmd, special, + id, (caddr_t)addr); } spec = getname32 (special); err = PTR_ERR(spec); if (IS_ERR(spec)) return err; old_fs = get_fs (); set_fs (KERNEL_DS); - err = sys_quotactl(cmd, (const char *)spec, id, (caddr_t)A(addr)); + err = sys_quotactl(cmd, (const char *)spec, id, (caddr_t)&d); set_fs (old_fs); putname32 (spec); if (cmds == Q_GETQUOTA) { __kernel_time_t b = d.dqb_btime, i = d.dqb_itime; ((struct dqblk32 *)&d)->dqb_itime = i; ((struct dqblk32 *)&d)->dqb_btime = b; - if (copy_to_user ((struct dqblk32 *)A(addr), &d, + if (copy_to_user ((struct dqblk32 *)addr, &d, sizeof (struct dqblk32))) return -EFAULT; } @@ -632,23 +669,24 @@ static inline int put_statfs (struct statfs32 *ubuf, struct statfs *kbuf) { - if (put_user (kbuf->f_type, &ubuf->f_type) || - __put_user (kbuf->f_bsize, &ubuf->f_bsize) || - __put_user (kbuf->f_blocks, &ubuf->f_blocks) || - __put_user (kbuf->f_bfree, &ubuf->f_bfree) || - __put_user (kbuf->f_bavail, &ubuf->f_bavail) || - __put_user (kbuf->f_files, &ubuf->f_files) || - __put_user (kbuf->f_ffree, &ubuf->f_ffree) || - __put_user (kbuf->f_namelen, &ubuf->f_namelen) || - __put_user (kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) || - __put_user (kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1])) - return -EFAULT; - return 0; + int err; + + err = put_user (kbuf->f_type, &ubuf->f_type); + err |= __put_user (kbuf->f_bsize, &ubuf->f_bsize); + err |= __put_user (kbuf->f_blocks, &ubuf->f_blocks); + err |= __put_user (kbuf->f_bfree, &ubuf->f_bfree); + err |= __put_user (kbuf->f_bavail, &ubuf->f_bavail); + err |= __put_user (kbuf->f_files, &ubuf->f_files); + err |= __put_user (kbuf->f_ffree, &ubuf->f_ffree); + err |= __put_user (kbuf->f_namelen, &ubuf->f_namelen); + err |= __put_user (kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]); + err |= __put_user (kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]); + return err; } extern asmlinkage int sys_statfs(const char * path, struct statfs * buf); -asmlinkage int sys32_statfs(u32 path, u32 buf) +asmlinkage int sys32_statfs(const char * path, struct statfs32 *buf) { int ret; struct statfs s; @@ -662,7 +700,7 @@ ret = sys_statfs((const char *)pth, &s); set_fs (old_fs); putname32 (pth); - if (put_statfs((struct statfs32 *)A(buf), &s)) + if (put_statfs(buf, &s)) return -EFAULT; } return ret; @@ -670,7 +708,7 @@ extern asmlinkage int sys_fstatfs(unsigned int fd, struct statfs * buf); -asmlinkage int sys32_fstatfs(unsigned int fd, u32 buf) +asmlinkage int sys32_fstatfs(unsigned int fd, struct statfs32 *buf) { int ret; struct statfs s; @@ -679,25 +717,28 @@ set_fs (KERNEL_DS); ret = sys_fstatfs(fd, &s); set_fs (old_fs); - if (put_statfs((struct statfs32 *)A(buf), &s)) + if (put_statfs(buf, &s)) return -EFAULT; return ret; } extern asmlinkage int sys_utime(char * filename, struct utimbuf * times); -asmlinkage int sys32_utime(u32 filename, u32 times) +struct utimbuf32 { + __kernel_time_t32 actime, modtime; +}; + +asmlinkage int sys32_utime(char * filename, struct utimbuf32 *times) { - struct utimbuf32 { __kernel_time_t32 actime, modtime; }; struct utimbuf t; mm_segment_t old_fs; int ret; char *filenam; if (!times) - return sys_utime((char *)A(filename), NULL); - if (get_user (t.actime, &(((struct utimbuf32 *)A(times))->actime)) || - __get_user (t.modtime, &(((struct utimbuf32 *)A(times))->modtime))) + return sys_utime(filename, NULL); + if (get_user (t.actime, ×->actime) || + __get_user (t.modtime, ×->modtime)) return -EFAULT; filenam = getname32 (filename); ret = PTR_ERR(filenam); @@ -813,7 +854,7 @@ return retval; } -asmlinkage long sys32_readv(int fd, u32 vector, u32 count) +asmlinkage long sys32_readv(int fd, struct iovec32 *vector, u32 count) { struct file *file; long ret = -EBADF; @@ -827,7 +868,7 @@ goto out; ret = do_readv_writev32(VERIFY_WRITE, file, - (struct iovec32 *)A(vector), count); + vector, count); out: fput(file); bad_file: @@ -835,7 +876,7 @@ return ret; } -asmlinkage long sys32_writev(int fd, u32 vector, u32 count) +asmlinkage long sys32_writev(int fd, struct iovec32 *vector, u32 count) { struct file *file; int ret = -EBADF; @@ -850,7 +891,7 @@ down(&file->f_dentry->d_inode->i_sem); ret = do_readv_writev32(VERIFY_READ, file, - (struct iovec32 *)A(vector), count); + vector, count); up(&file->f_dentry->d_inode->i_sem); out: fput(file); @@ -894,7 +935,7 @@ return 0; } -asmlinkage int old32_readdir(unsigned int fd, u32 dirent, unsigned int count) +asmlinkage int old32_readdir(unsigned int fd, struct old_linux_dirent32 *dirent, unsigned int count) { int error = -EBADF; struct file * file; @@ -907,7 +948,7 @@ goto out; buf.count = 0; - buf.dirent = (struct old_linux_dirent32 *)A(dirent); + buf.dirent = dirent; error = -ENOTDIR; if (!file->f_op || !file->f_op->readdir) @@ -966,7 +1007,7 @@ return 0; } -asmlinkage int sys32_getdents(unsigned int fd, u32 dirent, unsigned int count) +asmlinkage int sys32_getdents(unsigned int fd, struct linux_dirent32 *dirent, unsigned int count) { struct file * file; struct inode * inode; @@ -979,7 +1020,7 @@ if (!file) goto out; - buf.current_dir = (struct linux_dirent32 *) A(dirent); + buf.current_dir = dirent; buf.previous = NULL; buf.count = count; buf.error = 0; @@ -1015,10 +1056,8 @@ */ static inline int -get_fd_set32(unsigned long n, unsigned long *fdset, u32 ufdset_x) +get_fd_set32(unsigned long n, unsigned long *fdset, u32 *ufdset) { - u32 *ufdset = (u32 *)A(ufdset_x); - if (ufdset) { unsigned long odd; @@ -1048,10 +1087,9 @@ } static inline void -set_fd_set32(unsigned long n, u32 ufdset_x, unsigned long *fdset) +set_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset) { unsigned long odd; - u32 *ufdset = (u32 *)A(ufdset_x); if (!ufdset) return; @@ -1071,10 +1109,10 @@ __put_user(*fdset, ufdset); } -asmlinkage int sys32_select(int n, u32 inp, u32 outp, u32 exp, u32 tvp_x) +asmlinkage int sys32_select(int n, u32 *inp, u32 *outp, u32 *exp, u32 tvp_x) { fd_set_buffer *fds; - struct timeval32 *tvp = (struct timeval32 *)A(tvp_x); + struct timeval32 *tvp = (struct timeval32 *)AA(tvp_x); unsigned long timeout, nn; int ret; @@ -1148,26 +1186,27 @@ static inline int putstat(struct stat32 *ubuf, struct stat *kbuf) { - if (put_user (kbuf->st_dev, &ubuf->st_dev) || - __put_user (kbuf->st_ino, &ubuf->st_ino) || - __put_user (kbuf->st_mode, &ubuf->st_mode) || - __put_user (kbuf->st_nlink, &ubuf->st_nlink) || - __put_user (kbuf->st_uid, &ubuf->st_uid) || - __put_user (kbuf->st_gid, &ubuf->st_gid) || - __put_user (kbuf->st_rdev, &ubuf->st_rdev) || - __put_user (kbuf->st_size, &ubuf->st_size) || - __put_user (kbuf->st_atime, &ubuf->st_atime) || - __put_user (kbuf->st_mtime, &ubuf->st_mtime) || - __put_user (kbuf->st_ctime, &ubuf->st_ctime) || - __put_user (kbuf->st_blksize, &ubuf->st_blksize) || - __put_user (kbuf->st_blocks, &ubuf->st_blocks)) - return -EFAULT; - return 0; + int err; + + err = put_user (kbuf->st_dev, &ubuf->st_dev); + err |= __put_user (kbuf->st_ino, &ubuf->st_ino); + err |= __put_user (kbuf->st_mode, &ubuf->st_mode); + err |= __put_user (kbuf->st_nlink, &ubuf->st_nlink); + err |= __put_user (kbuf->st_uid, &ubuf->st_uid); + err |= __put_user (kbuf->st_gid, &ubuf->st_gid); + err |= __put_user (kbuf->st_rdev, &ubuf->st_rdev); + err |= __put_user (kbuf->st_size, &ubuf->st_size); + err |= __put_user (kbuf->st_atime, &ubuf->st_atime); + err |= __put_user (kbuf->st_mtime, &ubuf->st_mtime); + err |= __put_user (kbuf->st_ctime, &ubuf->st_ctime); + err |= __put_user (kbuf->st_blksize, &ubuf->st_blksize); + err |= __put_user (kbuf->st_blocks, &ubuf->st_blocks); + return err; } extern asmlinkage int sys_newstat(char * filename, struct stat * statbuf); -asmlinkage int sys32_newstat(u32 filename, u32 statbuf) +asmlinkage int sys32_newstat(char * filename, struct stat32 *statbuf) { int ret; struct stat s; @@ -1181,7 +1220,7 @@ ret = sys_newstat(filenam, &s); set_fs (old_fs); putname32 (filenam); - if (putstat ((struct stat32 *)A(statbuf), &s)) + if (putstat (statbuf, &s)) return -EFAULT; } return ret; @@ -1189,7 +1228,7 @@ extern asmlinkage int sys_newlstat(char * filename, struct stat * statbuf); -asmlinkage int sys32_newlstat(u32 filename, u32 statbuf) +asmlinkage int sys32_newlstat(char * filename, struct stat32 *statbuf) { int ret; struct stat s; @@ -1203,7 +1242,7 @@ ret = sys_newlstat(filenam, &s); set_fs (old_fs); putname32 (filenam); - if (putstat ((struct stat32 *)A(statbuf), &s)) + if (putstat (statbuf, &s)) return -EFAULT; } return ret; @@ -1211,7 +1250,7 @@ extern asmlinkage int sys_newfstat(unsigned int fd, struct stat * statbuf); -asmlinkage int sys32_newfstat(unsigned int fd, u32 statbuf) +asmlinkage int sys32_newfstat(unsigned int fd, struct stat32 *statbuf) { int ret; struct stat s; @@ -1220,7 +1259,7 @@ set_fs (KERNEL_DS); ret = sys_newfstat(fd, &s); set_fs (old_fs); - if (putstat ((struct stat32 *)A(statbuf), &s)) + if (putstat (statbuf, &s)) return -EFAULT; return ret; } @@ -1318,7 +1357,7 @@ #define SMBFS_NAME "smbfs" #define NCPFS_NAME "ncpfs" -asmlinkage int sys32_mount(u32 dev_name, u32 dir_name, u32 type, u32 new_flags, u32 data) +asmlinkage int sys32_mount(char *dev_name, char *dir_name, char *type, unsigned long new_flags, u32 data) { unsigned long type_page; int err, is_smb, is_ncp; @@ -1326,7 +1365,7 @@ if(!capable(CAP_SYS_ADMIN)) return -EPERM; is_smb = is_ncp = 0; - err = copy_mount_stuff_to_kernel((const void *)A(type), &type_page); + err = copy_mount_stuff_to_kernel((const void *)type, &type_page); if(err) return err; if(type_page) { @@ -1336,20 +1375,18 @@ if(!is_smb && !is_ncp) { if(type_page) free_page(type_page); - return sys_mount((char *)A(dev_name), (char *)A(dir_name), - (char *)A(type), (unsigned long)new_flags, - (void *)A(data)); + return sys_mount(dev_name, dir_name, type, new_flags, (void *)AA(data)); } else { unsigned long dev_page, dir_page, data_page; mm_segment_t old_fs; - err = copy_mount_stuff_to_kernel((const void *)A(dev_name), &dev_page); + err = copy_mount_stuff_to_kernel((const void *)dev_name, &dev_page); if(err) goto out; - err = copy_mount_stuff_to_kernel((const void *)A(dir_name), &dir_page); + err = copy_mount_stuff_to_kernel((const void *)dir_name, &dir_page); if(err) goto dev_out; - err = copy_mount_stuff_to_kernel((const void *)A(data), &data_page); + err = copy_mount_stuff_to_kernel((const void *)AA(data), &data_page); if(err) goto dir_out; if(is_ncp) @@ -1361,7 +1398,7 @@ old_fs = get_fs(); set_fs(KERNEL_DS); err = sys_mount((char *)dev_page, (char *)dir_page, - (char *)type_page, (unsigned long)new_flags, + (char *)type_page, new_flags, (void *)data_page); set_fs(old_fs); @@ -1399,37 +1436,38 @@ s32 ru_nivcsw; }; -static int put_rusage (u32 ru, struct rusage *r) +static int put_rusage (struct rusage32 *ru, struct rusage *r) { - if (put_user (r->ru_utime.tv_sec, &(((struct rusage32 *)A(ru))->ru_utime.tv_sec)) || - __put_user (r->ru_utime.tv_usec, &(((struct rusage32 *)A(ru))->ru_utime.tv_usec)) || - __put_user (r->ru_stime.tv_sec, &(((struct rusage32 *)A(ru))->ru_stime.tv_sec)) || - __put_user (r->ru_stime.tv_usec, &(((struct rusage32 *)A(ru))->ru_stime.tv_usec)) || - __put_user (r->ru_maxrss, &(((struct rusage32 *)A(ru))->ru_maxrss)) || - __put_user (r->ru_ixrss, &(((struct rusage32 *)A(ru))->ru_ixrss)) || - __put_user (r->ru_idrss, &(((struct rusage32 *)A(ru))->ru_idrss)) || - __put_user (r->ru_isrss, &(((struct rusage32 *)A(ru))->ru_isrss)) || - __put_user (r->ru_minflt, &(((struct rusage32 *)A(ru))->ru_minflt)) || - __put_user (r->ru_majflt, &(((struct rusage32 *)A(ru))->ru_majflt)) || - __put_user (r->ru_nswap, &(((struct rusage32 *)A(ru))->ru_nswap)) || - __put_user (r->ru_inblock, &(((struct rusage32 *)A(ru))->ru_inblock)) || - __put_user (r->ru_oublock, &(((struct rusage32 *)A(ru))->ru_oublock)) || - __put_user (r->ru_msgsnd, &(((struct rusage32 *)A(ru))->ru_msgsnd)) || - __put_user (r->ru_msgrcv, &(((struct rusage32 *)A(ru))->ru_msgrcv)) || - __put_user (r->ru_nsignals, &(((struct rusage32 *)A(ru))->ru_nsignals)) || - __put_user (r->ru_nvcsw, &(((struct rusage32 *)A(ru))->ru_nvcsw)) || - __put_user (r->ru_nivcsw, &(((struct rusage32 *)A(ru))->ru_nivcsw))) - return -EFAULT; - return 0; + int err; + + err = put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec); + err |= __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec); + err |= __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec); + err |= __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec); + err |= __put_user (r->ru_maxrss, &ru->ru_maxrss); + err |= __put_user (r->ru_ixrss, &ru->ru_ixrss); + err |= __put_user (r->ru_idrss, &ru->ru_idrss); + err |= __put_user (r->ru_isrss, &ru->ru_isrss); + err |= __put_user (r->ru_minflt, &ru->ru_minflt); + err |= __put_user (r->ru_majflt, &ru->ru_majflt); + err |= __put_user (r->ru_nswap, &ru->ru_nswap); + err |= __put_user (r->ru_inblock, &ru->ru_inblock); + err |= __put_user (r->ru_oublock, &ru->ru_oublock); + err |= __put_user (r->ru_msgsnd, &ru->ru_msgsnd); + err |= __put_user (r->ru_msgrcv, &ru->ru_msgrcv); + err |= __put_user (r->ru_nsignals, &ru->ru_nsignals); + err |= __put_user (r->ru_nvcsw, &ru->ru_nvcsw); + err |= __put_user (r->ru_nivcsw, &ru->ru_nivcsw); + return err; } extern asmlinkage int sys_wait4(pid_t pid,unsigned int * stat_addr, int options, struct rusage * ru); -asmlinkage int sys32_wait4(__kernel_pid_t32 pid, u32 stat_addr, int options, u32 ru) +asmlinkage int sys32_wait4(__kernel_pid_t32 pid, unsigned int *stat_addr, int options, struct rusage32 *ru) { if (!ru) - return sys_wait4(pid, (unsigned int *)A(stat_addr), options, NULL); + return sys_wait4(pid, stat_addr, options, NULL); else { struct rusage r; int ret; @@ -1440,7 +1478,7 @@ ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r); set_fs (old_fs); if (put_rusage (ru, &r)) return -EFAULT; - if (stat_addr && put_user (status, (unsigned int *)A(stat_addr))) + if (stat_addr && put_user (status, stat_addr)) return -EFAULT; return ret; } @@ -1461,26 +1499,27 @@ extern asmlinkage int sys_sysinfo(struct sysinfo *info); -asmlinkage int sys32_sysinfo(u32 info) +asmlinkage int sys32_sysinfo(struct sysinfo32 *info) { struct sysinfo s; - int ret; + int ret, err; mm_segment_t old_fs = get_fs (); set_fs (KERNEL_DS); ret = sys_sysinfo(&s); set_fs (old_fs); - if (put_user (s.uptime, &(((struct sysinfo32 *)A(info))->uptime)) || - __put_user (s.loads[0], &(((struct sysinfo32 *)A(info))->loads[0])) || - __put_user (s.loads[1], &(((struct sysinfo32 *)A(info))->loads[1])) || - __put_user (s.loads[2], &(((struct sysinfo32 *)A(info))->loads[2])) || - __put_user (s.totalram, &(((struct sysinfo32 *)A(info))->totalram)) || - __put_user (s.freeram, &(((struct sysinfo32 *)A(info))->freeram)) || - __put_user (s.sharedram, &(((struct sysinfo32 *)A(info))->sharedram)) || - __put_user (s.bufferram, &(((struct sysinfo32 *)A(info))->bufferram)) || - __put_user (s.totalswap, &(((struct sysinfo32 *)A(info))->totalswap)) || - __put_user (s.freeswap, &(((struct sysinfo32 *)A(info))->freeswap)) || - __put_user (s.procs, &(((struct sysinfo32 *)A(info))->procs))) + err = put_user (s.uptime, &info->uptime); + err |= __put_user (s.loads[0], &info->loads[0]); + err |= __put_user (s.loads[1], &info->loads[1]); + err |= __put_user (s.loads[2], &info->loads[2]); + err |= __put_user (s.totalram, &info->totalram); + err |= __put_user (s.freeram, &info->freeram); + err |= __put_user (s.sharedram, &info->sharedram); + err |= __put_user (s.bufferram, &info->bufferram); + err |= __put_user (s.totalswap, &info->totalswap); + err |= __put_user (s.freeswap, &info->freeswap); + err |= __put_user (s.procs, &info->procs); + if (err) return -EFAULT; return ret; } @@ -1492,7 +1531,7 @@ extern asmlinkage int sys_sched_rr_get_interval(pid_t pid, struct timespec *interval); -asmlinkage int sys32_sched_rr_get_interval(__kernel_pid_t32 pid, u32 interval) +asmlinkage int sys32_sched_rr_get_interval(__kernel_pid_t32 pid, struct timespec32 *interval) { struct timespec t; int ret; @@ -1501,29 +1540,29 @@ set_fs (KERNEL_DS); ret = sys_sched_rr_get_interval(pid, &t); set_fs (old_fs); - if (put_user (t.tv_sec, &(((struct timespec32 *)A(interval))->tv_sec)) || - __put_user (t.tv_nsec, &(((struct timespec32 *)A(interval))->tv_nsec))) + if (put_user (t.tv_sec, &interval->tv_sec) || + __put_user (t.tv_nsec, &interval->tv_nsec)) return -EFAULT; return ret; } extern asmlinkage int sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp); -asmlinkage int sys32_nanosleep(u32 rqtp, u32 rmtp) +asmlinkage int sys32_nanosleep(struct timespec32 *rqtp, struct timespec32 *rmtp) { struct timespec t; int ret; mm_segment_t old_fs = get_fs (); - if (get_user (t.tv_sec, &(((struct timespec32 *)A(rqtp))->tv_sec)) || - __get_user (t.tv_nsec, &(((struct timespec32 *)A(rqtp))->tv_nsec))) + if (get_user (t.tv_sec, &rqtp->tv_sec) || + __get_user (t.tv_nsec, &rqtp->tv_nsec)) return -EFAULT; set_fs (KERNEL_DS); ret = sys_nanosleep(&t, rmtp ? &t : NULL); set_fs (old_fs); if (rmtp && ret == -EINTR) { - if (__put_user (t.tv_sec, &(((struct timespec32 *)A(rmtp))->tv_sec)) || - __put_user (t.tv_nsec, &(((struct timespec32 *)A(rmtp))->tv_nsec))) + if (__put_user (t.tv_sec, &rmtp->tv_sec) || + __put_user (t.tv_nsec, &rmtp->tv_nsec)) return -EFAULT; } return ret; @@ -1531,24 +1570,24 @@ extern asmlinkage int sys_sigprocmask(int how, old_sigset_t *set, old_sigset_t *oset); -asmlinkage int sys32_sigprocmask(int how, u32 set, u32 oset) +asmlinkage int sys32_sigprocmask(int how, old_sigset_t32 *set, old_sigset_t32 *oset) { old_sigset_t s; int ret; mm_segment_t old_fs = get_fs(); - if (set && get_user (s, (old_sigset_t32 *)A(set))) return -EFAULT; + if (set && get_user (s, set)) return -EFAULT; set_fs (KERNEL_DS); ret = sys_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL); set_fs (old_fs); if (ret) return ret; - if (oset && put_user (s, (old_sigset_t32 *)A(oset))) return -EFAULT; + if (oset && put_user (s, oset)) return -EFAULT; return 0; } extern asmlinkage int sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, size_t sigsetsize); -asmlinkage int sys32_rt_sigprocmask(int how, u32 set, u32 oset, __kernel_size_t32 sigsetsize) +asmlinkage int sys32_rt_sigprocmask(int how, sigset_t32 *set, sigset_t32 *oset, __kernel_size_t32 sigsetsize) { sigset_t s; sigset_t32 s32; @@ -1556,7 +1595,7 @@ mm_segment_t old_fs = get_fs(); if (set) { - if (copy_from_user (&s32, (sigset_t32 *)A(set), sizeof(sigset_t32))) + if (copy_from_user (&s32, set, sizeof(sigset_t32))) return -EFAULT; switch (_NSIG_WORDS) { case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32); @@ -1576,7 +1615,7 @@ case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1]; case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0]; } - if (copy_to_user ((sigset_t32 *)A(set), &s32, sizeof(sigset_t32))) + if (copy_to_user (oset, &s32, sizeof(sigset_t32))) return -EFAULT; } return 0; @@ -1584,7 +1623,7 @@ extern asmlinkage int sys_sigpending(old_sigset_t *set); -asmlinkage int sys32_sigpending(u32 set) +asmlinkage int sys32_sigpending(old_sigset_t32 *set) { old_sigset_t s; int ret; @@ -1593,13 +1632,13 @@ set_fs (KERNEL_DS); ret = sys_sigpending(&s); set_fs (old_fs); - if (put_user (s, (old_sigset_t32 *)A(set))) return -EFAULT; + if (put_user (s, set)) return -EFAULT; return ret; } extern asmlinkage int sys_rt_sigpending(sigset_t *set, size_t sigsetsize); -asmlinkage int sys32_rt_sigpending(u32 set, __kernel_size_t32 sigsetsize) +asmlinkage int sys32_rt_sigpending(sigset_t32 *set, __kernel_size_t32 sigsetsize) { sigset_t s; sigset_t32 s32; @@ -1616,7 +1655,7 @@ case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1]; case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0]; } - if (copy_to_user ((sigset_t32 *)A(set), &s32, sizeof(sigset_t32))) + if (copy_to_user (set, &s32, sizeof(sigset_t32))) return -EFAULT; } return ret; @@ -1706,8 +1745,8 @@ const struct timespec *uts, size_t sigsetsize); asmlinkage int -sys32_rt_sigtimedwait(u32 uthese, u32 uinfo, - u32 uts, __kernel_size_t32 sigsetsize) +sys32_rt_sigtimedwait(sigset_t32 *uthese, siginfo_t32 *uinfo, + struct timespec32 *uts, __kernel_size_t32 sigsetsize) { sigset_t s; sigset_t32 s32; @@ -1717,7 +1756,7 @@ siginfo_t info; siginfo_t32 info32; - if (copy_from_user (&s32, (sigset_t32 *)A(uthese), sizeof(sigset_t32))) + if (copy_from_user (&s32, uthese, sizeof(sigset_t32))) return -EFAULT; switch (_NSIG_WORDS) { case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32); @@ -1726,15 +1765,16 @@ case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32); } if (uts) { - if (get_user (t.tv_sec, &(((struct timespec32 *)A(uts))->tv_sec)) || - __get_user (t.tv_nsec, &(((struct timespec32 *)A(uts))->tv_nsec))) + ret = get_user (t.tv_sec, &uts->tv_sec); + ret |= __get_user (t.tv_nsec, &uts->tv_nsec); + if (ret) return -EFAULT; } set_fs (KERNEL_DS); ret = sys_rt_sigtimedwait(&s, &info, &t, sigsetsize); set_fs (old_fs); if (ret >= 0 && uinfo) { - if (copy_to_user ((siginfo_t32 *)A(uinfo), siginfo64to32(&info32, &info), sizeof(siginfo_t32))) + if (copy_to_user (uinfo, siginfo64to32(&info32, &info), sizeof(siginfo_t32))) return -EFAULT; } return ret; @@ -1744,14 +1784,14 @@ sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo); asmlinkage int -sys32_rt_sigqueueinfo(int pid, int sig, u32 uinfo) +sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 *uinfo) { siginfo_t info; siginfo_t32 info32; int ret; mm_segment_t old_fs = get_fs(); - if (copy_from_user (&info32, (siginfo_t32 *)A(uinfo), sizeof(siginfo_t32))) + if (copy_from_user (&info32, uinfo, sizeof(siginfo_t32))) return -EFAULT; /* XXX: Is this correct? */ siginfo32to64(&info, &info32); @@ -1788,7 +1828,7 @@ extern asmlinkage int sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); -asmlinkage int sys32_getresuid(u32 ruid, u32 euid, u32 suid) +asmlinkage int sys32_getresuid(__kernel_uid_t32 *ruid, __kernel_uid_t32 *euid, __kernel_uid_t32 *suid) { uid_t a, b, c; int ret; @@ -1797,9 +1837,7 @@ set_fs (KERNEL_DS); ret = sys_getresuid(&a, &b, &c); set_fs (old_fs); - if (put_user (a, (__kernel_uid_t32 *)A(ruid)) || - put_user (b, (__kernel_uid_t32 *)A(euid)) || - put_user (c, (__kernel_uid_t32 *)A(suid))) + if (put_user (a, ruid) || put_user (b, euid) || put_user (c, suid)) return -EFAULT; return ret; } @@ -1831,7 +1869,7 @@ extern asmlinkage int sys_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); -asmlinkage int sys32_getresgid(u32 rgid, u32 egid, u32 sgid) +asmlinkage int sys32_getresgid(__kernel_gid_t32 *rgid, __kernel_gid_t32 *egid, __kernel_gid_t32 *sgid) { gid_t a, b, c; int ret; @@ -1840,10 +1878,11 @@ set_fs (KERNEL_DS); ret = sys_getresgid(&a, &b, &c); set_fs (old_fs); - if (put_user (a, (__kernel_gid_t32 *)A(rgid)) || - put_user (b, (__kernel_gid_t32 *)A(egid)) || - put_user (c, (__kernel_gid_t32 *)A(sgid))) - return -EFAULT; + if (!ret) { + ret = put_user (a, rgid); + ret |= put_user (b, egid); + ret |= put_user (c, sgid); + } return ret; } @@ -1856,27 +1895,30 @@ extern asmlinkage long sys_times(struct tms * tbuf); -asmlinkage long sys32_times(u32 tbuf) +asmlinkage long sys32_times(struct tms32 *tbuf) { struct tms t; long ret; mm_segment_t old_fs = get_fs (); + int err; set_fs (KERNEL_DS); ret = sys_times(tbuf ? &t : NULL); set_fs (old_fs); - if (tbuf && ( - put_user (t.tms_utime, &(((struct tms32 *)A(tbuf))->tms_utime)) || - __put_user (t.tms_stime, &(((struct tms32 *)A(tbuf))->tms_stime)) || - __put_user (t.tms_cutime, &(((struct tms32 *)A(tbuf))->tms_cutime)) || - __put_user (t.tms_cstime, &(((struct tms32 *)A(tbuf))->tms_cstime)))) - return -EFAULT; + if (tbuf) { + err = put_user (t.tms_utime, &tbuf->tms_utime); + err |= __put_user (t.tms_stime, &tbuf->tms_stime); + err |= __put_user (t.tms_cutime, &tbuf->tms_cutime); + err |= __put_user (t.tms_cstime, &tbuf->tms_cstime); + if (err) + ret = -EFAULT; + } return ret; } extern asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist); -asmlinkage int sys32_getgroups(int gidsetsize, u32 grouplist) +asmlinkage int sys32_getgroups(int gidsetsize, __kernel_gid_t32 *grouplist) { gid_t gl[NGROUPS]; int ret, i; @@ -1886,15 +1928,15 @@ ret = sys_getgroups(gidsetsize, gl); set_fs (old_fs); if (gidsetsize && ret > 0 && ret <= NGROUPS) - for (i = 0; i < ret; i++, grouplist += sizeof(__kernel_gid_t32)) - if (__put_user (gl[i], (__kernel_gid_t32 *)A(grouplist))) + for (i = 0; i < ret; i++, grouplist++) + if (__put_user (gl[i], grouplist)) return -EFAULT; return ret; } extern asmlinkage int sys_setgroups(int gidsetsize, gid_t *grouplist); -asmlinkage int sys32_setgroups(int gidsetsize, u32 grouplist) +asmlinkage int sys32_setgroups(int gidsetsize, __kernel_gid_t32 *grouplist) { gid_t gl[NGROUPS]; int ret, i; @@ -1902,8 +1944,8 @@ if ((unsigned) gidsetsize > NGROUPS) return -EINVAL; - for (i = 0; i < gidsetsize; i++, grouplist += sizeof(__kernel_gid_t32)) - if (__get_user (gl[i], (__kernel_gid_t32 *)A(grouplist))) + for (i = 0; i < gidsetsize; i++, grouplist++) + if (__get_user (gl[i], grouplist)) return -EFAULT; set_fs (KERNEL_DS); ret = sys_setgroups(gidsetsize, gl); @@ -1921,7 +1963,7 @@ extern asmlinkage int sys_getrlimit(unsigned int resource, struct rlimit *rlim); -asmlinkage int sys32_getrlimit(unsigned int resource, u32 rlim) +asmlinkage int sys32_getrlimit(unsigned int resource, struct rlimit32 *rlim) { struct rlimit r; int ret; @@ -1930,24 +1972,24 @@ set_fs (KERNEL_DS); ret = sys_getrlimit(resource, &r); set_fs (old_fs); - if (!ret && ( - put_user (RESOURCE32(r.rlim_cur), &(((struct rlimit32 *)A(rlim))->rlim_cur)) || - __put_user (RESOURCE32(r.rlim_max), &(((struct rlimit32 *)A(rlim))->rlim_max)))) - return -EFAULT; + if (!ret) { + ret = put_user (RESOURCE32(r.rlim_cur), &rlim->rlim_cur); + ret |= __put_user (RESOURCE32(r.rlim_max), &rlim->rlim_max); + } return ret; } extern asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim); -asmlinkage int sys32_setrlimit(unsigned int resource, u32 rlim) +asmlinkage int sys32_setrlimit(unsigned int resource, struct rlimit32 *rlim) { struct rlimit r; int ret; mm_segment_t old_fs = get_fs (); if (resource >= RLIM_NLIMITS) return -EINVAL; - if (get_user (r.rlim_cur, &(((struct rlimit32 *)A(rlim))->rlim_cur)) || - __get_user (r.rlim_max, &(((struct rlimit32 *)A(rlim))->rlim_max))) + if (get_user (r.rlim_cur, &rlim->rlim_cur) || + __get_user (r.rlim_max, &rlim->rlim_max)) return -EFAULT; if (r.rlim_cur == RLIM_INFINITY32) r.rlim_cur = RLIM_INFINITY; @@ -1961,7 +2003,7 @@ extern asmlinkage int sys_getrusage(int who, struct rusage *ru); -asmlinkage int sys32_getrusage(int who, u32 ru) +asmlinkage int sys32_getrusage(int who, struct rusage32 *ru) { struct rusage r; int ret; @@ -1999,49 +2041,46 @@ int :32; int :32; int :32; int :32; }; -extern asmlinkage int sys_adjtimex(struct timex *txc_p); +extern int do_adjtimex(struct timex *); -asmlinkage int sys32_adjtimex(u32 txc_p) +asmlinkage int sys32_adjtimex(struct timex32 *txc_p) { struct timex t; int ret; - mm_segment_t old_fs = get_fs (); - if (get_user (t.modes, &(((struct timex32 *)A(txc_p))->modes)) || - __get_user (t.offset, &(((struct timex32 *)A(txc_p))->offset)) || - __get_user (t.freq, &(((struct timex32 *)A(txc_p))->freq)) || - __get_user (t.maxerror, &(((struct timex32 *)A(txc_p))->maxerror)) || - __get_user (t.esterror, &(((struct timex32 *)A(txc_p))->esterror)) || - __get_user (t.status, &(((struct timex32 *)A(txc_p))->status)) || - __get_user (t.constant, &(((struct timex32 *)A(txc_p))->constant)) || - __get_user (t.tick, &(((struct timex32 *)A(txc_p))->tick)) || - __get_user (t.shift, &(((struct timex32 *)A(txc_p))->shift))) - return -EFAULT; - set_fs (KERNEL_DS); - ret = sys_adjtimex(&t); - set_fs (old_fs); - if ((unsigned)ret >= 0 && ( - __put_user (t.modes, &(((struct timex32 *)A(txc_p))->modes)) || - __put_user (t.offset, &(((struct timex32 *)A(txc_p))->offset)) || - __put_user (t.freq, &(((struct timex32 *)A(txc_p))->freq)) || - __put_user (t.maxerror, &(((struct timex32 *)A(txc_p))->maxerror)) || - __put_user (t.esterror, &(((struct timex32 *)A(txc_p))->esterror)) || - __put_user (t.status, &(((struct timex32 *)A(txc_p))->status)) || - __put_user (t.constant, &(((struct timex32 *)A(txc_p))->constant)) || - __put_user (t.precision, &(((struct timex32 *)A(txc_p))->precision)) || - __put_user (t.tolerance, &(((struct timex32 *)A(txc_p))->tolerance)) || - __put_user (t.time.tv_sec, &(((struct timex32 *)A(txc_p))->time.tv_sec)) || - __put_user (t.time.tv_usec, &(((struct timex32 *)A(txc_p))->time.tv_usec)) || - __put_user (t.tick, &(((struct timex32 *)A(txc_p))->tick)) || - __put_user (t.ppsfreq, &(((struct timex32 *)A(txc_p))->ppsfreq)) || - __put_user (t.jitter, &(((struct timex32 *)A(txc_p))->jitter)) || - __put_user (t.shift, &(((struct timex32 *)A(txc_p))->shift)) || - __put_user (t.stabil, &(((struct timex32 *)A(txc_p))->stabil)) || - __put_user (t.jitcnt, &(((struct timex32 *)A(txc_p))->jitcnt)) || - __put_user (t.calcnt, &(((struct timex32 *)A(txc_p))->calcnt)) || - __put_user (t.errcnt, &(((struct timex32 *)A(txc_p))->errcnt)) || - __put_user (t.stbcnt, &(((struct timex32 *)A(txc_p))->stbcnt)))) - return -EFAULT; + ret = get_user (t.modes, &txc_p->modes); + ret |= __get_user (t.offset, &txc_p->offset); + ret |= __get_user (t.freq, &txc_p->freq); + ret |= __get_user (t.maxerror, &txc_p->maxerror); + ret |= __get_user (t.esterror, &txc_p->esterror); + ret |= __get_user (t.status, &txc_p->status); + ret |= __get_user (t.constant, &txc_p->constant); + ret |= __get_user (t.tick, &txc_p->tick); + ret |= __get_user (t.shift, &txc_p->shift); + if (ret || (ret = do_adjtimex(&t))) + return ret; + ret = __put_user (t.modes, &txc_p->modes); + ret |= __put_user (t.offset, &txc_p->offset); + ret |= __put_user (t.freq, &txc_p->freq); + ret |= __put_user (t.maxerror, &txc_p->maxerror); + ret |= __put_user (t.esterror, &txc_p->esterror); + ret |= __put_user (t.status, &txc_p->status); + ret |= __put_user (t.constant, &txc_p->constant); + ret |= __put_user (t.precision, &txc_p->precision); + ret |= __put_user (t.tolerance, &txc_p->tolerance); + ret |= __put_user (t.time.tv_sec, &txc_p->time.tv_sec); + ret |= __put_user (t.time.tv_usec, &txc_p->time.tv_usec); + ret |= __put_user (t.tick, &txc_p->tick); + ret |= __put_user (t.ppsfreq, &txc_p->ppsfreq); + ret |= __put_user (t.jitter, &txc_p->jitter); + ret |= __put_user (t.shift, &txc_p->shift); + ret |= __put_user (t.stabil, &txc_p->stabil); + ret |= __put_user (t.jitcnt, &txc_p->jitcnt); + ret |= __put_user (t.calcnt, &txc_p->calcnt); + ret |= __put_user (t.errcnt, &txc_p->errcnt); + ret |= __put_user (t.stbcnt, &txc_p->stbcnt); + if (!ret) + ret = time_state; return ret; } @@ -2129,22 +2168,23 @@ struct msghdr32 *umsg) { u32 tmp1, tmp2, tmp3; + int err; - if(get_user(tmp1, &umsg->msg_name) || - get_user(tmp2, &umsg->msg_iov) || - get_user(tmp3, &umsg->msg_control)) + err = get_user(tmp1, &umsg->msg_name); + err |= __get_user(tmp2, &umsg->msg_iov); + err |= __get_user(tmp3, &umsg->msg_control); + if (err) return -EFAULT; kmsg->msg_name = (void *)A(tmp1); kmsg->msg_iov = (struct iovec *)A(tmp2); kmsg->msg_control = (void *)A(tmp3); - if(get_user(kmsg->msg_namelen, &umsg->msg_namelen) || - get_user(kmsg->msg_controllen, &umsg->msg_controllen) || - get_user(kmsg->msg_flags, &umsg->msg_flags)) - return -EFAULT; - - return 0; + err = get_user(kmsg->msg_namelen, &umsg->msg_namelen); + err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen); + err |= get_user(kmsg->msg_flags, &umsg->msg_flags); + + return err; } /* I've named the args so it is easy to tell whose space the pointers are in. */ @@ -2183,7 +2223,7 @@ return tot_len; } -asmlinkage int sys32_sendmsg(int fd, u32 user_msg, unsigned user_flags) +asmlinkage int sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags) { struct socket *sock; char address[MAX_SOCK_ADDR]; @@ -2193,7 +2233,7 @@ struct msghdr kern_msg; int err, total_len; - if(msghdr_from_user32_to_kern(&kern_msg, (struct msghdr32 *)A(user_msg))) + if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) return -EFAULT; if(kern_msg.msg_iovlen > UIO_MAXIOV) return -EINVAL; @@ -2246,7 +2286,7 @@ return err; } -asmlinkage int sys32_recvmsg(int fd, u32 user_msg, unsigned int user_flags) +asmlinkage int sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags) { struct iovec iovstack[UIO_FASTIOV]; struct msghdr kern_msg; @@ -2258,13 +2298,13 @@ unsigned long cmsg_ptr; int err, total_len, len = 0; - if(msghdr_from_user32_to_kern(&kern_msg, (struct msghdr32 *)A(user_msg))) + if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) return -EFAULT; if(kern_msg.msg_iovlen > UIO_MAXIOV) return -EINVAL; uaddr = kern_msg.msg_name; - uaddr_len = &((struct msghdr32 *)A(user_msg))->msg_namelen; + uaddr_len = &user_msg->msg_namelen; err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE); if (err < 0) goto out; @@ -2288,12 +2328,11 @@ if(uaddr != NULL && err >= 0) err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len); if(err >= 0) { - err = __put_user(kern_msg.msg_flags, - &((struct msghdr32 *)A(user_msg))->msg_flags); + err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags); if(!err) { /* XXX Convert cmsg back into userspace 32-bit format... */ err = __put_user((unsigned long)kern_msg.msg_control - cmsg_ptr, - &((struct msghdr32 *)A(user_msg))->msg_controllen); + &user_msg->msg_controllen); } } @@ -2334,14 +2373,14 @@ extern asmlinkage int sys_shutdown(int fd, int how); extern asmlinkage int sys_listen(int fd, int backlog); -asmlinkage int sys32_socketcall(int call, u32 args) +asmlinkage int sys32_socketcall(int call, u32 *args) { u32 a[6]; u32 a0,a1; if (callSYS_RECVMSG) return -EINVAL; - if (copy_from_user(a, (u32 *)A(args), nargs[call])) + if (copy_from_user(a, args, nargs[call])) return -EFAULT; a0=a[0]; a1=a[1]; @@ -2379,16 +2418,16 @@ case SYS_GETSOCKOPT: return sys32_getsockopt(a0, a1, a[2], a[3], a[4]); case SYS_SENDMSG: - return sys32_sendmsg(a0, a1, a[2]); + return sys32_sendmsg(a0, (struct msghdr32 *)A(a1), a[2]); case SYS_RECVMSG: - return sys32_recvmsg(a0, a1, a[2]); + return sys32_recvmsg(a0, (struct msghdr32 *)A(a1), a[2]); } return -EINVAL; } extern void check_pending(int signum); -asmlinkage int sys32_sigaction (int sig, u32 act, u32 oact) +asmlinkage int sys32_sigaction (int sig, struct old_sigaction32 *act, struct old_sigaction32 *oact) { struct k_sigaction new_ka, old_ka; int ret; @@ -2401,31 +2440,31 @@ if (act) { old_sigset_t32 mask; - if (get_user((long)new_ka.sa.sa_handler, &((struct old_sigaction32 *)A(act))->sa_handler) || - __get_user((long)new_ka.sa.sa_restorer, &((struct old_sigaction32 *)A(act))->sa_restorer)) - return -EFAULT; - __get_user(new_ka.sa.sa_flags, &((struct old_sigaction32 *)A(act))->sa_flags); - __get_user(mask, &((struct old_sigaction32 *)A(act))->sa_mask); - new_ka.ka_restorer = NULL; - siginitset(&new_ka.sa.sa_mask, mask); + ret = get_user((long)new_ka.sa.sa_handler, &act->sa_handler); + ret |= __get_user((long)new_ka.sa.sa_restorer, &act->sa_restorer); + ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags); + ret |= __get_user(mask, &act->sa_mask); + if (ret) + return ret; + new_ka.ka_restorer = NULL; + siginitset(&new_ka.sa.sa_mask, mask); } ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - if (!ret && oact) { - if (put_user((long)old_ka.sa.sa_handler, &((struct old_sigaction32 *)A(oact))->sa_handler) || - __put_user((long)old_ka.sa.sa_restorer, &((struct old_sigaction32 *)A(oact))->sa_restorer)) - return -EFAULT; - __put_user(old_ka.sa.sa_flags, &((struct old_sigaction32 *)A(oact))->sa_flags); - __put_user(old_ka.sa.sa_mask.sig[0], &((struct old_sigaction32 *)A(oact))->sa_mask); + if (!ret && oact) { + ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler); + ret |= __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer); + ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags); + ret |= __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); } return ret; } asmlinkage int -sys32_rt_sigaction(int sig, u32 act, u32 oact, - u32 restorer, __kernel_size_t32 sigsetsize) +sys32_rt_sigaction(int sig, struct sigaction32 *act, struct sigaction32 *oact, + void *restorer, __kernel_size_t32 sigsetsize) { struct k_sigaction new_ka, old_ka; int ret; @@ -2435,35 +2474,40 @@ if (sigsetsize != sizeof(sigset_t32)) return -EINVAL; + /* All tasks which use RT signals (effectively) use + * new style signals. + */ + current->tss.new_signal = 1; + if (act) { - if (get_user((long)new_ka.sa.sa_handler, &((struct sigaction32 *)A(act))->sa_handler) || - __copy_from_user(&set32, &((struct sigaction32 *)A(act))->sa_mask, sizeof(sigset_t32))) - return -EFAULT; + new_ka.ka_restorer = restorer; + ret = get_user((long)new_ka.sa.sa_handler, &act->sa_handler); + ret |= __copy_from_user(&set32, &act->sa_mask, sizeof(sigset_t32)); switch (_NSIG_WORDS) { case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6] | (((long)set32.sig[7]) << 32); case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4] | (((long)set32.sig[5]) << 32); case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2] | (((long)set32.sig[3]) << 32); case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0] | (((long)set32.sig[1]) << 32); } - __get_user(new_ka.sa.sa_flags, &((struct sigaction32 *)A(act))->sa_flags); - __get_user((long)new_ka.sa.sa_restorer, &((struct sigaction32 *)A(act))->sa_restorer); - new_ka.ka_restorer = (void *)(long)restorer; - } + ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags); + ret |= __get_user((long)new_ka.sa.sa_restorer, &act->sa_restorer); + if (ret) + return -EFAULT; + } - ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); + ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - if (!ret && oact) { + if (!ret && oact) { switch (_NSIG_WORDS) { case 4: set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32); set32.sig[6] = old_ka.sa.sa_mask.sig[3]; case 3: set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32); set32.sig[4] = old_ka.sa.sa_mask.sig[2]; case 2: set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32); set32.sig[2] = old_ka.sa.sa_mask.sig[1]; case 1: set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32); set32.sig[0] = old_ka.sa.sa_mask.sig[0]; } - if (put_user((long)old_ka.sa.sa_handler, &((struct sigaction32 *)A(oact))->sa_handler) || - __copy_to_user(&((struct sigaction32 *)A(oact))->sa_mask, &set32, sizeof(sigset_t32))) - return -EFAULT; - __put_user(old_ka.sa.sa_flags, &((struct sigaction32 *)A(oact))->sa_flags); - __put_user((long)old_ka.sa.sa_restorer, &((struct sigaction32 *)A(oact))->sa_restorer); + ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler); + ret |= __copy_to_user(&oact->sa_mask, &set32, sizeof(sigset_t32)); + ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags); + ret |= __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer); } return ret; @@ -2608,14 +2652,14 @@ base = 1; lock_kernel(); - filename = getname((char *)A((u32)regs->u_regs[base + UREG_I0])); + filename = getname32((char *)AA(regs->u_regs[base + UREG_I0])); error = PTR_ERR(filename); if(IS_ERR(filename)) goto out; error = do_execve32(filename, - (u32 *)A((u32)regs->u_regs[base + UREG_I1]), - (u32 *)A((u32)regs->u_regs[base + UREG_I2]), regs); - putname(filename); + (u32 *)AA((u32)regs->u_regs[base + UREG_I1]), + (u32 *)AA((u32)regs->u_regs[base + UREG_I2]), regs); + putname32(filename); if(!error) { fprs_write(0); @@ -2632,9 +2676,9 @@ extern asmlinkage unsigned long sys_create_module(const char *name_user, size_t size); -asmlinkage unsigned long sys32_create_module(u32 name_user, __kernel_size_t32 size) +asmlinkage unsigned long sys32_create_module(const char *name_user, __kernel_size_t32 size) { - return sys_create_module((const char *)A(name_user), (size_t)size); + return sys_create_module(name_user, (size_t)size); } extern asmlinkage int sys_init_module(const char *name_user, struct module *mod_user); @@ -2642,16 +2686,16 @@ /* Hey, when you're trying to init module, take time and prepare us a nice 64bit * module structure, even if from 32bit modutils... Why to pollute kernel... :)) */ -asmlinkage int sys32_init_module(u32 nameuser, u32 mod_user) +asmlinkage int sys32_init_module(const char *name_user, struct module *mod_user) { - return sys_init_module((const char *)A(nameuser), (struct module *)A(mod_user)); + return sys_init_module(name_user, mod_user); } extern asmlinkage int sys_delete_module(const char *name_user); -asmlinkage int sys32_delete_module(u32 name_user) +asmlinkage int sys32_delete_module(const char *name_user) { - return sys_delete_module((const char *)A(name_user)); + return sys_delete_module(name_user); } struct module_info32 { @@ -2876,7 +2920,7 @@ return error; } -asmlinkage int sys32_query_module(u32 name_user, int which, u32 buf, __kernel_size_t32 bufsize, u32 ret) +asmlinkage int sys32_query_module(char *name_user, int which, char *buf, __kernel_size_t32 bufsize, u32 ret) { struct module *mod; int err; @@ -2888,7 +2932,7 @@ long namelen; char *name; - if ((namelen = get_mod_name((char *)A(name_user), &name)) < 0) { + if ((namelen = get_mod_name(name_user, &name)) < 0) { err = namelen; goto out; } @@ -2908,19 +2952,19 @@ err = 0; break; case QM_MODULES: - err = qm_modules((char *)A(buf), bufsize, (__kernel_size_t32 *)A(ret)); + err = qm_modules(buf, bufsize, (__kernel_size_t32 *)AA(ret)); break; case QM_DEPS: - err = qm_deps(mod, (char *)A(buf), bufsize, (__kernel_size_t32 *)A(ret)); + err = qm_deps(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret)); break; case QM_REFS: - err = qm_refs(mod, (char *)A(buf), bufsize, (__kernel_size_t32 *)A(ret)); + err = qm_refs(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret)); break; case QM_SYMBOLS: - err = qm_symbols(mod, (char *)A(buf), bufsize, (__kernel_size_t32 *)A(ret)); + err = qm_symbols(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret)); break; case QM_INFO: - err = qm_info(mod, (char *)A(buf), bufsize, (__kernel_size_t32 *)A(ret)); + err = qm_info(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret)); break; default: err = -EINVAL; @@ -2938,7 +2982,7 @@ extern asmlinkage int sys_get_kernel_syms(struct kernel_sym *table); -asmlinkage int sys32_get_kernel_syms(u32 table) +asmlinkage int sys32_get_kernel_syms(struct kernel_sym32 *table) { int len, i; struct kernel_sym *tbl; @@ -2953,8 +2997,8 @@ sys_get_kernel_syms(tbl); set_fs (old_fs); for (i = 0; i < len; i++, table += sizeof (struct kernel_sym32)) { - if (put_user (tbl[i].value, &(((struct kernel_sym32 *)A(table))->value)) || - copy_to_user (((struct kernel_sym32 *)A(table))->name, tbl[i].name, 60)) + if (put_user (tbl[i].value, &table->value) || + copy_to_user (table->name, tbl[i].name, 60)) break; } kfree (tbl); @@ -3069,61 +3113,65 @@ static int nfs_svc32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) { - if(__get_user(karg->ca_version, &arg32->ca32_version) || - __get_user(karg->ca_svc.svc_port, &arg32->ca32_svc.svc32_port) || - __get_user(karg->ca_svc.svc_nthreads, &arg32->ca32_svc.svc32_nthreads)) - return -EFAULT; - return 0; + int err; + + err = __get_user(karg->ca_version, &arg32->ca32_version); + err |= __get_user(karg->ca_svc.svc_port, &arg32->ca32_svc.svc32_port); + err |= __get_user(karg->ca_svc.svc_nthreads, &arg32->ca32_svc.svc32_nthreads); + return err; } static int nfs_clnt32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) { - if(__get_user(karg->ca_version, &arg32->ca32_version) || - copy_from_user(&karg->ca_client.cl_ident[0], + int err; + + err = __get_user(karg->ca_version, &arg32->ca32_version); + err |= copy_from_user(&karg->ca_client.cl_ident[0], &arg32->ca32_client.cl32_ident[0], - NFSCLNT_IDMAX) || - __get_user(karg->ca_client.cl_naddr, &arg32->ca32_client.cl32_naddr) || - copy_from_user(&karg->ca_client.cl_addrlist[0], + NFSCLNT_IDMAX); + err |= __get_user(karg->ca_client.cl_naddr, &arg32->ca32_client.cl32_naddr); + err |= copy_from_user(&karg->ca_client.cl_addrlist[0], &arg32->ca32_client.cl32_addrlist[0], - (sizeof(struct in_addr) * NFSCLNT_ADDRMAX)) || - __get_user(karg->ca_client.cl_fhkeytype, - &arg32->ca32_client.cl32_fhkeytype) || - __get_user(karg->ca_client.cl_fhkeylen, - &arg32->ca32_client.cl32_fhkeylen) || - copy_from_user(&karg->ca_client.cl_fhkey[0], + (sizeof(struct in_addr) * NFSCLNT_ADDRMAX)); + err |= __get_user(karg->ca_client.cl_fhkeytype, + &arg32->ca32_client.cl32_fhkeytype); + err |= __get_user(karg->ca_client.cl_fhkeylen, + &arg32->ca32_client.cl32_fhkeylen); + err |= copy_from_user(&karg->ca_client.cl_fhkey[0], &arg32->ca32_client.cl32_fhkey[0], - NFSCLNT_KEYMAX)) - return -EFAULT; - return 0; + NFSCLNT_KEYMAX); + return err; } static int nfs_exp32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) { - if(__get_user(karg->ca_version, &arg32->ca32_version) || - copy_from_user(&karg->ca_export.ex_client[0], + int err; + + err = __get_user(karg->ca_version, &arg32->ca32_version); + err |= copy_from_user(&karg->ca_export.ex_client[0], &arg32->ca32_export.ex32_client[0], - NFSCLNT_IDMAX) || - copy_from_user(&karg->ca_export.ex_path[0], + NFSCLNT_IDMAX); + err |= copy_from_user(&karg->ca_export.ex_path[0], &arg32->ca32_export.ex32_path[0], - NFS_MAXPATHLEN) || - __get_user(karg->ca_export.ex_dev, - &arg32->ca32_export.ex32_dev) || - __get_user(karg->ca_export.ex_ino, - &arg32->ca32_export.ex32_ino) || - __get_user(karg->ca_export.ex_flags, - &arg32->ca32_export.ex32_flags) || - __get_user(karg->ca_export.ex_anon_uid, - &arg32->ca32_export.ex32_anon_uid) || - __get_user(karg->ca_export.ex_anon_gid, - &arg32->ca32_export.ex32_anon_gid)) - return -EFAULT; - return 0; + NFS_MAXPATHLEN); + err |= __get_user(karg->ca_export.ex_dev, + &arg32->ca32_export.ex32_dev); + err |= __get_user(karg->ca_export.ex_ino, + &arg32->ca32_export.ex32_ino); + err |= __get_user(karg->ca_export.ex_flags, + &arg32->ca32_export.ex32_flags); + err |= __get_user(karg->ca_export.ex_anon_uid, + &arg32->ca32_export.ex32_anon_uid); + err |= __get_user(karg->ca_export.ex_anon_gid, + &arg32->ca32_export.ex32_anon_gid); + return err; } static int nfs_uud32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) { u32 uaddr; int i; + int err; memset(karg, 0, sizeof(*karg)); if(__get_user(karg->ca_version, &arg32->ca32_version)) @@ -3131,76 +3179,74 @@ karg->ca_umap.ug_ident = (char *)get_free_page(GFP_USER); if(!karg->ca_umap.ug_ident) return -ENOMEM; - if(__get_user(uaddr, &arg32->ca32_umap.ug32_ident)) - return -EFAULT; + err = __get_user(uaddr, &arg32->ca32_umap.ug32_ident); if(strncpy_from_user(karg->ca_umap.ug_ident, (char *)A(uaddr), PAGE_SIZE) <= 0) return -EFAULT; - if(__get_user(karg->ca_umap.ug_uidbase, - &arg32->ca32_umap.ug32_uidbase) || - __get_user(karg->ca_umap.ug_uidlen, - &arg32->ca32_umap.ug32_uidlen) || - __get_user(uaddr, &arg32->ca32_umap.ug32_udimap)) + err |= __get_user(karg->ca_umap.ug_uidbase, + &arg32->ca32_umap.ug32_uidbase); + err |= __get_user(karg->ca_umap.ug_uidlen, + &arg32->ca32_umap.ug32_uidlen); + err |= __get_user(uaddr, &arg32->ca32_umap.ug32_udimap); + if (err) return -EFAULT; karg->ca_umap.ug_udimap = kmalloc((sizeof(uid_t) * karg->ca_umap.ug_uidlen), GFP_USER); if(!karg->ca_umap.ug_udimap) - return -EFAULT; + return -ENOMEM; for(i = 0; i < karg->ca_umap.ug_uidlen; i++) - if(__get_user(karg->ca_umap.ug_udimap[i], - &(((__kernel_uid_t32 *)A(uaddr))[i]))) - return -EFAULT; - if(__get_user(karg->ca_umap.ug_gidbase, - &arg32->ca32_umap.ug32_gidbase) || - __get_user(karg->ca_umap.ug_uidlen, - &arg32->ca32_umap.ug32_gidlen) || - __get_user(uaddr, &arg32->ca32_umap.ug32_gdimap)) + err |= __get_user(karg->ca_umap.ug_udimap[i], + &(((__kernel_uid_t32 *)A(uaddr))[i])); + err |= __get_user(karg->ca_umap.ug_gidbase, + &arg32->ca32_umap.ug32_gidbase); + err |= __get_user(karg->ca_umap.ug_uidlen, + &arg32->ca32_umap.ug32_gidlen); + err |= __get_user(uaddr, &arg32->ca32_umap.ug32_gdimap); + if (err) return -EFAULT; karg->ca_umap.ug_gdimap = kmalloc((sizeof(gid_t) * karg->ca_umap.ug_uidlen), GFP_USER); if(!karg->ca_umap.ug_gdimap) - return -EFAULT; + return -ENOMEM; for(i = 0; i < karg->ca_umap.ug_gidlen; i++) - if(__get_user(karg->ca_umap.ug_gdimap[i], - &(((__kernel_gid_t32 *)A(uaddr))[i]))) - return -EFAULT; + err |= __get_user(karg->ca_umap.ug_gdimap[i], + &(((__kernel_gid_t32 *)A(uaddr))[i])); - /* Success! */ - return 0; + return err; } static int nfs_getfh32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) { - if(__get_user(karg->ca_version, &arg32->ca32_version) || - copy_from_user(&karg->ca_getfh.gf_addr, + int err; + + err = __get_user(karg->ca_version, &arg32->ca32_version); + err |= copy_from_user(&karg->ca_getfh.gf_addr, &arg32->ca32_getfh.gf32_addr, - (sizeof(struct sockaddr))) || - __get_user(karg->ca_getfh.gf_dev, - &arg32->ca32_getfh.gf32_dev) || - __get_user(karg->ca_getfh.gf_ino, - &arg32->ca32_getfh.gf32_ino) || - __get_user(karg->ca_getfh.gf_version, - &arg32->ca32_getfh.gf32_version)) - return -EFAULT; - return 0; + (sizeof(struct sockaddr))); + err |= __get_user(karg->ca_getfh.gf_dev, + &arg32->ca32_getfh.gf32_dev); + err |= __get_user(karg->ca_getfh.gf_ino, + &arg32->ca32_getfh.gf32_ino); + err |= __get_user(karg->ca_getfh.gf_version, + &arg32->ca32_getfh.gf32_version); + return err; } static int nfs_getfh32_res_trans(union nfsctl_res *kres, union nfsctl_res32 *res32) { - if(copy_to_user(&res32->cr32_getfh, + int err; + + err = copy_to_user(&res32->cr32_getfh, &kres->cr_getfh, - sizeof(res32->cr32_getfh)) || - __put_user(kres->cr_debug, &res32->cr32_debug)) - return -EFAULT; - return 0; + sizeof(res32->cr32_getfh)); + err |= __put_user(kres->cr_debug, &res32->cr32_debug); + return err; } extern asmlinkage int sys_nfsservctl(int cmd, void *arg, void *resp); -int asmlinkage sys32_nfsservctl(int cmd, u32 u_argp, u32 u_resp) +int asmlinkage sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsctl_res32 *res32) { - struct nfsctl_arg32 *arg32 = (struct nfsctl_arg32 *)A(u_argp); - union nfsctl_res32 *res32 = (union nfsctl_res32 *)A(u_resp); struct nfsctl_arg *karg = NULL; union nfsctl_res *kres = NULL; mm_segment_t oldfs; @@ -3273,32 +3319,32 @@ extern struct timezone sys_tz; extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz); -asmlinkage int sys32_gettimeofday(u32 tv, u32 tz) +asmlinkage int sys32_gettimeofday(struct timeval32 *tv, struct timezone *tz) { if (tv) { struct timeval ktv; do_gettimeofday(&ktv); - if (put_tv32((struct timeval32 *)A(tv), &ktv)) + if (put_tv32(tv, &ktv)) return -EFAULT; } if (tz) { - if (copy_to_user((void*)A(tz), &sys_tz, sizeof(sys_tz))) + if (copy_to_user(tz, &sys_tz, sizeof(sys_tz))) return -EFAULT; } return 0; } -asmlinkage int sys32_settimeofday(u32 tv, u32 tz) +asmlinkage int sys32_settimeofday(struct timeval32 *tv, struct timezone *tz) { struct timeval ktv; struct timezone ktz; if (tv) { - if (get_tv32(&ktv, (struct timeval32 *)A(tv))) + if (get_tv32(&ktv, tv)) return -EFAULT; } if (tz) { - if (copy_from_user(&ktz, (void*)A(tz), sizeof(ktz))) + if (copy_from_user(&ktz, tz, sizeof(ktz))) return -EFAULT; } @@ -3307,13 +3353,13 @@ extern int do_getitimer(int which, struct itimerval *value); -asmlinkage int sys32_getitimer(int which, u32 it) +asmlinkage int sys32_getitimer(int which, struct itimerval32 *it) { struct itimerval kit; int error; error = do_getitimer(which, &kit); - if (!error && put_it32((struct itimerval32 *)A(it), &kit)) + if (!error && put_it32(it, &kit)) error = -EFAULT; return error; @@ -3321,13 +3367,13 @@ extern int do_setitimer(int which, struct itimerval *, struct itimerval *); -asmlinkage int sys32_setitimer(int which, u32 in, u32 out) +asmlinkage int sys32_setitimer(int which, struct itimerval32 *in, struct itimerval32 *out) { struct itimerval kin, kout; int error; if (in) { - if (get_it32(&kin, (struct itimerval32 *)A(in))) + if (get_it32(&kin, in)) return -EFAULT; } else memset(&kin, 0, sizeof(kin)); @@ -3335,7 +3381,7 @@ error = do_setitimer(which, &kin, out ? &kout : NULL); if (error || !out) return error; - if (put_it32((struct itimerval32 *)A(out), &kout)) + if (put_it32(out, &kout)) return -EFAULT; return 0; @@ -3344,7 +3390,7 @@ asmlinkage int sys_utimes(char *, struct timeval *); -asmlinkage int sys32_utimes(u32 filename, u32 tvs) +asmlinkage int sys32_utimes(char *filename, struct timeval32 *tvs) { char *kfilename; struct timeval ktvs[2]; @@ -3355,8 +3401,8 @@ ret = PTR_ERR(kfilename); if (!IS_ERR(kfilename)) { if (tvs) { - if (get_tv32(&ktvs[0], (struct timeval32 *)A(tvs)) || - get_tv32(&ktvs[1], 1+(struct timeval32 *)A(tvs))) + if (get_tv32(&ktvs[0], tvs) || + get_tv32(&ktvs[1], 1+tvs)) return -EFAULT; } @@ -3397,7 +3443,7 @@ (unsigned long) dfn, (unsigned long) off, (unsigned long) len, - (unsigned char *)A(ubuf)); + (unsigned char *)AA(ubuf)); } asmlinkage int sys32_pciconfig_write(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf) @@ -3406,7 +3452,7 @@ (unsigned long) dfn, (unsigned long) off, (unsigned long) len, - (unsigned char *)A(ubuf)); + (unsigned char *)AA(ubuf)); } extern asmlinkage int sys_prctl(int option, unsigned long arg2, unsigned long arg3, @@ -3442,16 +3488,16 @@ typedef __kernel_ssize_t32 ssize_t32; -asmlinkage ssize_t32 sys32_pread(unsigned int fd, u32 ubuf, +asmlinkage ssize_t32 sys32_pread(unsigned int fd, char *ubuf, __kernel_size_t32 count, u32 pos) { - return sys_pread(fd, (char *) A(ubuf), count, pos); + return sys_pread(fd, ubuf, count, pos); } -asmlinkage ssize_t32 sys32_pwrite(unsigned int fd, u32 ubuf, +asmlinkage ssize_t32 sys32_pwrite(unsigned int fd, char *ubuf, __kernel_size_t32 count, u32 pos) { - return sys_pwrite(fd, (char *) A(ubuf), count, pos); + return sys_pwrite(fd, ubuf, count, pos); } @@ -3472,20 +3518,20 @@ extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count); -asmlinkage int sys32_sendfile(int out_fd, int in_fd, u32 offset, s32 count) +asmlinkage int sys32_sendfile(int out_fd, int in_fd, __kernel_off_t32 *offset, s32 count) { mm_segment_t old_fs = get_fs(); int ret; off_t of; - if (offset && get_user(of, (__kernel_off_t32 *)A(offset))) + if (offset && get_user(of, offset)) return -EFAULT; set_fs(KERNEL_DS); ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count); set_fs(old_fs); - if (!ret && offset && put_user(of, (__kernel_off_t32 *)A(offset))) + if (!ret && offset && put_user(of, offset)) return -EFAULT; return ret; diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/sys_sunos32.c linux/arch/sparc64/kernel/sys_sunos32.c --- v2.1.123/linux/arch/sparc64/kernel/sys_sunos32.c Thu Aug 6 14:06:31 1998 +++ linux/arch/sparc64/kernel/sys_sunos32.c Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -/* $Id: sys_sunos32.c,v 1.16 1998/06/16 04:37:06 davem Exp $ +/* $Id: sys_sunos32.c,v 1.18 1998/08/31 03:41:01 davem Exp $ * sys_sunos32.c: SunOS binary compatability layer on sparc64. * * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu) @@ -52,7 +52,14 @@ #include #include -#define A(x) ((unsigned long)x) +/* Use this to get at 32-bit user passed pointers. */ +#define A(__x) \ +({ unsigned long __ret; \ + __asm__ ("srl %0, 0, %0" \ + : "=r" (__ret) \ + : "0" (__x)); \ + __ret; \ +}) #define SUNOS_NR_OPEN 256 @@ -98,6 +105,7 @@ ret_type = flags & _MAP_NEW; flags &= ~_MAP_NEW; + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); retval = do_mmap(file, (unsigned long) addr, (unsigned long) len, (unsigned long) prot, (unsigned long) flags, diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/systbls.S linux/arch/sparc64/kernel/systbls.S --- v2.1.123/linux/arch/sparc64/kernel/systbls.S Thu Aug 6 14:06:31 1998 +++ linux/arch/sparc64/kernel/systbls.S Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -/* $Id: systbls.S,v 1.47 1998/07/28 13:07:55 jj Exp $ +/* $Id: systbls.S,v 1.49 1998/09/13 04:30:32 davem Exp $ * systbls.S: System call entry point tables for OS compatibility. * The native Linux system call table lives here also. * @@ -17,9 +17,9 @@ .globl sys_call_table32 sys_call_table32: -/*0*/ .word sys_setup, sparc_exit, sys_fork, sys_read, sys_write +/*0*/ .word sys_nis_syscall, sparc_exit, sys_fork, sys_read, sys_write /*5*/ .word sys_open, sys_close, sys32_wait4, sys_creat, sys_link -/*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys_nis_syscall, sys32_mknod +/*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys32_chown, sys32_mknod /*15*/ .word sys32_chmod, sys32_lchown, sparc_brk, sys_nis_syscall, sys32_lseek /*20*/ .word sys_getpid, sys_capget, sys_capset, sys_setuid, sys_getuid /*25*/ .word sys_time, sys_ptrace, sys_alarm, sys32_sigaltstack, sys32_pause @@ -76,9 +76,9 @@ .globl sys_call_table64, sys_call_table sys_call_table64: sys_call_table: -/*0*/ .word sys_setup, sparc_exit, sys_fork, sys_read, sys_write +/*0*/ .word sys_nis_syscall, sparc_exit, sys_fork, sys_read, sys_write /*5*/ .word sys_open, sys_close, sys_wait4, sys_creat, sys_link -/*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys_nis_syscall, sys_mknod +/*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys_chown, sys_mknod /*15*/ .word sys_chmod, sys_lchown, sparc_brk, sys_nis_syscall, sys_lseek /*20*/ .word sys_getpid, sys_capget, sys_capset, sys_setuid, sys_getuid /*25*/ .word sys_time, sys_ptrace, sys_alarm, sys_sigaltstack, sys_nis_syscall diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/time.c linux/arch/sparc64/kernel/time.c --- v2.1.123/linux/arch/sparc64/kernel/time.c Thu Aug 6 14:06:31 1998 +++ linux/arch/sparc64/kernel/time.c Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -/* $Id: time.c,v 1.15 1998/05/12 22:38:29 ecd Exp $ +/* $Id: time.c,v 1.16 1998/09/05 17:25:28 jj Exp $ * time.c: UltraSparc timer and TOD clock support. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -32,8 +32,8 @@ #include struct mostek48t02 *mstk48t02_regs = 0; -struct mostek48t08 *mstk48t08_regs = 0; -struct mostek48t59 *mstk48t59_regs = 0; +static struct mostek48t08 *mstk48t08_regs = 0; +static struct mostek48t59 *mstk48t59_regs = 0; static int set_rtc_mmss(unsigned long); @@ -133,7 +133,7 @@ } /* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */ -static void kick_start_clock(void) +static void __init kick_start_clock(void) { register struct mostek48t02 *regs = mstk48t02_regs; unsigned char sec; @@ -182,7 +182,7 @@ } /* Return nonzero if the clock chip battery is low. */ -static int has_low_battery(void) +static int __init has_low_battery(void) { register struct mostek48t02 *regs = mstk48t02_regs; unsigned char data1, data2; @@ -197,7 +197,7 @@ /* Probe for the real time clock chip. */ -__initfunc(static void set_system_time(void)) +static void __init set_system_time(void) { unsigned int year, mon, day, hour, min, sec; struct mostek48t02 *mregs; @@ -222,15 +222,18 @@ mregs->creg &= ~MSTK_CREG_READ; } -__initfunc(void clock_probe(void)) +void __init clock_probe(void) { struct linux_prom_registers clk_reg[2]; char model[128]; int node, busnd = -1, err; + unsigned long flags; #ifdef CONFIG_PCI struct linux_ebus *ebus = 0; #endif + __save_and_cli(flags); + if(central_bus != NULL) { busnd = central_bus->child->prom_node; } @@ -349,6 +352,8 @@ kick_start_clock(); set_system_time(); + + __restore_flags(flags); } #ifndef BCD_TO_BIN @@ -359,19 +364,15 @@ #define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10) #endif -__initfunc(void time_init(void)) -{ - /* clock_probe() is now done at end of sbus_init on sparc64 - * so that both sbus and fhc bus information is probed and - * available. - */ -} - extern void init_timers(void (*func)(int, void *, struct pt_regs *), unsigned long *); -__initfunc(void sun4u_start_timers(void)) +void __init time_init(void) { + /* clock_probe() is now done at end of [se]bus_init on sparc64 + * so that sbus, fhc and ebus bus information is probed and + * available. + */ unsigned long clock; init_timers(timer_interrupt, &clock); diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/traps.c linux/arch/sparc64/kernel/traps.c --- v2.1.123/linux/arch/sparc64/kernel/traps.c Thu Aug 6 14:06:31 1998 +++ linux/arch/sparc64/kernel/traps.c Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -/* $Id: traps.c,v 1.51 1998/06/12 14:54:20 jj Exp $ +/* $Id: traps.c,v 1.54 1998/09/25 01:09:02 davem Exp $ * arch/sparc64/kernel/traps.c * * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) @@ -178,6 +178,79 @@ } #endif /* SYSCALL_TRACING */ +#if 0 +void rtrap_check(struct pt_regs *regs) +{ + register unsigned long pgd_phys asm("o1"); + register unsigned long pgd_cache asm("o2"); + register unsigned long g1_or_g3 asm("o3"); + register unsigned long g2 asm("o4"); + unsigned long ctx; + +#if 0 + do { + unsigned long test; + __asm__ __volatile__("rdpr %%pstate, %0" + : "=r" (test)); + if((test & PSTATE_MG) != 0 || + (test & PSTATE_IE) == 0) { + printk("rtrap_check: Bogus pstate[%016lx]\n", test); + return; + } + } while(0); +#endif + + __asm__ __volatile__(" + rdpr %%pstate, %%o5 + wrpr %%o5, %4, %%pstate + or %%g1, %%g3, %2 + mov %%g2, %3 + mov %%g7, %0 + mov %5, %1 + ldxa [%1] %6, %1 + wrpr %%o5, 0x0, %%pstate" + : "=r" (pgd_phys), "=r" (pgd_cache), + "=r" (g1_or_g3), "=r" (g2) + : "i" (PSTATE_IE | PSTATE_MG), "i" (TSB_REG), + "i" (ASI_DMMU) + : "o5"); + + ctx = spitfire_get_secondary_context(); + + if((pgd_phys != __pa(current->mm->pgd)) || + ((pgd_cache != 0) && + (pgd_cache != pgd_val(current->mm->pgd[0]))) || + (g1_or_g3 != (0xfffffffe00000000UL | 0x0000000000000018UL)) || +#define KERN_HIGHBITS ((_PAGE_VALID | _PAGE_SZ4MB) ^ 0xfffff80000000000) +#define KERN_LOWBITS (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W) + (g2 != (KERN_HIGHBITS | KERN_LOWBITS)) || +#undef KERN_HIGHBITS +#undef KERN_LOWBITS + ((ctx != (current->mm->context & 0x3ff)) || + (ctx == 0) || + (current->tss.ctx != ctx))) { + printk("SHIT[%s:%d]: " + "(PP[%016lx] CACH[%016lx] CTX[%x] g1g3[%016lx] g2[%016lx]) ", + current->comm, current->pid, + pgd_phys, pgd_cache, ctx, g1_or_g3, g2); + printk("SHIT[%s:%d]: " + "[PP[%016lx] CACH[%016lx] CTX[%x:%x]] PC[%016lx:%016lx]\n", + current->comm, current->pid, + __pa(current->mm->pgd), + pgd_val(current->mm->pgd[0]), + current->mm->context & 0x3ff, + current->tss.ctx, + regs->tpc, regs->tnpc); + show_regs(regs); +#if 1 + __sti(); + while(1) + barrier(); +#endif + } +} +#endif + void bad_trap (struct pt_regs *regs, long lvl) { lock_kernel (); @@ -205,7 +278,20 @@ unlock_kernel(); } -void data_access_exception (struct pt_regs *regs) +void instruction_access_exception (struct pt_regs *regs, + unsigned long sfsr, unsigned long sfar) +{ + lock_kernel(); +#if 1 + printk("instruction_access_exception: Shit SFSR[%016lx] SFAR[%016lx], going.\n", + sfsr, sfar); +#endif + die_if_kernel("Iax", regs); + unlock_kernel(); +} + +void data_access_exception (struct pt_regs *regs, + unsigned long sfsr, unsigned long sfar) { if (regs->tstate & TSTATE_PRIV) { /* Test if this comes from uaccess places. */ @@ -224,7 +310,17 @@ regs->u_regs[UREG_G2] = g2; return; } + /* Shit... */ +#if 1 + printk("data_access_exception: Shit SFSR[%016lx] SFAR[%016lx], going.\n", + sfsr, sfar); +#endif + die_if_kernel("Dax", regs); } +#if 0 + else + rtrap_check(regs); +#endif lock_kernel(); force_sig(SIGSEGV, current); unlock_kernel(); @@ -286,17 +382,10 @@ unlock_kernel(); } -void instruction_access_exception (struct pt_regs *regs) +void do_iae(struct pt_regs *regs) { clean_and_reenable_l1_caches(); - lock_kernel(); - force_sig(SIGSEGV, current); - unlock_kernel(); -} - -void do_iae(struct pt_regs *regs) -{ lock_kernel(); force_sig(SIGSEGV, current); unlock_kernel(); diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/ttable.S linux/arch/sparc64/kernel/ttable.S --- v2.1.123/linux/arch/sparc64/kernel/ttable.S Thu Aug 6 14:06:31 1998 +++ linux/arch/sparc64/kernel/ttable.S Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -/* $Id: ttable.S,v 1.25 1998/05/23 18:24:53 jj Exp $ +/* $Id: ttable.S,v 1.27 1998/09/25 01:09:10 davem Exp $ * ttable.S: Sparc V9 Trap Table(s) with SpitFire extensions. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -11,7 +11,7 @@ sparc64_ttable_tl0: tl0_resv000: BOOT_KERNEL BTRAP(0x1) BTRAP(0x2) BTRAP(0x3) tl0_resv004: BTRAP(0x4) BTRAP(0x5) BTRAP(0x6) BTRAP(0x7) -tl0_iax: ACCESS_EXCEPTION_TRAP(instruction_access_exception) +tl0_iax: TRAP_NOSAVE(__do_instruction_access_exception) tl0_resv009: BTRAP(0x9) tl0_iae: TRAP(do_iae) tl0_resv00b: BTRAP(0xb) BTRAP(0xc) BTRAP(0xd) BTRAP(0xe) BTRAP(0xf) @@ -28,14 +28,14 @@ tl0_div0: TRAP(do_div0) tl0_resv029: BTRAP(0x29) BTRAP(0x2a) BTRAP(0x2b) BTRAP(0x2c) BTRAP(0x2d) BTRAP(0x2e) tl0_resv02f: BTRAP(0x2f) -tl0_dax: ACCESS_EXCEPTION_TRAP(data_access_exception) +tl0_dax: TRAP_NOSAVE(__do_data_access_exception) tl0_resv031: BTRAP(0x31) tl0_dae: TRAP(do_dae) tl0_resv033: BTRAP(0x33) tl0_mna: TRAP_NOSAVE(do_mna) tl0_lddfmna: TRAP_NOSAVE(do_lddfmna) tl0_stdfmna: TRAP_NOSAVE(do_stdfmna) -tl0_privact: TRAP(do_privact) +tl0_privact: TRAP_NOSAVE(__do_privact) tl0_resv038: BTRAP(0x38) BTRAP(0x39) BTRAP(0x3a) BTRAP(0x3b) BTRAP(0x3c) BTRAP(0x3d) tl0_resv03e: BTRAP(0x3e) BTRAP(0x3f) BTRAP(0x40) tl0_irq1: TRAP_IRQ(handler_irq, 1) TRAP_IRQ(handler_irq, 2) @@ -160,7 +160,7 @@ sparc64_ttable_tl1: tl1_resv000: BOOT_KERNEL BTRAPTL1(0x1) BTRAPTL1(0x2) BTRAPTL1(0x3) tl1_resv004: BTRAPTL1(0x4) BTRAPTL1(0x5) BTRAPTL1(0x6) BTRAPTL1(0x7) -tl1_iax: ACCESS_EXCEPTION_TRAPTL1(instruction_access_exception) +tl1_iax: TRAP_NOSAVE(__do_instruction_access_exception_tl1) tl1_resv009: BTRAPTL1(0x9) tl1_iae: TRAPTL1(do_iae_tl1) tl1_resv00b: BTRAPTL1(0xb) BTRAPTL1(0xc) BTRAPTL1(0xd) BTRAPTL1(0xe) BTRAPTL1(0xf) @@ -178,7 +178,7 @@ tl1_div0: TRAPTL1(do_div0_tl1) tl1_resv029: BTRAPTL1(0x29) BTRAPTL1(0x2a) BTRAPTL1(0x2b) BTRAPTL1(0x2c) tl1_resv02d: BTRAPTL1(0x2d) BTRAPTL1(0x2e) BTRAPTL1(0x2f) -tl1_dax: ACCESS_EXCEPTION_TRAPTL1(data_access_exception) +tl1_dax: TRAP_NOSAVE(__do_data_access_exception_tl1) tl1_resv031: BTRAPTL1(0x31) tl1_dae: TRAPTL1(do_dae_tl1) tl1_resv033: BTRAPTL1(0x33) diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/unaligned.c linux/arch/sparc64/kernel/unaligned.c --- v2.1.123/linux/arch/sparc64/kernel/unaligned.c Thu Aug 6 14:06:31 1998 +++ linux/arch/sparc64/kernel/unaligned.c Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -/* $Id: unaligned.c,v 1.10 1998/06/19 13:00:32 jj Exp $ +/* $Id: unaligned.c,v 1.11 1998/09/22 03:24:52 davem Exp $ * unaligned.c: Unaligned load/store trap handling with special * cases for the kernel to do them more quickly. * @@ -91,10 +91,13 @@ } static inline void maybe_flush_windows(unsigned int rs1, unsigned int rs2, - unsigned int rd) + unsigned int rd, int from_kernel) { if(rs2 >= 16 || rs1 >= 16 || rd >= 16) { - flushw_user(); + if(from_kernel != 0) + __asm__ __volatile__("flushw"); + else + flushw_user(); } } @@ -149,12 +152,13 @@ { unsigned int rs1 = (insn >> 14) & 0x1f; unsigned int rs2 = insn & 0x1f; + int from_kernel = (regs->tstate & TSTATE_PRIV) != 0; if(insn & 0x2000) { - maybe_flush_windows(rs1, 0, rd); + maybe_flush_windows(rs1, 0, rd, from_kernel); return (fetch_reg(rs1, regs) + sign_extend_imm13(insn)); } else { - maybe_flush_windows(rs1, rs2, rd); + maybe_flush_windows(rs1, rs2, rd, from_kernel); return (fetch_reg(rs1, regs) + fetch_reg(rs2, regs)); } } @@ -430,12 +434,13 @@ { u64 value; int ret, i, rd = ((insn >> 25) & 0x1f); + int from_kernel = (regs->tstate & TSTATE_PRIV) != 0; if (insn & 0x2000) { - maybe_flush_windows(0, 0, rd); + maybe_flush_windows(0, 0, rd, from_kernel); value = sign_extend_imm13(insn); } else { - maybe_flush_windows(0, insn & 0x1f, rd); + maybe_flush_windows(0, insn & 0x1f, rd, from_kernel); value = fetch_reg(insn & 0x1f, regs); } for (ret = 0, i = 0; i < 16; i++) { @@ -583,7 +588,8 @@ pc = (u32)pc; if (get_user(insn, (u32 *)pc) != -EFAULT) { asi = sfsr >> 16; - if (asi > ASI_SNFL) + if ((asi > ASI_SNFL) || + (asi < ASI_P)) goto daex; if (get_user(first, (u32 *)sfar) || get_user(second, (u32 *)(sfar + 4))) { @@ -637,7 +643,8 @@ asi = sfsr >> 16; value = 0; flag = (freg < 32) ? FPRS_DL : FPRS_DU; - if (asi > ASI_SNFL) + if ((asi > ASI_SNFL) || + (asi < ASI_P)) goto daex; save_and_clear_fpu(); if (current->tss.fpsaved[0] & flag) diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/winfixup.S linux/arch/sparc64/kernel/winfixup.S --- v2.1.123/linux/arch/sparc64/kernel/winfixup.S Thu Aug 6 14:06:31 1998 +++ linux/arch/sparc64/kernel/winfixup.S Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -/* $Id: winfixup.S,v 1.24 1998/06/12 14:54:19 jj Exp $ +/* $Id: winfixup.S,v 1.27 1998/09/25 01:09:14 davem Exp $ * * winfixup.S: Handle cases where user stack pointer is found to be bogus. * @@ -27,7 +27,7 @@ * These are layed out in a special way for cache reasons, * don't touch... */ - .globl winfix_trampoline, fill_fixup, spill_fixup + .globl fill_fixup, spill_fixup fill_fixup: rdpr %tstate, %g1 andcc %g1, TSTATE_PRIV, %g0 @@ -192,8 +192,8 @@ stxa %g0, [%g1] ASI_DMMU ! Back into the nucleus. flush %g6 ! Flush instruction buffers rdpr %pstate, %l1 ! Prepare to change globals. - mov %g4, %o5 ! Setup args for - mov %g5, %o4 ! final call to do_sparc64_fault. + mov %g4, %o2 ! Setup args for + mov %g5, %o1 ! final call to mem_address_unaligned. andn %l1, PSTATE_MM, %l1 ! We want to be in RMO mov %g6, %o7 ! Stash away current. @@ -261,7 +261,116 @@ sethi %hi(109f), %g7 ba,pt %xcc, etrap 109: or %g7, %lo(109b), %g7 + mov %l4, %o2 + mov %l5, %o1 call mem_address_unaligned + add %sp, STACK_BIAS + REGWIN_SZ, %o0 + ba,pt %xcc, rtrap + clr %l6 + + /* These are only needed for 64-bit mode processes which + * put their stack pointer into the VPTE area and there + * happens to be a VPTE tlb entry mapped there during + * a spill/fill trap to that stack frame. + */ + .globl winfix_dax, fill_fixup_dax, spill_fixup_dax +winfix_dax: + andn %g3, 0x7f, %g3 + add %g3, 0x74, %g3 + wrpr %g3, %tnpc + done +fill_fixup_dax: + rdpr %tstate, %g1 + andcc %g1, TSTATE_PRIV, %g0 + be,pt %xcc, window_dax_from_user_common + and %g1, TSTATE_CWP, %g1 + + /* Please, see fill_fixup commentary about why we must preserve + * %l5 and %l6 to preserve absolute correct semantics. + */ + rdpr %wstate, %g2 ! Grab user mode wstate. + wrpr %g1, %cwp ! Get into the right window. + sll %g2, 3, %g2 ! NORMAL-->OTHER + wrpr %g0, 0x0, %canrestore ! Standard etrap stuff. + + wrpr %g2, 0x0, %wstate ! This must be consistant. + wrpr %g0, 0x0, %otherwin ! We know this. + mov PRIMARY_CONTEXT, %g1 ! Change contexts... + stxa %g0, [%g1] ASI_DMMU ! Back into the nucleus. + flush %g6 ! Flush instruction buffers + rdpr %pstate, %l1 ! Prepare to change globals. + mov %g4, %o1 ! Setup args for + mov %g5, %o2 ! final call to data_access_exception. + andn %l1, PSTATE_MM, %l1 ! We want to be in RMO + + mov %g6, %o7 ! Stash away current. + wrpr %g0, 0x0, %tl ! Out of trap levels. + wrpr %l1, (PSTATE_IE | PSTATE_AG | PSTATE_RMO), %pstate + sethi %uhi(PAGE_OFFSET), %g4 ! Set page_offset global reg. + mov %o7, %g6 ! Get current back. + sllx %g4, 32, %g4 ! Finish it. + call data_access_exception + add %sp, STACK_BIAS + REGWIN_SZ, %o0 + + b,pt %xcc, rtrap + nop ! yes, the nop is correct +spill_fixup_dax: + lduh [%g6 + AOFF_task_tss + AOFF_thread_flags], %g1 + andcc %g1, SPARC_FLAG_32BIT, %g0 + lduh [%g6 + AOFF_task_tss + AOFF_thread_w_saved], %g1 + sll %g1, 3, %g3 + add %g6, %g3, %g3 + stx %sp, [%g3 + AOFF_task_tss + AOFF_thread_rwbuf_stkptrs] + + sll %g1, 7, %g3 + bne,pt %xcc, 1f + add %g6, %g3, %g3 + stx %l0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x00] + stx %l1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x08] + stx %l2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x10] + stx %l3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x18] + stx %l4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x20] + + stx %l5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x28] + stx %l6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x30] + stx %l7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x38] + stx %i0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x40] + stx %i1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x48] + stx %i2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x50] + stx %i3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x58] + stx %i4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x60] + + stx %i5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x68] + stx %i6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x70] + stx %i7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x78] + b,pt %xcc, 2f + add %g1, 1, %g1 +1: std %l0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x00] + std %l2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x08] + std %l4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x10] + + std %l6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x18] + std %i0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x20] + std %i2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x28] + std %i4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x30] + std %i6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x38] + add %g1, 1, %g1 +2: sth %g1, [%g6 + AOFF_task_tss + AOFF_thread_w_saved] + rdpr %tstate, %g1 + + andcc %g1, TSTATE_PRIV, %g0 + saved + be,pn %xcc, window_dax_from_user_common + and %g1, TSTATE_CWP, %g1 + retry +window_dax_from_user_common: + wrpr %g1, %cwp + sethi %hi(109f), %g7 + ba,pt %xcc, etrap +109: or %g7, %lo(109b), %g7 + mov %l4, %o1 + mov %l5, %o2 + call data_access_exception add %sp, STACK_BIAS + REGWIN_SZ, %o0 ba,pt %xcc, rtrap clr %l6 diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/lib/checksum.S linux/arch/sparc64/lib/checksum.S --- v2.1.123/linux/arch/sparc64/lib/checksum.S Mon Jan 12 15:15:44 1998 +++ linux/arch/sparc64/lib/checksum.S Sun Oct 4 10:22:43 1998 @@ -180,7 +180,7 @@ bcs,a,pn %xcc, 1f ! CTI add %o0, 1, %o0 ! IEU1 4 clocks (mispredict) 1: retl ! CTI Group brk forced - sllx %g4, 32,%g4 ! IEU0 Group + sllx %g4, 32, %g4 ! IEU0 Group ccslow: mov 0, %g5 brlez,pn %len, 4f @@ -268,8 +268,9 @@ sub %g0, EFAULT, %g2 brnz,a,pt %g1, 1f st %g2, [%g1] -1: retl - nop +1: sethi %uhi(PAGE_OFFSET), %g4 + retl + sllx %g4, 32, %g4 .section __ex_table .align 4 diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/lib/strlen.S linux/arch/sparc64/lib/strlen.S --- v2.1.123/linux/arch/sparc64/lib/strlen.S Thu Mar 27 14:40:01 1997 +++ linux/arch/sparc64/lib/strlen.S Sun Oct 4 10:22:43 1998 @@ -8,9 +8,9 @@ #define LO_MAGIC 0x01010101 #define HI_MAGIC 0x80808080 - .align 4 - .global strlen -strlen: + .align 32 + .global __strlen +__strlen: mov %o0, %o1 andcc %o0, 3, %g0 be,pt %icc, 9f diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/mm/asyncd.c linux/arch/sparc64/mm/asyncd.c --- v2.1.123/linux/arch/sparc64/mm/asyncd.c Wed Sep 9 14:51:06 1998 +++ linux/arch/sparc64/mm/asyncd.c Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -/* $Id: asyncd.c,v 1.4 1998/05/24 02:53:58 davem Exp $ +/* $Id: asyncd.c,v 1.5 1998/09/13 04:30:33 davem Exp $ * The asyncd kernel daemon. This handles paging on behalf of * processes that receive page faults due to remote (async) memory * accesses. diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/mm/fault.c linux/arch/sparc64/mm/fault.c --- v2.1.123/linux/arch/sparc64/mm/fault.c Thu Apr 23 20:21:32 1998 +++ linux/arch/sparc64/mm/fault.c Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -/* $Id: fault.c,v 1.21 1998/03/25 10:43:20 jj Exp $ +/* $Id: fault.c,v 1.24 1998/09/22 03:27:33 davem Exp $ * arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -100,49 +100,38 @@ (unsigned long) tsk->mm->context); printk(KERN_ALERT "tsk->mm->pgd = %016lx\n", (unsigned long) tsk->mm->pgd); + lock_kernel(); die_if_kernel("Oops", regs); -} - -asmlinkage int lookup_fault(unsigned long pc, unsigned long ret_pc, - unsigned long address) -{ - unsigned long g2; - int i; - unsigned insn; - struct pt_regs regs; - - i = search_exception_table (ret_pc, &g2); - switch (i) { - /* load & store will be handled by fixup */ - case 3: return 3; - /* store will be handled by fixup, load will bump out */ - /* for _to_ macros */ - case 1: insn = *(unsigned *)pc; if ((insn >> 21) & 1) return 1; break; - /* load will be handled by fixup, store will bump out */ - /* for _from_ macros */ - case 2: insn = *(unsigned *)pc; - if (!((insn >> 21) & 1) || ((insn>>19)&0x3f) == 15) return 2; - break; - default: break; - } - memset (®s, 0, sizeof (regs)); - regs.tpc = pc; - regs.tnpc = pc + 4; - /* FIXME: Should set up regs->tstate? */ - unhandled_fault (address, current, ®s); - /* Not reached */ - return 0; + unlock_kernel(); } /* #define DEBUG_EXCEPTIONS */ +/* #define DEBUG_LOCKUPS */ asmlinkage void do_sparc64_fault(struct pt_regs *regs, unsigned long address, int write) { struct mm_struct *mm = current->mm; struct vm_area_struct *vma; +#ifdef DEBUG_LOCKUPS + static unsigned long lastaddr, lastpc; + static int lastwrite, lockcnt; +#endif - lock_kernel(); down(&mm->mmap_sem); +#ifdef DEBUG_LOCKUPS + if (regs->tpc == lastpc && address == lastaddr && write == lastwrite) { + lockcnt++; + if (lockcnt == 100000) { + printk("do_sparc64_fault: possible fault loop for %016lx %s\n", address, write ? "write" : "read"); + show_regs(regs); + } + } else { + lastpc = regs->tpc; + lastaddr = address; + lastwrite = write; + lockcnt = 0; + } +#endif vma = find_vma(mm, address); if(!vma) goto bad_area; @@ -167,7 +156,7 @@ } handle_mm_fault(current, vma, address, write); up(&mm->mmap_sem); - goto out; + return; /* * Something tried to access memory that isn't in our memory map.. * Fix it, but check if it's kernel or user first.. @@ -204,16 +193,14 @@ regs->tpc = fixup; regs->tnpc = regs->tpc + 4; regs->u_regs[UREG_G2] = g2; - goto out; + return; } } else { current->tss.sig_address = address; current->tss.sig_desc = SUBSIG_NOMAPPING; force_sig(SIGSEGV, current); - goto out; + return; } unhandled_fault (address, current, regs); } -out: - unlock_kernel(); } diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c --- v2.1.123/linux/arch/sparc64/mm/init.c Thu Aug 6 14:06:31 1998 +++ linux/arch/sparc64/mm/init.c Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.93 1998/08/04 20:49:25 davem Exp $ +/* $Id: init.c,v 1.98 1998/09/28 06:18:39 davem Exp $ * arch/sparc64/mm/init.c * * Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu) @@ -37,7 +37,8 @@ /* Ugly, but necessary... -DaveM */ unsigned long phys_base; -unsigned long tlb_context_cache = CTX_FIRST_VERSION; +/* get_new_mmu_context() uses "cache + 1". */ +unsigned long tlb_context_cache = CTX_FIRST_VERSION - 1; /* References to section boundaries */ extern char __init_begin, __init_end, etext, __bss_start; @@ -565,9 +566,9 @@ unsigned long prom_reserved_base = 0xfffffffc00000000UL; int i; - __asm__ __volatile__("rdpr %%pstate, %0\n\t" - "wrpr %0, %1, %%pstate\n\t" - "flushw" + __asm__ __volatile__("flushw\n\t" + "rdpr %%pstate, %0\n\t" + "wrpr %0, %1, %%pstate" : "=r" (pstate) : "i" (PSTATE_IE)); @@ -720,6 +721,18 @@ membar("#Sync"); } +void __flush_dcache_range(unsigned long start, unsigned long end) +{ + unsigned long va; + int n = 0; + + for (va = start; va < end; va += 32) { + spitfire_put_dcache_tag(va & 0x3fe0, 0x0); + if (++n >= 512) + break; + } +} + void __flush_cache_all(void) { unsigned long va; @@ -735,9 +748,9 @@ unsigned long pstate; int i; - __asm__ __volatile__("rdpr %%pstate, %0\n\t" - "wrpr %0, %1, %%pstate\n\t" - "flushw" + __asm__ __volatile__("flushw\n\t" + "rdpr %%pstate, %0\n\t" + "wrpr %0, %1, %%pstate" : "=r" (pstate) : "i" (PSTATE_IE)); for(i = 0; i < 64; i++) { @@ -913,7 +926,6 @@ pte_clear(ptep); } -#ifdef NOTUSED void sparc_ultra_dump_itlb(void) { int slot; @@ -933,17 +945,17 @@ { int slot; - prom_printf ("Contents of dtlb: "); + printk ("Contents of dtlb: "); for (slot = 0; slot < 14; slot++) printk (" "); - prom_printf ("%2x:%016lx,%016lx\n", 0, spitfire_get_dtlb_tag(0), spitfire_get_dtlb_data(0)); + printk ("%2x:%016lx,%016lx\n", 0, spitfire_get_dtlb_tag(0), + spitfire_get_dtlb_data(0)); for (slot = 1; slot < 64; slot+=3) { - prom_printf ("%2x:%016lx,%016lx %2x:%016lx,%016lx %2x:%016lx,%016lx\n", + printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx %2x:%016lx,%016lx\n", slot, spitfire_get_dtlb_tag(slot), spitfire_get_dtlb_data(slot), slot+1, spitfire_get_dtlb_tag(slot+1), spitfire_get_dtlb_data(slot+1), slot+2, spitfire_get_dtlb_tag(slot+2), spitfire_get_dtlb_data(slot+2)); } } -#endif /* paging_init() sets up the page tables */ diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/mm/ultra.S linux/arch/sparc64/mm/ultra.S --- v2.1.123/linux/arch/sparc64/mm/ultra.S Thu Aug 6 14:06:31 1998 +++ linux/arch/sparc64/mm/ultra.S Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -/* $Id: ultra.S,v 1.24 1998/05/22 11:02:56 davem Exp $ +/* $Id: ultra.S,v 1.27 1998/09/28 06:18:42 davem Exp $ * ultra.S: Don't expand these all over the place... * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -56,6 +56,7 @@ __flush_tlb_range_constant_time: /* %o0=ctx, %o1=start, %o3=end */ /*IC5*/ rdpr %pstate, %g1 wrpr %g1, PSTATE_IE, %pstate + mov TLB_TAG_ACCESS, %g3 mov (62 << 3), %g2 1: ldxa [%g2] ASI_ITLB_TAG_READ, %o4 and %o4, 0x3ff, %o5 @@ -80,10 +81,12 @@ sub %g2, (1 << 3), %g2 /*IC8*/ retl wrpr %g1, 0x0, %pstate -4: stxa %g0, [%g2] ASI_ITLB_DATA_ACCESS +4: stxa %g0, [%g3] ASI_IMMU + stxa %g0, [%g2] ASI_ITLB_DATA_ACCESS ba,pt %xcc, 2b flush %g6 -5: stxa %g0, [%g2] ASI_DTLB_DATA_ACCESS +5: stxa %g0, [%g3] ASI_DMMU + stxa %g0, [%g2] ASI_DTLB_DATA_ACCESS ba,pt %xcc, 3b flush %g6 __flush_tlb_mm_slow: @@ -121,6 +124,35 @@ flush %g6 retl wrpr %g1, 0x0, %pstate + + /* Unfortunately, it is necessary. */ + .globl flush_page_to_ram +flush_page_to_ram: /* %o0 = page */ + rdpr %pstate, %g5 + wrpr %g5, PSTATE_IE, %pstate + sethi %hi(dcache_aliases_found), %g1 + ldx [%g1 + %lo(dcache_aliases_found)], %g2 + sub %o0, %g4, %o0 ! Get phys_page + clr %o2 ! This dcache area begin + sethi %hi(1<<14), %o1 ! This dcache area end +1: ldxa [%o2] ASI_DCACHE_TAG, %o3 + andcc %o3, 0x3, %g0 ! Valid bits set? + be,pn %xcc, 2f ! Nope, skip this one + andn %o3, 0x3, %o3 ! Mask out valid bits + sllx %o3, (13 - 2), %o3 ! Shift into physaddr + cmp %o3, %o0 ! Match? + bne,pt %xcc, 2f ! Nope, skip to next + nop + stxa %g0, [%o2] ASI_DCACHE_TAG + membar #Sync + add %g2, 1, %g2 ! Increment alias counter +2: add %o2, (1<<5), %o2 ! 32-bytes per full line + cmp %o2, %o1 + bne,pt %xcc, 1b + nop + stx %g2, [%g1 + %lo(dcache_aliases_found)] + retl + wrpr %g5, 0x0, %pstate #ifdef __SMP__ /* These are all called by the slaves of a cross call, at diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/solaris/conv.h linux/arch/sparc64/solaris/conv.h --- v2.1.123/linux/arch/sparc64/solaris/conv.h Thu Apr 23 20:21:32 1998 +++ linux/arch/sparc64/solaris/conv.h Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -/* $Id: conv.h,v 1.3 1998/03/26 08:46:13 jj Exp $ +/* $Id: conv.h,v 1.4 1998/08/15 20:42:51 davem Exp $ * conv.h: Utility macros for Solaris emulation * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -11,13 +11,14 @@ #include -/* As gcc will warn about casting u32 to some ptr, we have to cast it to - * unsigned long first, and that's what is A() for. - * You just do (void *)A(x), instead of having to - * type (void *)((unsigned long)x) or instead of just (void *)x, which will - * produce warnings. - */ -#define A(x) ((unsigned long)x) +/* Use this to get at 32-bit user passed pointers. */ +#define A(__x) \ +({ unsigned long __ret; \ + __asm__ ("srl %0, 0, %0" \ + : "=r" (__ret) \ + : "0" (__x)); \ + __ret; \ +}) extern unsigned sys_call_table[]; extern unsigned sys_call_table32[]; diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/solaris/socksys.c linux/arch/sparc64/solaris/socksys.c --- v2.1.123/linux/arch/sparc64/solaris/socksys.c Wed Aug 26 11:37:34 1998 +++ linux/arch/sparc64/solaris/socksys.c Sun Oct 4 10:22:43 1998 @@ -1,4 +1,4 @@ -/* $Id: socksys.c,v 1.7 1998/03/29 10:11:04 davem Exp $ +/* $Id: socksys.c,v 1.8 1998/08/26 10:28:28 davem Exp $ * socksys.c: /dev/inet/ stuff for Solaris emulation. * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) diff -u --recursive --new-file v2.1.123/linux/drivers/block/Config.in linux/drivers/block/Config.in --- v2.1.123/linux/drivers/block/Config.in Thu Sep 17 17:53:35 1998 +++ linux/drivers/block/Config.in Mon Sep 28 11:09:52 1998 @@ -33,6 +33,7 @@ bool ' Generic PCI IDE chipset support' CONFIG_BLK_DEV_IDEPCI if [ "$CONFIG_BLK_DEV_IDEPCI" = "y" ]; then bool ' Generic PCI bus-master DMA support' CONFIG_BLK_DEV_IDEDMA + bool ' Boot off-board chipsets first support' CONFIG_BLK_DEV_OFFBOARD if [ "$CONFIG_BLK_DEV_IDEDMA" = "y" ]; then bool ' Use DMA by default when available' CONFIG_IDEDMA_AUTO fi diff -u --recursive --new-file v2.1.123/linux/drivers/block/floppy.c linux/drivers/block/floppy.c --- v2.1.123/linux/drivers/block/floppy.c Thu Sep 17 17:53:35 1998 +++ linux/drivers/block/floppy.c Wed Sep 30 15:58:53 1998 @@ -102,6 +102,10 @@ * failures. */ +/* + * 1998/09/20 -- David Weinehall -- Added slow-down code for buggy PS/2-drives. + */ + #define FLOPPY_SANITY_CHECK #undef FLOPPY_SILENT_DCL_CLEAR @@ -149,6 +153,8 @@ #include #include +static int slow_floppy = 0; + #include #include #include @@ -1300,6 +1306,9 @@ /* Convert step rate from microseconds to milliseconds and 4 bits */ srt = 16 - (DP->srt*scale_dtr/1000 + NOMINAL_DTR - 1)/NOMINAL_DTR; + if( slow_floppy ) { + srt = srt / 4; + } SUPBOUND(srt, 0xf); INFBOUND(srt, 0); @@ -4026,7 +4035,16 @@ { int i; int param; - if (str) + if (str) { + /* + * PS/2 floppies have much slower step rates than regular floppies. + * It's been recommended that take about 1/4 of the default speed + * in some more extreme cases. + */ + if( strcmp(str,"slow") == 0) { + slow_floppy = 1; + return; + } for (i=0; i< ARRAY_SIZE(config_params); i++){ if (strcmp(str,config_params[i].name) == 0){ if (ints[0]) @@ -4044,6 +4062,7 @@ return; } } + } if (str) { DPRINT("unknown floppy option [%s]\n", str); diff -u --recursive --new-file v2.1.123/linux/drivers/block/ide-pci.c linux/drivers/block/ide-pci.c --- v2.1.123/linux/drivers/block/ide-pci.c Thu Sep 17 17:53:35 1998 +++ linux/drivers/block/ide-pci.c Mon Sep 28 11:09:52 1998 @@ -117,29 +117,39 @@ unsigned int extra; } ide_pci_device_t; +#ifdef CONFIG_BLK_DEV_OFFBOARD +# define ON_BOARD 0 +# define OFF_BOARD 1 +# define NEVER_BOARD 0 +#else /* CONFIG_BLK_DEV_OFFBOARD */ +# define ON_BOARD 1 +# define OFF_BOARD 0 +# define NEVER_BOARD 0 +#endif /* CONFIG_BLK_DEV_OFFBOARD */ + static ide_pci_device_t ide_pci_chipsets[] __initdata = { - {DEVID_PIIXa, "PIIX", NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 0x01, 0 }, - {DEVID_PIIXb, "PIIX", NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 0x01, 0 }, - {DEVID_PIIX3, "PIIX3", NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 0x01, 0 }, - {DEVID_PIIX4, "PIIX4", NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 0x01, 0 }, - {DEVID_VP_IDE, "VP_IDE", INIT_VIA82C586, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, 0x01, 0 }, - {DEVID_PDC20246,"PDC20246", NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, 0x01, 16 }, - {DEVID_RZ1000, "RZ1000", INIT_RZ1000, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 0x01, 0 }, - {DEVID_RZ1001, "RZ1001", INIT_RZ1000, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 0x01, 0 }, - {DEVID_CMD640, "CMD640", IDE_IGNORE, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 0x01, 0 }, - {DEVID_NS87410, "NS87410", NULL, {{0x43,0x08,0x08}, {0x47,0x08,0x08}}, 0x01, 0 }, - {DEVID_SIS5513, "SIS5513", NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, 0x01, 0 }, - {DEVID_CMD646, "CMD646", INIT_CMD646, {{0x00,0x00,0x00}, {0x51,0x80,0x80}}, 0x01, 0 }, - {DEVID_HT6565, "HT6565", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 0x01, 0 }, - {DEVID_OPTI621, "OPTI621", INIT_OPTI621, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, 0x01, 0 }, - {DEVID_OPTI621X,"OPTI621X", INIT_OPTI621, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, 0x01, 0 }, - {DEVID_TRM290, "TRM290", INIT_TRM290, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 0x01, 0 }, - {DEVID_NS87415, "NS87415", INIT_NS87415, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 0x01, 0 }, - {DEVID_AEC6210, "AEC6210", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 0x01, 0 }, - {DEVID_W82C105, "W82C105", INIT_W82C105, {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, 0x01, 0 }, - {DEVID_UM8886BF,"UM8886BF", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 0x01, 0 }, - {DEVID_HPT343, "HPT343", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 0x00, 16 }, - {IDE_PCI_DEVID_NULL, "PCI_IDE", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 0x01, 0 }}; + {DEVID_PIIXa, "PIIX", NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIXb, "PIIX", NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX3, "PIIX3", NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX4, "PIIX4", NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_VP_IDE, "VP_IDE", INIT_VIA82C586, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 }, + {DEVID_PDC20246,"PDC20246", NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 16 }, + {DEVID_RZ1000, "RZ1000", INIT_RZ1000, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_RZ1001, "RZ1001", INIT_RZ1000, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_CMD640, "CMD640", IDE_IGNORE, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_NS87410, "NS87410", NULL, {{0x43,0x08,0x08}, {0x47,0x08,0x08}}, ON_BOARD, 0 }, + {DEVID_SIS5513, "SIS5513", NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, ON_BOARD, 0 }, + {DEVID_CMD646, "CMD646", INIT_CMD646, {{0x00,0x00,0x00}, {0x51,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_HT6565, "HT6565", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_OPTI621, "OPTI621", INIT_OPTI621, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 }, + {DEVID_OPTI621X,"OPTI621X", INIT_OPTI621, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 }, + {DEVID_TRM290, "TRM290", INIT_TRM290, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_NS87415, "NS87415", INIT_NS87415, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_AEC6210, "AEC6210", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, + {DEVID_W82C105, "W82C105", INIT_W82C105, {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, ON_BOARD, 0 }, + {DEVID_UM8886BF,"UM8886BF", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_HPT343, "HPT343", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 16 }, + {IDE_PCI_DEVID_NULL, "PCI_IDE", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }}; /* * This allows offboard ide-pci cards the enable a BIOS, verify interrupt @@ -175,6 +185,8 @@ pci_write_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, irq1); /* 0xbc */ } } + return dev->irq; + case PCI_DEVICE_ID_TTI_HPT343: return dev->irq; default: break; diff -u --recursive --new-file v2.1.123/linux/drivers/block/ns87415.c linux/drivers/block/ns87415.c --- v2.1.123/linux/drivers/block/ns87415.c Thu Aug 6 14:06:31 1998 +++ linux/drivers/block/ns87415.c Sun Oct 4 10:22:43 1998 @@ -74,8 +74,8 @@ case ide_dma_end: /* returns 1 on error, 0 otherwise */ drive->waiting_for_dma = 0; dma_stat = inb(hwif->dma_base+2); - outb(7, hwif->dma_base); /* from errata: stop DMA, clear INTR & ERROR */ - outb(dma_stat|6, hwif->dma_base+2); /* clear the INTR & ERROR bits */ + outb(inb(hwif->dma_base)&~1, hwif->dma_base); /* stop DMA */ + outb(inb(hwif->dma_base)|6, hwif->dma_base); /* from ERRATA: clear the INTR & ERROR bits */ return (dma_stat & 7) != 4; /* verify good DMA status */ case ide_dma_write: case ide_dma_read: diff -u --recursive --new-file v2.1.123/linux/drivers/block/paride/frpw.c linux/drivers/block/paride/frpw.c --- v2.1.123/linux/drivers/block/paride/frpw.c Wed May 20 19:10:38 1998 +++ linux/drivers/block/paride/frpw.c Mon Sep 28 10:51:16 1998 @@ -12,10 +12,11 @@ 1.01 GRG 1998.05.06 init_proto, release_proto fix chip detect added EPP-16 and EPP-32 + 1.02 GRG 1998.09.23 added hard reset to initialisation process */ -#define FRPW_VERSION "1.01" +#define FRPW_VERSION "1.02" #include #include @@ -183,6 +184,9 @@ /* returns chip_type: 0 = Xilinx, 1 = ASIC */ { int olddelay, a, b; + + w0(0); w2(8); udelay(50); w2(0xc); /* parallel bus reset */ + mdelay(1500); olddelay = pi->delay; pi->delay = 10; diff -u --recursive --new-file v2.1.123/linux/drivers/block/paride/jumbo linux/drivers/block/paride/jumbo --- v2.1.123/linux/drivers/block/paride/jumbo Wed Dec 31 16:00:00 1969 +++ linux/drivers/block/paride/jumbo Mon Sep 28 10:51:16 1998 @@ -0,0 +1,70 @@ +#!/bin/sh +# +# This script can be used to build "jumbo" modules that contain the +# base PARIDE support, one protocol module and one high-level driver. +# +echo -n "High level driver [pcd] : " +read X +HLD=${X:-pcd} +# +echo -n "Protocol module [bpck] : " +read X +PROTO=${X:-bpck} +# +echo -n "Use MODVERSIONS [y] ? " +read X +UMODV=${X:-y} +# +echo -n "For SMP kernel [n] ? " +read X +USMP=${X:-n} +# +echo -n "Support PARPORT [n] ? " +read X +UPARP=${X:-n} +# +echo +# +case $USMP in + y* | Y* ) FSMP="-D__SMP__" + ;; + *) FSMP="" + ;; +esac +# +MODI="-include ../../../include/linux/modversions.h" +# +case $UMODV in + y* | Y* ) FMODV="-DMODVERSIONS $MODI" + ;; + *) FMODV="" + ;; +esac +# +case $UPARP in + y* | Y* ) FPARP="-DCONFIG_PARPORT" + ;; + *) FPARP="" + ;; +esac +# +TARG=$HLD-$PROTO.o +FPROTO=-DCONFIG_PARIDE_`echo "$PROTO" | tr [a-z] [A-Z]` +FK="-D__KERNEL__ -I ../../../include" +FLCH=-D_LINUX_CONFIG_H +# +echo cc $FK $FSMP $FLCH $FPARP $FPROTO -Wall -O2 -o Jb.o -c paride.c +cc $FK $FSMP $FLCH $FPARP $FPROTO -Wall -O2 -o Jb.o -c paride.c +# +echo cc $FK $FSMP -Wall -O2 -o Jp.o -c $PROTO.c +cc $FK $FSMP -Wall -O2 -o Jp.o -c $PROTO.c +# +echo cc $FK $FSMP $FMODV -DMODULE -DPARIDE_JUMBO -Wall -O2 -o Jd.o -c $HLD.c +cc $FK $FSMP $FMODV -DMODULE -DPARIDE_JUMBO -Wall -O2 -o Jd.o -c $HLD.c +# +echo ld -r -o $TARG Jp.o Jb.o Jd.o +ld -r -o $TARG Jp.o Jb.o Jd.o +# +# +rm Jp.o Jb.o Jd.o +# diff -u --recursive --new-file v2.1.123/linux/drivers/block/paride/on26.c linux/drivers/block/paride/on26.c --- v2.1.123/linux/drivers/block/paride/on26.c Wed May 20 19:10:38 1998 +++ linux/drivers/block/paride/on26.c Mon Sep 28 10:51:16 1998 @@ -10,10 +10,11 @@ /* Changes: 1.01 GRG 1998.05.06 init_proto, release_proto + 1.02 GRG 1998.09.23 updates for the -E rev chip */ -#define ON26_VERSION "1.01" +#define ON26_VERSION "1.02" #include #include @@ -91,8 +92,8 @@ } } -#define CCP(x) w0(0xff);w0(0xaa);w0(0x55);w0(0);w0(0xff);\ - w0(0x87);w0(0x78);w0(x);w2(4); +#define CCP(x) w0(0xfe);w0(0xaa);w0(0x55);w0(0);w0(0xff);\ + w0(0x87);w0(0x78);w0(x);w2(4);w2(5);w2(4);w0(0xff); static void on26_connect ( PIA *pi ) @@ -102,7 +103,6 @@ pi->saved_r2 = r2(); CCP(0x20); - w2(0xcd); w2(0xcc); w0(0xff); x = 8; if (pi->mode) x = 9; w0(2); P1; w0(8); P2; @@ -114,11 +114,62 @@ { if (pi->mode >= 2) { w3(4); w3(4); w3(4); w3(4); } else { w0(4); P1; w0(4); P1; } CCP(0x30); - w2(0xcd); w2(0xcc); w0(0xff); w0(pi->saved_r0); w2(pi->saved_r2); } +static int on26_test_port( PIA *pi) /* hard reset */ + +{ int i, m, d; + + pi->saved_r0 = r0(); + pi->saved_r2 = r2(); + + d = pi->delay; + m = pi->mode; + pi->delay = 5; + pi->mode = 0; + + w2(0xc); + + CCP(0x30); CCP(0); + + w0(0xfe);w0(0xaa);w0(0x55);w0(0);w0(0xff); + i = ((r1() & 0xf0) << 4); w0(0x87); + i |= (r1() & 0xf0); w0(0x78); + w0(0x20);w2(4);w2(5); + i |= ((r1() & 0xf0) >> 4); + w2(4);w0(0xff); + + if (i == 0xb5f) { + + w0(2); P1; w0(0); P2; + w0(3); P1; w0(0); P2; + w0(2); P1; w0(8); P2; udelay(100); + w0(2); P1; w0(0xa); P2; udelay(100); + w0(2); P1; w0(8); P2; udelay(1000); + + on26_write_regr(pi,0,6,0xa0); + + for (i=0;i<100;i++) { + if (!(on26_read_regr(pi,0,7) & 0x80)) break; + udelay(100000); + } + + w0(4); P1; w0(4); P1; + } + + CCP(0x30); + + pi->delay = d; + pi->mode = m; + w0(pi->saved_r0); + w2(pi->saved_r2); + + return 5; +} + + static void on26_read_block( PIA *pi, char * buf, int count ) { int k, a, b; @@ -240,7 +291,7 @@ on26_read_block, on26_connect, on26_disconnect, - 0, + on26_test_port, 0, 0, on26_log_adapter, diff -u --recursive --new-file v2.1.123/linux/drivers/block/paride/pcd.c linux/drivers/block/paride/pcd.c --- v2.1.123/linux/drivers/block/paride/pcd.c Wed Aug 26 11:37:35 1998 +++ linux/drivers/block/paride/pcd.c Mon Sep 28 10:51:16 1998 @@ -96,10 +96,11 @@ pcd_completion, use HZ in loop timing 1.05 GRG 1998.08.16 Conformed to "Uniform CD-ROM" standard 1.06 GRG 1998.08.19 Added audio ioctl support + 1.07 GRG 1998.09.24 Increased reset timeout, added jumbo support */ -#define PCD_VERSION "1.06" +#define PCD_VERSION "1.07" #define PCD_MAJOR 46 #define PCD_NAME "pcd" #define PCD_UNITS 4 @@ -191,7 +192,7 @@ #define PCD_TMO 800 /* timeout in jiffies */ #define PCD_DELAY 50 /* spin delay in uS */ #define PCD_READY_TMO 20 /* in seconds */ -#define PCD_RESET_TMO 30 /* in tenths of a second */ +#define PCD_RESET_TMO 100 /* in tenths of a second */ #define PCD_SPIN (1000000*PCD_TMO)/(HZ*PCD_DELAY) @@ -364,6 +365,12 @@ int init_module(void) { int err; + +#ifdef PARIDE_JUMBO + { extern paride_init(); + paride_init(); + } +#endif err = pcd_init(); diff -u --recursive --new-file v2.1.123/linux/drivers/block/paride/pd.c linux/drivers/block/paride/pd.c --- v2.1.123/linux/drivers/block/paride/pd.c Wed Aug 26 11:37:35 1998 +++ linux/drivers/block/paride/pd.c Mon Sep 28 10:51:16 1998 @@ -110,10 +110,11 @@ Added slave support 1.03 GRG 1998.06.16 Eliminate an Ugh. 1.04 GRG 1998.08.15 Extra debugging, use HZ in loop timing + 1.05 GRG 1998.09.24 Added jumbo support */ -#define PD_VERSION "1.04" +#define PD_VERSION "1.05" #define PD_MAJOR 45 #define PD_NAME "pd" #define PD_UNITS 4 @@ -610,6 +611,12 @@ int init_module(void) { int err, unit; + +#ifdef PARIDE_JUMBO + { extern paride_init(); + paride_init(); + } +#endif err = pd_init(); if (err) return err; diff -u --recursive --new-file v2.1.123/linux/drivers/block/paride/pf.c linux/drivers/block/paride/pf.c --- v2.1.123/linux/drivers/block/paride/pf.c Wed Aug 26 11:37:35 1998 +++ linux/drivers/block/paride/pf.c Mon Sep 28 10:51:16 1998 @@ -109,10 +109,11 @@ up transfer size. 1.02 GRG 1998.06.16 Eliminated an Ugh 1.03 GRG 1998.08.16 Use HZ in loop timings, extra debugging + 1.04 GRG 1998.09.24 Added jumbo support */ -#define PF_VERSION "1.03" +#define PF_VERSION "1.04" #define PF_MAJOR 47 #define PF_NAME "pf" #define PF_UNITS 4 @@ -508,6 +509,12 @@ int init_module(void) { int err; + +#ifdef PARIDE_JUMBO + { extern paride_init(); + paride_init(); + } +#endif err = pf_init(); diff -u --recursive --new-file v2.1.123/linux/drivers/block/paride/pg.c linux/drivers/block/paride/pg.c --- v2.1.123/linux/drivers/block/paride/pg.c Wed Aug 26 11:37:35 1998 +++ linux/drivers/block/paride/pg.c Mon Sep 28 10:51:16 1998 @@ -34,10 +34,10 @@ To use this device, you must have the following device special files defined: - /dev/pg0 b 97 0 - /dev/pg1 b 97 1 - /dev/pg2 b 97 2 - /dev/pg3 b 97 3 + /dev/pg0 c 97 0 + /dev/pg1 c 97 1 + /dev/pg2 c 97 2 + /dev/pg3 c 97 3 (You'll need to change the 97 to something else if you use the 'major' parameter to install the driver on a different @@ -117,9 +117,11 @@ /* Changes: 1.01 GRG 1998.06.16 Bug fixes + 1.02 GRG 1998.09.24 Added jumbo support + */ -#define PG_VERSION "1.01" +#define PG_VERSION "1.02" #define PG_MAJOR 97 #define PG_NAME "pg" #define PG_UNITS 4 @@ -323,6 +325,12 @@ int init_module(void) { int err; + +#ifdef PARIDE_JUMBO + { extern paride_init(); + paride_init(); + } +#endif err = pg_init(); diff -u --recursive --new-file v2.1.123/linux/drivers/block/paride/pt.c linux/drivers/block/paride/pt.c --- v2.1.123/linux/drivers/block/paride/pt.c Wed Aug 26 11:37:35 1998 +++ linux/drivers/block/paride/pt.c Mon Sep 28 10:51:16 1998 @@ -100,10 +100,11 @@ 1.02 GRG 1998.06.16 Eliminate an Ugh. 1.03 GRG 1998.08.15 Adjusted PT_TMO, use HZ in loop timing, extra debugging - + 1.04 GRG 1998.09.24 Repair minor coding error, added jumbo support + */ -#define PT_VERSION "1.03" +#define PT_VERSION "1.04" #define PT_MAJOR 96 #define PT_NAME "pt" #define PT_UNITS 4 @@ -328,6 +329,12 @@ { int err; +#ifdef PARIDE_JUMBO + { extern paride_init(); + paride_init(); + } +#endif + err = pt_init(); return err; @@ -584,8 +591,8 @@ char *ms[2] = {"master","slave"}; char mf[10], id[18]; char id_cmd[12] = { ATAPI_IDENTIFY,0,0,0,36,0,0,0,0,0,0,0}; - char ms_cmd[12] = { ATAPI_MODE_SENSE,0,0x2a,0,128,0,0,0,0,0,0,0}; - char ls_cmd[12] = { ATAPI_LOG_SENSE,0,0x71,0,0,0,0,0,128,0,0,0}; + char ms_cmd[12] = { ATAPI_MODE_SENSE,0,0x2a,0,36,0,0,0,0,0,0,0}; + char ls_cmd[12] = { ATAPI_LOG_SENSE,0,0x71,0,0,0,0,0,36,0,0,0}; char buf[36]; s = pt_atapi(unit,id_cmd,36,buf,"identify"); diff -u --recursive --new-file v2.1.123/linux/drivers/char/Makefile linux/drivers/char/Makefile --- v2.1.123/linux/drivers/char/Makefile Mon Sep 28 10:51:33 1998 +++ linux/drivers/char/Makefile Sun Oct 4 10:22:43 1998 @@ -27,17 +27,16 @@ L_OBJS += vt.o vc_screen.o consolemap.o consolemap_deftbl.o LX_OBJS += console.o selection.o endif -ifdef CONFIG_FB - LX_OBJS += fbmem.o -endif ifeq ($(CONFIG_SERIAL),y) - ifndef CONFIG_SUN_SERIAL + ifeq ($(CONFIG_SUN_SERIAL),) LX_OBJS += serial.o endif else ifeq ($(CONFIG_SERIAL),m) - MX_OBJS += serial.o + ifeq ($(CONFIG_SUN_SERIAL),) + MX_OBJS += serial.o + endif endif endif diff -u --recursive --new-file v2.1.123/linux/drivers/char/console.c linux/drivers/char/console.c --- v2.1.123/linux/drivers/char/console.c Mon Sep 28 10:51:33 1998 +++ linux/drivers/char/console.c Thu Oct 1 10:02:21 1998 @@ -130,7 +130,9 @@ static struct termios *console_termios_locked[MAX_NR_CONSOLES]; struct vc vc_cons [MAX_NR_CONSOLES]; +#ifndef VT_SINGLE_DRIVER static struct consw *con_driver_map[MAX_NR_CONSOLES]; +#endif static int con_open(struct tty_struct *, struct file *); static void vc_init(unsigned int console, unsigned int rows, @@ -192,6 +194,12 @@ #define IS_FG (currcons == fg_console) #define IS_VISIBLE CON_IS_VISIBLE(vc_cons[currcons].d) +#ifdef VT_BUF_VRAM_ONLY +#define DO_UPDATE 0 +#else +#define DO_UPDATE IS_VISIBLE +#endif + static inline unsigned short *screenpos(int currcons, int offset, int viewed) { unsigned short *p = (unsigned short *)(visible_origin + offset); @@ -240,6 +248,7 @@ static void do_update_region(int currcons, unsigned long start, int count) { +#ifndef VT_BUF_VRAM_ONLY unsigned int xx, yy, offset; u16 *p; @@ -276,11 +285,12 @@ xx = 0; yy++; } +#endif } void update_region(int currcons, unsigned long start, int count) { - if (IS_VISIBLE) { + if (DO_UPDATE) { hide_cursor(currcons); do_update_region(currcons, start, count); set_cursor(currcons); @@ -294,6 +304,7 @@ if (sw->con_build_attr) return sw->con_build_attr(vc_cons[currcons].d, _color, _intensity, _blink, _underline, _reverse); +#ifndef VT_BUF_VRAM_ONLY /* * ++roman: I completely changed the attribute format for monochrome * mode (!can_do_color). The formerly used MDA (monochrome display @@ -325,6 +336,9 @@ a <<= 1; return a; } +#else + return 0; +#endif } static void update_attr(int currcons) @@ -343,6 +357,7 @@ p = screenpos(currcons, offset, viewed); if (sw->con_invert_region) sw->con_invert_region(vc_cons[currcons].d, p, count); +#ifndef VT_BUF_VRAM_ONLY else { u16 *q = p; int cnt = count; @@ -363,7 +378,8 @@ } } } - if (IS_VISIBLE) +#endif + if (DO_UPDATE) do_update_region(currcons, (unsigned long) p, count); } @@ -376,7 +392,7 @@ if (p) { scr_writew(old, p); - if (IS_VISIBLE) + if (DO_UPDATE) sw->con_putc(vc_cons[currcons].d, old, oldy, oldx); } if (offset == -1) @@ -387,7 +403,7 @@ old = scr_readw(p); new = old ^ complement_mask; scr_writew(new, p); - if (IS_VISIBLE) { + if (DO_UPDATE) { oldx = (offset >> 1) % video_num_columns; oldy = (offset >> 1) / video_num_columns; sw->con_putc(vc_cons[currcons].d, new, oldy, oldx); @@ -404,7 +420,7 @@ scr_writew(scr_readw(p), p + nr); scr_memsetw(q, video_erase_char, nr*2); need_wrap = 0; - if (IS_VISIBLE) { + if (DO_UPDATE) { unsigned short oldattr = attr; sw->con_bmove(vc_cons[currcons].d,y,x,y,x+nr,1, video_num_columns-x-nr); @@ -427,7 +443,7 @@ } scr_memsetw(p, video_erase_char, nr*2); need_wrap = 0; - if (IS_VISIBLE) { + if (DO_UPDATE) { unsigned short oldattr = attr; sw->con_bmove(vc_cons[currcons].d, y, x+nr, y, x, 1, video_num_columns-x-nr); @@ -455,7 +471,7 @@ if ((type & 0x20) && ((softcursor_original & 0x7000) == (i & 0x7000))) i ^= 0x7000; if ((type & 0x40) && ((i & 0x700) == ((i & 0x7000) >> 4))) i ^= 0x0700; scr_writew(i, (u16 *) pos); - if (IS_VISIBLE) + if (DO_UPDATE) sw->con_putc(vc_cons[currcons].d, i, y, x); } @@ -465,7 +481,7 @@ clear_selection(); if (softcursor_original != -1) { scr_writew(softcursor_original,(u16 *) pos); - if (IS_VISIBLE) + if (DO_UPDATE) sw->con_putc(vc_cons[currcons].d, softcursor_original, y, x); softcursor_original = -1; } @@ -572,8 +588,10 @@ { /* ++Geert: sw->con_init determines console size */ sw = conswitchp; +#ifndef VT_SINGLE_DRIVER if (con_driver_map[currcons]) sw = con_driver_map[currcons]; +#endif cons_num = currcons; display_fg = &master_display_fg; vc_cons[currcons].d->vc_uni_pagedir_loc = &vc_cons[currcons].d->vc_uni_pagedir; @@ -887,7 +905,7 @@ case 0: /* erase from cursor to end of display */ count = (scr_end-pos)>>1; start = (unsigned short *) pos; - if (IS_VISIBLE) { + if (DO_UPDATE) { /* do in two stages */ sw->con_clear(vc_cons[currcons].d, y, x, 1, video_num_columns-x); @@ -899,7 +917,7 @@ case 1: /* erase from start to cursor */ count = ((pos-origin)>>1)+1; start = (unsigned short *) origin; - if (IS_VISIBLE) { + if (DO_UPDATE) { /* do in two stages */ sw->con_clear(vc_cons[currcons].d, 0, 0, y, video_num_columns); @@ -910,7 +928,7 @@ case 2: /* erase whole display */ count = video_num_columns * video_num_lines; start = (unsigned short *) origin; - if (IS_VISIBLE) + if (DO_UPDATE) sw->con_clear(vc_cons[currcons].d, 0, 0, video_num_lines, video_num_columns); @@ -931,21 +949,21 @@ case 0: /* erase from cursor to end of line */ count = video_num_columns-x; start = (unsigned short *) pos; - if (IS_VISIBLE) + if (DO_UPDATE) sw->con_clear(vc_cons[currcons].d, y, x, 1, video_num_columns-x); break; case 1: /* erase from start of line to cursor */ start = (unsigned short *) (pos - (x<<1)); count = x+1; - if (IS_VISIBLE) + if (DO_UPDATE) sw->con_clear(vc_cons[currcons].d, y, 0, 1, x + 1); break; case 2: /* erase whole line */ start = (unsigned short *) (pos - (x<<1)); count = video_num_columns; - if (IS_VISIBLE) + if (DO_UPDATE) sw->con_clear(vc_cons[currcons].d, y, 0, 1, video_num_columns); break; @@ -965,7 +983,7 @@ count = (vpar > video_num_columns-x) ? (video_num_columns-x) : vpar; scr_memsetw((unsigned short *) pos, video_erase_char, 2 * count); - if (IS_VISIBLE) + if (DO_UPDATE) sw->con_clear(vc_cons[currcons].d, y, x, 1, count); need_wrap = 0; } @@ -1743,10 +1761,14 @@ static int do_con_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count) { +#ifdef VT_BUF_VRAM_ONLY +#define FLUSH do { } while(0); +#else #define FLUSH if (draw_x >= 0) { \ sw->con_putcs(vc_cons[currcons].d, (u16 *)draw_from, (u16 *)draw_to-(u16 *)draw_from, y, draw_x); \ draw_x = -1; \ } +#endif int c, tc, ok, n = 0, draw_x = -1; unsigned int currcons; @@ -1874,7 +1896,7 @@ ((attr & ~himask) << 8) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) : (attr << 8) + tc, (u16 *) pos); - if (IS_VISIBLE && draw_x < 0) { + if (DO_UPDATE && draw_x < 0) { draw_x = x; draw_from = pos; } @@ -1958,6 +1980,9 @@ goto quit; } + if (vcmode != KD_TEXT) + return; + /* undraw cursor first */ if (IS_FG) hide_cursor(currcons); @@ -2329,6 +2354,8 @@ return kmem_start; } +#ifndef VT_SINGLE_DRIVER + static void clear_buffer_attributes(int currcons) { unsigned short *p = (unsigned short *) origin; @@ -2403,6 +2430,8 @@ con_driver_map[i] = NULL; } +#endif + /* * Screen blanking */ @@ -2766,5 +2795,7 @@ EXPORT_SYMBOL(video_scan_lines); EXPORT_SYMBOL(vc_resize); +#ifndef VT_SINGLE_DRIVER EXPORT_SYMBOL(take_over_console); EXPORT_SYMBOL(give_up_console); +#endif diff -u --recursive --new-file v2.1.123/linux/drivers/char/fbmem.c linux/drivers/char/fbmem.c --- v2.1.123/linux/drivers/char/fbmem.c Wed Aug 26 11:37:36 1998 +++ linux/drivers/char/fbmem.c Wed Dec 31 16:00:00 1969 @@ -1,654 +0,0 @@ -/* - * linux/drivers/char/fbmem.c - * - * Copyright (C) 1994 Martin Schaller - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive - * for more details. - */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_PROC_FS -#include -#endif -#ifdef CONFIG_KMOD -#include -#endif - -#ifdef __mc68000__ -#include -#endif -#ifdef __powerpc__ -#include -#endif -#include -#include -#include - -#include - - - /* - * Frame buffer device initialization and setup routines - */ - -extern unsigned long acornfb_init(void); -extern void acornfb_setup(char *options, int *ints); -extern void amifb_init(void); -extern void amifb_setup(char *options, int *ints); -extern void atafb_init(void); -extern void atafb_setup(char *options, int *ints); -extern void macfb_init(void); -extern void macfb_setup(char *options, int *ints); -extern void cyberfb_init(void); -extern void cyberfb_setup(char *options, int *ints); -extern void retz3fb_init(void); -extern void retz3fb_setup(char *options, int *ints); -extern void clgenfb_init(void); -extern void clgenfb_setup(char *options, int *ints); -extern void vfb_init(void); -extern void vfb_setup(char *options, int *ints); -extern void offb_init(void); -extern void offb_setup(char *options, int *ints); -extern void atyfb_init(void); -extern void atyfb_setup(char *options, int *ints); -extern void dnfb_init(void); -extern void tgafb_init(void); -extern void virgefb_init(void); -extern void virgefb_setup(char *options, int *ints); -extern void resolver_video_setup(char *options, int *ints); -extern void s3triofb_init(void); -extern void s3triofb_setup(char *options, int *ints); -extern void vgafb_init(void); -extern void vgafb_setup(char *options, int *ints); -extern void vesafb_init(void); -extern void vesafb_setup(char *options, int *ints); -extern void mdafb_init(void); -extern void mdafb_setup(char *options, int *ints); -extern void hpfb_init(void); -extern void hpfb_setup(char *options, int *ints); -extern void sbusfb_init(void); -extern void sbusfb_setup(char *options, int *ints); - -static struct { - const char *name; - void (*init)(void); - void (*setup)(char *options, int *ints); -} fb_drivers[] __initdata = { -#ifdef CONFIG_FB_RETINAZ3 - { "retz3", retz3fb_init, retz3fb_setup }, -#endif -#ifdef CONFIG_FB_ACORN - { "acorn", acornfb_init, acornfb_setup }, -#endif -#ifdef CONFIG_FB_AMIGA - { "amifb", amifb_init, amifb_setup }, -#endif -#ifdef CONFIG_FB_ATARI - { "atafb", atafb_init, atafb_setup }, -#endif -#ifdef CONFIG_FB_MAC - { "macfb", macfb_init, macfb_setup }, -#endif -#ifdef CONFIG_FB_CYBER - { "cyber", cyberfb_init, cyberfb_setup }, -#endif -#ifdef CONFIG_FB_CLGEN - { "clgen", clgenfb_init, clgenfb_setup }, -#endif -#ifdef CONFIG_FB_OF - { "offb", offb_init, offb_setup }, -#endif -#ifdef CONFIG_FB_ATY - { "atyfb", atyfb_init, atyfb_setup }, -#endif -#ifdef CONFIG_APOLLO - { "apollo", dnfb_init, NULL }, -#endif -#ifdef CONFIG_FB_S3TRIO - { "s3trio", s3triofb_init, s3triofb_setup }, -#endif -#ifdef CONFIG_FB_TGA - { "tga", tgafb_init, NULL }, -#endif -#ifdef CONFIG_FB_VIRGE - { "virge", virgefb_init, virgefb_setup }, -#endif -#ifdef CONFIG_FB_VGA - { "vga", vgafb_init, vgafb_setup }, -#endif -#ifdef CONFIG_FB_VESA - { "vesa", vesafb_init, vesafb_setup }, -#endif -#ifdef CONFIG_FB_MDA - { "mda", mdafb_init, mdafb_setup }, -#endif -#ifdef CONFIG_FB_HP300 - { "hpfb", hpfb_init, hpfb_setup }, -#endif -#ifdef CONFIG_FB_SBUS - { "sbus", sbusfb_init, sbusfb_setup }, -#endif -#ifdef CONFIG_GSP_RESOLVER - /* Not a real frame buffer device... */ - { "resolver", NULL, resolver_video_setup }, -#endif -#ifdef CONFIG_FB_VIRTUAL - /* Must be last to avoid that vfb becomes your primary display */ - { "vfb", vfb_init, vfb_setup }, -#endif -}; - -#define NUM_FB_DRIVERS (sizeof(fb_drivers)/sizeof(*fb_drivers)) - -static void (*pref_init_funcs[FB_MAX])(void); -static int num_pref_init_funcs __initdata = 0; - - -#define GET_INODE(i) MKDEV(FB_MAJOR, (i) << FB_MODES_SHIFT) -#define GET_FB_VAR_IDX(node) (MINOR(node) & ((1 << FB_MODES_SHIFT)-1)) - -struct fb_info *registered_fb[FB_MAX]; -int num_registered_fb = 0; - -char con2fb_map[MAX_NR_CONSOLES]; - -static inline int PROC_CONSOLE(void) -{ - if (!current->tty) - return fg_console; - - if (current->tty->driver.type != TTY_DRIVER_TYPE_CONSOLE) - /* XXX Should report error here? */ - return fg_console; - - if (MINOR(current->tty->device) < 1) - return fg_console; - - return MINOR(current->tty->device) - 1; -} - -#ifdef CONFIG_PROC_FS -static int fbmem_read_proc(char *buf, char **start, off_t offset, - int len, int *eof, void *private) -{ - struct fb_info **fi; - - len = 0; - for (fi = registered_fb; fi < ®istered_fb[FB_MAX] && len < 4000; fi++) - if (*fi) - len += sprintf(buf + len, "%d %s\n", - GET_FB_IDX((*fi)->node), - (*fi)->modename); - *start = buf + offset; - return len > offset ? len - offset : 0; -} -#endif - -static ssize_t -fb_read(struct file *file, char *buf, size_t count, loff_t *ppos) -{ - unsigned long p = *ppos; - struct inode *inode = file->f_dentry->d_inode; - int fbidx = GET_FB_IDX(inode->i_rdev); - struct fb_info *info = registered_fb[fbidx]; - struct fb_ops *fb = info->fbops; - struct fb_fix_screeninfo fix; - char *base_addr; - ssize_t copy_size; - - if (! fb || ! info->disp) - return -ENODEV; - - fb->fb_get_fix(&fix,PROC_CONSOLE(), info); - base_addr=info->disp->screen_base; - copy_size=(count + p <= fix.smem_len ? count : fix.smem_len - p); - if (copy_to_user(buf, base_addr+p, copy_size)) - return -EFAULT; - *ppos += copy_size; - return copy_size; -} - -static ssize_t -fb_write(struct file *file, const char *buf, size_t count, loff_t *ppos) -{ - unsigned long p = *ppos; - struct inode *inode = file->f_dentry->d_inode; - int fbidx = GET_FB_IDX(inode->i_rdev); - struct fb_info *info = registered_fb[fbidx]; - struct fb_ops *fb = info->fbops; - struct fb_fix_screeninfo fix; - char *base_addr; - ssize_t copy_size; - - if (! fb || ! info->disp) - return -ENODEV; - - fb->fb_get_fix(&fix, PROC_CONSOLE(), info); - base_addr=info->disp->screen_base; - copy_size=(count + p <= fix.smem_len ? count : fix.smem_len - p); - if (copy_from_user(base_addr+p, buf, copy_size)) - return -EFAULT; - file->f_pos += copy_size; - return copy_size; -} - - -static void set_con2fb_map(int unit, int newidx) -{ - int oldidx = con2fb_map[unit]; - struct fb_info *oldfb, *newfb; - struct vc_data *conp; - - if (newidx != con2fb_map[unit]) { - oldfb = registered_fb[oldidx]; - newfb = registered_fb[newidx]; - if (newfb->fbops->fb_open(newfb,0)) - return; - oldfb->fbops->fb_release(oldfb,0); - conp = fb_display[unit].conp; - con2fb_map[unit] = newidx; - fb_display[unit] = *(newfb->disp); - fb_display[unit].conp = conp; - fb_display[unit].fb_info = newfb; - if (!newfb->changevar) - newfb->changevar = oldfb->changevar; - /* tell console var has changed */ - if (newfb->changevar) - newfb->changevar(unit); - } -} - -#ifdef CONFIG_KMOD -static void try_to_load(int fb) -{ - char modname[16]; - - sprintf(modname, "fb%d", fb); - request_module(modname); -} -#endif /* CONFIG_KMOD */ - -static int -fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) -{ - int fbidx = GET_FB_IDX(inode->i_rdev); - struct fb_info *info = registered_fb[fbidx]; - struct fb_ops *fb = info->fbops; - struct fb_cmap cmap; - struct fb_var_screeninfo var; - struct fb_fix_screeninfo fix; - struct fb_con2fbmap con2fb; - int i; - - if (! fb) - return -ENODEV; - switch (cmd) { - case FBIOGET_VSCREENINFO: - if ((i = fb->fb_get_var(&var, PROC_CONSOLE(), info))) - return i; - return copy_to_user((void *) arg, &var, - sizeof(var)) ? -EFAULT : 0; - case FBIOPUT_VSCREENINFO: - if (copy_from_user(&var, (void *) arg, sizeof(var))) - return -EFAULT; - if ((i = fb->fb_set_var(&var, PROC_CONSOLE(), info))) - return i; - if (copy_to_user((void *) arg, &var, sizeof(var))) - return -EFAULT; - return 0; - case FBIOGET_FSCREENINFO: - if ((i = fb->fb_get_fix(&fix, PROC_CONSOLE(), info))) - return i; - return copy_to_user((void *) arg, &fix, sizeof(fix)) ? - -EFAULT : 0; - case FBIOPUTCMAP: - if (copy_from_user(&cmap, (void *) arg, sizeof(cmap))) - return -EFAULT; - return (fb->fb_set_cmap(&cmap, 0, PROC_CONSOLE(), info)); - case FBIOGETCMAP: - if (copy_from_user(&cmap, (void *) arg, sizeof(cmap))) - return -EFAULT; - return (fb->fb_get_cmap(&cmap, 0, PROC_CONSOLE(), info)); - case FBIOPAN_DISPLAY: - if (copy_from_user(&var, (void *) arg, sizeof(var))) - return -EFAULT; - if ((i=fb->fb_pan_display(&var, PROC_CONSOLE(), info))) - return i; - if (copy_to_user((void *) arg, &var, sizeof(var))) - return -EFAULT; - return i; - case FBIOGET_CON2FBMAP: - if (copy_from_user(&con2fb, (void *)arg, sizeof(con2fb))) - return -EFAULT; - if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) - return -EINVAL; - con2fb.framebuffer = con2fb_map[con2fb.console-1]; - return copy_to_user((void *)arg, &con2fb, - sizeof(con2fb)) ? -EFAULT : 0; - case FBIOPUT_CON2FBMAP: - if (copy_from_user(&con2fb, (void *)arg, sizeof(con2fb))) - return - EFAULT; - if (con2fb.console < 0 || con2fb.console > MAX_NR_CONSOLES) - return -EINVAL; - if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX) - return -EINVAL; -#ifdef CONFIG_KMOD - if (!registered_fb[con2fb.framebuffer]) - try_to_load(con2fb.framebuffer); -#endif /* CONFIG_KMOD */ - if (!registered_fb[con2fb.framebuffer]) - return -EINVAL; - if (con2fb.console != 0) - set_con2fb_map(con2fb.console-1, con2fb.framebuffer); - else - /* set them all */ - for (i = 0; i < MAX_NR_CONSOLES; i++) - set_con2fb_map(i, con2fb.framebuffer); - return 0; - default: - return fb->fb_ioctl(inode, file, cmd, arg, PROC_CONSOLE(), - info); - } -} - -static int -fb_mmap(struct file *file, struct vm_area_struct * vma) -{ - int fbidx = GET_FB_IDX(file->f_dentry->d_inode->i_rdev); - struct fb_info *info = registered_fb[fbidx]; - struct fb_ops *fb = info->fbops; - struct fb_fix_screeninfo fix; - struct fb_var_screeninfo var; - unsigned long start; - u32 len; - - if (!fb) - return -ENODEV; - if (fb->fb_mmap) - return fb->fb_mmap(info, file, vma); - fb->fb_get_fix(&fix, PROC_CONSOLE(), info); - - /* frame buffer memory */ - start = (unsigned long)fix.smem_start; - len = (start & ~PAGE_MASK)+fix.smem_len; - start &= PAGE_MASK; - len = (len+~PAGE_MASK) & PAGE_MASK; - if (vma->vm_offset >= len) { - /* memory mapped io */ - vma->vm_offset -= len; - fb->fb_get_var(&var, PROC_CONSOLE(), info); - if (var.accel_flags) - return -EINVAL; - start = (unsigned long)fix.mmio_start; - len = (start & ~PAGE_MASK)+fix.mmio_len; - start &= PAGE_MASK; - len = (len+~PAGE_MASK) & PAGE_MASK; - } - if ((vma->vm_end - vma->vm_start + vma->vm_offset) > len) - return -EINVAL; - vma->vm_offset += start; - if (vma->vm_offset & ~PAGE_MASK) - return -ENXIO; -#if defined(__mc68000__) - if (CPU_IS_020_OR_030) - pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE030; - if (CPU_IS_040_OR_060) { - pgprot_val(vma->vm_page_prot) &= _CACHEMASK040; - /* Use no-cache mode, serialized */ - pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE_S; - } -#elif defined(__powerpc__) - pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE|_PAGE_GUARDED; -#elif defined(__alpha__) - /* Caching is off in the I/O space quadrant by design. */ -#elif defined(__sparc__) - /* Should never get here, all fb drivers should have their own - mmap routines */ -#elif defined(__i386__) - if (boot_cpu_data.x86 > 3) - pgprot_val(vma->vm_page_prot) |= _PAGE_PCD; -#else -#warning What do we have to do here?? -#endif - if (remap_page_range(vma->vm_start, vma->vm_offset, - vma->vm_end - vma->vm_start, vma->vm_page_prot)) - return -EAGAIN; - vma->vm_file = file; - file->f_count++; - return 0; -} - -static int -fb_open(struct inode *inode, struct file *file) -{ - int fbidx = GET_FB_IDX(inode->i_rdev); - struct fb_info *info; - -#ifdef CONFIG_KMOD - if (!(info = registered_fb[fbidx])) - try_to_load(fbidx); -#endif /* CONFIG_KMOD */ - if (!(info = registered_fb[fbidx])) - return -ENODEV; - return info->fbops->fb_open(info,1); -} - -static int -fb_release(struct inode *inode, struct file *file) -{ - int fbidx = GET_FB_IDX(inode->i_rdev); - struct fb_info *info = registered_fb[fbidx]; - - info->fbops->fb_release(info,1); - return 0; -} - -static struct file_operations fb_fops = { - NULL, /* lseek */ - fb_read, /* read */ - fb_write, /* write */ - NULL, /* readdir */ - NULL, /* poll */ - fb_ioctl, /* ioctl */ - fb_mmap, /* mmap */ - fb_open, /* open */ - NULL, /* flush */ - fb_release, /* release */ - NULL /* fsync */ -}; - -int -register_framebuffer(struct fb_info *fb_info) -{ - int i, j; - static int fb_ever_opened[FB_MAX]; - static int first = 1; - - if (num_registered_fb == FB_MAX) - return -ENXIO; - num_registered_fb++; - for (i = 0 ; i < FB_MAX; i++) - if (!registered_fb[i]) - break; - fb_info->node=GET_INODE(i); - registered_fb[i] = fb_info; - if (!fb_ever_opened[i]) { - /* - * We assume initial frame buffer devices can be opened this - * many times - */ - for (j = 0; j < MAX_NR_CONSOLES; j++) - if (con2fb_map[j] == i) - fb_info->fbops->fb_open(fb_info,0); - fb_ever_opened[i] = 1; - } - - if (first) { - first = 0; - take_over_console(&fb_con, 0, MAX_NR_CONSOLES-1, 1); - } - - return 0; -} - -int -unregister_framebuffer(const struct fb_info *fb_info) -{ - int i, j; - - i = GET_FB_IDX(fb_info->node); - for (j = 0; j < MAX_NR_CONSOLES; j++) - if (con2fb_map[j] == i) - return -EBUSY; - if (!registered_fb[i]) - return -EINVAL; - registered_fb[i]=NULL; - num_registered_fb--; - return 0; -} - -#ifdef CONFIG_PROC_FS -static struct proc_dir_entry *proc_fbmem; -#endif - -__initfunc(void -fbmem_init(void)) -{ - int i; - -#ifdef CONFIG_PROC_FS - proc_fbmem = create_proc_entry("fb", 0, 0); - if (proc_fbmem) - proc_fbmem->read_proc = fbmem_read_proc; -#endif - - if (register_chrdev(FB_MAJOR,"fb",&fb_fops)) - printk("unable to get major %d for fb devs\n", FB_MAJOR); - - /* - * Probe for all builtin frame buffer devices - */ - for (i = 0; i < num_pref_init_funcs; i++) - pref_init_funcs[i](); - - for (i = 0; i < NUM_FB_DRIVERS; i++) - if (fb_drivers[i].init) - fb_drivers[i].init(); -} - - -int fbmon_valid_timings(u_int pixclock, u_int htotal, u_int vtotal, - const struct fb_info *fb_info) -{ -#if 0 - /* - * long long divisions .... $#%%#$ - */ - unsigned long long hpicos, vpicos; - const unsigned long long _1e12 = 1000000000000ULL; - const struct fb_monspecs *monspecs = &fb_info->monspecs; - - hpicos = (unsigned long long)htotal*(unsigned long long)pixclock; - vpicos = (unsigned long long)vtotal*(unsigned long long)hpicos; - if (!vpicos) - return 0; - - if (monspecs->hfmin == 0) - return 1; - - if (hpicos*monspecs->hfmin > _1e12 || hpicos*monspecs->hfmax < _1e12 || - vpicos*monspecs->vfmin > _1e12 || vpicos*monspecs->vfmax < _1e12) - return 0; -#endif - return 1; -} - -int fbmon_dpms(const struct fb_info *fb_info) -{ - return fb_info->monspecs.dpms; -} - - - /* - * Command line options - */ - -__initfunc(void video_setup(char *options, int *ints)) -{ - int i, j; - - if (!options || !*options) - return; - - if (!strncmp(options, "map:", 4)) { - options += 4; - if (*options) - for (i = 0, j = 0; i < MAX_NR_CONSOLES; i++) { - if (!options[j]) - j = 0; - con2fb_map[i] = (options[j++]-'0') % FB_MAX; - } - return; - } - - if (num_pref_init_funcs == FB_MAX) - return; - - for (i = 0; i < NUM_FB_DRIVERS; i++) { - j = strlen(fb_drivers[i].name); - if (!strncmp(options, fb_drivers[i].name, j) && - options[j] == ':') { - if (!strcmp(options+j+1, "off")) - fb_drivers[i].init = NULL; - else { - if (fb_drivers[i].init) { - pref_init_funcs[num_pref_init_funcs++] = - fb_drivers[i].init; - fb_drivers[i].init = NULL; - } - if (fb_drivers[i].setup) - fb_drivers[i].setup(options+j+1, ints); - } - return; - } - } - /* - * If we get here no fb was specified and we default to pass the - * options to the first frame buffer that has an init and a setup - * function. - */ - for (i = 0; i < NUM_FB_DRIVERS; i++) { - if (fb_drivers[i].init && fb_drivers[i].setup) { - pref_init_funcs[num_pref_init_funcs++] = - fb_drivers[i].init; - fb_drivers[i].init = NULL; - - fb_drivers[i].setup(options, ints); - return; - } - } -} - - - /* - * Visible symbols for modules - */ - -EXPORT_SYMBOL(register_framebuffer); -EXPORT_SYMBOL(unregister_framebuffer); diff -u --recursive --new-file v2.1.123/linux/drivers/char/mem.c linux/drivers/char/mem.c --- v2.1.123/linux/drivers/char/mem.c Mon Sep 28 10:51:33 1998 +++ linux/drivers/char/mem.c Thu Oct 1 10:03:16 1998 @@ -44,6 +44,12 @@ #ifdef CONFIG_FB extern void fbmem_init(void); #endif +#ifdef CONFIG_PROM_CONSOLE +extern void prom_con_init(void); +#endif +#ifdef CONFIG_MDA_CONSOLE +extern void mda_console_init(void); +#endif static ssize_t do_write_mem(struct file * file, void *p, unsigned long realp, const char * buf, size_t count, loff_t *ppos) @@ -544,6 +550,12 @@ rand_initialize(); #if defined (CONFIG_FB) fbmem_init(); +#endif +#if defined (CONFIG_PROM_CONSOLE) + prom_con_init(); +#endif +#if defined (CONFIG_MDA_CONSOLE) + mda_console_init(); #endif tty_init(); #ifdef CONFIG_PRINTER diff -u --recursive --new-file v2.1.123/linux/drivers/char/pty.c linux/drivers/char/pty.c --- v2.1.123/linux/drivers/char/pty.c Tue Aug 18 22:02:03 1998 +++ linux/drivers/char/pty.c Mon Sep 28 11:07:45 1998 @@ -336,7 +336,9 @@ __initfunc(int pty_init(void)) { +#ifdef CONFIG_UNIX98_PTYS int i; +#endif /* Traditional BSD devices */ diff -u --recursive --new-file v2.1.123/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c --- v2.1.123/linux/drivers/char/tty_io.c Mon Sep 28 10:51:33 1998 +++ linux/drivers/char/tty_io.c Mon Sep 28 11:07:45 1998 @@ -1276,8 +1276,10 @@ if (retval) return retval; +#ifdef CONFIG_UNIX98_PTYS /* N.B. this error exit may leave filp->f_flags with O_NONBLOCK set */ init_dev_done: +#endif filp->private_data = tty; check_tty_count(tty, "tty_open"); if (tty->driver.type == TTY_DRIVER_TYPE_PTY && diff -u --recursive --new-file v2.1.123/linux/drivers/isdn/isdn_net.c linux/drivers/isdn/isdn_net.c --- v2.1.123/linux/drivers/isdn/isdn_net.c Wed May 20 19:10:39 1998 +++ linux/drivers/isdn/isdn_net.c Tue Sep 29 21:30:05 1998 @@ -1042,12 +1042,14 @@ if (ret == len) { lp->transcount += len; clear_bit(0, (void *) &(ndev->tbusy)); + mark_bh(NET_BH); return 0; } if (ret < 0) { dev_kfree_skb(skb); lp->stats.tx_errors++; clear_bit(0, (void *) &(ndev->tbusy)); + mark_bh(NET_BH); return 0; } return 1; diff -u --recursive --new-file v2.1.123/linux/drivers/net/8390.h linux/drivers/net/8390.h --- v2.1.123/linux/drivers/net/8390.h Thu Jul 16 18:09:25 1998 +++ linux/drivers/net/8390.h Sun Oct 4 10:21:00 1998 @@ -178,6 +178,7 @@ /* The new statistics table. */ struct net_device_stats stat; unsigned char *reg_offset; /* Register mapping table */ + unsigned long priv; /* Private field to store bus IDs etc. */ }; /* The maximum number of 8390 interrupt service routines called per IRQ. */ @@ -207,11 +208,11 @@ #define E8390_PAGE1 0x40 /* using the two high-order bits */ #define E8390_PAGE2 0x80 /* Page 3 is invalid. */ - -#ifndef CONFIG_MAC -#define EI_SHIFT(x) (x) -#else +#if defined(CONFIG_MAC) || defined(CONFIG_AMIGA_PCMCIA) || \ + defined(CONFIG_ARIADNE2) || defined(CONFIG_ARIADNE2_MODULE) #define EI_SHIFT(x) (ei_local->reg_offset[x]) +#else +#define EI_SHIFT(x) (x) #endif #define E8390_CMD EI_SHIFT(0x00) /* The command register (for all pages) */ diff -u --recursive --new-file v2.1.123/linux/drivers/net/Config.in linux/drivers/net/Config.in --- v2.1.123/linux/drivers/net/Config.in Thu Sep 17 17:53:36 1998 +++ linux/drivers/net/Config.in Sun Oct 4 10:21:00 1998 @@ -37,6 +37,7 @@ fi if [ "$CONFIG_ZORRO" = "y" ]; then tristate 'Ariadne support' CONFIG_ARIADNE + tristate 'Ariadne II support' CONFIG_ARIADNE2 tristate 'A2065 support' CONFIG_A2065 tristate 'Hydra support' CONFIG_HYDRA fi diff -u --recursive --new-file v2.1.123/linux/drivers/net/Makefile linux/drivers/net/Makefile --- v2.1.123/linux/drivers/net/Makefile Wed Sep 9 14:51:08 1998 +++ linux/drivers/net/Makefile Sun Oct 4 10:21:00 1998 @@ -752,6 +752,16 @@ endif endif +ifeq ($(CONFIG_ARIADNE2),y) +L_OBJS += ariadne2.o +CONFIG_8390_BUILTIN = y +else + ifeq ($(CONFIG_ARIADNE2),m) + M_OBJS += ariadne2.o + CONFIG_8390_MODULE = y + endif +endif + # If anything built-in uses the 8390, then build it into the kernel also. # If not, but a module uses it, build as a module. ifdef CONFIG_8390_BUILTIN diff -u --recursive --new-file v2.1.123/linux/drivers/net/Space.c linux/drivers/net/Space.c --- v2.1.123/linux/drivers/net/Space.c Mon Aug 3 12:45:45 1998 +++ linux/drivers/net/Space.c Sun Oct 4 10:21:00 1998 @@ -90,6 +90,7 @@ extern int atarilance_probe(struct device *); extern int a2065_probe(struct device *); extern int ariadne_probe(struct device *); +extern int ariadne2_probe(struct device *); extern int hydra_probe(struct device *); extern int apne_probe(struct device *); extern int bionet_probe(struct device *); @@ -363,6 +364,9 @@ #endif #ifdef CONFIG_ARIADNE /* Village Tronic Ariadne Ethernet Board */ {ariadne_probe, 0}, +#endif +#ifdef CONFIG_ARIADNE2 /* Village Tronic Ariadne II Ethernet Board */ + {ariadne2_probe, 0}, #endif #ifdef CONFIG_HYDRA /* Hydra Systems Amiganet Ethernet board */ {hydra_probe, 0}, diff -u --recursive --new-file v2.1.123/linux/drivers/net/a2065.c linux/drivers/net/a2065.c --- v2.1.123/linux/drivers/net/a2065.c Thu Feb 12 20:56:07 1998 +++ linux/drivers/net/a2065.c Sun Oct 4 10:21:00 1998 @@ -570,6 +570,7 @@ int entry, skblen, len; int status = 0; static int outs; + unsigned long flags; /* Transmitter timeout, serious problems */ if (dev->tbusy) { @@ -586,18 +587,20 @@ } /* Block a timer-based transmit from overlapping. */ -#ifdef OLD_METHOD - dev->tbusy = 1; -#else if (test_and_set_bit (0, (void *) &dev->tbusy) != 0) { printk ("Transmitter access conflict.\n"); return -1; } -#endif + skblen = skb->len; - if (!TX_BUFFS_AVAIL) + save_flags(flags); + cli(); + + if (!TX_BUFFS_AVAIL){ + restore_flags(flags); return -1; + } #ifdef DEBUG_DRIVER /* dump the packet */ @@ -634,6 +637,7 @@ if (TX_BUFFS_AVAIL) dev->tbusy = 0; + restore_flags(flags); return status; } diff -u --recursive --new-file v2.1.123/linux/drivers/net/apne.c linux/drivers/net/apne.c --- v2.1.123/linux/drivers/net/apne.c Mon Aug 3 17:48:27 1998 +++ linux/drivers/net/apne.c Sun Oct 4 10:21:00 1998 @@ -577,13 +577,13 @@ void cleanup_module(void) { - unregister_netdev(&apne_dev); - pcmcia_disable_irq(); free_irq(IRQ_AMIGA_PORTS, &apne_dev); pcmcia_reset(); + + unregister_netdev(&apne_dev); unlock_8390_module(); } diff -u --recursive --new-file v2.1.123/linux/drivers/net/ariadne2.c linux/drivers/net/ariadne2.c --- v2.1.123/linux/drivers/net/ariadne2.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/ariadne2.c Sun Oct 4 10:21:00 1998 @@ -0,0 +1,424 @@ +/* + * Amiga Linux/m68k Ariadne II Ethernet Driver + * + * (C) Copyright 1998 by some Elitist 680x0 Users(TM) + * + * --------------------------------------------------------------------------- + * + * This program is based on all the other NE2000 drivers for Linux + * + * --------------------------------------------------------------------------- + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of the Linux + * distribution for more details. + * + * --------------------------------------------------------------------------- + * + * The Ariadne II is a Zorro-II board made by Village Tronic. It contains a + * Realtek RTL8019AS Ethernet Controller. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "8390.h" + + +#define ARIADNE2_BASE 0x0300 +#define ARIADNE2_BOOTROM 0xc000 + + +#define NE_BASE (dev->base_addr) +#define NE_CMD (0x00*2) +#define NE_DATAPORT (0x10*2) /* NatSemi-defined port window offset. */ +#define NE_RESET (0x1f*2) /* Issue a read to reset, a write to clear. */ +#define NE_IO_EXTENT (0x20*2) + +#define NE_EN0_ISR (0x07*2) +#define NE_EN0_DCFG (0x0e*2) + +#define NE_EN0_RSARLO (0x08*2) +#define NE_EN0_RSARHI (0x09*2) +#define NE_EN0_RCNTLO (0x0a*2) +#define NE_EN0_RXCR (0x0c*2) +#define NE_EN0_TXCR (0x0d*2) +#define NE_EN0_RCNTHI (0x0b*2) +#define NE_EN0_IMR (0x0f*2) + +#define NESM_START_PG 0x40 /* First page of TX buffer */ +#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */ + + +#define WORDSWAP(a) ((((a)>>8)&0xff) | ((a)<<8)) + +int ariadne2_probe(struct device *dev); +static int ariadne2_init(struct device *dev, unsigned int key, + unsigned long board); + +static int ariadne2_open(struct device *dev); +static int ariadne2_close(struct device *dev); + +static void ariadne2_reset_8390(struct device *dev); +static void ariadne2_get_8390_hdr(struct device *dev, + struct e8390_pkt_hdr *hdr, int ring_page); +static void ariadne2_block_input(struct device *dev, int count, + struct sk_buff *skb, int ring_offset); +static void ariadne2_block_output(struct device *dev, const int count, + const unsigned char *buf, + const int start_page); + + +__initfunc(int ariadne2_probe(struct device *dev)) +{ + unsigned int key; + const struct ConfigDev *cd; + u_long board; + int err; + + if ((key = zorro_find(ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, 0, 0))) { + cd = zorro_get_board(key); + if ((board = (u_long)cd->cd_BoardAddr)) { + if ((err = ariadne2_init(dev, key, ZTWO_VADDR(board)))) + return err; + zorro_config_board(key, 0); + return 0; + } + } + return ENODEV; +} + +__initfunc(static int ariadne2_init(struct device *dev, unsigned int key, + unsigned long board)) +{ + int i; + unsigned char SA_prom[32]; + const char *name = NULL; + int start_page, stop_page; + static int ariadne2_offsets[16] = { + 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, + 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, + }; + int ioaddr = board+ARIADNE2_BASE*2; + + if (load_8390_module("ariadne2.c")) + return -ENOSYS; + + /* We should have a "dev" from Space.c or the static module table. */ + if (dev == NULL) { + printk(KERN_ERR "ariadne2.c: Passed a NULL device.\n"); + dev = init_etherdev(0, 0); + } + + /* Reset card. Who knows what dain-bramaged state it was left in. */ + { + unsigned long reset_start_time = jiffies; + + writeb(readb(ioaddr + NE_RESET), ioaddr + NE_RESET); + + while ((readb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0) + if (jiffies - reset_start_time > 2*HZ/100) { + printk(" not found (no reset ack).\n"); + return ENODEV; + } + + writeb(0xff, ioaddr + NE_EN0_ISR); /* Ack all intr. */ + } + + /* Read the 16 bytes of station address PROM. + We must first initialize registers, similar to NS8390_init(eifdev, 0). + We can't reliably read the SAPROM address without this. + (I learned the hard way!). */ + { + struct { + u32 value; + u32 offset; + } program_seq[] = { + {E8390_NODMA+E8390_PAGE0+E8390_STOP, NE_CMD}, /* Select page 0*/ + {0x48, NE_EN0_DCFG}, /* Set byte-wide (0x48) access. */ + {0x00, NE_EN0_RCNTLO}, /* Clear the count regs. */ + {0x00, NE_EN0_RCNTHI}, + {0x00, NE_EN0_IMR}, /* Mask completion irq. */ + {0xFF, NE_EN0_ISR}, + {E8390_RXOFF, NE_EN0_RXCR}, /* 0x20 Set to monitor */ + {E8390_TXOFF, NE_EN0_TXCR}, /* 0x02 and loopback mode. */ + {32, NE_EN0_RCNTLO}, + {0x00, NE_EN0_RCNTHI}, + {0x00, NE_EN0_RSARLO}, /* DMA starting at 0x0000. */ + {0x00, NE_EN0_RSARHI}, + {E8390_RREAD+E8390_START, NE_CMD}, + }; + for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++) { + writeb(program_seq[i].value, ioaddr + program_seq[i].offset); + } + } + for (i = 0; i < 16; i++) { + SA_prom[i] = readb(ioaddr + NE_DATAPORT); + (void)readb(ioaddr + NE_DATAPORT); + } + + /* We must set the 8390 for word mode. */ + writeb(0x49, ioaddr + NE_EN0_DCFG); + start_page = NESM_START_PG; + stop_page = NESM_STOP_PG; + + name = "NE2000"; + + dev->base_addr = ioaddr; + + /* Install the Interrupt handler */ + if (request_irq(IRQ_AMIGA_PORTS, ei_interrupt, 0, "AriadNE2 Ethernet", + dev)) + return -EAGAIN; + + /* Allocate dev->priv and fill in 8390 specific dev fields. */ + if (ethdev_init(dev)) { + printk("Unable to get memory for dev->priv.\n"); + return -ENOMEM; + } + ((struct ei_device *)dev->priv)->priv = key; + + for(i = 0; i < ETHER_ADDR_LEN; i++) { + printk(" %2.2x", SA_prom[i]); + dev->dev_addr[i] = SA_prom[i]; + } + + printk("%s: AriadNE2 at 0x%08lx, Ethernet Address " + "%02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, board, + dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], + dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); + + ei_status.name = name; + ei_status.tx_start_page = start_page; + ei_status.stop_page = stop_page; + ei_status.word16 = 1; + + ei_status.rx_start_page = start_page + TX_PAGES; + + ei_status.reset_8390 = &ariadne2_reset_8390; + ei_status.block_input = &ariadne2_block_input; + ei_status.block_output = &ariadne2_block_output; + ei_status.get_8390_hdr = &ariadne2_get_8390_hdr; + ei_status.reg_offset = ariadne2_offsets; + dev->open = &ariadne2_open; + dev->stop = &ariadne2_close; + NS8390_init(dev, 0); + return 0; +} + +static int ariadne2_open(struct device *dev) +{ + ei_open(dev); + MOD_INC_USE_COUNT; + return 0; +} + +static int ariadne2_close(struct device *dev) +{ + if (ei_debug > 1) + printk("%s: Shutting down ethercard.\n", dev->name); + ei_close(dev); + MOD_DEC_USE_COUNT; + return 0; +} + +/* Hard reset the card. This used to pause for the same period that a + 8390 reset command required, but that shouldn't be necessary. */ +static void ariadne2_reset_8390(struct device *dev) +{ + unsigned long reset_start_time = jiffies; + + if (ei_debug > 1) + printk("resetting the 8390 t=%ld...", jiffies); + + writeb(readb(NE_BASE + NE_RESET), NE_BASE + NE_RESET); + + ei_status.txing = 0; + ei_status.dmaing = 0; + + /* This check _should_not_ be necessary, omit eventually. */ + while ((readb(NE_BASE+NE_EN0_ISR) & ENISR_RESET) == 0) + if (jiffies - reset_start_time > 2*HZ/100) { + printk("%s: ne_reset_8390() did not complete.\n", dev->name); + break; + } + writeb(ENISR_RESET, NE_BASE + NE_EN0_ISR); /* Ack intr. */ +} + +/* Grab the 8390 specific header. Similar to the block_input routine, but + we don't need to be concerned with ring wrap as the header will be at + the start of a page, so we optimize accordingly. */ + +static void ariadne2_get_8390_hdr(struct device *dev, + struct e8390_pkt_hdr *hdr, int ring_page) +{ + int nic_base = dev->base_addr; + int cnt; + short *ptrs; + + /* This *shouldn't* happen. If it does, it's the last thing you'll see */ + if (ei_status.dmaing) { + printk("%s: DMAing conflict in ne_get_8390_hdr " + "[DMAstat:%d][irqlock:%d][intr:%ld].\n", dev->name, ei_status.dmaing, + ei_status.irqlock, dev->interrupt); + return; + } + + ei_status.dmaing |= 0x01; + writeb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD); + writeb(ENISR_RDC, nic_base + NE_EN0_ISR); + writeb(sizeof(struct e8390_pkt_hdr), nic_base + NE_EN0_RCNTLO); + writeb(0, nic_base + NE_EN0_RCNTHI); + writeb(0, nic_base + NE_EN0_RSARLO); /* On page boundary */ + writeb(ring_page, nic_base + NE_EN0_RSARHI); + writeb(E8390_RREAD+E8390_START, nic_base + NE_CMD); + + ptrs = (short*)hdr; + for (cnt = 0; cnt < (sizeof(struct e8390_pkt_hdr)>>1); cnt++) + *ptrs++ = readw(NE_BASE + NE_DATAPORT); + + writeb(ENISR_RDC, nic_base + NE_EN0_ISR); /* Ack intr. */ + + hdr->count = WORDSWAP(hdr->count); + + ei_status.dmaing &= ~0x01; +} + +/* Block input and output, similar to the Crynwr packet driver. If you + are porting to a new ethercard, look at the packet driver source for hints. + The NEx000 doesn't share the on-board packet memory -- you have to put + the packet out through the "remote DMA" dataport using writeb. */ + +static void ariadne2_block_input(struct device *dev, int count, + struct sk_buff *skb, int ring_offset) +{ + int nic_base = dev->base_addr; + char *buf = skb->data; + short *ptrs; + int cnt; + + /* This *shouldn't* happen. If it does, it's the last thing you'll see */ + if (ei_status.dmaing) { + printk("%s: DMAing conflict in ne_block_input " + "[DMAstat:%d][irqlock:%d][intr:%ld].\n", + dev->name, ei_status.dmaing, ei_status.irqlock, + dev->interrupt); + return; + } + ei_status.dmaing |= 0x01; + writeb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD); + writeb(ENISR_RDC, nic_base + NE_EN0_ISR); + writeb(count & 0xff, nic_base + NE_EN0_RCNTLO); + writeb(count >> 8, nic_base + NE_EN0_RCNTHI); + writeb(ring_offset & 0xff, nic_base + NE_EN0_RSARLO); + writeb(ring_offset >> 8, nic_base + NE_EN0_RSARHI); + writeb(E8390_RREAD+E8390_START, nic_base + NE_CMD); + ptrs = (short*)buf; + for (cnt = 0; cnt < (count>>1); cnt++) + *ptrs++ = readw(NE_BASE + NE_DATAPORT); + if (count & 0x01) + buf[count-1] = readb(NE_BASE + NE_DATAPORT); + + writeb(ENISR_RDC, nic_base + NE_EN0_ISR); /* Ack intr. */ + ei_status.dmaing &= ~0x01; +} + +static void ariadne2_block_output(struct device *dev, int count, + const unsigned char *buf, + const int start_page) +{ + int nic_base = NE_BASE; + unsigned long dma_start; + short *ptrs; + int cnt; + + /* Round the count up for word writes. Do we need to do this? + What effect will an odd byte count have on the 8390? + I should check someday. */ + if (count & 0x01) + count++; + + /* This *shouldn't* happen. If it does, it's the last thing you'll see */ + if (ei_status.dmaing) { + printk("%s: DMAing conflict in ne_block_output." + "[DMAstat:%d][irqlock:%d][intr:%ld]\n", dev->name, ei_status.dmaing, + ei_status.irqlock, dev->interrupt); + return; + } + ei_status.dmaing |= 0x01; + /* We should already be in page 0, but to be safe... */ + writeb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD); + + writeb(ENISR_RDC, nic_base + NE_EN0_ISR); + + /* Now the normal output. */ + writeb(count & 0xff, nic_base + NE_EN0_RCNTLO); + writeb(count >> 8, nic_base + NE_EN0_RCNTHI); + writeb(0x00, nic_base + NE_EN0_RSARLO); + writeb(start_page, nic_base + NE_EN0_RSARHI); + + writeb(E8390_RWRITE+E8390_START, nic_base + NE_CMD); + ptrs = (short*)buf; + for (cnt = 0; cnt < count>>1; cnt++) + writew(*ptrs++, NE_BASE+NE_DATAPORT); + + dma_start = jiffies; + + while ((readb(NE_BASE + NE_EN0_ISR) & ENISR_RDC) == 0) + if (jiffies - dma_start > 2*HZ/100) { /* 20ms */ + printk("%s: timeout waiting for Tx RDC.\n", dev->name); + ariadne2_reset_8390(dev); + NS8390_init(dev,1); + break; + } + + writeb(ENISR_RDC, nic_base + NE_EN0_ISR); /* Ack intr. */ + ei_status.dmaing &= ~0x01; + return; +} + +#ifdef MODULE +static char devicename[9] = { 0, }; + +static struct device ariadne2_dev = +{ + devicename, + 0, 0, 0, 0, + 0, 0, + 0, 0, 0, NULL, ariadne2_probe, +}; + +int init_module(void) +{ + int err; + if ((err = register_netdev(&ariadne2_dev))) { + if (err == -EIO) + printk("No AriadNE2 ethernet card found.\n"); + return err; + } + lock_8390_module(); + return 0; +} + +void cleanup_module(void) +{ + unsigned int key = ((struct ei_device *)ariadne2_dev.priv)->priv; + free_irq(IRQ_AMIGA_PORTS, &ariadne2_dev); + unregister_netdev(&ariadne2_dev); + zorro_config_board(key, 0); + unlock_8390_module(); +} + +#endif /* MODULE */ diff -u --recursive --new-file v2.1.123/linux/drivers/net/dummy.c linux/drivers/net/dummy.c --- v2.1.123/linux/drivers/net/dummy.c Thu Feb 12 20:56:08 1998 +++ linux/drivers/net/dummy.c Sun Oct 4 10:21:00 1998 @@ -99,7 +99,7 @@ ether_setup(dev); dev->tx_queue_len = 0; dev->flags |= IFF_NOARP; - dev->flags &= ~(IFF_BROADCAST|IFF_MULTICAST); + dev->flags &= ~IFF_MULTICAST; #ifdef CONFIG_NET_FASTROUTE dev->accept_fastpath = dummy_accept_fastpath; #endif diff -u --recursive --new-file v2.1.123/linux/drivers/net/mace.c linux/drivers/net/mace.c --- v2.1.123/linux/drivers/net/mace.c Sat Sep 5 16:46:40 1998 +++ linux/drivers/net/mace.c Sun Oct 4 10:21:00 1998 @@ -120,6 +120,7 @@ if (dev->priv == 0) return -ENOMEM; } + memset(dev->priv, 0, PRIV_BYTES); mp = (struct mace_data *) dev->priv; dev->base_addr = mace->addrs[0].address; @@ -127,21 +128,6 @@ ioremap(mace->addrs[0].address, 0x1000); dev->irq = mace->intrs[0].line; - if (request_irq(dev->irq, mace_interrupt, 0, "MACE", dev)) { - printk(KERN_ERR "MACE: can't get irq %d\n", dev->irq); - return -EAGAIN; - } - if (request_irq(mace->intrs[1].line, mace_txdma_intr, 0, "MACE-txdma", - dev)) { - printk(KERN_ERR "MACE: can't get irq %d\n", mace->intrs[1].line); - return -EAGAIN; - } - if (request_irq(mace->intrs[2].line, mace_rxdma_intr, 0, "MACE-rxdma", - dev)) { - printk(KERN_ERR "MACE: can't get irq %d\n", mace->intrs[2].line); - return -EAGAIN; - } - addr = get_property(mace, "mac-address", NULL); if (addr == NULL) { addr = get_property(mace, "local-mac-address", NULL); @@ -187,6 +173,23 @@ ether_setup(dev); + mace_reset(dev); + + if (request_irq(dev->irq, mace_interrupt, 0, "MACE", dev)) { + printk(KERN_ERR "MACE: can't get irq %d\n", dev->irq); + return -EAGAIN; + } + if (request_irq(mace->intrs[1].line, mace_txdma_intr, 0, "MACE-txdma", + dev)) { + printk(KERN_ERR "MACE: can't get irq %d\n", mace->intrs[1].line); + return -EAGAIN; + } + if (request_irq(mace->intrs[2].line, mace_rxdma_intr, 0, "MACE-rxdma", + dev)) { + printk(KERN_ERR "MACE: can't get irq %d\n", mace->intrs[2].line); + return -EAGAIN; + } + return 0; } @@ -197,36 +200,49 @@ int i; /* soft-reset the chip */ - mb->biucc = SWRST; eieio(); - udelay(100); + i = 200; + while (--i) { + out_8(&mb->biucc, SWRST); + if (mb->biucc & SWRST) { + udelay(20); + continue; + } + break; + } + if (!i) { + printk("mace: cannot reset chip!\n"); + return; + } + + out_8(&mb->imr, 0xff); /* disable all intrs for now */ + i = in_8(&mb->ir); + out_8(&mb->maccc, 0); /* turn off tx, rx */ mb->biucc = XMTSP_64; - mb->imr = 0xff; /* disable all intrs for now */ - i = mb->ir; - mb->maccc = 0; /* turn off tx, rx */ mb->utr = RTRD; - mb->fifocc = RCVFW_64; + mb->fifocc = RCVFW_32 | XMTFW_16 | XMTFWU | RCVFWU | XMTBRST; mb->xmtfc = AUTO_PAD_XMIT; /* auto-pad short frames */ + mb->rcvfc = 0; /* load up the hardware address */ - mb->iac = ADDRCHG | PHYADDR; eieio(); - while ((mb->iac & ADDRCHG) != 0) - eieio(); + out_8(&mb->iac, ADDRCHG | PHYADDR); + while ((in_8(&mb->iac) & ADDRCHG) != 0) + ; for (i = 0; i < 6; ++i) { - mb->padr = dev->dev_addr[i]; - eieio(); + out_8(&mb->padr, dev->dev_addr[i]); } /* clear the multicast filter */ - mb->iac = ADDRCHG | LOGADDR; eieio(); - while ((mb->iac & ADDRCHG) != 0) - eieio(); + out_8(&mb->iac, ADDRCHG | LOGADDR); + while ((in_8(&mb->iac) & ADDRCHG) != 0) + ; for (i = 0; i < 8; ++i) { - mb->ladrf = 0; - eieio(); + out_8(&mb->ladrf, 0); } + /* done changing address */ + out_8(&mb->iac, 0); - mb->plscc = PORTSEL_GPSI + ENPLSIO; + out_8(&mb->plscc, PORTSEL_GPSI + ENPLSIO); } static int mace_set_address(struct device *dev, void *addr) @@ -240,15 +256,15 @@ save_flags(flags); cli(); /* load up the hardware address */ - mb->iac = ADDRCHG | PHYADDR; eieio(); - while ((mb->iac & ADDRCHG) != 0) - eieio(); + out_8(&mb->iac, ADDRCHG | PHYADDR); + while ((in_8(&mb->iac) & ADDRCHG) != 0) + ; for (i = 0; i < 6; ++i) { - mb->padr = dev->dev_addr[i] = p[i]; - eieio(); + out_8(&mb->padr, dev->dev_addr[i] = p[i]); } + out_8(&mb->iac, 0); /* note: setting ADDRCHG clears ENRCV */ - mb->maccc = mp->maccc; eieio(); + out_8(&mb->maccc, mp->maccc); restore_flags(flags); return 0; @@ -316,9 +332,9 @@ mp->tx_bad_runt = 0; /* turn it on! */ - mb->maccc = mp->maccc; eieio(); + out_8(&mb->maccc, mp->maccc); /* enable all interrupts except receive interrupts */ - mb->imr = RCVINT; eieio(); + out_8(&mb->imr, RCVINT); return 0; } @@ -389,7 +405,7 @@ dev->tbusy = 1; mp->tx_fullup = 1; restore_flags(flags); - return -1; /* can't take it at the moment */ + return 1; /* can't take it at the moment */ } restore_flags(flags); @@ -483,16 +499,15 @@ printk("\n"); #endif - mb->iac = ADDRCHG | LOGADDR; eieio(); - while ((mb->iac & ADDRCHG) != 0) - eieio(); + out_8(&mb->iac, ADDRCHG | LOGADDR); + while ((in_8(&mb->iac) & ADDRCHG) != 0) + ; for (i = 0; i < 8; ++i) { - mb->ladrf = multicast_filter[i]; - eieio(); + out_8(&mb->ladrf, multicast_filter[i]); } } /* reset maccc */ - mb->maccc = mp->maccc; eieio(); + out_8(&mb->maccc, mp->maccc); } static void mace_handle_misc_intrs(struct mace_data *mp, int intr) @@ -525,9 +540,10 @@ volatile struct dbdma_cmd *cp; int intr, fs, i, stat, x; int xcount, dstat; - static int mace_last_fs, mace_last_xcount; + /* static int mace_last_fs, mace_last_xcount; */ - intr = mb->ir; /* read interrupt register */ + intr = in_8(&mb->ir); /* read interrupt register */ + in_8(&mb->xmtrc); /* get retries */ mace_handle_misc_intrs(mp, intr); i = mp->tx_empty; @@ -543,10 +559,9 @@ if (intr != 0) mace_handle_misc_intrs(mp, intr); if (mp->tx_bad_runt) { - fs = mb->xmtfs; - eieio(); + fs = in_8(&mb->xmtfs); mp->tx_bad_runt = 0; - mb->xmtfc = AUTO_PAD_XMIT; + mb->xmtfc = AUTO_PAD_XMIT; continue; } dstat = ld_le32(&td->status); @@ -569,8 +584,7 @@ * so the two bytes will only be a runt packet which should * be ignored by other stations. */ - mb->xmtfc = DXMTFCS; - eieio(); + out_8(&mb->xmtfc, DXMTFCS); } fs = mb->xmtfs; if ((fs & XMTSV) == 0) { @@ -618,14 +632,16 @@ ++mp->stats.tx_carrier_errors; if (fs & (UFLO|LCOL|RTRY)) ++mp->stats.tx_aborted_errors; - } else + } else ++mp->stats.tx_packets; dev_kfree_skb(mp->tx_bufs[i]); --mp->tx_active; if (++i >= N_TX_RING) i = 0; +#if 0 mace_last_fs = fs; mace_last_xcount = xcount; +#endif } if (i != mp->tx_empty) { @@ -675,7 +691,7 @@ cp = mp->tx_cmds + NCMDS_TX * mp->tx_empty; /* turn off both tx and rx and reset the chip */ - mb->maccc = 0; + out_8(&mb->maccc, 0); out_le32(&td->control, (RUN|PAUSE|FLUSH|WAKE) << 16); printk(KERN_ERR "mace: transmit timeout - resetting\n"); mace_reset(dev); diff -u --recursive --new-file v2.1.123/linux/drivers/net/sunhme.c linux/drivers/net/sunhme.c --- v2.1.123/linux/drivers/net/sunhme.c Tue Jul 28 14:21:08 1998 +++ linux/drivers/net/sunhme.c Sun Oct 4 10:21:00 1998 @@ -1676,9 +1676,14 @@ TXD(("[%d]", elem)); this = &txbase[elem]; +#ifdef __sparc_v9__ __asm__ __volatile__("lduwa [%1] %2, %0" : "=r" (flags) : "r" (&this->tx_flags), "i" (ASI_PL)); +#else + flush_cache_all(); + flags = flip_dword(this->tx_flags); +#endif if(flags & TXFLAG_OWN) break; skb = hp->tx_skbs[elem]; @@ -1813,7 +1818,7 @@ } /* This card is _fucking_ hot... */ - if(!~(csum)) + if(!(csum ^ 0xffff)) skb->ip_summed = CHECKSUM_UNNECESSARY; else skb->ip_summed = CHECKSUM_NONE; @@ -1845,9 +1850,14 @@ RXD(("RX<")); this = &rxbase[elem]; +#ifdef __sparc_v9__ __asm__ __volatile__("lduwa [%1] %2, %0" : "=r" (flags) : "r" (&this->rx_flags), "i" (ASI_PL)); +#else + flush_cache_all(); + flags = flip_dword(this->rx_flags); /* FIXME */ +#endif while(!(flags & RXFLAG_OWN)) { struct sk_buff *skb; int len; @@ -1934,9 +1944,14 @@ next: elem = NEXT_RX(elem); this = &rxbase[elem]; +#ifdef __sparc_v9__ __asm__ __volatile__("lduwa [%1] %2, %0" : "=r" (flags) : "r" (&this->rx_flags), "i" (ASI_PL)); +#else + flush_cache_all(); + flags = flip_dword(this->rx_flags); /* FIXME */ +#endif } hp->rx_new = elem; if(drops) @@ -2159,7 +2174,7 @@ return -EAGAIN; } } else -#else +#endif #ifdef CONFIG_PCI if(hp->happy_flags & HFLAG_PCI) { if(request_irq(dev->irq, &pci_happy_meal_interrupt, @@ -2170,7 +2185,6 @@ return -EAGAIN; } } else -#endif #endif if(request_irq(dev->irq, &happy_meal_interrupt, SA_SHIRQ, "HAPPY MEAL", (void *)dev)) { diff -u --recursive --new-file v2.1.123/linux/drivers/net/sunhme.h linux/drivers/net/sunhme.h --- v2.1.123/linux/drivers/net/sunhme.h Fri May 8 23:14:48 1998 +++ linux/drivers/net/sunhme.h Sun Oct 4 10:21:00 1998 @@ -632,6 +632,7 @@ } #ifdef CONFIG_PCI +#ifdef __sparc_v9__ extern inline void pcihme_write_rxd(struct happy_meal_rxd *rp, unsigned int flags, unsigned int addr) @@ -655,6 +656,27 @@ : "r" (&tp->tx_addr), "r" (&tp->tx_flags), "i" (ASI_PL), "r" (addr), "r" (flags)); } -#endif +#else + +extern inline void pcihme_write_rxd(struct happy_meal_rxd *rp, + unsigned int flags, + unsigned int addr) +{ + rp->rx_addr = flip_dword(addr); + rp->rx_flags = flip_dword(flags); + flush_cache_all(); +} + +extern inline void pcihme_write_txd(struct happy_meal_txd *tp, + unsigned int flags, + unsigned int addr) +{ + tp->tx_addr = flip_dword(addr); + tp->tx_flags = flip_dword(flags); + flush_cache_all(); +} + +#endif /* def __sparc_v9__ */ +#endif /* def CONFIG_PCI */ #endif /* !(_SUNHME_H) */ diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/audio/Config.in linux/drivers/sbus/audio/Config.in --- v2.1.123/linux/drivers/sbus/audio/Config.in Mon Mar 17 14:54:27 1997 +++ linux/drivers/sbus/audio/Config.in Sun Oct 4 10:22:43 1998 @@ -9,4 +9,5 @@ tristate 'Audio support (EXPERIMENTAL)' CONFIG_SPARCAUDIO dep_tristate ' AMD7930 Lowlevel Driver' CONFIG_SPARCAUDIO_AMD7930 $CONFIG_SPARCAUDIO dep_tristate ' CS4231 Lowlevel Driver' CONFIG_SPARCAUDIO_CS4231 $CONFIG_SPARCAUDIO + dep_tristate ' DBRI Lowlevel Driver' CONFIG_SPARCAUDIO_DBRI $CONFIG_SPARCAUDIO fi diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/audio/Makefile linux/drivers/sbus/audio/Makefile --- v2.1.123/linux/drivers/sbus/audio/Makefile Tue Mar 10 10:03:32 1998 +++ linux/drivers/sbus/audio/Makefile Sun Oct 4 10:22:43 1998 @@ -43,6 +43,16 @@ endif endif +ifeq ($(CONFIG_SPARCAUDIO_DBRI),y) +SBUS_AUDIO=y +O_OBJS += dbri.o +else + ifeq ($(CONFIG_SPARCAUDIO_DBRI),m) + SBUS_AUDIO_MODULE=y + M_OBJS += dbri.o + endif +endif + ifdef SBUS_AUDIO OX_OBJS += audio.o else diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/audio/amd7930.c linux/drivers/sbus/audio/amd7930.c --- v2.1.123/linux/drivers/sbus/audio/amd7930.c Thu Aug 6 14:06:32 1998 +++ linux/drivers/sbus/audio/amd7930.c Sun Oct 4 10:22:43 1998 @@ -1334,10 +1334,7 @@ /* Point at the information structure and initialize it. */ drv->ops = &amd7930_ops; info = (struct amd7930_info *)drv->private; - info->Bb.output_ptr = info->Bb.input_ptr = NULL; - info->Bb.output_count = info->Bb.input_count = 0; - info->Bc.output_ptr = info->Bc.input_ptr = NULL; - info->Bc.output_count = info->Bc.input_count = 0; + memset(info, 0, sizeof(*info)); info->ints_on = 1; /* force disable below */ drv->dev = sdev; diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/audio/audio.c linux/drivers/sbus/audio/audio.c --- v2.1.123/linux/drivers/sbus/audio/audio.c Wed Aug 26 11:37:38 1998 +++ linux/drivers/sbus/audio/audio.c Sun Oct 4 10:22:43 1998 @@ -1035,6 +1035,10 @@ cs4231_init(); #endif +#ifdef CONFIG_SPARCAUDIO_DBRI + dbri_init(); +#endif + return 0; } diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/audio/cs4215.h linux/drivers/sbus/audio/cs4215.h --- v2.1.123/linux/drivers/sbus/audio/cs4215.h Wed Jun 24 22:54:07 1998 +++ linux/drivers/sbus/audio/cs4215.h Sun Oct 4 10:22:43 1998 @@ -41,22 +41,22 @@ unsigned char xtal; unsigned char csval; } CS4215_FREQ[] = { - { 8000, 1, (0<<3) }, - { 16000, 1, (1<<3) }, - { 27429, 1, (2<<3) }, /* Actually 24428.57 */ - { 32000, 1, (3<<3) }, - /* { NA, 1, (4<<3) }, */ - /* { NA, 1, (5<<3) }, */ - { 48000, 1, (6<<3) }, - { 9600, 1, (7<<3) }, - { 5513, 2, (0<<3) }, /* Actually 5512.5 */ - { 11025, 2, (1<<3) }, - { 18900, 2, (2<<3) }, - { 22050, 2, (3<<3) }, - { 37800, 2, (4<<3) }, - { 44100, 2, (5<<3) }, - { 33075, 2, (6<<3) }, - { 6615, 2, (7<<3) }, + { 8000, (1<<4), (0<<3) }, + { 16000, (1<<4), (1<<3) }, + { 27429, (1<<4), (2<<3) }, /* Actually 24428.57 */ + { 32000, (1<<4), (3<<3) }, + /* { NA, (1<<4), (4<<3) }, */ + /* { NA, (1<<4), (5<<3) }, */ + { 48000, (1<<4), (6<<3) }, + { 9600, (1<<4), (7<<3) }, + { 5513, (2<<4), (0<<3) }, /* Actually 5512.5 */ + { 11025, (2<<4), (1<<3) }, + { 18900, (2<<4), (2<<3) }, + { 22050, (2<<4), (3<<3) }, + { 37800, (2<<4), (4<<3) }, + { 44100, (2<<4), (5<<3) }, + { 33075, (2<<4), (6<<3) }, + { 6615, (2<<4), (7<<3) }, { 0, 0, 0 } }; #define CS4215_HPF (1<<7) /* High Pass Filter, 1: Enabled */ diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/audio/dbri.c linux/drivers/sbus/audio/dbri.c --- v2.1.123/linux/drivers/sbus/audio/dbri.c Mon Jan 12 15:15:45 1998 +++ linux/drivers/sbus/audio/dbri.c Sun Oct 4 10:22:44 1998 @@ -59,7 +59,7 @@ #include #include -#include "audio.h" +#include #include "dbri.h" @@ -84,10 +84,13 @@ /* Bit hunting */ #define dumpcmd {int i; for(i=0; icmd[i]); } +#define DBRI_CMD(cmd, intr, value) ((cmd << 28) | (1 << 27) | value) + #else #define dprintk(a, x) #define dumpcmd +#define DBRI_CMD(cmd, intr, value) ((cmd << 28) | (intr << 27) | value) #endif /* DBRI_DEBUG */ @@ -103,6 +106,7 @@ static int num_drivers; static int dbri_cmdlocked = 0; +static void * output_callback_arg; /* * Make sure, that we can send a command to the dbri @@ -130,21 +134,6 @@ return 0; } -static void dummy() -{ -} - -static struct sparcaudio_operations dbri_ops = { - dummy, /* dbri_open, */ - dummy, /* dbri_release, */ - dummy, /* dbri_ioctl, */ - dummy, /* dbri_start_output, */ - dummy, /* dbri_stop_output, */ - dummy, /* dbri_start_input, */ - dummy, /* dbri_stop_input, */ - dummy, /* dbri_audio_getdev, */ -}; - static void dbri_reset(struct sparcaudio_driver *drv) { struct dbri *dbri = (struct dbri *)drv->private; @@ -171,7 +160,7 @@ } -static void dbri_init(struct sparcaudio_driver *drv) +static void dbri_initialize(struct sparcaudio_driver *drv) { struct dbri *dbri = (struct dbri *)drv->private; int n; @@ -191,7 +180,13 @@ dbri->intr[n * DBRI_INT_BLK] = (int)(dbri->intr); dbri->dbri_irqp = 1; +#ifdef USE_SBUS_BURSTS + /* Enable 4-word, 8-word, and 16-word SBus Bursts */ dbri->regs->reg0 |= (D_G|D_S|D_E); +#else + /* Disable 4-word, 8-word, and 16-word SBus Bursts */ + dbri->regs->reg0 &= ~(D_G|D_S|D_E); +#endif /* * Set up the interrupt queue @@ -236,7 +231,7 @@ */ mm->data[0] = CS4215_LO(0x20) | CS4215_HE|CS4215_LE; mm->data[1] = CS4215_RO(0x20) | CS4215_SE; - mm->data[2] = CS4215_LG( 0x8) | CS4215_IS; + mm->data[2] = CS4215_LG( 0x8) | CS4215_IS | CS4215_PIO0 | CS4215_PIO1; mm->data[3] = CS4215_RG( 0x8) | CS4215_MA(0xf); /* @@ -248,7 +243,7 @@ */ mm->ctrl[0] = CS4215_RSRVD_1; mm->ctrl[1] = CS4215_DFR_ULAW | CS4215_FREQ[0].csval; - mm->ctrl[2] = CS4215_XEN | CS4215_XCLK | + mm->ctrl[2] = CS4215_XCLK | CS4215_BSEL_128 | CS4215_FREQ[0].xtal; mm->ctrl[3] = 0; } @@ -264,69 +259,86 @@ * Pipe 4: Send timeslots 1-4 (audio data) * Pipe 17: Send timeslots 5-8 (part of ctrl data) * Pipe 6: Receive timeslots 1-4 (audio data) - * Pipe 19: Receive timeslots 6-7. We can only receive 20 bits via + * Pipe 20: Receive timeslots 6-7. We can only receive 20 bits via * interrupt, and the rest of the data (slot 5 and 8) is * not relevant for us (only for doublechecking). + * + * Just like in control mode, the time slots are all offset by eight + * bits. The CS4215, it seems, observes TSIN (the delayed signal) + * even if it's the CHI master. Don't ask me... */ - /* Transmit & Receive Memory setup */ - dbri->mm.td.flags = DBRI_TD_F|DBRI_TD_D|DBRI_TD_CNT(0); - dbri->mm.td.ba = 0; - dbri->mm.td.nda = (__u32)&dbri->mm.td; - dbri->mm.td.status = 0; - - dbri->mm.td.flags = DBRI_RD_BCNT(0); - dbri->mm.td.ba = 0; - dbri->mm.td.nda = (__u32)&dbri->mm.rd; - dbri->mm.td.status = 0; - /* Pipe 4: SDP + DTS */ - val = D_SDP_MEM|D_SDP_TO_SER|D_SDP_C|D_SDP_MSB|D_PIPE(D_P_4); + /* Pipe 4: SDP */ + val = D_SDP_MEM|D_SDP_TO_SER|D_SDP_C|D_SDP_P|D_SDP_MSB|D_PIPE(D_P_4); dbri->cmd[n++] = DBRI_CMD(D_SDP, 0, val); - dbri->cmd[n++] = (__u32)&dbri->mm.td; - - val = D_DTS_VO | D_DTS_INS | D_DTS_PRVOUT(D_P_16) | D_PIPE(D_P_4); - dbri->cmd[n++] = DBRI_CMD(D_DTS, 0, val); dbri->cmd[n++] = 0; - dbri->cmd[n++] = D_TS_LEN(8) | D_TS_CYCLE(0)| D_TS_NEXT(D_P_16); - /* Pipe 17: SDP + DTS + SSP */ + /* Pipe 17: SDP */ val = D_SDP_FIXED|D_SDP_TO_SER|D_SDP_C|D_PIPE(D_P_17); dbri->cmd[n++] = DBRI_CMD(D_SDP, 0, val); dbri->cmd[n++] = 0; /* Fixed data */ - val = D_DTS_VO | D_DTS_INS | D_DTS_PRVOUT(D_P_4) | D_PIPE(D_P_17); - dbri->cmd[n++] = DBRI_CMD(D_DTS, 0, val); - dbri->cmd[n++] = 0; - dbri->cmd[n++] = D_TS_LEN(32) | D_TS_CYCLE(32) | D_TS_NONCONTIG | - D_TS_MON(D_P_4) | D_TS_NEXT(D_P_16); - + /* Pipe 17: SSP */ dbri->cmd[n++] = DBRI_CMD(D_SSP, 0, D_PIPE(D_P_17)); dbri->cmd[n++] = reverse_bytes(*(int *)dbri->mm.data, 4); - /* Pipe 6: SDP + DTS */ - val=D_SDP_MEM|D_SDP_FROM_SER|D_SDP_C|D_SDP_MSB|D_PIPE(D_P_6); + /* Pipe 6: SDP */ + val=D_SDP_MEM|D_SDP_FROM_SER|D_SDP_C|D_SDP_P|D_SDP_MSB|D_PIPE(D_P_6); dbri->cmd[n++] = DBRI_CMD(D_SDP, 0, val); - dbri->cmd[n++] = (__u32)&dbri->mm.rd; - - val = D_DTS_VI | D_DTS_INS | D_DTS_PRVIN(D_P_16) | D_PIPE(D_P_6); - dbri->cmd[n++] = DBRI_CMD(D_DTS, 0, val); - dbri->cmd[n++] = D_TS_LEN(8) | D_TS_CYCLE(0)| D_TS_NEXT(D_P_16); dbri->cmd[n++] = 0; - /* Pipe 19: SDP + DTS */ - val = D_SDP_FIXED|D_SDP_FROM_SER|D_SDP_P|D_SDP_C|D_PIPE(D_P_19); + /* Pipe 20: SDP */ + val = D_SDP_FIXED|D_SDP_FROM_SER|D_SDP_CHANGE|D_SDP_C|D_PIPE(D_P_20); dbri->cmd[n++] = DBRI_CMD(D_SDP, 0, val); dbri->cmd[n++] = 0; /* Fixed data */ - val = D_DTS_VI | D_DTS_INS | D_DTS_PRVIN(D_P_6) | D_PIPE(D_P_19); + + + dbri->cmd[n++] = DBRI_CMD(D_PAUSE, 0, 0); + + + /* Pipe 4: DTS */ + val = D_DTS_VO | D_DTS_INS | D_DTS_PRVOUT(D_P_16) | D_PIPE(D_P_4); dbri->cmd[n++] = DBRI_CMD(D_DTS, 0, val); - dbri->cmd[n++] = D_TS_LEN(16) | D_TS_CYCLE(40) | D_TS_NONCONTIG | - D_TS_MON(D_P_6) | D_TS_NEXT(D_P_16); dbri->cmd[n++] = 0; +#if 0 + /* Full blown, four time slots, 16 bit stereo */ + dbri->cmd[n++] = D_TS_LEN(32) | D_TS_CYCLE(8)| D_TS_NEXT(D_P_16); +#else + /* Single time slot, 8 bit mono */ + dbri->cmd[n++] = D_TS_LEN(8) | D_TS_CYCLE(8)| D_TS_NEXT(D_P_16); +#endif + + /* Pipe 17: DTS */ + val = D_DTS_VO | D_DTS_INS | D_DTS_PRVOUT(D_P_4) | D_PIPE(D_P_17); + dbri->cmd[n++] = DBRI_CMD(D_DTS, 0, val); + dbri->cmd[n++] = 0; + dbri->cmd[n++] = D_TS_LEN(32) | D_TS_CYCLE(40) | D_TS_NEXT(D_P_16); + + /* Pipe 6: DTS */ + val = D_DTS_VI | D_DTS_INS | D_DTS_PRVIN(D_P_16) | D_PIPE(D_P_6); + dbri->cmd[n++] = DBRI_CMD(D_DTS, 0, val); +#if 0 + /* Full blown, four time slots, 16 bit stereo */ + dbri->cmd[n++] = D_TS_LEN(32) | D_TS_CYCLE(8)| D_TS_NEXT(D_P_16); +#else + /* Single time slot, 8 bit mono */ + dbri->cmd[n++] = D_TS_LEN(8) | D_TS_CYCLE(8)| D_TS_NEXT(D_P_16); +#endif + dbri->cmd[n++] = 0; + + /* Pipe 20: DTS */ + val = D_DTS_VI | D_DTS_INS | D_DTS_PRVIN(D_P_6) | D_PIPE(D_P_20); + dbri->cmd[n++] = DBRI_CMD(D_DTS, 0, val); + dbri->cmd[n++] = D_TS_LEN(16) | D_TS_CYCLE(48) | D_TS_NEXT(D_P_16); + dbri->cmd[n++] = 0; + + /* CHI: Slave mode; enable interrupts */ + dbri->cmd[n++] = DBRI_CMD(D_CHI, 0, D_CHI_CHICM(0) | D_CHI_IR | D_CHI_EN); dbri->cmd[n++] = DBRI_CMD(D_WAIT, 0, WAIT_INTR1); @@ -342,12 +354,31 @@ int n = 0, val; /* - * Enable Command mode: Set PIO3 to 0, then wait + * Enable Control mode: Set DBRI's PIO3 (4215's D/~C) to 0, then wait * 12 cycles <= 12/(5512.5*64) sec = 34.01 usec */ val = D_ENPIO | D_PIO1 | (dbri->mm.onboard ? D_PIO0 : D_PIO2); dbri->regs->reg2 = val; - udelay(34); + udelay(34); + + /* In Control mode, the CS4215 is a slave device, so the DBRI must + * operate as CHI master, supplying clocking and frame synchronization. + * + * In Data mode, however, the CS4215 must be CHI master to insure + * that its data stream is synchronous with its codec. + * + * The upshot of all this? We start by putting the DBRI into master + * mode, program the CS4215 in Control mode, then switch the CS4215 + * into Data mode and put the DBRI into slave mode. Various timing + * requirements must be observed along the way. + * + * Oh, and one more thing - when the DBRI is master (and only when + * the DBRI is master), the addressing of the CS4215's time slots + * is offset by eight bits, so we add eight to all the "cycle" + * values in the Define Time Slot (DTS) commands. This is done in + * hardware by a TI 248 that delays the DBRI->4215 frame sync signal + * by eight clock cycles. Anybody know why? + */ dbri_cmdlock(dbri); @@ -371,11 +402,11 @@ dbri->cmd[n++] = DBRI_CMD(D_SDP, 0, val); dbri->cmd[n++] = 0; - val = D_SDP_FIXED|D_SDP_CHANGE|D_SDP_P|D_SDP_C|D_PIPE(D_P_18); + val = D_SDP_FIXED|D_SDP_CHANGE|D_SDP_C|D_PIPE(D_P_18); dbri->cmd[n++] = DBRI_CMD(D_SDP, 0, val); dbri->cmd[n++] = 0; - val = D_SDP_FIXED|D_SDP_CHANGE|D_SDP_P|D_SDP_C|D_PIPE(D_P_19); + val = D_SDP_FIXED|D_SDP_CHANGE|D_SDP_C|D_PIPE(D_P_19); dbri->cmd[n++] = DBRI_CMD(D_SDP, 0, val); dbri->cmd[n++] = 0; @@ -389,76 +420,103 @@ /* Link the timeslots */ + + /* Pipe 17 - CS4215 Status, Data Format, Serial Control, Test - output + * time slots 1, 2, 3 and 4 - 32 bits + */ + val = D_DTS_VO | D_DTS_INS | D_DTS_PRVOUT(D_P_16) | D_PIPE(D_P_17); dbri->cmd[n++] = DBRI_CMD(D_DTS, 0, val); dbri->cmd[n++] = 0; - dbri->cmd[n++] = D_TS_LEN(32) | D_TS_CYCLE(256) | D_TS_NEXT(D_P_16); + dbri->cmd[n++] = D_TS_LEN(32) | D_TS_CYCLE(8) | D_TS_NEXT(D_P_16); + + /* Pipe 18 - CS4215 Status and Data Format - input + * time slots 1 & 2 - 16 bits + */ val = D_DTS_VI | D_DTS_INS | D_DTS_PRVIN(D_P_16) | D_PIPE(D_P_18); dbri->cmd[n++] = DBRI_CMD(D_DTS, 0, val); - dbri->cmd[n++] = D_TS_LEN(16) | D_TS_CYCLE(0) | D_TS_NEXT(D_P_16); + dbri->cmd[n++] = D_TS_LEN(16) | D_TS_CYCLE(8) | D_TS_NEXT(D_P_16); dbri->cmd[n++] = 0; + /* Pipe 19 - CS4215 Revision - time slot 7, eight bits - input + */ + val = D_DTS_VI | D_DTS_INS | D_DTS_PRVIN(D_P_18) | D_PIPE(D_P_19); dbri->cmd[n++] = DBRI_CMD(D_DTS, 0, val); - dbri->cmd[n++] = D_TS_LEN(8) | D_TS_CYCLE(48) | D_TS_NEXT(D_P_16); - /* - * According to the manual we should also specify - * D_TS_NONCONTIG | D_TS_MON(D_P_18), but the machine freezes - * if we do that. Can somebody explain me why? - */ + dbri->cmd[n++] = D_TS_LEN(8) | D_TS_CYCLE(56) | D_TS_NEXT(D_P_16); dbri->cmd[n++] = 0; - /* Setup DBRI for CHI Master */ - dbri->cmd[n++] = DBRI_CMD(D_CDM, 0, D_CDM_XCE|D_CDM_REN); - dbri->cmd[n++] = DBRI_CMD(D_CHI, 0, D_CHI_CHICM(6) | D_CHI_FD | - D_CHI_IR | D_CHI_EN); - dbri->cmd[n++] = DBRI_CMD(D_PAUSE, 0, 0); + /* Setup DBRI for CHI Master + * + * BPF = 128 (128 bits per 8 kHz frame = 1.024 MHz clock rate) + * CHICM = 12 (12.288 MHz / 24 = 1.024 MHz clock rate) + * FD = 1 - drive CHIFS on rising edge of CHICK + * + * RCE = 0 - receive on falling edge of CHICK + * XCE = 1 - transmit on rising edge of CHICK + */ + dbri->cmd[n++] = DBRI_CMD(D_CHI, 0, D_CHI_CHICM(12) | D_CHI_FD | + D_CHI_IR | D_CHI_EN | D_CHI_BPF(128)); dbri->cmd[n++] = DBRI_CMD(D_CDM, 0, D_CDM_XCE|D_CDM_XEN|D_CDM_REN); + dbri->cmd[n++] = DBRI_CMD(D_PAUSE, 0, 0); - dbri->cmd[n++] = DBRI_CMD(D_WAIT, 0, 0); + dbri->cmd[n++] = DBRI_CMD(D_WAIT, 1, WAIT_INTR1); dbri->regs->reg8 = (int)dbri->cmd; + /* Wait for the data from the CS4215 */ - interruptible_sleep_on(&dbri->int_wait); -printk("Woke up (1) reg2: %x\n", dbri->regs->reg2); + interruptible_sleep_on(&dbri->int_wait); + + /* Switch CS4215 to data mode - data sheet says + * "Set CLB=1 and send two more frames of valid control info" + */ + dbri_cmdlock(dbri); + + n = 0; + dbri->mm.ctrl[0] |= CS4215_CLB; + dbri->cmd[n++] = DBRI_CMD(D_SSP, 0, D_PIPE(D_P_17)); + dbri->cmd[n++] = reverse_bytes(*(int *)dbri->mm.ctrl, 4); + dbri->cmd[n++] = DBRI_CMD(D_WAIT, 1, WAIT_INTR1); + dbri->regs->reg8 = (int)dbri->cmd; + + dbri_cmdlock(dbri); + + /* Two frames of control info @ 8kHz frame rate = 250 us delay */ + udelay(250); - /* Now switch back to data mode */ n = 0; - /* CHI Anchor: Stop Send/Receive */ + + /* Now switch back to data mode */ + /* Reset CHI Anchor: Stop Send/Receive */ val = D_DTS_VI | D_DTS_VO | D_DTS_INS | D_DTS_PRVIN(D_P_16) | D_DTS_PRVOUT(D_P_16) | D_PIPE(D_P_16); dbri->cmd[n++] = DBRI_CMD(D_DTS, 0, val); dbri->cmd[n++] = D_TS_ANCHOR | D_TS_NEXT(D_P_16); dbri->cmd[n++] = D_TS_ANCHOR | D_TS_NEXT(D_P_16); - dbri->cmd[n++] = DBRI_CMD(D_WAIT, 0, 0x17); - dbri->regs->reg8 = (int)dbri->cmd; - -#if 0 - dbri->mm.ctrl[0] |= CS4215_CLB; - dbri->cmd[n++] = DBRI_CMD(D_SSP, 1, D_PIPE(D_P_17)); - dbri->cmd[n++] = reverse_bytes(*(int *)dbri->mm.ctrl, 4); /* Setup DBRI for CHI Slave */ - dbri->cmd[n++] = DBRI_CMD(D_CDM, 1, D_CDM_XCE|D_CDM_REN); - dbri->cmd[n++] = DBRI_CMD(D_CHI, 1, D_CHI_CHICM(1) | D_CHI_FD | - D_CHI_IR | D_CHI_EN); - dbri->cmd[n++] = DBRI_CMD(D_PAUSE, 1, 0x16); - dbri->cmd[n++] = DBRI_CMD(D_CDM, 0, D_CDM_XCE|D_CDM_XEN|D_CDM_REN); + dbri->cmd[n++] = DBRI_CMD(D_CHI, 0, D_CHI_CHICM(0)); + /* dbri->cmd[n++] = DBRI_CMD(D_CHI, 0, D_CHI_CHICM(0) | D_CHI_IR | D_CHI_EN); */ + dbri->cmd[n++] = DBRI_CMD(D_PAUSE, 0, 0x16); - dbri->cmd[n++] = DBRI_CMD(D_WAIT, 1, 0x17); + + dbri->cmd[n++] = DBRI_CMD(D_WAIT, 1, WAIT_INTR1); dbri->regs->reg8 = (int)dbri->cmd; - dbri->regs->reg2 = D_ENPIO | D_PIO3 | - (dbri->mm.onboard ? D_PIO0 : D_PIO2); -#endif + /* Wait for command to complete */ + dbri_cmdlock(dbri); + n = 0; + dbri->cmd[n++] = DBRI_CMD(D_WAIT, 1, WAIT_INTR1); + dbri->regs->reg8 = (int)dbri->cmd; - /* We are ready */ - dbri_cmdlocked = 0; - wake_up(&dbri->wait); + + /* Switch CS4215 to data mode - set PIO3 to 1 */ + dbri->regs->reg2 = D_ENPIO | D_PIO1 | D_PIO3 | + (dbri->mm.onboard ? D_PIO0 : D_PIO2); } static int mmcodec_init(struct sparcaudio_driver *drv) @@ -500,9 +558,7 @@ if(dbri->mm.version == 0xff) return -EIO; - /* - mmcodec_init_data(dbri, &n); - */ + mmcodec_init_data(dbri); return 0; } @@ -518,11 +574,13 @@ * Read it, so the interrupt goes away. */ x = dbri->regs->reg1; +#if 0 if(numint++ > 20) { dbri->regs->reg0 = D_R; /* Soft Reset */ numint = 0; printk("Soft reset\n"); } +#endif if ( x & (D_MRR|D_MLE|D_LBG|D_MBE) ) { /* @@ -562,6 +620,12 @@ if(val == WAIT_INTR2) wake_up(&dbri->int_wait); break; + case D_P_4: + if (D_INTR_GETCODE(x) == D_INTR_XCMP) { + sparcaudio_output_done(output_callback_arg, 1); + } + break; + case D_P_18: if(val != 0) { x = reverse_bytes(val,2)&CS4215_12_MASK; @@ -591,7 +655,123 @@ } +/* +**************************************************************************** +******************** Interface with sparcaudio midlevel ******************** +**************************************************************************** +*/ + + +static void dummy() +{ +} + +static int dbri_open(struct inode * inode, struct file * file, + struct sparcaudio_driver *drv) +{ + struct dbri *dbri = (struct dbri *)drv->private; + +#if 0 + /* Set the default audio parameters. */ + info->rgain = 128; + info->pgain = 200; + info->mgain = 0; +#endif + + MOD_INC_USE_COUNT; + + return 0; +} + +static void dbri_release(struct inode * inode, struct file * file, + struct sparcaudio_driver *drv) +{ + MOD_DEC_USE_COUNT; +} + +static void dbri_start_output(struct sparcaudio_driver *drv, + __u8 * buffer, unsigned long count) +{ + struct dbri *dbri = (struct dbri *)drv->private; + int val, n = 0; + + /* XXX - This routine can be called via interrupt. If DBRI + * was cmdlocked, that would cause a sleep, which would be + * scheduling in an interrupt, and that's not allowed + * + * Fortunately, there's nothing else talking to our DBRI (yet), + * so this isn't a problem (yet) + */ + + dbri_cmdlock(dbri); + + dbri->mm.td.flags = DBRI_TD_F | DBRI_TD_B | DBRI_TD_D | DBRI_TD_CNT(count); + dbri->mm.td.ba = (__u32) buffer; + dbri->mm.td.nda = 0; + dbri->mm.td.status = 0; + + /* Pipe 4 is audio transmit */ + val = D_SDP_MEM|D_SDP_TO_SER|D_SDP_P|D_SDP_MSB|D_PIPE(D_P_4); + dbri->cmd[n++] = DBRI_CMD(D_SDP, 0, val); + dbri->cmd[n++] = (__u32)&dbri->mm.td; + dbri->cmd[n++] = DBRI_CMD(D_WAIT, 0, WAIT_INTR1); + + dbri->regs->reg8 = (int)dbri->cmd; + + output_callback_arg = drv; +} + +static void dbri_stop_output(struct sparcaudio_driver *drv) +{ + struct dbri *dbri = (struct dbri *)drv->private; +} + +static struct sparcaudio_operations dbri_ops = { + dbri_open, + dbri_release, + dummy, /* dbri_ioctl, */ + dbri_start_output, + dbri_stop_output, + dummy, /* dbri_start_input, */ + dummy, /* dbri_stop_input, */ + dummy, /* dbri_audio_getdev, */ + dummy, /* dbri_set_output_volume, */ + dummy, /* dbri_get_output_volume, */ + dummy, /* dbri_set_input_volume, */ + dummy, /* dbri_get_input_volume, */ + dummy, /* dbri_set_monitor_volume, */ + dummy, /* dbri_get_monitor_volume, */ + dummy, /* dbri_set_output_balance */ + dummy, /* dbri_get_output_balance, */ + dummy, /* dbri_set_input_balance */ + dummy, /* dbri_get_input_balance, */ + dummy, /* dbri_set_output_channels */ + dummy, /* dbri_get_output_channels, */ + dummy, /* dbri_set_input_channels */ + dummy, /* dbri_get_input_channels, */ + dummy, /* dbri_set_output_precision */ + dummy, /* dbri_get_output_precision, */ + dummy, /* dbri_set_input_precision */ + dummy, /* dbri_get_input_precision, */ + dummy, /* dbri_set_output_port */ + dummy, /* dbri_get_output_port, */ + dummy, /* dbri_set_input_port */ + dummy, /* dbri_get_input_port, */ + dummy, /* dbri_set_output_encoding */ + dummy, /* dbri_get_output_encoding, */ + dummy, /* dbri_set_input_encoding */ + dummy, /* dbri_get_input_encoding, */ + dummy, /* dbri_set_output_rate */ + dummy, /* dbri_get_output_rate, */ + dummy, /* dbri_set_input_rate */ + dummy, /* dbri_get_input_rate, */ + dummy, /* dbri_sunaudio_getdev_sunos, */ + dummy, /* dbri_get_output_ports, */ + dummy, /* dbri_get_input_ports, */ + dummy, /* dbri_set_output_muted */ + dummy, /* dbri_get_output_muted, */ +}; static int dbri_attach(struct sparcaudio_driver *drv, @@ -651,7 +831,7 @@ return err; } - dbri_init(drv); + dbri_initialize(drv); err = mmcodec_init(drv); if(err) { dbri_detach(drv); @@ -713,3 +893,22 @@ } } #endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-indent-level: 4 + * c-brace-imaginary-offset: 0 + * c-brace-offset: -4 + * c-argdecl-indent: 4 + * c-label-offset: -4 + * c-continued-statement-offset: 4 + * c-continued-brace-offset: 0 + * indent-tabs-mode: nil + * tab-width: 8 + * End: + */ diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/audio/dbri.h linux/drivers/sbus/audio/dbri.h --- v2.1.123/linux/drivers/sbus/audio/dbri.h Mon Jan 12 15:15:45 1998 +++ linux/drivers/sbus/audio/dbri.h Sun Oct 4 10:22:44 1998 @@ -106,7 +106,6 @@ #define D_TEST 0xd /* No comment */ #define D_CDM 0xe /* CHI Data mode command */ -#define DBRI_CMD(cmd, intr, value) ((cmd << 28) | (intr << 27) | value) /* Special bits for some commands */ @@ -268,7 +267,7 @@ /* Transmit descriptor defines */ #define DBRI_TD_F (1<<31) /* End of Frame */ -#define DBRI_TD_D (1<<31) /* Do not append CRC */ +#define DBRI_TD_D (1<<30) /* Do not append CRC */ #define DBRI_TD_CNT(v) (v<<16) /* Number of valid bytes in the buffer */ #define DBRI_TD_B (1<<15) /* Final interrupt */ #define DBRI_TD_M (1<<14) /* Marker interrupt */ diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/char/Config.in linux/drivers/sbus/char/Config.in --- v2.1.123/linux/drivers/sbus/char/Config.in Thu Aug 6 14:06:32 1998 +++ linux/drivers/sbus/char/Config.in Sun Oct 4 10:22:44 1998 @@ -2,7 +2,9 @@ tristate '/dev/openprom device support' CONFIG_SUN_OPENPROMIO tristate 'Mostek real time clock support' CONFIG_SUN_MOSTEK_RTC if [ "$ARCH" = "sparc64" ]; then - tristate 'Siemens SAB82532 serial support' CONFIG_SAB82532 + if [ "$CONFIG_PCI" = "y" ]; then + tristate 'Siemens SAB82532 serial support' CONFIG_SAB82532 + fi tristate 'OBP Flash Device support' CONFIG_OBP_FLASH fi diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/char/Makefile linux/drivers/sbus/char/Makefile --- v2.1.123/linux/drivers/sbus/char/Makefile Thu Aug 6 14:06:32 1998 +++ linux/drivers/sbus/char/Makefile Sun Oct 4 10:22:44 1998 @@ -47,7 +47,13 @@ endif endif -endif # eq($(ARCH),sparc64) +else # !eq($(ARCH),sparc64) + +ifeq ($(CONFIG_PCI),y) +O_OBJS += su32.o pcikbd.o +endif + +endif # !eq($(ARCH),sparc64) ifeq ($(CONFIG_SUN_OPENPROMIO),y) O_OBJS += openprom.o diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/char/bpp.c linux/drivers/sbus/char/bpp.c --- v2.1.123/linux/drivers/sbus/char/bpp.c Wed Aug 26 11:37:38 1998 +++ linux/drivers/sbus/char/bpp.c Sun Oct 4 10:22:44 1998 @@ -314,13 +314,6 @@ #endif /* __sparc__ */ -/* - * This is TRUE if the module_init successfully loaded the module. - */ -#if 0 -static int loaded_flag = 0; -#endif - static void bpp_wake_up(unsigned long val) { wake_up(&instances[val].wait_queue); } @@ -946,25 +939,22 @@ { volatile struct bpp_regs *regs; - /* Apply ranges to here, do not pollute Sbus devices list. */ - struct linux_prom_registers areg; - /* * PROM reports different numbers on Zebra and on DMA2. * We need to figure out when to apply parent ranges. * printk will show this on different machines. */ - areg = dev->reg_addrs[0]; - printk("bpp%d.map_bpp: 0x%x.%p[0x%x] i=%d\n", idx, - areg.which_io, areg.phys_addr, areg.reg_size, - dev->irqs[0]); /* IPC Zebra 1.fa200000[1c] i=2 */ - /** prom_apply_sbus_ranges (&areg, 1); **/ + prom_apply_sbus_ranges(dev->my_bus, &dev->reg_addrs[0], + dev->num_registers, dev); - regs = sparc_alloc_io (areg.phys_addr, 0, - sizeof(struct bpp_regs), "bpp", - areg.which_io, 0x0); + regs = sparc_alloc_io(dev->reg_addrs[0].phys_addr, 0, + dev->reg_addrs[0].reg_size, "bpp", + dev->reg_addrs[0].which_io, 0x0); + printk("bpp%d.map_bpp: 0x%x.%p[0x%x] i=%d\n", idx, + dev->reg_addrs[0].which_io, dev->reg_addrs[0].phys_addr, + dev->reg_addrs[0].reg_size, dev->irqs[0]); return regs; } diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/char/envctrl.c linux/drivers/sbus/char/envctrl.c --- v2.1.123/linux/drivers/sbus/char/envctrl.c Wed Aug 26 11:37:38 1998 +++ linux/drivers/sbus/char/envctrl.c Sun Oct 4 10:22:44 1998 @@ -1,4 +1,4 @@ -/* $Id: envctrl.c,v 1.7 1998/06/10 07:25:28 davem Exp $ +/* $Id: envctrl.c,v 1.8 1998/08/26 10:29:40 davem Exp $ * envctrl.c: Temperature and Fan monitoring on Machines providing it. * * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/char/flash.c linux/drivers/sbus/char/flash.c --- v2.1.123/linux/drivers/sbus/char/flash.c Wed Aug 26 11:37:38 1998 +++ linux/drivers/sbus/char/flash.c Sun Oct 4 10:22:44 1998 @@ -1,4 +1,4 @@ -/* $Id: flash.c,v 1.9 1998/05/17 06:33:39 ecd Exp $ +/* $Id: flash.c,v 1.10 1998/08/26 10:29:41 davem Exp $ * flash.c: Allow mmap access to the OBP Flash, for OBP updates. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/char/pcikbd.c linux/drivers/sbus/char/pcikbd.c --- v2.1.123/linux/drivers/sbus/char/pcikbd.c Wed Aug 26 11:37:38 1998 +++ linux/drivers/sbus/char/pcikbd.c Sun Oct 4 10:22:44 1998 @@ -1,7 +1,8 @@ -/* $Id: pcikbd.c,v 1.18 1998/05/29 06:00:23 ecd Exp $ +/* $Id: pcikbd.c,v 1.22 1998/09/21 05:06:45 jj Exp $ * pcikbd.c: Ultra/AX PC keyboard support. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) + * JavaStation(MrCoffee) support by Pete A. Zaitcev. * * This code is mainly put together from various places in * drivers/char, please refer to these sources for credits @@ -29,15 +30,32 @@ #include #include +#ifdef __sparc_v9__ +#define PCI_KB_NAME "kb_ps2" +#define PCI_MS_NAME "kdmouse" +#else +#define PCI_KB_NAME "keyboard" +#define PCI_MS_NAME "mouse" +/* + * XXX. + * Gleb defines check_region and request_region here. + * This looks suspicios because he neglects to call + * sparc_alloc_io, but the conflict with sparc_alloc_io is what + * causes problems. + */ +#endif + #include "pcikbd.h" #include "sunserial.h" -static int kbd_node; -static int beep_node; +#ifndef __sparc_v9__ +static int pcikbd_mrcoffee = 0; +#else +#define pcikbd_mrcoffee 0 +#endif static unsigned long pcikbd_iobase = 0; -static unsigned long pcibeep_iobase = 0; -static unsigned int pcikbd_irq; +static unsigned int pcikbd_irq = 0; /* used only by send_data - set by keyboard_interrupt */ static volatile unsigned char reply_expected = 0; @@ -53,6 +71,8 @@ extern void pci_setledstate(struct kbd_struct *, unsigned int); extern unsigned char pci_getledstate(void); +#ifdef __sparc_v9__ + static __inline__ unsigned char pcikbd_inb(unsigned long port) { return inb(port); @@ -63,6 +83,20 @@ outb(val, port); } +#else + +static __inline__ unsigned char pcikbd_inb(unsigned long port) +{ + return *(volatile unsigned char *)port; +} + +static __inline__ void pcikbd_outb(unsigned char val, unsigned long port) +{ + *(volatile unsigned char *)port = val; +} + +#endif + static inline void kb_wait(void) { unsigned long start = jiffies; @@ -372,6 +406,10 @@ pcikbd_outb(data, pcikbd_iobase + address); } +#ifdef __sparc_v9__ + +static unsigned long pcibeep_iobase = 0; + /* Timer routine to turn off the beep after the interval expires. */ static void pcikbd_kd_nosound(unsigned long __unused) { @@ -402,6 +440,7 @@ outl(0, pcibeep_iobase); restore_flags(flags); } +#endif static void nop_kd_mksound(unsigned int hz, unsigned int ticks) { @@ -411,6 +450,7 @@ __initfunc(static char *do_pcikbd_init_hw(void)) { + while(pcikbd_wait_for_input() != -1) ; @@ -458,40 +498,58 @@ struct linux_ebus_child *child; char *msg; - for_each_ebus(ebus) { - for_each_ebusdev(edev, ebus) { - if(!strcmp(edev->prom_name, "8042")) { - for_each_edevchild(edev, child) { - if (!strcmp(child->prom_name, "kb_ps2")) - goto found; + if (pcikbd_mrcoffee) { + if ((pcikbd_iobase = (unsigned long) sparc_alloc_io(0x71300060, + 0, 8, "ps2kbd-regs", 0x0, 0)) == 0) { + prom_printf("pcikbd_init_hw: cannot map\n"); + return; + } + pcikbd_irq = 13 | 0x20; + if (request_irq(pcikbd_irq, &pcikbd_interrupt, + SA_SHIRQ, "keyboard", (void *)pcikbd_iobase)) { + printk("8042: cannot register IRQ %x\n", pcikbd_irq); + return; + } + printk("8042(kbd): iobase[%08x] irq[%x]\n", + (unsigned)pcikbd_iobase, pcikbd_irq); + } else { + for_each_ebus(ebus) { + for_each_ebusdev(edev, ebus) { + if(!strcmp(edev->prom_name, "8042")) { + for_each_edevchild(edev, child) { + if (!strcmp(child->prom_name, "kb_ps2")) + goto found; + } } } } - } - printk("pcikbd_probe: no 8042 found\n"); - return; + printk("pcikbd_init_hw: no 8042 found\n"); + return; found: - pcikbd_iobase = child->base_address[0]; - if (check_region(pcikbd_iobase, sizeof(unsigned long))) { - printk("8042: can't get region %lx, %d\n", - pcikbd_iobase, (int)sizeof(unsigned long)); - return; - } - request_region(pcikbd_iobase, sizeof(unsigned long), "8042 controller"); + pcikbd_iobase = child->base_address[0]; + if (check_region(pcikbd_iobase, sizeof(unsigned long))) { + printk("8042: can't get region %lx, %d\n", + pcikbd_iobase, (int)sizeof(unsigned long)); + return; + } + request_region(pcikbd_iobase, sizeof(unsigned long), "8042 controller"); - pcikbd_irq = child->irqs[0]; - if (request_irq(pcikbd_irq, &pcikbd_interrupt, - SA_SHIRQ, "keyboard", (void *)pcikbd_iobase)) { - printk("8042: cannot register IRQ %s\n", + pcikbd_irq = child->irqs[0]; + if (request_irq(pcikbd_irq, &pcikbd_interrupt, + SA_SHIRQ, "keyboard", (void *)pcikbd_iobase)) { + printk("8042: cannot register IRQ %s\n", + __irq_itoa(pcikbd_irq)); + return; + } + + printk("8042(kbd) at 0x%lx (irq %s)\n", pcikbd_iobase, __irq_itoa(pcikbd_irq)); - return; } - printk("8042(kbd) at 0x%lx (irq %s)\n", pcikbd_iobase, - __irq_itoa(pcikbd_irq)); - kd_mksound = nop_kd_mksound; + +#ifdef __sparc_v9__ edev = 0; for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { @@ -504,6 +562,8 @@ /* * XXX: my 3.1.3 PROM does not give me the beeper node for the audio * auxio register, though I know it is there... (ecd) + * + * Both JE1 & MrCoffe have no beeper. How about Krups? --zaitcev */ if (!edev) pcibeep_iobase = (pcikbd_iobase & ~(0xffffff)) | 0x722000; @@ -519,6 +579,7 @@ printk("8042(speaker): iobase[%016lx]%s\n", pcibeep_iobase, edev ? "" : " (forced)"); } +#endif disable_irq(pcikbd_irq); msg = do_pcikbd_init_hw(); @@ -534,8 +595,6 @@ * Here begins the Mouse Driver. */ -static int ms_node; - static unsigned long pcimouse_iobase = 0; static unsigned int pcimouse_irq; @@ -554,6 +613,8 @@ static int aux_count = 0; static int aux_present = 0; +#ifdef __sparc_v9__ + static __inline__ unsigned char pcimouse_inb(unsigned long port) { return inb(port); @@ -564,6 +625,20 @@ outb(val, port); } +#else + +static __inline__ unsigned char pcimouse_inb(unsigned long port) +{ + return *(volatile unsigned char *)port; +} + +static __inline__ void pcimouse_outb(unsigned char val, unsigned long port) +{ + *(volatile unsigned char *)port = val; +} + +#endif + /* * Shared subroutines */ @@ -587,11 +662,11 @@ return queue->head == queue->tail; } -static int aux_fasync(struct file *filp, int on) +static int aux_fasync(int fd, struct file *filp, int on) { int retval; - retval = fasync_helper(filp, on, &queue->fasync); + retval = fasync_helper(fd, filp, on, &queue->fasync); if (retval < 0) return retval; return 0; @@ -721,7 +796,7 @@ static int aux_release(struct inode * inode, struct file * file) { - aux_fasync(file, 0); + aux_fasync(-1, file, 0); if (--aux_count) return 0; aux_start_atomic(); @@ -885,29 +960,43 @@ struct linux_ebus_device *edev; struct linux_ebus_child *child; - for_each_ebus(ebus) { - for_each_ebusdev(edev, ebus) { - if(!strcmp(edev->prom_name, "8042")) { - for_each_edevchild(edev, child) { - if (!strcmp(child->prom_name,"kdmouse")) - goto found; + if (pcikbd_mrcoffee) { + if ((pcimouse_iobase = pcikbd_iobase) == 0) { + printk("pcimouse_init: no 8042 given\n"); + return -ENODEV; + } + pcimouse_irq = pcikbd_irq; + } else { + for_each_ebus(ebus) { + for_each_ebusdev(edev, ebus) { + if(!strcmp(edev->prom_name, "8042")) { + for_each_edevchild(edev, child) { + if (!strcmp(child->prom_name, PCI_MS_NAME)) + goto found; + } } } } - } - printk("pcimouse_init: no 8042 found\n"); - return -ENODEV; + printk("pcimouse_init: no 8042 found\n"); + return -ENODEV; found: - pcimouse_iobase = child->base_address[0]; - /* - * Just in case the iobases for kbd/mouse ever differ... - */ - if (!check_region(pcimouse_iobase, sizeof(unsigned long))) - request_region(pcimouse_iobase, sizeof(unsigned long), - "8042 controller"); + pcimouse_iobase = child->base_address[0]; + /* + * Just in case the iobases for kbd/mouse ever differ... + */ + if (!check_region(pcimouse_iobase, sizeof(unsigned long))) + request_region(pcimouse_iobase, sizeof(unsigned long), + "8042 controller"); + + pcimouse_irq = child->irqs[0]; + } + + queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL); + memset(queue, 0, sizeof(*queue)); + queue->head = queue->tail = 0; + queue->proc_list = NULL; - pcimouse_irq = child->irqs[0]; if (request_irq(pcimouse_irq, &pcimouse_interrupt, SA_SHIRQ, "mouse", (void *)pcimouse_iobase)) { printk("8042: Cannot register IRQ %s\n", @@ -923,10 +1012,6 @@ pckbd_read_mask = AUX_STAT_OBF; misc_register(&psaux_mouse); - queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL); - memset(queue, 0, sizeof(*queue)); - queue->head = queue->tail = 0; - queue->proc_list = NULL; aux_start_atomic(); pcimouse_outb(KBD_CCMD_MOUSE_ENABLE, pcimouse_iobase + KBD_CNTL_REG); aux_write_ack(AUX_RESET); @@ -956,8 +1041,22 @@ char prop[128]; int len; +#ifndef __sparc_v9__ + /* + * MrCoffee has hardware but has no PROM nodes whatsoever. + */ + len = prom_getproperty(prom_root_node, "name", prop, sizeof(prop)); + if (len < 0) { + printk("ps2kbd_probe: no name of root node\n"); + return -ENODEV; + } + if (strncmp(prop, "SUNW,JavaStation-1", len) == 0) { + pcikbd_mrcoffee = 1; /* Brain damage detected */ + goto found; + } +#endif /* - * Get the nodes for keyboard and mouse from 'aliases'... + * Get the nodes for keyboard and mouse from aliases on normal systems. */ node = prom_getchild(prom_root_node); node = prom_searchsiblings(node, "aliases"); @@ -1020,17 +1119,14 @@ * Does it match? */ dnode = prom_getchild(node); - dnode = prom_searchsiblings(dnode, "kb_ps2"); + dnode = prom_searchsiblings(dnode, PCI_KB_NAME); if (dnode == kbnode) { - kbd_node = kbnode; - beep_node = bnode; ++devices; } dnode = prom_getchild(node); - dnode = prom_searchsiblings(dnode, "kdmouse"); + dnode = prom_searchsiblings(dnode, PCI_MS_NAME); if (dnode == msnode) { - ms_node = msnode; ++devices; } diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/char/rtc.c linux/drivers/sbus/char/rtc.c --- v2.1.123/linux/drivers/sbus/char/rtc.c Wed Aug 26 11:37:38 1998 +++ linux/drivers/sbus/char/rtc.c Sun Oct 4 10:22:44 1998 @@ -1,4 +1,4 @@ -/* $Id: rtc.c,v 1.12 1998/05/08 21:04:35 davem Exp $ +/* $Id: rtc.c,v 1.13 1998/08/26 10:29:44 davem Exp $ * * Linux/SPARC Real Time Clock Driver * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu) diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/char/sab82532.c linux/drivers/sbus/char/sab82532.c --- v2.1.123/linux/drivers/sbus/char/sab82532.c Thu Aug 6 14:06:32 1998 +++ linux/drivers/sbus/char/sab82532.c Sun Oct 4 10:22:44 1998 @@ -1,4 +1,4 @@ -/* $Id: sab82532.c,v 1.20 1998/05/29 06:00:24 ecd Exp $ +/* $Id: sab82532.c,v 1.23 1998/09/16 03:20:25 ecd Exp $ * sab82532.c: ASYNC Driver for the SIEMENS SAB82532 DUSCC. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -52,6 +52,13 @@ #undef SERIAL_DEBUG_SEND_BREAK #undef SERIAL_DEBUG_INTR +/* Trace things on serial device, useful for console debugging: */ +#undef SERIAL_LOG_DEVICE + +#ifdef SERIAL_LOG_DEVICE +static void dprint_init(int tty); +#endif + static void change_speed(struct sab82532 *info); static void sab82532_wait_until_sent(struct tty_struct *tty, int timeout); @@ -1330,57 +1337,34 @@ /* * This routine sends a break character out the serial port. */ -static void send_break( struct sab82532 * info, int duration) +static void sab82532_break(struct tty_struct *tty, int break_state) { - if (!info->regs) - return; - current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + duration; -#ifdef SERIAL_DEBUG_SEND_BREAK - printk("sab82532_send_break(%d) jiff=%lu...", duration, jiffies); -#endif - cli(); - info->regs->rw.dafo |= SAB82532_DAFO_XBRK; - schedule(); - info->regs->rw.dafo &= ~(SAB82532_DAFO_XBRK); - sti(); -#ifdef SERIAL_DEBUG_SEND_BREAK - printk("done jiffies=%lu\n", jiffies); -#endif -} + struct sab82532 * info = (struct sab82532 *)tty->driver_data; + unsigned long flags; -/* - * This routine sets the break condition on the serial port. - */ -static void begin_break(struct sab82532 * info) -{ - if (!info->regs) + if (serial_paranoia_check(info, tty->device, "sab82532_break")) return; - info->regs->rw.dafo |= SAB82532_DAFO_XBRK; -#ifdef SERIAL_DEBUG_SEND_BREAK - printk("begin_break: jiffies=%lu\n", jiffies); -#endif -} -/* - * This routine clears the break condition on the serial port. - */ -static void end_break(struct sab82532 * info) -{ if (!info->regs) return; - info->regs->rw.dafo &= ~(SAB82532_DAFO_XBRK); + #ifdef SERIAL_DEBUG_SEND_BREAK - printk("end_break: jiffies=%lu\n", jiffies); + printk("sab82532_break(%d) jiff=%lu...", break_state, jiffies); #endif + save_flags(flags); cli(); + if (break_state == -1) + info->regs->rw.dafo |= SAB82532_DAFO_XBRK; + else + info->regs->rw.dafo &= ~(SAB82532_DAFO_XBRK); + restore_flags(flags); } + static int sab82532_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) { int error; struct sab82532 * info = (struct sab82532 *)tty->driver_data; - int retval; struct async_icount cprev, cnow; /* kernel counter temps */ struct serial_icounter_struct *p_cuser; /* user space */ @@ -1396,43 +1380,6 @@ } switch (cmd) { - case TCSBRK: /* SVID version: non-zero arg --> no break */ - retval = tty_check_change(tty); - if (retval) - return retval; - tty_wait_until_sent(tty, 0); - if (signal_pending(current)) - return -EINTR; - if (!arg) { - send_break(info, HZ/4); /* 1/4 second */ - if (signal_pending(current)) - return -EINTR; - } - return 0; - case TCSBRKP: /* support for POSIX tcsendbreak() */ - retval = tty_check_change(tty); - if (retval) - return retval; - tty_wait_until_sent(tty, 0); - if (signal_pending(current)) - return -EINTR; - send_break(info, arg ? arg*(HZ/10) : HZ/4); - if (signal_pending(current)) - return -EINTR; - return 0; - case TIOCSBRK: - retval = tty_check_change(tty); - if (retval) - return retval; - tty_wait_until_sent(tty, 0); - begin_break(info); - return 0; - case TIOCCBRK: - retval = tty_check_change(tty); - if (retval) - return retval; - end_break(info); - return 0; case TIOCGSOFTCAR: return put_user(C_CLOCAL(tty) ? 1 : 0, (int *) arg); case TIOCSSOFTCAR: @@ -2047,7 +1994,7 @@ int i, len = 0; off_t begin = 0; - len += sprintf(page, "serinfo:1.0 driver:%s\n", "$Revision: 1.20 $"); + len += sprintf(page, "serinfo:1.0 driver:%s\n", "$Revision: 1.23 $"); for (i = 0; i < NR_PORTS && len < 4000; i++) { len += line_info(page + len, sab82532_table[i]); if (len+begin > off+count) @@ -2142,7 +2089,7 @@ __initfunc(static inline void show_serial_version(void)) { - char *revision = "$Revision: 1.20 $"; + char *revision = "$Revision: 1.23 $"; char *version, *p; version = strchr(revision, ' '); @@ -2203,6 +2150,7 @@ serial_driver.stop = sab82532_stop; serial_driver.start = sab82532_start; serial_driver.hangup = sab82532_hangup; + serial_driver.break_ctl = sab82532_break; serial_driver.wait_until_sent = sab82532_wait_until_sent; serial_driver.read_proc = sab82532_read_proc; @@ -2274,6 +2222,10 @@ info->line, (unsigned long)info->regs, __irq_itoa(info->irq), sab82532_version[info->type]); } + +#ifdef SERIAL_LOG_DEVICE + dprint_init(SERIAL_LOG_DEVICE); +#endif return 0; } @@ -2388,7 +2340,12 @@ struct sab82532 *info; int i; - info = sab82532_chain + con->index; + info = sab82532_chain; + for (i = con->index; i; i--) { + info = info->next; + if (!info) + return; + } for (i = 0; i < n; i++) { if (*s == '\n') @@ -2421,7 +2378,12 @@ int i, bits; unsigned long flags; - info = sab82532_chain + con->index; + info = sab82532_chain; + for (i = con->index; i; i--) { + info = info->next; + if (!info) + return -ENODEV; + } info->is_console = 1; /* @@ -2487,7 +2449,7 @@ if (i & CBAUDEX) { i &= ~(CBAUDEX); if ((i < 1) || ((i + 15) >= NR_EBRG_VALUES)) - info->tty->termios->c_cflag &= ~CBAUDEX; + cflag &= ~CBAUDEX; else i += 15; } @@ -2565,4 +2527,36 @@ return 0; } +#ifdef SERIAL_LOG_DEVICE + +static int serial_log_device = 0; + +static void +dprint_init(int tty) +{ + serial_console = tty + 1; + sab82532_console.index = tty; + sab82532_console_setup(&sab82532_console, ""); + serial_console = 0; + serial_log_device = tty + 1; +} + +int +dprintf(const char *fmt, ...) +{ + static char buffer[4096]; + va_list args; + int i; + + if (!serial_log_device) + return 0; + + va_start(args, fmt); + i = vsprintf(buffer, fmt, args); + va_end(args); + sab82532_console.write(&sab82532_console, buffer, i); + return i; +} +#endif /* SERIAL_LOG_DEVICE */ #endif /* CONFIG_SERIAL_CONSOLE */ + diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/char/su32.c linux/drivers/sbus/char/su32.c --- v2.1.123/linux/drivers/sbus/char/su32.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/sbus/char/su32.c Sun Oct 4 10:22:44 1998 @@ -0,0 +1,3565 @@ +/* $Id: su32.c,v 1.1 1998/09/18 10:45:32 jj Exp $ + * su.c: Small serial driver for keyboard/mouse interface on sparc32/PCI + * + * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) + * Coypright (C) 1998 Pete Zaitcev (zaitcev@metabyte.com) + * + * This is mainly a variation of drivers/char/serial.c, + * credits go to authors mentioned therein. + */ + +/* + * Configuration section. + */ +#define SERIAL_PARANOIA_CHECK +#define CONFIG_SERIAL_NOPAUSE_IO /* Unused on sparc */ +#define SERIAL_DO_RESTART + +#if 1 +/* Normally these defines are controlled by the autoconf.h */ + +#undef CONFIG_SERIAL_MANY_PORTS +#define CONFIG_SERIAL_SHARE_IRQ /* Must be enabled for MrCoffee. */ +#undef CONFIG_SERIAL_DETECT_IRQ /* code is removed from su.c */ +#undef CONFIG_SERIAL_MULTIPORT +#endif + +/* Sanity checks */ + +#ifdef CONFIG_SERIAL_MULTIPORT +#ifndef CONFIG_SERIAL_SHARE_IRQ +#define CONFIG_SERIAL_SHARE_IRQ +#endif +#endif + +/* Set of debugging defines */ + +#undef SERIAL_DEBUG_INTR +#undef SERIAL_DEBUG_OPEN +#undef SERIAL_DEBUG_FLOW +#undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT +#undef SERIAL_DEBUG_THROTTLE + +/* */ + +#define RS_STROBE_TIME (10*HZ) +#define RS_ISR_PASS_LIMIT 256 + +#ifdef __sparc_v9__ +#define IRQ_4M(n) (n) +#define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT) +#else +/* 0x20 is sun4m thing, Dave Redman heritage. See arch/sparc/kernel/irq.c. */ +#define IRQ_4M(n) ((n)|0x20) +/* Interrupts must be shared on MrCoffee. */ +#define IRQ_T(info) SA_SHIRQ +#endif + +#define SERIAL_INLINE + +#if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT) +#define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \ + kdevname(tty->device), (info->flags), serial_refcount,info->count,tty->count,s) +#else +#define DBG_CNT(s) +#endif + +/* + * End of serial driver configuration section. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_SERIAL_CONSOLE +#include +#include +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#if 0 /* P3: Needed if we to support /sbin/setserial. */ +#include +#endif + +#include "sunserial.h" +#include "sunkbd.h" +#include "sunmouse.h" + +/* We are on a NS PC87303 clocked with 24.0 MHz, which results + * in a UART clock of 1.8462 MHz. + */ +#define BAUD_BASE (1846200 / 16) + +#ifdef CONFIG_SERIAL_CONSOLE +extern int serial_console; +static struct console sercons; +int su_serial_console_init(void); +#endif + +/* + * serial.c saves memory when it allocates async_info upon first open. + * We have parts of state structure together because we do call startup + * for keyboard and mouse. + */ +struct su_struct { + int magic; + unsigned long port; + int baud_base; + int type; /* Hardware type: e.g. 16550 */ + int irq; + int flags; + int line; + int cflag; + + /* XXX Unify. */ + int kbd_node; + int ms_node; + int port_node; + + char name[16]; + + int xmit_fifo_size; + int custom_divisor; + unsigned short close_delay; + unsigned short closing_wait; /* time to wait before closing */ + unsigned short closing_wait2; /* no longer used... */ + + struct tty_struct *tty; + int read_status_mask; + int ignore_status_mask; + int timeout; + int quot; + int x_char; /* xon/xoff character */ + int IER; /* Interrupt Enable Register */ + int MCR; /* Modem control register */ + unsigned long event; + int blocked_open; /* # of blocked opens */ + long session; /* Session of opening process */ + long pgrp; /* pgrp of opening process */ + unsigned char *xmit_buf; + int xmit_head; + int xmit_tail; + int xmit_cnt; + struct tq_struct tqueue; + struct wait_queue *open_wait; + struct wait_queue *close_wait; + struct wait_queue *delta_msr_wait; + + struct su_struct *next_port; + struct su_struct *prev_port; + + int count; + struct async_icount icount; + struct termios normal_termios, callout_termios; + unsigned long last_active; /* For async_struct, to be */ +}; + +#if 0 /* P3: became unused after surgery. */ +/* + * This is used to figure out the divisor speeds and the timeouts + */ +static int baud_table[] = { + 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, + 9600, 19200, 38400, 57600, 115200, 230400, 460800, 0 }; +#endif + +#ifdef SERIAL_INLINE +#define _INLINE_ inline +#endif + +static char *serial_name = "Serial driver"; +static char *serial_version = "4.25.s1"; + +static DECLARE_TASK_QUEUE(tq_serial); + +static struct tty_driver serial_driver, callout_driver; +static int serial_refcount; + +/* number of characters left in xmit buffer before we ask for more */ +#define WAKEUP_CHARS 256 + +/* + * IRQ_timeout - How long the timeout should be for each IRQ + * should be after the IRQ has been active. + */ +static struct su_struct *IRQ_ports[NR_IRQS]; +#ifdef CONFIG_SERIAL_MULTIPORT +static struct rs_multiport_struct rs_multiport[NR_IRQS]; +#endif +static int IRQ_timeout[NR_IRQS]; + +static void autoconfig(struct su_struct *info); +static void change_speed(struct su_struct *info); +static void su_wait_until_sent(struct tty_struct *tty, int timeout); + +/* + * Here we define the default xmit fifo size used for each type of + * UART + */ +static struct serial_uart_config uart_config[] = { + { "unknown", 1, 0 }, + { "8250", 1, 0 }, + { "16450", 1, 0 }, + { "16550", 1, 0 }, + { "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO }, + { "cirrus", 1, 0 }, + { "ST16650", 1, UART_CLEAR_FIFO |UART_STARTECH }, + { "ST16650V2", 32, UART_CLEAR_FIFO | UART_USE_FIFO | + UART_STARTECH }, + { "TI16750", 64, UART_CLEAR_FIFO | UART_USE_FIFO}, + { 0, 0} +}; + + +#define NR_PORTS 4 + +static struct su_struct su_table[NR_PORTS]; +static struct tty_struct *serial_table[NR_PORTS]; +static struct termios *serial_termios[NR_PORTS]; +static struct termios *serial_termios_locked[NR_PORTS]; + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +/* + * tmp_buf is used as a temporary buffer by serial_write. We need to + * lock it in case the copy_from_user blocks while swapping in a page, + * and some other program tries to do a serial write at the same time. + * Since the lock will only come under contention when the system is + * swapping and available memory is low, it makes sense to share one + * buffer across all the serial ports, since it significantly saves + * memory if large numbers of serial ports are open. + */ +static unsigned char *tmp_buf; +static struct semaphore tmp_buf_sem = MUTEX; + +static inline int serial_paranoia_check(struct su_struct *info, + kdev_t device, const char *routine) +{ +#ifdef SERIAL_PARANOIA_CHECK + static const char *badmagic = + "Warning: bad magic number for serial struct (%s) in %s\n"; + static const char *badinfo = + "Warning: null su_struct for (%s) in %s\n"; + + if (!info) { + printk(badinfo, kdevname(device), routine); + return 1; + } + if (info->magic != SERIAL_MAGIC) { + printk(badmagic, kdevname(device), routine); + return 1; + } +#endif + return 0; +} + +#ifdef __sparc_v9__ + +static inline +unsigned int su_inb(struct su_struct *info, unsigned long offset) +{ + return inb(info->port + offset); +} + +static inline void +su_outb(struct su_struct *info, unsigned long offset, int value) +{ + outb(value, info->port + offset); +} + +#else + +static inline +unsigned int su_inb(struct su_struct *info, unsigned long offset) +{ + return (unsigned int)(*(volatile unsigned char *)(info->port + offset)); +} + +static inline void +su_outb(struct su_struct *info, unsigned long offset, int value) +{ + /* + * MrCoffee has weird schematics: IRQ4 & P10(?) pins of SuperIO are + * connected with a gate then go to SlavIO. When IRQ4 goes tristated + * gate gives logical one. Since we use level triggered interrupts + * we have lockup and watchdog reset. We cannot mask IRQ because + * keyboard shares IRQ with us (Bob Smelik: I would not hire you). + * P3: Assure that OUT2 never goes down. + */ + if (offset == UART_MCR) value |= UART_MCR_OUT2; + *(volatile unsigned char *)(info->port + offset) = value; +} + +#endif + +#define serial_in(info, off) su_inb(info, off) +#define serial_inp(info, off) su_inb(info, off) +#define serial_out(info, off, val) su_outb(info, off, val) +#define serial_outp(info, off, val) su_outb(info, off, val) + +/* + * ------------------------------------------------------------ + * su_stop() and su_start() + * + * This routines are called before setting or resetting tty->stopped. + * They enable or disable transmitter interrupts, as necessary. + * ------------------------------------------------------------ + */ +static void su_stop(struct tty_struct *tty) +{ + struct su_struct *info = (struct su_struct *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "su_stop")) + return; + + save_flags(flags); cli(); + if (info->IER & UART_IER_THRI) { + info->IER &= ~UART_IER_THRI; + serial_out(info, UART_IER, info->IER); + } + restore_flags(flags); +} + +static void su_start(struct tty_struct *tty) +{ + struct su_struct *info = (struct su_struct *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "su_start")) + return; + + save_flags(flags); cli(); + if (info->xmit_cnt && info->xmit_buf && !(info->IER & UART_IER_THRI)) { + info->IER |= UART_IER_THRI; + serial_out(info, UART_IER, info->IER); + } + restore_flags(flags); +} + +/* + * ---------------------------------------------------------------------- + * + * Here starts the interrupt handling routines. All of the following + * subroutines are declared as inline and are folded into + * su_interrupt(). They were separated out for readability's sake. + * + * Note: rs_interrupt() is a "fast" interrupt, which means that it + * runs with interrupts turned off. People who may want to modify + * rs_interrupt() should try to keep the interrupt handler as fast as + * possible. After you are done making modifications, it is not a bad + * idea to do: + * + * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c + * + * and look at the resulting assemble code in serial.s. + * + * - Ted Ts'o (tytso@mit.edu), 7-Mar-93 + * ----------------------------------------------------------------------- + */ + +/* + * This routine is used by the interrupt handler to schedule + * processing in the software interrupt portion of the driver. + */ +static _INLINE_ void su_sched_event(struct su_struct *info, int event) +{ + info->event |= 1 << event; + queue_task(&info->tqueue, &tq_serial); + mark_bh(SERIAL_BH); +} + +static _INLINE_ void receive_chars(struct su_struct *info, int *status, + struct pt_regs *regs) +{ + struct tty_struct *tty = info->tty; + unsigned char ch; + int ignored = 0; + struct async_icount *icount; + + icount = &info->icount; + do { + ch = serial_inp(info, UART_RX); + if (info->kbd_node) { + if(ch == SUNKBD_RESET) { + l1a_state.kbd_id = 1; + l1a_state.l1_down = 0; + } else if(l1a_state.kbd_id) { + l1a_state.kbd_id = 0; + } else if(ch == SUNKBD_L1) { + l1a_state.l1_down = 1; + } else if(ch == (SUNKBD_L1|SUNKBD_UP)) { + l1a_state.l1_down = 0; + } else if(ch == SUNKBD_A && l1a_state.l1_down) { + /* whee... */ + batten_down_hatches(); + /* Continue execution... */ + l1a_state.l1_down = 0; + l1a_state.kbd_id = 0; + return; + } + sunkbd_inchar(ch, regs); + } else { + sun_mouse_inbyte(ch); + } + if (tty->flip.count >= TTY_FLIPBUF_SIZE) + break; + *tty->flip.char_buf_ptr = ch; + icount->rx++; + +#ifdef SERIAL_DEBUG_INTR + printk("DR%02x:%02x...", ch, *status); +#endif + *tty->flip.flag_buf_ptr = 0; + if (*status & (UART_LSR_BI | UART_LSR_PE | + UART_LSR_FE | UART_LSR_OE)) { + /* + * For statistics only + */ + if (*status & UART_LSR_BI) { + *status &= ~(UART_LSR_FE | UART_LSR_PE); + icount->brk++; + } else if (*status & UART_LSR_PE) + icount->parity++; + else if (*status & UART_LSR_FE) + icount->frame++; + if (*status & UART_LSR_OE) + icount->overrun++; + + /* + * Now check to see if character should be + * ignored, and mask off conditions which + * should be ignored. + */ + if (*status & info->ignore_status_mask) { + if (++ignored > 100) + break; + goto ignore_char; + } + *status &= info->read_status_mask; + + if (*status & (UART_LSR_BI)) { +#ifdef SERIAL_DEBUG_INTR + printk("handling break...."); +#endif + *tty->flip.flag_buf_ptr = TTY_BREAK; + if (info->flags & ASYNC_SAK) + do_SAK(tty); + } else if (*status & UART_LSR_PE) + *tty->flip.flag_buf_ptr = TTY_PARITY; + else if (*status & UART_LSR_FE) + *tty->flip.flag_buf_ptr = TTY_FRAME; + if (*status & UART_LSR_OE) { + /* + * Overrun is special, since it's + * reported immediately, and doesn't + * affect the current character + */ + if (tty->flip.count < TTY_FLIPBUF_SIZE) { + tty->flip.count++; + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + *tty->flip.flag_buf_ptr = TTY_OVERRUN; + } + } + } + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + tty->flip.count++; + ignore_char: + *status = serial_inp(info, UART_LSR); + } while (*status & UART_LSR_DR); + tty_flip_buffer_push(tty); +} + +static _INLINE_ void transmit_chars(struct su_struct *info, int *intr_done) +{ + int count; + + if (info->x_char) { + serial_outp(info, UART_TX, info->x_char); + info->icount.tx++; + info->x_char = 0; + if (intr_done) + *intr_done = 0; + return; + } + if ((info->xmit_cnt <= 0) || info->tty->stopped || + info->tty->hw_stopped) { + info->IER &= ~UART_IER_THRI; + serial_out(info, UART_IER, info->IER); + return; + } + + count = info->xmit_fifo_size; + do { + serial_out(info, UART_TX, info->xmit_buf[info->xmit_tail++]); + info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); + info->icount.tx++; + if (--info->xmit_cnt <= 0) + break; + } while (--count > 0); + + if (info->xmit_cnt < WAKEUP_CHARS) + su_sched_event(info, RS_EVENT_WRITE_WAKEUP); + +#ifdef SERIAL_DEBUG_INTR + printk("THRE..."); +#endif + if (intr_done) + *intr_done = 0; + + if (info->xmit_cnt <= 0) { + info->IER &= ~UART_IER_THRI; + serial_out(info, UART_IER, info->IER); + } +} + +static _INLINE_ void check_modem_status(struct su_struct *info) +{ + int status; + struct async_icount *icount; + + status = serial_in(info, UART_MSR); + + if (status & UART_MSR_ANY_DELTA) { + icount = &info->icount; + /* update input line counters */ + if (status & UART_MSR_TERI) + icount->rng++; + if (status & UART_MSR_DDSR) + icount->dsr++; + if (status & UART_MSR_DDCD) { + icount->dcd++; +#ifdef CONFIG_HARD_PPS + if ((info->flags & ASYNC_HARDPPS_CD) && + (status & UART_MSR_DCD)) + hardpps(); +#endif + } + if (status & UART_MSR_DCTS) + icount->cts++; + wake_up_interruptible(&info->delta_msr_wait); + } + + if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) { +#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR)) + printk("ttys%d CD now %s...", info->line, + (status & UART_MSR_DCD) ? "on" : "off"); +#endif + if (status & UART_MSR_DCD) + wake_up_interruptible(&info->open_wait); + else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) && + (info->flags & ASYNC_CALLOUT_NOHUP))) { +#ifdef SERIAL_DEBUG_OPEN + printk("doing serial hangup..."); +#endif + if (info->tty) + tty_hangup(info->tty); + } + } + if (info->flags & ASYNC_CTS_FLOW) { + if (info->tty->hw_stopped) { + if (status & UART_MSR_CTS) { +#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW)) + printk("CTS tx start..."); +#endif + info->tty->hw_stopped = 0; + info->IER |= UART_IER_THRI; + serial_out(info, UART_IER, info->IER); + su_sched_event(info, RS_EVENT_WRITE_WAKEUP); + return; + } + } else { + if (!(status & UART_MSR_CTS)) { +#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW)) + printk("CTS tx stop..."); +#endif + info->tty->hw_stopped = 1; + info->IER &= ~UART_IER_THRI; + serial_out(info, UART_IER, info->IER); + } + } + } +} + +#ifdef CONFIG_SERIAL_SHARE_IRQ +/* + * This is the serial driver's generic interrupt routine + */ +static void su_interrupt(int irq, void *dev_id, struct pt_regs * regs) +{ + int status; + struct su_struct *info; + int pass_counter = 0; + struct su_struct *end_mark = 0; +#ifdef CONFIG_SERIAL_MULTIPORT + int first_multi = 0; + struct su_multiport_struct *multi; +#endif + +#ifdef SERIAL_DEBUG_INTR + printk("su_interrupt(%s)...", __irq_itoa(irq)); +#endif + + info = IRQ_ports[irq]; + if (!info) + return; + +#ifdef CONFIG_SERIAL_MULTIPORT + multi = &rs_multiport[irq]; + if (multi->port_monitor) + first_multi = inb(multi->port_monitor); +#endif + + do { + if (!info->tty || + (serial_in(info, UART_IIR) & UART_IIR_NO_INT)) { + if (!end_mark) + end_mark = info; + goto next; + } + end_mark = 0; + + info->last_active = jiffies; + + status = serial_inp(info, UART_LSR); +#ifdef SERIAL_DEBUG_INTR + printk("status = %x...", status); +#endif + if (status & UART_LSR_DR) + receive_chars(info, &status, regs); + check_modem_status(info); + if (status & UART_LSR_THRE) + transmit_chars(info, 0); + + next: + info = info->next_port; + if (!info) { + info = IRQ_ports[irq]; + if (pass_counter++ > RS_ISR_PASS_LIMIT) { +#if 0 + printk("rs loop break\n"); +#endif + break; /* Prevent infinite loops */ + } + continue; + } + } while (end_mark != info); +#ifdef CONFIG_SERIAL_MULTIPORT + if (multi->port_monitor) + printk("rs port monitor (normal) irq %d: 0x%x, 0x%x\n", + info->irq, first_multi, + inb(multi->port_monitor)); +#endif +#ifdef SERIAL_DEBUG_INTR + printk("end.\n"); +#endif +} +#endif /* #ifdef CONFIG_SERIAL_SHARE_IRQ */ + + +/* + * This is the serial driver's interrupt routine for a single port + */ +static void su_interrupt_single(int irq, void *dev_id, struct pt_regs * regs) +{ + int status; + int pass_counter = 0; + struct su_struct * info; +#ifdef CONFIG_SERIAL_MULTIPORT + int first_multi = 0; + struct rs_multiport_struct *multi; +#endif + +#ifdef SERIAL_DEBUG_INTR + printk("su_interrupt_single(%d) int=%x ...", irq, + serial_inp(&su_table[0], UART_IIR)); +#endif + + info = IRQ_ports[irq]; + if (!info || !info->tty) + return; + +#ifdef CONFIG_SERIAL_MULTIPORT + multi = &rs_multiport[irq]; + if (multi->port_monitor) + first_multi = inb(multi->port_monitor); +#endif + + do { + status = serial_inp(info, UART_LSR); +#ifdef SERIAL_DEBUG_INTR + printk("status = %x...", status); +#endif + if (status & UART_LSR_DR) + receive_chars(info, &status, regs); + check_modem_status(info); + if (status & UART_LSR_THRE) + transmit_chars(info, 0); + if (pass_counter++ > RS_ISR_PASS_LIMIT) { +#if 0 + printk("su_single loop break.\n"); +#endif + break; + } + } while (!(serial_in(info, UART_IIR) & UART_IIR_NO_INT)); + info->last_active = jiffies; +#ifdef CONFIG_SERIAL_MULTIPORT + if (multi->port_monitor) + printk("rs port monitor (single) irq %s: 0x%x, 0x%x\n", + __irq_itoa(info->irq), first_multi, + inb(multi->port_monitor)); +#endif +#ifdef SERIAL_DEBUG_INTR + printk("end.\n"); +#endif +} + +#ifdef CONFIG_SERIAL_MULTIPORT +/* + * This is the serial driver's for multiport boards + */ +static void su_interrupt_multi(int irq, void *dev_id, struct pt_regs * regs) +{ + int status; + struct su_struct * info; + int pass_counter = 0; + int first_multi= 0; + struct rs_multiport_struct *multi; + +#ifdef SERIAL_DEBUG_INTR + printk("rs_interrupt_multi(%d)...", irq); +#endif + + info = IRQ_ports[irq]; + if (!info) + return; + multi = &rs_multiport[irq]; + if (!multi->port1) { + /* Should never happen */ + printk("rs_interrupt_multi: NULL port1!\n"); + return; + } + if (multi->port_monitor) + first_multi = inb(multi->port_monitor); + + while (1) { + if (!info->tty || + (serial_in(info, UART_IIR) & UART_IIR_NO_INT)) + goto next; + + info->last_active = jiffies; + + status = serial_inp(info, UART_LSR); +#ifdef SERIAL_DEBUG_INTR + printk("status = %x...", status); +#endif + if (status & UART_LSR_DR) + receive_chars(info, &status, regs); + check_modem_status(info); + if (status & UART_LSR_THRE) + transmit_chars(info, 0); + + next: + info = info->next_port; + if (info) + continue; + + info = IRQ_ports[irq]; + if (pass_counter++ > RS_ISR_PASS_LIMIT) { +#if 1 + printk("rs_multi loop break\n"); +#endif + break; /* Prevent infinite loops */ + } + if (multi->port_monitor) + printk("rs port monitor irq %d: 0x%x, 0x%x\n", + info->irq, first_multi, + inb(multi->port_monitor)); + if ((inb(multi->port1) & multi->mask1) != multi->match1) + continue; + if (!multi->port2) + break; + if ((inb(multi->port2) & multi->mask2) != multi->match2) + continue; + if (!multi->port3) + break; + if ((inb(multi->port3) & multi->mask3) != multi->match3) + continue; + if (!multi->port4) + break; + if ((inb(multi->port4) & multi->mask4) == multi->match4) + continue; + break; + } +#ifdef SERIAL_DEBUG_INTR + printk("end.\n"); +#endif +} +#endif + +/* + * ------------------------------------------------------------------- + * Here ends the serial interrupt routines. + * ------------------------------------------------------------------- + */ + +/* + * This routine is used to handle the "bottom half" processing for the + * serial driver, known also the "software interrupt" processing. + * This processing is done at the kernel interrupt level, after the + * su_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This + * is where time-consuming activities which can not be done in the + * interrupt driver proper are done; the interrupt driver schedules + * them using su_sched_event(), and they get done here. + */ +static void do_serial_bh(void) +{ + run_task_queue(&tq_serial); +} + +static void do_softint(void *private_) +{ + struct su_struct *info = (struct su_struct *) private_; + struct tty_struct *tty; + + tty = info->tty; + if (!tty) + return; + + if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) { + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); + wake_up_interruptible(&tty->write_wait); + } +} + +/* + * This subroutine is called when the RS_TIMER goes off. It is used + * by the serial driver to handle ports that do not have an interrupt + * (irq=0). This doesn't work very well for 16450's, but gives barely + * passable results for a 16550A. (Although at the expense of much + * CPU overhead). + */ +static void su_timer(void) +{ + static unsigned long last_strobe = 0; + struct su_struct *info; + unsigned int i; + + if ((jiffies - last_strobe) >= RS_STROBE_TIME) { + for (i=1; i < NR_IRQS; i++) { + info = IRQ_ports[i]; + if (!info) + continue; + cli(); +#ifdef CONFIG_SERIAL_SHARE_IRQ + if (info->next_port) { + do { + serial_out(info, UART_IER, 0); + info->IER |= UART_IER_THRI; + serial_out(info, UART_IER, info->IER); + info = info->next_port; + } while (info); +#ifdef CONFIG_SERIAL_MULTIPORT + if (rs_multiport[i].port1) + rs_interrupt_multi(i, NULL, NULL); + else +#endif + su_interrupt(i, NULL, NULL); + } else +#endif /* CONFIG_SERIAL_SHARE_IRQ */ + su_interrupt_single(i, NULL, NULL); + sti(); + } + } + last_strobe = jiffies; + timer_table[RS_TIMER].expires = jiffies + RS_STROBE_TIME; + timer_active |= 1 << RS_TIMER; + + if (IRQ_ports[0]) { + cli(); +#ifdef CONFIG_SERIAL_SHARE_IRQ + su_interrupt(0, NULL, NULL); +#else + su_interrupt_single(0, NULL, NULL); +#endif + sti(); + + timer_table[RS_TIMER].expires = jiffies + IRQ_timeout[0] - 2; + } +} + +/* + * --------------------------------------------------------------- + * Low level utility subroutines for the serial driver: routines to + * figure out the appropriate timeout for an interrupt chain, routines + * to initialize and startup a serial port, and routines to shutdown a + * serial port. Useful stuff like that. + * --------------------------------------------------------------- + */ + +/* + * This routine figures out the correct timeout for a particular IRQ. + * It uses the smallest timeout of all of the serial ports in a + * particular interrupt chain. Now only used for IRQ 0.... + */ +static void figure_IRQ_timeout(int irq) +{ + struct su_struct *info; + int timeout = 60*HZ; /* 60 seconds === a long time :-) */ + + info = IRQ_ports[irq]; + if (!info) { + IRQ_timeout[irq] = 60*HZ; + return; + } + while (info) { + if (info->timeout < timeout) + timeout = info->timeout; + info = info->next_port; + } + if (!irq) + timeout = timeout / 2; + IRQ_timeout[irq] = timeout ? timeout : 1; +} + +static int startup(struct su_struct *info) +{ + unsigned long flags; + int retval=0; + void (*handler)(int, void *, struct pt_regs *); + unsigned long page; +#ifdef CONFIG_SERIAL_MANY_PORTS + unsigned short ICP; +#endif + + page = get_free_page(GFP_KERNEL); + if (!page) + return -ENOMEM; + + save_flags(flags); cli(); + + if (info->flags & ASYNC_INITIALIZED) { + free_page(page); + goto errout; + } + + if (info->port == 0 || info->type == PORT_UNKNOWN) { + if (info->tty) + set_bit(TTY_IO_ERROR, &info->tty->flags); + free_page(page); + goto errout; + } + if (info->xmit_buf) + free_page(page); + else + info->xmit_buf = (unsigned char *) page; + + if (uart_config[info->type].flags & UART_STARTECH) { + /* Wake up UART */ + serial_outp(info, UART_LCR, 0xBF); + serial_outp(info, UART_EFR, UART_EFR_ECB); + serial_outp(info, UART_IER, 0); + serial_outp(info, UART_EFR, 0); + serial_outp(info, UART_LCR, 0); + } + + if (info->type == PORT_16750) { + /* Wake up UART */ + serial_outp(info, UART_IER, 0); + } + + /* + * Clear the FIFO buffers and disable them + * (they will be reenabled in change_speed()) + */ + if (uart_config[info->type].flags & UART_CLEAR_FIFO) + serial_outp(info, UART_FCR, (UART_FCR_CLEAR_RCVR | + UART_FCR_CLEAR_XMIT)); + + /* + * At this point there's no way the LSR could still be 0xFF; + * if it is, then bail out, because there's likely no UART + * here. + */ + if (serial_inp(info, UART_LSR) == 0xff) { + if (capable(CAP_SYS_ADMIN)) { + if (info->tty) + set_bit(TTY_IO_ERROR, &info->tty->flags); + } else + retval = -ENODEV; + goto errout; + } + + /* + * Allocate the IRQ if necessary + */ + if (info->irq && (!IRQ_ports[info->irq] || + !IRQ_ports[info->irq]->next_port)) { + if (IRQ_ports[info->irq]) { +#ifdef CONFIG_SERIAL_SHARE_IRQ + free_irq(IRQ_4M(info->irq), info); +#ifdef CONFIG_SERIAL_MULTIPORT + if (rs_multiport[info->irq].port1) + handler = rs_interrupt_multi; + else +#endif + handler = su_interrupt; +#else + retval = -EBUSY; + goto errout; +#endif /* CONFIG_SERIAL_SHARE_IRQ */ + } else + handler = su_interrupt_single; + + retval = request_irq(IRQ_4M(info->irq), handler, IRQ_T(info), + "serial", info); + if (retval) { + if (capable(CAP_SYS_ADMIN)) { + if (info->tty) + set_bit(TTY_IO_ERROR, + &info->tty->flags); + retval = 0; + } + goto errout; + } + } + + /* + * Insert serial port into IRQ chain. + */ + info->prev_port = 0; + info->next_port = IRQ_ports[info->irq]; + if (info->next_port) + info->next_port->prev_port = info; + IRQ_ports[info->irq] = info; + figure_IRQ_timeout(info->irq); + + /* + * Clear the interrupt registers. + */ + /* (void) serial_inp(info, UART_LSR); */ /* (see above) */ + (void) serial_inp(info, UART_RX); + (void) serial_inp(info, UART_IIR); + (void) serial_inp(info, UART_MSR); + + /* + * Now, initialize the UART + */ + serial_outp(info, UART_LCR, UART_LCR_WLEN8); /* reset DLAB */ + + info->MCR = 0; + if (info->tty->termios->c_cflag & CBAUD) + info->MCR = UART_MCR_DTR | UART_MCR_RTS; +#ifdef CONFIG_SERIAL_MANY_PORTS + if (info->flags & ASYNC_FOURPORT) { + if (info->irq == 0) + info->MCR |= UART_MCR_OUT1; + } else +#endif + { + if (info->irq != 0) + info->MCR |= UART_MCR_OUT2; + } +#if defined(__alpha__) && !defined(CONFIG_PCI) + /* + * DEC did something gratutiously wrong.... + */ + info->MCR |= UART_MCR_OUT1 | UART_MCR_OUT2; +#endif + serial_outp(info, UART_MCR, info->MCR); + + /* + * Finally, enable interrupts + */ + info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI; + serial_outp(info, UART_IER, info->IER); /* enable interrupts */ + +#ifdef CONFIG_SERIAL_MANY_PORTS + if (info->flags & ASYNC_FOURPORT) { + /* Enable interrupts on the AST Fourport board */ + ICP = (info->port & 0xFE0) | 0x01F; + outb_p(0x80, ICP); + (void) inb_p(ICP); + } +#endif + + /* + * And clear the interrupt registers again for luck. + */ + (void)serial_inp(info, UART_LSR); + (void)serial_inp(info, UART_RX); + (void)serial_inp(info, UART_IIR); + (void)serial_inp(info, UART_MSR); + + if (info->tty) + clear_bit(TTY_IO_ERROR, &info->tty->flags); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + + /* + * Set up serial timers... + */ + timer_table[RS_TIMER].expires = jiffies + 2*HZ/100; + timer_active |= 1 << RS_TIMER; + + /* + * Set up the tty->alt_speed kludge + */ + if (info->tty) { + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) + info->tty->alt_speed = 57600; + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) + info->tty->alt_speed = 115200; + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) + info->tty->alt_speed = 230400; + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) + info->tty->alt_speed = 460800; + } + + /* + * and set the speed of the serial port + */ + change_speed(info); + + info->flags |= ASYNC_INITIALIZED; + restore_flags(flags); + return 0; + +errout: + restore_flags(flags); + return retval; +} + +/* + * This routine will shutdown a serial port; interrupts are disabled, and + * DTR is dropped if the hangup on close termio flag is on. + */ +static void shutdown(struct su_struct *info) +{ + unsigned long flags; + int retval; + + if (!(info->flags & ASYNC_INITIALIZED)) + return; + + save_flags(flags); cli(); /* Disable interrupts */ + + /* + * clear delta_msr_wait queue to avoid mem leaks: we may free the irq + * here so the queue might never be waken up + */ + wake_up_interruptible(&info->delta_msr_wait); + + /* + * First unlink the serial port from the IRQ chain... + */ + if (info->next_port) + info->next_port->prev_port = info->prev_port; + if (info->prev_port) + info->prev_port->next_port = info->next_port; + else + IRQ_ports[info->irq] = info->next_port; + figure_IRQ_timeout(info->irq); + + /* + * Free the IRQ, if necessary + */ + if (info->irq && (!IRQ_ports[info->irq] || + !IRQ_ports[info->irq]->next_port)) { + if (IRQ_ports[info->irq]) { + free_irq(IRQ_4M(info->irq), info); + retval = request_irq(IRQ_4M(info->irq), + su_interrupt_single, IRQ_T(info), "serial", info); + + if (retval) + printk("serial shutdown: request_irq: error %d" + " Couldn't reacquire IRQ.\n", retval); + } else + free_irq(IRQ_4M(info->irq), info); + } + + if (info->xmit_buf) { + free_page((unsigned long) info->xmit_buf); + info->xmit_buf = 0; + } + + info->IER = 0; + serial_outp(info, UART_IER, 0x00); /* disable all intrs */ +#ifdef CONFIG_SERIAL_MANY_PORTS + if (info->flags & ASYNC_FOURPORT) { + /* reset interrupts on the AST Fourport board */ + (void) inb((info->port & 0xFE0) | 0x01F); + info->MCR |= UART_MCR_OUT1; + } else +#endif + info->MCR &= ~UART_MCR_OUT2; +#if defined(__alpha__) && !defined(CONFIG_PCI) + /* + * DEC did something gratutiously wrong.... + */ + info->MCR |= UART_MCR_OUT1 | UART_MCR_OUT2; +#endif + + /* disable break condition */ + serial_out(info, UART_LCR, serial_inp(info, UART_LCR) & ~UART_LCR_SBC); + + if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) + info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS); + serial_outp(info, UART_MCR, info->MCR); + + /* disable FIFO's */ + serial_outp(info, UART_FCR, (UART_FCR_CLEAR_RCVR | + UART_FCR_CLEAR_XMIT)); + (void)serial_in(info, UART_RX); /* read data port to reset things */ + + if (info->tty) + set_bit(TTY_IO_ERROR, &info->tty->flags); + + if (uart_config[info->type].flags & UART_STARTECH) { + /* Arrange to enter sleep mode */ + serial_outp(info, UART_LCR, 0xBF); + serial_outp(info, UART_EFR, UART_EFR_ECB); + serial_outp(info, UART_IER, UART_IERX_SLEEP); + serial_outp(info, UART_LCR, 0); + } + if (info->type == PORT_16750) { + /* Arrange to enter sleep mode */ + serial_outp(info, UART_IER, UART_IERX_SLEEP); + } + info->flags &= ~ASYNC_INITIALIZED; + restore_flags(flags); +} + +/* + * This routine is called to set the UART divisor registers to match + * the specified baud rate for a serial port. + */ +static void change_speed(struct su_struct *info) +{ + unsigned short port; + int quot = 0, baud_base, baud; + unsigned cflag, cval, fcr = 0; + int bits; + unsigned long flags; + + if (!info->tty || !info->tty->termios) + return; + cflag = info->tty->termios->c_cflag; + if (!(port = info->port)) + return; + + /* byte size and parity */ + switch (cflag & CSIZE) { + case CS5: cval = 0x00; bits = 7; break; + case CS6: cval = 0x01; bits = 8; break; + case CS7: cval = 0x02; bits = 9; break; + case CS8: cval = 0x03; bits = 10; break; + /* Never happens, but GCC is too dumb to figure it out */ + default: cval = 0x00; bits = 7; break; + } + if (cflag & CSTOPB) { + cval |= 0x04; + bits++; + } + if (cflag & PARENB) { + cval |= UART_LCR_PARITY; + bits++; + } + if (!(cflag & PARODD)) + cval |= UART_LCR_EPAR; +#ifdef CMSPAR + if (cflag & CMSPAR) + cval |= UART_LCR_SPAR; +#endif + + /* Determine divisor based on baud rate */ + baud = tty_get_baud_rate(info->tty); + baud_base = info->baud_base; + if (baud == 38400 && + ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) + quot = info->custom_divisor; + else { + if (baud == 134) + /* Special case since 134 is really 134.5 */ + quot = (2*baud_base / 269); + else if (baud) + quot = baud_base / baud; + } + /* If the quotient is ever zero, default to 9600 bps */ + if (!quot) + quot = baud_base / 9600; + info->quot = quot; + info->timeout = ((info->xmit_fifo_size*HZ*bits*quot) / baud_base); + info->timeout += HZ/50; /* Add .02 seconds of slop */ + + /* Set up FIFO's */ + if (uart_config[info->type].flags & UART_USE_FIFO) { + if ((info->baud_base / quot) < 2400) + fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1; + else + fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8; + } + if (info->type == PORT_16750) + fcr |= UART_FCR7_64BYTE; + + /* CTS flow control flag and modem status interrupts */ + info->IER &= ~UART_IER_MSI; + if (info->flags & ASYNC_HARDPPS_CD) + info->IER |= UART_IER_MSI; + if (cflag & CRTSCTS) { + info->flags |= ASYNC_CTS_FLOW; + info->IER |= UART_IER_MSI; + } else + info->flags &= ~ASYNC_CTS_FLOW; + if (cflag & CLOCAL) + info->flags &= ~ASYNC_CHECK_CD; + else { + info->flags |= ASYNC_CHECK_CD; + info->IER |= UART_IER_MSI; + } + serial_out(info, UART_IER, info->IER); + + /* + * Set up parity check flag + */ +#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) + + info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; + if (I_INPCK(info->tty)) + info->read_status_mask |= UART_LSR_FE | UART_LSR_PE; + if (I_BRKINT(info->tty) || I_PARMRK(info->tty)) + info->read_status_mask |= UART_LSR_BI; + + /* + * Characters to ignore + */ + info->ignore_status_mask = 0; + if (I_IGNPAR(info->tty)) + info->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; + if (I_IGNBRK(info->tty)) { + info->ignore_status_mask |= UART_LSR_BI; + /* + * If we're ignore parity and break indicators, ignore + * overruns too. (For real raw support). + */ + if (I_IGNPAR(info->tty)) + info->ignore_status_mask |= UART_LSR_OE; + } + /* + * !!! ignore all characters if CREAD is not set + */ + if ((cflag & CREAD) == 0) + info->ignore_status_mask |= UART_LSR_DR; + save_flags(flags); cli(); + if (uart_config[info->type].flags & UART_STARTECH) { + serial_outp(info, UART_LCR, 0xBF); + serial_outp(info, UART_EFR, + (cflag & CRTSCTS) ? UART_EFR_CTS : 0); + } + serial_outp(info, UART_LCR, cval | UART_LCR_DLAB); /* set DLAB */ + serial_outp(info, UART_DLL, quot & 0xff); /* LS of divisor */ + serial_outp(info, UART_DLM, quot >> 8); /* MS of divisor */ + if (info->type == PORT_16750) + serial_outp(info, UART_FCR, fcr); /* set fcr */ + serial_outp(info, UART_LCR, cval); /* reset DLAB */ + if (info->type != PORT_16750) + serial_outp(info, UART_FCR, fcr); /* set fcr */ + restore_flags(flags); + info->quot = quot; +} + +static void su_put_char(struct tty_struct *tty, unsigned char ch) +{ + struct su_struct *info = (struct su_struct *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "su_put_char")) + return; + + if (!tty || !info->xmit_buf) + return; + + save_flags(flags); cli(); + if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1) { + restore_flags(flags); + return; + } + + info->xmit_buf[info->xmit_head++] = ch; + info->xmit_head &= SERIAL_XMIT_SIZE-1; + info->xmit_cnt++; + restore_flags(flags); +} + +static void su_put_char_kbd(unsigned char c) +{ + struct su_struct *info; + int i; + int lsr; + + for (i = 0, info = su_table; i < NR_PORTS; i++, info++) { + if (info->kbd_node != 0) + break; + } + if (i >= NR_PORTS) { + /* XXX P3: I would put a printk here but it may flood. */ + return; + } + + do { + lsr = serial_in(info, UART_LSR); + } while (!(lsr & UART_LSR_THRE)); + + /* Send the character out. */ + su_outb(info, UART_TX, c); +} + +static void su_change_mouse_baud(int baud) +{ + struct su_struct *info = su_table; + int i; + + for (i = 0, info = su_table; i < NR_PORTS; i++, info++) + if (info->kbd_node != 0) break; + if (i >= NR_PORTS) return; + + info->cflag &= ~(CBAUDEX | CBAUD); + switch(baud) { + case 1200: + info->cflag |= B1200; + break; + case 2400: + info->cflag |= B2400; + break; + case 4800: + info->cflag |= B4800; + break; + case 9600: + info->cflag |= B9600; + break; + default: + printk("su_change_mouse_baud: unknown baud rate %d, " + "defaulting to 1200\n", baud); + info->cflag |= 1200; + break; + } + change_speed(info); +} + +static void su_flush_chars(struct tty_struct *tty) +{ + struct su_struct *info = (struct su_struct *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "su_flush_chars")) + return; + + if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || + !info->xmit_buf) + return; + + save_flags(flags); cli(); + info->IER |= UART_IER_THRI; + serial_out(info, UART_IER, info->IER); + restore_flags(flags); +} + +static int su_write(struct tty_struct * tty, int from_user, + const unsigned char *buf, int count) +{ + int c, ret = 0; + struct su_struct *info = (struct su_struct *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "su_write")) + return 0; + + if (!tty || !info->xmit_buf || !tmp_buf) + return 0; + + save_flags(flags); + if (from_user) { + down(&tmp_buf_sem); + while (1) { + c = MIN(count, + MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + if (c <= 0) + break; + + c -= copy_from_user(tmp_buf, buf, c); + if (!c) { + if (!ret) + ret = -EFAULT; + break; + } + cli(); + c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); + info->xmit_head = ((info->xmit_head + c) & + (SERIAL_XMIT_SIZE-1)); + info->xmit_cnt += c; + restore_flags(flags); + buf += c; + count -= c; + ret += c; + } + up(&tmp_buf_sem); + } else { + while (1) { + cli(); + c = MIN(count, + MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + if (c <= 0) { + restore_flags(flags); + break; + } + memcpy(info->xmit_buf + info->xmit_head, buf, c); + info->xmit_head = ((info->xmit_head + c) & + (SERIAL_XMIT_SIZE-1)); + info->xmit_cnt += c; + restore_flags(flags); + buf += c; + count -= c; + ret += c; + } + } + if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped && + !(info->IER & UART_IER_THRI)) { + info->IER |= UART_IER_THRI; + serial_out(info, UART_IER, info->IER); + } + return ret; +} + +static int su_write_room(struct tty_struct *tty) +{ + struct su_struct *info = (struct su_struct *)tty->driver_data; + int ret; + + if (serial_paranoia_check(info, tty->device, "su_write_room")) + return 0; + ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; + if (ret < 0) + ret = 0; + return ret; +} + +static int su_chars_in_buffer(struct tty_struct *tty) +{ + struct su_struct *info = (struct su_struct *)tty->driver_data; + + if (serial_paranoia_check(info, tty->device, "su_chars_in_buffer")) + return 0; + return info->xmit_cnt; +} + +static void su_flush_buffer(struct tty_struct *tty) +{ + struct su_struct *info = (struct su_struct *)tty->driver_data; + + if (serial_paranoia_check(info, tty->device, "su_flush_buffer")) + return; + cli(); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + sti(); + wake_up_interruptible(&tty->write_wait); + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); +} + +/* + * This function is used to send a high-priority XON/XOFF character to + * the device + */ +static void su_send_xchar(struct tty_struct *tty, char ch) +{ + struct su_struct *info = (struct su_struct *)tty->driver_data; + + if (serial_paranoia_check(info, tty->device, "su_send_char")) + return; + + info->x_char = ch; + if (ch) { + /* Make sure transmit interrupts are on */ + info->IER |= UART_IER_THRI; + serial_out(info, UART_IER, info->IER); + } +} + +/* + * ------------------------------------------------------------ + * su_throttle() + * + * This routine is called by the upper-layer tty layer to signal that + * incoming characters should be throttled. + * ------------------------------------------------------------ + */ +static void su_throttle(struct tty_struct * tty) +{ + struct su_struct *info = (struct su_struct *)tty->driver_data; +#ifdef SERIAL_DEBUG_THROTTLE + char buf[64]; + + printk("throttle %s: %d....\n", tty_name(tty, buf), + tty->ldisc.chars_in_buffer(tty)); +#endif + + if (serial_paranoia_check(info, tty->device, "su_throttle")) + return; + + if (I_IXOFF(tty)) + su_send_xchar(tty, STOP_CHAR(tty)); + + if (tty->termios->c_cflag & CRTSCTS) + info->MCR &= ~UART_MCR_RTS; + + cli(); + serial_out(info, UART_MCR, info->MCR); + sti(); +} + +static void su_unthrottle(struct tty_struct * tty) +{ + struct su_struct *info = (struct su_struct *)tty->driver_data; +#ifdef SERIAL_DEBUG_THROTTLE + char buf[64]; + + printk("unthrottle %s: %d....\n", tty_name(tty, buf), + tty->ldisc.chars_in_buffer(tty)); +#endif + + if (serial_paranoia_check(info, tty->device, "su_unthrottle")) + return; + + if (I_IXOFF(tty)) { + if (info->x_char) + info->x_char = 0; + else + su_send_xchar(tty, START_CHAR(tty)); + } + if (tty->termios->c_cflag & CRTSCTS) + info->MCR |= UART_MCR_RTS; + cli(); + serial_out(info, UART_MCR, info->MCR); + sti(); +} + +/* + * ------------------------------------------------------------ + * su_ioctl() and friends + * ------------------------------------------------------------ + */ + +#if 0 +static int get_serial_info(struct su_struct * info, + struct serial_struct * retinfo) +{ + struct serial_struct tmp; + + if (!retinfo) + return -EFAULT; + memset(&tmp, 0, sizeof(tmp)); + tmp.type = info->type; + tmp.line = info->line; + tmp.port = info->port; + tmp.irq = info->irq; + tmp.flags = info->flags; + tmp.xmit_fifo_size = info->xmit_fifo_size; + tmp.baud_base = info->baud_base; + tmp.close_delay = info->close_delay; + tmp.closing_wait = info->closing_wait; + tmp.custom_divisor = info->custom_divisor; + tmp.hub6 = 0; + if (copy_to_user(retinfo,&tmp,sizeof(*retinfo))) + return -EFAULT; + return 0; +} + +static int set_serial_info(struct su_struct * info, + struct serial_struct * new_info) +{ + struct serial_struct new_serial; + struct serial_state old_state, *state; + unsigned int i,change_irq,change_port; + int retval = 0; + + if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) + return -EFAULT; + old_state = *state; + + change_irq = new_serial.irq != state->irq; + change_port = (new_serial.port != state->port); + + if (!capable(CAP_SYS_ADMIN)) { + if (change_irq || change_port || + (new_serial.baud_base != state->baud_base) || + (new_serial.type != state->type) || + (new_serial.close_delay != state->close_delay) || + (new_serial.xmit_fifo_size != state->xmit_fifo_size) || + ((new_serial.flags & ~ASYNC_USR_MASK) != + (state->flags & ~ASYNC_USR_MASK))) + return -EPERM; + state->flags = ((state->flags & ~ASYNC_USR_MASK) | + (new_serial.flags & ASYNC_USR_MASK)); + state->custom_divisor = new_serial.custom_divisor; + goto check_and_exit; + } + + new_serial.irq = irq_cannonicalize(new_serial.irq); + + if ((new_serial.irq >= NR_IRQS) || (new_serial.port > 0xffff) || + (new_serial.type < PORT_UNKNOWN) || (new_serial.type > PORT_MAX)) { + return -EINVAL; + } + + /* Make sure address is not already in use */ + if (new_serial.type) { + for (i = 0 ; i < NR_PORTS; i++) + if ((state != &su_table[i]) && + (su_table[i].port == new_serial.port) && + su_table[i].type) + return -EADDRINUSE; + } + + if ((change_port || change_irq) && (state->count > 1)) + return -EBUSY; + + /* + * OK, past this point, all the error checking has been done. + * At this point, we start making changes..... + */ + + state->baud_base = new_serial.baud_base; + state->flags = ((state->flags & ~ASYNC_FLAGS) | + (new_serial.flags & ASYNC_FLAGS)); + info->flags = ((state->flags & ~ASYNC_INTERNAL_FLAGS) | + (info->flags & ASYNC_INTERNAL_FLAGS)); + state->custom_divisor = new_serial.custom_divisor; + state->type = new_serial.type; + state->close_delay = new_serial.close_delay * HZ/100; + state->closing_wait = new_serial.closing_wait * HZ/100; + info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + info->xmit_fifo_size = state->xmit_fifo_size = + new_serial.xmit_fifo_size; + + release_region(state->port,8); + if (change_port || change_irq) { + /* + * We need to shutdown the serial port at the old + * port/irq combination. + */ + shutdown(info); + state->irq = new_serial.irq; + info->port = state->port = new_serial.port; + info->hub6 = state->hub6 = new_serial.hub6; + } + if (state->type != PORT_UNKNOWN) + request_region(state->port,8,"serial(set)"); + +check_and_exit: + if (!state->port || !state->type) + return 0; + if (state->type != old_state.type) + info->xmit_fifo_size = state->xmit_fifo_size = + uart_config[state->type].dfl_xmit_fifo_size; + if (state->flags & ASYNC_INITIALIZED) { + if (((old_state.flags & ASYNC_SPD_MASK) != + (state->flags & ASYNC_SPD_MASK)) || + (old_state.custom_divisor != state->custom_divisor)) { + if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) + info->tty->alt_speed = 57600; + if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) + info->tty->alt_speed = 115200; + if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) + info->tty->alt_speed = 230400; + if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) + info->tty->alt_speed = 460800; + change_speed(info); + } + } else + retval = startup(info); + return retval; +} +#endif + + +/* + * get_lsr_info - get line status register info + * + * Purpose: Let user call ioctl() to get info when the UART physically + * is emptied. On bus types like RS485, the transmitter must + * release the bus after transmitting. This must be done when + * the transmit shift register is empty, not be done when the + * transmit holding register is empty. This functionality + * allows an RS485 driver to be written in user space. + */ +static int get_lsr_info(struct su_struct * info, unsigned int *value) +{ + unsigned char status; + unsigned int result; + + cli(); + status = serial_in(info, UART_LSR); + sti(); + result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0); + return put_user(result,value); +} + + +static int get_modem_info(struct su_struct * info, unsigned int *value) +{ + unsigned char control, status; + unsigned int result; + + control = info->MCR; + cli(); + status = serial_in(info, UART_MSR); + sti(); + result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) + | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) +#ifdef TIOCM_OUT1 + | ((control & UART_MCR_OUT1) ? TIOCM_OUT1 : 0) + | ((control & UART_MCR_OUT2) ? TIOCM_OUT2 : 0) +#endif + | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) + | ((status & UART_MSR_RI) ? TIOCM_RNG : 0) + | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) + | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0); + return put_user(result,value); +} + +static int set_modem_info(struct su_struct * info, unsigned int cmd, + unsigned int *value) +{ + int error; + unsigned int arg; + + error = get_user(arg, value); + if (error) + return error; + switch (cmd) { + case TIOCMBIS: + if (arg & TIOCM_RTS) + info->MCR |= UART_MCR_RTS; + if (arg & TIOCM_DTR) + info->MCR |= UART_MCR_DTR; +#ifdef TIOCM_OUT1 + if (arg & TIOCM_OUT1) + info->MCR |= UART_MCR_OUT1; + if (arg & TIOCM_OUT2) + info->MCR |= UART_MCR_OUT2; +#endif + break; + case TIOCMBIC: + if (arg & TIOCM_RTS) + info->MCR &= ~UART_MCR_RTS; + if (arg & TIOCM_DTR) + info->MCR &= ~UART_MCR_DTR; +#ifdef TIOCM_OUT1 + if (arg & TIOCM_OUT1) + info->MCR &= ~UART_MCR_OUT1; + if (arg & TIOCM_OUT2) + info->MCR &= ~UART_MCR_OUT2; +#endif + break; + case TIOCMSET: + info->MCR = ((info->MCR & ~(UART_MCR_RTS | +#ifdef TIOCM_OUT1 + UART_MCR_OUT1 | + UART_MCR_OUT2 | +#endif + UART_MCR_DTR)) + | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0) +#ifdef TIOCM_OUT1 + | ((arg & TIOCM_OUT1) ? UART_MCR_OUT1 : 0) + | ((arg & TIOCM_OUT2) ? UART_MCR_OUT2 : 0) +#endif + | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0)); + break; + default: + return -EINVAL; + } + cli(); + serial_out(info, UART_MCR, info->MCR); + sti(); + return 0; +} + +#if 0 +static int do_autoconfig(struct su_struct * info) +{ + int retval; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (info->state->count > 1) + return -EBUSY; + + shutdown(info); + + autoconfig(info->state); + if ((info->state->flags & ASYNC_AUTO_IRQ) && (info->state->port != 0)) + info->state->irq = detect_uart_irq(info->state); + + retval = startup(info); + if (retval) + return retval; + return 0; +} +#endif + +/* + * su_break() --- routine which turns the break handling on or off + */ +static void su_break(struct tty_struct *tty, int break_state) +{ + struct su_struct * info = (struct su_struct *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "su_break")) + return; + + if (!info->port) + return; + save_flags(flags); cli(); + if (break_state == -1) + serial_out(info, UART_LCR, + serial_inp(info, UART_LCR) | UART_LCR_SBC); + else + serial_out(info, UART_LCR, + serial_inp(info, UART_LCR) & ~UART_LCR_SBC); + restore_flags(flags); +} + +#ifdef CONFIG_SERIAL_MULTIPORT +static int get_multiport_struct(struct su_struct * info, + struct serial_multiport_struct *retinfo) +{ + struct serial_multiport_struct ret; + struct rs_multiport_struct *multi; + + multi = &rs_multiport[info->state->irq]; + + ret.port_monitor = multi->port_monitor; + + ret.port1 = multi->port1; + ret.mask1 = multi->mask1; + ret.match1 = multi->match1; + + ret.port2 = multi->port2; + ret.mask2 = multi->mask2; + ret.match2 = multi->match2; + + ret.port3 = multi->port3; + ret.mask3 = multi->mask3; + ret.match3 = multi->match3; + + ret.port4 = multi->port4; + ret.mask4 = multi->mask4; + ret.match4 = multi->match4; + + ret.irq = info->state->irq; + + if (copy_to_user(retinfo,&ret,sizeof(*retinfo))) + return -EFAULT; + return 0; +} + +static int set_multiport_struct(struct su_struct * info, + struct serial_multiport_struct *in_multi) +{ + struct serial_multiport_struct new_multi; + struct rs_multiport_struct *multi; + struct serial_state *state; + int was_multi, now_multi; + int retval; + void (*handler)(int, void *, struct pt_regs *); + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + state = info->state; + + if (copy_from_user(&new_multi, in_multi, + sizeof(struct serial_multiport_struct))) + return -EFAULT; + + if (new_multi.irq != state->irq || state->irq == 0 || + !IRQ_ports[state->irq]) + return -EINVAL; + + multi = &rs_multiport[state->irq]; + was_multi = (multi->port1 != 0); + + multi->port_monitor = new_multi.port_monitor; + + if (multi->port1) + release_region(multi->port1,1); + multi->port1 = new_multi.port1; + multi->mask1 = new_multi.mask1; + multi->match1 = new_multi.match1; + if (multi->port1) + request_region(multi->port1,1,"serial(multiport1)"); + + if (multi->port2) + release_region(multi->port2,1); + multi->port2 = new_multi.port2; + multi->mask2 = new_multi.mask2; + multi->match2 = new_multi.match2; + if (multi->port2) + request_region(multi->port2,1,"serial(multiport2)"); + + if (multi->port3) + release_region(multi->port3,1); + multi->port3 = new_multi.port3; + multi->mask3 = new_multi.mask3; + multi->match3 = new_multi.match3; + if (multi->port3) + request_region(multi->port3,1,"serial(multiport3)"); + + if (multi->port4) + release_region(multi->port4,1); + multi->port4 = new_multi.port4; + multi->mask4 = new_multi.mask4; + multi->match4 = new_multi.match4; + if (multi->port4) + request_region(multi->port4,1,"serial(multiport4)"); + + now_multi = (multi->port1 != 0); + + if (IRQ_ports[state->irq]->next_port && + (was_multi != now_multi)) { + free_irq(IRQ_4M(state->irq), info); + if (now_multi) + handler = rs_interrupt_multi; + else + handler = su_interrupt; + + retval = request_irq(IRQ_4M(state->irq), handler, IRQ_T(info), + "serial", info); + if (retval) { + printk("Couldn't reallocate serial interrupt " + "driver!!\n"); + } + } + + return 0; +} +#endif + +static int su_ioctl(struct tty_struct *tty, struct file * file, + unsigned int cmd, unsigned long arg) +{ + int error; + struct su_struct * info = (struct su_struct *)tty->driver_data; + struct async_icount cprev, cnow; /* kernel counter temps */ + struct serial_icounter_struct *p_cuser; /* user space */ + + if (serial_paranoia_check(info, tty->device, "su_ioctl")) + return -ENODEV; + + if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && + (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) && + (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + } + + switch (cmd) { + case TIOCMGET: + return get_modem_info(info, (unsigned int *) arg); + case TIOCMBIS: + case TIOCMBIC: + case TIOCMSET: + return set_modem_info(info, cmd, (unsigned int *) arg); +#if 0 + case TIOCGSERIAL: + return get_serial_info(info, + (struct serial_struct *) arg); + case TIOCSSERIAL: + return set_serial_info(info, + (struct serial_struct *) arg); + case TIOCSERCONFIG: + return do_autoconfig(info); +#endif + + case TIOCSERGETLSR: /* Get line status register */ + return get_lsr_info(info, (unsigned int *) arg); + +#if 0 + case TIOCSERGSTRUCT: + if (copy_to_user((struct async_struct *) arg, + info, sizeof(struct async_struct))) + return -EFAULT; + return 0; +#endif + +#ifdef CONFIG_SERIAL_MULTIPORT + case TIOCSERGETMULTI: + return get_multiport_struct(info, + (struct serial_multiport_struct *) arg); + case TIOCSERSETMULTI: + return set_multiport_struct(info, + (struct serial_multiport_struct *) arg); +#endif + + /* + * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change + * - mask passed in arg for lines of interest + * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) + * Caller should use TIOCGICOUNT to see which one it was + */ + case TIOCMIWAIT: + cli(); + /* note the counters on entry */ + cprev = info->icount; + sti(); + while (1) { + interruptible_sleep_on(&info->delta_msr_wait); + /* see if a signal did it */ + if (signal_pending(current)) + return -ERESTARTSYS; + cli(); + cnow = info->icount; /* atomic copy */ + sti(); + if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && + cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) + return -EIO; /* no change => error */ + if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || + ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || + ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || + ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) { + return 0; + } + cprev = cnow; + } + /* NOTREACHED */ + + /* + * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) + * Return: write counters to the user passed counter struct + * NB: both 1->0 and 0->1 transitions are counted except for + * RI where only 0->1 is counted. + */ + case TIOCGICOUNT: + cli(); + cnow = info->icount; + sti(); + p_cuser = (struct serial_icounter_struct *) arg; + error = put_user(cnow.cts, &p_cuser->cts); + if (error) return error; + error = put_user(cnow.dsr, &p_cuser->dsr); + if (error) return error; + error = put_user(cnow.rng, &p_cuser->rng); + if (error) return error; + error = put_user(cnow.dcd, &p_cuser->dcd); + if (error) return error; + return 0; + + default: + return -ENOIOCTLCMD; + } + /* return 0; */ /* Trigger warnings is fall through by a chance. */ +} + +static void su_set_termios(struct tty_struct *tty, struct termios *old_termios) +{ + struct su_struct *info = (struct su_struct *)tty->driver_data; + + if ( (tty->termios->c_cflag == old_termios->c_cflag) + && ( RELEVANT_IFLAG(tty->termios->c_iflag) + == RELEVANT_IFLAG(old_termios->c_iflag))) + return; + + change_speed(info); + + /* Handle transition to B0 status */ + if ((old_termios->c_cflag & CBAUD) && + !(tty->termios->c_cflag & CBAUD)) { + info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS); + cli(); + serial_out(info, UART_MCR, info->MCR); + sti(); + } + + /* Handle transition away from B0 status */ + if (!(old_termios->c_cflag & CBAUD) && + (tty->termios->c_cflag & CBAUD)) { + info->MCR |= UART_MCR_DTR; + if (!(tty->termios->c_cflag & CRTSCTS) || + !test_bit(TTY_THROTTLED, &tty->flags)) { + info->MCR |= UART_MCR_RTS; + } + cli(); + serial_out(info, UART_MCR, info->MCR); + sti(); + } + + /* Handle turning off CRTSCTS */ + if ((old_termios->c_cflag & CRTSCTS) && + !(tty->termios->c_cflag & CRTSCTS)) { + tty->hw_stopped = 0; + su_start(tty); + } + +#if 0 + /* + * No need to wake up processes in open wait, since they + * sample the CLOCAL flag once, and don't recheck it. + * XXX It's not clear whether the current behavior is correct + * or not. Hence, this may change..... + */ + if (!(old_termios->c_cflag & CLOCAL) && + (tty->termios->c_cflag & CLOCAL)) + wake_up_interruptible(&info->open_wait); +#endif +} + +/* + * ------------------------------------------------------------ + * su_close() + * + * This routine is called when the serial port gets closed. First, we + * wait for the last remaining data to be sent. Then, we unlink its + * async structure from the interrupt chain if necessary, and we free + * that IRQ if nothing is left in the chain. + * ------------------------------------------------------------ + */ +static void su_close(struct tty_struct *tty, struct file * filp) +{ + struct su_struct *info = (struct su_struct *)tty->driver_data; + unsigned long flags; + + if (!info || serial_paranoia_check(info, tty->device, "su_close")) + return; + + save_flags(flags); cli(); + + if (tty_hung_up_p(filp)) { + DBG_CNT("before DEC-hung"); + MOD_DEC_USE_COUNT; + restore_flags(flags); + return; + } + +#ifdef SERIAL_DEBUG_OPEN + printk("su_close ttys%d, count = %d\n", info->line, info->count); +#endif + if ((tty->count == 1) && (info->count != 1)) { + /* + * Uh, oh. tty->count is 1, which means that the tty + * structure will be freed. info->count should always + * be one in these conditions. If it's greater than + * one, we've got real problems, since it means the + * serial port won't be shutdown. + */ + printk("su_close: bad serial port count; tty->count is 1, " + "info->count is %d\n", info->count); + info->count = 1; + } + if (--info->count < 0) { + printk("su_close: bad serial port count for ttys%d: %d\n", + info->line, info->count); + info->count = 0; + } + if (info->count) { + DBG_CNT("before DEC-2"); + MOD_DEC_USE_COUNT; + restore_flags(flags); + return; + } + info->flags |= ASYNC_CLOSING; + /* + * Save the termios structure, since this port may have + * separate termios for callout and dialin. + */ + if (info->flags & ASYNC_NORMAL_ACTIVE) + info->normal_termios = *tty->termios; + if (info->flags & ASYNC_CALLOUT_ACTIVE) + info->callout_termios = *tty->termios; + /* + * Now we wait for the transmit buffer to clear; and we notify + * the line discipline to only process XON/XOFF characters. + */ + tty->closing = 1; + if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) + tty_wait_until_sent(tty, info->closing_wait); + /* + * At this point we stop accepting input. To do this, we + * disable the receive line status interrupts, and tell the + * interrupt driver to stop checking the data ready bit in the + * line status register. + */ + info->IER &= ~UART_IER_RLSI; + info->read_status_mask &= ~UART_LSR_DR; + if (info->flags & ASYNC_INITIALIZED) { + serial_out(info, UART_IER, info->IER); + /* + * Before we drop DTR, make sure the UART transmitter + * has completely drained; this is especially + * important if there is a transmit FIFO! + */ + su_wait_until_sent(tty, info->timeout); + } + shutdown(info); + if (tty->driver.flush_buffer) + tty->driver.flush_buffer(tty); + if (tty->ldisc.flush_buffer) + tty->ldisc.flush_buffer(tty); + tty->closing = 0; + info->event = 0; + info->tty = 0; + if (info->blocked_open) { + if (info->close_delay) { + current->state = TASK_INTERRUPTIBLE; + current->timeout = jiffies + info->close_delay; + schedule(); + } + wake_up_interruptible(&info->open_wait); + } + info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE| + ASYNC_CLOSING); + wake_up_interruptible(&info->close_wait); + MOD_DEC_USE_COUNT; + restore_flags(flags); +} + +/* + * su_wait_until_sent() --- wait until the transmitter is empty + */ +static void su_wait_until_sent(struct tty_struct *tty, int timeout) +{ + struct su_struct * info = (struct su_struct *)tty->driver_data; + unsigned long orig_jiffies, char_time; + int lsr; + + if (serial_paranoia_check(info, tty->device, "su_wait_until_sent")) + return; + + if (info->type == PORT_UNKNOWN) + return; + + orig_jiffies = jiffies; + /* + * Set the check interval to be 1/5 of the estimated time to + * send a single character, and make it at least 1. The check + * interval should also be less than the timeout. + * + * Note: we have to use pretty tight timings here to satisfy + * the NIST-PCTS. + */ + char_time = (info->timeout - HZ/50) / info->xmit_fifo_size; + char_time = char_time / 5; + if (char_time == 0) + char_time = 1; + if (timeout) + char_time = MIN(char_time, timeout); +#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + printk("In su_wait_until_sent(%d) check=%lu...", timeout, char_time); + printk("jiff=%lu...", jiffies); +#endif + while (!((lsr = serial_inp(info, UART_LSR)) & UART_LSR_TEMT)) { +#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + printk("lsr = %d (jiff=%lu)...", lsr, jiffies); +#endif + current->state = TASK_INTERRUPTIBLE; + current->counter = 0; /* make us low-priority */ + current->timeout = jiffies + char_time; + schedule(); + if (signal_pending(current)) + break; + if (timeout && ((orig_jiffies + timeout) < jiffies)) + break; + } + current->state = TASK_RUNNING; +#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); +#endif +} + +/* + * su_hangup() --- called by tty_hangup() when a hangup is signaled. + */ +static void su_hangup(struct tty_struct *tty) +{ + struct su_struct * info = (struct su_struct *)tty->driver_data; + + if (serial_paranoia_check(info, tty->device, "su_hangup")) + return; + + su_flush_buffer(tty); + shutdown(info); + info->event = 0; + info->count = 0; + info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE); + info->tty = 0; + wake_up_interruptible(&info->open_wait); +} + +/* + * ------------------------------------------------------------ + * su_open() and friends + * ------------------------------------------------------------ + */ +static int block_til_ready(struct tty_struct *tty, struct file * filp, + struct su_struct *info) +{ + struct wait_queue wait = { current, NULL }; + int retval; + int do_clocal = 0; + + /* + * If the device is in the middle of being closed, then block + * until it's done, and then try again. + */ + if (tty_hung_up_p(filp) || + (info->flags & ASYNC_CLOSING)) { + if (info->flags & ASYNC_CLOSING) + interruptible_sleep_on(&info->close_wait); +#ifdef SERIAL_DO_RESTART + return ((info->flags & ASYNC_HUP_NOTIFY) ? + -EAGAIN : -ERESTARTSYS); +#else + return -EAGAIN; +#endif + } + + /* + * If this is a callout device, then just make sure the normal + * device isn't being used. + */ + if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) { + if (info->flags & ASYNC_NORMAL_ACTIVE) + return -EBUSY; + if ((info->flags & ASYNC_CALLOUT_ACTIVE) && + (info->flags & ASYNC_SESSION_LOCKOUT) && + (info->session != current->session)) + return -EBUSY; + if ((info->flags & ASYNC_CALLOUT_ACTIVE) && + (info->flags & ASYNC_PGRP_LOCKOUT) && + (info->pgrp != current->pgrp)) + return -EBUSY; + info->flags |= ASYNC_CALLOUT_ACTIVE; + return 0; + } + + /* + * If non-blocking mode is set, or the port is not enabled, + * then make the check up front and then exit. + */ + if ((filp->f_flags & O_NONBLOCK) || + (tty->flags & (1 << TTY_IO_ERROR))) { + if (info->flags & ASYNC_CALLOUT_ACTIVE) + return -EBUSY; + info->flags |= ASYNC_NORMAL_ACTIVE; + return 0; + } + + if (info->flags & ASYNC_CALLOUT_ACTIVE) { + if (info->normal_termios.c_cflag & CLOCAL) + do_clocal = 1; + } else { + if (tty->termios->c_cflag & CLOCAL) + do_clocal = 1; + } + + /* + * Block waiting for the carrier detect and the line to become + * free (i.e., not in use by the callout). While we are in + * this loop, info->count is dropped by one, so that + * su_close() knows when to free things. We restore it upon + * exit, either normal or abnormal. + */ + retval = 0; + add_wait_queue(&info->open_wait, &wait); +#ifdef SERIAL_DEBUG_OPEN + printk("block_til_ready before block: ttys%d, count = %d\n", + info->line, info->count); +#endif + cli(); + if (!tty_hung_up_p(filp)) + info->count--; + sti(); + info->blocked_open++; + while (1) { + cli(); + if (!(info->flags & ASYNC_CALLOUT_ACTIVE) && + (tty->termios->c_cflag & CBAUD)) + serial_out(info, UART_MCR, + serial_inp(info, UART_MCR) | + (UART_MCR_DTR | UART_MCR_RTS)); + sti(); + current->state = TASK_INTERRUPTIBLE; + if (tty_hung_up_p(filp) || + !(info->flags & ASYNC_INITIALIZED)) { +#ifdef SERIAL_DO_RESTART + if (info->flags & ASYNC_HUP_NOTIFY) + retval = -EAGAIN; + else + retval = -ERESTARTSYS; +#else + retval = -EAGAIN; +#endif + break; + } + if (!(info->flags & ASYNC_CALLOUT_ACTIVE) && + !(info->flags & ASYNC_CLOSING) && + (do_clocal || (serial_in(info, UART_MSR) & + UART_MSR_DCD))) + break; + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } +#ifdef SERIAL_DEBUG_OPEN + printk("block_til_ready blocking: ttys%d, count = %d\n", + info->line, info->count); +#endif + schedule(); + } + current->state = TASK_RUNNING; + remove_wait_queue(&info->open_wait, &wait); + if (!tty_hung_up_p(filp)) + info->count++; + info->blocked_open--; +#ifdef SERIAL_DEBUG_OPEN + printk("block_til_ready after blocking: ttys%d, count = %d\n", + info->line, info->count); +#endif + if (retval) + return retval; + info->flags |= ASYNC_NORMAL_ACTIVE; + return 0; +} + +/* + * This routine is called whenever a serial port is opened. It + * enables interrupts for a serial port, linking in its async structure into + * the IRQ chain. It also performs the serial-specific + * initialization for the tty structure. + */ +static int su_open(struct tty_struct *tty, struct file * filp) +{ + struct su_struct *info; + int retval, line; + unsigned long page; + + line = MINOR(tty->device) - tty->driver.minor_start; + if ((line < 0) || (line >= NR_PORTS)) + return -ENODEV; + info = su_table + line; + if (serial_paranoia_check(info, tty->device, "su_open")) + return -ENODEV; + info->count++; + +#ifdef SERIAL_DEBUG_OPEN + printk("su_open %s%d, count = %d\n", tty->driver.name, info->line, + info->count); +#endif + tty->driver_data = info; + info->tty = tty; + info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + + if (!tmp_buf) { + page = get_free_page(GFP_KERNEL); + if (!page) + return -ENOMEM; + if (tmp_buf) + free_page(page); + else + tmp_buf = (unsigned char *) page; + } + + /* + * If the port is the middle of closing, bail out now + */ + if (tty_hung_up_p(filp) || + (info->flags & ASYNC_CLOSING)) { + if (info->flags & ASYNC_CLOSING) + interruptible_sleep_on(&info->close_wait); +#ifdef SERIAL_DO_RESTART + return ((info->flags & ASYNC_HUP_NOTIFY) ? + -EAGAIN : -ERESTARTSYS); +#else + return -EAGAIN; +#endif + } + + /* + * Start up serial port + */ + retval = startup(info); + if (retval) + return retval; + + MOD_INC_USE_COUNT; + retval = block_til_ready(tty, filp, info); + if (retval) { +#ifdef SERIAL_DEBUG_OPEN + printk("su_open returning after block_til_ready with %d\n", + retval); +#endif + return retval; + } + + if ((info->count == 1) && + (info->flags & ASYNC_SPLIT_TERMIOS)) { + if (tty->driver.subtype == SERIAL_TYPE_NORMAL) + *tty->termios = info->normal_termios; + else + *tty->termios = info->callout_termios; + change_speed(info); + } +#ifdef CONFIG_SERIAL_CONSOLE + if (sercons.cflag && sercons.index == line) { + tty->termios->c_cflag = sercons.cflag; + sercons.cflag = 0; + change_speed(info); + } +#endif + info->session = current->session; + info->pgrp = current->pgrp; + +#ifdef SERIAL_DEBUG_OPEN + printk("su_open ttys%d successful...", info->line); +#endif + return 0; +} + +/* + * /proc fs routines.... + */ + +static inline int line_info(char *buf, struct su_struct *info) +{ + char stat_buf[30], control, status; + int ret; + + ret = sprintf(buf, "%d: uart:%s port:%X irq:%d", + info->line, uart_config[info->type].name, + (int)info->port, info->irq); + + if (info->port == 0 || info->type == PORT_UNKNOWN) { + ret += sprintf(buf+ret, "\n"); + return ret; + } + + /* + * Figure out the current RS-232 lines + */ + cli(); + status = serial_in(info, UART_MSR); + control = info ? info->MCR : serial_in(info, UART_MCR); + sti(); + + stat_buf[0] = 0; + stat_buf[1] = 0; + if (control & UART_MCR_RTS) + strcat(stat_buf, "|RTS"); + if (status & UART_MSR_CTS) + strcat(stat_buf, "|CTS"); + if (control & UART_MCR_DTR) + strcat(stat_buf, "|DTR"); + if (status & UART_MSR_DSR) + strcat(stat_buf, "|DSR"); + if (status & UART_MSR_DCD) + strcat(stat_buf, "|CD"); + if (status & UART_MSR_RI) + strcat(stat_buf, "|RI"); + + if (info->quot) { + ret += sprintf(buf+ret, " baud:%d", + info->baud_base / info->quot); + } + + ret += sprintf(buf+ret, " tx:%d rx:%d", + info->icount.tx, info->icount.rx); + + if (info->icount.frame) + ret += sprintf(buf+ret, " fe:%d", info->icount.frame); + + if (info->icount.parity) + ret += sprintf(buf+ret, " pe:%d", info->icount.parity); + + if (info->icount.brk) + ret += sprintf(buf+ret, " brk:%d", info->icount.brk); + + if (info->icount.overrun) + ret += sprintf(buf+ret, " oe:%d", info->icount.overrun); + + /* + * Last thing is the RS-232 status lines + */ + ret += sprintf(buf+ret, " %s\n", stat_buf+1); + return ret; +} + +int su_read_proc(char *page, char **start, off_t off, int count, + int *eof, void *data) +{ + int i, len = 0; + off_t begin = 0; + + len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version); + for (i = 0; i < NR_PORTS && len < 4000; i++) { + len += line_info(page + len, &su_table[i]); + if (len+begin > off+count) + goto done; + if (len+begin < off) { + begin += len; + len = 0; + } + } + *eof = 1; +done: + if (off >= len+begin) + return 0; + *start = page + (begin-off); + return ((count < begin+len-off) ? count : begin+len-off); +} + +/* + * --------------------------------------------------------------------- + * su_init() and friends + * + * su_init() is called at boot-time to initialize the serial driver. + * --------------------------------------------------------------------- + */ + +/* + * This routine prints out the appropriate serial driver version + * number, and identifies which options were configured into this + * driver. + */ +static _INLINE_ void show_su_version(void) +{ + printk(KERN_INFO "%s version %s with", serial_name, serial_version); +#ifdef CONFIG_SERIAL_MANY_PORTS + printk(" MANY_PORTS"); +#define SERIAL_OPT +#endif +#ifdef CONFIG_SERIAL_MULTIPORT + printk(" MULTIPORT"); +#define SERIAL_OPT +#endif +#ifdef CONFIG_SERIAL_SHARE_IRQ + printk(" SHARE_IRQ"); +#endif +#define SERIAL_OPT +#ifdef CONFIG_SERIAL_DETECT_IRQ + printk(" DETECT_IRQ"); +#endif +#ifdef SERIAL_OPT + printk(" enabled\n"); +#else + printk(" no serial options enabled\n"); +#endif +#undef SERIAL_OPT +} + +/* + * This routine is called by su_init() to initialize a specific serial + * port. It determines what type of UART chip this serial port is + * using: 8250, 16450, 16550, 16550A. The important question is + * whether or not this UART is a 16550A or not, since this will + * determine whether or not we can use its FIFO features or not. + */ +static void +autoconfig(struct su_struct *info) +{ + unsigned char status1, status2, scratch, scratch2; +#ifdef __sparc_v9__ + struct linux_ebus_device *dev = 0; + struct linux_ebus *ebus; +#else + struct linux_prom_registers reg0; +#endif + unsigned long flags; + +#ifdef __sparc_v9__ + for_each_ebus(ebus) { + for_each_ebusdev(dev, ebus) { + if (!strncmp(dev->prom_name, "su", 2)) { + if (dev->prom_node == info->kbd_node) + goto ebus_done; + if (dev->prom_node == info->ms_node) + goto ebus_done; + } + } + } +ebus_done: + if (!dev) + return; + + info->port = dev->base_address[0]; + if (check_region(info->port, 8)) + return; + + info->irq = dev->irqs[0]; + +#ifdef DEBUG_SERIAL_OPEN + printk("Found 'su' at %016lx IRQ %s\n", dev->base_address[0], + __irq_itoa(dev->irqs[0])); +#endif + +#else + if (info->port_node == 0) { + return; + } + if (prom_getproperty(info->port_node, "reg", + (char *)®0, sizeof(reg0)) == -1) { + prom_printf("su: no \"reg\" property\n"); + return; + } + prom_apply_obio_ranges(®0, 1); + if ((info->port = (unsigned long) sparc_alloc_io(reg0.phys_addr, + 0, reg0.reg_size, "su-regs", reg0.which_io, 0)) == 0) { + prom_printf("su: cannot map\n"); + return; + } + /* + * There is no intr property on MrCoffee, so hardwire it. Krups? + */ + info->irq = 13; +#endif + + info->magic = SERIAL_MAGIC; + + save_flags(flags); cli(); + + /* + * Do a simple existence test first; if we fail this, there's + * no point trying anything else. + * + * 0x80 is used as a nonsense port to prevent against false + * positives due to ISA bus float. The assumption is that + * 0x80 is a non-existent port; which should be safe since + * include/asm/io.h also makes this assumption. + */ + scratch = serial_in(info, UART_IER); + su_outb(info, UART_IER, 0); + scratch2 = serial_in(info, UART_IER); + su_outb(info, UART_IER, scratch); + if (scratch2) { + restore_flags(flags); + return; /* We failed; there's nothing here */ + } + +#if 0 /* P3 You will never beleive but SuperIO fails this test in MrCoffee. */ + scratch = serial_in(info, UART_MCR); + su_outb(info, UART_MCR, UART_MCR_LOOP | scratch); + scratch2 = serial_in(info, UART_MSR); + su_outb(info, UART_MCR, UART_MCR_LOOP | 0x0A); + status1 = serial_in(info, UART_MSR) & 0xF0; + su_outb(info, UART_MCR, scratch); + su_outb(info, UART_MSR, scratch2); + if (status1 != 0x90) { + restore_flags(flags); + return; + } +#endif + + scratch2 = serial_in(info, UART_LCR); + su_outb(info, UART_LCR, 0xBF); /* set up for StarTech test */ + su_outb(info, UART_EFR, 0); /* EFR is the same as FCR */ + su_outb(info, UART_LCR, 0); + su_outb(info, UART_FCR, UART_FCR_ENABLE_FIFO); + scratch = serial_in(info, UART_IIR) >> 6; + switch (scratch) { + case 0: + info->type = PORT_16450; + break; + case 1: + info->type = PORT_UNKNOWN; + break; + case 2: + info->type = PORT_16550; + break; + case 3: + info->type = PORT_16550A; + break; + } + if (info->type == PORT_16550A) { + /* Check for Startech UART's */ + su_outb(info, UART_LCR, scratch2 | UART_LCR_DLAB); + if (su_inb(info, UART_EFR) == 0) { + info->type = PORT_16650; + } else { + su_outb(info, UART_LCR, 0xBF); + if (su_inb(info, UART_EFR) == 0) + info->type = PORT_16650V2; + } + } + if (info->type == PORT_16550A) { + /* Check for TI 16750 */ + su_outb(info, UART_LCR, scratch2 | UART_LCR_DLAB); + su_outb(info, UART_FCR, + UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE); + scratch = su_inb(info, UART_IIR) >> 5; + if (scratch == 7) { + su_outb(info, UART_LCR, 0); + su_outb(info, UART_FCR, UART_FCR_ENABLE_FIFO); + scratch = su_inb(info, UART_IIR) >> 5; + if (scratch == 6) + info->type = PORT_16750; + } + su_outb(info, UART_FCR, UART_FCR_ENABLE_FIFO); + } + su_outb(info, UART_LCR, scratch2); + if (info->type == PORT_16450) { + scratch = su_inb(info, UART_SCR); + su_outb(info, UART_SCR, 0xa5); + status1 = su_inb(info, UART_SCR); + su_outb(info, UART_SCR, 0x5a); + status2 = su_inb(info, UART_SCR); + su_outb(info, UART_SCR, scratch); + + if ((status1 != 0xa5) || (status2 != 0x5a)) + info->type = PORT_8250; + } + info->xmit_fifo_size = uart_config[info->type].dfl_xmit_fifo_size; + + if (info->type == PORT_UNKNOWN) { + restore_flags(flags); + return; + } + +#ifdef __sparc_v9__ + sprintf(info->name, "su(%s)", info->ms_node ? "mouse" : "kbd"); + request_region(info->port, 8, info->name); +#else + strcpy(info->name, "su(serial)"); +#endif + + /* + * Reset the UART. + */ + su_outb(info, UART_MCR, 0x00); + su_outb(info, UART_FCR, (UART_FCR_CLEAR_RCVR | + UART_FCR_CLEAR_XMIT)); + su_inb(info, UART_RX); + + restore_flags(flags); +} + +/* + * The serial driver boot-time initialization code! + */ +__initfunc(int su_init(void)) +{ + int i; + struct su_struct *info; + extern void atomwide_serial_init (void); + extern void dualsp_serial_init (void); + +#ifdef CONFIG_ATOMWIDE_SERIAL + atomwide_serial_init (); +#endif +#ifdef CONFIG_DUALSP_SERIAL + dualsp_serial_init (); +#endif + + init_bh(SERIAL_BH, do_serial_bh); + timer_table[RS_TIMER].fn = su_timer; + timer_table[RS_TIMER].expires = 0; + + for (i = 0; i < NR_IRQS; i++) { + IRQ_ports[i] = 0; + IRQ_timeout[i] = 0; +#ifdef CONFIG_SERIAL_MULTIPORT + memset(&rs_multiport[i], 0, + sizeof(struct rs_multiport_struct)); +#endif + } +#if 0 /* Must be shared with keyboard on MrCoffee. */ +#ifdef CONFIG_SERIAL_CONSOLE + /* + * The interrupt of the serial console port + * can't be shared. + */ + if (sercons.flags & CON_CONSDEV) { + for(i = 0; i < NR_PORTS; i++) + if (i != sercons.index && + su_table[i].irq == su_table[sercons.index].irq) + su_table[i].irq = 0; + } +#endif +#endif + show_su_version(); + + /* Initialize the tty_driver structure */ + + memset(&serial_driver, 0, sizeof(struct tty_driver)); + serial_driver.magic = TTY_DRIVER_MAGIC; + serial_driver.driver_name = "su"; + serial_driver.name = "ttyS"; + serial_driver.major = TTY_MAJOR; + serial_driver.minor_start = 64; + serial_driver.num = NR_PORTS; + serial_driver.type = TTY_DRIVER_TYPE_SERIAL; + serial_driver.subtype = SERIAL_TYPE_NORMAL; + serial_driver.init_termios = tty_std_termios; + serial_driver.init_termios.c_cflag = + B9600 | CS8 | CREAD | HUPCL | CLOCAL; + serial_driver.flags = TTY_DRIVER_REAL_RAW; + serial_driver.refcount = &serial_refcount; + serial_driver.table = serial_table; + serial_driver.termios = serial_termios; + serial_driver.termios_locked = serial_termios_locked; + + serial_driver.open = su_open; + serial_driver.close = su_close; + serial_driver.write = su_write; + serial_driver.put_char = su_put_char; + serial_driver.flush_chars = su_flush_chars; + serial_driver.write_room = su_write_room; + serial_driver.chars_in_buffer = su_chars_in_buffer; + serial_driver.flush_buffer = su_flush_buffer; + serial_driver.ioctl = su_ioctl; + serial_driver.throttle = su_throttle; + serial_driver.unthrottle = su_unthrottle; + serial_driver.send_xchar = su_send_xchar; + serial_driver.set_termios = su_set_termios; + serial_driver.stop = su_stop; + serial_driver.start = su_start; + serial_driver.hangup = su_hangup; + serial_driver.break_ctl = su_break; + serial_driver.wait_until_sent = su_wait_until_sent; + serial_driver.read_proc = su_read_proc; + + /* + * The callout device is just like normal device except for + * major number and the subtype code. + */ + callout_driver = serial_driver; + callout_driver.name = "cua"; + callout_driver.major = TTYAUX_MAJOR; + callout_driver.subtype = SERIAL_TYPE_CALLOUT; + callout_driver.read_proc = 0; + callout_driver.proc_entry = 0; + + if (tty_register_driver(&serial_driver)) + panic("Couldn't register regular su\n"); + if (tty_register_driver(&callout_driver)) + panic("Couldn't register callout su\n"); + + for (i = 0, info = su_table; i < NR_PORTS; i++, info++) { + info->magic = SSTATE_MAGIC; + info->line = i; + info->type = PORT_UNKNOWN; + info->baud_base = BAUD_BASE; + /* info->flags = 0; */ + info->custom_divisor = 0; + info->close_delay = 5*HZ/10; + info->closing_wait = 30*HZ; + info->callout_termios = callout_driver.init_termios; + info->normal_termios = serial_driver.init_termios; + info->icount.cts = info->icount.dsr = + info->icount.rng = info->icount.dcd = 0; + info->icount.rx = info->icount.tx = 0; + info->icount.frame = info->icount.parity = 0; + info->icount.overrun = info->icount.brk = 0; + info->tqueue.routine = do_softint; + info->tqueue.data = info; + + if (info->kbd_node) + info->cflag = B1200 | CS8 | CREAD; + else if (info->ms_node) + info->cflag = B4800 | CS8 | CREAD; + else + info->cflag = B9600 | CS8 | CREAD; + + autoconfig(info); + if (info->type == PORT_UNKNOWN) + continue; + + printk(KERN_INFO "%s at %16lx (irq = %s) is a %s\n", + info->name, info->port, __irq_itoa(info->irq), + uart_config[info->type].name); + + /* + * We want startup here because we want mouse and keyboard + * working without opening. On SPARC console will work + * without startup. + */ + if (info->kbd_node) { + startup(info); + keyboard_zsinit(su_put_char_kbd); + } else if (info->ms_node) { + startup(info); + sun_mouse_zsinit(); + } + } + + return 0; +} + +__initfunc(int su_probe (unsigned long *memory_start)) +{ + struct su_struct *info = su_table; + int node, enode, tnode, sunode; + int kbnode = 0, msnode = 0; + int devices = 0; + char prop[128]; + int len; + + /* + * Find su on MrCoffee. We return OK code if find any. + * Then su_init finds every one and initializes them. + * We do this early because MrCoffee got no aliases. + */ + node = prom_getchild(prom_root_node); + if ((node = prom_searchsiblings(node, "obio")) != 0) { + if ((sunode = prom_getchild(node)) != 0) { + if ((sunode = prom_searchsiblings(sunode, "su")) != 0) { + info->port_node = sunode; +#ifdef CONFIG_SERIAL_CONSOLE + /* + * Console must be initiated after the generic initialization. + * sunserial_setinitfunc inverts order, so call this before next one. + */ + sunserial_setinitfunc(memory_start, su_serial_console_init); +#endif + sunserial_setinitfunc(memory_start, su_init); + return 0; + } + } + } + + /* + * Get the nodes for keyboard and mouse from 'aliases'... + */ + node = prom_getchild(prom_root_node); + node = prom_searchsiblings(node, "aliases"); + if (!node) + return -ENODEV; + + len = prom_getproperty(node, "keyboard", prop, sizeof(prop)); + if (len > 0) { + prop[len] = 0; + kbnode = prom_finddevice(prop); + } + if (!kbnode) + return -ENODEV; + + len = prom_getproperty(node, "mouse", prop, sizeof(prop)); + if (len > 0) { + prop[len] = 0; + msnode = prom_finddevice(prop); + } + if (!msnode) + return -ENODEV; + + /* + * Find matching EBus nodes... + */ + node = prom_getchild(prom_root_node); + if ((node = prom_searchsiblings(node, "pci")) == 0) { + return -ENODEV; /* Plain sparc */ + } + + /* + * Check for SUNW,sabre on Ultra 5/10/AXi. + */ + len = prom_getproperty(node, "model", prop, sizeof(prop)); + if ((len > 0) && !strncmp(prop, "SUNW,sabre", len)) { + node = prom_getchild(node); + node = prom_searchsiblings(node, "pci"); + } + + /* + * For each PCI bus... + */ + while (node) { + enode = prom_getchild(node); + enode = prom_searchsiblings(enode, "ebus"); + + /* + * For each EBus on this PCI... + */ + while (enode) { + sunode = prom_getchild(enode); + tnode = prom_searchsiblings(sunode, "su"); + if (!tnode) + tnode = prom_searchsiblings(sunode, "su_pnp"); + sunode = tnode; + + /* + * For each 'su' on this EBus... + */ + while (sunode) { + /* + * Does it match? + */ + if (sunode == kbnode) { + info->kbd_node = sunode; + ++info; + ++devices; + } + if (sunode == msnode) { + info->ms_node = sunode; + ++info; + ++devices; + } + + /* + * Found everything we need? + */ + if (devices == NR_PORTS) + goto found; + + sunode = prom_getsibling(sunode); + tnode = prom_searchsiblings(sunode, "su"); + if (!tnode) + tnode = prom_searchsiblings(sunode, + "su_pnp"); + sunode = tnode; + } + enode = prom_getsibling(enode); + enode = prom_searchsiblings(enode, "ebus"); + } + node = prom_getsibling(node); + node = prom_searchsiblings(node, "pci"); + } + return -ENODEV; + +found: + sunserial_setinitfunc(memory_start, su_init); + rs_ops.rs_change_mouse_baud = su_change_mouse_baud; + sunkbd_setinitfunc(memory_start, sun_kbd_init); + kbd_ops.compute_shiftstate = sun_compute_shiftstate; + kbd_ops.setledstate = sun_setledstate; + kbd_ops.getledstate = sun_getledstate; + kbd_ops.setkeycode = sun_setkeycode; + kbd_ops.getkeycode = sun_getkeycode; +#ifdef CONFIG_PCI + sunkbd_install_keymaps(memory_start, sun_key_maps, sun_keymap_count, + sun_func_buf, sun_func_table, + sun_funcbufsize, sun_funcbufleft, + sun_accent_table, sun_accent_table_size); +#endif + return 0; +} + +#if 0 +#ifdef MODULE +int init_module(void) +{ + return su_init(); /* rs_init? su_probe? XXX */ +} + +void cleanup_module(void) +{ + unsigned long flags; + int e1, e2; + int i; + + /* printk("Unloading %s: version %s\n", serial_name, serial_version); */ + save_flags(flags); + cli(); + timer_active &= ~(1 << RS_TIMER); + timer_table[RS_TIMER].fn = NULL; + timer_table[RS_TIMER].expires = 0; + remove_bh(SERIAL_BH); + if ((e1 = tty_unregister_driver(&serial_driver))) + printk("SERIAL: failed to unregister serial driver (%d)\n", + e1); + if ((e2 = tty_unregister_driver(&callout_driver))) + printk("SERIAL: failed to unregister callout driver (%d)\n", + e2); + restore_flags(flags); + + for (i = 0; i < NR_PORTS; i++) { + if (su_table[i].type != PORT_UNKNOWN) + release_region(su_table[i].port, 8); + } + if (tmp_buf) { + free_page((unsigned long) tmp_buf); + tmp_buf = NULL; + } +} +#endif /* MODULE */ +#endif /* deadwood */ + +/* + * ------------------------------------------------------------ + * Serial console driver + * ------------------------------------------------------------ + */ +#ifdef CONFIG_SERIAL_CONSOLE + +#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) + +/* + * Wait for transmitter & holding register to empty + */ +static inline void wait_for_xmitr(struct su_struct *info) +{ + int lsr; + unsigned int tmout = 1000000; + + do { + lsr = su_inb(info, UART_LSR); + if (--tmout == 0) + break; + } while ((lsr & BOTH_EMPTY) != BOTH_EMPTY); +} + +/* + * Print a string to the serial port trying not to disturb + * any possible real use of the port... + */ +static void serial_console_write(struct console *co, const char *s, + unsigned count) +{ + struct su_struct *info; + int ier; + unsigned i; + + info = su_table + co->index; + /* + * First save the IER then disable the interrupts + */ + ier = su_inb(info, UART_IER); + su_outb(info, UART_IER, 0x00); + + /* + * Now, do each character + */ + for (i = 0; i < count; i++, s++) { + wait_for_xmitr(info); + + /* + * Send the character out. + * If a LF, also do CR... + */ + su_outb(info, UART_TX, *s); + if (*s == 10) { + wait_for_xmitr(info); + su_outb(info, UART_TX, 13); + } + } + + /* + * Finally, Wait for transmitter & holding register to empty + * and restore the IER + */ + wait_for_xmitr(info); + su_outb(info, UART_IER, ier); +} + +/* + * Receive character from the serial port + */ +static int serial_console_wait_key(struct console *co) +{ + struct su_struct *info; + int ier; + int lsr; + int c; + + info = su_table + co->index; + + /* + * First save the IER then disable the interrupts so + * that the real driver for the port does not get the + * character. + */ + ier = su_inb(info, UART_IER); + su_outb(info, UART_IER, 0x00); + + do { + lsr = su_inb(info, UART_LSR); + } while (!(lsr & UART_LSR_DR)); + c = su_inb(info, UART_RX); + + /* + * Restore the interrupts + */ + su_outb(info, UART_IER, ier); + + return c; +} + +static kdev_t serial_console_device(struct console *c) +{ + return MKDEV(TTY_MAJOR, 64 + c->index); +} + +/* + * Setup initial baud/bits/parity. We do two things here: + * - construct a cflag setting for the first su_open() + * - initialize the serial port + * Return non-zero if we didn't find a serial port. + */ +__initfunc(static int serial_console_setup(struct console *co, char *options)) +{ + struct su_struct *info; + unsigned cval; + int baud = 9600; + int bits = 8; + int parity = 'n'; + int cflag = CREAD | HUPCL | CLOCAL; + int quot = 0; + char *s; + + if (options) { + baud = simple_strtoul(options, NULL, 10); + s = options; + while(*s >= '0' && *s <= '9') + s++; + if (*s) parity = *s++; + if (*s) bits = *s - '0'; + } + + /* + * Now construct a cflag setting. + */ + switch(baud) { + case 1200: + cflag |= B1200; + break; + case 2400: + cflag |= B2400; + break; + case 4800: + cflag |= B4800; + break; + case 19200: + cflag |= B19200; + break; + case 38400: + cflag |= B38400; + break; + case 57600: + cflag |= B57600; + break; + case 115200: + cflag |= B115200; + break; + case 9600: + default: + cflag |= B9600; + break; + } + switch(bits) { + case 7: + cflag |= CS7; + break; + default: + case 8: + cflag |= CS8; + break; + } + switch(parity) { + case 'o': case 'O': + cflag |= PARODD; + break; + case 'e': case 'E': + cflag |= PARENB; + break; + } + co->cflag = cflag; + + /* + * Divisor, bytesize and parity + */ + info = su_table + co->index; + quot = BAUD_BASE / baud; + cval = cflag & (CSIZE | CSTOPB); +#if defined(__powerpc__) || defined(__alpha__) + cval >>= 8; +#else /* !__powerpc__ && !__alpha__ */ + cval >>= 4; +#endif /* !__powerpc__ && !__alpha__ */ + if (cflag & PARENB) + cval |= UART_LCR_PARITY; + if (!(cflag & PARODD)) + cval |= UART_LCR_EPAR; + + /* + * Disable UART interrupts, set DTR and RTS high + * and set speed. + */ + su_outb(info, UART_IER, 0); + su_outb(info, UART_MCR, UART_MCR_DTR | UART_MCR_RTS); + su_outb(info, UART_LCR, cval | UART_LCR_DLAB); /* set DLAB */ + su_outb(info, UART_DLL, quot & 0xff); /* LS of divisor */ + su_outb(info, UART_DLM, quot >> 8); /* MS of divisor */ + su_outb(info, UART_LCR, cval); /* reset DLAB */ + info->quot = quot; + + /* + * If we read 0xff from the LSR, there is no UART here. + */ + if (su_inb(info, UART_LSR) == 0xff) + return -1; + + return 0; +} + +static struct console sercons = { + "ttyS", + serial_console_write, + NULL, + serial_console_device, + serial_console_wait_key, + NULL, + serial_console_setup, + CON_PRINTBUFFER, + -1, + 0, + NULL +}; + +/* + * Register console. + */ +__initfunc(int su_serial_console_init(void)) +{ + extern int con_is_present(void); + + if (con_is_present()) + return 0; + if (serial_console == 0) + return 0; + if (su_table[0].port == 0 || su_table[0].port_node == 0) + return 0; + sercons.index = 0; + register_console(&sercons); + return 0; +} + +#endif /* CONFIG_SERIAL_CONSOLE */ diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/char/sunkbd.c linux/drivers/sbus/char/sunkbd.c --- v2.1.123/linux/drivers/sbus/char/sunkbd.c Wed Aug 26 11:37:38 1998 +++ linux/drivers/sbus/char/sunkbd.c Sun Oct 4 10:22:44 1998 @@ -1325,11 +1325,11 @@ } /* Needed by X */ -static int kbd_fasync (struct file *filp, int on) +static int kbd_fasync (int fd, struct file *filp, int on) { int retval; - retval = fasync_helper (filp, on, &kb_fasync); + retval = fasync_helper (fd, filp, on, &kb_fasync); if (retval < 0) return retval; return 0; @@ -1479,7 +1479,7 @@ kbd_redirected = 0; kbd_opened = 0; - kbd_fasync (f, 0); + kbd_fasync (-1, f, 0); return 0; } diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/char/sunmouse.c linux/drivers/sbus/char/sunmouse.c --- v2.1.123/linux/drivers/sbus/char/sunmouse.c Wed Aug 26 11:37:38 1998 +++ linux/drivers/sbus/char/sunmouse.c Sun Oct 4 10:22:44 1998 @@ -329,11 +329,11 @@ return 0; } -static int sun_mouse_fasync (struct file *filp, int on) +static int sun_mouse_fasync (int fd, struct file *filp, int on) { int retval; - retval = fasync_helper (filp, on, &sunmouse.fasync); + retval = fasync_helper (fd, filp, on, &sunmouse.fasync); if (retval < 0) return retval; return 0; @@ -342,7 +342,7 @@ static int sun_mouse_close(struct inode *inode, struct file *file) { - sun_mouse_fasync (file, 0); + sun_mouse_fasync (-1, file, 0); if (--sunmouse.active) return 0; sunmouse.ready = 0; diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/char/sunserial.c linux/drivers/sbus/char/sunserial.c --- v2.1.123/linux/drivers/sbus/char/sunserial.c Thu Aug 6 14:06:32 1998 +++ linux/drivers/sbus/char/sunserial.c Sun Oct 4 10:22:44 1998 @@ -1,4 +1,4 @@ -/* $Id: sunserial.c,v 1.61 1998/07/28 13:59:52 jj Exp $ +/* $Id: sunserial.c,v 1.66 1998/09/21 05:48:48 jj Exp $ * serial.c: Serial port driver infrastructure for the Sparc. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -69,8 +69,9 @@ rs_ops.rs_kgdb_hook(channel); } -__initfunc(void serial_console_init(void)) +__initfunc(long serial_console_init(long kmem_start, long kmem_end)) { + return kmem_start; } void rs_change_mouse_baud(int baud) @@ -169,7 +170,6 @@ return kbd_ops.getkeycode(scancode); } - void sunserial_setinitfunc(unsigned long *memory_start, int (*init) (void)) { @@ -343,29 +343,41 @@ } #endif +extern int su_probe(unsigned long *); extern int zs_probe(unsigned long *); #ifdef CONFIG_SAB82532 extern int sab82532_probe(unsigned long *); #endif #ifdef CONFIG_PCI extern int ps2kbd_probe(unsigned long *); -extern int su_probe(unsigned long *); #endif __initfunc(unsigned long sun_serial_setup(unsigned long memory_start)) { - int ret = -ENODEV; - - /* Probe for controllers. */ - ret = zs_probe(&memory_start); - if (!ret) + int ret = 1; + +#if defined(CONFIG_PCI) && !defined(__sparc_v9__) + /* + * Probing sequence on sparc differs from sparc64. + * Keyboard is probed ahead of su because we want su function + * when keyboard is active. su is probed ahead of zs in order to + * get console on MrCoffee with fine but disconnected zs. + */ + if (!serial_console) + ps2kbd_probe(&memory_start); + if (su_probe(&memory_start) == 0) return memory_start; +#endif + if (zs_probe(&memory_start) == 0) + return memory_start; + #ifdef CONFIG_SAB82532 ret = sab82532_probe(&memory_start); #endif -#ifdef CONFIG_PCI + +#if defined(CONFIG_PCI) && defined(__sparc_v9__) /* * Keyboard serial devices. * @@ -384,6 +396,7 @@ return memory_start; } #endif + if (!ret) return memory_start; diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/char/vfc_dev.c linux/drivers/sbus/char/vfc_dev.c --- v2.1.123/linux/drivers/sbus/char/vfc_dev.c Wed Aug 26 11:37:38 1998 +++ linux/drivers/sbus/char/vfc_dev.c Sun Oct 4 10:22:44 1998 @@ -21,7 +21,6 @@ #include #include #include -#include #include #include @@ -31,6 +30,7 @@ #include #include #include +#include #define VFC_MAJOR (60) diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/char/zs.c linux/drivers/sbus/char/zs.c --- v2.1.123/linux/drivers/sbus/char/zs.c Thu Aug 6 14:06:32 1998 +++ linux/drivers/sbus/char/zs.c Sun Oct 4 10:22:44 1998 @@ -1,9 +1,9 @@ -/* $Id: zs.c,v 1.26 1998/08/03 23:58:14 davem Exp $ +/* $Id: zs.c,v 1.29 1998/09/21 05:06:53 jj Exp $ * zs.c: Zilog serial port driver for the Sparc. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) - * Fixes by Pete A. Zaitcev . + * Fixes by Pete A. Zaitcev . */ #include @@ -36,10 +36,10 @@ #include #ifdef __sparc_v9__ #include +#endif #ifdef CONFIG_PCI #include #endif -#endif #include "sunserial.h" #include "zs.h" @@ -111,7 +111,7 @@ DECLARE_TASK_QUEUE(tq_serial); -struct tty_driver serial_driver, callout_driver; +static struct tty_driver serial_driver, callout_driver; static int serial_refcount; /* serial subtype definitions */ @@ -1808,7 +1808,7 @@ static void show_serial_version(void) { - char *revision = "$Revision: 1.26 $"; + char *revision = "$Revision: 1.29 $"; char *version, *p; version = strchr(revision, ' '); diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/dvma.c linux/drivers/sbus/dvma.c --- v2.1.123/linux/drivers/sbus/dvma.c Thu Aug 6 14:06:32 1998 +++ linux/drivers/sbus/dvma.c Sun Oct 4 10:22:44 1998 @@ -138,24 +138,24 @@ struct Linux_SBus_DMA *dchain; if(sun4_dma_physaddr) { - dma = kmalloc(sizeof(struct Linux_SBus_DMA), GFP_ATOMIC); + dma = kmalloc(sizeof(struct Linux_SBus_DMA), GFP_ATOMIC); - /* No SBUS */ - dma->SBus_dev = 0x0; + /* No SBUS */ + dma->SBus_dev = 0x0; - /* Only one DMA device */ - dma_chain=dma; + /* Only one DMA device */ + dma_chain=dma; - dma->regs = (struct sparc_dma_registers *) - sparc_alloc_io (sun4_dma_physaddr, 0, - PAGE_SIZE, "dma", 0x0, 0x0); + dma->regs = (struct sparc_dma_registers *) + sparc_alloc_io (sun4_dma_physaddr, 0, + PAGE_SIZE, "dma", 0x0, 0x0); - /* No prom node */ - dma->node = 0x0; + /* No prom node */ + dma->node = 0x0; - init_one_dvma(dma, 0); + init_one_dvma(dma, 0); } else { - dma_chain=0x0; + dma_chain=0x0; } } diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/sbus.c linux/drivers/sbus/sbus.c --- v2.1.123/linux/drivers/sbus/sbus.c Thu Aug 6 14:06:32 1998 +++ linux/drivers/sbus/sbus.c Sun Oct 4 10:22:44 1998 @@ -1,4 +1,4 @@ -/* $Id: sbus.c,v 1.69 1998/07/28 16:53:11 jj Exp $ +/* $Id: sbus.c,v 1.72 1998/09/05 17:25:51 jj Exp $ * sbus.c: SBus support routines. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -246,7 +247,7 @@ int num_sbus = 0; /* How many did we find? */ #ifdef CONFIG_SUN4 - return sun4_init(); + return sun4_dvma_init(); #endif topnd = prom_getchild(prom_root_node); @@ -257,7 +258,10 @@ nd = prom_searchsiblings(topnd, "sbus"); if(nd == 0) { #ifdef CONFIG_PCI - /* printk("SBUS: No SBUS's found.\n"); */ + if (!pcibios_present()) { + prom_printf("Neither SBUS nor PCI found.\n"); + prom_halt(); + } return; #else prom_printf("YEEE, UltraSparc sbus not found\n"); @@ -418,21 +422,9 @@ #endif #ifdef __sparc_v9__ if (sparc_cpu_model == sun4u) { - extern void sun4u_start_timers(void); extern void clock_probe(void); - sun4u_start_timers(); clock_probe(); } #endif } - -#ifdef CONFIG_SUN4 - -extern void sun4_dvma_init(void); - -__initfunc(void sun4_init(void)) -{ - sun4_dvma_init(); -} -#endif diff -u --recursive --new-file v2.1.123/linux/drivers/scsi/qlogicpti.c linux/drivers/scsi/qlogicpti.c --- v2.1.123/linux/drivers/scsi/qlogicpti.c Thu Aug 6 14:06:33 1998 +++ linux/drivers/scsi/qlogicpti.c Sun Oct 4 10:22:44 1998 @@ -564,6 +564,9 @@ } static void do_qlogicpti_intr_handler(int irq, void *dev_id, struct pt_regs *regs); +#ifndef __sparc_v9__ +static void do_qlogicpti_intr_handler_sun4m(int irq, void *dev_id, struct pt_regs *regs); +#endif /* Detect all PTI Qlogic ISP's in the machine. */ __initfunc(int qlogicpti_detect(Scsi_Host_Template *tpnt)) @@ -671,34 +674,30 @@ qpti_host->irq = qpti->irq = qpti->qdev->irqs[0]; -#ifndef __sparc_v9__ - /* Allocate the irq only if necessary. */ + /* On Ultra and S{S1,C2}000 we must always call request_irq for each + * qpti, so that imap registers get setup etc. + * But irq values are different in that case anyway... + * Otherwise allocate the irq only if necessary. + */ for_each_qlogicpti(qlink) { if((qlink != qpti) && (qpti->irq == qlink->irq)) { goto qpti_irq_acquired; /* BASIC rulez */ } } - if(request_irq(qpti->qhost->irq, do_qlogicpti_intr_handler, - SA_SHIRQ, "PTI Qlogic/ISP SCSI", NULL)) { - printk("Cannot acquire PTI Qlogic/ISP irq line\n"); - /* XXX Unmap regs, unregister scsi host, free things. */ - continue; - } -qpti_irq_acquired: - printk("qpti%d: IRQ %d ", qpti->qpti_id, qpti->qhost->irq); -#else - /* On Ultra we must always call request_irq for each - * qpti, so that imap registers get setup etc. - */ - if(request_irq(qpti->qhost->irq, do_qlogicpti_intr_handler, + if(request_irq(qpti->qhost->irq, +#ifndef __sparc_v9__ + (sparc_cpu_model == sun4m || sparc_cpu_model == sun4c) ? + do_qlogicpti_intr_handler_sun4m : +#endif + do_qlogicpti_intr_handler, SA_SHIRQ, "PTI Qlogic/ISP SCSI", qpti)) { printk("Cannot acquire PTI Qlogic/ISP irq line\n"); /* XXX Unmap regs, unregister scsi host, free things. */ continue; } +qpti_irq_acquired: printk("qpti%d: IRQ %s ", qpti->qpti_id, __irq_itoa(qpti->qhost->irq)); -#endif /* Figure out our scsi ID on the bus */ qpti->scsi_id = prom_getintdefault(qpti->prom_node, @@ -809,8 +808,8 @@ static char buf[80]; struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata; - sprintf(buf, "PTI Qlogic,ISP SBUS SCSI irq %d regs at %08lx", - host->irq, (unsigned long) qpti->qregs); + sprintf(buf, "PTI Qlogic,ISP SBUS SCSI irq %s regs at %08lx", + __irq_itoa(qpti->qhost->irq), (unsigned long) qpti->qregs); return buf; } @@ -1068,162 +1067,89 @@ return (sts->scsi_status & STATUS_MASK) | (host_status << 16); } -#ifndef __sparc_v9__ - -static __inline__ void qlogicpti_intr_handler(int irq, void *dev_id, - struct pt_regs *regs) +static __inline__ int qlogicpti_intr_handler(struct qlogicpti *qpti) { - static int running = 0; Scsi_Cmnd *Cmnd; struct Status_Entry *sts; - struct qlogicpti *qpti; u_int in_ptr, out_ptr; - int again; - - /* It is ok to take irq's on one qpti while the other - * is amidst the processing of a reset. - */ - running++; - -#if 0 /* XXX Investigate why resets cause this with one controller. */ - if(running > qptis_running) - printk("qlogicpti_intr_handler: yieee, recursive interrupt!\n"); -#endif + struct qlogicpti_regs *qregs; - /* Handle all ISP interrupts showing */ -repeat: - again = 0; - for_each_qlogicpti(qpti) { - if(qpti->qregs->sbus_stat & SBUS_STAT_RINT) { - struct qlogicpti_regs *qregs = qpti->qregs; - - again = 1; - in_ptr = qregs->mbox5; - qregs->hcctrl = HCCTRL_CRIRQ; - if(qregs->sbus_semaphore & SBUS_SEMAPHORE_LCK) { - switch(qregs->mbox0) { - case ASYNC_SCSI_BUS_RESET: - case EXECUTION_TIMEOUT_RESET: - qpti->send_marker = 1; - break; - case INVALID_COMMAND: - case HOST_INTERFACE_ERROR: - case COMMAND_ERROR: - case COMMAND_PARAM_ERROR: - break; - } - qregs->sbus_semaphore = 0; - } + if(!(qpti->qregs->sbus_stat & SBUS_STAT_RINT)) + return 0; + + qregs = qpti->qregs; - /* This looks like a network driver! */ - out_ptr = qpti->res_out_ptr; - while(out_ptr != in_ptr) { - sts = (struct Status_Entry *) &qpti->res_cpu[out_ptr]; - out_ptr = NEXT_RES_PTR(out_ptr); - Cmnd = (Scsi_Cmnd *) ((unsigned long)sts->handle); - if(sts->completion_status == CS_RESET_OCCURRED || - sts->completion_status == CS_ABORTED || - (sts->status_flags & STF_BUS_RESET)) - qpti->send_marker = 1; - - if(sts->state_flags & SF_GOT_SENSE) - memcpy(Cmnd->sense_buffer, sts->req_sense_data, - sizeof(Cmnd->sense_buffer)); - - if(sts->hdr.entry_type == ENTRY_STATUS) - Cmnd->result = qlogicpti_return_status(sts); - else - Cmnd->result = DID_ERROR << 16; - - if(Cmnd->use_sg) - mmu_release_scsi_sgl((struct mmu_sglist *) - Cmnd->buffer, - Cmnd->use_sg - 1, - qpti->qdev->my_bus); - else - mmu_release_scsi_one((__u32)Cmnd->SCp.ptr, - Cmnd->request_bufflen, - qpti->qdev->my_bus); - - qpti->cmd_count[Cmnd->target]--; - qregs->mbox5 = out_ptr; - Cmnd->scsi_done(Cmnd); - } - qpti->res_out_ptr = out_ptr; + in_ptr = qregs->mbox5; + qregs->hcctrl = HCCTRL_CRIRQ; + if(qregs->sbus_semaphore & SBUS_SEMAPHORE_LCK) { + switch(qregs->mbox0) { + case ASYNC_SCSI_BUS_RESET: + case EXECUTION_TIMEOUT_RESET: + qpti->send_marker = 1; + break; + case INVALID_COMMAND: + case HOST_INTERFACE_ERROR: + case COMMAND_ERROR: + case COMMAND_PARAM_ERROR: + break; } + qregs->sbus_semaphore = 0; } - if(again) - goto repeat; - running--; + + /* This looks like a network driver! */ + out_ptr = qpti->res_out_ptr; + while(out_ptr != in_ptr) { + sts = (struct Status_Entry *) &qpti->res_cpu[out_ptr]; + out_ptr = NEXT_RES_PTR(out_ptr); + Cmnd = (Scsi_Cmnd *) (((unsigned long)sts->handle)+PAGE_OFFSET); + + if(sts->completion_status == CS_RESET_OCCURRED || + sts->completion_status == CS_ABORTED || + (sts->status_flags & STF_BUS_RESET)) + qpti->send_marker = 1; + + if(sts->state_flags & SF_GOT_SENSE) + memcpy(Cmnd->sense_buffer, sts->req_sense_data, + sizeof(Cmnd->sense_buffer)); + + if(sts->hdr.entry_type == ENTRY_STATUS) + Cmnd->result = qlogicpti_return_status(sts); + else + Cmnd->result = DID_ERROR << 16; + + if(Cmnd->use_sg) + mmu_release_scsi_sgl((struct mmu_sglist *) + Cmnd->buffer, + Cmnd->use_sg - 1, + qpti->qdev->my_bus); + else + mmu_release_scsi_one((__u32)((unsigned long)Cmnd->SCp.ptr), + Cmnd->request_bufflen, + qpti->qdev->my_bus); + + qpti->cmd_count[Cmnd->target]--; + qregs->mbox5 = out_ptr; + Cmnd->scsi_done(Cmnd); + } + qpti->res_out_ptr = out_ptr; + return 1; } -#else /* __sparc_v9__ */ +#ifndef __sparc_v9__ -static __inline__ void qlogicpti_intr_handler(int irq, void *dev_id, - struct pt_regs *regs) +static void do_qlogicpti_intr_handler_sun4m(int irq, void *dev_id, struct pt_regs *regs) { - struct qlogicpti *qpti = dev_id; - Scsi_Cmnd *Cmnd; - struct Status_Entry *sts; - u_int in_ptr, out_ptr; - - if(qpti->qregs->sbus_stat & SBUS_STAT_RINT) { - struct qlogicpti_regs *qregs = qpti->qregs; - - in_ptr = qregs->mbox5; - qregs->hcctrl = HCCTRL_CRIRQ; - if(qregs->sbus_semaphore & SBUS_SEMAPHORE_LCK) { - switch(qregs->mbox0) { - case ASYNC_SCSI_BUS_RESET: - case EXECUTION_TIMEOUT_RESET: - qpti->send_marker = 1; - break; - case INVALID_COMMAND: - case HOST_INTERFACE_ERROR: - case COMMAND_ERROR: - case COMMAND_PARAM_ERROR: - break; - } - qregs->sbus_semaphore = 0; - } + unsigned long flags; + struct qlogicpti *qpti; + int again; - /* This looks like a network driver! */ - out_ptr = qpti->res_out_ptr; - while(out_ptr != in_ptr) { - sts = (struct Status_Entry *) &qpti->res_cpu[out_ptr]; - out_ptr = NEXT_RES_PTR(out_ptr); - Cmnd = (Scsi_Cmnd *) (((unsigned long)sts->handle)+PAGE_OFFSET); - - if(sts->completion_status == CS_RESET_OCCURRED || - sts->completion_status == CS_ABORTED || - (sts->status_flags & STF_BUS_RESET)) - qpti->send_marker = 1; - - if(sts->state_flags & SF_GOT_SENSE) - memcpy(Cmnd->sense_buffer, sts->req_sense_data, - sizeof(Cmnd->sense_buffer)); - - if(sts->hdr.entry_type == ENTRY_STATUS) - Cmnd->result = qlogicpti_return_status(sts); - else - Cmnd->result = DID_ERROR << 16; - - if(Cmnd->use_sg) - mmu_release_scsi_sgl((struct mmu_sglist *) - Cmnd->buffer, - Cmnd->use_sg - 1, - qpti->qdev->my_bus); - else - mmu_release_scsi_one((__u32)((unsigned long)Cmnd->SCp.ptr), - Cmnd->request_bufflen, - qpti->qdev->my_bus); - - qpti->cmd_count[Cmnd->target]--; - qregs->mbox5 = out_ptr; - Cmnd->scsi_done(Cmnd); - } - qpti->res_out_ptr = out_ptr; - } + spin_lock_irqsave(&io_request_lock, flags); + again = 0; + do { + for_each_qlogicpti(qpti) + again |= qlogicpti_intr_handler(qpti); + } while (again); + spin_unlock_irqrestore(&io_request_lock, flags); } #endif @@ -1233,7 +1159,7 @@ unsigned long flags; spin_lock_irqsave(&io_request_lock, flags); - qlogicpti_intr_handler(irq, dev_id, regs); + qlogicpti_intr_handler((struct qlogicpti *)dev_id); spin_unlock_irqrestore(&io_request_lock, flags); } diff -u --recursive --new-file v2.1.123/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c --- v2.1.123/linux/drivers/scsi/sd.c Wed Aug 26 11:37:38 1998 +++ linux/drivers/scsi/sd.c Wed Sep 30 10:22:14 1998 @@ -675,7 +675,7 @@ goto repeat; } - sd_devname(devm, nbuff); + sd_devname(devm >> 4, nbuff); SCSI_LOG_HLQUEUE(2,printk("%s : real dev = /dev/%d, block = %d\n", nbuff, dev, block)); diff -u --recursive --new-file v2.1.123/linux/drivers/video/Config.in linux/drivers/video/Config.in --- v2.1.123/linux/drivers/video/Config.in Thu Aug 20 17:05:17 1998 +++ linux/drivers/video/Config.in Wed Sep 30 10:19:10 1998 @@ -35,9 +35,9 @@ if [ "$CONFIG_FB_OF" = "y" ]; then bool 'Apple "control" display support' CONFIG_FB_CONTROL bool 'Apple "platinum" display support' CONFIG_FB_PLATINUM -# bool 'Apple "valkyrie" display support' CONFIG_FB_VALKYRIE + bool 'Apple "valkyrie" display support' CONFIG_FB_VALKYRIE bool 'ATI Mach64 display support' CONFIG_FB_ATY -# bool 'IMS Twin Turbo display support' CONFIG_FB_IMSTT + bool 'IMS Twin Turbo display support' CONFIG_FB_IMSTT bool 'Chips 65550 display support' CONFIG_FB_CT65550 bool 'S3 Trio display support' CONFIG_FB_S3TRIO fi @@ -48,21 +48,12 @@ if [ "$CONFIG_HP300" = "y" ]; then define_bool CONFIG_FB_HP300 y fi - # I used CONFIG_ARM here because the ARCH construct doesn't seem to work - # with xconfig. --pb - if [ "$ARCH" = "i386" -o "$ARCH" = "alpha" -o "$ARCH" = "ppc" -o \ - "$CONFIG_ARM" = "y" ]; then - if [ "$CONFIG_ARM" != "y" -o "$CONFIG_ARCH_ACORN" != "y" ] ; then - tristate 'Deprecated almost-VGA support (text only - use normal VGA console instead)' CONFIG_FB_VGA - fi - fi if [ "$ARCH" = "alpha" ]; then tristate 'TGA framebuffer support' CONFIG_FB_TGA fi if [ "$ARCH" = "i386" ]; then bool 'VESA VGA graphics console' CONFIG_FB_VESA define_bool CONFIG_VIDEO_SELECT y - tristate 'MDA dual-headed support' CONFIG_FB_MDA fi if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then bool 'SBUS and UPA framebuffers' CONFIG_FB_SBUS @@ -75,7 +66,9 @@ bool ' CGthree support' CONFIG_FB_CGTHREE if [ "$ARCH" = "sparc" ]; then bool ' TCX (SS4/SS5 only) support' CONFIG_FB_TCX + bool ' CGfourteen (SX) support' CONFIG_FB_CGFOURTEEN fi + bool ' Leo (ZX) support' CONFIG_FB_LEO fi fi if [ "$ARCH" = "sparc64" ]; then @@ -138,48 +131,56 @@ "$CONFIG_FB_OF" = "y" -o "$CONFIG_FB_TGA" = "y" -o \ "$CONFIG_FB_VESA" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \ "$CONFIG_FB_TCX" = "y" -o "$CONFIG_FB_CGTHREE" = "y" -o \ - "$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" ]; then + "$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \ + "$CONFIG_FB_CGFOURTEEN" = "y" -o "$CONFIG_FB_G364" = "y" -o \ + "$CONFIG_FB_VALKYRIE" = "y" -o "$CONFIG_FB_PLATINUM" = "y" ]; then define_bool CONFIG_FBCON_CFB8 y else if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \ - "$CONFIG_FB_ATY" = "y" -o "$CONFIG_FB_MAC" = "y" -o \ + "$CONFIG_FB_ATY" = "m" -o "$CONFIG_FB_MAC" = "m" -o \ "$CONFIG_FB_OF" = "m" -o "$CONFIG_FB_TGA" = "m" -o \ "$CONFIG_FB_VESA" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \ "$CONFIG_FB_TCX" = "m" -o "$CONFIG_FB_CGTHREE" = "m" -o \ - "$CONFIG_FB_CONTROL" = "m" ]; then + "$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \ + "$CONFIG_FB_CGFOURTEEN" = "m" -o "$CONFIG_FB_G364" = "m" -o \ + "$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" ]; then define_bool CONFIG_FBCON_CFB8 m fi fi if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_ATY" = "y" -o \ "$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_VESA" = "y" -o \ "$CONFIG_FB_VIRTUAL" = "y" -o "$CONFIG_FB_TBOX" = "y" -o \ - "$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" ]; then + "$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \ + "$CONFIG_FB_VALKYRIE" = "y" -o "$CONFIG_FB_PLATINUM" = "y" ]; then define_bool CONFIG_FBCON_CFB16 y else if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \ "$CONFIG_FB_MAC" = "m" -o "$CONFIG_FB_VESA" = "m" -o \ "$CONFIG_FB_VIRTUAL" = "m" -o "$CONFIG_FB_TBOX" = "m" -o \ - "$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" ]; then + "$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \ + "$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" ]; then define_bool CONFIG_FBCON_CFB16 m fi fi if [ "$CONFIG_FB_ATY" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \ - "$CONFIG_FB_CLGEN" = "y" ]; then + "$CONFIG_FB_CLGEN" = "y" -o "$CONFIG_FB_VESA" = "y" ]; then define_bool CONFIG_FBCON_CFB24 y else if [ "$CONFIG_FB_ATY" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \ - "$CONFIG_FB_CLGEN" = "m" ]; then + "$CONFIG_FB_CLGEN" = "m" -o "$CONFIG_FB_VESA" = "m" ]; then define_bool CONFIG_FBCON_CFB24 m fi fi if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_ATY" = "y" -o \ "$CONFIG_FB_VESA" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \ - "$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" ]; then + "$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \ + "$CONFIG_FB_TGA" = "y" -o "$CONFIG_FB_PLATINUM" = "y" ]; then define_bool CONFIG_FBCON_CFB32 y else if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \ "$CONFIG_FB_VESA" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \ - "$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" ]; then + "$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \ + "$CONFIG_FB_TGA" = "m" -o "$CONFIG_FB_PLATINUM" = "m" ]; then define_bool CONFIG_FBCON_CFB32 m fi fi diff -u --recursive --new-file v2.1.123/linux/drivers/video/Makefile linux/drivers/video/Makefile --- v2.1.123/linux/drivers/video/Makefile Tue Jul 28 14:21:09 1998 +++ linux/drivers/video/Makefile Wed Sep 30 10:19:10 1998 @@ -9,9 +9,6 @@ # parent makes.. # -GSPA = gspa -GSPH2C = gspahextoc - L_TARGET := video.a L_OBJS := M_OBJS := @@ -19,11 +16,16 @@ MX_OBJS := MOD_LIST_NAME := VIDEO_MODULES +CONFIG_FBGEN_BUILTIN := +CONFIG_FBGEN_MODULE := + # Frame Buffer Console -# Nasty trick to make sure all wanted stuff is linked in -O_TARGET = fbdev.o -L_OBJS += fbdev.o +ifeq ($(CONFIG_FB),y) + # Nasty trick to make sure all wanted stuff is linked in + O_TARGET = fbdev.o + L_OBJS += fbdev.o +endif ifeq ($(CONFIG_DUMMY_CONSOLE),y) L_OBJS += dummycon.o @@ -35,8 +37,7 @@ ifeq ($(CONFIG_FB),y) L_OBJS += fonts.o - OX_OBJS += fbcon.o fbcmap.o -# fbgen is not compiled by default since nobody uses it yet, except clgenfb + OX_OBJS += fbcon.o fbcmap.o fbmem.o ifeq ($(CONFIG_FONT_8x8),y) L_OBJS += font_8x8.o endif @@ -102,6 +103,10 @@ L_OBJS += platinumfb.o endif +ifeq ($(CONFIG_FB_VALKYRIE),y) +L_OBJS += valkyriefb.o +endif + ifeq ($(CONFIG_FB_CT65550),y) L_OBJS += chipsfb.o endif @@ -126,6 +131,10 @@ L_OBJS += offb.o macmodes.o endif +ifeq ($(CONFIG_FB_IMSTT),y) +L_OBJS += imsttfb.o +endif + ifeq ($(CONFIG_FB_RETINAZ3),y) L_OBJS += retz3fb.o else @@ -136,11 +145,11 @@ ifeq ($(CONFIG_FB_CLGEN),y) L_OBJS += clgenfb.o -OX_OBJS += fbgen.o +CONFIG_FBGEN_BUILTIN = y else ifeq ($(CONFIG_FB_CLGEN),m) M_OBJS += clgenfb.o - OX_OBJS += fbgen.o + CONFIG_FBGEN_MODULE = y endif endif @@ -160,26 +169,10 @@ endif endif -ifeq ($(CONFIG_FB_VGA),y) -L_OBJS += vgafb.o -else - ifeq ($(CONFIG_FB_VGA),m) - M_OBJS += vgafb.o - endif -endif - ifeq ($(CONFIG_FB_VESA),y) L_OBJS += vesafb.o endif -ifeq ($(CONFIG_FB_MDA),y) -L_OBJS += mdafb.o -else - ifeq ($(CONFIG_FB_MDA),m) - M_OBJS += mdafb.o - endif -endif - ifeq ($(CONFIG_FB_VIRGE),y) L_OBJS += virgefb.o else @@ -188,6 +181,10 @@ endif endif +ifdef CONFIG_FB_G364 +L_OBJS := $(L_OBJS) g364fb.o +endif + ifeq ($(CONFIG_FB_SBUS),y) L_OBJS += sbusfb.o ifeq ($(CONFIG_FB_CREATOR),y) @@ -225,6 +222,20 @@ M_OBJS += tcxfb.o endif endif + ifeq ($(CONFIG_FB_CGFOURTEEN),y) + L_OBJS += cgfourteenfb.o + else + ifeq ($(CONFIG_FB_CGFOURTEEN),m) + M_OBJS += cgfourteenfb.o + endif + endif + ifeq ($(CONFIG_FB_LEO),y) + L_OBJS += leofb.o + else + ifeq ($(CONFIG_FB_LEO),m) + M_OBJS += leofb.o + endif + endif else ifeq ($(CONFIG_FB_SBUS),m) M_OBJS += sbusfb.o @@ -263,6 +274,20 @@ M_OBJS += tcxfb.o endif endif + ifeq ($(CONFIG_FB_CGFOURTEEN),y) + M_OBJS += cgfourteenfb.o + else + ifeq ($(CONFIG_FB_CGFOURTEEN),m) + M_OBJS += cgfourteenfb.o + endif + endif + ifeq ($(CONFIG_FB_LEO),y) + M_OBJS += leofb.o + else + ifeq ($(CONFIG_FB_LEO),m) + M_OBJS += leofb.o + endif + endif endif endif @@ -274,6 +299,14 @@ endif endif +ifdef CONFIG_FBGEN_BUILTIN +OX_OBJS += fbgen.o +else + ifdef CONFIG_FBGEN_MODULE + MX_OBJS += fbgen.o + endif +endif + # Generic Low Level Drivers ifeq ($(CONFIG_FBCON_AFB),y) @@ -396,23 +429,23 @@ endif endif -# GSP Console - -ifdef CONFIG_AMIGA_GSP -L_OBJS += gspcon.o gspcore.o -endif - # VGA Text Console ifdef CONFIG_VGA_CONSOLE L_OBJS += vgacon.o endif -include $(TOPDIR)/Rules.make +# MDA Text Console -gspcore.c: gspcore.gsp - $(GSPA) $< > $*.hex - $(GSPH2C) $*.hex > gspcore.c +ifeq ($(CONFIG_MDA_CONSOLE),y) +L_OBJS += mdacon.o +else + ifeq ($(CONFIG_MDA_CONSOLE),m) + M_OBJS += mdacon.o + endif +endif + +include $(TOPDIR)/Rules.make promcon_tbl.c: prom.uni ../char/conmakehash prom.uni | \ diff -u --recursive --new-file v2.1.123/linux/drivers/video/S3triofb.c linux/drivers/video/S3triofb.c --- v2.1.123/linux/drivers/video/S3triofb.c Sun Jul 26 11:57:17 1998 +++ linux/drivers/video/S3triofb.c Thu Oct 1 10:02:21 1998 @@ -45,9 +45,9 @@ #include #endif -#include "fbcon.h" -#include "fbcon-cfb8.h" -#include "s3blit.h" +#include